Sign in to follow this  
Silentdarkness1

How to make a tool stay on hitting 0% durability?

Recommended Posts

Silentdarkness1    1161

So, we're trying to make a tool for the player to use, that, when it hits 0% durability, instead of breaking, will go in the player inventory and stay there, unusable until it gets repaired.

I'm aware that we'd need to add a repair action, but we're struggling to actually work out how to make this happen. I did find an old thread with some code from w00tydood, but it didn't actually work. Could use a hand here on figuring out how to make this work.

Share this post


Link to post
Share on other sites
Aquaterion    821

This is all from memory but if it has an onbreak/ondeplete function, you could add a different item that acts as the broken version which spawns when the real one breaks. If not, you would probably have to adjust the armr component a bit

Share this post


Link to post
Share on other sites
Silentdarkness1    1161
6 minutes ago, Aquaterion said:

This is all from memory but if it has an onbreak/ondeplete function, you could add a different item that acts as the broken version which spawns when the real one breaks. If not, you would probably have to adjust the armr component a bit

We tried that. It didn't give the item. Going to need an example to work with.

Share this post


Link to post
Share on other sites
Ricoom    15

Well if it is using tool component then you could listen for event `toolbroke` and give player an broken item when that event is fired

Share this post


Link to post
Share on other sites
Aquaterion    821

How about you show me what you've got so far for the onfinished function? Now that I'm home I see that the onfinished function is called but it doesn't seem to have any parameters so it might not be that useful

Edited by Aquaterion

Share this post


Link to post
Share on other sites
Aquaterion    821
local function checkCondition(inst, percent)
	if percent <= 0 then
		local owner = inst.components.inventoryitem.owner
		if owner ~= nil then
			local brokenitem = GLOBAL.SpawnPrefab("broken_armor")
			owner.components.inventory:GiveItem(brokenitem)
		end
	end
end

--after adding armor component
inst:ListenForEvent("percentusedchange", checkCondition)

 

Share this post


Link to post
Share on other sites
Silentdarkness1    1161
10 minutes ago, Ricoom said:

Maybe post your code instead of making people guess what you are doing and what components you are using?

Eusong has the code for that right now. When I get in touch with her again, she can give it.

Share this post


Link to post
Share on other sites
Silentdarkness1    1161

	local assets =
{
    Asset("ANIM", "anim/lightshield.zip"),
    Asset("ANIM", "anim/swap_lightshield.zip"),
}
	local prefabs =
{
    "opalpreciousgem"
}
	
local function onbreak(inst, owner)
    local x,y,z = owner.Transform:GetWorldPosition()
    local opal = SpawnPrefab("opalpreciousgem")
    opal.Transform:SetPosition(x,y,z)
end
	local function OnBlocked(owner, attacker) 
    owner.SoundEmitter:PlaySound("dontstarve/wilson/hit_marble")
end
	local function onequip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "swap_lightshield", "swap_lightshield")
    owner.AnimState:SetMultiSymbolExchange("swap_object", "hand")
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
    inst:ListenForEvent("blocked", OnBlocked, owner)
    owner:AddTag("holdingshield")
    inst.Light:Enable(true)
end
	local function onunequip(inst, owner)
    owner.AnimState:ClearSymbolExchanges()
    owner.AnimState:Hide("ARM_carry")
    owner.AnimState:Show("ARM_normal")
    inst:RemoveEventCallback("blocked", OnBlocked, owner)
    owner:RemoveTag("holdingshield")
    inst.Light:Enable(false)
end
	--[[local function absorptionamount(inst, dt)
    if inst.components.armor.condition < inst.components.armor.maxcondition then
        inst.components.armor:SetAbsorption(inst.components.armor.condition/inst.components.armor.maxcondition)
    end
end]]--
	local function fn()
    local inst = CreateEntity()
	    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()
    inst.entity:AddSoundEmitter()
    inst.entity:AddLight()
	    MakeInventoryPhysics(inst)
	    inst.AnimState:SetBank("lightshield")
    inst.AnimState:SetBuild("lightshield")
    inst.AnimState:PlayAnimation("idle")
	    inst.entity:SetPristine()
    
    
    if not TheWorld.ismastersim then
        return inst
    end
	    inst:AddComponent("inspectable")
	    -------
	
    -------
    MakeHauntableLaunch(inst)
    -------
	
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "lightshield"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/InventoryShieldLight.xml"
    
    inst:AddComponent("armor")
    inst.components.armor:InitCondition(DURABILITYLIGHT, 0.95)
    --[[if DURABILITYLIGHT == "150" then
        inst.components.armor:InitCondition(150, 1)
    elseif DURABILITYLIGHT == "200" then
        inst.components.armor:InitCondition(200, 1)
    elseif DURABILITYLIGHT == "250" then
        inst.components.armor:InitCondition(250, 1)
    elseif DURABILITYLIGHT == "300" then
        inst.components.armor:InitCondition(300, 1)
    elseif DURABILITYLIGHT == "350" then
        inst.components.armor:InitCondition(350, 1)
    end]]--
    inst:AddTag("metal")
    inst:AddTag("ruins")
    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip(onequip)
    inst.components.equippable:SetOnUnequip(onunequip)
    inst:ListenForEvent("armorbroke", onbreak)
    
    inst:AddComponent("weapon")
    inst.components.weapon:SetDamage(0)
    
    --inst:DoPeriodicTask(1, function() absorptionamount(inst, 1) end)
    inst.Light:SetIntensity(.75)
    inst.Light:SetColour(252 / 255, 251 / 255, 237 / 255)
    inst.Light:SetFalloff(.6)
    inst.Light:SetRadius(10)
    inst.Light:Enable(true)
    
	    return inst
end
return Prefab("common/inventory/lightshield", fn, assets, prefabs)

Edited by Silentdarkness1

Share this post


Link to post
Share on other sites
Ricoom    15

it seems event is never caught. I am not that familiar yet with the event system but could you try 

inst.components.inventoryitem.owner:ListenForEvent("armorbroke", onbreak)

instead of 

inst:ListenForEvent("armorbroke", onbreak)

 

Share this post


Link to post
Share on other sites
Silentdarkness1    1161
12 minutes ago, Ricoom said:

it seems event is never caught. I am not that familiar yet with the event system but could you try 


inst.components.inventoryitem.owner:ListenForEvent("armorbroke", onbreak)

instead of 


inst:ListenForEvent("armorbroke", onbreak)

 

[00:01:20]: [string "../mods/Shields - Unfinished/scripts/prefab..."]:104: attempt to index field 'owner' (a nil value) LUA ERROR stack traceback: ../mods/Shields - Unfinished/scripts/prefabs/lightshield.lua:104 in (field) fn (Lua) <48-118> scripts/mainfunctions.lua:206 in () ? (Lua) <195-237> =[C]:-1 in (method) SpawnPrefab (C) <-1--1> scripts/mainfunctions.lua:254 in (global) SpawnPrefab (Lua) <248-256> scripts/util.lua:24 in (global) DebugSpawn (Lua) <20-31> scripts/consolecommands.lua:365 in (global) c_give (Lua) <361-376> c_give("lightshield"):1 in () ? (main) <0-0> =[C]:-1 in (global) pcall (C) <-1--1> scripts/mainfunctions.lua:1409 in (global) ExecuteConsoleCommand (Lua) <1401-1418> scripts/screens/consolescreen.lua:146 in (method) Run (Lua) <133-148> scripts/screens/consolescreen.lua:159 in (field) fn (Lua) <157-164> scripts/scheduler.lua:177 in (method) OnTick (Lua) <155-207> scripts/scheduler.lua:371 in (global) RunScheduler (Lua) <369-377> scripts/update.lua:170 in () ? (Lua) <149-228>

We added this to the code....

inst:DoPeriodicTask(5, function() if inst.components.inventoryitem.owner ~= nil then inst.components.inventoryitem.owner:ListenForEvent("armorbroke", onbreak) end end)

 

And got this instead:

[00:01:58]: [string "../mods/Shields - Unfinished/scripts/prefab..."]:14: attempt to index field 'Transform' (a nil value) LUA ERROR stack traceback: ../mods/Shields - Unfinished/scripts/prefabs/lightshield.lua:14 in (local) fn (Lua) <13-17> scripts/entityscript.lua:1035 in (method) PushEvent (Lua) <1022-1049> scripts/components/armor.lua:7 in (local) fn (Lua) <1-10> scripts/entityscript.lua:1035 in (method) PushEvent (Lua) <1022-1049> scripts/components/armor.lua:77 in (method) SetCondition (Lua) <71-90> scripts/components/armor.lua:133 in (method) TakeDamage (Lua) <132-138> scripts/components/inventory.lua:285 in (method) ApplyDamage (Lua) <252-290> scripts/components/combat.lua:417 in (method) GetAttacked (Lua) <405-480> scripts/components/combat.lua:843 in (method) DoAttack (Lua) <793-867> scripts/stategraphs/SGhound.lua:72 in (field) fn (Lua) <72-72> scripts/stategraph.lua:568 in (method) UpdateState (Lua) <536-580> scripts/stategraph.lua:607 in (method) Update (Lua) <599-627> scripts/stategraph.lua:125 in (method) Update (Lua) <109-148> scripts/update.lua:218 in () ? (Lua) <149-228>

 

EDIT: We fixed it. Had to use inst instead of owner.

Edited by Silentdarkness1

Share this post


Link to post
Share on other sites
Ricoom    15

well one way would be to add the listener onequip and remove it on unequip try putting the listener inside onequip. its due to the fact that you are trying to listen for the owner event before the inventory item has owner and thats why its crashing. your way works as well but the error you get then is from the fact that 

owner.Transform 

does not exist as in that event owner is not passed directly it passes the armor component instance instead 

inst.components.inventoryitem.owner:PushEvent("armorbroke", { armor = inst })

you could try changing 

 local x,y,z = owner.Transform:GetWorldPosition()

 

to this 

 local x,y,z = inst.components.inventoryitem.owner.Transform:GetWorldPosition()

 

PS: using 

inst:DoPeriodicTask

is kinda bad as even the smallest task when done in loop will eat up conciderable amount of resources. I suggest looking into setting instance variable as eventlister onequip and removing it onunequip

Edited by Ricoom

Share this post


Link to post
Share on other sites
pedregales    480

I cannot give much help in terms of code, but maybe you would like to go into Bernie and bone armor's files; both do what you are looking for (have health, but stay after it reaches 0), and the bone armor is even an armor (the prefab name is "armorskeleton" BTW).

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this