-- TODO Should be server side in 42.13 local StaticData = require("TOC/StaticData") local CommonMethods = require("TOC/CommonMethods") --------------------------- --- Submodule to handle spawning the correct items after certain actions (ie: cutting a hand). LOCAL ONLY! ---@class ItemsController local ItemsController = {} --* Player Methods *-- ---@class ItemsController.Player ItemsController.Player = {} ---Returns the correct index for the textures of the amputation ---@param playerObj IsoPlayer ---@param isCicatrized boolean ---@return number ---@private function ItemsController.Player.GetAmputationTexturesIndex(playerObj, isCicatrized) local textureString = playerObj:getHumanVisual():getSkinTexture() local isHairy = textureString:sub(-1) == "a" local matchedIndex = tonumber(textureString:match("%d%d")) -- it must always be at least 1 TOC_DEBUG.print("Texture string: " .. tostring(textureString)) if isHairy then matchedIndex = matchedIndex + 5 end if isCicatrized then matchedIndex = matchedIndex + (isHairy and 5 or 10) -- We add 5 is it's the texture, else 10 end TOC_DEBUG.print("isCicatrized = " .. tostring(isCicatrized)) TOC_DEBUG.print("Amputation Texture Index: " .. tostring(matchedIndex)) return matchedIndex - 1 end ---Main function to delete a clothing item ---@param playerObj IsoPlayer ---@param clothingItem InventoryItem ---@return boolean ---@private function ItemsController.Player.RemoveClothingItem(playerObj, clothingItem) if clothingItem and instanceof(clothingItem, "InventoryItem") then playerObj:removeWornItem(clothingItem) ---@diagnostic disable-next-line: param-type-mismatch playerObj:getInventory():Remove(clothingItem) -- Umbrella is wrong, can be an InventoryItem too TOC_DEBUG.print("found and deleted" .. tostring(clothingItem)) -- Reset model playerObj:resetModelNextFrame() return true end return false end ---Search and deletes an old amputation clothing item on the same side ---@param playerObj IsoPlayer ---@param limbName string function ItemsController.Player.DeleteOldAmputationItem(playerObj, limbName) local side = CommonMethods.GetSide(limbName) for partName, _ in pairs(StaticData.PARTS_IND_STR) do local othLimbName = partName .. "_" .. side local othClothingItemName = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. othLimbName local othClothingItem = playerObj:getInventory():FindAndReturn(othClothingItemName) -- If we manage to find and remove an item, then we should stop this function. ---@cast othClothingItem InventoryItem if ItemsController.Player.RemoveClothingItem(playerObj, othClothingItem) then return end end end ---Deletes all the old amputation items, used for resets ---@param playerObj IsoPlayer function ItemsController.Player.DeleteAllOldAmputationItems(playerObj) -- TODO Fix visual bug -- This part is a workaround for a pretty shitty implementation on the java side. Check ProsthesisHandler for more infos -- local group = BodyLocations.getGroup("Human") -- group:setMultiItem("TOC_Arm", false) -- group:setMultiItem("TOC_ArmProst", false) for i = 1, #StaticData.LIMBS_STR do local limbName = StaticData.LIMBS_STR[i] -- TODO Won't work with dedicated clothingItems for multi amps local clothItemName = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName local clothItem = playerObj:getInventory():FindAndReturn(clothItemName) ---@cast clothItem InventoryItem ItemsController.Player.RemoveClothingItem(playerObj, clothItem) end -- Reset model just in case playerObj:resetModel() -- group:setMultiItem("TOC_Arm", true) -- group:setMultiItem("TOC_ArmProst", true) end ---Spawns and equips the correct amputation item to the player. ---@param playerObj IsoPlayer ---@param limbName string function ItemsController.Player.SpawnAmputationItem(playerObj, limbName) TOC_DEBUG.print("clothing name " .. StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName) local clothingItem = playerObj:getInventory():AddItem(StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName) local texId = ItemsController.Player.GetAmputationTexturesIndex(playerObj, false) ---@cast clothingItem InventoryItem clothingItem:getVisual():setTextureChoice(texId) -- it counts from 0, so we have to subtract 1 playerObj:setWornItem(clothingItem:getBodyLocation(), clothingItem) end ---Search through worn items and modifies a specific amputation item ---@param playerObj IsoPlayer ---@param limbName string ---@param isCicatrized boolean function ItemsController.Player.OverrideAmputationItemVisuals(playerObj, limbName, isCicatrized) local wornItems = playerObj:getWornItems() local fullType = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName for i = 1, wornItems:size() do local it = wornItems:get(i - 1) if it then local wornItem = wornItems:get(i - 1):getItem() TOC_DEBUG.print(wornItem:getFullType()) if wornItem:getFullType() == fullType then TOC_DEBUG.print("Found amputation item for " .. limbName) -- change it here local texId = ItemsController.Player.GetAmputationTexturesIndex(playerObj, isCicatrized) wornItem:getVisual():setTextureChoice(texId) playerObj:resetModelNextFrame() -- necessary to update the model return end end end end --* Zombie Methods *-- ---@class ItemsController.Zombie ItemsController.Zombie = {} ---Set an amputation to a zombie ---@param zombie IsoZombie ---@param amputationFullType string Full Type function ItemsController.Zombie.SpawnAmputationItem(zombie, amputationFullType) local texId = ItemsController.Zombie.GetAmputationTexturesIndex(zombie) local zombieVisuals = zombie:getItemVisuals() local itemVisual = ItemVisual:new() itemVisual:setItemType(amputationFullType) itemVisual:setTextureChoice(texId) if zombieVisuals then zombieVisuals:add(itemVisual) end zombie:resetModelNextFrame() -- Spawn the item too in the inventory to keep track of stuff this way. It's gonna get deleted when we reload the game local zombieInv = zombie:getInventory() zombieInv:AddItem(amputationFullType) -- TODO Remove objects in that part of the body to prevent items floating in mid air end function ItemsController.Zombie.GetAmputationTexturesIndex(zombie) local x = zombie:getHumanVisual():getSkinTexture() -- Starting ID for zombies = 20 -- 3 levels local matchedIndex = tonumber(x:match("ZedBody0(%d)")) - 1 matchedIndex = matchedIndex * 3 local level = tonumber(x:match("%d$")) - 1 -- it's from 1 to 3, but we're using it like 0 indexed arrays local finalId = 20 + matchedIndex + level --print("Zombie texture index: " .. tostring(finalId)) return finalId end return ItemsController