fix bug that leaves units equipped after armor item is destroyed

This commit is contained in:
Martin Michelsen
2023-11-19 15:58:55 -08:00
parent bc4092fb75
commit b03ccc7e3e
4 changed files with 29 additions and 9 deletions
+14 -4
View File
@@ -572,8 +572,11 @@ bool PlayerInventory::has_equipped_item(EquipSlot slot) const {
}
}
void PlayerInventory::equip_item(uint32_t item_id, EquipSlot slot) {
size_t index = this->find_item(item_id);
void PlayerInventory::equip_item_id(uint32_t item_id, EquipSlot slot) {
this->equip_item_index(this->find_item(item_id), slot);
}
void PlayerInventory::equip_item_index(size_t index, EquipSlot slot) {
auto& item = this->items[index];
if (slot == EquipSlot::UNKNOWN) {
@@ -594,8 +597,15 @@ void PlayerInventory::equip_item(uint32_t item_id, EquipSlot slot) {
}
}
void PlayerInventory::unequip_item(uint32_t item_id) {
size_t index = this->find_item(item_id);
void PlayerInventory::unequip_item_id(uint32_t item_id) {
this->unequip_item_index(this->find_item(item_id));
}
void PlayerInventory::unequip_item_slot(EquipSlot slot) {
this->unequip_item_index(this->find_equipped_item(slot));
}
void PlayerInventory::unequip_item_index(size_t index) {
auto& item = this->items[index];
item.flags &= (~0x00000008);
+5 -2
View File
@@ -76,8 +76,11 @@ struct PlayerInventory {
size_t find_equipped_item(EquipSlot slot) const;
bool has_equipped_item(EquipSlot slot) const;
void equip_item(uint32_t item_id, EquipSlot slot);
void unequip_item(uint32_t item_id);
void equip_item_id(uint32_t item_id, EquipSlot slot);
void equip_item_index(size_t index, EquipSlot slot);
void unequip_item_id(uint32_t item_id);
void unequip_item_slot(EquipSlot slot);
void unequip_item_index(size_t index);
size_t remove_all_items_of_type(uint8_t data0, int16_t data1 = -1);
+2 -2
View File
@@ -1215,7 +1215,7 @@ static void on_equip_item(shared_ptr<Client> c, uint8_t command, uint8_t flag, c
if (l->check_flag(Lobby::Flag::ITEM_TRACKING_ENABLED)) {
EquipSlot slot = static_cast<EquipSlot>(cmd.equip_slot.load());
auto p = c->game_data.character();
p->inventory.equip_item(cmd.item_id, slot);
p->inventory.equip_item_id(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");
@@ -1234,7 +1234,7 @@ 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)) {
auto p = c->game_data.character();
p->inventory.unequip_item(cmd.item_id);
p->inventory.unequip_item_id(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");
+8 -1
View File
@@ -310,6 +310,7 @@ ItemData PSOBBCharacterFile::remove_item(uint32_t item_id, uint32_t amount, bool
size_t index = this->inventory.find_item(item_id);
auto& inventory_item = this->inventory.items[index];
bool is_equipped = (inventory_item.flags & 0x00000008);
// If the item is a combine item and are we removing less than we have of it,
// then create a new item and reduce the amount of the existing stack. Note
@@ -317,6 +318,9 @@ ItemData PSOBBCharacterFile::remove_item(uint32_t item_id, uint32_t amount, bool
// applies if amount is nonzero.
if (amount && (inventory_item.data.stack_size() > 1) &&
(amount < inventory_item.data.data1[5])) {
if (is_equipped) {
throw runtime_error("character has a combine item equipped");
}
ret = inventory_item.data;
ret.data1[5] = amount;
ret.id = 0xFFFFFFFF;
@@ -327,6 +331,9 @@ ItemData PSOBBCharacterFile::remove_item(uint32_t item_id, uint32_t amount, bool
// If we get here, then it's not meseta, and either it's not a combine item or
// we're removing the entire stack. Delete the item from the inventory slot
// and return the deleted item.
if (is_equipped) {
this->inventory.unequip_item_index(index);
}
ret = inventory_item.data;
this->inventory.num_items--;
for (size_t x = index; x < this->inventory.num_items; x++) {
@@ -425,7 +432,7 @@ void PSOBBCharacterFile::print_inventory(FILE* stream, GameVersion version, shar
const auto& item = this->inventory.items[x];
auto name = name_index->describe_item(version, item.data);
auto hex = item.data.hex();
fprintf(stream, "[PlayerInventory] %2zu: %s (%s)\n", x, hex.c_str(), name.c_str());
fprintf(stream, "[PlayerInventory] %2zu: [+%08" PRIX32 "] %s (%s)\n", x, item.flags.load(), hex.c_str(), name.c_str());
}
}