From 0173a8df2b1a62a71d520642ff05de6c6d0543bb Mon Sep 17 00:00:00 2001 From: sruon Date: Tue, 4 Mar 2025 04:52:06 -0700 Subject: [PATCH] Treasure Pool lua bindings --- scripts/commands/getpool.lua | 82 ++++++++++++ scripts/enum/treasure_pool.lua | 14 ++ scripts/specs/core/CBaseEntity.lua | 5 + scripts/specs/core/CTreasurePool.lua | 55 ++++++++ src/map/alliance.cpp | 4 +- src/map/entities/charentity.cpp | 2 +- src/map/entities/mobentity.cpp | 54 +++++++- src/map/lua/CMakeLists.txt | 2 + src/map/lua/lua_baseentity.cpp | 18 +++ src/map/lua/lua_baseentity.h | 1 + src/map/lua/lua_treasure_pool.cpp | 191 +++++++++++++++++++++++++++ src/map/lua/lua_treasure_pool.h | 47 +++++++ src/map/lua/luautils.cpp | 3 + src/map/lua/sol_bindings.cpp | 4 + src/map/lua/sol_bindings.h | 4 + src/map/packet_system.cpp | 10 +- src/map/party.cpp | 46 +++---- src/map/treasure_pool.cpp | 188 +++++++++++++------------- src/map/treasure_pool.h | 59 +++++---- src/map/utils/charutils.cpp | 2 +- src/map/zone.cpp | 16 +-- src/map/zone_entities.cpp | 2 +- 22 files changed, 650 insertions(+), 159 deletions(-) create mode 100644 scripts/commands/getpool.lua create mode 100644 scripts/enum/treasure_pool.lua create mode 100644 scripts/specs/core/CTreasurePool.lua create mode 100644 src/map/lua/lua_treasure_pool.cpp create mode 100644 src/map/lua/lua_treasure_pool.h diff --git a/scripts/commands/getpool.lua b/scripts/commands/getpool.lua new file mode 100644 index 00000000000..43ecf97d9cc --- /dev/null +++ b/scripts/commands/getpool.lua @@ -0,0 +1,82 @@ +----------------------------------- +-- func: getpool +-- desc: prints the treasure pool of the current target. +----------------------------------- +---@type TCommand +local commandObj = {} + +commandObj.cmdprops = +{ + permission = 3, + parameters = '' +} + +local function getItemNameById(id) + for name, value in pairs(xi.item) do + if value == id then + return name + end + end + + return id +end + +local function getPoolTypeById(id) + for name, value in pairs(xi.treasurePool) do + if value == id then + return name + end + end + + return id +end + +local function printPool(player, target, treasurePool) + local itemsInPool = treasurePool:getItems() + local members = treasurePool:getMembers() + player:printToPlayer( + string.format('%s\'s Treasure Pool (%s)', target:getName(), getPoolTypeById(treasurePool:getType())), xi.msg.channel.SYSTEM_3) + player:printToPlayer( + string.format('%d/%d member(s)', #members, treasurePool:getType()), xi.msg.channel.SYSTEM_3) + for _, member in pairs(members) do + player:printToPlayer( + string.format(' %s (%d)', member:getName(), member:getID()), xi.msg.channel.SYSTEM_3) + end + + for _, item in pairs(itemsInPool) do + if item.id ~= 0 then + local lotters = item.lotters + player:printToPlayer( + string.format('Slot_%d = %s', item.slotId, getItemNameById(item.id), #lotters), xi.msg.channel.SYSTEM_3) + if #lotters == 0 then + player:printToPlayer( + ' No lots', xi.msg.channel.SYSTEM_3) + else + for _, lotter in pairs(lotters) do + player:printToPlayer( + string.format(' %s -> %d', lotter.member:getName(), lotter.lot), xi.msg.channel.SYSTEM_3) + end + end + end + end +end + +local function error(player, msg) + player:printToPlayer(msg) + player:printToPlayer('!getpool') +end + +commandObj.onTrigger = function(player) + local target = player:getCursorTarget() + if target == nil then + target = player + elseif target:isNPC() then + error(player, 'Current target is an NPC.') + return + end + + local treasurePool = target:getTreasurePool() + printPool(player, target, treasurePool) +end + +return commandObj diff --git a/scripts/enum/treasure_pool.lua b/scripts/enum/treasure_pool.lua new file mode 100644 index 00000000000..26363e911bb --- /dev/null +++ b/scripts/enum/treasure_pool.lua @@ -0,0 +1,14 @@ +----------------------------------- +-- Treasure Pool +----------------------------------- +xi = xi or {} + +---@enum xi.treasurePool +xi.treasurePool = +{ + -- Keep synced with TreasurePoolType + SOLO = 1, + PARTY = 6, + ALLIANCE = 18, + ZONE = 128, +} diff --git a/scripts/specs/core/CBaseEntity.lua b/scripts/specs/core/CBaseEntity.lua index 825a0be0768..15e3cdc62a7 100644 --- a/scripts/specs/core/CBaseEntity.lua +++ b/scripts/specs/core/CBaseEntity.lua @@ -3937,6 +3937,11 @@ end function CBaseEntity:addTreasure(itemID, arg1, arg2) end +---@nodiscard +---@return CTreasurePool? +function CBaseEntity:getTreasurePool() +end + ---@nodiscard ---@return integer function CBaseEntity:getStealItem() diff --git a/scripts/specs/core/CTreasurePool.lua b/scripts/specs/core/CTreasurePool.lua new file mode 100644 index 00000000000..a0a44250763 --- /dev/null +++ b/scripts/specs/core/CTreasurePool.lua @@ -0,0 +1,55 @@ +---@meta + +-- luacheck: ignore 241 +---@class CTreasurePool +local CTreasurePool = {} + +---@nodiscard +---@return xi.treasurePool +function CTreasurePool:getType() +end + +---@nodiscard +---@return nil +function CTreasurePool:flush() +end + +---@nodiscard +---@param PEntity CBaseEntity? +---@return nil +function CTreasurePool:addMember(PEntity) +end + +---@nodiscard +---@param PEntity CBaseEntity? +---@return nil +function CTreasurePool:delMember(PEntity) +end + +---@nodiscard +---@param PEntity CBaseEntity? +---@return nil +function CTreasurePool:update(PEntity) +end + +---@nodiscard +---@param ItemID integer +---@param PEntity CBaseEntity? +---@return integer +function CTreasurePool:addItem(ItemID, PEntity) +end + +---@nodiscard +---@return integer +function CTreasurePool:memberCount() +end + +---@nodiscard +---@return table +function CTreasurePool:getMembers() +end + +---@nodiscard +---@return table +function CTreasurePool:getItems() +end diff --git a/src/map/alliance.cpp b/src/map/alliance.cpp index bb2c48f41ed..9de677f742d 100644 --- a/src/map/alliance.cpp +++ b/src/map/alliance.cpp @@ -206,9 +206,9 @@ void CAlliance::delParty(CParty* party) for (auto* entry : party->members) { auto* member = dynamic_cast(entry); - if (member != nullptr && member->PTreasurePool != nullptr && member->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) + if (member != nullptr && member->PTreasurePool != nullptr && member->PTreasurePool->getPoolType() != TreasurePoolType::Zone) { - member->PTreasurePool->DelMember(member); + member->PTreasurePool->delMember(member); } } diff --git a/src/map/entities/charentity.cpp b/src/map/entities/charentity.cpp index e6ed9162379..75be74275be 100644 --- a/src/map/entities/charentity.cpp +++ b/src/map/entities/charentity.cpp @@ -278,7 +278,7 @@ CCharEntity::~CCharEntity() if (PTreasurePool != nullptr) { // remove myself - PTreasurePool->DelMember(this); + PTreasurePool->delMember(this); } ClearTrusts(); // trusts don't survive zone lines diff --git a/src/map/entities/mobentity.cpp b/src/map/entities/mobentity.cpp index 932340d317e..263f79936ed 100644 --- a/src/map/entities/mobentity.cpp +++ b/src/map/entities/mobentity.cpp @@ -43,6 +43,7 @@ #include "packets/action.h" #include "packets/entity_update.h" #include "packets/pet_sync.h" +#include "recast_container.h" #include "roe.h" #include "status_effect_container.h" #include "treasure_pool.h" @@ -688,10 +689,57 @@ void CMobEntity::DropItems(CCharEntity* PChar) // Adds an item to the treasure pool. Treasure pool will automatically kick out items if the pool is full (prioritizing non rare non ex items) auto AddItemToPool = [this, PChar](uint16 ItemID) { - PChar->PTreasurePool->AddItem(ItemID, this); + PChar->PTreasurePool->addItem(ItemID, this); PAI->EventHandler.triggerListener("TREASUREPOOL", CLuaBaseEntity(this), CLuaBaseEntity(PChar), ItemID); }; + auto CanAddSeal = [PChar]() + { + const auto PParty = PChar->PParty; + + if (!PParty || !PChar->PTreasurePool) + { + return !PChar->PRecastContainer->Has(RECAST_LOOT, 1); + } + + for (const auto& member : PChar->PTreasurePool->getMembers()) + { + if (member->PParty == PParty) + { + if (member->PRecastContainer->Has(RECAST_LOOT, 1)) + { + return false; + } + } + } + + return true; + }; + + // Seals are limited to one every 5 minutes per party. + // Cooldown is applied to members (in zone) of the party that delivered the killing blow. + // Note that the following has been verified to be retail accurate: + // - Other alliance parties are NOT included in that cooldown. + // - The cooldown does reset when zoning. + auto AddSealRecast = [PChar]() + { + const auto PParty = PChar->PParty; + + if (!PParty || !PChar->PTreasurePool) + { + PChar->PRecastContainer->Add(RECAST_LOOT, 1, 300); + return; + } + + for (const auto& member : PChar->PTreasurePool->getMembers()) + { + if (member->PParty == PParty) + { + member->PRecastContainer->Add(RECAST_LOOT, 1, 300); + } + } + }; + DropList_t* dropList = itemutils::GetDropList(m_DropID); if (!getMobMod(MOBMOD_NO_DROPS) && dropList != nullptr && (!dropList->Items.empty() || !dropList->Groups.empty() || PAI->EventHandler.hasListener("ITEM_DROPS"))) @@ -769,7 +817,7 @@ void CMobEntity::DropItems(CCharEntity* PChar) >= 75 = Kindred Crests ID=2955 >= 90 = High Kindred Crests ID=2956 */ - if (xirand::GetRandomNumber(100) < 20 && PChar->PTreasurePool->CanAddSeal()) + if (xirand::GetRandomNumber(100) < 20 && CanAddSeal()) { // RULES: Only 1 kind may drop per mob if (GetMLevel() >= 75 && luautils::IsContentEnabled("ABYSSEA")) // all 4 types @@ -789,6 +837,8 @@ void CMobEntity::DropItems(CCharEntity* PChar) AddItemToPool(2956); break; } + + AddSealRecast(); } else if (GetMLevel() >= 70 && luautils::IsContentEnabled("ABYSSEA")) // b.seal & k.seal & k.crest { diff --git a/src/map/lua/CMakeLists.txt b/src/map/lua/CMakeLists.txt index 326b581304a..31a84963c3c 100644 --- a/src/map/lua/CMakeLists.txt +++ b/src/map/lua/CMakeLists.txt @@ -25,6 +25,8 @@ set(LUA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/lua_statuseffect.h ${CMAKE_CURRENT_SOURCE_DIR}/lua_trade_container.cpp ${CMAKE_CURRENT_SOURCE_DIR}/lua_trade_container.h + ${CMAKE_CURRENT_SOURCE_DIR}/lua_treasure_pool.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/lua_treasure_pool.h ${CMAKE_CURRENT_SOURCE_DIR}/lua_trigger_area.cpp ${CMAKE_CURRENT_SOURCE_DIR}/lua_trigger_area.h ${CMAKE_CURRENT_SOURCE_DIR}/lua_zone.cpp diff --git a/src/map/lua/lua_baseentity.cpp b/src/map/lua/lua_baseentity.cpp index ac0a6c647ac..8dc6b43ecda 100644 --- a/src/map/lua/lua_baseentity.cpp +++ b/src/map/lua/lua_baseentity.cpp @@ -18168,6 +18168,23 @@ void CLuaBaseEntity::addTreasure(uint16 itemID, sol::object const& arg1, sol::ob } } +/************************************************************************ + * Function: getTreasurePool() + * Purpose : Returns PC treasure pool + * Example : player:getTreasurePool() + * Notes : + ************************************************************************/ + +auto CLuaBaseEntity::getTreasurePool() -> CTreasurePool* +{ + if (const auto PChar = dynamic_cast(m_PBaseEntity)) + { + return PChar->PTreasurePool; + } + + return nullptr; +} + /************************************************************************ * Function: getStealItem() * Purpose : Used to return the Item ID of a mob's item which can be stolen @@ -19697,6 +19714,7 @@ void CLuaBaseEntity::Register() SOL_REGISTER("getDropID", CLuaBaseEntity::getDropID); SOL_REGISTER("setDropID", CLuaBaseEntity::setDropID); SOL_REGISTER("addTreasure", CLuaBaseEntity::addTreasure); + SOL_REGISTER("getTreasurePool", CLuaBaseEntity::getTreasurePool); SOL_REGISTER("getStealItem", CLuaBaseEntity::getStealItem); SOL_REGISTER("getDespoilItem", CLuaBaseEntity::getDespoilItem); SOL_REGISTER("getDespoilDebuff", CLuaBaseEntity::getDespoilDebuff); diff --git a/src/map/lua/lua_baseentity.h b/src/map/lua/lua_baseentity.h index efd53191fc3..30a6e053040 100644 --- a/src/map/lua/lua_baseentity.h +++ b/src/map/lua/lua_baseentity.h @@ -903,6 +903,7 @@ class CLuaBaseEntity uint32 getDropID(); void setDropID(uint32 dropID); void addTreasure(uint16 itemID, sol::object const& arg1, sol::object const& arg2); + auto getTreasurePool() -> CTreasurePool*; uint16 getStealItem(); uint16 getDespoilItem(); // gets ItemID of droplist despoil item from mob (steal item if no despoil item) uint16 getDespoilDebuff(uint16 itemID); // gets the status effect id to apply to the mob on successful despoil diff --git a/src/map/lua/lua_treasure_pool.cpp b/src/map/lua/lua_treasure_pool.cpp new file mode 100644 index 00000000000..9f2cf657822 --- /dev/null +++ b/src/map/lua/lua_treasure_pool.cpp @@ -0,0 +1,191 @@ +/* +=========================================================================== + + Copyright (c) 2025 LandSandBoat Dev Teams + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#include "lua_treasure_pool.h" + +#include "treasure_pool.h" +#include "utils/zoneutils.h" + +CLuaTreasurePool::CLuaTreasurePool(CTreasurePool* PTreasurePool) +: m_PLuaTreasurePool(PTreasurePool) +{ +} + +/************************************************************************ + * Function: getType() + * Purpose : Returns the type of the Treasure Pool + * Example : pool:getType() + * Notes : See xi.treasurePool enum + ************************************************************************/ +auto CLuaTreasurePool::getType() const -> TreasurePoolType +{ + return m_PLuaTreasurePool->getPoolType(); +} + +/************************************************************************ + * Function: flush() + * Purpose : Forcibly flushes the treasure pool, as if all items timers expired + * Example : pool:flush() + * Notes : + ************************************************************************/ +void CLuaTreasurePool::flush() const +{ + m_PLuaTreasurePool->flush(); +} + +/************************************************************************ + * Function: addMember() + * Purpose : Adds a PC to the treasure pool + * Example : pool:addMember(target) + * Notes : + ************************************************************************/ +void CLuaTreasurePool::addMember(CBaseEntity* PEntity) const +{ + if (const auto PChar = dynamic_cast(PEntity)) + { + m_PLuaTreasurePool->addMember(PChar); + } +} + +/************************************************************************ + * Function: delMember() + * Purpose : Removes a PC from the treasure pool + * Example : pool:delMember(target) + * Notes : + ************************************************************************/ +void CLuaTreasurePool::delMember(CBaseEntity* PEntity) const +{ + if (const auto PChar = dynamic_cast(PEntity)) + { + m_PLuaTreasurePool->delMember(PChar); + } +} + +/************************************************************************ + * Function: update() + * Purpose : Force refreshes the treasure pool content for a PC + * Example : pool:update(target) + * Notes : + ************************************************************************/ +void CLuaTreasurePool::update(CBaseEntity* PEntity) const +{ + if (const auto PChar = dynamic_cast(PEntity)) + { + m_PLuaTreasurePool->updatePool(PChar); + } +} + +/************************************************************************ + * Function: addItem() + * Purpose : Adds an item to the treasure pool + * Example : pool:addItem(xi.item.RIDILL) + * Notes : The entity can be either a NPC, a mob or nullptr. + ************************************************************************/ +auto CLuaTreasurePool::addItem(const uint16 ItemID, CBaseEntity* PEntity) const -> uint8 +{ + return m_PLuaTreasurePool->addItem(ItemID, PEntity); +} + +/************************************************************************ + * Function: memberCount() + * Purpose : Returns the number of members in the treasure pool + * Example : pool:memberCount() + * Notes : + ************************************************************************/ +auto CLuaTreasurePool::memberCount() const -> size_t +{ + return m_PLuaTreasurePool->memberCount(); +} + +/************************************************************************ + * Function: getMembers() + * Purpose : Returns all members present in the pool. + * Example : pool:getMembers() + * Notes : + ************************************************************************/ +auto CLuaTreasurePool::getMembers() const -> sol::table +{ + sol::table result = lua.create_table(); + uint8 index = 1; + + for (const auto& member : m_PLuaTreasurePool->getMembers()) + { + result[index++] = member; + } + + return result; +} + +/************************************************************************ + * Function: getItems() + * Purpose : Returns all items present in the pool, along with their lotters + * Example : pool:getItems() + * Notes : id of 0 means no item present in the given slot. + * { + * { id = 1, slotId = 0, timestamp = 0, Lotters = { { member = {...}, lot = 0 } } }, + * [...] + * } + ************************************************************************/ +auto CLuaTreasurePool::getItems() const -> sol::table +{ + sol::table result = lua.create_table(); + uint8 index = 1; + + for (const auto& item : m_PLuaTreasurePool->getItems()) + { + sol::table itemRow = lua.create_table(); + itemRow["id"] = item.ID; + itemRow["slotId"] = item.SlotID; + itemRow["timestamp"] = item.TimeStamp.time_since_epoch().count(); + + sol::table lotters = lua.create_table(); + int lotterIndex = 1; + + for (const auto& lotter : item.Lotters) + { + sol::table lotterRow = lua.create_table(); + lotterRow["member"] = lotter.member; + lotterRow["lot"] = lotter.lot; + lotters[lotterIndex++] = lotterRow; + } + + itemRow["lotters"] = lotters; + result[index++] = itemRow; + } + + return result; +} + +//==========================================================// + +void CLuaTreasurePool::Register() +{ + SOL_USERTYPE("CTreasurePool", CLuaTreasurePool); + SOL_REGISTER("getType", CLuaTreasurePool::getType); + SOL_REGISTER("flush", CLuaTreasurePool::flush); + SOL_REGISTER("addMember", CLuaTreasurePool::addMember); + SOL_REGISTER("delMember", CLuaTreasurePool::delMember); + SOL_REGISTER("updatePool", CLuaTreasurePool::update); + SOL_REGISTER("addItem", CLuaTreasurePool::addItem); + SOL_REGISTER("memberCount", CLuaTreasurePool::memberCount); + SOL_REGISTER("getMembers", CLuaTreasurePool::getMembers); + SOL_REGISTER("getItems", CLuaTreasurePool::getItems); +} diff --git a/src/map/lua/lua_treasure_pool.h b/src/map/lua/lua_treasure_pool.h new file mode 100644 index 00000000000..712ee215a23 --- /dev/null +++ b/src/map/lua/lua_treasure_pool.h @@ -0,0 +1,47 @@ +/* +=========================================================================== + + Copyright (c) 2025 LandSandBoat Dev Teams + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include "common/cbasetypes.h" +#include "luautils.h" + +enum class TreasurePoolType : uint8; +class CTreasurePool; +class CLuaTreasurePool +{ + CTreasurePool* m_PLuaTreasurePool; + +public: + CLuaTreasurePool(CTreasurePool* PTreasurePool); + + auto getType() const -> TreasurePoolType; + void flush() const; + void addMember(CBaseEntity* PEntity) const; + void delMember(CBaseEntity* PEntity) const; + void update(CBaseEntity* PEntity) const; + auto addItem(uint16 ItemID, CBaseEntity* PEntity) const -> uint8; + auto memberCount() const -> size_t; + auto getItems() const -> sol::table; + auto getMembers() const -> sol::table; + + static void Register(); +}; diff --git a/src/map/lua/luautils.cpp b/src/map/lua/luautils.cpp index 820eb021521..598cdf78c5e 100644 --- a/src/map/lua/luautils.cpp +++ b/src/map/lua/luautils.cpp @@ -45,6 +45,7 @@ #include "lua_spell.h" #include "lua_statuseffect.h" #include "lua_trade_container.h" +#include "lua_treasure_pool.h" #include "lua_trigger_area.h" #include "lua_zone.h" @@ -92,6 +93,7 @@ #include "timetriggers.h" #include "trade_container.h" #include "transport.h" +#include "treasure_pool.h" #include "weapon_skill.h" #include "zone.h" #include "zone_entities.h" @@ -356,6 +358,7 @@ namespace luautils CLuaSpell::Register(); CLuaStatusEffect::Register(); CLuaTradeContainer::Register(); + CLuaTreasurePool::Register(); CLuaZone::Register(); CLuaItem::Register(); diff --git a/src/map/lua/sol_bindings.cpp b/src/map/lua/sol_bindings.cpp index 5c32ae45462..3bb4e7072b4 100644 --- a/src/map/lua/sol_bindings.cpp +++ b/src/map/lua/sol_bindings.cpp @@ -121,4 +121,8 @@ SOL_BIND_DEF(CLuaTriggerArea, ITriggerArea); #include "zone.h" #include "lua_zone.h" SOL_BIND_DEF(CLuaZone, CZone); + +#include "treasure_pool.h" +#include "lua_treasure_pool.h" +SOL_BIND_DEF(CLuaTreasurePool, CTreasurePool); // clang-format on diff --git a/src/map/lua/sol_bindings.h b/src/map/lua/sol_bindings.h index e59ddf5ea91..6bb63dbd633 100644 --- a/src/map/lua/sol_bindings.h +++ b/src/map/lua/sol_bindings.h @@ -155,3 +155,7 @@ SOL_BIND_DEC(CLuaTriggerArea, ITriggerArea); class CLuaZone; class CZone; SOL_BIND_DEC(CLuaZone, CZone); + +class CLuaTreasurePool; +class CTreasurePool; +SOL_BIND_DEC(CLuaTreasurePool, CTreasurePool); diff --git a/src/map/packet_system.cpp b/src/map/packet_system.cpp index c28f97ec621..0df90f0a443 100644 --- a/src/map/packet_system.cpp +++ b/src/map/packet_system.cpp @@ -447,7 +447,7 @@ void SmallPacket0x00C(map_session_data_t* const PSession, CCharEntity* const PCh // TODO: While in mog house; treasure pool is not created. if (PChar->PTreasurePool != nullptr) { - PChar->PTreasurePool->UpdatePool(PChar); + PChar->PTreasurePool->updatePool(PChar); } PChar->loc.zone->SpawnTransport(PChar); @@ -2251,9 +2251,9 @@ void SmallPacket0x041(map_session_data_t* const PSession, CCharEntity* const PCh if (PChar->PTreasurePool != nullptr) { - if (!PChar->PTreasurePool->HasLottedItem(PChar, SlotID)) + if (!PChar->PTreasurePool->hasLottedItem(PChar, SlotID)) { - PChar->PTreasurePool->LotItem(PChar, SlotID, xirand::GetRandomNumber(1, 1000)); // 1 ~ 998+1 + PChar->PTreasurePool->lotItem(PChar, SlotID, xirand::GetRandomNumber(1, 1000)); // 1 ~ 998+1 } } } @@ -2278,9 +2278,9 @@ void SmallPacket0x042(map_session_data_t* const PSession, CCharEntity* const PCh if (PChar->PTreasurePool != nullptr) { - if (!PChar->PTreasurePool->HasPassedItem(PChar, SlotID)) + if (!PChar->PTreasurePool->hasPassedItem(PChar, SlotID)) { - PChar->PTreasurePool->PassItem(PChar, SlotID); + PChar->PTreasurePool->passItem(PChar, SlotID); } } } diff --git a/src/map/party.cpp b/src/map/party.cpp index bd8408c001f..f8801649e64 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -140,12 +140,12 @@ void CParty::DisbandParty(bool playerInitiated) // TODO: TreasurePool should stay with the last character, but now it is not critical - if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) + if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->getPoolType() != TreasurePoolType::Zone) { - PChar->PTreasurePool->DelMember(PChar); - PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); - PChar->PTreasurePool->AddMember(PChar); - PChar->PTreasurePool->UpdatePool(PChar); + PChar->PTreasurePool->delMember(PChar); + PChar->PTreasurePool = new CTreasurePool(TreasurePoolType::Solo); + PChar->PTreasurePool->addMember(PChar); + PChar->PTreasurePool->updatePool(PChar); } CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) @@ -364,12 +364,12 @@ void CParty::RemoveMember(CBattleEntity* PEntity) }); } - if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) + if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->getPoolType() != TreasurePoolType::Zone) { - PChar->PTreasurePool->DelMember(PChar); - PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); - PChar->PTreasurePool->AddMember(PChar); - PChar->PTreasurePool->UpdatePool(PChar); + PChar->PTreasurePool->delMember(PChar); + PChar->PTreasurePool = new CTreasurePool(TreasurePoolType::Solo); + PChar->PTreasurePool->addMember(PChar); + PChar->PTreasurePool->updatePool(PChar); } } @@ -440,12 +440,12 @@ void CParty::DelMember(CBattleEntity* PEntity) PChar->pushPacket(PChar); PChar->PParty = nullptr; - if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) + if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->getPoolType() != TreasurePoolType::Zone) { - PChar->PTreasurePool->DelMember(PChar); - PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); - PChar->PTreasurePool->AddMember(PChar); - PChar->PTreasurePool->UpdatePool(PChar); + PChar->PTreasurePool->delMember(PChar); + PChar->PTreasurePool = new CTreasurePool(TreasurePoolType::Solo); + PChar->PTreasurePool->addMember(PChar); + PChar->PTreasurePool->updatePool(PChar); } } else @@ -644,7 +644,7 @@ void CParty::AddMember(CBattleEntity* PEntity) PChar->pushPacket(PChar); } - PChar->PTreasurePool->UpdatePool(PChar); + PChar->PTreasurePool->updatePool(PChar); // Apply level sync if the party is level synced if (m_PSyncTarget != nullptr) @@ -969,7 +969,7 @@ void CParty::ReloadTreasurePool(CCharEntity* PChar) return; } - if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->GetPoolType() == TREASUREPOOL_ZONE) + if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->getPoolType() == TreasurePoolType::Zone) { return; } @@ -989,10 +989,10 @@ void CParty::ReloadTreasurePool(CCharEntity* PChar) { if (PChar->PTreasurePool != nullptr) { - PChar->PTreasurePool->DelMember(PChar); + PChar->PTreasurePool->delMember(PChar); } PChar->PTreasurePool = PPartyMember->PTreasurePool; - PChar->PTreasurePool->AddMember(PChar); + PChar->PTreasurePool->addMember(PChar); return; } } @@ -1009,10 +1009,10 @@ void CParty::ReloadTreasurePool(CCharEntity* PChar) { if (PChar->PTreasurePool != nullptr) { - PChar->PTreasurePool->DelMember(PChar); + PChar->PTreasurePool->delMember(PChar); } PChar->PTreasurePool = PPartyMember->PTreasurePool; - PChar->PTreasurePool->AddMember(PChar); + PChar->PTreasurePool->addMember(PChar); return; } } @@ -1021,8 +1021,8 @@ void CParty::ReloadTreasurePool(CCharEntity* PChar) if (PChar->PTreasurePool == nullptr) { - PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); - PChar->PTreasurePool->AddMember(PChar); + PChar->PTreasurePool = new CTreasurePool(TreasurePoolType::Solo); + PChar->PTreasurePool->addMember(PChar); } } diff --git a/src/map/treasure_pool.cpp b/src/map/treasure_pool.cpp index 61024483921..ab6e2e504ed 100644 --- a/src/map/treasure_pool.cpp +++ b/src/map/treasure_pool.cpp @@ -1,7 +1,7 @@ /* =========================================================================== - Copyright (c) 2010-2015 Darkstar Dev Teams + Copyright (c) 2025 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ static constexpr duration treasure_checktime = 3s; static constexpr duration treasure_livetime = 5min; -CTreasurePool::CTreasurePool(TREASUREPOOLTYPE PoolType) +CTreasurePool::CTreasurePool(const TreasurePoolType PoolType) : m_count(0) , m_TreasurePoolType(PoolType) { @@ -44,15 +44,41 @@ CTreasurePool::CTreasurePool(TREASUREPOOLTYPE PoolType) m_PoolItems[i].ID = 0; m_PoolItems[i].SlotID = i; } - members.reserve(PoolType); + + m_Members.reserve(static_cast(PoolType)); } -TREASUREPOOLTYPE CTreasurePool::GetPoolType() +auto CTreasurePool::getPoolType() const -> TreasurePoolType { return m_TreasurePoolType; } -void CTreasurePool::AddMember(CCharEntity* PChar) +auto CTreasurePool::getItems() const -> const std::array& +{ + return m_PoolItems; +} + +auto CTreasurePool::itemCount() const -> uint8 +{ + return m_count; +} + +auto CTreasurePool::getMembers() const -> const std::vector& +{ + return m_Members; +} + +auto CTreasurePool::memberCount() const -> size_t +{ + return m_Members.size(); +} + +bool CTreasurePool::isMember(const CCharEntity* PChar) +{ + return std::find(m_Members.begin(), m_Members.end(), PChar) != m_Members.end(); +} + +void CTreasurePool::addMember(CCharEntity* PChar) { if (PChar == nullptr || PChar->PTreasurePool != this) { @@ -60,25 +86,27 @@ void CTreasurePool::AddMember(CCharEntity* PChar) return; } - if (std::find(members.begin(), members.end(), PChar) != members.end()) + if (std::find(m_Members.begin(), m_Members.end(), PChar) != m_Members.end()) { ShowWarning("CTreasurePool::AddMember() - PChar was already in the members list!"); return; } - members.emplace_back(PChar); + m_Members.emplace_back(PChar); - if (m_TreasurePoolType == TREASUREPOOL_SOLO && members.size() > 1) + if (m_TreasurePoolType == TreasurePoolType::Solo && PChar->PParty) { - m_TreasurePoolType = TREASUREPOOL_PARTY; + m_TreasurePoolType = TreasurePoolType::Party; } - else if (m_TreasurePoolType == TREASUREPOOL_PARTY && members.size() > 6) + else if (m_TreasurePoolType == TreasurePoolType::Party && PChar->PParty && PChar->PParty->m_PAlliance) { - m_TreasurePoolType = TREASUREPOOL_ALLIANCE; + m_TreasurePoolType = TreasurePoolType::Alliance; } + + updatePool(PChar); } -void CTreasurePool::DelMember(CCharEntity* PChar) +void CTreasurePool::delMember(CCharEntity* PChar) { if (PChar == nullptr || PChar->PTreasurePool != this) { @@ -97,30 +125,29 @@ void CTreasurePool::DelMember(CCharEntity* PChar) while (lotterIterator != m_PoolItems[i].Lotters.end()) { // remove their lot info - LotInfo* info = &(*lotterIterator); - if (PChar->id == info->member->id) + if (LotInfo* info = &(*lotterIterator); PChar->id == info->member->id) { lotterIterator = m_PoolItems[i].Lotters.erase(lotterIterator); continue; } - lotterIterator++; + ++lotterIterator; } } } - auto memberToDelete = std::find(members.begin(), members.end(), PChar); - if (memberToDelete != members.end()) + auto memberToDelete = std::find(m_Members.begin(), m_Members.end(), PChar); + if (memberToDelete != m_Members.end()) { PChar->PTreasurePool = nullptr; - members.erase(memberToDelete); + m_Members.erase(memberToDelete); } - if ((m_TreasurePoolType == TREASUREPOOL_PARTY || m_TreasurePoolType == TREASUREPOOL_ALLIANCE) && members.size() == 1) + if ((m_TreasurePoolType == TreasurePoolType::Party || m_TreasurePoolType == TreasurePoolType::Alliance) && memberCount() == 1) { - m_TreasurePoolType = TREASUREPOOL_SOLO; + m_TreasurePoolType = TreasurePoolType::Solo; } - if (m_TreasurePoolType != TREASUREPOOL_ZONE && members.empty()) + if (m_TreasurePoolType != TreasurePoolType::Zone && memberCount() == 0) { // TODO: This entire system needs rewriting to both: // : - Make it stable @@ -136,7 +163,7 @@ void CTreasurePool::DelMember(CCharEntity* PChar) * * ************************************************************************/ -uint8 CTreasurePool::AddItem(uint16 ItemID, CBaseEntity* PEntity) +uint8 CTreasurePool::addItem(uint16 ItemID, CBaseEntity* PEntity) { uint8 SlotID = 0; uint8 FreeSlotID = -1; @@ -153,7 +180,7 @@ uint8 CTreasurePool::AddItem(uint16 ItemID, CBaseEntity* PEntity) { bool doesNotHaveRareItem = false; - for (const auto& member : members) + for (const auto& member : m_Members) { // Someone doesn't have the rare item if (!charutils::HasItem(member, PNewItem->getID())) @@ -170,19 +197,6 @@ uint8 CTreasurePool::AddItem(uint16 ItemID, CBaseEntity* PEntity) } } - switch (ItemID) - { - case 1126: // beastmen seal - case 1127: // kindred seal - case 2955: // kindred crest - case 2956: // high kindred crest - for (auto& member : members) - { - member->PRecastContainer->Add(RECAST_LOOT, 1, 300); // 300 = 5 min cooldown - } - break; - } - for (SlotID = 0; SlotID < 10; ++SlotID) { if (m_PoolItems[SlotID].ID == 0) @@ -241,27 +255,27 @@ uint8 CTreasurePool::AddItem(uint16 ItemID, CBaseEntity* PEntity) if (SlotID == 10) { m_PoolItems[FreeSlotID].TimeStamp = get_server_start_time(); - CheckTreasureItem(server_clock::now(), FreeSlotID); + checkTreasureItem(server_clock::now(), FreeSlotID); } m_count++; m_PoolItems[FreeSlotID].ID = ItemID; m_PoolItems[FreeSlotID].TimeStamp = server_clock::now() - treasure_checktime; - for (auto& member : members) + for (const auto& member : m_Members) { member->pushPacket(&m_PoolItems[FreeSlotID], PEntity, false); } - if (m_TreasurePoolType == TREASUREPOOL_SOLO) + if (memberCount() == 1) { - CheckTreasureItem(server_clock::now(), FreeSlotID); + checkTreasureItem(server_clock::now(), FreeSlotID); } return m_count; } -void CTreasurePool::UpdatePool(CCharEntity* PChar) +void CTreasurePool::updatePool(CCharEntity* PChar) { if (PChar == nullptr || PChar->PTreasurePool != this) { @@ -278,13 +292,26 @@ void CTreasurePool::UpdatePool(CCharEntity* PChar) } } +void CTreasurePool::flush() +{ + if (m_count != 0) + { + const auto tick = server_clock::now() + treasure_checktime + std::chrono::seconds(1); + + for (uint8 i = 0; i < TREASUREPOOL_SIZE; ++i) + { + checkTreasureItem(tick, i); + } + } +} + /************************************************************************ * * * Character refuses/votes for item in treasure pool * * * ************************************************************************/ -void CTreasurePool::LotItem(CCharEntity* PChar, uint8 SlotID, uint16 Lot) +void CTreasurePool::lotItem(CCharEntity* PChar, uint8 SlotID, uint16 Lot) { if (PChar == nullptr || PChar->PTreasurePool != this) { @@ -337,19 +364,19 @@ void CTreasurePool::LotItem(CCharEntity* PChar, uint8 SlotID, uint16 Lot) } // Player lots Item for XXX message - for (auto& member : members) + for (const auto& member : m_Members) { member->pushPacket(highestLotter, highestLot, PChar, SlotID, Lot); } // if all lotters have lotted, evaluate immediately. - if (m_PoolItems[SlotID].Lotters.size() == members.size()) + if (m_PoolItems[SlotID].Lotters.size() == memberCount()) { - CheckTreasureItem(m_Tick, SlotID); + checkTreasureItem(m_Tick, SlotID); } } -void CTreasurePool::PassItem(CCharEntity* PChar, uint8 SlotID) +void CTreasurePool::passItem(CCharEntity* PChar, uint8 SlotID) { if (PChar == nullptr || PChar->PTreasurePool != this) { @@ -397,28 +424,26 @@ void CTreasurePool::PassItem(CCharEntity* PChar, uint8 SlotID) uint16 PassedLot = 65535; // passed mask is FF FF // Player lots Item for XXX message - for (auto& member : members) + for (const auto& member : m_Members) { member->pushPacket(highestLotter, highestLot, PChar, SlotID, PassedLot); } // if all lotters have lotted, evaluate immediately. - if (m_PoolItems[SlotID].Lotters.size() == members.size()) + if (m_PoolItems[SlotID].Lotters.size() == memberCount()) { - CheckTreasureItem(m_Tick, SlotID); + checkTreasureItem(m_Tick, SlotID); } } -bool CTreasurePool::HasLottedItem(CCharEntity* PChar, uint8 SlotID) +bool CTreasurePool::hasLottedItem(CCharEntity* PChar, uint8 SlotID) { if (SlotID >= TREASUREPOOL_SIZE) { return false; } - std::vector lotters = m_PoolItems[SlotID].Lotters; - - for (auto& lotter : lotters) + for (const auto& lotter : m_PoolItems[SlotID].Lotters) { if (lotter.member->id == PChar->id) { @@ -429,16 +454,14 @@ bool CTreasurePool::HasLottedItem(CCharEntity* PChar, uint8 SlotID) return false; } -bool CTreasurePool::HasPassedItem(CCharEntity* PChar, uint8 SlotID) +bool CTreasurePool::hasPassedItem(CCharEntity* PChar, uint8 SlotID) { if (SlotID >= TREASUREPOOL_SIZE) { return false; } - std::vector lotters = m_PoolItems[SlotID].Lotters; - - for (auto& lotter : lotters) + for (auto& lotter : m_PoolItems[SlotID].Lotters) { if (lotter.member->id == PChar->id) { @@ -449,7 +472,7 @@ bool CTreasurePool::HasPassedItem(CCharEntity* PChar, uint8 SlotID) return false; } -void CTreasurePool::CheckItems(time_point tick) +void CTreasurePool::checkItems(time_point tick) { if (m_count != 0) { @@ -457,14 +480,14 @@ void CTreasurePool::CheckItems(time_point tick) { for (uint8 i = 0; i < TREASUREPOOL_SIZE; ++i) { - CheckTreasureItem(tick, i); + checkTreasureItem(tick, i); } m_Tick = tick; } } } -void CTreasurePool::CheckTreasureItem(time_point tick, uint8 SlotID) +void CTreasurePool::checkTreasureItem(time_point tick, uint8 SlotID) { if (m_PoolItems[SlotID].ID == 0) { @@ -472,8 +495,8 @@ void CTreasurePool::CheckTreasureItem(time_point tick, uint8 SlotID) } if ((tick - m_PoolItems[SlotID].TimeStamp) > treasure_livetime || - (m_TreasurePoolType == TREASUREPOOL_SOLO && members[0]->getStorage(LOC_INVENTORY)->GetFreeSlotsCount() != 0) || - m_PoolItems[SlotID].Lotters.size() == members.size()) + (memberCount() == 1 && m_Members[0]->getStorage(LOC_INVENTORY)->GetFreeSlotsCount() != 0) || + m_PoolItems[SlotID].Lotters.size() == memberCount()) { // Find item's highest lotter LotInfo highestInfo; @@ -494,31 +517,31 @@ void CTreasurePool::CheckTreasureItem(time_point tick, uint8 SlotID) // add item as they have room! if (charutils::AddItem(highestInfo.member, LOC_INVENTORY, m_PoolItems[SlotID].ID, 1, true) != ERROR_SLOTID) { - TreasureWon(highestInfo.member, SlotID); + treasureWon(highestInfo.member, SlotID); } else { - TreasureError(highestInfo.member, SlotID); + treasureError(highestInfo.member, SlotID); } } else { // drop the item - TreasureLost(SlotID); + treasureLost(SlotID); } } else { // No one has lotted on this item - Give to random member who has not passed std::vector candidates; - for (auto& member : members) + for (auto& member : m_Members) { if (charutils::HasItem(member, m_PoolItems[SlotID].ID) && itemutils::GetItem(m_PoolItems[SlotID].ID)->getFlag() & ITEM_FLAG_RARE) { continue; } - if (member->getStorage(LOC_INVENTORY)->GetFreeSlotsCount() != 0 && !HasPassedItem(member, SlotID)) + if (member->getStorage(LOC_INVENTORY)->GetFreeSlotsCount() != 0 && !hasPassedItem(member, SlotID)) { candidates.emplace_back(member); } @@ -526,7 +549,7 @@ void CTreasurePool::CheckTreasureItem(time_point tick, uint8 SlotID) if (candidates.empty()) { - TreasureLost(SlotID); + treasureLost(SlotID); } else { @@ -534,18 +557,18 @@ void CTreasurePool::CheckTreasureItem(time_point tick, uint8 SlotID) CCharEntity* PChar = candidates.at(xirand::GetRandomNumber(candidates.size())); if (charutils::AddItem(PChar, LOC_INVENTORY, m_PoolItems[SlotID].ID, 1, true) != ERROR_SLOTID) { - TreasureWon(PChar, SlotID); + treasureWon(PChar, SlotID); } else { - TreasureError(PChar, SlotID); + treasureError(PChar, SlotID); } } } } } -void CTreasurePool::TreasureWon(CCharEntity* winner, uint8 SlotID) +void CTreasurePool::treasureWon(CCharEntity* winner, uint8 SlotID) { if (winner == nullptr || winner->PTreasurePool != this || m_PoolItems[SlotID].ID == 0) { @@ -557,7 +580,7 @@ void CTreasurePool::TreasureWon(CCharEntity* winner, uint8 SlotID) roeutils::event(ROE_EVENT::ROE_LOOTITEM, winner, RoeDatagram("itemid", m_PoolItems[SlotID].ID)); - for (auto& member : members) + for (const auto& member : m_Members) { member->pushPacket(winner, SlotID, 0, ITEMLOT_WIN); } @@ -567,7 +590,7 @@ void CTreasurePool::TreasureWon(CCharEntity* winner, uint8 SlotID) m_PoolItems[SlotID].Lotters.clear(); } -void CTreasurePool::TreasureError(CCharEntity* winner, uint8 SlotID) +void CTreasurePool::treasureError(CCharEntity* winner, uint8 SlotID) { if (winner == nullptr || winner->PTreasurePool != this || m_PoolItems[SlotID].ID == 0) { @@ -577,7 +600,7 @@ void CTreasurePool::TreasureError(CCharEntity* winner, uint8 SlotID) m_PoolItems[SlotID].TimeStamp = get_server_start_time(); - for (auto& member : members) + for (const auto& member : m_Members) { member->pushPacket(winner, SlotID, -1, ITEMLOT_WINERROR); } @@ -587,7 +610,7 @@ void CTreasurePool::TreasureError(CCharEntity* winner, uint8 SlotID) m_PoolItems[SlotID].Lotters.clear(); } -void CTreasurePool::TreasureLost(uint8 SlotID) +void CTreasurePool::treasureLost(uint8 SlotID) { if (m_PoolItems[SlotID].ID == 0) { @@ -597,7 +620,7 @@ void CTreasurePool::TreasureLost(uint8 SlotID) m_PoolItems[SlotID].TimeStamp = get_server_start_time(); - for (auto& member : members) + for (const auto& member : m_Members) { member->pushPacket(SlotID, ITEMLOT_WINERROR); } @@ -606,16 +629,3 @@ void CTreasurePool::TreasureLost(uint8 SlotID) m_PoolItems[SlotID].ID = 0; m_PoolItems[SlotID].Lotters.clear(); } - -bool CTreasurePool::CanAddSeal() -{ - for (auto& member : members) - { - if (member->PRecastContainer->Has(RECAST_LOOT, 1)) - { - return false; - } - } - - return true; -} diff --git a/src/map/treasure_pool.h b/src/map/treasure_pool.h index 96fee92ebf3..458bbbb16d2 100644 --- a/src/map/treasure_pool.h +++ b/src/map/treasure_pool.h @@ -1,7 +1,7 @@ /* =========================================================================== - Copyright (c) 2010-2015 Darkstar Dev Teams + Copyright (c) 2025 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,18 +26,20 @@ #include -enum TREASUREPOOLTYPE +// Update xi.treasurePool accordingly when making changes +enum class TreasurePoolType : uint8 { - TREASUREPOOL_SOLO = 1, - TREASUREPOOL_PARTY = 6, - TREASUREPOOL_ALLIANCE = 18, - TREASUREPOOL_ZONE = 128 + Solo = 1, + Party = 6, + Alliance = 18, + Zone = 128 }; #define TREASUREPOOL_SIZE 10 // characters get a new TreasurePool when moving between zones class CCharEntity; +class CBaseEntity; class CMobEntity; struct LotInfo @@ -70,40 +72,43 @@ struct TreasurePoolItem class CTreasurePool { public: - CTreasurePool(TREASUREPOOLTYPE PoolType); + CTreasurePool(TreasurePoolType PoolType); - TREASUREPOOLTYPE GetPoolType(); + auto getPoolType() const -> TreasurePoolType; - uint8 AddItem(uint16 ItemID, CBaseEntity*); + auto addItem(uint16 ItemID, CBaseEntity*) -> uint8; + void lotItem(CCharEntity* PChar, uint8 SlotID, uint16 Lot); + void passItem(CCharEntity* PChar, uint8 SlotID); + bool hasLottedItem(CCharEntity* PChar, uint8 SlotID); + bool hasPassedItem(CCharEntity* PChar, uint8 SlotID); + auto getItems() const -> const std::array&; + auto itemCount() const -> uint8; - void LotItem(uint8 SlotID, uint16 Lot); - void LotItem(CCharEntity* PChar, uint8 SlotID, uint16 Lot); - void PassItem(CCharEntity* PChar, uint8 SlotID); - bool HasLottedItem(CCharEntity* PChar, uint8 SlotID); - bool HasPassedItem(CCharEntity* PChar, uint8 SlotID); - void AddMember(CCharEntity* PChar); - void DelMember(CCharEntity* PChar); - void UpdatePool(CCharEntity* PChar); + void addMember(CCharEntity* PChar); + void delMember(CCharEntity* PChar); + auto getMembers() const -> const std::vector&; + bool isMember(const CCharEntity* PChar); + auto memberCount() const -> size_t; - void CheckItems(time_point); + void updatePool(CCharEntity* PChar); + void flush(); - void TreasureWon(CCharEntity* winner, uint8 SlotID); - void TreasureError(CCharEntity* winner, uint8 SlotID); - void TreasureLost(uint8 SlotID); + void checkItems(time_point); - bool CanAddSeal(); + void treasureWon(CCharEntity* winner, uint8 SlotID); + void treasureError(CCharEntity* winner, uint8 SlotID); + void treasureLost(uint8 SlotID); private: time_point m_Tick; uint8 m_count; - TREASUREPOOLTYPE m_TreasurePoolType; + TreasurePoolType m_TreasurePoolType; - void CheckTreasureItem(time_point tick, uint8 SlotID); + void checkTreasureItem(time_point tick, uint8 SlotID); - TreasurePoolItem m_PoolItems[TREASUREPOOL_SIZE]; - - std::vector members; + std::array m_PoolItems; + std::vector m_Members; }; #endif diff --git a/src/map/utils/charutils.cpp b/src/map/utils/charutils.cpp index 054384b6a06..88019734357 100644 --- a/src/map/utils/charutils.cpp +++ b/src/map/utils/charutils.cpp @@ -4176,7 +4176,7 @@ namespace charutils if (thDropRate > 0 && xirand::GetRandomNumber(1, 10000) <= thDropRate * settings::get("map.DROP_RATE_MULTIPLIER")) { - PChar->PTreasurePool->AddItem(itemid, PEntity); + PChar->PTreasurePool->addItem(itemid, PEntity); } } diff --git a/src/map/zone.cpp b/src/map/zone.cpp index d925419a8c2..d9fd631250f 100644 --- a/src/map/zone.cpp +++ b/src/map/zone.cpp @@ -430,7 +430,7 @@ void CZone::LoadZoneSettings() } if (m_miscMask & MISC_TREASURE) { - m_TreasurePool = new CTreasurePool(TREASUREPOOL_ZONE); + m_TreasurePool = new CTreasurePool(TreasurePoolType::Zone); } if (m_CampaignHandler && m_CampaignHandler->m_PZone == nullptr) { @@ -992,10 +992,10 @@ void CZone::CharZoneIn(CCharEntity* PChar) PChar->ReloadPartyInc(); // Zone-wide treasure pool takes precendence over all others - if (m_TreasurePool && m_TreasurePool->GetPoolType() == TREASUREPOOL_ZONE) + if (m_TreasurePool && m_TreasurePool->getPoolType() == TreasurePoolType::Zone) { PChar->PTreasurePool = m_TreasurePool; - PChar->PTreasurePool->AddMember(PChar); + PChar->PTreasurePool->addMember(PChar); } else { @@ -1005,8 +1005,8 @@ void CZone::CharZoneIn(CCharEntity* PChar) } else { - PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); - PChar->PTreasurePool->AddMember(PChar); + PChar->PTreasurePool = new CTreasurePool(TreasurePoolType::Solo); + PChar->PTreasurePool->addMember(PChar); } } @@ -1118,15 +1118,15 @@ void CZone::CharZoneOut(CCharEntity* PChar) if (PChar->PTreasurePool != nullptr) // TODO: Condition for eliminating problems with MobHouse, we need to solve it once and for all! { - PChar->PTreasurePool->DelMember(PChar); + PChar->PTreasurePool->delMember(PChar); } // If zone-wide treasure pool but no players in zone then destroy current pool and create new pool // this prevents loot from staying in zone pool after the last player leaves the zone - if (m_TreasurePool && m_TreasurePool->GetPoolType() == TREASUREPOOL_ZONE && m_zoneEntities->CharListEmpty()) + if (m_TreasurePool && m_TreasurePool->getPoolType() == TreasurePoolType::Zone && m_zoneEntities->CharListEmpty()) { destroy(m_TreasurePool); - m_TreasurePool = new CTreasurePool(TREASUREPOOL_ZONE); + m_TreasurePool = new CTreasurePool(TreasurePoolType::Zone); } PChar->loc.zone = nullptr; diff --git a/src/map/zone_entities.cpp b/src/map/zone_entities.cpp index 244187426b3..ed8de446d9f 100644 --- a/src/map/zone_entities.cpp +++ b/src/map/zone_entities.cpp @@ -1882,7 +1882,7 @@ void CZoneEntities::ZoneServer(time_point tick) if (PChar->PTreasurePool) { - PChar->PTreasurePool->CheckItems(tick); + PChar->PTreasurePool->checkItems(tick); } }