mathem99 Posted November 15, 2021 Share Posted November 15, 2021 (edited) Hello! I'm trying to make a body armor that will absorb 0% of all damage dealt to the player (but the armor's durability will lower based on the damage dealt by the enemy) and will make the player lose 20 health (with the additional damage dealt by the enemy). Why do I want a painful armor like that? Well I made it so that equipping said armor will make the player deal 50% more damage, but the cost is that the player should use this if they're confident they can kite well. (This code for the extra damage has already been done) Can anyone help me? Thanks for reading, -mathem99 Edited November 16, 2021 by mathem99 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/ Share on other sites More sharing options...
Wonderlarr Posted November 15, 2021 Share Posted November 15, 2021 (edited) Unfortunately there isn't an easy way to do this built in to the armor component. The way I would do this is listen for the armor's wearer's Health Delta's and the event armordamaged, and damage the armor by the amount of health lost if the armor should have been hit, as well as damaging the wearer for 20. As long as the armor itself is set to 0% protection this should work fine theoretically. I'm at work at the moment but I can help with this code if someone else hasn't already by the time I'm home. Edited November 16, 2021 by TheSkylarr 1 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/#findComment-1513324 Share on other sites More sharing options...
Wonderlarr Posted November 16, 2021 Share Posted November 16, 2021 (edited) Alright, so scratch what I commented before. The better way to do this would be to set your armor to be 100% absorption. This may sound wrong, but hear out. We can use the armordamaged event from the armor component to see how much damage to armor takes. Since the armor is taking 100% of the damage instead of the player, we can take the amount of damage the armor just took, subtract another 20, then hit the player for that much with a health delta. That should leave the player damaged for 20 + the amount they would have been damaged anyway, on top of damaging the armor for only the normal hit automatically. So, in your constructor make sure to set your absorption to 100% like so when adding your armor component. The constructor is the part of your item that adds components, tags, and sets other variables for when one of your item is spawned in the world. inst:AddComponent("armor") -- Only add the armor component once, if you already have it you can omit this line inst.components.armor:InitCondition(TUNING.ARMORWOOD, 1) -- The 1 here is the absorption, be sure change TUNING.ARMORWOOD to whatever durability variable or number you'll be using for your own armor. Unfortunately, since the absorption is technically 100% some HUD mods may display the "incorrect" value, of 100% armor. I'm not personally sure how to fix this, but players should know how this armor works in advance hopefully and ignore the fake 100% absorption. Now that the armor is the taking all the damage, we'll listen for the armor getting damaged in the OnEquip and OnUnequip functions. This should go in OnEquip inst:ListenForEvent("armordamaged", OnDamaged, inst) -- Listens for the armor getting damaged, then when it is, it calls the function OnDamaged, and passes inst to it as a variable And this in OnUnequip inst:RemoveEventCallback("armordamaged", OnDamaged, inst) -- Removes the event listener we added in OnEquip. We only want the player getting damaged while they're wearing the armor. Finally, we'll need to add this function above both OnEquip and OnUnequip to handle the damage penalty local function OnDamaged(inst, data) local owner = inst.components.inventoryitem:GetGrandOwner() -- Sets the varaible owner as the armors owner/wearer if owner and owner.components.health and owner.components.combat then -- This ensures we won't crash by checking if the things we're accessing exist owner.components.health:DoDelta(-data - 20) -- data is the variable for how much damage the armor took, -- So we make it negative, then take away an additional 20 for your damage penalty and apply it to the players health owner.components.combat:GetAttacked() -- This ensures the player still goes into hitstun, and the damage feels normal. end end Hope this helps! Don't hesitate to ask any questions, no matter how stupid you may think it is. We all need to learn somehow. Edited November 16, 2021 by TheSkylarr 1 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/#findComment-1513516 Share on other sites More sharing options...
mathem99 Posted November 16, 2021 Author Share Posted November 16, 2021 (edited) 5 hours ago, TheSkylarr said: - SNIP- I didn't mention it before but this mod is being worked for DS and your code worked like a charm! Thank-you!! If it's possible and you have the time I'd like to ask your help for another matter with another armor my mod introduces. This armor (armor_ghost) is supposed to update its Absorption amount based on the player's sanity (if owner's sanity is 100% the armor gives 60% protection, if sanity=75% then 75% protection, if sanity=0.5 then 80% protection and last if sanity=0.25 then 95% protection) What I've tried to do is this: Spoiler local assets= { Asset("ANIM", "anim/armor_ghost.zip"), } local function UpdateAbsorption(inst, owner) if owner ~= nil and owner.components.sanity >= 1 then inst.components.armor:SetAbsorption(.6) elseif owner ~= nil and owner.components.sanity >= 0.75 then inst.components.armor:SetAbsorption(.75) elseif owner ~= nil and owner.components.sanity >= 0.5 then inst.components.armor:SetAbsorption(.8) elseif owner ~= nil and owner.components.sanity >= 0.25 then inst.components.armor:SetAbsorption(.95) end end local function OnBlocked(owner) UpdateAbsorption(inst) owner.SoundEmitter:PlaySound("dontstarve/wilson/hit_nightarmour") if math.random() <= TUNING.ARMORGHOST_ATKCHANCE then local fx = SpawnPrefab("bramblefx") local x,y,z = owner.Transform:GetWorldPosition() fx.Transform:SetPosition(x,y,z) local ents = TheSim:FindEntities(x,y,z, 4,nil,{"INLIMBO"}) if #ents > 0 then for i,ent in pairs(ents)do if ent.components.combat and ent ~= owner then local src = owner if ent.components.follower and ent.components.follower.leader == owner then src = nil end ent.components.combat:GetAttacked(src, TUNING.ARMORGOST_ATKDMG, nil, "thorns") end end end end end local function OnLoad(inst, data) UpdateAbsorption(inst) end local function onequip(inst, owner) UpdateAbsorption(inst) owner.AnimState:OverrideSymbol("swap_body", "armor_ghost", "swap_body") inst:ListenForEvent("blocked", OnBlocked, owner) end local function onunequip(inst, owner) UpdateAbsorption(inst) owner.AnimState:ClearOverrideSymbol("swap_body") inst:RemoveEventCallback("blocked", OnBlocked, owner) end local function OnTakeDamage(inst) UpdateAbsorption(inst) end local function fn(Sim) local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() MakeInventoryPhysics(inst) -- MakeInventoryFloatable(inst, "idle_water", "idle_loop") inst.AnimState:SetBank("hf_armors") inst.AnimState:SetBuild("armor_hf_ghost") inst.AnimState:PlayAnimation("idle_loop") inst:AddComponent("inspectable") inst:AddComponent("inventoryitem") inst.components.inventoryitem.imagename = "armor_ghost" inst.components.inventoryitem.atlasname = "images/inventoryimages/armor_ghost.xml" inst.components.inventoryitem.foleysound = "dontstarve_DLC003/common/crafted/vortex_armour/foley" inst:AddComponent("armor") inst.components.armor:InitCondition(TUNING.ARMOR_GHOST) inst.components.armor:SetAbsorption(TUNING.ARMOR_GHOST_ABSORPTION) inst.components.armor.ontakedamage = OnTakeDamage inst:AddComponent("equippable") inst.components.equippable.equipslot = EQUIPSLOTS.BODY inst.components.equippable:SetOnEquip( onequip ) inst.components.equippable:SetOnUnequip( onunequip ) UpdateAbsorption(inst) return inst end return Prefab( "common/inventory/armor_ghost", fn, assets) Also the TUNING values I've set on another file: local TUNING = GLOBAL.TUNING TUNING.ARMOR_GHOST = 2000 TUNING.ARMOR_GHOST_ABSORPTION = .7 TUNING.ARMORGHOST_ATKCHANCE = .33 TUNING.ARMORGOST_ATKDMG = 34 I'm still working on it, maybe I can find some solution on some other in-game item, right now the game crashes and the log says: armor_ghost.lua:7: attempt to index local 'owner' (a nil value) I hope you can help. Thanks again for helping me with the original problem (I will credit you on the mod page once it gets released, unless it's against your wishes to use your name.) EDIT UPDATE 1: I had no idea how to make it work with the player's health, so I decided to make the absorption change based on the armor's own health! And it seems to have worked. This is the code I came up with: local function UpdateAbsorption(inst, owner) if inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.75) elseif inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.5 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.85) elseif inst.components.armor.condition > TUNING.ARMOR_GHOST*0.25 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.5 then inst.components.armor:SetAbsorption(0.90) elseif inst.components.armor.condition <= TUNING.ARMOR_GHOST*.25 then inst.components.armor:SetAbsorption(0.95) end end local function OnLoad(inst, data) UpdateAbsorption(inst) -- When the Player loads back in the armor will check its durability and absorption end local function OnTakeDamage(inst) UpdateAbsorption(inst) -- Everytime the armor gets hit it will recheck its condition and then apply the appropriate absorption end Edited November 16, 2021 by mathem99 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/#findComment-1513540 Share on other sites More sharing options...
Wonderlarr Posted November 16, 2021 Share Posted November 16, 2021 5 hours ago, mathem99 said: I didn't mention it before but this mod is being worked for DS and your code worked like a charm! Thank-you!! If it's possible and you have the time I'd like to ask your help for another matter with another armor my mod introduces. This armor (armor_ghost) is supposed to update its Absorption amount based on the player's sanity (if owner's sanity is 100% the armor gives 60% protection, if sanity=75% then 75% protection, if sanity=0.5 then 80% protection and last if sanity=0.25 then 95% protection) What I've tried to do is this: Reveal hidden contents local assets= { Asset("ANIM", "anim/armor_ghost.zip"), } local function UpdateAbsorption(inst, owner) if owner ~= nil and owner.components.sanity >= 1 then inst.components.armor:SetAbsorption(.6) elseif owner ~= nil and owner.components.sanity >= 0.75 then inst.components.armor:SetAbsorption(.75) elseif owner ~= nil and owner.components.sanity >= 0.5 then inst.components.armor:SetAbsorption(.8) elseif owner ~= nil and owner.components.sanity >= 0.25 then inst.components.armor:SetAbsorption(.95) end end local function OnBlocked(owner) UpdateAbsorption(inst) owner.SoundEmitter:PlaySound("dontstarve/wilson/hit_nightarmour") if math.random() <= TUNING.ARMORGHOST_ATKCHANCE then local fx = SpawnPrefab("bramblefx") local x,y,z = owner.Transform:GetWorldPosition() fx.Transform:SetPosition(x,y,z) local ents = TheSim:FindEntities(x,y,z, 4,nil,{"INLIMBO"}) if #ents > 0 then for i,ent in pairs(ents)do if ent.components.combat and ent ~= owner then local src = owner if ent.components.follower and ent.components.follower.leader == owner then src = nil end ent.components.combat:GetAttacked(src, TUNING.ARMORGOST_ATKDMG, nil, "thorns") end end end end end local function OnLoad(inst, data) UpdateAbsorption(inst) end local function onequip(inst, owner) UpdateAbsorption(inst) owner.AnimState:OverrideSymbol("swap_body", "armor_ghost", "swap_body") inst:ListenForEvent("blocked", OnBlocked, owner) end local function onunequip(inst, owner) UpdateAbsorption(inst) owner.AnimState:ClearOverrideSymbol("swap_body") inst:RemoveEventCallback("blocked", OnBlocked, owner) end local function OnTakeDamage(inst) UpdateAbsorption(inst) end local function fn(Sim) local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() MakeInventoryPhysics(inst) -- MakeInventoryFloatable(inst, "idle_water", "idle_loop") inst.AnimState:SetBank("hf_armors") inst.AnimState:SetBuild("armor_hf_ghost") inst.AnimState:PlayAnimation("idle_loop") inst:AddComponent("inspectable") inst:AddComponent("inventoryitem") inst.components.inventoryitem.imagename = "armor_ghost" inst.components.inventoryitem.atlasname = "images/inventoryimages/armor_ghost.xml" inst.components.inventoryitem.foleysound = "dontstarve_DLC003/common/crafted/vortex_armour/foley" inst:AddComponent("armor") inst.components.armor:InitCondition(TUNING.ARMOR_GHOST) inst.components.armor:SetAbsorption(TUNING.ARMOR_GHOST_ABSORPTION) inst.components.armor.ontakedamage = OnTakeDamage inst:AddComponent("equippable") inst.components.equippable.equipslot = EQUIPSLOTS.BODY inst.components.equippable:SetOnEquip( onequip ) inst.components.equippable:SetOnUnequip( onunequip ) UpdateAbsorption(inst) return inst end return Prefab( "common/inventory/armor_ghost", fn, assets) Also the TUNING values I've set on another file: local TUNING = GLOBAL.TUNING TUNING.ARMOR_GHOST = 2000 TUNING.ARMOR_GHOST_ABSORPTION = .7 TUNING.ARMORGHOST_ATKCHANCE = .33 TUNING.ARMORGOST_ATKDMG = 34 I'm still working on it, maybe I can find some solution on some other in-game item, right now the game crashes and the log says: armor_ghost.lua:7: attempt to index local 'owner' (a nil value) I hope you can help. Thanks again for helping me with the original problem (I will credit you on the mod page once it gets released, unless it's against your wishes to use your name.) EDIT UPDATE 1: I had no idea how to make it work with the player's health, so I decided to make the absorption change based on the armor's own health! And it seems to have worked. This is the code I came up with: local function UpdateAbsorption(inst, owner) if inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.75) elseif inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.5 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.85) elseif inst.components.armor.condition > TUNING.ARMOR_GHOST*0.25 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.5 then inst.components.armor:SetAbsorption(0.90) elseif inst.components.armor.condition <= TUNING.ARMOR_GHOST*.25 then inst.components.armor:SetAbsorption(0.95) end end local function OnLoad(inst, data) UpdateAbsorption(inst) -- When the Player loads back in the armor will check its durability and absorption end local function OnTakeDamage(inst) UpdateAbsorption(inst) -- Everytime the armor gets hit it will recheck its condition and then apply the appropriate absorption end Im glad you got it working, though I'm confused whether you wanted it to change based on Sanity or Health? Also, if you'd like i can help code a more elegant solution for either one, there can be rare cases where it gets applied incorrectly, like if the players health changes while wearing the armor for a non-combat reason. 1 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/#findComment-1513615 Share on other sites More sharing options...
mathem99 Posted November 16, 2021 Author Share Posted November 16, 2021 (edited) 53 minutes ago, TheSkylarr said: Im glad you got it working, though I'm confused whether you wanted it to change based on Sanity or Health? Also, if you'd like i can help code a more elegant solution for either one, there can be rare cases where it gets applied incorrectly, like if the players health changes while wearing the armor for a non-combat reason. I made the Armor's Absorption be based on the Armor's Durability (Health) instead of the Player's Sanity, it's much easier and I thought game-play wise it looks a lot more fun. As of right now the code I'm using to change the armor's absorption is this: local function UpdateAbsorption(inst, owner) if inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.75) elseif inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.5 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.85) elseif inst.components.armor.condition > TUNING.ARMOR_GHOST*0.25 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.5 then inst.components.armor:SetAbsorption(0.90) elseif inst.components.armor.condition <= TUNING.ARMOR_GHOST*.25 then inst.components.armor:SetAbsorption(0.95) end end And I haven't met any problems yet. (I made the armor go through this function automatically when you equip the armor, when you take damage and when you load in the game) Edited November 16, 2021 by mathem99 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/#findComment-1513622 Share on other sites More sharing options...
Wonderlarr Posted November 16, 2021 Share Posted November 16, 2021 (edited) 2 hours ago, mathem99 said: I made the Armor's Absorption be based on the Armor's Durability (Health) instead of the Player's Sanity, it's much easier and I thought game-play wise it looks a lot more fun. As of right now the code I'm using to change the armor's absorption is this: local function UpdateAbsorption(inst, owner) if inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.75) elseif inst.components.armor.condition >= TUNING.ARMOR_GHOST*0.5 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.75 then inst.components.armor:SetAbsorption(0.85) elseif inst.components.armor.condition > TUNING.ARMOR_GHOST*0.25 and inst.components.armor.condition < TUNING.ARMOR_GHOST*0.5 then inst.components.armor:SetAbsorption(0.90) elseif inst.components.armor.condition <= TUNING.ARMOR_GHOST*.25 then inst.components.armor:SetAbsorption(0.95) end end And I haven't met any problems yet. (I made the armor go through this function automatically when you equip the armor, when you take damage and when you load in the game) Oh i see! I suppose i misunderstood you before, I thought you were basing it off the players health, in the case of the armors remaining durability your code should be full proof! If you need any other help don't be afraid to post here again, or if you have discord, add me, I'm Skylarr#9203, and I can give you more direct help. Edited November 16, 2021 by TheSkylarr 1 Link to comment https://forums.kleientertainment.com/forums/topic/135315-solved-making-negative-armor/#findComment-1513641 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