diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/manaserv_protocol.h | 4 | ||||
-rw-r--r-- | src/game-server/inventory.cpp | 19 | ||||
-rw-r--r-- | src/game-server/inventory.h | 5 | ||||
-rw-r--r-- | src/game-server/itemmanager.cpp | 16 | ||||
-rw-r--r-- | src/game-server/state.cpp | 81 |
5 files changed, 66 insertions, 59 deletions
diff --git a/src/common/manaserv_protocol.h b/src/common/manaserv_protocol.h index 25dd7c77..2448a357 100644 --- a/src/common/manaserv_protocol.h +++ b/src/common/manaserv_protocol.h @@ -106,12 +106,12 @@ enum { GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, W attribute
PGMSG_RESPAWN = 0x0180, // -
GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position, B direction
- // character: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }*
+ // character: S name, B hair style, B hair color, B gender, B sprite layers changed, { B slot type, W item id }*
// monster: W type id
// npc: W type id
GPMSG_BEING_LEAVE = 0x0201, // W being id
GPMSG_ITEM_APPEAR = 0x0202, // W item id, W*2 position
- GPMSG_BEING_LOOKS_CHANGE = 0x0210, // W weapon, W hat, W top clothes, W bottom clothes
+ GPMSG_BEING_LOOKS_CHANGE = 0x0210, // B sprite layers changed, { B slot type, W item id }*
PGMSG_WALK = 0x0260, // W*2 destination
PGMSG_ACTION_CHANGE = 0x0270, // B Action
GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action
diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 55986106..e486f7c0 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -740,8 +740,10 @@ bool Inventory::equip(int inventorySlot) // Remove item from inventory removeFromSlot(inventorySlot, 1); - if (equipMsg.getLength() > 2) - gameHandler->sendTo(mCharacter, equipMsg); + gameHandler->sendTo(mCharacter, equipMsg); + + // Update look when necessary + checkLookchanges(equipReq.equipSlotId); return true; } @@ -756,6 +758,7 @@ bool Inventory::unequip(unsigned int itemInstance) // The itemId to unequip unsigned int itemId = 0; + unsigned int slotTypeId = 0; // Empties all equip entries that point to the given equipment slot // The equipment slots should NEVER be erased after initialization! @@ -768,6 +771,10 @@ bool Inventory::unequip(unsigned int itemInstance) itemId = it->second.itemId; it->second.itemId = 0; it->second.itemInstance = 0; + + // We keep track of the slot type to be able to raise a potential + // change in the character sprite + slotTypeId = it->first; } } @@ -790,5 +797,13 @@ bool Inventory::unequip(unsigned int itemInstance) // Apply unequip trigger updateEquipmentTrigger(itemId, 0); + checkLookchanges(slotTypeId); + return true; } + +void Inventory::checkLookchanges(unsigned int slotTypeId) +{ + if (itemManager->isEquipSlotVisible(slotTypeId)) + mCharacter->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); +} diff --git a/src/game-server/inventory.h b/src/game-server/inventory.h index 1eaf0527..547abdf0 100644 --- a/src/game-server/inventory.h +++ b/src/game-server/inventory.h @@ -153,10 +153,9 @@ class Inventory void checkInventorySize(); /** - * Check whether the equipment change has visible consequence - * on the character sprite. + * Check potential visible character sprite changes. */ - void checkLookUpdate(unsigned slotTypeId); + void checkLookchanges(unsigned int slotTypeId); /** * Apply equipment triggers. diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index d41212bb..6840368a 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -132,16 +132,18 @@ void ItemManager::readEquipSlotsFile() continue; } - bool visible = XML::getBoolProperty(node, "visible", false); - if (visible) + if (slotId > 255) { - if (++mVisibleEquipSlotCount > 7) - { - LOG_WARN("Item Manager: More than 7 visible equip slot!" - "This will not work with current netcode!"); - } + LOG_WARN("Item Manager: equip slot " << slotId + << ": (" << name << ") is superior to 255 " + "and has been ignored."); + continue; } + bool visible = XML::getBoolProperty(node, "visible", false); + if (visible) + ++mVisibleEquipSlotCount; + EquipSlotsInfo::iterator i = mEquipSlotsInfo.find(slotId); if (i != mEquipSlotsInfo.end()) diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index d8f9b183..30b57cae 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -106,59 +106,50 @@ static void updateMap(MapComposite *map) /** * Sets message fields describing character look. */ -static void serializeLooks(Character *ch, MessageOut &msg, bool full) +static void serializeLooks(Character *ch, MessageOut &msg) { const EquipData &equipData = ch->getPossessions().getEquipment(); - unsigned int nb_slots = itemManager->getVisibleEquipSlotCount(); - // Bitmask describing the changed entries. - int changed = (1 << nb_slots) - 1; - if (!full) - { - // TODO: do not assume the whole equipment changed, - // when an update is asked for. - changed = (1 << nb_slots) - 1; - } + // We'll use a set to check whether we already sent the update for the given + // item instance. + std::set<unsigned int> itemInstances; + + // The map storing the info about the look changes to send + //{ slot type id, item id } + std::map <unsigned int, unsigned int> lookChanges; - std::vector<unsigned int> items; - items.resize(nb_slots, 0); - // Partially build both kinds of packet, to get their sizes. - unsigned int mask_full = 0, mask_diff = 0; - unsigned int nb_full = 0, nb_diff = 0; - std::map<unsigned int, EquipmentItem>::const_iterator it = - equipData.begin(); - for (unsigned int i = 0; i < nb_slots; ++i) + // Note that we can send several updates on the same slot type as different + // items may have been equipped. + for (EquipData::const_iterator it = equipData.begin(), + it_end = equipData.end(); it != it_end; ++it) { - if (changed & (1 << i)) - { - // Skip slots that have not changed, when sending an update. - ++nb_diff; - mask_diff |= 1 << i; - } - if (it == equipData.end() || it->first > i) continue; - ItemClass *eq; - items[i] = it->first && (eq = itemManager->getItem(it->first)) ? - eq->getSpriteID() : 0; - if (items[i]) + if (!itemManager->isEquipSlotVisible(it->first)) + continue; + + if (!it->second.itemInstance + || itemInstances.insert(it->second.itemInstance).second) { - /* If we are sending the whole equipment, only filled slots have to - be accounted for, as the other ones will be automatically cleared. */ - ++nb_full; - mask_full |= 1 << i; + // When the insertion succeeds, its the first time + // we encounter the item, so we can send the look change. + // We also send empty slots for unequipment handling. + lookChanges.insert( + std::make_pair<unsigned int, unsigned int>(it->first, + it->second.itemId)); } } - // Choose the smaller payload. - if (nb_full <= nb_diff) full = true; - - /* Bitmask enumerating the sent slots. - Setting the upper bit tells the client to clear the slots beforehand. */ - int mask = full ? mask_full | (1 << 7) : mask_diff; - - msg.writeInt8(mask); - for (unsigned int i = 0; i < nb_slots; ++i) + if (lookChanges.size() > 0) { - if (mask & (1 << i)) msg.writeInt16(items[i]); + // Number of look changes to send + msg.writeInt8(lookChanges.size()); + + for (std::map<unsigned int, unsigned int>::const_iterator it2 = + lookChanges.begin(), it2_end = lookChanges.end(); + it2 != it2_end; ++it2) + { + msg.writeInt8(it2->first); + msg.writeInt16(it2->second); + } } } @@ -222,7 +213,7 @@ static void informPlayer(MapComposite *map, Character *p, int worldTime) MessageOut LooksMsg(GPMSG_BEING_LOOKS_CHANGE); LooksMsg.writeInt16(oid); Character * c = static_cast<Character * >(o); - serializeLooks(c, LooksMsg, false); + serializeLooks(c, LooksMsg); LooksMsg.writeInt16(c->getHairStyle()); LooksMsg.writeInt16(c->getHairColor()); LooksMsg.writeInt16(c->getGender()); @@ -286,7 +277,7 @@ static void informPlayer(MapComposite *map, Character *p, int worldTime) enterMsg.writeInt8(q->getHairStyle()); enterMsg.writeInt8(q->getHairColor()); enterMsg.writeInt8(q->getGender()); - serializeLooks(q, enterMsg, true); + serializeLooks(q, enterMsg); } break; case OBJECT_MONSTER: |