Ir para conteúdo
  • 0

[Resolvido] Unable to load items (OTB)


Fosil

Pergunta

Boa tarde galera!                                                 Erro: Unable to load items (OTB)

 

Eu estou precisando de uma pequena ajuda que por incrível que pareça não estou conseguindo resolver  um erro (bem comum). Existe diversos tutoriais na qual tem soluções de resolver porém comigo está um pouco mais Hard. Irei mostrar algumas soluções que eu tentei e não tive exito.

 

+ ( OTX 2 ) Rev 0.4, Compilado.

+ Consigo ligar o server apenas no Items OTB 3.21.21-8.61.

 

1º) Em config.lua lá em Check ( skipItemsVersionCheck ) alterei de false para true, tentei novamente não tive exito.

 

2º) Fui nas soucers em definition.h:

  Citar

#define CLIENT_VERSION_ITEMS 20

 

Mudei para:

 

#define CLIENT_VERSION_ITEMS 22

 

image.thumb.png.a719733e3dde421f6632d84a4c16580a.png 

porque a version que eu quero atual é a 8.62, 22 por ter um pouco mais de opção. Em fim, eu quero que aceite qualquer items otb..

 

3º) vi um tutorial também que tinha que adicionar os /* */ no começo e no fim procurando por:

Porem nas minhas soucers em item.cpp não tinha essas linhas...

Citar

if(Items::dwMajorVersion == 0xFFFFFFFF)

std::clog << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl;

else if(Items::dwMajorVersion < 3)

{

std::clog << "[Error - Items::loadFromOtb] Old version detected, a newer version of items.otb is required." << std::endl;

return ERROR_INVALID_FORMAT;

}

else if(Items::dwMajorVersion > 3)

{

std::clog << "[Error - Items::loadFromOtb] New version detected, an older version of items.otb is required." << std::endl;

return ERROR_INVALID_FORMAT;

}

else if(Items::dwMinorVersion != CLIENT_VERSION_861)

{

std::clog << "[Error - Items::loadFromOtb] Another (client) version of items.otb is required." << std::endl;

return ERROR_INVALID_FORMAT;

  • + Infos:

 

+ eu não uso MYSQL pois está em andamento ainda e para eu testar as coisas preciso abrir o server né rs! 

+ não sei se estou fazendo as cosias certas, pois é minha primeira vez usando soucers, não sei como faz as coisas, salvar e tals, irei explicar como eu faço as coisas:

Eu edito lá do 20 para o 22 em definitions.h e dou ctrl + s logo dps ctrl + f9 ( para fazer a compilação ) ai gera um novo .exe e eu substituo o antigo pelo novo que gerou na pasta... EU USO O Dev c++.

 

Bom glr, quem puder me ajudar ficarei muito grato e estará ganhando rep+ é nois!

Editado por Fosil
Link para o comentário
Compartilhar em outros sites

5 respostass a esta questão

Posts Recomendados

  • 0

items.cpp:

Spoiler

#include "otpch.h"
#include <iostream>
#include <libxml/xmlmemory.h>

#include "items.h"
#include "condition.h"
#include "configmanager.h"

#include "movement.h"
#include "weapons.h"
#include "spells.h"


extern Spells* g_spells;
extern ConfigManager g_config;
extern MoveEvents* g_moveEvents;
extern Weapons* g_weapons;

uint32_t Items::dwMajorVersion = 0;
uint32_t Items::dwMinorVersion = 0;
uint32_t Items::dwBuildNumber = 0;

ItemType::ItemType()
{
    abilities = NULL;
    group = ITEM_GROUP_NONE;
    type = ITEM_TYPE_NONE;
    stackable = usable = alwaysOnTop = lookThrough = pickupable = rotable = hasHeight = forceSerialize = false;
    loaded = blockSolid = blockProjectile = blockPathFind = allowPickupable = isAnimation = cache = false;
    movable = walkStack = true;
    alwaysOnTopOrder = 0;
    rotateTo = 0;

    wieldInfo = 0;
    minReqLevel = 0;
    minReqMagicLevel = 0;

    runeMagLevel = runeLevel = 0;

    speed = id = 0;
    clientId = 100;
    maxItems = 8; //maximum size if this is a container
    weight = 0; //weight of the item, e.g. throwing distance depends on it
    showCount = true;
    weaponType = WEAPON_NONE;
    slotPosition = SLOTP_HAND;
    wieldPosition = SLOT_HAND;
    ammoType = AMMO_NONE;
    ammoAction = AMMOACTION_NONE;
    shootType = (ShootEffect_t)0;
    magicEffect = MAGIC_EFFECT_NONE;
    attack = extraAttack = 0;
    defense = extraDefense = 0;
    attackSpeed = 0;
    criticalHitChance = 0;
    armor = 0;
    decayTo = -1;
    decayTime = 0;
    stopTime = false;
    corpseType = RACE_NONE;
    armorRndMin = armorRndMax = defenseRndMin = defenseRndMax = extraDefenseRndMin = extraDefenseRndMax = 0;
    attackRndMin = attackRndMax = extraAttackRndMin = extraAttackRndMax = 0;
    attackSpeedRndMin = attackSpeedRndMax = attackSpeedChance = extraAttackChance = extraDefenseChance = 0;
    fluidSource = FLUID_NONE;
    allowDistRead = false;

    isVertical = isHorizontal = isHangable = false;
    lightLevel = lightColor = 0;

    maxTextLength = 0;
    canReadText = canWriteText = false;
    date = 0;
    writeOnceItemId = wareId = premiumDays = 0;

    transformEquipTo = transformDeEquipTo = transformUseTo = 0;
    showDuration = showCharges = showAttributes = dualWield = false;
    charges    = 0;
    hitChance = maxHitChance = breakChance = -1;
    shootRange = 1;

    condition = NULL;
    combatType = COMBAT_NONE;

    replacable = true;
    worth = 0;

    bedPartnerDir = NORTH;
    transformBed[PLAYERSEX_FEMALE] = transformBed[PLAYERSEX_MALE] = 0;

    levelDoor = 0;
    specialDoor = closingDoor = false;

    memset(floorChange, 0, sizeof(floorChange));
}

ItemType::~ItemType()
{
    delete condition;
}

void Items::clear()
{
    moneyMap.clear();
    randomizationMap.clear();

    reverseItemMap.clear();
    if(items.size())
        items.clear();
}

bool Items::reload()
{
    clear();
    if(!items.size())
        return false;

    items.reload();
    loadFromOtb(getFilePath(FILE_TYPE_OTHER, "items/items.otb"));
    if(!loadFromXml())
        return false;

    g_moveEvents->reload();
    g_weapons->reload();
    return true;
}

int32_t Items::loadFromOtb(std::string file)
{
    FileLoader f;
    if(!f.openFile(file.c_str(), "OTBI", false, true))
        return f.getError();

    uint32_t type;
    NODE node = f.getChildNode(NO_NODE, type);

    PropStream props;
    if(f.getProps(node, props))
    {
        //4 byte flags
        //attributes
        //0x01 = version data
        uint32_t flags;
        if(!props.getLong(flags))
            return ERROR_INVALID_FORMAT;

        attribute_t attr;
        if(!props.getType(attr))
            return ERROR_INVALID_FORMAT;

        if(attr == ROOT_ATTR_VERSION)
        {
            datasize_t length = 0;
            if(!props.getType(length))
                return ERROR_INVALID_FORMAT;

            if(length != sizeof(VERSIONINFO))
                return ERROR_INVALID_FORMAT;

            VERSIONINFO *vi;
            if(!props.getStruct(vi))
                return ERROR_INVALID_FORMAT;

            Items::dwMajorVersion = vi->dwMajorVersion; //items otb format file version
            Items::dwMinorVersion = vi->dwMinorVersion; //client version
            Items::dwBuildNumber = vi->dwBuildNumber; //revision
        }
    }

   /* if(Items::dwMajorVersion == 0xFFFFFFFF)
        std::clog << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl;
    else if(Items::dwMajorVersion != 3)
    {
        std::clog << "[Error - Items::loadFromOtb] Incorrect version detected, please use official items.otb." << std::endl;
        return ERROR_INVALID_FORMAT;
    }
    else if(!g_config.getBool(ConfigManager::SKIP_ITEMS_VERSION) && Items::dwMinorVersion != CLIENT_VERSION_ITEMS)
    {
        std::clog << "[Error - Items::loadFromOtb] Another client version of items.otb is required." << std::endl;
        return ERROR_INVALID_FORMAT;
    }*/

    uint16_t lastId = 99;
    for(node = f.getChildNode(node, type); node != NO_NODE; node = f.getNextNode(node, type))
    {
        PropStream props;
        if(!f.getProps(node, props))
            return f.getError();

        ItemType* iType = new ItemType();
        iType->group = (itemgroup_t)type;

        flags_t flags;
        switch(type)
        {
            case ITEM_GROUP_CONTAINER:
                iType->type = ITEM_TYPE_CONTAINER;
                break;
            case ITEM_GROUP_DOOR:
                //not used
                iType->type = ITEM_TYPE_DOOR;
                break;
            case ITEM_GROUP_MAGICFIELD:
                //not used
                iType->type = ITEM_TYPE_MAGICFIELD;
                break;
            case ITEM_GROUP_TELEPORT:
                //not used
                iType->type = ITEM_TYPE_TELEPORT;
                break;
            case ITEM_GROUP_NONE:
            case ITEM_GROUP_GROUND:
            case ITEM_GROUP_SPLASH:
            case ITEM_GROUP_FLUID:
            case ITEM_GROUP_CHARGES:
            case ITEM_GROUP_DEPRECATED:
                break;
            default:
                return ERROR_INVALID_FORMAT;
        }

        //read 4 byte flags
        if(!props.getType(flags))
            return ERROR_INVALID_FORMAT;

        iType->blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags);
        iType->blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags);
        iType->blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags);
        iType->hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags);
        iType->usable = hasBitSet(FLAG_USABLE, flags);
        iType->pickupable = hasBitSet(FLAG_PICKUPABLE, flags);
        iType->movable = hasBitSet(FLAG_MOVABLE, flags);
        iType->stackable = hasBitSet(FLAG_STACKABLE, flags);

        iType->alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags);
        iType->isVertical = hasBitSet(FLAG_VERTICAL, flags);
        iType->isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags);
        iType->isHangable = hasBitSet(FLAG_HANGABLE, flags);
        iType->allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags);
        iType->rotable = hasBitSet(FLAG_ROTABLE, flags);
        iType->canReadText = hasBitSet(FLAG_READABLE, flags);
        iType->lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags);
        iType->isAnimation = hasBitSet(FLAG_ANIMATION, flags);
        iType->walkStack = !hasBitSet(FLAG_WALKSTACK, flags);

        attribute_t attr;
        while(props.getType(attr))
        {
            //size of data
            datasize_t length = 0;
            if(!props.getType(length))
            {
                delete iType;
                return ERROR_INVALID_FORMAT;
            }

            switch(attr)
            {
                case ITEM_ATTR_SERVERID:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t serverId;
                    if(!props.getShort(serverId))
                        return ERROR_INVALID_FORMAT;

                    if(serverId > 20000 && serverId < 20100)
                        serverId = serverId - 20000;
                    else if(lastId > 99 && lastId != serverId - 1)
                    {
                        static ItemType dummyItemType;
                        while(lastId != serverId - 1)
                        {
                            dummyItemType.id = ++lastId;
                            items.addElement(&dummyItemType, lastId);
                        }
                    }

                    iType->id = serverId;
                    lastId = serverId;
                    break;
                }
                case ITEM_ATTR_CLIENTID:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t clientId;
                    if(!props.getShort(clientId))
                        return ERROR_INVALID_FORMAT;

                    iType->clientId = clientId;
                    break;
                }
                case ITEM_ATTR_SPEED:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t speed;
                    if(!props.getShort(speed))
                        return ERROR_INVALID_FORMAT;

                    iType->speed = speed;
                    break;
                }
                case ITEM_ATTR_LIGHT2:
                {
                    if(length != sizeof(lightBlock2))
                        return ERROR_INVALID_FORMAT;

                    lightBlock2* block;
                    if(!props.getStruct(block))
                        return ERROR_INVALID_FORMAT;

                    iType->lightLevel = block->lightLevel;
                    iType->lightColor = block->lightColor;
                    break;
                }
                case ITEM_ATTR_TOPORDER:
                {
                    if(length != sizeof(uint8_t))
                        return ERROR_INVALID_FORMAT;

                    uint8_t topOrder;
                    if(!props.getByte(topOrder))
                        return ERROR_INVALID_FORMAT;

                    iType->alwaysOnTopOrder = topOrder;
                    break;
                }
                case ITEM_ATTR_WAREID:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t wareId;
                    if(!props.getShort(wareId))
                        return ERROR_INVALID_FORMAT;

                    iType->wareId = wareId;
                    break;
                }
                case ITEM_ATTR_NAME:
                {
                    std::string name;
                    if(!props.getString(name, length))
                        return ERROR_INVALID_FORMAT;

                    iType->name = name;
                    break;
                }
                default:
                {
                    //skip unknown attributes
                    if(!props.skip(length))
                        return ERROR_INVALID_FORMAT;

                    break;
                }
            }
        }

        // store the found item
        items.addElement(iType, iType->id);
        if (iType->clientId) {
            if (reverseItemMap.find(iType->clientId) == reverseItemMap.end())
                reverseItemMap[iType->clientId] = iType->id;
        }
    }

    return ERROR_NONE;
}

bool Items::loadFromXml()
{
    xmlDocPtr doc = xmlParseFile(getFilePath(FILE_TYPE_OTHER, "items/items.xml").c_str());
    if(!doc)
    {
        std::clog << "[Warning - Items::loadFromXml] Cannot load items file."
            << std::endl << getLastXMLError() << std::endl;
        return false;
    }

    xmlNodePtr root = xmlDocGetRootElement(doc);
    if(xmlStrcmp(root->name,(const xmlChar*)"items"))
    {
        xmlFreeDoc(doc);
        std::clog << "[Warning - Items::loadFromXml] Malformed items file." << std::endl;
        return false;
    }

    IntegerVec intVector, endVector;
    std::string strValue, endValue;
    StringVec strVector;

    int32_t intValue, id = 0, endId = 0, fromId = 0, toId = 0;
    for(xmlNodePtr node = root->children; node; node = node->next)
    {
        if(xmlStrcmp(node->name,(const xmlChar*)"item"))
            continue;

        if(readXMLString(node, "id", strValue))
        {
            strVector = explodeString(strValue, ";");
            for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it)
            {
                intVector = vectorAtoi(explodeString(*it, "-"));
                if(intVector.size() > 1)
                {
                    int32_t i = intVector[0];
                    while(i <= intVector[1])
                        parseItemNode(node, i++);
                }
                else
                    parseItemNode(node, atoi((*it).c_str()));
            }
        }
        else if(readXMLString(node, "fromid", strValue) && readXMLString(node, "toid", endValue))
        {
            intVector = vectorAtoi(explodeString(strValue, ";"));
            endVector = vectorAtoi(explodeString(endValue, ";"));
            if(intVector[0] && intVector.size() == endVector.size())
            {
                size_t size = intVector.size();
                for(size_t i = 0; i < size; ++i)
                {
                    while(intVector <= endVector)
                        parseItemNode(node, intVector++);
                }
            }
            else
                std::clog << "[Warning - Items::loadFromXml] Malformed entry (from: \"" << strValue << "\", to: \"" << endValue << "\")" << std::endl;
        }
        else
            std::clog << "[Warning - Items::loadFromXml] No itemid found at line " << node->line << std::endl;
    }

    const ItemType* it;
    for(uint32_t i = 0; i < Item::items.size(); ++i) //lets do some checks...
    {
        if(!(it = Item::items.getElement(i)))
            continue;

        //check bed items
        if((it->transformBed[PLAYERSEX_FEMALE] || it->transformBed[PLAYERSEX_MALE]) && it->type != ITEM_TYPE_BED)
            std::clog << "[Warning - Items::loadFromXml] Item " << it->id << " is not set as a bed-type." << std::endl;
    }

    xmlFreeDoc(doc);
    if(!(doc = xmlParseFile(getFilePath(FILE_TYPE_OTHER, "items/randomization.xml").c_str())))
    {
        std::clog << "[Warning - Items::loadFromXml] Cannot load randomization file."
            << std::endl << getLastXMLError() << std::endl;
        return false;
    }

    root = xmlDocGetRootElement(doc);
    if(xmlStrcmp(root->name,(const xmlChar*)"randomization"))
    {
        xmlFreeDoc(doc);
        std::clog << "[Warning - Items::loadFromXml] Malformed randomization file." << std::endl;
        return false;
    }

    for(xmlNodePtr node = root->children; node; node = node->next)
    {
        if(!xmlStrcmp(node->name, (const xmlChar*)"config"))
        {
            if(readXMLInteger(node, "chance", intValue) || readXMLInteger(node, "defaultChance", intValue))
            {
                if(intValue > 100)
                {
                    intValue = 100;
                    std::clog << "[Warning - Items::loadFromXml] Randomize chance cannot be higher than 100." << std::endl;
                }

                m_randomizationChance = intValue;
            }
        }
        else if(!xmlStrcmp(node->name, (const xmlChar*)"palette"))
        {
            if(!readXMLString(node, "randomize", strValue))
                continue;

            IntegerVec itemList = vectorAtoi(explodeString(strValue, ";"));
            if(itemList.size() < 2)
                itemList = vectorAtoi(explodeString(strValue, "-"));

            if(itemList.size() > 1)
            {
                if(itemList[0] < itemList[1])
                {
                    fromId = itemList[0];
                    toId = itemList[1];
                }
                else
                    std::clog << "[Warning - Items::loadFromXml] Randomize min cannot be higher than max." << std::endl;
            }

            int32_t chance = getRandomizationChance();
            if(readXMLInteger(node, "chance", intValue))
            {
                if(intValue > 100)
                {
                    intValue = 100;
                    std::clog << "[Warning: Items::loadRandomization] Randomize chance cannot be higher than 100." << std::endl;
                }

                chance = intValue;
            }

            if(readXMLInteger(node, "itemid", id))
                parseRandomizationBlock(id, fromId, toId, chance);
            else if(readXMLInteger(node, "fromid", id) && readXMLInteger(node, "toid", endId))
            {
                while(id <= endId)
                    parseRandomizationBlock(id++, fromId, toId, chance);
            }
        }
    }

    xmlFreeDoc(doc);
    return true;
}

void Items::parseItemNode(xmlNodePtr itemNode, uint32_t id)
{
    int32_t intValue;
    std::string strValue;
    if(id > 20000 && id < 20100)
    {
        id -= 20000;
        ItemType* iType = new ItemType();

        iType->id = id;
        items.addElement(iType, iType->id);
    }

    bool override = readXMLString(itemNode, "override", strValue) && booleanString(strValue);
    ItemType& it = Item::items.getItemType(id);
    if(it.loaded)
    {
        if(override)
        {
            // setup some defaults
            if(it.hasAbilities())
            {
                memset(it.getAbilities()->fieldAbsorb, 0, sizeof(it.getAbilities()->fieldAbsorb));
                memset(it.getAbilities()->absorb, 0, sizeof(it.getAbilities()->absorb));
                for(uint32_t j = REFLECT_FIRST; j <= REFLECT_LAST; ++j)
                    memset(it.getAbilities()->reflect[j], 0, sizeof(it.getAbilities()->reflect[j]));
            }
        }
        else
            std::clog << "[Warning - Items::loadFromXml] Duplicate registered item with id " << id << std::endl;
    }
    else
        it.loaded = true;

    if(readXMLString(itemNode, "name", strValue))
        it.name = strValue;

    if(readXMLString(itemNode, "article", strValue))
        it.article = strValue;

    if(readXMLString(itemNode, "plural", strValue))
        it.pluralName = strValue;

    for(xmlNodePtr itemAttributesNode = itemNode->children; itemAttributesNode; itemAttributesNode = itemAttributesNode->next)
    {
        if(!readXMLString(itemAttributesNode, "key", strValue))
            continue;

#ifdef _MSC_VER
        bool notLoaded = false;
#endif
        std::string tmpStrValue = asLowerCaseString(strValue);
        if(tmpStrValue == "type")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "container")
                {
                    it.type = ITEM_TYPE_CONTAINER;
                    it.group = ITEM_GROUP_CONTAINER;
                }
                else if(tmpStrValue == "key")
                    it.type = ITEM_TYPE_KEY;
                else if(tmpStrValue == "magicfield")
                    it.type = ITEM_TYPE_MAGICFIELD;
                else if(tmpStrValue == "depot")
                    it.type = ITEM_TYPE_DEPOT;
                else if(tmpStrValue == "mailbox")
                    it.type = ITEM_TYPE_MAILBOX;
                else if(tmpStrValue == "trashholder")
                    it.type = ITEM_TYPE_TRASHHOLDER;
                else if(tmpStrValue == "teleport")
                    it.type = ITEM_TYPE_TELEPORT;
                else if(tmpStrValue == "door")
                    it.type = ITEM_TYPE_DOOR;
                else if(tmpStrValue == "bed")
                    it.type = ITEM_TYPE_BED;
                else if(tmpStrValue == "rune")
                    it.type = ITEM_TYPE_RUNE;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown type " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "name")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.name = strValue;
        }
        else if(tmpStrValue == "article")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.article = strValue;
        }
        else if(tmpStrValue == "plural")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.pluralName = strValue;
        }
        else if(tmpStrValue == "clientid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.clientId = intValue;
                if(it.group == ITEM_GROUP_DEPRECATED)
                    it.group = ITEM_GROUP_NONE;
            }
        }
        else if(tmpStrValue == "cache")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.cache = (intValue != 0);
        }
        else if(tmpStrValue == "wareid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.wareId = intValue;
        }
        else if(tmpStrValue == "blocksolid" || tmpStrValue == "blocking")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.blockSolid = (intValue != 0);
        }
        else if(tmpStrValue == "blockprojectile")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.blockProjectile = (intValue != 0);
        }
        else if(tmpStrValue == "blockpathfind" || tmpStrValue == "blockpathing" || tmpStrValue == "blockpath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.blockPathFind = (intValue != 0);
        }
        else if(tmpStrValue == "lightlevel")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.lightLevel = intValue;
        }
        else if(tmpStrValue == "lightcolor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.lightColor = intValue;
        }
        else if(tmpStrValue == "description")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.description = strValue;
        }
        else if(tmpStrValue == "runespellname")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.runeSpellName = strValue;
        }
        else if(tmpStrValue == "weight")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.weight = intValue / 100.f;
        }
        else if(tmpStrValue == "showcount")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showCount = (intValue != 0);
        }
        else if(tmpStrValue == "armor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.armor = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.armorRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.armorRndMax = intValue;
        }
        else if(tmpStrValue == "defense")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.defense = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.defenseRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.defenseRndMax = intValue;
        }
        else if(tmpStrValue == "extradefense" || tmpStrValue == "extradef")
        {
            if(readXMLInteger(itemAttributesNode, "chance", intValue))
                it.extraDefenseChance = intValue;
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.extraDefense = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.extraDefenseRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.extraDefenseRndMax = intValue;
        }
        else if(tmpStrValue == "criticalhitchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.criticalHitChance = intValue;
        }
        else if(tmpStrValue == "attack")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.attack = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.attackRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.attackRndMax = intValue;
        }
        else if(tmpStrValue == "extraattack" || tmpStrValue == "extraatk")
        {
            if(readXMLInteger(itemAttributesNode, "chance", intValue))
                it.extraAttackChance = intValue;
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.extraAttack = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.extraAttackRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.extraAttackRndMax = intValue;
        }
        else if(tmpStrValue == "attackspeed")
        {
            if(readXMLInteger(itemAttributesNode, "chance", intValue))
                it.attackSpeedChance = intValue;
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.attackSpeed = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.attackSpeedRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.attackSpeedRndMax = intValue;
        }
        else if(tmpStrValue == "rotateto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.rotateTo = intValue;
        }
        else if(tmpStrValue == "movable" || tmpStrValue == "moveable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.movable = (intValue != 0);
        }
        else if(tmpStrValue == "vertical" || tmpStrValue == "isvertical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.isVertical = (intValue != 0);
        }
        else if(tmpStrValue == "horizontal" || tmpStrValue == "ishorizontal")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.isHorizontal = (intValue != 0);
        }
        else if(tmpStrValue == "pickupable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.pickupable = (intValue != 0);
        }
        else if(tmpStrValue == "allowpickupable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.allowPickupable = (intValue != 0);
        }
        else if(tmpStrValue == "floorchange")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "down")
                    it.floorChange[CHANGE_DOWN] = true;
                else if(tmpStrValue == "north")
                    it.floorChange[CHANGE_NORTH] = true;
                else if(tmpStrValue == "south")
                    it.floorChange[CHANGE_SOUTH] = true;
                else if(tmpStrValue == "west")
                    it.floorChange[CHANGE_WEST] = true;
                else if(tmpStrValue == "east")
                    it.floorChange[CHANGE_EAST] = true;
                else if(tmpStrValue == "northex")
                    it.floorChange[CHANGE_NORTH_EX] = true;
                else if(tmpStrValue == "southex")
                    it.floorChange[CHANGE_SOUTH_EX] = true;
                else if(tmpStrValue == "westex")
                    it.floorChange[CHANGE_WEST_EX] = true;
                else if(tmpStrValue == "eastex")
                    it.floorChange[CHANGE_EAST_EX] = true;
            }
        }
        else if(tmpStrValue == "corpsetype")
        {
            tmpStrValue = asLowerCaseString(strValue);
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "venom")
                    it.corpseType = RACE_VENOM;
                else if(tmpStrValue == "blood")
                    it.corpseType = RACE_BLOOD;
                else if(tmpStrValue == "undead")
                    it.corpseType = RACE_UNDEAD;
                else if(tmpStrValue == "fire")
                    it.corpseType = RACE_FIRE;
                else if(tmpStrValue == "energy")
                    it.corpseType = RACE_ENERGY;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown corpseType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "containersize")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.maxItems = intValue;
                if(it.group == ITEM_GROUP_NONE)
                {
                    it.group = ITEM_GROUP_CONTAINER;
                    it.type = ITEM_TYPE_CONTAINER;
                }
            }
        }
        else if(tmpStrValue == "fluidsource")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                FluidTypes_t fluid = getFluidType(tmpStrValue);
                if(fluid != FLUID_NONE)
                    it.fluidSource = fluid;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown fluidSource " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "writeable" || tmpStrValue == "writable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.canWriteText = (intValue != 0);
                it.canReadText = (intValue != 0);
            }
        }
        else if(tmpStrValue == "readable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.canReadText = (intValue != 0);
        }
        else if(tmpStrValue == "maxtextlen" || tmpStrValue == "maxtextlength")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.maxTextLength = intValue;
        }
        else if(tmpStrValue == "text")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.text = strValue;
        }
        else if(tmpStrValue == "author" || tmpStrValue == "writer")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.writer = strValue;
        }
        else if(tmpStrValue == "date")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.date = intValue;
        }
        else if(tmpStrValue == "writeonceitemid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.writeOnceItemId = intValue;
        }
        else if(tmpStrValue == "wareid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.wareId = intValue;
        }
        else if(tmpStrValue == "worth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                if(moneyMap.find(intValue) != moneyMap.end() && !override)
                    std::clog << "[Warning - Items::loadFromXml] Duplicated money item " << id << " with worth " << intValue << "!" << std::endl;
                else
                {
                    moneyMap[intValue] = id;
                    it.worth = intValue;
                }
            }
        }
        else if(tmpStrValue == "forceserialize" || tmpStrValue == "forceserialization" || tmpStrValue == "forcesave")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.forceSerialize = (intValue != 0);
        }
        else if(tmpStrValue == "leveldoor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.levelDoor = intValue;
        }
        else if(tmpStrValue == "specialdoor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.specialDoor = (intValue != 0);
        }
        else if(tmpStrValue == "closingdoor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.closingDoor = (intValue != 0);
        }
        else if(tmpStrValue == "weapontype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "sword")
                    it.weaponType = WEAPON_SWORD;
                else if(tmpStrValue == "club")
                    it.weaponType = WEAPON_CLUB;
                else if(tmpStrValue == "axe")
                    it.weaponType = WEAPON_AXE;
                else if(tmpStrValue == "shield")
                    it.weaponType = WEAPON_SHIELD;
                else if(tmpStrValue == "distance" || tmpStrValue == "dist")
                    it.weaponType = WEAPON_DIST;
                else if(tmpStrValue == "wand" || tmpStrValue == "rod")
                    it.weaponType = WEAPON_WAND;
                else if(tmpStrValue == "ammunition" || tmpStrValue == "ammo")
                    it.weaponType = WEAPON_AMMO;
                else if(tmpStrValue == "fist")
                    it.weaponType = WEAPON_FIST;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown weaponType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "slottype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "head")
                {
                    it.slotPosition |= SLOTP_HEAD;
                    it.wieldPosition = SLOT_HEAD;
                }
                else if(tmpStrValue == "body")
                {
                    it.slotPosition |= SLOTP_ARMOR;
                    it.wieldPosition = SLOT_ARMOR;
                }
                else if(tmpStrValue == "legs")
                {
                    it.slotPosition |= SLOTP_LEGS;
                    it.wieldPosition = SLOT_LEGS;
                }
                else if(tmpStrValue == "feet")
                {
                    it.slotPosition |= SLOTP_FEET;
                    it.wieldPosition = SLOT_FEET;
                }
                else if(tmpStrValue == "backpack")
                {
                    it.slotPosition |= SLOTP_BACKPACK;
                    it.wieldPosition = SLOT_BACKPACK;
                }
                else if(tmpStrValue == "two-handed")
                {
                    it.slotPosition |= SLOTP_TWO_HAND;
                    it.wieldPosition = SLOT_TWO_HAND;
                }
                else if(tmpStrValue == "right-hand")
                {
                    it.slotPosition &= ~SLOTP_LEFT;
                    it.wieldPosition = SLOT_RIGHT;
                }
                else if(tmpStrValue == "left-hand")
                {
                    it.slotPosition &= ~SLOTP_RIGHT;
                    it.wieldPosition = SLOT_LEFT;
                }
                else if(tmpStrValue == "necklace")
                {
                    it.slotPosition |= SLOTP_NECKLACE;
                    it.wieldPosition = SLOT_NECKLACE;
                }
                else if(tmpStrValue == "ring")
                {
                    it.slotPosition |= SLOTP_RING;
                    it.wieldPosition = SLOT_RING;
                }
                else if(tmpStrValue == "ammo")
                {
                    it.slotPosition |= SLOTP_AMMO;
                    it.wieldPosition = SLOT_AMMO;
                }
                else if(tmpStrValue == "hand")
                    it.wieldPosition = SLOT_HAND;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown slotType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "ammotype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                it.ammoType = getAmmoType(strValue);
                if(it.ammoType == AMMO_NONE)
                    std::clog << "[Warning - Items::loadFromXml] Unknown ammoType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "shoottype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                ShootEffect_t shoot = getShootType(strValue);
                if(shoot != SHOOT_EFFECT_UNKNOWN)
                    it.shootType = shoot;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown shootType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "effect")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                MagicEffect_t effect = getMagicEffect(strValue);
                if(effect != MAGIC_EFFECT_UNKNOWN)
                    it.magicEffect = effect;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown effect " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "range")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.shootRange = intValue;
        }
        else if(tmpStrValue == "stopduration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.stopTime = (intValue != 0);
        }
        else if(tmpStrValue == "decayto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.decayTo = intValue;
        }
        else if(tmpStrValue == "transformequipto" || tmpStrValue == "onequipto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.transformEquipTo = intValue;
        }
        else if(tmpStrValue == "transformdeequipto" || tmpStrValue == "ondeequipto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.transformDeEquipTo = intValue;
        }
        else if(tmpStrValue == "duration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.decayTime = std::max((int32_t)0, intValue);
        }
        else if(tmpStrValue == "showduration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showDuration = (intValue != 0);
        }
        else if(tmpStrValue == "charges")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.charges = intValue;
        }
        else if(tmpStrValue == "showcharges")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showCharges = (intValue != 0);
        }
        else if(tmpStrValue == "showattributes")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showAttributes = (intValue != 0);
        }
        else if(tmpStrValue == "breakchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.breakChance = std::max(0, std::min(100, intValue));
        }
        else if(tmpStrValue == "ammoaction")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                AmmoAction_t ammo = getAmmoAction(strValue);
                if(ammo != AMMOACTION_NONE)
                    it.ammoAction = ammo;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown ammoAction " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "hitchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.hitChance = std::max(-100, std::min(100, intValue));
        }
        else if(tmpStrValue == "maxhitchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.maxHitChance = std::max(0, std::min(100, intValue));
        }
        else if(tmpStrValue == "dualwield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.dualWield = (intValue != 0);
        }
        else if(tmpStrValue == "preventloss")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->preventLoss = (intValue != 0);
        }
        else if(tmpStrValue == "preventdrop")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->preventDrop = (intValue != 0);
        }
        else if(tmpStrValue == "invisible")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->invisible = (intValue != 0);
        }
        else if(tmpStrValue == "speed")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->speed = intValue;
        }
        else if(tmpStrValue == "healthgain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->healthGain = intValue;
            }
        }
        else if(tmpStrValue == "healthticks")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->healthTicks = intValue;
            }
        }
        else if(tmpStrValue == "managain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->manaGain = intValue;
            }
        }
        else if(tmpStrValue == "manaticks")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->manaTicks = intValue;
            }
        }
        else if(tmpStrValue == "manashield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->manaShield = (intValue != 0);
        }
        else if(tmpStrValue == "skillsword")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_SWORD] = intValue;
        }
        else if(tmpStrValue == "skillaxe")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_AXE] = intValue;
        }
        else if(tmpStrValue == "skillclub")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_CLUB] = intValue;
        }
        else if(tmpStrValue == "skilldist")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_DIST] = intValue;
        }
        else if(tmpStrValue == "skillfish")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_FISH] = intValue;
        }
        else if(tmpStrValue == "skillshield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_SHIELD] = intValue;
        }
        else if(tmpStrValue == "skillfist")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_FIST] = intValue;
        }
        else if(tmpStrValue == "maxhealthpoints" || tmpStrValue == "maxhitpoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_MAXHEALTH] = intValue;
        }
        else if(tmpStrValue == "maxhealthpercent" || tmpStrValue == "maxhitpointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_MAXHEALTH] = intValue;
        }
        else if(tmpStrValue == "maxmanapoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_MAXMANA] = intValue;
        }
        else if(tmpStrValue == "maxmanapercent" || tmpStrValue == "maxmanapointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_MAXMANA] = intValue;
        }
        else if(tmpStrValue == "soulpoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_SOUL] = intValue;
        }
        else if(tmpStrValue == "soulpercent" || tmpStrValue == "soulpointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_SOUL] = intValue;
        }
        else if(tmpStrValue == "magiclevelpoints" || tmpStrValue == "magicpoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_MAGICLEVEL] = intValue;
        }
        else if(tmpStrValue == "magiclevelpercent" || tmpStrValue == "magicpointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_MAGICLEVEL] = intValue;
        }
        else if(tmpStrValue == "increasemagicvalue")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[MAGIC_VALUE] = intValue;
        }
        else if(tmpStrValue == "increasemagicpercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[MAGIC_PERCENT] = intValue;
        }
        else if(tmpStrValue == "increasehealingvalue")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[HEALING_VALUE] = intValue;
        }
        else if(tmpStrValue == "increasehealingpercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[HEALING_PERCENT] = intValue;
        }
        else if(tmpStrValue == "fieldabsorbpercentenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->fieldAbsorb[COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "fieldabsorbpercentfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->fieldAbsorb[COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "fieldabsorbpercentpoison" || tmpStrValue == "fieldabsorbpercentearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->fieldAbsorb[COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentall")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                    it.getAbilities()->absorb += intValue;
            }
        }
        else if(tmpStrValue == "absorbpercentelements")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->absorb[COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_ICEDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "absorbpercentmagic")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->absorb[COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_ICEDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_HOLYDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_DEATHDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "absorbpercentenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentpoison" || tmpStrValue == "absorbpercentearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_ICEDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_HOLYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_DEATHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentlifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_LIFEDRAIN] += intValue;
        }
        else if(tmpStrValue == "absorbpercentmanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_MANADRAIN] += intValue;
        }
        else if(tmpStrValue == "absorbpercentdrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_DROWNDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_PHYSICALDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercenthealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_HEALING] += intValue;
        }
        else if(tmpStrValue == "absorbpercentundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_UNDEFINEDDAMAGE] += intValue;
        }
#ifndef _MSC_VER
        else if(tmpStrValue == "reflectpercentall")
#else
        else
            notLoaded = true;

        if(!notLoaded)
            continue;

        if(tmpStrValue == "reflectpercentall")
#endif
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                    it.getAbilities()->reflect[REFLECT_PERCENT] += intValue;
            }
        }
        else if(tmpStrValue == "reflectpercentelements")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ICEDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectpercentmagic")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ICEDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_HOLYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_DEATHDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectpercentenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentpoison" || tmpStrValue == "reflectpercentearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ICEDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_HOLYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_DEATHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentlifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_LIFEDRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectpercentmanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_MANADRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectpercentdrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_DROWNDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_PHYSICALDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercenthealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_HEALING] += intValue;
        }
        else if(tmpStrValue == "reflectpercentundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_UNDEFINEDDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchanceall")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                    it.getAbilities()->reflect[REFLECT_CHANCE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectchanceelements")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ICEDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectchancemagic")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ICEDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_HOLYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_DEATHDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectchanceenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancefire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancepoison" ||    tmpStrValue == "reflectchanceearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchanceice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ICEDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchanceholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_HOLYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancedeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_DEATHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancelifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_LIFEDRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectchancemanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_MANADRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectchancedrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_DROWNDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancephysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_PHYSICALDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancehealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_HEALING] += intValue;
        }
        else if(tmpStrValue == "reflectchanceundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_UNDEFINEDDAMAGE] += intValue;
        }
        else if(tmpStrValue == "suppressshock" || tmpStrValue == "suppressenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_ENERGY;
        }
        else if(tmpStrValue == "suppressburn" || tmpStrValue == "suppressfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_FIRE;
        }
        else if(tmpStrValue == "suppresspoison" || tmpStrValue == "suppressearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_POISON;
        }
        else if(tmpStrValue == "suppressfreeze" || tmpStrValue == "suppressice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_FREEZING;
        }
        else if(tmpStrValue == "suppressdazzle" || tmpStrValue == "suppressholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_DAZZLED;
        }
        else if(tmpStrValue == "suppresscurse" || tmpStrValue == "suppressdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_CURSED;
        }
        else if(tmpStrValue == "suppressdrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_DROWN;
        }
        else if(tmpStrValue == "suppressphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_BLEEDING;
        }
        else if(tmpStrValue == "suppresshaste")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_HASTE;
        }
        else if(tmpStrValue == "suppressparalyze")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_PARALYZE;
        }
        else if(tmpStrValue == "suppressdrunk")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_DRUNK;
        }
        else if(tmpStrValue == "suppressregeneration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_REGENERATION;
        }
        else if(tmpStrValue == "suppresssoul")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_SOUL;
        }
        else if(tmpStrValue == "suppressoutfit")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_OUTFIT;
        }
        else if(tmpStrValue == "suppressinvisible")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_INVISIBLE;
        }
        else if(tmpStrValue == "suppressinfight")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_INFIGHT;
        }
        else if(tmpStrValue == "suppressexhaust")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_EXHAUST;
        }
        else if(tmpStrValue == "suppressmuted")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_MUTED;
        }
        else if(tmpStrValue == "suppresspacified")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_PACIFIED;
        }
        else if(tmpStrValue == "suppresslight")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_LIGHT;
        }
        else if(tmpStrValue == "suppressattributes")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_ATTRIBUTES;
        }
        else if(tmpStrValue == "suppressmanashield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_MANASHIELD;
        }
        else if(tmpStrValue == "field")
        {
            it.group = ITEM_GROUP_MAGICFIELD;
            it.type = ITEM_TYPE_MAGICFIELD;

            CombatType_t combatType = COMBAT_NONE;
            ConditionDamage* conditionDamage = NULL;
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "fire")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FIRE, false, 0);
                    combatType = COMBAT_FIREDAMAGE;
                }
                else if(tmpStrValue == "energy")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_ENERGY, false, 0);
                    combatType = COMBAT_ENERGYDAMAGE;
                }
                else if(tmpStrValue == "earth" || tmpStrValue == "poison")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_POISON, false, 0);
                    combatType = COMBAT_EARTHDAMAGE;
                }
                else if(tmpStrValue == "ice" || tmpStrValue == "freezing")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FREEZING, false, 0);
                    combatType = COMBAT_ICEDAMAGE;
                }
                else if(tmpStrValue == "holy" || tmpStrValue == "dazzled")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DAZZLED, false, 0);
                    combatType = COMBAT_HOLYDAMAGE;
                }
                else if(tmpStrValue == "death" || tmpStrValue == "cursed")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_CURSED, false, 0);
                    combatType = COMBAT_DEATHDAMAGE;
                }
                else if(tmpStrValue == "drown")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DROWN, false, 0);
                    combatType = COMBAT_DROWNDAMAGE;
                }
                else if(tmpStrValue == "physical" || tmpStrValue == "bleed")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_BLEEDING, false, 0);
                    combatType = COMBAT_PHYSICALDAMAGE;
                }
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown field value " << strValue << std::endl;

                if(combatType != COMBAT_NONE)
                {
                    it.combatType = combatType;
                    it.condition = conditionDamage;

                    uint32_t ticks = 0;
                    int32_t damage = 0, start = 0, count = 1;
                    for(xmlNodePtr fieldAttributesNode = itemAttributesNode->children; fieldAttributesNode; fieldAttributesNode = fieldAttributesNode->next)
                    {
                        if(!readXMLString(fieldAttributesNode, "key", strValue))
                            continue;

                        tmpStrValue = asLowerCaseString(strValue);
                        if(tmpStrValue == "ticks")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                                ticks = std::max(0, intValue);
                        }

                        if(tmpStrValue == "count")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                                count = std::max(1, intValue);
                        }

                        if(tmpStrValue == "start")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                                start = std::max(0, intValue);
                        }

                        if(tmpStrValue == "damage")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                            {
                                damage = -intValue;
                                if(start > 0)
                                {
                                    std::list<int32_t> damageList;
                                    ConditionDamage::generateDamageList(damage, start, damageList);
                                    for(std::list<int32_t>::iterator it = damageList.begin(); it != damageList.end(); ++it)
                                        conditionDamage->addDamage(1, ticks, -*it);

                                    start = 0;
                                }
                                else
                                    conditionDamage->addDamage(count, ticks, damage);
                            }
                        }
                    }

                    conditionDamage->setParam(CONDITIONPARAM_FIELD, true);
                    if(conditionDamage->getTotalDamage() > 0)
                        conditionDamage->setParam(CONDITIONPARAM_FORCEUPDATE, true);
                }
            }
        }
        else if(tmpStrValue == "elementphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_PHYSICALDAMAGE;
            }
        }
        else if(tmpStrValue == "elementfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_FIREDAMAGE;
            }
        }
        else if(tmpStrValue == "elementenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_ENERGYDAMAGE;
            }
        }
        else if(tmpStrValue == "elementearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_EARTHDAMAGE;
            }
        }
        else if(tmpStrValue == "elementice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_ICEDAMAGE;
            }
        }
        else if(tmpStrValue == "elementholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_HOLYDAMAGE;
            }
        }
        else if(tmpStrValue == "elementdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_DEATHDAMAGE;
            }
        }
        else if(tmpStrValue == "elementlifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_LIFEDRAIN;
            }
        }
        else if(tmpStrValue == "elementmanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_MANADRAIN;
            }
        }
        else if(tmpStrValue == "elementhealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_HEALING;
            }
        }
        else if(tmpStrValue == "elementundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_UNDEFINEDDAMAGE;
            }
        }
        else if(tmpStrValue == "replacable" || tmpStrValue == "replaceable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.replacable = (intValue != 0);
        }
        else if(tmpStrValue == "partnerdirection")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.bedPartnerDir = getDirection(strValue);
        }
        else if(tmpStrValue == "maletransformto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.transformBed[PLAYERSEX_MALE] = intValue;
                ItemType& ot = getItemType(intValue);
                if(!ot.transformUseTo)
                    ot.transformUseTo = it.id;

                if(!it.transformBed[PLAYERSEX_FEMALE])
                    it.transformBed[PLAYERSEX_FEMALE] = intValue;
            }
        }
        else if(tmpStrValue == "femaletransformto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.transformBed[PLAYERSEX_FEMALE] = intValue;
                ItemType& ot = getItemType(intValue);
                if(!ot.transformUseTo)
                    ot.transformUseTo = it.id;

                if(!it.transformBed[PLAYERSEX_MALE])
                    it.transformBed[PLAYERSEX_MALE] = intValue;
            }
        }
        else if(tmpStrValue == "transformto" || tmpStrValue == "transformuseto" || tmpStrValue == "onuseto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.transformUseTo = intValue;
        }
        else if(tmpStrValue == "walkstack")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.walkStack = (intValue != 0);
        }
        else if(tmpStrValue == "premiumdays")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.premiumDays = intValue;
        }
        else
            std::clog << "[Warning - Items::loadFromXml] Unknown key value " << strValue << std::endl;
    }

    if(it.pluralName.empty() && !it.name.empty())
    {
        it.pluralName = it.name;
        if(it.showCount)
            it.pluralName += "s";
    }

    it.getAbilities()->absorb[COMBAT_ALL] = it.getAbilities()->absorb[COMBAT_FIRST + 1];
    it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ALL] = it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIRST + 1];
    it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ALL] = it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIRST + 1];
    for(uint32_t i = (COMBAT_FIRST + 1) << 1; i <= COMBAT_LAST; i <<= 1)
    {
        if(it.getAbilities()->absorb[COMBAT_ALL] != it.getAbilities()->absorb)
            it.getAbilities()->absorb[COMBAT_ALL] = 0;

        if(it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ALL] != it.getAbilities()->reflect[REFLECT_PERCENT])
            it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ALL] = 0;

        if(it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ALL] != it.getAbilities()->reflect[REFLECT_CHANCE])
            it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ALL] = 0;
    }
}

void Items::parseRandomizationBlock(int32_t id, int32_t fromId, int32_t toId, int32_t chance)
{
    RandomizationMap::iterator it = randomizationMap.find(id);
    if(it != randomizationMap.end())
    {
        std::clog << "[Warning - Items::parseRandomizationBlock] Duplicated item with id: " << id << std::endl;
        return;
    }

    RandomizationBlock rand;
    rand.fromRange = fromId;
    rand.toRange = toId;

    rand.chance = chance;
    randomizationMap[id] = rand;
}

uint16_t Items::getRandomizedItem(uint16_t id)
{
    if(!g_config.getBool(ConfigManager::RANDOMIZE_TILES))
        return id;

    RandomizationBlock randomize = getRandomization(id);
    if(randomize.chance >= random_range(1, 100))
        id = random_range(randomize.fromRange, randomize.toRange);

    return id;
}

ItemType& Items::getItemType(int32_t id)
{
    ItemType* iType = items.getElement(id);
    if(iType)
        return *iType;

    #ifdef __DEBUG__
    std::clog << "[Warning - Items::getItemType] Unknown itemtype with id " << id << ", using defaults." << std::endl;
    #endif
    static ItemType dummyItemType; // use this for invalid ids
    return dummyItemType;
}

const ItemType& Items::getItemType(int32_t id) const
{
    if(ItemType* iType = items.getElement(id))
        return *iType;

    static ItemType dummyItemType; // use this for invalid ids
    return dummyItemType;
}

const ItemType& Items::getItemIdByClientId(int32_t spriteId) const
{
    auto it = reverseItemMap.find(spriteId);
    if (it != reverseItemMap.end()) {
        return getItemType(it->second);
    }

    static ItemType dummyItemType; // use this for invalid ids
    return dummyItemType;
}

int32_t Items::getItemIdByName(const std::string& name)
{
    if(!name.empty())
    {
        uint32_t i = 100;
        ItemType* iType = NULL;
        do
        {
            if((iType = items.getElement(i)) && boost::algorithm::iequals(name, iType->name))
                return i;

            ++i;
        }
        while(iType);
    }

    return -1;
}

 

Link para o comentário
Compartilhar em outros sites

  • 0

item.cpp:

Citar

#include "otpch.h"
#include <iostream>
#include <iomanip>

#include "item.h"
#include "container.h"
#include "depot.h"

#include "teleport.h"
#include "trashholder.h"
#include "mailbox.h"

#include "luascript.h"
#include "combat.h"

#include "house.h"
#include "beds.h"

#include "actions.h"
#include "configmanager.h"
#include "game.h"
#include "movement.h"

extern Game g_game;
extern ConfigManager g_config;
extern MoveEvents* g_moveEvents;

Items Item::items;
Item* Item::CreateItem(const uint16_t type, uint16_t amount/* = 0*/)
{
    const ItemType& it = Item::items[type];
    if(it.group == ITEM_GROUP_DEPRECATED)
    {
        #ifdef __DEBUG__
        std::clog << "[Error - Item::CreateItem] Item " << it.id << " has been declared as deprecated" << std::endl;
        #endif
        return NULL;
    }

    if(!it.id)
        return NULL;

    Item* newItem = NULL;
    if(it.isDepot())
        newItem = new Depot(type);
    else if(it.isContainer())
        newItem = new Container(type);
    else if(it.isTeleport())
        newItem = new Teleport(type);
    else if(it.isMagicField())
        newItem = new MagicField(type);
    else if(it.isDoor())
        newItem = new Door(type);
    else if(it.isTrashHolder())
        newItem = new TrashHolder(type, it.magicEffect);
    else if(it.isMailbox())
        newItem = new Mailbox(type);
    else if(it.isBed())
        newItem = new BedItem(type);
    else if(it.id >= 2210 && it.id <= 2212)
        newItem = new Item(type - 3, amount);
    else if(it.id == 2215 || it.id == 2216)
        newItem = new Item(type - 2, amount);
    else if(it.id >= 2202 && it.id <= 2206)
        newItem = new Item(type - 37, amount);
    else if(it.id == 2640)
        newItem = new Item(6132, amount);
    else if(it.id == 6301)
        newItem = new Item(6300, amount);
    else
        newItem = new Item(type, amount);

    newItem->addRef();
    return newItem;
}

Item* Item::CreateItem(PropStream& propStream)
{
    uint16_t type;
    if(!propStream.getShort(type))
        return NULL;

    return Item::CreateItem(items.getRandomizedItem(type), 0);
}

bool Item::loadItem(xmlNodePtr node, Container* parent)
{
    if(!xmlStrcmp(node->name, (const xmlChar*)"item"))
        return false;

    int32_t intValue;
    std::string strValue;

    Item* item = NULL;
    if(readXMLInteger(node, "id", intValue))
        item = Item::CreateItem(intValue);

    if(!item)
        return false;

    if(readXMLString(node, "attributes", strValue))
    {
        StringVec v, attr = explodeString(strValue, ";");
        for(StringVec::iterator it = attr.begin(); it != attr.end(); ++it)
        {
            v = explodeString((*it), ",");
            if(v.size() < 2)
                continue;

            if(atoi(v[1].c_str()) || v[1] == "0")
                item->setAttribute(v[0].c_str(), atoi(v[1].c_str()));
            else
                item->setAttribute(v[0].c_str(), v[1]);
        }
    }

    //compatibility
    if(readXMLInteger(node, "subtype", intValue) || readXMLInteger(node, "subType", intValue))
        item->setSubType(intValue);

    if(readXMLInteger(node, "actionId", intValue) || readXMLInteger(node, "actionid", intValue)
        || readXMLInteger(node, "aid", intValue))
        item->setActionId(intValue);

    if(readXMLInteger(node, "uniqueId", intValue) || readXMLInteger(node, "uniqueid", intValue)
        || readXMLInteger(node, "uid", intValue))
        item->setUniqueId(intValue);

    if(readXMLString(node, "text", strValue))
        item->setText(strValue);

    if(item->getContainer())
        loadContainer(node, item->getContainer());

    if(parent)
        parent->addItem(item);

    return true;
}

bool Item::loadContainer(xmlNodePtr parentNode, Container* parent)
{
    for(xmlNodePtr node = parentNode->children; node; node = node->next)
    {
        if(node->type != XML_ELEMENT_NODE)
            continue;

        if(!xmlStrcmp(node->name, (const xmlChar*)"item") && !loadItem(node, parent))
            return false;
    }

    return true;
}

Item::Item(const uint16_t type, uint16_t amount/* = 0*/):
    ItemAttributes(), id(type)
{
    duration = 0;
    raid = NULL;
    loadedFromMap = false;

    setItemCount(1);
    setDefaultDuration();
    itemUid = -1;

    const ItemType& it = items[type];
    if(it.isFluidContainer() || it.isSplash())
        setFluidType(amount);
    else if(it.stackable)
    {
        if(amount)
            setItemCount(amount);
        else if(it.charges)
            setItemCount(it.charges);
    }
    else if(it.charges)
        setCharges(amount ? amount : it.charges);

    if(it.armorRndMin > 0 && it.armorRndMax > it.armorRndMin)
        setAttribute("armor", it.armorRndMin + rand() % (it.armorRndMax+1 - it.armorRndMin));

    if(it.defenseRndMin > 0 && it.defenseRndMax > it.defenseRndMin)
        setAttribute("defense", it.defenseRndMin + rand() % (it.defenseRndMax+1 - it.defenseRndMin));

    if(it.extraDefenseRndMin > 0 && it.extraDefenseRndMax > it.extraDefenseRndMin)
    if(it.extraDefenseChance == 0 || (it.extraDefenseChance >= rand() % 101) )
        setAttribute("extradefense", it.extraDefenseRndMin + rand() % (it.extraDefenseRndMax+1 - it.extraDefenseRndMin));

    if(it.attackRndMin > 0 && it.attackRndMax > it.attackRndMin)
        setAttribute("attack", it.attackRndMin + rand() % (it.attackRndMax - it.attackRndMin));

    if(it.extraAttackRndMin > 0 && it.extraAttackRndMax > it.extraAttackRndMin)
    if(it.extraAttackChance == 0 || (it.extraAttackChance >= rand() % 101) )
        setAttribute("extraattack", it.extraAttackRndMin + rand() % (it.extraAttackRndMax+1 - it.extraAttackRndMin));

    if(it.attackSpeedRndMin > 0 && it.attackSpeedRndMax > it.attackSpeedRndMin)
    if(it.attackSpeedChance == 0 || (it.attackSpeedChance >= rand() % 101) )
        setAttribute("attackSpeed", it.attackSpeedRndMin + rand() % (it.attackSpeedRndMax+1 - it.attackSpeedRndMin));
}

Item* Item::clone() const
{
    Item* tmp = Item::CreateItem(id, count);
    if(!tmp)
        return NULL;

    if(!attributes || attributes->empty())
        return tmp;

    tmp->createAttributes();
    *tmp->attributes = *attributes;
    tmp->eraseAttribute("uid");
    return tmp;
}

void Item::copyAttributes(Item* item)
{
    if (item && item->attributes && !item->attributes->empty())
    {
        createAttributes();
        *attributes = *item->attributes;
        eraseAttribute("uid");
    }

    eraseAttribute("decaying");
    duration = 0;
}

void Item::makeUnique(Item* parent)
{
    if(!parent || !parent->getUniqueId())
        return;

    ScriptEnviroment::removeUniqueThing(parent);
    setUniqueId(parent->getUniqueId());
    parent->eraseAttribute("uid");
}

void Item::onRemoved()
{
    if(raid)
    {
        raid->unRef();
        raid = NULL;
    }

    ScriptEnviroment::removeTempItem(this);
    if(getUniqueId())
        ScriptEnviroment::removeUniqueThing(this);
}

void Item::setDefaultSubtype()
{
    setItemCount(1);
    const ItemType& it = items[id];
    if(it.charges)
        setCharges(it.charges);
}

void Item::setID(uint16_t newId)
{
    const ItemType& it = Item::items[newId];
    const ItemType& pit = Item::items[id];
    id = newId;

    uint32_t newDuration = it.decayTime * 1000;
    if (!newDuration && !it.stopTime && it.decayTo == -1)
    {
        eraseAttribute("decaying");
        duration = -1;
    }

    eraseAttribute("corpseowner");
    if (newDuration > 0 && (!pit.stopTime || duration == 0))
    {
        setDecaying(DECAYING_FALSE);
        setDuration(newDuration);
    }
}

bool Item::floorChange(FloorChange_t change/* = CHANGE_NONE*/) const
{
    if(change < CHANGE_NONE)
        return Item::items[id].floorChange[change];

    for(int32_t i = CHANGE_PRE_FIRST; i < CHANGE_LAST; ++i)
    {
        if(Item::items[id].floorChange)
            return true;
    }

    return false;
}

Player* Item::getHoldingPlayer()
{
    for(Cylinder* p = getParent(); p; p = p->getParent())
    {
        if(p->getCreature())
            return p->getCreature()->getPlayer();
    }

    return NULL;
}

const Player* Item::getHoldingPlayer() const
{
    return const_cast<Item*>(this)->getHoldingPlayer();
}

uint16_t Item::getSubType() const
{
    const ItemType& it = items[id];
    if(it.isFluidContainer() || it.isSplash())
        return getFluidType();

    if(it.charges)
        return getCharges();

    return count;
}

void Item::setSubType(uint16_t n)
{
    const ItemType& it = items[id];
    if(it.isFluidContainer() || it.isSplash())
        setFluidType(n);
    else if(it.charges)
        setCharges(n);
    else
        count = n;
}

Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream& propStream)
{
    switch(attr)
    {
        case ATTR_COUNT:
        {
            uint8_t _count;
            if(!propStream.getByte(_count))
                return ATTR_READ_ERROR;

            setSubType((uint16_t)_count);
            break;
        }

        case ATTR_ACTION_ID:
        {
            uint16_t aid;
            if(!propStream.getShort(aid))
                return ATTR_READ_ERROR;

            setAttribute("aid", aid);
            break;
        }

        case ATTR_UNIQUE_ID:
        {
            uint16_t uid;
            if(!propStream.getShort(uid))
                return ATTR_READ_ERROR;
            
            itemUid = uid;
            setUniqueId(uid);
            break;
        }

        case ATTR_NAME:
        {
            std::string name;
            if(!propStream.getString(name))
                return ATTR_READ_ERROR;

            setAttribute("name", name);
            break;
        }

        case ATTR_PLURALNAME:
        {
            std::string name;
            if(!propStream.getString(name))
                return ATTR_READ_ERROR;

            setAttribute("pluralname", name);
            break;
        }

        case ATTR_ARTICLE:
        {
            std::string article;
            if(!propStream.getString(article))
                return ATTR_READ_ERROR;

            setAttribute("article", article);
            break;
        }

        case ATTR_CRITICALHITCHANCE:
        {
            int32_t criticalHitChance;
            if(!propStream.getLong((uint32_t&)criticalHitChance))
                return ATTR_READ_ERROR;

            setAttribute("criticalhitchance", criticalHitChance);
            break;
        }

        case ATTR_ATTACK:
        {
            int32_t attack;
            if(!propStream.getLong((uint32_t&)attack))
                return ATTR_READ_ERROR;

            setAttribute("attack", attack);
            break;
        }

        case ATTR_EXTRAATTACK:
        {
            int32_t attack;
            if(!propStream.getLong((uint32_t&)attack))
                return ATTR_READ_ERROR;

            setAttribute("extraattack", attack);
            break;
        }

        case ATTR_DEFENSE:
        {
            int32_t defense;
            if(!propStream.getLong((uint32_t&)defense))
                return ATTR_READ_ERROR;

            setAttribute("defense", defense);
            break;
        }

        case ATTR_EXTRADEFENSE:
        {
            int32_t defense;
            if(!propStream.getLong((uint32_t&)defense))
                return ATTR_READ_ERROR;

            setAttribute("extradefense", defense);
            break;
        }

        case ATTR_ARMOR:
        {
            int32_t armor;
            if(!propStream.getLong((uint32_t&)armor))
                return ATTR_READ_ERROR;

            setAttribute("armor", armor);
            break;
        }

        case ATTR_ATTACKSPEED:
        {
            int32_t attackSpeed;
            if(!propStream.getLong((uint32_t&)attackSpeed))
                return ATTR_READ_ERROR;

            setAttribute("attackspeed", attackSpeed);
            break;
        }

        case ATTR_HITCHANCE:
        {
            int32_t hitChance;
            if(!propStream.getLong((uint32_t&)hitChance))
                return ATTR_READ_ERROR;

            setAttribute("hitchance", hitChance);
            break;
        }

        case ATTR_SCRIPTPROTECTED:
        {
            uint8_t protection;
            if(!propStream.getByte(protection))
                return ATTR_READ_ERROR;

            setAttribute("scriptprotected", protection != 0);
            break;
        }

        case ATTR_DUALWIELD:
        {
            uint8_t wield;
            if(!propStream.getByte(wield))
                return ATTR_READ_ERROR;

            setAttribute("dualwield", wield != 0);
            break;
        }

        case ATTR_TEXT:
        {
            std::string text;
            if(!propStream.getString(text))
                return ATTR_READ_ERROR;

            setAttribute("text", text);
            break;
        }

        case ATTR_WRITTENDATE:
        {
            int32_t date;
            if(!propStream.getLong((uint32_t&)date))
                return ATTR_READ_ERROR;

            setAttribute("date", date);
            break;
        }

        case ATTR_WRITTENBY:
        {
            std::string writer;
            if(!propStream.getString(writer))
                return ATTR_READ_ERROR;

            setAttribute("writer", writer);
            break;
        }

        case ATTR_DESC:
        {
            std::string text;
            if(!propStream.getString(text))
                return ATTR_READ_ERROR;

            setAttribute("description", text);
            break;
        }

        case ATTR_RUNE_CHARGES:
        {
            uint8_t charges;
            if(!propStream.getByte(charges))
                return ATTR_READ_ERROR;

            setSubType((uint16_t)charges);
            break;
        }

        case ATTR_CHARGES:
        {
            uint16_t charges;
            if(!propStream.getShort(charges))
                return ATTR_READ_ERROR;

            setSubType(charges);
            break;
        }

        case ATTR_DURATION:
        {
            int32_t duration;
            if(!propStream.getLong((uint32_t&)duration))
                return ATTR_READ_ERROR;

            //setAttribute("duration", duration);
            this->duration = duration;
            break;
        }

        case ATTR_DECAYING_STATE:
        {
            uint8_t state;
            if(!propStream.getByte(state))
                return ATTR_READ_ERROR;

            if((ItemDecayState_t)state != DECAYING_FALSE)
                setAttribute("decaying", (int32_t)DECAYING_PENDING);

            break;
        }

        //these should be handled through derived classes
        //if these are called then something has changed in the items.otb since the map was saved
        //just read the values

        //Depot class
        case ATTR_DEPOT_ID:
        {
            uint16_t depot;
            if(!propStream.getShort(depot))
                return ATTR_READ_ERROR;

            break;
        }

        //Door class
        case ATTR_HOUSEDOORID:
        {
            uint8_t door;
            if(!propStream.getByte(door))
                return ATTR_READ_ERROR;

            break;
        }

        //Teleport class
        case ATTR_TELE_DEST:
        {
            TeleportDest* dest;
            if(!propStream.getStruct(dest))
                return ATTR_READ_ERROR;

            break;
        }

        //Bed class
        case ATTR_SLEEPERGUID:
        {
            uint32_t sleeper;
            if(!propStream.getLong(sleeper))
                return ATTR_READ_ERROR;

            break;
        }

        case ATTR_SLEEPSTART:
        {
            uint32_t sleepStart;
            if(!propStream.getLong(sleepStart))
                return ATTR_READ_ERROR;

            break;
        }

        //Container class
        case ATTR_CONTAINER_ITEMS:
        {
            uint32_t _count;
            propStream.getLong(_count);
            return ATTR_READ_ERROR;
        }

        //ItemAttributes class
        case ATTR_ATTRIBUTE_MAP:
        {
            bool unique = hasIntegerAttribute("uid"), ret = unserializeMap(propStream);
            if(!unique && hasIntegerAttribute("uid")) // unfortunately we have to do this
                ScriptEnviroment::addUniqueThing(this);

            // this attribute has a custom behavior as well
            if(getDecaying() != DECAYING_FALSE)
                setDecaying(DECAYING_PENDING);

            if(ret)
                break;
        }

        default:
            return ATTR_READ_ERROR;
    }

    return ATTR_READ_CONTINUE;
}

bool Item::unserializeAttr(PropStream& propStream)
{
    uint8_t attrType = ATTR_END;
    while(propStream.getByte(attrType) && attrType != ATTR_END)
    {
        switch(readAttr((AttrTypes_t)attrType, propStream))
        {
            case ATTR_READ_ERROR:
                return false;

            case ATTR_READ_END:
                return true;

            default:
                break;
        }
    }

    return true;
}

bool Item::serializeAttr(PropWriteStream& propWriteStream) const
{
    if (isStackable() || isFluidContainer() || isSplash())
    {
        propWriteStream.addByte(ATTR_COUNT);
        propWriteStream.addByte((uint8_t)getSubType());
    }

    if (duration != 0)
    {
        propWriteStream.addByte(ATTR_DURATION);
        propWriteStream.addType(duration);
    }

    if (attributes && !attributes->empty())
    {
        propWriteStream.addByte(ATTR_ATTRIBUTE_MAP);
        serializeMap(propWriteStream);
    }

    return true;
}

bool Item::hasProperty(enum ITEMPROPERTY prop) const
{
    const ItemType& it = items[id];
    switch(prop)
    {
        case BLOCKSOLID:
            if(it.blockSolid)
                return true;

            break;

        case MOVABLE:
            if(it.movable && (!loadedFromMap || (!getUniqueId()
                && (!getActionId() || !getContainer()))))
                return true;

            break;

        case HASHEIGHT:
            if(it.hasHeight)
                return true;

            break;

        case BLOCKPROJECTILE:
            if(it.blockProjectile)
                return true;

            break;

        case BLOCKPATH:
            if(it.blockPathFind)
                return true;

            break;

        case ISVERTICAL:
            if(it.isVertical)
                return true;

            break;

        case ISHORIZONTAL:
            if(it.isHorizontal)
                return true;

            break;

        case IMMOVABLEBLOCKSOLID:
            if(it.blockSolid && (!it.movable || (loadedFromMap &&
                (getUniqueId() || (getActionId() && getContainer())))))
                return true;

            break;

        case IMMOVABLEBLOCKPATH:
            if(it.blockPathFind && (!it.movable || (loadedFromMap &&
                (getUniqueId() || (getActionId() && getContainer())))))
                return true;

            break;

        case SUPPORTHANGABLE:
            if(it.isHorizontal || it.isVertical)
                return true;

            break;

        case IMMOVABLENOFIELDBLOCKPATH:
            if(!it.isMagicField() && it.blockPathFind && (!it.movable || (loadedFromMap &&
                (getUniqueId() || (getActionId() && getContainer())))))
                return true;

            break;

        case NOFIELDBLOCKPATH:
            if(!it.isMagicField() && it.blockPathFind)
                return true;

            break;

        case FLOORCHANGEDOWN:
            if(it.floorChange[CHANGE_DOWN])
                return true;

            break;

        case FLOORCHANGEUP:
            for(uint16_t i = CHANGE_FIRST; i <= CHANGE_PRE_LAST; ++i)
            {
                if(it.floorChange)
                    return true;
            }

            break;

        default:
            break;
    }

    return false;
}

double Item::getWeight() const
{
    if(isStackable())
        return items[id].weight * std::max((int32_t)1, (int32_t)count);

    return items[id].weight;
}

std::string Item::getDescription(const ItemType& it, int32_t lookDistance, const Item* item/* = NULL*/,
    int32_t subType/* = -1*/, bool addArticle/* = true*/)
{
    std::ostringstream s;
    s << getNameDescription(it, item, subType, addArticle);
    if(item)
        subType = item->getSubType();

    bool dot = true;
    if(it.isRune())
    {
        if(!it.runeSpellName.empty())
            s << "(\"" << it.runeSpellName << "\")";

        if(it.runeLevel > 0 || it.runeMagLevel > 0 || (it.vocationString != "" && it.wieldInfo == 0))
        {
            s << "." << std::endl << "It can only be used";
            if(it.vocationString != "" && it.wieldInfo == 0)
                s << " by " << it.vocationString;

            bool begin = true;
            if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && it.runeLevel > 0)
            {
                begin = false;
                s << " with level " << it.runeLevel;
            }

            if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && it.runeMagLevel > 0)
            {
                begin = false;
                s << " " << (begin ? "with" : "and") << " magic level " << it.runeMagLevel;
            }

            if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && !begin)
                s << " or higher";
        }
    }
    else if(it.weaponType != WEAPON_NONE)
    {
        bool begin = true;
        if(it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE)
        {
            begin = false;
            s << " (Range:" << int32_t(item ? item->getShootRange() : it.shootRange);
            if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack())))
            {
                s << ", Atk " << std::showpos << int32_t(item ? item->getAttack() : it.attack);
                if(it.extraAttack || (item && item->getExtraAttack()))
                    s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;
            }

            if(it.hitChance != -1 || (item && item->getHitChance() != -1))
                s << ", Hit% " << std::showpos << (item ? item->getHitChance() : it.hitChance) << std::noshowpos;

            if(it.attackSpeed || (item && item->getAttackSpeed()))
                s << ", AS: " << (item ? item->getAttackSpeed() : it.attackSpeed);
        }
        else if(it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND)
        {
            int32_t attack, defense, extraDefense;
            if (item) {
                attack = item->getAttack();
                defense = item->getDefense();
                extraDefense = item->getExtraDefense();
            } else {
                attack = it.attack;
                defense = it.defense;
                extraDefense = it.extraDefense;
            }

            if (attack != 0) {
                begin = false;
                s << " (Atk:" << attack;

                if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) {
                    s << " physical + " << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType);
                }
            }

            if (defense != 0 || extraDefense != 0) {
                if (begin) {
                    begin = false;
                    s << " (";
                } else {
                    s << ", ";
                }

                s << "Def:" << defense;
                if (extraDefense != 0) {
                    s << ' ' << std::showpos << extraDefense << std::noshowpos;
                }
            }
        }
        
        if(it.criticalHitChance || (item && item->getCriticalHitChance()))
        {
            if(begin)
            {
                begin = false;
                s << " (";
            }
            else
                s << ", ";
                s << "Crit Chance:" << std::showpos << int32_t(item ? item->getCriticalHitChance() : it.criticalHitChance) << "%"<< std::noshowpos;
        }

        if(it.attackSpeed || (item && item->getAttackSpeed()))
        {
            if(begin)
            {
                begin = false;
                s << " (";
            }
            else
                s << ", ";

            s << "AS: " << (item ? item->getAttackSpeed() : it.attackSpeed);
        }

        if(it.hasAbilities())
        {
            for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
            {
                if(!it.abilities->skills)
                    continue;

                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities->skills << std::noshowpos;
            }

            if(it.abilities->stats[STAT_MAGICLEVEL])
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "magic level " << std::showpos << (int32_t)it.abilities->stats[STAT_MAGICLEVEL] << std::noshowpos;
            }

            int32_t show = it.abilities->absorb[COMBAT_ALL];
            if(!show)
            {
                bool tmp = true;
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                {
                    if(!it.abilities->absorb)
                        continue;

                    if(tmp)
                    {
                        tmp = false;
                        if(begin)
                        {
                            begin = false;
                            s << " (";
                        }
                        else
                            s << ", ";

                        s << "protection ";
                    }
                    else
                        s << ", ";

                    s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb << std::noshowpos << "%";
                }
            }
            else
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "protection all " << std::showpos << show << std::noshowpos << "%";
            }

            show = it.abilities->fieldAbsorb[COMBAT_ALL];
            if(!show)
            {
                bool tmp = true;
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                {
                    if(!it.abilities->fieldAbsorb)
                        continue;

                    if(tmp)
                    {
                        tmp = false;
                        if(begin)
                        {
                            begin = false;
                            s << " (";
                        }
                        else
                            s << ", ";

                        s << "protection ";
                    }
                    else
                        s << ", ";

                    s << getCombatName((CombatType_t)i) << " field " << std::showpos << it.abilities->absorb << std::noshowpos << "%";
                }
            }
            else
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "protection all fields " << std::showpos << show << std::noshowpos << "%";
            }

            show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL];
            if(!show)
            {
                bool tmp = true;
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                {
                    if(!it.abilities->reflect[REFLECT_CHANCE] || !it.abilities->reflect[REFLECT_PERCENT])
                        continue;

                    if(tmp)
                    {
                        tmp = false;
                        if(begin)
                        {
                            begin = false;
                            s << " (";
                        }
                        else
                            s << ", ";

                        s << "reflect: ";
                    }
                    else
                        s << ", ";

                    s << it.abilities->reflect[REFLECT_CHANCE] << "% for ";
                    if(it.abilities->reflect[REFLECT_PERCENT] > 99)
                        s << "whole";
                    else if(it.abilities->reflect[REFLECT_PERCENT] >= 75)
                        s << "huge";
                    else if(it.abilities->reflect[REFLECT_PERCENT] >= 50)
                        s << "medium";
                    else if(it.abilities->reflect[REFLECT_PERCENT] >= 25)
                        s << "small";
                    else
                        s << "tiny";

                    s << getCombatName((CombatType_t)i);
                }

                if(!tmp)
                    s << " damage";
            }
            else
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL];
                s << "reflect: " << show << "% for ";
                if(tmp)
                {
                    if(tmp > 99)
                        s << "whole";
                    else if(tmp >= 75)
                        s << "huge";
                    else if(tmp >= 50)
                        s << "medium";
                    else if(tmp >= 25)
                        s << "small";
                    else
                        s << "tiny";
                }
                else
                    s << "mixed";

                s << " damage";
            }

            if(it.abilities->speed)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
            }

            if(it.abilities->invisible)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "invisibility";
            }

            if(it.abilities->regeneration)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "faster regeneration";
            }

            if(it.abilities->manaShield)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "mana shield";
            }

            if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions))
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "hard drinking";
            }
        }

        if(it.dualWield || (item && item->isDualWield()))
        {
            if(begin)
            {
                begin = false;
                s << " (";
            }
            else
                s << ", ";

            s << "dual wielding";
        }

        if(!begin)
            s << ")";
    }
    else if(it.armor || (item && item->getArmor()) || it.showAttributes)
    {
        int32_t tmp = it.armor;
        if(item)
            tmp = item->getArmor();

        bool begin = true;
        if(tmp)
        {
            s << " (Arm:" << tmp;
            begin = false;
        }

        if(it.criticalHitChance || (item && item->getCriticalHitChance()))
        {
            if(begin)
            {
                begin = false;
                s << " (";
            }
            else
                s << ", ";
                s << "Crit Chance:" << std::showpos << int32_t(item ? item->getCriticalHitChance() : it.criticalHitChance) << "%"<< std::noshowpos;
        }

        if(it.hasAbilities())
        {
            for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
            {
                if(!it.abilities->skills)
                    continue;

                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities->skills << std::noshowpos;
            }

            if(it.abilities->stats[STAT_MAGICLEVEL])
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "magic level " << std::showpos << (int32_t)it.abilities->stats[STAT_MAGICLEVEL] << std::noshowpos;
            }

            int32_t show = it.abilities->absorb[COMBAT_ALL];
            if(!show)
            {
                bool tmp = true;
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                {
                    if(!it.abilities->absorb)
                        continue;

                    if(tmp)
                    {
                        tmp = false;
                        if(begin)
                        {
                            begin = false;
                            s << " (";
                        }
                        else
                            s << ", ";

                        s << "protection ";
                    }
                    else
                        s << ", ";

                    s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb << std::noshowpos << "%";
                }
            }
            else
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "protection all " << std::showpos << show << std::noshowpos << "%";
            }

            show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL];
            if(!show)
            {
                bool tmp = true;
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                {
                    if(!it.abilities->reflect[REFLECT_CHANCE] || !it.abilities->reflect[REFLECT_PERCENT])
                        continue;

                    if(tmp)
                    {
                        tmp = false;
                        if(begin)
                        {
                            begin = false;
                            s << " (";
                        }
                        else
                            s << ", ";

                        s << "reflect: ";
                    }
                    else
                        s << ", ";

                    s << it.abilities->reflect[REFLECT_CHANCE] << "% for ";
                    if(it.abilities->reflect[REFLECT_PERCENT] > 99)
                        s << "whole";
                    else if(it.abilities->reflect[REFLECT_PERCENT] >= 75)
                        s << "huge";
                    else if(it.abilities->reflect[REFLECT_PERCENT] >= 50)
                        s << "medium";
                    else if(it.abilities->reflect[REFLECT_PERCENT] >= 25)
                        s << "small";
                    else
                        s << "tiny";

                    s << getCombatName((CombatType_t)i);
                }

                if(!tmp)
                    s << " damage";
            }
            else
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL];
                s << "reflect: " << show << "% for ";
                if(tmp)
                {
                    if(tmp > 99)
                        s << "whole";
                    else if(tmp >= 75)
                        s << "huge";
                    else if(tmp >= 50)
                        s << "medium";
                    else if(tmp >= 25)
                        s << "small";
                    else
                        s << "tiny";
                }
                else
                    s << "mixed";

                s << " damage";
            }

            if(it.abilities->speed)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
            }

            if(it.abilities->invisible)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "invisibility";
            }

            if(it.abilities->regeneration)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "faster regeneration";
            }

            if(it.abilities->manaShield)
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "mana shield";
            }

            if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions))
            {
                if(begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";

                s << "hard drinking";
            }

            if(!begin)
                s << ")";
        }
    }
    else if(it.isContainer())
        s << " (Vol:" << (int32_t)it.maxItems << ")";
    else if(it.isKey())
        s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")";
    else if(it.isFluidContainer())
    {
        if(subType > 0)
            s << " of " << (items[subType].name.length() ? items[subType].name : "unknown");
        else
            s << ". It is empty";
    }
    else if(it.isSplash())
    {
        s << " of ";
        if(subType > 0 && items[subType].name.length())
            s << items[subType].name;
        else
            s << "unknown";
    }
    else if(it.allowDistRead)
    {
        s << "." << std::endl;
        if(item && !item->getText().empty())
        {
            if(lookDistance <= 4)
            {
                if(!item->getWriter().empty())
                {
                    s << item->getWriter() << " wrote";
                    time_t date = item->getDate();
                    if(date > 0)
                        s << " on " << formatDate(date);

                    s << ": ";
                }
                else
                    s << "You read: ";

                std::string text = item->getText();
                s << text;

                char end = *text.rbegin();
                if(end == '?' || end == '!' || end == '.')
                    dot = false;
            }
            else
                s << "You are too far away to read it";
        }
        else
            s << "Nothing is written on it";
    }
    else if(it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor && item->getActionId()
        <= ((int32_t)it.levelDoor + g_config.getNumber(ConfigManager::MAXIMUM_DOOR_LEVEL)))
        s << " for level " << item->getActionId() - it.levelDoor;

    if(it.showCharges)
        s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left";

    if(it.showDuration)
    {
        int32_t duration = item ? item->getDuration() / 1000 : 0;
        if (duration != 0)
        {
            s << " that will expire in ";
            if(duration >= 86400)
            {
                uint16_t days = duration / 86400;
                uint16_t hours = (duration % 86400) / 3600;
                s << days << " day" << (days > 1 ? "s" : "");
                if(hours > 0)
                    s << " and " << hours << " hour" << (hours > 1 ? "s" : "");
            }
            else if(duration >= 3600)
            {
                uint16_t hours = duration / 3600;
                uint16_t minutes = (duration % 3600) / 60;
                s << hours << " hour" << (hours > 1 ? "s" : "");
                if(hours > 0)
                    s << " and " << minutes << " minute" << (minutes > 1 ? "s" : "");
            }
            else if(duration >= 60)
            {
                uint16_t minutes = duration / 60;
                uint16_t seconds = duration % 60;
                s << minutes << " minute" << (minutes > 1 ? "s" : "");
                if(seconds > 0)
                    s << " and " << seconds << " second" << (seconds > 1 ? "s" : "");
            }
            else
                s << duration << " second" << (duration > 1 ? "s" : "");
        }
        else
            s << " that is brand-new";
    }

    if(dot)
        s << ".";

    if(it.wieldInfo)
    {
        s << std::endl << "It can only be wielded properly by ";
        if(it.wieldInfo & WIELDINFO_PREMIUM)
            s << "premium ";

        if(it.wieldInfo & WIELDINFO_VOCREQ)
            s << it.vocationString;
        else
            s << "players";

        if(it.wieldInfo & WIELDINFO_LEVEL)
            s << " of level " << (int32_t)it.minReqLevel << " or higher";

        if(it.wieldInfo & WIELDINFO_MAGLV)
        {
            if(it.wieldInfo & WIELDINFO_LEVEL)
                s << " and";
            else
                s << " of";

            s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher";
        }

        s << ".";
    }

    if(lookDistance <= 1 && it.pickupable)
    {
        std::string tmp;
        if(!item)
            tmp = getWeightDescription(it.weight, it.stackable && it.showCount, subType);
        else
            tmp = item->getWeightDescription();

        if(!tmp.empty())
            s << std::endl << tmp;
    }

    if(item && !item->getSpecialDescription().empty())
        s << std::endl << item->getSpecialDescription();
    else if(!it.description.empty() && lookDistance <= 1)
        s << std::endl << it.description;

    std::string str = s.str();
    if(str.find("|PLAYERNAME|") != std::string::npos)
    {
        std::string tmp = "You";
        if(item)
        {
            if(const Player* player = item->getHoldingPlayer())
                tmp = player->getName();
        }

        replaceString(str, "|PLAYERNAME|", tmp);
    }

    if(str.find("|TIME|") != std::string::npos || str.find("|DATE|") != std::string::npos || str.find(
        "|DAY|") != std::string::npos || str.find("|MONTH|") != std::string::npos || str.find(
        "|YEAR|") != std::string::npos || str.find("|HOUR|") != std::string::npos || str.find(
        "|MINUTES|") != std::string::npos || str.find("|SECONDS|") != std::string::npos ||
        str.find("|WEEKDAY|") != std::string::npos || str.find("|YEARDAY|") != std::string::npos)
    {
        time_t now = time(NULL);
        tm* ts = localtime(&now);

        std::ostringstream ss;
        ss << ts->tm_sec;
        replaceString(str, "|SECONDS|", ss.str());

        ss.str("");
        ss << ts->tm_min;
        replaceString(str, "|MINUTES|", ss.str());

        ss.str("");
        ss << ts->tm_hour;
        replaceString(str, "|HOUR|", ss.str());

        ss.str("");
        ss << ts->tm_mday;
        replaceString(str, "|DAY|", ss.str());

        ss.str("");
        ss << (ts->tm_mon + 1);
        replaceString(str, "|MONTH|", ss.str());

        ss.str("");
        ss << (ts->tm_year + 1900);
        replaceString(str, "|YEAR|", ss.str());

        ss.str("");
        ss << ts->tm_wday;
        replaceString(str, "|WEEKDAY|", ss.str());

        ss.str("");
        ss << ts->tm_yday;
        replaceString(str, "|YEARDAY|", ss.str());

        ss.str("");
        ss << ts->tm_hour << ":" << ts->tm_min << ":" << ts->tm_sec;
        replaceString(str, "|TIME|", ss.str());

        ss.str("");
        replaceString(str, "|DATE|", formatDateEx(now));
    }

    return str;
}

std::string Item::getNameDescription(const ItemType& it, const Item* item/* = NULL*/, int32_t subType/* = -1*/, bool addArticle/* = true*/)
{
    if(item)
        subType = item->getSubType();

    std::ostringstream s;
    if(it.loaded || (item && !item->getName().empty()))
    {
        if(subType > 1 && it.stackable && it.showCount)
            s << subType << " " << (item ? item->getPluralName() : it.pluralName);
        else
        {
            if(addArticle)
            {
                if(item && !item->getArticle().empty())
                    s << item->getArticle() << " ";
                else if(!it.article.empty())
                    s << it.article << " ";
            }

            s << (item ? item->getName() : it.name);
        }
    }
    else if(it.name.empty())
        s << "an item of type " << it.id << ", please report it to gamemaster";
    else
        s << "an item '" << it.name << "', please report it to gamemaster";

    return s.str();
}

std::string Item::getWeightDescription(double weight, bool stackable, uint32_t count/* = 1*/)
{
    if(weight <= 0)
        return "";

    std::ostringstream s;
    if(stackable && count > 1)
        s << "They weigh " << std::fixed << std::setprecision(2) << weight << " oz.";
    else
        s << "It weighs " << std::fixed << std::setprecision(2) << weight << " oz.";

    return s.str();
}

void Item::setActionId(int32_t aid, bool callEvent/* = true*/)
{
    Tile* tile = NULL;
    if(callEvent)
        tile = getTile();

    if(tile && getActionId())
        g_moveEvents->onRemoveTileItem(tile, this);

    setAttribute("aid", aid);
    if(tile)
        g_moveEvents->onAddTileItem(tile, this);
}

void Item::resetActionId(bool callEvent/* = true*/)
{
    if(!getActionId())
        return;

    Tile* tile = NULL;
    if(callEvent)
        tile = getTile();

    eraseAttribute("aid");
    if(tile)
        g_moveEvents->onAddTileItem(tile, this);
}

void Item::setUniqueId(int32_t uid)
{
    if(getUniqueId())
        return;

    setAttribute("uid", uid);
    ScriptEnviroment::addUniqueThing(this);
}

bool Item::canDecay()
{
    if (isRemoved()) {
        return false;
    }

    const ItemType& it = Item::items[id];
    if (it.decayTo < 0 || it.decayTime == 0) {
        return false;
    }

    if (itemUid != -1) {
        return false;
    }

    return true;
}

void Item::getLight(LightInfo& lightInfo)
{
    const ItemType& it = items[id];
    lightInfo.color = it.lightColor;
    lightInfo.level = it.lightLevel;
}

void Item::__startDecaying()
{
    g_game.startDecay(this);
}

void Item::generateSerial()
{
    std::string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    std::string serial = "";
    for(int32_t i = 1; i < 6; i++)
    {
        int32_t l = rand() % (letters.length() - 1) + 1;
        serial += letters.substr(l, 1);
    }
    serial += "-";
    for(int32_t i = 1; i < 6; i++)
    {
        int32_t l = rand() % (letters.length() - 1) + 1;
        serial += letters.substr(l, 1);
    }
    serial += "-";
    for(int32_t i = 1; i < 6; i++)
    {
        int32_t l = rand() % (letters.length() - 1) + 1;
        serial += letters.substr(l, 1);
    }
    serial += "-";
    for(int32_t i = 1; i < 6; i++)
    {
        int32_t l = rand() % (letters.length() - 1) + 1;
        serial += letters.substr(l, 1);
    }

    std::string key = "serial";
    this->setAttribute(key.c_str(), serial);
    serial = "";
}
 

items.cpp:

Citar

#include "otpch.h"
#include <iostream>
#include <libxml/xmlmemory.h>

#include "items.h"
#include "condition.h"
#include "configmanager.h"

#include "movement.h"
#include "weapons.h"
#include "spells.h"


extern Spells* g_spells;
extern ConfigManager g_config;
extern MoveEvents* g_moveEvents;
extern Weapons* g_weapons;

uint32_t Items::dwMajorVersion = 0;
uint32_t Items::dwMinorVersion = 0;
uint32_t Items::dwBuildNumber = 0;

ItemType::ItemType()
{
    abilities = NULL;
    group = ITEM_GROUP_NONE;
    type = ITEM_TYPE_NONE;
    stackable = usable = alwaysOnTop = lookThrough = pickupable = rotable = hasHeight = forceSerialize = false;
    loaded = blockSolid = blockProjectile = blockPathFind = allowPickupable = isAnimation = cache = false;
    movable = walkStack = true;
    alwaysOnTopOrder = 0;
    rotateTo = 0;

    wieldInfo = 0;
    minReqLevel = 0;
    minReqMagicLevel = 0;

    runeMagLevel = runeLevel = 0;

    speed = id = 0;
    clientId = 100;
    maxItems = 8; //maximum size if this is a container
    weight = 0; //weight of the item, e.g. throwing distance depends on it
    showCount = true;
    weaponType = WEAPON_NONE;
    slotPosition = SLOTP_HAND;
    wieldPosition = SLOT_HAND;
    ammoType = AMMO_NONE;
    ammoAction = AMMOACTION_NONE;
    shootType = (ShootEffect_t)0;
    magicEffect = MAGIC_EFFECT_NONE;
    attack = extraAttack = 0;
    defense = extraDefense = 0;
    attackSpeed = 0;
    criticalHitChance = 0;
    armor = 0;
    decayTo = -1;
    decayTime = 0;
    stopTime = false;
    corpseType = RACE_NONE;
    armorRndMin = armorRndMax = defenseRndMin = defenseRndMax = extraDefenseRndMin = extraDefenseRndMax = 0;
    attackRndMin = attackRndMax = extraAttackRndMin = extraAttackRndMax = 0;
    attackSpeedRndMin = attackSpeedRndMax = attackSpeedChance = extraAttackChance = extraDefenseChance = 0;
    fluidSource = FLUID_NONE;
    allowDistRead = false;

    isVertical = isHorizontal = isHangable = false;
    lightLevel = lightColor = 0;

    maxTextLength = 0;
    canReadText = canWriteText = false;
    date = 0;
    writeOnceItemId = wareId = premiumDays = 0;

    transformEquipTo = transformDeEquipTo = transformUseTo = 0;
    showDuration = showCharges = showAttributes = dualWield = false;
    charges    = 0;
    hitChance = maxHitChance = breakChance = -1;
    shootRange = 1;

    condition = NULL;
    combatType = COMBAT_NONE;

    replacable = true;
    worth = 0;

    bedPartnerDir = NORTH;
    transformBed[PLAYERSEX_FEMALE] = transformBed[PLAYERSEX_MALE] = 0;

    levelDoor = 0;
    specialDoor = closingDoor = false;

    memset(floorChange, 0, sizeof(floorChange));
}

ItemType::~ItemType()
{
    delete condition;
}

void Items::clear()
{
    moneyMap.clear();
    randomizationMap.clear();

    reverseItemMap.clear();
    if(items.size())
        items.clear();
}

bool Items::reload()
{
    clear();
    if(!items.size())
        return false;

    items.reload();
    loadFromOtb(getFilePath(FILE_TYPE_OTHER, "items/items.otb"));
    if(!loadFromXml())
        return false;

    g_moveEvents->reload();
    g_weapons->reload();
    return true;
}

int32_t Items::loadFromOtb(std::string file)
{
    FileLoader f;
    if(!f.openFile(file.c_str(), "OTBI", false, true))
        return f.getError();

    uint32_t type;
    NODE node = f.getChildNode(NO_NODE, type);

    PropStream props;
    if(f.getProps(node, props))
    {
        //4 byte flags
        //attributes
        //0x01 = version data
        uint32_t flags;
        if(!props.getLong(flags))
            return ERROR_INVALID_FORMAT;

        attribute_t attr;
        if(!props.getType(attr))
            return ERROR_INVALID_FORMAT;

        if(attr == ROOT_ATTR_VERSION)
        {
            datasize_t length = 0;
            if(!props.getType(length))
                return ERROR_INVALID_FORMAT;

            if(length != sizeof(VERSIONINFO))
                return ERROR_INVALID_FORMAT;

            VERSIONINFO *vi;
            if(!props.getStruct(vi))
                return ERROR_INVALID_FORMAT;

            Items::dwMajorVersion = vi->dwMajorVersion; //items otb format file version
            Items::dwMinorVersion = vi->dwMinorVersion; //client version
            Items::dwBuildNumber = vi->dwBuildNumber; //revision
        }
    }

    if(Items::dwMajorVersion == 0xFFFFFFFF)
        std::clog << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl;
    else if(Items::dwMajorVersion != 3)
    {
        std::clog << "[Error - Items::loadFromOtb] Incorrect version detected, please use official items.otb." << std::endl;
        return ERROR_INVALID_FORMAT;
    }
    else if(!g_config.getBool(ConfigManager::SKIP_ITEMS_VERSION) && Items::dwMinorVersion != CLIENT_VERSION_ITEMS)
    {
        std::clog << "[Error - Items::loadFromOtb] Another client version of items.otb is required." << std::endl;
        return ERROR_INVALID_FORMAT;
    }

    uint16_t lastId = 99;
    for(node = f.getChildNode(node, type); node != NO_NODE; node = f.getNextNode(node, type))
    {
        PropStream props;
        if(!f.getProps(node, props))
            return f.getError();

        ItemType* iType = new ItemType();
        iType->group = (itemgroup_t)type;

        flags_t flags;
        switch(type)
        {
            case ITEM_GROUP_CONTAINER:
                iType->type = ITEM_TYPE_CONTAINER;
                break;
            case ITEM_GROUP_DOOR:
                //not used
                iType->type = ITEM_TYPE_DOOR;
                break;
            case ITEM_GROUP_MAGICFIELD:
                //not used
                iType->type = ITEM_TYPE_MAGICFIELD;
                break;
            case ITEM_GROUP_TELEPORT:
                //not used
                iType->type = ITEM_TYPE_TELEPORT;
                break;
            case ITEM_GROUP_NONE:
            case ITEM_GROUP_GROUND:
            case ITEM_GROUP_SPLASH:
            case ITEM_GROUP_FLUID:
            case ITEM_GROUP_CHARGES:
            case ITEM_GROUP_DEPRECATED:
                break;
            default:
                return ERROR_INVALID_FORMAT;
        }

        //read 4 byte flags
        if(!props.getType(flags))
            return ERROR_INVALID_FORMAT;

        iType->blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags);
        iType->blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags);
        iType->blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags);
        iType->hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags);
        iType->usable = hasBitSet(FLAG_USABLE, flags);
        iType->pickupable = hasBitSet(FLAG_PICKUPABLE, flags);
        iType->movable = hasBitSet(FLAG_MOVABLE, flags);
        iType->stackable = hasBitSet(FLAG_STACKABLE, flags);

        iType->alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags);
        iType->isVertical = hasBitSet(FLAG_VERTICAL, flags);
        iType->isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags);
        iType->isHangable = hasBitSet(FLAG_HANGABLE, flags);
        iType->allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags);
        iType->rotable = hasBitSet(FLAG_ROTABLE, flags);
        iType->canReadText = hasBitSet(FLAG_READABLE, flags);
        iType->lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags);
        iType->isAnimation = hasBitSet(FLAG_ANIMATION, flags);
        iType->walkStack = !hasBitSet(FLAG_WALKSTACK, flags);

        attribute_t attr;
        while(props.getType(attr))
        {
            //size of data
            datasize_t length = 0;
            if(!props.getType(length))
            {
                delete iType;
                return ERROR_INVALID_FORMAT;
            }

            switch(attr)
            {
                case ITEM_ATTR_SERVERID:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t serverId;
                    if(!props.getShort(serverId))
                        return ERROR_INVALID_FORMAT;

                    if(serverId > 20000 && serverId < 20100)
                        serverId = serverId - 20000;
                    else if(lastId > 99 && lastId != serverId - 1)
                    {
                        static ItemType dummyItemType;
                        while(lastId != serverId - 1)
                        {
                            dummyItemType.id = ++lastId;
                            items.addElement(&dummyItemType, lastId);
                        }
                    }

                    iType->id = serverId;
                    lastId = serverId;
                    break;
                }
                case ITEM_ATTR_CLIENTID:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t clientId;
                    if(!props.getShort(clientId))
                        return ERROR_INVALID_FORMAT;

                    iType->clientId = clientId;
                    break;
                }
                case ITEM_ATTR_SPEED:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t speed;
                    if(!props.getShort(speed))
                        return ERROR_INVALID_FORMAT;

                    iType->speed = speed;
                    break;
                }
                case ITEM_ATTR_LIGHT2:
                {
                    if(length != sizeof(lightBlock2))
                        return ERROR_INVALID_FORMAT;

                    lightBlock2* block;
                    if(!props.getStruct(block))
                        return ERROR_INVALID_FORMAT;

                    iType->lightLevel = block->lightLevel;
                    iType->lightColor = block->lightColor;
                    break;
                }
                case ITEM_ATTR_TOPORDER:
                {
                    if(length != sizeof(uint8_t))
                        return ERROR_INVALID_FORMAT;

                    uint8_t topOrder;
                    if(!props.getByte(topOrder))
                        return ERROR_INVALID_FORMAT;

                    iType->alwaysOnTopOrder = topOrder;
                    break;
                }
                case ITEM_ATTR_WAREID:
                {
                    if(length != sizeof(uint16_t))
                        return ERROR_INVALID_FORMAT;

                    uint16_t wareId;
                    if(!props.getShort(wareId))
                        return ERROR_INVALID_FORMAT;

                    iType->wareId = wareId;
                    break;
                }
                case ITEM_ATTR_NAME:
                {
                    std::string name;
                    if(!props.getString(name, length))
                        return ERROR_INVALID_FORMAT;

                    iType->name = name;
                    break;
                }
                default:
                {
                    //skip unknown attributes
                    if(!props.skip(length))
                        return ERROR_INVALID_FORMAT;

                    break;
                }
            }
        }

        // store the found item
        items.addElement(iType, iType->id);
        if (iType->clientId) {
            if (reverseItemMap.find(iType->clientId) == reverseItemMap.end())
                reverseItemMap[iType->clientId] = iType->id;
        }
    }

    return ERROR_NONE;
}

bool Items::loadFromXml()
{
    xmlDocPtr doc = xmlParseFile(getFilePath(FILE_TYPE_OTHER, "items/items.xml").c_str());
    if(!doc)
    {
        std::clog << "[Warning - Items::loadFromXml] Cannot load items file."
            << std::endl << getLastXMLError() << std::endl;
        return false;
    }

    xmlNodePtr root = xmlDocGetRootElement(doc);
    if(xmlStrcmp(root->name,(const xmlChar*)"items"))
    {
        xmlFreeDoc(doc);
        std::clog << "[Warning - Items::loadFromXml] Malformed items file." << std::endl;
        return false;
    }

    IntegerVec intVector, endVector;
    std::string strValue, endValue;
    StringVec strVector;

    int32_t intValue, id = 0, endId = 0, fromId = 0, toId = 0;
    for(xmlNodePtr node = root->children; node; node = node->next)
    {
        if(xmlStrcmp(node->name,(const xmlChar*)"item"))
            continue;

        if(readXMLString(node, "id", strValue))
        {
            strVector = explodeString(strValue, ";");
            for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it)
            {
                intVector = vectorAtoi(explodeString(*it, "-"));
                if(intVector.size() > 1)
                {
                    int32_t i = intVector[0];
                    while(i <= intVector[1])
                        parseItemNode(node, i++);
                }
                else
                    parseItemNode(node, atoi((*it).c_str()));
            }
        }
        else if(readXMLString(node, "fromid", strValue) && readXMLString(node, "toid", endValue))
        {
            intVector = vectorAtoi(explodeString(strValue, ";"));
            endVector = vectorAtoi(explodeString(endValue, ";"));
            if(intVector[0] && intVector.size() == endVector.size())
            {
                size_t size = intVector.size();
                for(size_t i = 0; i < size; ++i)
                {
                    while(intVector <= endVector)
                        parseItemNode(node, intVector++);
                }
            }
            else
                std::clog << "[Warning - Items::loadFromXml] Malformed entry (from: \"" << strValue << "\", to: \"" << endValue << "\")" << std::endl;
        }
        else
            std::clog << "[Warning - Items::loadFromXml] No itemid found at line " << node->line << std::endl;
    }

    const ItemType* it;
    for(uint32_t i = 0; i < Item::items.size(); ++i) //lets do some checks...
    {
        if(!(it = Item::items.getElement(i)))
            continue;

        //check bed items
        if((it->transformBed[PLAYERSEX_FEMALE] || it->transformBed[PLAYERSEX_MALE]) && it->type != ITEM_TYPE_BED)
            std::clog << "[Warning - Items::loadFromXml] Item " << it->id << " is not set as a bed-type." << std::endl;
    }

    xmlFreeDoc(doc);
    if(!(doc = xmlParseFile(getFilePath(FILE_TYPE_OTHER, "items/randomization.xml").c_str())))
    {
        std::clog << "[Warning - Items::loadFromXml] Cannot load randomization file."
            << std::endl << getLastXMLError() << std::endl;
        return false;
    }

    root = xmlDocGetRootElement(doc);
    if(xmlStrcmp(root->name,(const xmlChar*)"randomization"))
    {
        xmlFreeDoc(doc);
        std::clog << "[Warning - Items::loadFromXml] Malformed randomization file." << std::endl;
        return false;
    }

    for(xmlNodePtr node = root->children; node; node = node->next)
    {
        if(!xmlStrcmp(node->name, (const xmlChar*)"config"))
        {
            if(readXMLInteger(node, "chance", intValue) || readXMLInteger(node, "defaultChance", intValue))
            {
                if(intValue > 100)
                {
                    intValue = 100;
                    std::clog << "[Warning - Items::loadFromXml] Randomize chance cannot be higher than 100." << std::endl;
                }

                m_randomizationChance = intValue;
            }
        }
        else if(!xmlStrcmp(node->name, (const xmlChar*)"palette"))
        {
            if(!readXMLString(node, "randomize", strValue))
                continue;

            IntegerVec itemList = vectorAtoi(explodeString(strValue, ";"));
            if(itemList.size() < 2)
                itemList = vectorAtoi(explodeString(strValue, "-"));

            if(itemList.size() > 1)
            {
                if(itemList[0] < itemList[1])
                {
                    fromId = itemList[0];
                    toId = itemList[1];
                }
                else
                    std::clog << "[Warning - Items::loadFromXml] Randomize min cannot be higher than max." << std::endl;
            }

            int32_t chance = getRandomizationChance();
            if(readXMLInteger(node, "chance", intValue))
            {
                if(intValue > 100)
                {
                    intValue = 100;
                    std::clog << "[Warning: Items::loadRandomization] Randomize chance cannot be higher than 100." << std::endl;
                }

                chance = intValue;
            }

            if(readXMLInteger(node, "itemid", id))
                parseRandomizationBlock(id, fromId, toId, chance);
            else if(readXMLInteger(node, "fromid", id) && readXMLInteger(node, "toid", endId))
            {
                while(id <= endId)
                    parseRandomizationBlock(id++, fromId, toId, chance);
            }
        }
    }

    xmlFreeDoc(doc);
    return true;
}

void Items::parseItemNode(xmlNodePtr itemNode, uint32_t id)
{
    int32_t intValue;
    std::string strValue;
    if(id > 20000 && id < 20100)
    {
        id -= 20000;
        ItemType* iType = new ItemType();

        iType->id = id;
        items.addElement(iType, iType->id);
    }

    bool override = readXMLString(itemNode, "override", strValue) && booleanString(strValue);
    ItemType& it = Item::items.getItemType(id);
    if(it.loaded)
    {
        if(override)
        {
            // setup some defaults
            if(it.hasAbilities())
            {
                memset(it.getAbilities()->fieldAbsorb, 0, sizeof(it.getAbilities()->fieldAbsorb));
                memset(it.getAbilities()->absorb, 0, sizeof(it.getAbilities()->absorb));
                for(uint32_t j = REFLECT_FIRST; j <= REFLECT_LAST; ++j)
                    memset(it.getAbilities()->reflect[j], 0, sizeof(it.getAbilities()->reflect[j]));
            }
        }
        else
            std::clog << "[Warning - Items::loadFromXml] Duplicate registered item with id " << id << std::endl;
    }
    else
        it.loaded = true;

    if(readXMLString(itemNode, "name", strValue))
        it.name = strValue;

    if(readXMLString(itemNode, "article", strValue))
        it.article = strValue;

    if(readXMLString(itemNode, "plural", strValue))
        it.pluralName = strValue;

    for(xmlNodePtr itemAttributesNode = itemNode->children; itemAttributesNode; itemAttributesNode = itemAttributesNode->next)
    {
        if(!readXMLString(itemAttributesNode, "key", strValue))
            continue;

#ifdef _MSC_VER
        bool notLoaded = false;
#endif
        std::string tmpStrValue = asLowerCaseString(strValue);
        if(tmpStrValue == "type")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "container")
                {
                    it.type = ITEM_TYPE_CONTAINER;
                    it.group = ITEM_GROUP_CONTAINER;
                }
                else if(tmpStrValue == "key")
                    it.type = ITEM_TYPE_KEY;
                else if(tmpStrValue == "magicfield")
                    it.type = ITEM_TYPE_MAGICFIELD;
                else if(tmpStrValue == "depot")
                    it.type = ITEM_TYPE_DEPOT;
                else if(tmpStrValue == "mailbox")
                    it.type = ITEM_TYPE_MAILBOX;
                else if(tmpStrValue == "trashholder")
                    it.type = ITEM_TYPE_TRASHHOLDER;
                else if(tmpStrValue == "teleport")
                    it.type = ITEM_TYPE_TELEPORT;
                else if(tmpStrValue == "door")
                    it.type = ITEM_TYPE_DOOR;
                else if(tmpStrValue == "bed")
                    it.type = ITEM_TYPE_BED;
                else if(tmpStrValue == "rune")
                    it.type = ITEM_TYPE_RUNE;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown type " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "name")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.name = strValue;
        }
        else if(tmpStrValue == "article")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.article = strValue;
        }
        else if(tmpStrValue == "plural")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.pluralName = strValue;
        }
        else if(tmpStrValue == "clientid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.clientId = intValue;
                if(it.group == ITEM_GROUP_DEPRECATED)
                    it.group = ITEM_GROUP_NONE;
            }
        }
        else if(tmpStrValue == "cache")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.cache = (intValue != 0);
        }
        else if(tmpStrValue == "wareid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.wareId = intValue;
        }
        else if(tmpStrValue == "blocksolid" || tmpStrValue == "blocking")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.blockSolid = (intValue != 0);
        }
        else if(tmpStrValue == "blockprojectile")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.blockProjectile = (intValue != 0);
        }
        else if(tmpStrValue == "blockpathfind" || tmpStrValue == "blockpathing" || tmpStrValue == "blockpath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.blockPathFind = (intValue != 0);
        }
        else if(tmpStrValue == "lightlevel")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.lightLevel = intValue;
        }
        else if(tmpStrValue == "lightcolor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.lightColor = intValue;
        }
        else if(tmpStrValue == "description")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.description = strValue;
        }
        else if(tmpStrValue == "runespellname")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.runeSpellName = strValue;
        }
        else if(tmpStrValue == "weight")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.weight = intValue / 100.f;
        }
        else if(tmpStrValue == "showcount")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showCount = (intValue != 0);
        }
        else if(tmpStrValue == "armor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.armor = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.armorRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.armorRndMax = intValue;
        }
        else if(tmpStrValue == "defense")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.defense = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.defenseRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.defenseRndMax = intValue;
        }
        else if(tmpStrValue == "extradefense" || tmpStrValue == "extradef")
        {
            if(readXMLInteger(itemAttributesNode, "chance", intValue))
                it.extraDefenseChance = intValue;
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.extraDefense = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.extraDefenseRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.extraDefenseRndMax = intValue;
        }
        else if(tmpStrValue == "criticalhitchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.criticalHitChance = intValue;
        }
        else if(tmpStrValue == "attack")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.attack = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.attackRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.attackRndMax = intValue;
        }
        else if(tmpStrValue == "extraattack" || tmpStrValue == "extraatk")
        {
            if(readXMLInteger(itemAttributesNode, "chance", intValue))
                it.extraAttackChance = intValue;
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.extraAttack = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.extraAttackRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.extraAttackRndMax = intValue;
        }
        else if(tmpStrValue == "attackspeed")
        {
            if(readXMLInteger(itemAttributesNode, "chance", intValue))
                it.attackSpeedChance = intValue;
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.attackSpeed = intValue;
            if(readXMLInteger(itemAttributesNode, "random_min", intValue))
                it.attackSpeedRndMin = intValue;
            if(readXMLInteger(itemAttributesNode, "random_max", intValue))
                it.attackSpeedRndMax = intValue;
        }
        else if(tmpStrValue == "rotateto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.rotateTo = intValue;
        }
        else if(tmpStrValue == "movable" || tmpStrValue == "moveable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.movable = (intValue != 0);
        }
        else if(tmpStrValue == "vertical" || tmpStrValue == "isvertical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.isVertical = (intValue != 0);
        }
        else if(tmpStrValue == "horizontal" || tmpStrValue == "ishorizontal")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.isHorizontal = (intValue != 0);
        }
        else if(tmpStrValue == "pickupable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.pickupable = (intValue != 0);
        }
        else if(tmpStrValue == "allowpickupable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.allowPickupable = (intValue != 0);
        }
        else if(tmpStrValue == "floorchange")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "down")
                    it.floorChange[CHANGE_DOWN] = true;
                else if(tmpStrValue == "north")
                    it.floorChange[CHANGE_NORTH] = true;
                else if(tmpStrValue == "south")
                    it.floorChange[CHANGE_SOUTH] = true;
                else if(tmpStrValue == "west")
                    it.floorChange[CHANGE_WEST] = true;
                else if(tmpStrValue == "east")
                    it.floorChange[CHANGE_EAST] = true;
                else if(tmpStrValue == "northex")
                    it.floorChange[CHANGE_NORTH_EX] = true;
                else if(tmpStrValue == "southex")
                    it.floorChange[CHANGE_SOUTH_EX] = true;
                else if(tmpStrValue == "westex")
                    it.floorChange[CHANGE_WEST_EX] = true;
                else if(tmpStrValue == "eastex")
                    it.floorChange[CHANGE_EAST_EX] = true;
            }
        }
        else if(tmpStrValue == "corpsetype")
        {
            tmpStrValue = asLowerCaseString(strValue);
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "venom")
                    it.corpseType = RACE_VENOM;
                else if(tmpStrValue == "blood")
                    it.corpseType = RACE_BLOOD;
                else if(tmpStrValue == "undead")
                    it.corpseType = RACE_UNDEAD;
                else if(tmpStrValue == "fire")
                    it.corpseType = RACE_FIRE;
                else if(tmpStrValue == "energy")
                    it.corpseType = RACE_ENERGY;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown corpseType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "containersize")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.maxItems = intValue;
                if(it.group == ITEM_GROUP_NONE)
                {
                    it.group = ITEM_GROUP_CONTAINER;
                    it.type = ITEM_TYPE_CONTAINER;
                }
            }
        }
        else if(tmpStrValue == "fluidsource")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                FluidTypes_t fluid = getFluidType(tmpStrValue);
                if(fluid != FLUID_NONE)
                    it.fluidSource = fluid;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown fluidSource " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "writeable" || tmpStrValue == "writable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.canWriteText = (intValue != 0);
                it.canReadText = (intValue != 0);
            }
        }
        else if(tmpStrValue == "readable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.canReadText = (intValue != 0);
        }
        else if(tmpStrValue == "maxtextlen" || tmpStrValue == "maxtextlength")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.maxTextLength = intValue;
        }
        else if(tmpStrValue == "text")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.text = strValue;
        }
        else if(tmpStrValue == "author" || tmpStrValue == "writer")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.writer = strValue;
        }
        else if(tmpStrValue == "date")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.date = intValue;
        }
        else if(tmpStrValue == "writeonceitemid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.writeOnceItemId = intValue;
        }
        else if(tmpStrValue == "wareid")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.wareId = intValue;
        }
        else if(tmpStrValue == "worth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                if(moneyMap.find(intValue) != moneyMap.end() && !override)
                    std::clog << "[Warning - Items::loadFromXml] Duplicated money item " << id << " with worth " << intValue << "!" << std::endl;
                else
                {
                    moneyMap[intValue] = id;
                    it.worth = intValue;
                }
            }
        }
        else if(tmpStrValue == "forceserialize" || tmpStrValue == "forceserialization" || tmpStrValue == "forcesave")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.forceSerialize = (intValue != 0);
        }
        else if(tmpStrValue == "leveldoor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.levelDoor = intValue;
        }
        else if(tmpStrValue == "specialdoor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.specialDoor = (intValue != 0);
        }
        else if(tmpStrValue == "closingdoor")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.closingDoor = (intValue != 0);
        }
        else if(tmpStrValue == "weapontype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "sword")
                    it.weaponType = WEAPON_SWORD;
                else if(tmpStrValue == "club")
                    it.weaponType = WEAPON_CLUB;
                else if(tmpStrValue == "axe")
                    it.weaponType = WEAPON_AXE;
                else if(tmpStrValue == "shield")
                    it.weaponType = WEAPON_SHIELD;
                else if(tmpStrValue == "distance" || tmpStrValue == "dist")
                    it.weaponType = WEAPON_DIST;
                else if(tmpStrValue == "wand" || tmpStrValue == "rod")
                    it.weaponType = WEAPON_WAND;
                else if(tmpStrValue == "ammunition" || tmpStrValue == "ammo")
                    it.weaponType = WEAPON_AMMO;
                else if(tmpStrValue == "fist")
                    it.weaponType = WEAPON_FIST;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown weaponType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "slottype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "head")
                {
                    it.slotPosition |= SLOTP_HEAD;
                    it.wieldPosition = SLOT_HEAD;
                }
                else if(tmpStrValue == "body")
                {
                    it.slotPosition |= SLOTP_ARMOR;
                    it.wieldPosition = SLOT_ARMOR;
                }
                else if(tmpStrValue == "legs")
                {
                    it.slotPosition |= SLOTP_LEGS;
                    it.wieldPosition = SLOT_LEGS;
                }
                else if(tmpStrValue == "feet")
                {
                    it.slotPosition |= SLOTP_FEET;
                    it.wieldPosition = SLOT_FEET;
                }
                else if(tmpStrValue == "backpack")
                {
                    it.slotPosition |= SLOTP_BACKPACK;
                    it.wieldPosition = SLOT_BACKPACK;
                }
                else if(tmpStrValue == "two-handed")
                {
                    it.slotPosition |= SLOTP_TWO_HAND;
                    it.wieldPosition = SLOT_TWO_HAND;
                }
                else if(tmpStrValue == "right-hand")
                {
                    it.slotPosition &= ~SLOTP_LEFT;
                    it.wieldPosition = SLOT_RIGHT;
                }
                else if(tmpStrValue == "left-hand")
                {
                    it.slotPosition &= ~SLOTP_RIGHT;
                    it.wieldPosition = SLOT_LEFT;
                }
                else if(tmpStrValue == "necklace")
                {
                    it.slotPosition |= SLOTP_NECKLACE;
                    it.wieldPosition = SLOT_NECKLACE;
                }
                else if(tmpStrValue == "ring")
                {
                    it.slotPosition |= SLOTP_RING;
                    it.wieldPosition = SLOT_RING;
                }
                else if(tmpStrValue == "ammo")
                {
                    it.slotPosition |= SLOTP_AMMO;
                    it.wieldPosition = SLOT_AMMO;
                }
                else if(tmpStrValue == "hand")
                    it.wieldPosition = SLOT_HAND;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown slotType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "ammotype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                it.ammoType = getAmmoType(strValue);
                if(it.ammoType == AMMO_NONE)
                    std::clog << "[Warning - Items::loadFromXml] Unknown ammoType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "shoottype")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                ShootEffect_t shoot = getShootType(strValue);
                if(shoot != SHOOT_EFFECT_UNKNOWN)
                    it.shootType = shoot;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown shootType " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "effect")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                MagicEffect_t effect = getMagicEffect(strValue);
                if(effect != MAGIC_EFFECT_UNKNOWN)
                    it.magicEffect = effect;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown effect " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "range")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.shootRange = intValue;
        }
        else if(tmpStrValue == "stopduration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.stopTime = (intValue != 0);
        }
        else if(tmpStrValue == "decayto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.decayTo = intValue;
        }
        else if(tmpStrValue == "transformequipto" || tmpStrValue == "onequipto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.transformEquipTo = intValue;
        }
        else if(tmpStrValue == "transformdeequipto" || tmpStrValue == "ondeequipto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.transformDeEquipTo = intValue;
        }
        else if(tmpStrValue == "duration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.decayTime = std::max((int32_t)0, intValue);
        }
        else if(tmpStrValue == "showduration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showDuration = (intValue != 0);
        }
        else if(tmpStrValue == "charges")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.charges = intValue;
        }
        else if(tmpStrValue == "showcharges")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showCharges = (intValue != 0);
        }
        else if(tmpStrValue == "showattributes")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.showAttributes = (intValue != 0);
        }
        else if(tmpStrValue == "breakchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.breakChance = std::max(0, std::min(100, intValue));
        }
        else if(tmpStrValue == "ammoaction")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                AmmoAction_t ammo = getAmmoAction(strValue);
                if(ammo != AMMOACTION_NONE)
                    it.ammoAction = ammo;
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown ammoAction " << strValue << std::endl;
            }
        }
        else if(tmpStrValue == "hitchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.hitChance = std::max(-100, std::min(100, intValue));
        }
        else if(tmpStrValue == "maxhitchance")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.maxHitChance = std::max(0, std::min(100, intValue));
        }
        else if(tmpStrValue == "dualwield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.dualWield = (intValue != 0);
        }
        else if(tmpStrValue == "preventloss")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->preventLoss = (intValue != 0);
        }
        else if(tmpStrValue == "preventdrop")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->preventDrop = (intValue != 0);
        }
        else if(tmpStrValue == "invisible")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->invisible = (intValue != 0);
        }
        else if(tmpStrValue == "speed")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->speed = intValue;
        }
        else if(tmpStrValue == "healthgain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->healthGain = intValue;
            }
        }
        else if(tmpStrValue == "healthticks")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->healthTicks = intValue;
            }
        }
        else if(tmpStrValue == "managain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->manaGain = intValue;
            }
        }
        else if(tmpStrValue == "manaticks")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->regeneration = true;
                it.getAbilities()->manaTicks = intValue;
            }
        }
        else if(tmpStrValue == "manashield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->manaShield = (intValue != 0);
        }
        else if(tmpStrValue == "skillsword")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_SWORD] = intValue;
        }
        else if(tmpStrValue == "skillaxe")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_AXE] = intValue;
        }
        else if(tmpStrValue == "skillclub")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_CLUB] = intValue;
        }
        else if(tmpStrValue == "skilldist")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_DIST] = intValue;
        }
        else if(tmpStrValue == "skillfish")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_FISH] = intValue;
        }
        else if(tmpStrValue == "skillshield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_SHIELD] = intValue;
        }
        else if(tmpStrValue == "skillfist")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->skills[SKILL_FIST] = intValue;
        }
        else if(tmpStrValue == "maxhealthpoints" || tmpStrValue == "maxhitpoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_MAXHEALTH] = intValue;
        }
        else if(tmpStrValue == "maxhealthpercent" || tmpStrValue == "maxhitpointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_MAXHEALTH] = intValue;
        }
        else if(tmpStrValue == "maxmanapoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_MAXMANA] = intValue;
        }
        else if(tmpStrValue == "maxmanapercent" || tmpStrValue == "maxmanapointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_MAXMANA] = intValue;
        }
        else if(tmpStrValue == "soulpoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_SOUL] = intValue;
        }
        else if(tmpStrValue == "soulpercent" || tmpStrValue == "soulpointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_SOUL] = intValue;
        }
        else if(tmpStrValue == "magiclevelpoints" || tmpStrValue == "magicpoints")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->stats[STAT_MAGICLEVEL] = intValue;
        }
        else if(tmpStrValue == "magiclevelpercent" || tmpStrValue == "magicpointspercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->statsPercent[STAT_MAGICLEVEL] = intValue;
        }
        else if(tmpStrValue == "increasemagicvalue")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[MAGIC_VALUE] = intValue;
        }
        else if(tmpStrValue == "increasemagicpercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[MAGIC_PERCENT] = intValue;
        }
        else if(tmpStrValue == "increasehealingvalue")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[HEALING_VALUE] = intValue;
        }
        else if(tmpStrValue == "increasehealingpercent")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->increment[HEALING_PERCENT] = intValue;
        }
        else if(tmpStrValue == "fieldabsorbpercentenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->fieldAbsorb[COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "fieldabsorbpercentfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->fieldAbsorb[COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "fieldabsorbpercentpoison" || tmpStrValue == "fieldabsorbpercentearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->fieldAbsorb[COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentall")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                    it.getAbilities()->absorb += intValue;
            }
        }
        else if(tmpStrValue == "absorbpercentelements")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->absorb[COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_ICEDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "absorbpercentmagic")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->absorb[COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_ICEDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_HOLYDAMAGE] += intValue;
                it.getAbilities()->absorb[COMBAT_DEATHDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "absorbpercentenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentpoison" || tmpStrValue == "absorbpercentearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_ICEDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_HOLYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_DEATHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentlifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_LIFEDRAIN] += intValue;
        }
        else if(tmpStrValue == "absorbpercentmanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_MANADRAIN] += intValue;
        }
        else if(tmpStrValue == "absorbpercentdrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_DROWNDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercentphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_PHYSICALDAMAGE] += intValue;
        }
        else if(tmpStrValue == "absorbpercenthealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_HEALING] += intValue;
        }
        else if(tmpStrValue == "absorbpercentundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->absorb[COMBAT_UNDEFINEDDAMAGE] += intValue;
        }
#ifndef _MSC_VER
        else if(tmpStrValue == "reflectpercentall")
#else
        else
            notLoaded = true;

        if(!notLoaded)
            continue;

        if(tmpStrValue == "reflectpercentall")
#endif
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                    it.getAbilities()->reflect[REFLECT_PERCENT] += intValue;
            }
        }
        else if(tmpStrValue == "reflectpercentelements")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ICEDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectpercentmagic")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ICEDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_HOLYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_DEATHDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectpercentenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentpoison" || tmpStrValue == "reflectpercentearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ICEDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_HOLYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_DEATHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentlifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_LIFEDRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectpercentmanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_MANADRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectpercentdrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_DROWNDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercentphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_PHYSICALDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectpercenthealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_HEALING] += intValue;
        }
        else if(tmpStrValue == "reflectpercentundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_UNDEFINEDDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchanceall")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
                    it.getAbilities()->reflect[REFLECT_CHANCE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectchanceelements")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ICEDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectchancemagic")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ENERGYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIREDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_EARTHDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ICEDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_HOLYDAMAGE] += intValue;
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_DEATHDAMAGE] += intValue;
            }
        }
        else if(tmpStrValue == "reflectchanceenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ENERGYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancefire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIREDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancepoison" ||    tmpStrValue == "reflectchanceearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_EARTHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchanceice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ICEDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchanceholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_HOLYDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancedeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_DEATHDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancelifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_LIFEDRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectchancemanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_MANADRAIN] += intValue;
        }
        else if(tmpStrValue == "reflectchancedrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_DROWNDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancephysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_PHYSICALDAMAGE] += intValue;
        }
        else if(tmpStrValue == "reflectchancehealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_HEALING] += intValue;
        }
        else if(tmpStrValue == "reflectchanceundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_UNDEFINEDDAMAGE] += intValue;
        }
        else if(tmpStrValue == "suppressshock" || tmpStrValue == "suppressenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_ENERGY;
        }
        else if(tmpStrValue == "suppressburn" || tmpStrValue == "suppressfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_FIRE;
        }
        else if(tmpStrValue == "suppresspoison" || tmpStrValue == "suppressearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_POISON;
        }
        else if(tmpStrValue == "suppressfreeze" || tmpStrValue == "suppressice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_FREEZING;
        }
        else if(tmpStrValue == "suppressdazzle" || tmpStrValue == "suppressholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_DAZZLED;
        }
        else if(tmpStrValue == "suppresscurse" || tmpStrValue == "suppressdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_CURSED;
        }
        else if(tmpStrValue == "suppressdrown")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_DROWN;
        }
        else if(tmpStrValue == "suppressphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_BLEEDING;
        }
        else if(tmpStrValue == "suppresshaste")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_HASTE;
        }
        else if(tmpStrValue == "suppressparalyze")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_PARALYZE;
        }
        else if(tmpStrValue == "suppressdrunk")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_DRUNK;
        }
        else if(tmpStrValue == "suppressregeneration")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_REGENERATION;
        }
        else if(tmpStrValue == "suppresssoul")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_SOUL;
        }
        else if(tmpStrValue == "suppressoutfit")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_OUTFIT;
        }
        else if(tmpStrValue == "suppressinvisible")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_INVISIBLE;
        }
        else if(tmpStrValue == "suppressinfight")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_INFIGHT;
        }
        else if(tmpStrValue == "suppressexhaust")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_EXHAUST;
        }
        else if(tmpStrValue == "suppressmuted")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_MUTED;
        }
        else if(tmpStrValue == "suppresspacified")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_PACIFIED;
        }
        else if(tmpStrValue == "suppresslight")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_LIGHT;
        }
        else if(tmpStrValue == "suppressattributes")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_ATTRIBUTES;
        }
        else if(tmpStrValue == "suppressmanashield")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue) && intValue != 0)
                it.getAbilities()->conditionSuppressions |= CONDITION_MANASHIELD;
        }
        else if(tmpStrValue == "field")
        {
            it.group = ITEM_GROUP_MAGICFIELD;
            it.type = ITEM_TYPE_MAGICFIELD;

            CombatType_t combatType = COMBAT_NONE;
            ConditionDamage* conditionDamage = NULL;
            if(readXMLString(itemAttributesNode, "value", strValue))
            {
                tmpStrValue = asLowerCaseString(strValue);
                if(tmpStrValue == "fire")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FIRE, false, 0);
                    combatType = COMBAT_FIREDAMAGE;
                }
                else if(tmpStrValue == "energy")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_ENERGY, false, 0);
                    combatType = COMBAT_ENERGYDAMAGE;
                }
                else if(tmpStrValue == "earth" || tmpStrValue == "poison")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_POISON, false, 0);
                    combatType = COMBAT_EARTHDAMAGE;
                }
                else if(tmpStrValue == "ice" || tmpStrValue == "freezing")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FREEZING, false, 0);
                    combatType = COMBAT_ICEDAMAGE;
                }
                else if(tmpStrValue == "holy" || tmpStrValue == "dazzled")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DAZZLED, false, 0);
                    combatType = COMBAT_HOLYDAMAGE;
                }
                else if(tmpStrValue == "death" || tmpStrValue == "cursed")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_CURSED, false, 0);
                    combatType = COMBAT_DEATHDAMAGE;
                }
                else if(tmpStrValue == "drown")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DROWN, false, 0);
                    combatType = COMBAT_DROWNDAMAGE;
                }
                else if(tmpStrValue == "physical" || tmpStrValue == "bleed")
                {
                    conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_BLEEDING, false, 0);
                    combatType = COMBAT_PHYSICALDAMAGE;
                }
                else
                    std::clog << "[Warning - Items::loadFromXml] Unknown field value " << strValue << std::endl;

                if(combatType != COMBAT_NONE)
                {
                    it.combatType = combatType;
                    it.condition = conditionDamage;

                    uint32_t ticks = 0;
                    int32_t damage = 0, start = 0, count = 1;
                    for(xmlNodePtr fieldAttributesNode = itemAttributesNode->children; fieldAttributesNode; fieldAttributesNode = fieldAttributesNode->next)
                    {
                        if(!readXMLString(fieldAttributesNode, "key", strValue))
                            continue;

                        tmpStrValue = asLowerCaseString(strValue);
                        if(tmpStrValue == "ticks")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                                ticks = std::max(0, intValue);
                        }

                        if(tmpStrValue == "count")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                                count = std::max(1, intValue);
                        }

                        if(tmpStrValue == "start")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                                start = std::max(0, intValue);
                        }

                        if(tmpStrValue == "damage")
                        {
                            if(readXMLInteger(fieldAttributesNode, "value", intValue))
                            {
                                damage = -intValue;
                                if(start > 0)
                                {
                                    std::list<int32_t> damageList;
                                    ConditionDamage::generateDamageList(damage, start, damageList);
                                    for(std::list<int32_t>::iterator it = damageList.begin(); it != damageList.end(); ++it)
                                        conditionDamage->addDamage(1, ticks, -*it);

                                    start = 0;
                                }
                                else
                                    conditionDamage->addDamage(count, ticks, damage);
                            }
                        }
                    }

                    conditionDamage->setParam(CONDITIONPARAM_FIELD, true);
                    if(conditionDamage->getTotalDamage() > 0)
                        conditionDamage->setParam(CONDITIONPARAM_FORCEUPDATE, true);
                }
            }
        }
        else if(tmpStrValue == "elementphysical")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_PHYSICALDAMAGE;
            }
        }
        else if(tmpStrValue == "elementfire")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_FIREDAMAGE;
            }
        }
        else if(tmpStrValue == "elementenergy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_ENERGYDAMAGE;
            }
        }
        else if(tmpStrValue == "elementearth")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_EARTHDAMAGE;
            }
        }
        else if(tmpStrValue == "elementice")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_ICEDAMAGE;
            }
        }
        else if(tmpStrValue == "elementholy")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_HOLYDAMAGE;
            }
        }
        else if(tmpStrValue == "elementdeath")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_DEATHDAMAGE;
            }
        }
        else if(tmpStrValue == "elementlifedrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_LIFEDRAIN;
            }
        }
        else if(tmpStrValue == "elementmanadrain")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_MANADRAIN;
            }
        }
        else if(tmpStrValue == "elementhealing")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_HEALING;
            }
        }
        else if(tmpStrValue == "elementundefined")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.getAbilities()->elementDamage = intValue;
                it.getAbilities()->elementType = COMBAT_UNDEFINEDDAMAGE;
            }
        }
        else if(tmpStrValue == "replacable" || tmpStrValue == "replaceable")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.replacable = (intValue != 0);
        }
        else if(tmpStrValue == "partnerdirection")
        {
            if(readXMLString(itemAttributesNode, "value", strValue))
                it.bedPartnerDir = getDirection(strValue);
        }
        else if(tmpStrValue == "maletransformto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.transformBed[PLAYERSEX_MALE] = intValue;
                ItemType& ot = getItemType(intValue);
                if(!ot.transformUseTo)
                    ot.transformUseTo = it.id;

                if(!it.transformBed[PLAYERSEX_FEMALE])
                    it.transformBed[PLAYERSEX_FEMALE] = intValue;
            }
        }
        else if(tmpStrValue == "femaletransformto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
            {
                it.transformBed[PLAYERSEX_FEMALE] = intValue;
                ItemType& ot = getItemType(intValue);
                if(!ot.transformUseTo)
                    ot.transformUseTo = it.id;

                if(!it.transformBed[PLAYERSEX_MALE])
                    it.transformBed[PLAYERSEX_MALE] = intValue;
            }
        }
        else if(tmpStrValue == "transformto" || tmpStrValue == "transformuseto" || tmpStrValue == "onuseto")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.transformUseTo = intValue;
        }
        else if(tmpStrValue == "walkstack")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.walkStack = (intValue != 0);
        }
        else if(tmpStrValue == "premiumdays")
        {
            if(readXMLInteger(itemAttributesNode, "value", intValue))
                it.premiumDays = intValue;
        }
        else
            std::clog << "[Warning - Items::loadFromXml] Unknown key value " << strValue << std::endl;
    }

    if(it.pluralName.empty() && !it.name.empty())
    {
        it.pluralName = it.name;
        if(it.showCount)
            it.pluralName += "s";
    }

    it.getAbilities()->absorb[COMBAT_ALL] = it.getAbilities()->absorb[COMBAT_FIRST + 1];
    it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ALL] = it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_FIRST + 1];
    it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ALL] = it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_FIRST + 1];
    for(uint32_t i = (COMBAT_FIRST + 1) << 1; i <= COMBAT_LAST; i <<= 1)
    {
        if(it.getAbilities()->absorb[COMBAT_ALL] != it.getAbilities()->absorb)
            it.getAbilities()->absorb[COMBAT_ALL] = 0;

        if(it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ALL] != it.getAbilities()->reflect[REFLECT_PERCENT])
            it.getAbilities()->reflect[REFLECT_PERCENT][COMBAT_ALL] = 0;

        if(it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ALL] != it.getAbilities()->reflect[REFLECT_CHANCE])
            it.getAbilities()->reflect[REFLECT_CHANCE][COMBAT_ALL] = 0;
    }
}

void Items::parseRandomizationBlock(int32_t id, int32_t fromId, int32_t toId, int32_t chance)
{
    RandomizationMap::iterator it = randomizationMap.find(id);
    if(it != randomizationMap.end())
    {
        std::clog << "[Warning - Items::parseRandomizationBlock] Duplicated item with id: " << id << std::endl;
        return;
    }

    RandomizationBlock rand;
    rand.fromRange = fromId;
    rand.toRange = toId;

    rand.chance = chance;
    randomizationMap[id] = rand;
}

uint16_t Items::getRandomizedItem(uint16_t id)
{
    if(!g_config.getBool(ConfigManager::RANDOMIZE_TILES))
        return id;

    RandomizationBlock randomize = getRandomization(id);
    if(randomize.chance >= random_range(1, 100))
        id = random_range(randomize.fromRange, randomize.toRange);

    return id;
}

ItemType& Items::getItemType(int32_t id)
{
    ItemType* iType = items.getElement(id);
    if(iType)
        return *iType;

    #ifdef __DEBUG__
    std::clog << "[Warning - Items::getItemType] Unknown itemtype with id " << id << ", using defaults." << std::endl;
    #endif
    static ItemType dummyItemType; // use this for invalid ids
    return dummyItemType;
}

const ItemType& Items::getItemType(int32_t id) const
{
    if(ItemType* iType = items.getElement(id))
        return *iType;

    static ItemType dummyItemType; // use this for invalid ids
    return dummyItemType;
}

const ItemType& Items::getItemIdByClientId(int32_t spriteId) const
{
    auto it = reverseItemMap.find(spriteId);
    if (it != reverseItemMap.end()) {
        return getItemType(it->second);
    }

    static ItemType dummyItemType; // use this for invalid ids
    return dummyItemType;
}

int32_t Items::getItemIdByName(const std::string& name)
{
    if(!name.empty())
    {
        uint32_t i = 100;
        ItemType* iType = NULL;
        do
        {
            if((iType = items.getElement(i)) && boost::algorithm::iequals(name, iType->name))
                return i;

            ++i;
        }
        while(iType);
    }

    return -1;
}
 

 Bom, eu esqueci de editar o tópico atualizando que eu estava na pasta errada, achei que tinham editado errado e por isso eu ia no item.cpp enquanto tinha o " s " no final. Tem no items.cpp a substituição do código porém quando eu modifico algo nas soucers mostra varios erros

image.thumb.png.013ffdae053301891918f72d7a4d59b7.png

@Deadpool está ai.  

Editado por Fosil
Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novos posts.
  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...