int Items::loadFromOtb(std::string file) { ItemLoader f; if(!f.openFile(file.c_str(), false, true)){ return f.getError(); } unsigned long type; NODE node = f.getChildNode(NO_NODE, type); PropStream props; if(f.getProps(node,props)){ //4 byte flags //attributes //0x01 = version data unsigned long flags; if(!props.GET_ULONG(flags)){ return ERROR_INVALID_FORMAT; } attribute_t attr; if(!props.GET_VALUE(attr)){ return ERROR_INVALID_FORMAT; } if(attr == ROOT_ATTR_VERSION){ datasize_t datalen = 0; if(!props.GET_VALUE(datalen)){ return ERROR_INVALID_FORMAT; } if(datalen != sizeof(VERSIONINFO)){ return ERROR_INVALID_FORMAT; } VERSIONINFO *vi; if(!props.GET_STRUCT(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 != 1){ std::cout << "Not supported items.otb version." << std::endl; return ERROR_INVALID_FORMAT; } if(Items::dwMinorVersion != CLIENT_VERSION_760){ std::cout << "Not supported items.otb client version." << std::endl; return ERROR_INVALID_FORMAT; } node = f.getChildNode(node, type); while(node != NO_NODE){ PropStream props; if(!f.getProps(node,props)){ return f.getError(); } flags_t flags; ItemType* iType = new ItemType(); iType->group = (itemgroup_t)type; switch(type){ case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_CONTAINER: case ITEM_GROUP_WEAPON: case ITEM_GROUP_AMMUNITION: case ITEM_GROUP_ARMOR: case ITEM_GROUP_RUNE: case ITEM_GROUP_TELEPORT: case ITEM_GROUP_MAGICFIELD: case ITEM_GROUP_WRITEABLE: case ITEM_GROUP_KEY: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: case ITEM_GROUP_DOOR: break; default: return ERROR_INVALID_FORMAT; break; } //read 4 byte flags if(!props.GET_VALUE(flags)){ return ERROR_INVALID_FORMAT; } iType->blockSolid = ((flags & FLAG_BLOCK_SOLID) == FLAG_BLOCK_SOLID); iType->blockProjectile = ((flags & FLAG_BLOCK_PROJECTILE) == FLAG_BLOCK_PROJECTILE); iType->blockPathFind = ((flags & FLAG_BLOCK_PATHFIND) == FLAG_BLOCK_PATHFIND); iType->hasHeight = ((flags & FLAG_HAS_HEIGHT) == FLAG_HAS_HEIGHT); iType->useable = ((flags & FLAG_USEABLE) == FLAG_USEABLE); iType->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); iType->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); iType->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); iType->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); iType->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); iType->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); iType->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); iType->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); iType->alwaysOnTop = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); iType->canDecay = !((flags & FLAG_CANNOTDECAY) == FLAG_CANNOTDECAY); iType->isVertical = ((flags & FLAG_VERTICAL) == FLAG_VERTICAL); iType->isHorizontal = ((flags & FLAG_HORIZONTAL) == FLAG_HORIZONTAL); iType->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); iType->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); if(type == ITEM_GROUP_WRITEABLE) { iType->RWInfo |= CAN_BE_WRITTEN; } if((flags & FLAG_READABLE) == FLAG_READABLE) iType->RWInfo |= CAN_BE_READ; iType->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); attribute_t attrib; datasize_t datalen = 0; while(props.GET_VALUE(attrib)){ //size of data if(!props.GET_VALUE(datalen)){ delete iType; return ERROR_INVALID_FORMAT; } switch(attrib){ case ITEM_ATTR_SERVERID: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short serverid; if(!props.GET_USHORT(serverid)) return ERROR_INVALID_FORMAT; if(serverid > 20000 && serverid < 20100) serverid = serverid - 20000; iType->id = serverid; break; } case ITEM_ATTR_CLIENTID: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; if(!props.GET_USHORT(iType->clientId)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_NAME: { char name[128]; if(datalen >= sizeof(name)) return ERROR_INVALID_FORMAT; if(!props.GET_NSTRING(datalen, iType->name)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_DESCR: { char descr[128]; if(datalen >= sizeof(descr)) return ERROR_INVALID_FORMAT; if(!props.GET_NSTRING(datalen, iType->description)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_SPEED: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; if(!props.GET_USHORT(iType->speed)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_SLOT: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short otb_slot; if(!props.GET_USHORT(otb_slot)) return ERROR_INVALID_FORMAT; switch(otb_slot){ case OTB_SLOT_DEFAULT: case OTB_SLOT_WEAPON: case OTB_SLOT_HAND: //default break; case OTB_SLOT_HEAD: iType->slot_position = SLOTP_HEAD; break; case OTB_SLOT_BODY: iType->slot_position = SLOTP_ARMOR; break; case OTB_SLOT_LEGS: iType->slot_position = SLOTP_LEGS; break; case OTB_SLOT_BACKPACK: iType->slot_position = SLOTP_BACKPACK; break; case OTB_SLOT_2HAND: iType->slot_position = SLOTP_TWO_HAND; break; case OTB_SLOT_FEET: iType->slot_position = SLOTP_FEET; break; case OTB_SLOT_AMULET: iType->slot_position = SLOTP_NECKLACE; break; case OTB_SLOT_RING: iType->slot_position = SLOTP_RING; break; } iType->slot_position = iType->slot_position | SLOTP_LEFT | SLOTP_RIGHT | SLOTP_AMMO; break; } case ITEM_ATTR_MAXITEMS: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; if(!props.GET_USHORT(iType->maxItems)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_WEIGHT: { if(datalen != sizeof(double)) return ERROR_INVALID_FORMAT; if(!props.GET_VALUE(iType->weight)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_MAGLEVEL: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short maglev; if(!props.GET_USHORT(maglev)) return ERROR_INVALID_FORMAT; iType->runeMagLevel = maglev; break; } case ITEM_ATTR_MAGFIELDTYPE: { if(datalen != sizeof(unsigned char)) return ERROR_INVALID_FORMAT; unsigned char fieldtype; if(!props.GET_UCHAR(fieldtype)) return ERROR_INVALID_FORMAT; iType->magicfieldtype = fieldtype; break; } case ITEM_ATTR_ROTATETO: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short rotate; if(!props.GET_USHORT(rotate)) return ERROR_INVALID_FORMAT; iType->rotateTo = rotate; break; } case ITEM_ATTR_DECAY2: { if(datalen != sizeof(decayBlock2)) return ERROR_INVALID_FORMAT; decayBlock2* db2; if(!props.GET_STRUCT(db2)) return ERROR_INVALID_FORMAT; iType->decayTime = db2->decayTime; iType->decayTo = db2->decayTo; break; } case ITEM_ATTR_WEAPON2: { if(datalen != sizeof(weaponBlock2)) return ERROR_INVALID_FORMAT; weaponBlock2* wb2; if(!props.GET_STRUCT(wb2)) return ERROR_INVALID_FORMAT; iType->weaponType = (WeaponType_t)wb2->weaponType; iType->shootType = translateOTBShootType((ShootTypeOtb_t)wb2->shootType); iType->amuType = (Ammo_t)wb2->amuType; iType->attack = wb2->attack; iType->defence = wb2->defence; break; } case ITEM_ATTR_AMU2: { if(datalen != sizeof(amuBlock2)) return ERROR_INVALID_FORMAT; amuBlock2* ab2; if(!props.GET_STRUCT(ab2)) return ERROR_INVALID_FORMAT; iType->weaponType = WEAPON_AMMO; iType->shootType = translateOTBShootType((ShootTypeOtb_t)ab2->shootType); iType->amuType = (Ammo_t)ab2->amuType; iType->attack = ab2->attack; break; } case ITEM_ATTR_ARMOR2: { if(datalen != sizeof(armorBlock2)) return ERROR_INVALID_FORMAT; armorBlock2* ab2; if(!props.GET_STRUCT(ab2)) return ERROR_INVALID_FORMAT; iType->armor = ab2->armor; iType->weight = ab2->weight; //ignore this value //iType->slot_position = (slots_t)ab2.slot_position; break; } case ITEM_ATTR_WRITEABLE3: { if(datalen != sizeof(writeableBlock3)) return ERROR_INVALID_FORMAT; writeableBlock3* wb3; if(!props.GET_STRUCT(wb3)) return ERROR_INVALID_FORMAT; iType->readOnlyId = wb3->readOnlyId; iType->maxTextLen = wb3->maxTextLen; break; } case ITEM_ATTR_LIGHT2: { if(datalen != sizeof(lightBlock2)) return ERROR_INVALID_FORMAT; lightBlock2* lb2; if(!props.GET_STRUCT(lb2)) return ERROR_INVALID_FORMAT; iType->lightLevel = lb2->lightLevel; iType->lightColor = lb2->lightColor; break; } case ITEM_ATTR_TOPORDER: { if(datalen != sizeof(unsigned char)) return ERROR_INVALID_FORMAT; if(!props.GET_UCHAR(iType->alwaysOnTopOrder)) return ERROR_INVALID_FORMAT; break; } default: //skip unknown attributes if(!props.SKIP_N(datalen)) return ERROR_INVALID_FORMAT; break; } } //get rune mag level from spells.xml if(iType->group == ITEM_GROUP_RUNE){ /* std::map<unsigned short, Spell*>::iterator it = spells.getAllRuneSpells()->find(iType->id); if(it != spells.getAllRuneSpells()->end()){ iType->runeMagLevel = it->second->getMagLv(); } else{ iType->runeMagLevel = 0; } */ } // store the found item items[iType->id] = iType; //revItems[iType->clientId] = iType->id; node = f.getNextNode(node, type); } return ERROR_NONE; }