diff --git a/data-canary/scripts/actions/tools/magic_gold_converter.lua b/data-canary/scripts/actions/tools/magic_gold_converter.lua index ea4fa376e14..4ee89455451 100644 --- a/data-canary/scripts/actions/tools/magic_gold_converter.lua +++ b/data-canary/scripts/actions/tools/magic_gold_converter.lua @@ -12,7 +12,7 @@ local data = { local function findItem(self, cylinder, converterItem) if cylinder == 0 then cylinder = self:getSlotItem(CONST_SLOT_BACKPACK) - findItem(self, self:getSlotItem(CONST_SLOT_STORE_INBOX), converterItem) + findItem(self, self:getStoreInbox(), converterItem) end if cylinder and cylinder:isContainer() then diff --git a/data-otservbr-global/npc/emael.lua b/data-otservbr-global/npc/emael.lua index 891f7262b1d..79111f8f324 100644 --- a/data-otservbr-global/npc/emael.lua +++ b/data-otservbr-global/npc/emael.lua @@ -67,8 +67,9 @@ local function creatureSayCallback(npc, creature, type, message) if player:getStorageValue(30020) == 1 then if player:removeMoney(1000000) then npcHandler:say("Ah, I see you killed a lot of dangerous creatures. Here's your podium of vigour!", npc, creature) - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) if decoKit then decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "Unwrap it in your own house to create a <" .. ItemType(38707):getName() .. ">.") diff --git a/data-otservbr-global/npc/emperor_kruzak.lua b/data-otservbr-global/npc/emperor_kruzak.lua index 4f1a4803bb3..4f838396df0 100644 --- a/data-otservbr-global/npc/emperor_kruzak.lua +++ b/data-otservbr-global/npc/emperor_kruzak.lua @@ -80,8 +80,9 @@ local function creatureSayCallback(npc, creature, type, message) elseif npcHandler:getTopic(playerId) == 3 then -- ARMOR/OUTFIT if player:getStorageValue(Storage.OutfitQuest.GoldenOutfit) < 1 then if player:getMoney() + player:getBankBalance() >= 500000000 then - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) local decoItemName = ItemType(31510):getName() decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a " .. decoItemName .. ".") diff --git a/data-otservbr-global/npc/hireling.lua b/data-otservbr-global/npc/hireling.lua index ca72e1c5bcf..b2259069214 100644 --- a/data-otservbr-global/npc/hireling.lua +++ b/data-otservbr-global/npc/hireling.lua @@ -517,11 +517,11 @@ function createHirelingType(HirelingName) local playerId = creature:getId() local player = Player(creature) local itType = ItemType(food_id) - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() if player:getFreeCapacity() < itType:getWeight(1) then npcHandler:say("Sorry, but you don't have enough capacity.", npc, creature) - elseif not inbox then + elseif not inbox or #inboxItems > inbox:getMaxCapacity() then player:getPosition():sendMagicEffect(CONST_ME_POFF) npcHandler:say("Sorry, you don't have enough room on your inbox", npc, creature) elseif not player:removeMoneyBank(15000) then diff --git a/data-otservbr-global/npc/king_tibianus.lua b/data-otservbr-global/npc/king_tibianus.lua index 1f18aff7d85..d4d0b54ece1 100644 --- a/data-otservbr-global/npc/king_tibianus.lua +++ b/data-otservbr-global/npc/king_tibianus.lua @@ -85,8 +85,9 @@ local function creatureSayCallback(npc, creature, type, message) elseif npcHandler:getTopic(playerId) == 3 then -- ARMOR/OUTFIT if player:getStorageValue(Storage.OutfitQuest.GoldenOutfit) < 1 then if player:getMoney() + player:getBankBalance() >= 500000000 then - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) local decoItemName = ItemType(31510):getName() decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "Unwrap it in your own house to create a " .. decoItemName .. ".") diff --git a/data-otservbr-global/npc/queen_eloise.lua b/data-otservbr-global/npc/queen_eloise.lua index 1b65408cc74..dc72a95ba6c 100644 --- a/data-otservbr-global/npc/queen_eloise.lua +++ b/data-otservbr-global/npc/queen_eloise.lua @@ -75,8 +75,9 @@ local function creatureSayCallback(npc, creature, type, message) elseif npcHandler:getTopic(playerId) == 3 then -- ARMOR/OUTFIT if player:getStorageValue(Storage.OutfitQuest.GoldenOutfit) < 1 then if player:getMoney() + player:getBankBalance() >= 500000000 then - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) local decoItemName = ItemType(31510):getName() decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a " .. decoItemName .. ".") diff --git a/data-otservbr-global/npc/walter_jaeger.lua b/data-otservbr-global/npc/walter_jaeger.lua index 465b23badb9..ac2933a9224 100644 --- a/data-otservbr-global/npc/walter_jaeger.lua +++ b/data-otservbr-global/npc/walter_jaeger.lua @@ -281,14 +281,17 @@ local function processItemInboxPurchase(player, name, id) return false end - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) if decoKit then decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item with the Walter Jaeger.\nUnwrap it in your own house to create a <" .. name .. ">.") decoKit:setCustomAttribute("unWrapId", id) return true end + else + player:sendTextMessage(MESSAGE_INFO_DESCR, "Please make sure you have free slots in your store inbox.") end return false diff --git a/data-otservbr-global/scripts/actions/other/magic_gold_converter.lua b/data-otservbr-global/scripts/actions/other/magic_gold_converter.lua index f64ab905e54..d5b9b9d9335 100644 --- a/data-otservbr-global/scripts/actions/other/magic_gold_converter.lua +++ b/data-otservbr-global/scripts/actions/other/magic_gold_converter.lua @@ -12,7 +12,7 @@ local data = { local function finditem(self, cylinder, conv) if cylinder == 0 then cylinder = self:getSlotItem(CONST_SLOT_BACKPACK) - finditem(self, self:getSlotItem(CONST_SLOT_STORE_INBOX), conv) + finditem(self, self:getStoreInbox(), conv) end if cylinder and cylinder:isContainer() then diff --git a/data/libs/functions/player.lua b/data/libs/functions/player.lua index a596c2a683e..94e5f848603 100644 --- a/data/libs/functions/player.lua +++ b/data/libs/functions/player.lua @@ -521,7 +521,7 @@ function Player.getSubjectVerb(self, past) end function Player.findItemInInbox(self, itemId) - local inbox = self:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = self:getStoreInbox() local items = inbox:getItems() for _, item in pairs(items) do if item:getId() == itemId then @@ -556,7 +556,7 @@ function Player.updateHazard(self) end function Player:addItemStoreInboxEx(item, movable, setOwner) - local inbox = self:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = self:getStoreInbox() if not movable then item:setOwner(self) item:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) @@ -663,7 +663,7 @@ function Player:setFiendish() end function Player:findItemInInbox(itemId, name) - local inbox = self:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = self:getStoreInbox() local items = inbox:getItems() for _, item in pairs(items) do if item:getId() == itemId and (not name or item:getName() == name) then diff --git a/data/libs/hireling_lib.lua b/data/libs/hireling_lib.lua index 528a903da88..42390a2cc01 100644 --- a/data/libs/hireling_lib.lua +++ b/data/libs/hireling_lib.lua @@ -92,7 +92,7 @@ local function checkHouseAccess(hireling) -- Player is not invited anymore, return to lamp logger.debug("Returning Hireling: {} to owner '{}' Inbox", hireling:getName(), player:getName()) - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = player:getStoreInbox() if not inbox then return false end @@ -359,8 +359,9 @@ function Hireling:returnToLamp(player_id) return owner:sendTextMessage(MESSAGE_FAILURE, "You do not have enough capacity.") end - local inbox = owner:getSlotItem(CONST_SLOT_STORE_INBOX) - if not inbox then + local inbox = owner:getStoreInbox() + local inboxItems = inbox:getItems() + if not inbox or #inboxItems > inbox:getMaxCapacity() then owner:getPosition():sendMagicEffect(CONST_ME_POFF) return owner:sendTextMessage(MESSAGE_FAILURE, "You don't have enough room in your inbox.") end @@ -537,8 +538,9 @@ function Player:addNewHireling(name, sex) return false end - local inbox = self:getSlotItem(CONST_SLOT_STORE_INBOX) - if not inbox then + local inbox = self:getStoreInbox() + local inboxItems = inbox:getItems() + if not inbox or #inboxItems > inbox:getMaxCapacity() then self:getPosition():sendMagicEffect(CONST_ME_POFF) self:sendTextMessage(MESSAGE_FAILURE, "You don't have enough room in your inbox.") return false @@ -628,7 +630,7 @@ function Player:hasHirelings() end function Player:findHirelingLamp(hirelingId) - local inbox = self:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = self:getStoreInbox() if not inbox then return nil end diff --git a/data/modules/scripts/blessings/blessings.lua b/data/modules/scripts/blessings/blessings.lua index 5a8e5e56c9c..adfa364e7e1 100644 --- a/data/modules/scripts/blessings/blessings.lua +++ b/data/modules/scripts/blessings/blessings.lua @@ -299,7 +299,7 @@ Blessings.DropLoot = function(player, corpse, chance, skulled) end end if skulled and Blessings.Config.SkulledDeathLoseStoreItem then - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = player:getStoreInbox() local toBeDeleted = {} if inbox and inbox:getSize() > 0 then for i = 0, inbox:getSize() do diff --git a/data/modules/scripts/daily_reward/daily_reward.lua b/data/modules/scripts/daily_reward/daily_reward.lua index 177b23cc90b..815a7e2611c 100644 --- a/data/modules/scripts/daily_reward/daily_reward.lua +++ b/data/modules/scripts/daily_reward/daily_reward.lua @@ -452,8 +452,9 @@ function Player.selectDailyReward(self, msg) end -- Adding items to store inbox - local inbox = self:getSlotItem(CONST_SLOT_STORE_INBOX) - if not inbox then + local inbox = self:getStoreInbox() + local inboxItems = inbox:getItems() + if not inbox or #inboxItems > inbox:getMaxCapacity() then self:sendError("You do not have enough space in your store inbox.") return false end diff --git a/data/modules/scripts/gamestore/init.lua b/data/modules/scripts/gamestore/init.lua index f3959c3a1e9..439822a3f58 100644 --- a/data/modules/scripts/gamestore/init.lua +++ b/data/modules/scripts/gamestore/init.lua @@ -1573,8 +1573,9 @@ function GameStore.processStackablePurchase(player, offerId, offerCount, offerNa return error({ code = 0, message = "Please make sure you have free capacity to hold this item." }) end - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then if (isKeg and offerCount > 500) or offerCount > 100 then local parcel = inbox:addItem(PARCEL_ID, 1) parcel:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) @@ -1624,12 +1625,14 @@ function GameStore.processHouseRelatedPurchase(player, offer) return (itemId >= ITEM_HEALTH_CASK_START and itemId <= ITEM_HEALTH_CASK_END) or (itemId >= ITEM_MANA_CASK_START and itemId <= ITEM_MANA_CASK_END) or (itemId >= ITEM_SPIRIT_CASK_START and itemId <= ITEM_SPIRIT_CASK_END) end - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) local itemIds = offer.itemtype if type(itemIds) ~= "table" then itemIds = { itemIds } end - if inbox then + + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() then for _, itemId in ipairs(itemIds) do local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) if decoKit then diff --git a/data/scripts/talkactions/god/inbox_command.lua b/data/scripts/talkactions/god/inbox_command.lua index bfc902b1315..a080a237027 100644 --- a/data/scripts/talkactions/god/inbox_command.lua +++ b/data/scripts/talkactions/god/inbox_command.lua @@ -5,7 +5,7 @@ function inboxCommand.onSay(player, words, param) player:getPosition():sendMagicEffect(CONST_ME_TUTORIALSQUARE) local target = Creature(param[1]) if target then - local inbox = target:getSlotItem(CONST_SLOT_STORE_INBOX) + local inbox = target:getStoreInbox() local inboxSize = inbox:getSize() if inbox and inboxSize > 0 then if param[2] == "remove" then diff --git a/data/scripts/talkactions/player/reward.lua b/data/scripts/talkactions/player/reward.lua index b6c882eb9a2..3f4cc3787de 100644 --- a/data/scripts/talkactions/player/reward.lua +++ b/data/scripts/talkactions/player/reward.lua @@ -24,8 +24,9 @@ local function sendExerciseRewardModal(player) return true end - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - if inbox and inbox:getEmptySlots() > 0 and player:getFreeCapacity() >= iType:getWeight() then + local inbox = player:getStoreInbox() + local inboxItems = inbox:getItems() + if inbox and #inboxItems <= inbox:getMaxCapacity() and player:getFreeCapacity() >= iType:getWeight() then local item = inbox:addItem(it.id, it.charges) if item then item:setActionId(IMMOVABLE_ACTION_ID) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 0ff9094e03c..0a310061fc5 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -7813,6 +7813,16 @@ std::shared_ptr Player::getLootPouch() { return container; } +std::shared_ptr Player::getStoreInbox() const { + auto thing = getThing(CONST_SLOT_STORE_INBOX); + if (!thing) { + return nullptr; + } + + auto storeInbox = thing->getContainer(); + return storeInbox ? storeInbox : nullptr; +} + bool Player::hasPermittedConditionInPZ() const { static const std::unordered_set allowedConditions = { CONDITION_ENERGY, diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 9d7a555b050..521399425e9 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -2552,6 +2552,8 @@ class Player final : public Creature, public Cylinder, public Bankable { bool hasPermittedConditionInPZ() const; + std::shared_ptr getStoreInbox() const; + private: friend class PlayerLock; std::mutex mutex; diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index d4d55ba6cf1..0cb99cb46f8 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -241,6 +241,10 @@ std::ostringstream &Container::getContentDescription(std::ostringstream &os, boo return os; } +uint32_t Container::getMaxCapacity() const { + return m_maxItems; +} + bool Container::isStoreInbox() const { return getID() == ITEM_STORE_INBOX; } diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index 0f3f1df4398..9bcd2389299 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -87,6 +87,8 @@ class Container : public Item, public Cylinder { bool unserializeItemNode(OTB::Loader &loader, const OTB::Node &node, PropStream &propStream, Position &itemPosition) override; std::string getContentDescription(bool oldProtocol); + uint32_t getMaxCapacity() const; + size_t size() const { return itemlist.size(); } diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 203b24249c8..1c90bb5b4da 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4156,3 +4156,20 @@ int PlayerFunctions::luaPlayerKV(lua_State* L) { setMetatable(L, -1, "KV"); return 1; } + +int PlayerFunctions::luaPlayerGetStoreInbox(lua_State* L) { + // player:getStoreInbox() + const auto &player = getUserdataShared(L, 1); + if (!player) { + lua_pushnil(L); + return 1; + } + + if (auto item = player->getStoreInbox()) { + pushUserdata(L, item); + setItemMetatable(L, -1, item); + } else { + pushBoolean(L, false); + } + return 1; +} diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index 80e1e84c98a..b23c0090276 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -355,6 +355,7 @@ class PlayerFunctions final : LuaScriptInterface { registerMethod(L, "Player", "getVipTime", PlayerFunctions::luaPlayerGetVipTime); registerMethod(L, "Player", "kv", PlayerFunctions::luaPlayerKV); + registerMethod(L, "Player", "getStoreInbox", PlayerFunctions::luaPlayerGetStoreInbox); GroupFunctions::init(L); GuildFunctions::init(L); @@ -705,6 +706,7 @@ class PlayerFunctions final : LuaScriptInterface { static int luaPlayerGetVipTime(lua_State* L); static int luaPlayerKV(lua_State* L); + static int luaPlayerGetStoreInbox(lua_State* L); friend class CreatureFunctions; }; diff --git a/src/lua/functions/items/container_functions.cpp b/src/lua/functions/items/container_functions.cpp index b3503b662e1..132acbdc5b4 100644 --- a/src/lua/functions/items/container_functions.cpp +++ b/src/lua/functions/items/container_functions.cpp @@ -38,6 +38,17 @@ int ContainerFunctions::luaContainerGetSize(lua_State* L) { return 1; } +int ContainerFunctions::luaContainerGetMaxCapacity(lua_State* L) { + // container:getMaxCapacity() + const auto &container = getUserdataShared(L, 1); + if (container) { + lua_pushnumber(L, container->getMaxCapacity()); + } else { + lua_pushnil(L); + } + return 1; +} + int ContainerFunctions::luaContainerGetCapacity(lua_State* L) { // container:getCapacity() std::shared_ptr container = getUserdataShared(L, 1); diff --git a/src/lua/functions/items/container_functions.hpp b/src/lua/functions/items/container_functions.hpp index ce182326702..186f6b68119 100644 --- a/src/lua/functions/items/container_functions.hpp +++ b/src/lua/functions/items/container_functions.hpp @@ -19,6 +19,7 @@ class ContainerFunctions final : LuaScriptInterface { registerMetaMethod(L, "Container", "__eq", ContainerFunctions::luaUserdataCompare); registerMethod(L, "Container", "getSize", ContainerFunctions::luaContainerGetSize); + registerMethod(L, "Container", "getMaxCapacity", ContainerFunctions::luaContainerGetMaxCapacity); registerMethod(L, "Container", "getCapacity", ContainerFunctions::luaContainerGetCapacity); registerMethod(L, "Container", "getEmptySlots", ContainerFunctions::luaContainerGetEmptySlots); registerMethod(L, "Container", "getContentDescription", ContainerFunctions::luaContainerGetContentDescription); @@ -37,6 +38,7 @@ class ContainerFunctions final : LuaScriptInterface { static int luaContainerCreate(lua_State* L); static int luaContainerGetSize(lua_State* L); + static int luaContainerGetMaxCapacity(lua_State* L); static int luaContainerGetCapacity(lua_State* L); static int luaContainerGetEmptySlots(lua_State* L);