ArsFelenlis Posted February 15, 2025 Share Posted February 15, 2025 I'm currently in the middle of trying to create a custom item for my character which is essentially a craftable medpack that can be "repaired" / refilled with honey or some other item So far I have managed to make a healing item that had the percent display from finiteuse code, and even the repair part thanks to another post on this forum (which is still a bit wonky but it does semi-work, just that it only repair the item to full instead of maybe 10-20% like I wanted) But what I couldn't figure out is the more than one healing part, since no matter the percentage, the item is fully consumed and disappears immediately as opposed to going down to zero and simply not breaking I figured this might've something to do with the regular "healer" component since I did look at the healer.lua and found that it says the following at the bottom: Spoiler if self.inst.components.stackable ~= nil and self.inst.components.stackable:IsStack() then self.inst.components.stackable:Get():Remove() else self.inst:Remove() end Now, I must admit that I know practically nothing about how most of the code work, but I am assuming that meant that the item is consumed and removed from inventory once used. Which, then lead me to try and create an alternative healing component that in theory shouldn't remove the item once it is used, although that's where I then ran into a problem where the healing option just doesn't appear at all, so there's a likely chance i messed up the copying process somewhere But that makes me wonder if the whole new healer component thing was completely pointless from the start and I could've just used the original healer component if I had known how to set the finiteuse up properly, or if I was right to assume that I did indeed need to make a seperate healer component and the only way I can make this work was to figure out how to copy and edit the original healer component. This here is my lua file for the item itself: Spoiler local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() inst.entity:AddNetwork() MakeInventoryPhysics(inst) inst.AnimState:SetBank("bandage") inst.AnimState:SetBuild("bandage") inst.AnimState:PlayAnimation("idle") MakeInventoryFloatable(inst) inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end inst:AddComponent("inspectable") inst:AddComponent("inventoryitem") inst:AddComponent("repeathealer") inst.components.repeathealer:SetHealthAmount(15) MakeHauntableLaunch(inst) inst:AddComponent("finiteuses") inst.components.finiteuses:SetMaxUses(10) inst.components.finiteuses:SetUses(9) inst.components.finiteuses:SetConsumption(ACTIONS.REHEAL, 1) inst:AddComponent("repairable") inst.components.repairable.repairmaterial = "honey" return inst end return Prefab("traumakit", fn, assets) Link to comment https://forums.kleientertainment.com/forums/topic/164120-is-it-possible-to-make-a-healing-item-that-had-a-finite-use-but-repairable/ Share on other sites More sharing options...
Haruhi Kawaii Posted February 16, 2025 Share Posted February 16, 2025 20 hours ago, ArsFelenlis said: I'm currently in the middle of trying to create a custom item for my character which is essentially a craftable medpack that can be "repaired" / refilled with honey or some other item So far I have managed to make a healing item that had the percent display from finiteuse code, and even the repair part thanks to another post on this forum (which is still a bit wonky but it does semi-work, just that it only repair the item to full instead of maybe 10-20% like I wanted) But what I couldn't figure out is the more than one healing part, since no matter the percentage, the item is fully consumed and disappears immediately as opposed to going down to zero and simply not breaking I figured this might've something to do with the regular "healer" component since I did look at the healer.lua and found that it says the following at the bottom: Reveal hidden contents if self.inst.components.stackable ~= nil and self.inst.components.stackable:IsStack() then self.inst.components.stackable:Get():Remove() else self.inst:Remove() end Now, I must admit that I know practically nothing about how most of the code work, but I am assuming that meant that the item is consumed and removed from inventory once used. Which, then lead me to try and create an alternative healing component that in theory shouldn't remove the item once it is used, although that's where I then ran into a problem where the healing option just doesn't appear at all, so there's a likely chance i messed up the copying process somewhere But that makes me wonder if the whole new healer component thing was completely pointless from the start and I could've just used the original healer component if I had known how to set the finiteuse up properly, or if I was right to assume that I did indeed need to make a seperate healer component and the only way I can make this work was to figure out how to copy and edit the original healer component. This here is my lua file for the item itself: Hide contents local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() inst.entity:AddNetwork() MakeInventoryPhysics(inst) inst.AnimState:SetBank("bandage") inst.AnimState:SetBuild("bandage") inst.AnimState:PlayAnimation("idle") MakeInventoryFloatable(inst) inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end inst:AddComponent("inspectable") inst:AddComponent("inventoryitem") inst:AddComponent("repeathealer") inst.components.repeathealer:SetHealthAmount(15) MakeHauntableLaunch(inst) inst:AddComponent("finiteuses") inst.components.finiteuses:SetMaxUses(10) inst.components.finiteuses:SetUses(9) inst.components.finiteuses:SetConsumption(ACTIONS.REHEAL, 1) inst:AddComponent("repairable") inst.components.repairable.repairmaterial = "honey" return inst end return Prefab("traumakit", fn, assets) You will need to add AddComponentAction for your new component to make it work. Another way is to hook into the healer component, and you can also use this simple method inst:AddComponent("healer") inst.components.healer:SetHealthAmount(TUNING.HEALING_MEDLARGE) inst.components.healer.Heal = function(inst, target, doer, ...) if target.components.health then --[[Add health, finiteuses check or something you use to make sure it doesn't crash ]] target.components.health:DoDelta(1) return true end end Link to comment https://forums.kleientertainment.com/forums/topic/164120-is-it-possible-to-make-a-healing-item-that-had-a-finite-use-but-repairable/#findComment-1797999 Share on other sites More sharing options...
ArsFelenlis Posted February 16, 2025 Author Share Posted February 16, 2025 30 minutes ago, Haruhi Kawaii said: You will need to add AddComponentAction for your new component to make it work. Another way is to hook into the healer component, and you can also use this simple method inst:AddComponent("healer") inst.components.healer:SetHealthAmount(TUNING.HEALING_MEDLARGE) inst.components.healer.Heal = function(inst, target, doer, ...) if target.components.health then --[[Add health, finiteuses check or something you use to make sure it doesn't crash ]] target.components.health:DoDelta(1) return true end end I actually did manage to figure it out like less than an hour ago xD Now I'm mostly just figuring out the custom repair part since it kinda broke along the way (Granted I aboslutely could just use an easy method and make it say repair when I hover item over it, but for some reason I decided to make a custom component for it as well so it'd say "Refill" when I'm trying to repair Not sure how or what did it but I was finally able to create a proper working copy of the healer component without the remove upon consumption part So now it uses the finiteuse component properly, albeit with it continuing to work after it's at zero, so I just added another function to take away the custom healer component once its at zero use and add it back once it got more than >=10 uses And yes I already did had the AddComponent action, I just didn't copy it properly for some reason but it now works And nope, I also learned that I simply just can't use the game's built in healer component since they specifically have a part where they remove the item upon use, so I did indeed need to make that new copy of the healer component while cutting that part of the code out Thank you for your input anyway though! Link to comment https://forums.kleientertainment.com/forums/topic/164120-is-it-possible-to-make-a-healing-item-that-had-a-finite-use-but-repairable/#findComment-1798011 Share on other sites More sharing options...
GodIess Posted February 21, 2025 Share Posted February 21, 2025 On 2/16/2025 at 2:22 PM, ArsFelenlis said: I actually did manage to figure it out like less than an hour ago xD Now I'm mostly just figuring out the custom repair part since it kinda broke along the way (Granted I aboslutely could just use an easy method and make it say repair when I hover item over it, but for some reason I decided to make a custom component for it as well so it'd say "Refill" when I'm trying to repair Not sure how or what did it but I was finally able to create a proper working copy of the healer component without the remove upon consumption part So now it uses the finiteuse component properly, albeit with it continuing to work after it's at zero, so I just added another function to take away the custom healer component once its at zero use and add it back once it got more than >=10 uses And yes I already did had the AddComponent action, I just didn't copy it properly for some reason but it now works And nope, I also learned that I simply just can't use the game's built in healer component since they specifically have a part where they remove the item upon use, so I did indeed need to make that new copy of the healer component while cutting that part of the code out Thank you for your input anyway though! You could simply rewrite the function using AddComponentPostInit, adding a variable, and if it was true, then not delete the item after use, but reduce the number of uses, it's very simple and will not affect other mods if done correctly AddComponentPostInit("healer", function(self, inst) function self:Heal(target, doer) local health = target.components.health if health == nil then return false end if self.canhealfn ~= nil then local valid, reason = self.canhealfn(self.inst, target, doer) if not valid then return false, reason end end if health.canheal then -- NOTES(JBK): Tag healerbuffs can make this heal function be invoked but we do not want to apply health to things that can not be healed. health:DoDelta(self.health, false, self.inst.prefab) end if self.onhealfn ~= nil then self.onhealfn(self.inst, target, doer) end if self.dont_remove then -- add this return true end if self.inst.components.stackable ~= nil and self.inst.components.stackable:IsStack() then self.inst.components.stackable:Get():Remove() else self.inst:Remove() end return true end end 1 Link to comment https://forums.kleientertainment.com/forums/topic/164120-is-it-possible-to-make-a-healing-item-that-had-a-finite-use-but-repairable/#findComment-1800492 Share on other sites More sharing options...
oregu Posted February 22, 2025 Share Posted February 22, 2025 (edited) On 2/21/2025 at 4:30 PM, GodIess said: You could simply rewrite the function using AddComponentPostInit, adding a variable, and if it was true, then not delete the item after use, but reduce the number of uses, it's very simple and will not affect other mods if done correctly I would recommend making a new fuelsource in modmain.lua and use the fueled compoennt. Seems to match your needs the most. Spoiler GLOBAL.FUELTYPE.HONEY = "HONEY" --++ alain AddPrefabPostInit("honey", function(inst) if not GLOBAL.TheWorld.ismastersim then return end inst:AddComponent("fuel") inst.components.fuel.fueltype = GLOBAL.FUELTYPE.HONEY inst.components.fuel.fuelvalue = GLOBAL.TUNING.MED_LARGE_FUEL -- to assign fuel strength see tuning.lua end) PrefabFiles = { "testitem", } Assets = { Asset("ANIM", "anim/bandage.zip"), } Then in your itemtesting.lua (rename it to what you want it to be) Spoiler local assets = { Asset("ANIM", "anim/bandage.zip"), } local function MakeHealer(inst) local icf = inst.components.fueled if not icf then print(inst, "error, no fueled component") return end -- Fueled is supposed to exist by now -- suggest: PlayAnimation"idle" inst:AddComponent"healer" local ich = inst.components.healer ich:SetHealthAmount(TUNING.HEALING_MED) local Heal_old = ich.Heal local Remove_real = ich.inst.Remove ich.Heal = function(...) ich.inst.Remove = function() return end -- No item removed on heal local result, reason = Heal_old(...) ich.inst.Remove = Remove_real return result, reason end ich:SetOnHealFn(function(inst, target, doer) icf:DoDelta(-TUNING.MED_FUEL) if not icf.accepting then icf.accepting = true end return true end) ich:SetCanHealFn(function(inst, target, doer) if not icf:IsEmpty() then return true else return false, "NO_HEALER_FUEL" -- Not sure if will be said end end) end local function MakeFueled(inst) inst:AddComponent"fueled" local icf = inst.components.fueled local USES = 3 icf.fueltype = FUELTYPE.HONEY icf:InitializeFuelLevel(USES * TUNING.MED_FUEL) icf:SetDepletedFn(function() inst:RemoveComponent"healer" -- suggest: PlayAnimation"broken" end) icf:SetCanTakeFuelItemFn(function(inst, item, doer) return item.prefab == "honey" and not icf:IsFull() -- just in case end) local takesound = "dontstarve/creatures/monkey/poopsplat" inst.components.fueled:SetTakeFuelFn(function(inst) -- from amulet.lua if not inst.components.healer then MakeHealer(inst) end if icf:IsFull() then icf.accepting = false end local owner = inst.components.inventoryitem.owner if owner == nil then inst.SoundEmitter:PlaySound(takesound) else inst.playfuelsound:push() if not TheNet:IsDedicated() then local parent = inst.entity:GetParent() local container = parent ~= nil and (parent.replica.inventory or parent.replica.container) or nil if container ~= nil and container:IsOpenedBy(ThePlayer) then TheFocalPoint.SoundEmitter:PlaySound(takesound) end end end end) local SetPercent_old = icf.SetPercent icf.SetPercent = function(self, ...) -- in case a scenario where this gets spawned with this function happens SetPercent_old(self, ...) if not self:IsFull() then self.accepting = true end -- OnDepleted handles self:IsEmpty() end end local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() inst.entity:AddNetwork() MakeInventoryPhysics(inst) inst.AnimState:SetBank("bandage") inst.AnimState:SetBuild("bandage") inst.AnimState:PlayAnimation("idle") inst.playfuelsound = net_event(inst.GUID, "traumakit.playfuelsound") MakeInventoryFloatable(inst) inst.entity:AddSoundEmitter() -- add sound emitter inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end inst:AddComponent("inspectable") inst:AddComponent("inventoryitem") inst.components.inventoryitem.imagename = "bandage" --not sure why it doesnt show up otherwise MakeFueled(inst) MakeHealer(inst) MakeHauntableLaunch(inst) return inst end return Prefab("testitem", fn, assets) All I really did was patch together something similar to amulet.lua on your component and then overwrote the heal component like Godless did, but more precisely. I think MakeForgeRepairable could be most accurately you're looking for but I was a bit intimidated because it's new/undocumented and wasn't sure about a lot of stuff with it. Didn't want to implement something poorly. But fueled does the same thing in this way but uses a different action name. Edited February 23, 2025 by oregu 1 Link to comment https://forums.kleientertainment.com/forums/topic/164120-is-it-possible-to-make-a-healing-item-that-had-a-finite-use-but-repairable/#findComment-1800595 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