diff --git a/src/creatures/players/cyclopedia/player_cyclopedia.cpp b/src/creatures/players/cyclopedia/player_cyclopedia.cpp index 3e05c403f57..ba7c01fe90c 100644 --- a/src/creatures/players/cyclopedia/player_cyclopedia.cpp +++ b/src/creatures/players/cyclopedia/player_cyclopedia.cpp @@ -86,7 +86,7 @@ void PlayerCyclopedia::loadDeathHistory() { g_logger().debug("Checking and updating death history of player {} took {} milliseconds.", m_player.getName(), bm_check.duration()); } -void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, uint16_t id) { +void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, const std::string &id) { switch (type) { case Summary_t::HOUSE_ITEMS: case Summary_t::BLESSINGS: @@ -94,7 +94,7 @@ void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, uint16_ break; case Summary_t::ALL_BLESSINGS: for (int i = 1; i < 8; ++i) { - insertValue(static_cast(Summary_t::BLESSINGS), amount, i); + insertValue(static_cast(Summary_t::BLESSINGS), amount, fmt::format("{}", i)); } break; default: @@ -104,13 +104,13 @@ void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, uint16_ } uint16_t PlayerCyclopedia::getAmount(uint8_t type) { - auto kv = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->get("amount"); - return static_cast(kv ? kv->getNumber() : 0); + auto kvScope = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->get("amount"); + return static_cast(kvScope ? kvScope->getNumber() : 0); } -void PlayerCyclopedia::updateAmount(uint8_t type, uint16_t toAddPoints) { - auto oldPoints = getAmount(type); - m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->set("amount", oldPoints + toAddPoints); +void PlayerCyclopedia::updateAmount(uint8_t type, uint16_t amount) { + auto oldAmount = getAmount(type); + m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->set("amount", oldAmount + amount); } std::vector PlayerCyclopedia::getDeathHistory() const { @@ -133,24 +133,27 @@ Summary PlayerCyclopedia::getSummary() { return { getAmount(Summary_t::BOOSTS), getAmount(Summary_t::PREY_CARDS), getAmount(Summary_t::INSTANT_REWARDS), getAmount(Summary_t::HIRELINGS) }; } -std::map PlayerCyclopedia::getResult(uint8_t type) const { +std::map PlayerCyclopedia::getResult(uint8_t type) const { auto kvScope = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type)); - std::map result = {}; - for (const auto &id : kvScope->keys()) { - auto kv = kvScope->scoped(id)->get("amount"); - result[std::stoull(id)] = static_cast(kv ? kv->getNumber() : 0); + std::map result; + for (const auto &scope : kvScope->keys()) { + size_t pos = scope.find('.'); + if (pos == std::string::npos) { + g_logger().error("Invalid key format: {}", scope); + continue; + } + std::string id = scope.substr(0, pos); + auto amount = kvScope->scoped(id)->get("amount"); + result.emplace(id, static_cast(amount ? amount->getNumber() : 0)); } return result; } -void PlayerCyclopedia::insertValue(uint8_t type, uint16_t amount, uint16_t id) { - auto kv = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type)); - auto oldAmount = 0; +void PlayerCyclopedia::insertValue(uint8_t type, uint16_t amount, const std::string &id) { auto result = getResult(type); auto it = result.find(id); - if (it != result.end()) { - oldAmount = it->second; - } - kv->scoped(fmt::format("{}", id))->set("amount", oldAmount + amount); - g_logger().info("type: {}, old: {}, amount: {}, newamount: {}, id: {}", type, oldAmount, amount, oldAmount + amount, id); + auto oldAmount = (it != result.end() ? it->second : 0); + auto newAmount = oldAmount + amount; + m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->scoped(id)->set("amount", newAmount); + g_logger().info("type: {}, id: {}, old amount: {}, added amount: {}, new amount: {}", type, id, oldAmount, amount, newAmount); } diff --git a/src/creatures/players/cyclopedia/player_cyclopedia.hpp b/src/creatures/players/cyclopedia/player_cyclopedia.hpp index 63d44730023..6791986c0fa 100644 --- a/src/creatures/players/cyclopedia/player_cyclopedia.hpp +++ b/src/creatures/players/cyclopedia/player_cyclopedia.hpp @@ -35,9 +35,9 @@ class PlayerCyclopedia { void loadRecentKills(); void loadDeathHistory(); - void updateStoreSummary(uint8_t type, uint16_t amount = 1, uint16_t id = 0); + void updateStoreSummary(uint8_t type, uint16_t amount = 1, const std::string &id = ""); uint16_t getAmount(uint8_t type); - void updateAmount(uint8_t type, uint16_t toAddPoints); + void updateAmount(uint8_t type, uint16_t amount = 1); [[nodiscard]] std::vector getDeathHistory() const; void insertDeathOnHistory(std::string cause, uint32_t timestamp); @@ -47,8 +47,8 @@ class PlayerCyclopedia { Summary getSummary(); - [[nodiscard]] std::map getResult(uint8_t type) const; - void insertValue(uint8_t type, uint16_t amount = 1, uint16_t id = 0); + [[nodiscard]] std::map getResult(uint8_t type) const; + void insertValue(uint8_t type, uint16_t amount = 1, const std::string &id = ""); private: std::vector m_deathHistory; diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 934a0df1dba..f77c8f264e0 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4370,7 +4370,7 @@ int PlayerFunctions::luaPlayerCreateTransactionSummary(lua_State* L) { } auto amount = getNumber(L, 3, 1); - auto id = getNumber(L, 4, 0); + auto id = getString(L, 4, ""); g_logger().info("type: {}, amount: {}, id: {}", type, amount, id); player->cyclopedia()->updateStoreSummary(type, amount, id); diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 5330568ab53..384c56ce60a 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -3935,18 +3935,23 @@ void ProtocolGame::sendCyclopediaCharacterStoreSummary() { msg.addByte(CYCLOPEDIA_CHARACTERINFO_STORESUMMARY); msg.addByte(0x00); // 0x00 Here means 'no error' msg.add(player->getXpBoostTime()); // Remaining Store Xp Boost Time - msg.add(0); // RemainingDailyRewardXpBoostTime + auto remaining = player->kv()->get("daily-reward-xp-boost"); + msg.add(remaining ? static_cast(remaining->getNumber()) : 0x00); // Remaining Daily Reward Xp Boost Time auto cyclopediaSummary = player->cyclopedia()->getSummary(); // getBlessingsObtained - auto blessings = player->getBlessingNames(); - msg.addByte(static_cast(blessings.size())); - auto amountsByBlessing = player->cyclopedia()->getResult(static_cast(Summary_t::BLESSINGS)); - for (const auto &bless_it : blessings) { - msg.addString(bless_it.second, "ProtocolGame::sendCyclopediaCharacterStoreSummary - blessing.name"); - msg.addByte(static_cast(amountsByBlessing[bless_it.first])); - g_logger().info("bless id: {}, name: {}, found(count): {}", bless_it.first, bless_it.second, amountsByBlessing[bless_it.first]); + auto blessingNames = player->getBlessingNames(); + msg.addByte(static_cast(blessingNames.size())); + auto blessingsObtained = player->cyclopedia()->getResult(static_cast(Summary_t::BLESSINGS)); + for (const auto &name_it : blessingNames) { + msg.addString(name_it.second, "ProtocolGame::sendCyclopediaCharacterStoreSummary - blessing.name"); + auto it = std::find_if(blessingsObtained.begin(), blessingsObtained.end(), [&name_it](const std::pair &bName_it) { + return bName_it.first == name_it.first; + }); + uint16_t blessAmount = (it != blessingsObtained.end()) ? it->second : 0; + msg.addByte(static_cast(blessAmount)); + g_logger().info("bless id: {}, name: {}, amount: {}", name_it.first, name_it.second, blessAmount); } uint8_t preySlotsUnlocked = 0; @@ -3996,8 +4001,8 @@ void ProtocolGame::sendCyclopediaCharacterStoreSummary() { auto houseItems = player->cyclopedia()->getResult(static_cast(Summary_t::HOUSE_ITEMS)); msg.add(houseItems.size()); for (const auto &hItem_it : houseItems) { - const ItemType &it = Item::items[hItem_it.first]; - msg.add(hItem_it.first); // Item ID + const ItemType &it = Item::items[std::stoll(hItem_it.first)]; + msg.add(it.id); // Item ID msg.addString(it.name, "ProtocolGame::sendCyclopediaCharacterStoreSummary - houseItem.name"); msg.addByte(hItem_it.second); }