diff --git a/src/Episode3/DataIndex.cc b/src/Episode3/DataIndex.cc index 5a3ea6a9..10ff4a7a 100644 --- a/src/Episode3/DataIndex.cc +++ b/src/Episode3/DataIndex.cc @@ -1495,9 +1495,6 @@ DataIndex::DataIndex(const string& directory, uint32_t behavior_flags) add_maps_from_dir(directory + "/maps-free", false); add_maps_from_dir(directory + "/maps-quest", true); - // Generate (and cache) the map list to ensure it's not too large - this->get_compressed_map_list(); - try { auto json = JSONObject::parse(load_file(directory + "/com-decks.json")); for (const auto& def_json : json->as_list()) { diff --git a/src/Items.cc b/src/Items.cc index bd73cda3..04e87f2f 100644 --- a/src/Items.cc +++ b/src/Items.cc @@ -231,7 +231,9 @@ void player_use_item(shared_ptr c, size_t item_index) { } if (should_delete_item) { - c->game_data.player()->remove_item(item.data.id, 1); + // Allow overdrafting meseta if the client is not BB, since the server isn't + // informed when meseta is added or removed from the bank. + c->game_data.player()->remove_item(item.data.id, 1, c->version() != GameVersion::BB); } } diff --git a/src/Player.cc b/src/Player.cc index da028db3..6fc3df5d 100644 --- a/src/Player.cc +++ b/src/Player.cc @@ -793,18 +793,21 @@ void PlayerBank::add_item(const PlayerBankItem& item) { // TODO: Eliminate code duplication between this function and the parallel // function in PlayerBank PlayerInventoryItem SavedPlayerDataBB::remove_item( - uint32_t item_id, uint32_t amount) { + uint32_t item_id, uint32_t amount, bool allow_meseta_overdraft) { PlayerInventoryItem ret; // If we're removing meseta (signaled by an invalid item ID), then create a // meseta item. if (item_id == 0xFFFFFFFF) { - if (amount > this->disp.meseta) { + if (amount <= this->disp.meseta) { + this->disp.meseta -= amount; + } else if (allow_meseta_overdraft) { + this->disp.meseta = 0; + } else { throw out_of_range("player does not have enough meseta"); } ret.data.data1[0] = 0x04; ret.data.data2d = amount; - this->disp.meseta -= amount; return ret; } diff --git a/src/Player.hh b/src/Player.hh index 7cfb8c06..20f8bb89 100644 --- a/src/Player.hh +++ b/src/Player.hh @@ -483,7 +483,8 @@ struct SavedPlayerDataBB { // .nsc file format parray tech_menu_config; void add_item(const PlayerInventoryItem& item); - PlayerInventoryItem remove_item(uint32_t item_id, uint32_t amount); + PlayerInventoryItem remove_item( + uint32_t item_id, uint32_t amount, bool allow_meseta_overdraft); void print_inventory(FILE* stream) const; } __attribute__((packed)); diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index 74c6c47c..9f7553a2 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -476,8 +476,8 @@ static void on_player_drop_item(shared_ptr, } if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) { - l->add_item(c->game_data.player()->remove_item(cmd.item_id, 0), cmd.area, - cmd.x, cmd.z); + auto item = c->game_data.player()->remove_item(cmd.item_id, 0, c->version() != GameVersion::BB); + l->add_item(item, cmd.area, cmd.x, cmd.z); l->log.info("Player %hu dropped item %08" PRIX32 " at %hu:(%g, %g)", cmd.header.client_id.load(), cmd.item_id.load(), cmd.area.load(), @@ -563,7 +563,8 @@ static void on_drop_partial_stack_bb(shared_ptr, throw logic_error("item tracking not enabled in BB game"); } - auto item = c->game_data.player()->remove_item(cmd.item_id, cmd.amount); + auto item = c->game_data.player()->remove_item( + cmd.item_id, cmd.amount, c->version() != GameVersion::BB); // if a stack was split, the original item still exists, so the dropped item // needs a new ID. remove_item signals this by returning an item with id=-1 @@ -814,7 +815,8 @@ static void on_bank_action_bb(shared_ptr, c->game_data.player()->bank.meseta += cmd.meseta_amount; c->game_data.player()->disp.meseta -= cmd.meseta_amount; } else { // item - auto item = c->game_data.player()->remove_item(cmd.item_id, cmd.item_amount); + auto item = c->game_data.player()->remove_item( + cmd.item_id, cmd.item_amount, c->version() != GameVersion::BB); c->game_data.player()->bank.add_item(item); send_destroy_item(l, c, cmd.item_id, cmd.item_amount); } @@ -1130,7 +1132,8 @@ static void on_destroy_inventory_item(shared_ptr, return; } if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) { - c->game_data.player()->remove_item(cmd.item_id, cmd.amount); + c->game_data.player()->remove_item( + cmd.item_id, cmd.amount, c->version() != GameVersion::BB); l->log.info("Inventory item %hu:%08" PRIX32 " destroyed (%" PRIX32 " of them)", cmd.header.client_id.load(), cmd.item_id.load(), cmd.amount.load()); c->game_data.player()->print_inventory(stderr);