From 844530b7b8471743171c45964b5717da09b2123d Mon Sep 17 00:00:00 2001 From: omeranha <53233626+omeranha@users.noreply.github.com> Date: Mon, 28 Feb 2022 00:53:24 -0300 Subject: [PATCH] Add container:getItems() function and option stash moving items to supply stash and depot (#169) Part of code by @nekiro (https://github.com/nekiro) https://github.com/otland/forgottenserver/pull/3160 container:getItems() function New method which will return all container items, optional bool recursive to search in sub containers of container. Usage: ``` local items = container:getItems(true) for _, item in ipairs(items) do print(item:getName()) end ``` My part of code: - New stash option. - Stow an container to your Stash(or right click container->Stow Item), the stowable items go your stash, and non-stacked items go to the selected depot chest(default is 4, config.lua configurable). --- config.lua.dist | 4 ++++ src/config/config_definitions.hpp | 2 ++ src/config/configmanager.cpp | 2 ++ src/creatures/players/player.cpp | 13 +++++++++++ src/creatures/players/player.h | 2 ++ src/items/containers/container.cpp | 15 ++++++++++++ src/items/containers/container.h | 3 +++ .../functions/items/container_functions.cpp | 23 +++++++++++++++++++ .../functions/items/container_functions.hpp | 2 ++ 9 files changed, 66 insertions(+) diff --git a/config.lua.dist b/config.lua.dist index 48724c61a77..6dc9f890faa 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -61,6 +61,10 @@ onlyPremiumAccount = false weatherRain = false thunderEffect = false allConsoleLog = false +-- stashMoving = true, stow an container inside your stash +-- the non-stackable items will be moved to the selected depot chest(I - XVIII). +stashMoving = false +depotChest = 4 -- Stamina in Trainers staminaTrainer = false diff --git a/src/config/config_definitions.hpp b/src/config/config_definitions.hpp index 5865fc3c9d7..a70c4558570 100644 --- a/src/config/config_definitions.hpp +++ b/src/config/config_definitions.hpp @@ -65,6 +65,7 @@ enum booleanConfig_t { SORT_LOOT_BY_CHANCE, TOGLE_SAVE_INTERVAL, TOGLE_SAVE_INTERVAL_CLEAN_MAP, + STASH_MOVING, TOGLE_IMBUEMENT_SHRINE_STORAGE, LAST_BOOLEAN_CONFIG @@ -154,6 +155,7 @@ enum integerConfig_t { SAVE_INTERVAL_TIME, MAX_ALLOWED_ON_A_DUMMY, FREE_QUEST_STAGE, + DEPOTCHEST, LAST_INTEGER_CONFIG }; diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index d325c497ccc..df9c89aa0db 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -158,6 +158,7 @@ bool ConfigManager::load() boolean[CLASSIC_EQUIPMENT_SLOTS] = getGlobalBoolean(L, "classicEquipmentSlots", false); boolean[CLASSIC_ATTACK_SPEED] = getGlobalBoolean(L, "classicAttackSpeed", false); boolean[SCRIPTS_CONSOLE_LOGS] = getGlobalBoolean(L, "showScriptsLogInConsole", true); + boolean[STASH_MOVING] = getGlobalBoolean(L, "stashMoving", false); boolean[ALLOW_BLOCK_SPAWN] = getGlobalBoolean(L, "allowBlockSpawn", true); boolean[REMOVE_WEAPON_AMMO] = getGlobalBoolean(L, "removeWeaponAmmunition", true); boolean[REMOVE_WEAPON_CHARGES] = getGlobalBoolean(L, "removeWeaponCharges", true); @@ -246,6 +247,7 @@ bool ConfigManager::load() integer[SAVE_INTERVAL_TIME] = getGlobalNumber(L, "saveIntervalTime", 1); integer[MAX_ALLOWED_ON_A_DUMMY] = getGlobalNumber(L, "maxAllowedOnADummy", 1); integer[FREE_QUEST_STAGE] = getGlobalNumber(L, "freeQuestStage", 1); + integer[DEPOTCHEST] = getGlobalNumber(L, "depotChest", 4); floating[RATE_HEALTH_REGEN] = getGlobalFloat(L, "rateHealthRegen", 1.0); floating[RATE_HEALTH_REGEN_SPEED] = getGlobalFloat(L, "rateHealthRegenSpeed", 1.0); diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 89b72c6aba4..a0d0dab4609 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -3462,6 +3462,10 @@ void Player::stashContainer(StashContainerList itemDict) } retString << "Stowed " << totalStowed << " object" << (totalStowed > 1 ? "s." : "."); + if (moved) { + retString << " Moved " << movedItems << " object" << (movedItems > 1 ? "s." : "."); + movedItems = 0; + } sendTextMessage(MESSAGE_STATUS, retString.str()); } @@ -5593,6 +5597,15 @@ void Player::stowItem(Item* item, uint32_t count, bool allItems) { } } else if (item->getContainer()) { itemDict = item->getContainer()->getStowableItems(); + for (Item* containerItem : item->getContainer()->getItems()) { + uint32_t depotChest = g_configManager().getNumber(DEPOTCHEST); + bool validDepot = depotChest > 0 && depotChest < 19; + if (g_configManager().getBoolean(STASH_MOVING) && containerItem && !containerItem->isStackable() && validDepot) { + g_game.internalMoveItem(containerItem->getParent(), getDepotChest(depotChest, true), INDEX_WHEREEVER, containerItem, containerItem->getItemCount(), nullptr); + movedItems++; + moved = true; + } + } } else { itemDict.push_back(std::pair(item, count)); } diff --git a/src/creatures/players/player.h b/src/creatures/players/player.h index ff2fd7235a1..7fce4a0a110 100644 --- a/src/creatures/players/player.h +++ b/src/creatures/players/player.h @@ -2078,6 +2078,7 @@ class Player final : public Creature, public Cylinder uint16_t staminaXpBoost = 100; int16_t lastDepotId = -1; StashItemList stashItems; // [ClientID] = amount + uint32_t movedItems = 0; // Bestiary bool charmExpansion = false; @@ -2148,6 +2149,7 @@ class Player final : public Creature, public Cylinder bool supplyStash = false; // Menu option 'stow, stow container ...' bool marketMenu = false; // Menu option 'show in market' bool exerciseTraining = false; + bool moved = false; static uint32_t playerAutoID; diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index b0a71c0b75b..27b9deea7bb 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -729,6 +729,21 @@ Thing* Container::getThing(size_t index) const return getItemByIndex(index); } +ItemVector Container::getItems(bool recursive /*= false*/) const +{ + ItemVector containerItems; + if (recursive) { + for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { + containerItems.push_back(*it); + } + } else { + for (Item* item : itemlist) { + containerItems.push_back(item); + } + } + return containerItems; +} + void Container::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, CylinderLink_t) { Cylinder* topParent = getTopParent(); diff --git a/src/items/containers/container.h b/src/items/containers/container.h index 665ef823d0c..59e573dcd8c 100644 --- a/src/items/containers/container.h +++ b/src/items/containers/container.h @@ -24,6 +24,7 @@ #include "items/cylinder.h" #include "items/item.h" +#include "items/tile.h" class Container; class DepotChest; @@ -160,6 +161,8 @@ class Container : public Item, public Cylinder uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const override final; std::map& getAllItemTypeCount(std::map& countMap) const override final; Thing* getThing(size_t index) const override final; + + ItemVector getItems(bool recursive = false) const; void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; diff --git a/src/lua/functions/items/container_functions.cpp b/src/lua/functions/items/container_functions.cpp index 48081044916..08a37b34ddb 100644 --- a/src/lua/functions/items/container_functions.cpp +++ b/src/lua/functions/items/container_functions.cpp @@ -245,6 +245,29 @@ int ContainerFunctions::luaContainerGetContentDescription(lua_State* L) { return 1; } +int ContainerFunctions::luaContainerGetItems(lua_State* L) { + // container:getItems([recursive = false]) + const Container* container = getUserdata(L, 1); + if (!container) { + lua_pushnil(L); + return 1; + } + + bool recursive = getBoolean(L, 2, false); + std::vector items = container->getItems(recursive); + + lua_createtable(L, static_cast(items.size()), 0); + + int index = 0; + for (Item* item : items) { + index++; + pushUserdata(L, item); + setItemMetatable(L, -1, item); + lua_rawseti(L, -2, index); + } + return 1; +} + int ContainerFunctions::luaContainerRegisterReward(lua_State* L) { // container:registerReward() Container* container = getUserdata(L, 1); diff --git a/src/lua/functions/items/container_functions.hpp b/src/lua/functions/items/container_functions.hpp index 722f9aedb55..4ce9d9b03b8 100644 --- a/src/lua/functions/items/container_functions.hpp +++ b/src/lua/functions/items/container_functions.hpp @@ -36,6 +36,7 @@ class ContainerFunctions final : LuaScriptInterface { registerMethod(L, "Container", "getCapacity", ContainerFunctions::luaContainerGetCapacity); registerMethod(L, "Container", "getEmptySlots", ContainerFunctions::luaContainerGetEmptySlots); registerMethod(L, "Container", "getContentDescription", ContainerFunctions::luaContainerGetContentDescription); + registerMethod(L, "Container", "getItems", ContainerFunctions::luaContainerGetItems); registerMethod(L, "Container", "getItemHoldingCount", ContainerFunctions::luaContainerGetItemHoldingCount); registerMethod(L, "Container", "getItemCountById", ContainerFunctions::luaContainerGetItemCountById); @@ -54,6 +55,7 @@ class ContainerFunctions final : LuaScriptInterface { static int luaContainerGetEmptySlots(lua_State* L); static int luaContainerGetContentDescription(lua_State* L); + static int luaContainerGetItems(lua_State* L); static int luaContainerGetItemHoldingCount(lua_State* L); static int luaContainerGetItemCountById(lua_State* L);