summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/manaserv_protocol.h4
-rw-r--r--src/game-server/inventory.cpp19
-rw-r--r--src/game-server/inventory.h5
-rw-r--r--src/game-server/itemmanager.cpp16
-rw-r--r--src/game-server/state.cpp81
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: