From 3d068767adf9420dadfe741e8845df23768c5d88 Mon Sep 17 00:00:00 2001 From: sruon Date: Fri, 7 Mar 2025 02:00:46 -0700 Subject: [PATCH] Einherjar bindings --- scripts/specs/core/CBaseEntity.lua | 15 +++++ src/map/item_container.cpp | 14 +++++ src/map/item_container.h | 1 + src/map/lua/lua_baseentity.cpp | 89 ++++++++++++++++++++++++++++++ src/map/lua/lua_baseentity.h | 2 + 5 files changed, 121 insertions(+) diff --git a/scripts/specs/core/CBaseEntity.lua b/scripts/specs/core/CBaseEntity.lua index 15e3cdc62a7..ee403cf375d 100644 --- a/scripts/specs/core/CBaseEntity.lua +++ b/scripts/specs/core/CBaseEntity.lua @@ -946,6 +946,14 @@ end function CBaseEntity:delItem(itemID, quantity, containerID) end +---@param itemId integer +---@param quantity integer +---@param containerId integer +---@param slotId integer +---@return boolean +function CBaseEntity:delItemAt(itemId, quantity, containerId, slotId) +end + ---@param containerID integer? ---@return boolean function CBaseEntity:delContainerItems(containerID) @@ -981,6 +989,13 @@ end function CBaseEntity:findItem(itemID, location) end +---@nodiscard +---@param itemID integer +---@param location integer? +---@return table +function CBaseEntity:findItems(itemID, location) +end + ---@param size integer ---@param arg1 integer? ---@return nil diff --git a/src/map/item_container.cpp b/src/map/item_container.cpp index 32af1f18a36..9645db0d9c0 100644 --- a/src/map/item_container.cpp +++ b/src/map/item_container.cpp @@ -203,6 +203,20 @@ uint8 CItemContainer::SearchItem(uint16 ItemID) return ERROR_SLOTID; } +auto CItemContainer::SearchItems(uint16 ItemID) -> std::vector +{ + std::vector SlotIDs; + + for (uint8 SlotID = 0; SlotID <= m_size; ++SlotID) + { + if ((m_ItemList[SlotID] != nullptr) && (m_ItemList[SlotID]->getID() == ItemID)) + { + SlotIDs.push_back(SlotID); + } + } + return SlotIDs; +} + uint8 CItemContainer::SearchItemWithSpace(uint16 ItemID, uint32 quantity) { for (uint8 SlotID = 0; SlotID <= m_size; ++SlotID) diff --git a/src/map/item_container.h b/src/map/item_container.h index ec3adb8e686..b0f6b862eb3 100644 --- a/src/map/item_container.h +++ b/src/map/item_container.h @@ -66,6 +66,7 @@ class CItemContainer uint8 AddSize(int8 size); // increase/decrease container size uint8 SetSize(uint8 size); uint8 SearchItem(uint16 ItemID); + auto SearchItems(uint16 ItemID) -> std::vector; uint8 SearchItemWithSpace(uint16 ItemID, uint32 quantity); // search for item that has space to accomodate x items added uint8 InsertItem(CItem* PItem); // add a pre-created item to a free cell diff --git a/src/map/lua/lua_baseentity.cpp b/src/map/lua/lua_baseentity.cpp index 8dc6b43ecda..e00c0b4b710 100644 --- a/src/map/lua/lua_baseentity.cpp +++ b/src/map/lua/lua_baseentity.cpp @@ -4197,6 +4197,38 @@ bool CLuaBaseEntity::delItem(uint16 itemID, int32 quantity, sol::object const& c return false; } +/************************************************************************ + * Function: delItemAt() + * Purpose : Deletes an item from a player's inventory at specified container/slot + * Example : player:delItemAt(4102, 1, xi.inv.INVENTORY, 5) + * Notes : + ************************************************************************/ +bool CLuaBaseEntity::delItemAt(const uint16 itemID, const int32 quantity, uint8 containerId, const uint8 slotId) +{ + auto* PChar = dynamic_cast(m_PBaseEntity); + if (!PChar) + { + ShowWarning("Invalid entity type calling function (%s).", m_PBaseEntity->getName()); + return false; + } + + if (containerId >= CONTAINER_ID::MAX_CONTAINER_ID) + { + ShowWarning("Lua::delItemAt: Attempting to delete an item from an invalid slot. Defaulting to main inventory."); + containerId = LOC_INVENTORY; + } + + if (const auto* PItem = PChar->getStorage(containerId)->GetItem(slotId); PItem && PItem->getID() == itemID) + { + charutils::UpdateItem(PChar, containerId, slotId, -quantity); + PChar->pushPacket(); + + return true; + } + + return false; +} + /************************************************************************ * Function: delContainerItems() * Purpose : Deletes all items from a specific player's container @@ -4438,6 +4470,61 @@ auto CLuaBaseEntity::findItem(uint16 itemID, sol::object const& location) -> CIt return nullptr; } +/************************************************************************ + * Function: findItems() + * Purpose : Like findItem, but returns all matching item objects (empty if none found) + * Example : local items = player:findItems(xi.item.GLOWING_LAMP) + * Notes : + ************************************************************************/ +auto CLuaBaseEntity::findItems(uint16 itemID, sol::object const& location) -> sol::table +{ + auto table = lua.create_table(); + auto* PChar = dynamic_cast(m_PBaseEntity); + + if (!PChar) + { + return table; + } + + // Look in a specific container + if (location != sol::lua_nil) + { + uint8 locationID = LOC_INVENTORY; + + locationID = location.as(); + locationID = (locationID < CONTAINER_ID::MAX_CONTAINER_ID ? locationID : (uint8)LOC_INVENTORY); + + if (const auto slots = PChar->getStorage(locationID)->SearchItems(itemID); !slots.empty()) + { + for (const auto slot : slots) + { + if (auto* item = PChar->getStorage(locationID)->GetItem(slot)) + { + table.add(item); + } + } + } + } + else // Look in all containers + { + for (uint8 i = 0; i < CONTAINER_ID::MAX_CONTAINER_ID; ++i) + { + if (auto slots = PChar->getStorage(i)->SearchItems(itemID); !slots.empty()) + { + for (const auto slot : slots) + { + if (auto* item = PChar->getStorage(i)->GetItem(slot)) + { + table.add(item); + } + } + } + } + } + + return table; +} + /************************************************************************ * Function: createShop() * Purpose : Create a temporary shop for display to a player @@ -19053,12 +19140,14 @@ void CLuaBaseEntity::Register() SOL_REGISTER("getItemCount", CLuaBaseEntity::getItemCount); SOL_REGISTER("addItem", CLuaBaseEntity::addItem); SOL_REGISTER("delItem", CLuaBaseEntity::delItem); + SOL_REGISTER("delItemAt", CLuaBaseEntity::delItemAt); SOL_REGISTER("delContainerItems", CLuaBaseEntity::delContainerItems); SOL_REGISTER("addUsedItem", CLuaBaseEntity::addUsedItem); SOL_REGISTER("addTempItem", CLuaBaseEntity::addTempItem); SOL_REGISTER("getWornUses", CLuaBaseEntity::getWornUses); SOL_REGISTER("incrementItemWear", CLuaBaseEntity::incrementItemWear); SOL_REGISTER("findItem", CLuaBaseEntity::findItem); + SOL_REGISTER("findItems", CLuaBaseEntity::findItems); SOL_REGISTER("createShop", CLuaBaseEntity::createShop); SOL_REGISTER("addShopItem", CLuaBaseEntity::addShopItem); diff --git a/src/map/lua/lua_baseentity.h b/src/map/lua/lua_baseentity.h index 30a6e053040..a38b7f3f97a 100644 --- a/src/map/lua/lua_baseentity.h +++ b/src/map/lua/lua_baseentity.h @@ -236,12 +236,14 @@ class CLuaBaseEntity uint32 getItemCount(uint16 itemID); bool addItem(sol::variadic_args va); bool delItem(uint16 itemID, int32 quantity, sol::object const& containerID); + bool delItemAt(uint16 itemID, int32 quantity, uint8 containerId, uint8 slotId); bool delContainerItems(sol::object const& containerID); bool addUsedItem(uint16 itemID); bool addTempItem(uint16 itemID, sol::object const& arg1); uint8 getWornUses(uint16 itemID); // Check if the item is already worn uint8 incrementItemWear(uint16 itemID); // Increment the item's worn value and returns it auto findItem(uint16 itemID, sol::object const& location) -> CItem*; // Like hasItem, but returns the item object (nil if not found) + auto findItems(uint16 itemID, sol::object const& location) -> sol::table; void createShop(uint8 size, sol::object const& arg1); void addShopItem(uint16 itemID, double rawPrice, sol::object const& arg2, sol::object const& arg3);