yanecc Posted July 10, 2024 Share Posted July 10, 2024 Hi everyone, I'm currently working on a small part of a mod for Don't Starve Together and need some assistance. My goal is to replace a specific item in the players' inventory and backpack with another item during every full moon. This change should be permanent (i.e., the item does not revert back after the full moon ends). The items outside the player's inventory and backpack should remain unaffected. I've been studying the code for prefabs like Chester and have found it quite insightful. However, I haven't been able to figure out an effective way to globally detect the full moon and replace items in the inventory and backpack in place. Any help or guidance would be greatly appreciated. Thanks! Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/ Share on other sites More sharing options...
alainmcd Posted July 10, 2024 Share Posted July 10, 2024 Hi, welcome to the forums! You're on the right track. Chester waits for the full moon to see if he can morph (l. 694), though the MorphChester function is actually called from his stategraph. As for how to replace the item, the perisable component has some similar logic (the Perish function, in particular ll. 291 & 306-311) - including checking for the owner of the item; here, the perished item is deleted and a new one is spawned in. And regarding the detection itself, I'd leave it on the prefab. So, wtih all that, the suggestion would be: In your prefab .lua file, listen for the full moon. You might also want to check when the item is picked up, in case a player picks up the item during the full moon. Create a callback function that handles the transformation. Check that it's indeed full moon, that the item is in an inventory or backpack, and that the inventory or backpack is held by a player. Spawn your new item into the player's possession and delete the old item. And that should be all! Good luck! -- Spoiler Here's a possible solution, in case you need it. Untested! Spoiler -- In your prefab .lua file: local function CheckForTransformation(inst) if not TheWorld.state.isfullmoon then return end local owner = inst.components.inventoryitem ~= nil and inst.components.inventoryitem.owner or nil if not owner.HasTag("player") then return end local holder = owner ~= nil and owner.components.inventory or nil if holder ~= nil then local newItem = SpawnPrefab(YOUR_NEW_PREFAB_HERE) local slot = holder:GetItemSlot(inst) inst:Remove() holder:GiveItem(newItem, slot) end end -- In your prefab .lua file, in the main function, after checking that we're in the master sim: inst:WatchWorldState("isfullmoon", CheckForTransformation) inst:ListenForEvent("onpickup", CheckForTransformation) Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734350 Share on other sites More sharing options...
yanecc Posted July 11, 2024 Author Share Posted July 11, 2024 11 hours ago, alainmcd said: Hi, welcome to the forums! You're on the right track. Chester waits for the full moon to see if he can morph (l. 694), though the MorphChester function is actually called from his stategraph. As for how to replace the item, the perisable component has some similar logic (the Perish function, in particular ll. 291 & 306-311) - including checking for the owner of the item; here, the perished item is deleted and a new one is spawned in. And regarding the detection itself, I'd leave it on the prefab. So, wtih all that, the suggestion would be: In your prefab .lua file, listen for the full moon. You might also want to check when the item is picked up, in case a player picks up the item during the full moon. Create a callback function that handles the transformation. Check that it's indeed full moon, that the item is in an inventory or backpack, and that the inventory or backpack is held by a player. Spawn your new item into the player's possession and delete the old item. And that should be all! Good luck! -- Reveal hidden contents Here's a possible solution, in case you need it. Untested! Reveal hidden contents -- In your prefab .lua file: local function CheckForTransformation(inst) if not TheWorld.state.isfullmoon then return end local owner = inst.components.inventoryitem ~= nil and inst.components.inventoryitem.owner or nil if not owner.HasTag("player") then return end local holder = owner ~= nil and owner.components.inventory or nil if holder ~= nil then local newItem = SpawnPrefab(YOUR_NEW_PREFAB_HERE) local slot = holder:GetItemSlot(inst) inst:Remove() holder:GiveItem(newItem, slot) end end -- In your prefab .lua file, in the main function, after checking that we're in the master sim: inst:WatchWorldState("isfullmoon", CheckForTransformation) inst:ListenForEvent("onpickup", CheckForTransformation) Thank you for your prompt reply. But no luck, the code you provided causes a disconnection from the server when the full moon arrives. Currently, I am using the following code: local function OnFullMoon(inst) if not TheWorld.state.isfullmoon then return end for _, player in ipairs(AllPlayers) do for i = 1, player.components.inventory:GetNumSlots() do local item = player.components.inventory:GetItemInSlot(i) if item and item.prefab == "fhl_x" then local newItem = SpawnPrefab("fhl_x2") newItem.components.perishable:SetPercent(item.components.perishable:GetPercent()) player.components.inventory:RemoveItem(item, false) player.components.inventory:GiveItem(newItem, i) end end end end local function fn(Sim) ... inst.entity:SetPristine() if TheWorld.ismastersim then inst:WatchWorldState("isfullmoon", OnFullMoon) else return inst end ... end This code does convert items in the inventory when the full moon comes, but there are still several issues that need to be resolved: 1. When multiple fhl_x items are stacked, the converted fhl_x2 does not stay in the original slots. 2. It cannot convert items in the backpack. 3. The item has the following recipes, and during the full moon, crafting should directly yield fhl_x2, whereas at other times it should yield fhl_x. AddCharacterRecipe("fhl_x_1", { Ingredient("berries", 2), Ingredient("froglegs_cooked", 2), Ingredient("petals_evil", 1) }, TECH.NONE, { product = "fhl_x", builder_tag = "fhl" }) AddCharacterRecipe("fhl_x_2", { Ingredient("berries_juicy", 2), Ingredient("froglegs_cooked", 2), Ingredient("petals_evil", 1) }, TECH.NONE, { product = "fhl_x", builder_tag = "fhl" }) Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734485 Share on other sites More sharing options...
alainmcd Posted July 11, 2024 Share Posted July 11, 2024 Sorry that didn't work out. :-/ Might be a timing issue. Why not remove the item directly with item:Remove()? If that doesn't work, you could try to defer the removal with a DoTaskInTime(0, ...) or DoTaskInTime(1, ...). You'll need to check for items in containers. Check out the Has function in the inventory component and its checkallcontainers argument, ll. 1311-1319. Note that this loops through all open containers, including crockpots, chests and such. If you want to restrict it to equipped backpacks, check for its owner. I don't see a way to swap or remove recipes. Maybe give them different tags to check for and swap your character's tags according to the moon phase? Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734520 Share on other sites More sharing options...
yanecc Posted July 11, 2024 Author Share Posted July 11, 2024 (edited) Quote Why not remove the item directly with item:Remove()? Using item:Remove() alone increases items for some unknown reason. Now significant advancements have been made. The code below works almost as expected. local function OnFullMoon(inst) if not TheWorld.state.isfullmoon then return end for _, player in ipairs(AllPlayers) do local inventory = player.components.inventory local items = inventory:FindItems(function(item) return item.prefab == "fhl_x" end) for _, item in ipairs(items) do local newItem = SpawnPrefab("fhl_x2") local slot = inventory:GetItemSlot(item) newItem.components.stackable:SetStackSize(item.components.stackable:StackSize()) newItem.components.perishable:SetPercent(item.components.perishable:GetPercent()) inventory:RemoveItem(item, false) item:Remove() inventory:GiveItem(newItem, slot) end end end There's one last step left before reaching the goal: producing different items during the full moon period. What could be done here? To listen for a certain event to replace 'fhl_x' with 'fhl_x2' during the full moon, or update the recipe product at the beginning and end of the full moon? Edited July 11, 2024 by yanecc Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734524 Share on other sites More sharing options...
alainmcd Posted July 11, 2024 Share Posted July 11, 2024 Not sure if it'd work, but: make two recipes, one with builder_tag = "fhl_regular" and the other with builder_tag = "fhl_fullmoon", give your character the "fhl_regular" tag, listen for full moon and swap the tags accordingly. If that doesn't work, you could try the same but with tech trees: create two recipes with different, new techs; create two tech trees, one with each new tech; give your character the prototyper component; and swap out its tech tree according to the moon phase. But I'm running out of good ideas. Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734539 Share on other sites More sharing options...
yanecc Posted July 11, 2024 Author Share Posted July 11, 2024 Quote What could be done here? To listen for a certain event to replace 'fhl_x' with 'fhl_x2' during the full moon, or update the recipe product at the beginning and end of the full moon? I consulted the Tutorial and found a seemingly good implementation. All requirements in this post are now achieved, feel free to provide suggestions for further improvement! -- modmain.lua local function UseFullMoonRecipe() AddRecipePostInit("fhl_x_1", function(recipe) recipe.product = "fhl_x2" end) AddRecipePostInit("fhl_x_2", function(recipe) recipe.product = "fhl_x2" end) end local function RestoreOriginalRecipe() AddRecipePostInit("fhl_x_1", function(recipe) recipe.product = "fhl_x" end) AddRecipePostInit("fhl_x_2", function(recipe) recipe.product = "fhl_x" end) end AddPrefabPostInit("world", function(inst) inst:WatchWorldState("isfullmoon", function(inst, isfullmoon) if isfullmoon then UseFullMoonRecipe() else RestoreOriginalRecipe() end end) end) 1 Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734548 Share on other sites More sharing options...
yanecc Posted July 11, 2024 Author Share Posted July 11, 2024 As a supplement to the integrity record here, it is also necessary to add a listen for the "ms_playerjoined" event to avoid the condition that it's during the full moon night that players enter the world in which it won't trigger the "isfullmoon" check. local function CheckFullMoon() if GLOBAL.TheWorld.state.isfullmoon then UseFullMoonRecipe() end end AddPrefabPostInit("world", function(inst) inst:ListenForEvent("ms_playerjoined", CheckFullMoon) inst:WatchWorldState("isfullmoon", function(inst, isfullmoon) if isfullmoon then UseFullMoonRecipe() else RestoreOriginalRecipe() end end) end) Link to comment https://forums.kleientertainment.com/forums/topic/158131-help-how-to-replace-something-in-players-inventory-and-backpack-during-fullmoon/#findComment-1734684 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now