fix equip slot check

This commit is contained in:
Martin Michelsen
2023-11-15 15:22:50 -08:00
parent 3d7b6837ec
commit f997376819
4 changed files with 39 additions and 9 deletions
+20
View File
@@ -567,6 +567,26 @@ bool ItemData::is_s_rank_weapon() const {
return false;
}
EquipSlot ItemData::default_equip_slot() const {
switch (this->data1[0]) {
case 0x00:
return EquipSlot::WEAPON;
case 0x01:
switch (this->data1[1]) {
case 0x01:
return EquipSlot::ARMOR;
case 0x02:
return EquipSlot::SHIELD;
case 0x03:
return EquipSlot::UNIT_1;
}
break;
case 0x02:
return EquipSlot::MAG;
}
throw runtime_error("item cannot be equipped");
}
bool ItemData::can_be_equipped_in_slot(EquipSlot slot) const {
switch (slot) {
case EquipSlot::MAG:
+8
View File
@@ -11,6 +11,13 @@ constexpr uint32_t MESETA_IDENTIFIER = 0x040000;
class ItemParameterTable;
enum class EquipSlot {
// When equipping items through the Item Pack pause menu, the client sends
// UNKNOWN for the slot. The receiving client (and server, in our case) have
// to analyze the item being equipped and put it in the appropriate slot in
// this case. See ItemData::default_equip_slot() for this computation.
UNKNOWN = 0x00,
// When equipping items through the quick menu or Equip pause menu, the client
// sends one of the slots below.
MAG = 0x01,
ARMOR = 0x02,
SHIELD = 0x03,
@@ -163,6 +170,7 @@ struct ItemData { // 0x14 bytes
bool has_bonuses() const;
bool is_s_rank_weapon() const;
EquipSlot default_equip_slot() const;
bool can_be_equipped_in_slot(EquipSlot slot) const;
bool empty() const;
+4
View File
@@ -570,6 +570,10 @@ void PlayerInventory::equip_item(uint32_t item_id, EquipSlot slot) {
size_t index = this->find_item(item_id);
auto& item = this->items[index];
if (slot == EquipSlot::UNKNOWN) {
slot = item.data.default_equip_slot();
}
if (!item.data.can_be_equipped_in_slot(slot)) {
throw runtime_error("incorrect item type for equip slot");
}
+7 -9
View File
@@ -1155,11 +1155,10 @@ static void on_equip_item(shared_ptr<Client> c, uint8_t command, uint8_t flag, c
auto l = c->require_lobby();
if (l->check_flag(Lobby::Flag::ITEM_TRACKING_ENABLED)) {
if (l->base_version == GameVersion::BB) {
EquipSlot slot = static_cast<EquipSlot>(cmd.equip_slot.load());
auto p = c->game_data.character();
p->inventory.equip_item(cmd.item_id, slot);
}
EquipSlot slot = static_cast<EquipSlot>(cmd.equip_slot.load());
auto p = c->game_data.character();
p->inventory.equip_item(cmd.item_id, slot);
c->log.info("Equipped item %08" PRIX32, cmd.item_id.load());
} else if (l->base_version == GameVersion::BB) {
throw logic_error("item tracking not enabled in BB game");
}
@@ -1176,10 +1175,9 @@ static void on_unequip_item(shared_ptr<Client> c, uint8_t command, uint8_t flag,
auto l = c->require_lobby();
if (l->check_flag(Lobby::Flag::ITEM_TRACKING_ENABLED)) {
if (l->base_version == GameVersion::BB) {
auto p = c->game_data.character();
p->inventory.unequip_item(cmd.item_id);
}
auto p = c->game_data.character();
p->inventory.unequip_item(cmd.item_id);
c->log.info("Unequipped item %08" PRIX32, cmd.item_id.load());
} else if (l->base_version == GameVersion::BB) {
throw logic_error("item tracking not enabled in BB game");
}