Jump to content

Checking if health is below a certain point


Recommended Posts

Hello everyone,

 

I've recently gone and created my first character mod. She has a couple of perks already that I got working myself. I'm stuck at detecting if her health is below 25%, and if that's the case, it has a 30% chance that it spawns a friendly shadowcreature that defends her.

 

I've got the spawning/follower part working (using The Nightmare character mod as referrence) but again I'm stuck at detecting how much health she has. I've looked at how the Meat Effigy works and I've tried using the way it checks if the player has enough health, but that didn't work.

I also looked at the crafting recipe for the Telltale Heart since I thought that checked for how much health the player has (which it does, but it uses the player health as an ingredient which is not what I'm looking for).

Now I've looked inside health.lua and I tried using this code;

function oncurrenthealth(self, currenthealth)
 
    if self.inst.replica.health(currenthealth <= 25) then
inst.OnDespawn = OnDespawn
    inst.SpawnTerrorbeakpet = SpawnTerrorbeakpet
    inst:DoTaskInTime(0, function(inst) SpawnTerrorbeakpet(inst) end)
    onpercent(self)
end
end
 
Now it doesn't crash, but it still doesn't spawn it.
I'm pretty sure the code is just wrong, but I don't know if I'm on the right track or not.
 
Any help would be appreciated!
Ryan
Link to comment
Share on other sites

As far as I remember, there is an event pushed when a DoDelta is executed on the health component of an entity. So you could listen for this event and check the current health when this is pushed.

 

EDIT:

from health.lua

function Health:DoDelta(amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)    if self.redirect ~= nil then        self.redirect(self.inst, amount, overtime, cause)        return    end    if not ignore_invincible and (self.invincible or self.inst.is_teleporting == true) then        return    end    if amount < 0 and not ignore_absorb then        amount = amount - amount * self.absorb        if afflicter ~= nil and afflicter:HasTag("player") then            amount = amount - amount * self.playerabsorb        end    end    local old_percent = self:GetPercent()    self:SetVal(self.currenthealth + amount, cause, afflicter)    local new_percent = self:GetPercent()    self.inst:PushEvent("healthdelta", { oldpercent = old_percent, newpercent = self:GetPercent(), overtime = overtime, cause = cause, afflicter = afflicter, amount = amount })    if self.ondelta ~= nil then        self.ondelta(self.inst, old_percent, self:GetPercent())    endend

So just listen for the "healthdelta" event and check data.newpercent

Edited by ZupaleX
Link to comment
Share on other sites

As far as I remember, there is an event pushed when a DoDelta is executed on the health component of an entity. So you could listen for this event and check the current health when this is pushed.

 

EDIT:

from health.lua

function Health:DoDelta(amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)    if self.redirect ~= nil then        self.redirect(self.inst, amount, overtime, cause)        return    end    if not ignore_invincible and (self.invincible or self.inst.is_teleporting == true) then        return    end    if amount < 0 and not ignore_absorb then        amount = amount - amount * self.absorb        if afflicter ~= nil and afflicter:HasTag("player") then            amount = amount - amount * self.playerabsorb        end    end    local old_percent = self:GetPercent()    self:SetVal(self.currenthealth + amount, cause, afflicter)    local new_percent = self:GetPercent()    self.inst:PushEvent("healthdelta", { oldpercent = old_percent, newpercent = self:GetPercent(), overtime = overtime, cause = cause, afflicter = afflicter, amount = amount })    if self.ondelta ~= nil then        self.ondelta(self.inst, old_percent, self:GetPercent())    endend

So just listen for the "healthdelta" event and check data.newpercent

 

Hey, thanks for the answer! I'm sorry if I sound a bit noobish, but how exactly can I check for data.newpercent? I've got this right now:

local fn = function(inst)
inst:ListenForEvent("healthdelta", data.newpercent)
if data.newpercent <= 25 then
inst.OnDespawn = OnDespawn
inst.SpawnTerrorbeakpet = SpawnTerrorbeakpet
inst:DoTaskInTime(0, function(inst) SpawnTerrorbeakpet(inst) end)
end 
end
It doesn't crash, but it still doesn't do anything.
Thank you in advance!
Edited by RyanandLink
Link to comment
Share on other sites

It's because you're not using the ListenForEvent properly.

 

ListenForEvent take up to 3 arguments

 

First Argument: is the event you want your entity to listen to.

 

Second Argument:  is the function to execute when the event is triggered. This function typically can take up to 2 arguments itself.

  1. The entity at the source of the event pushed.
  2. The second one are the data passed when the event is pushed. You can see that when healthdelta is pushed, 2 parameters are given to PushEvent : the name of the event and a table. This table is the "data" with its several members which vary for each event.

Third Argument: is the source of the event, in an other word, which entity pushed the event. By default, if left blank, an entity will listen to event pushed by itself.

 

So here you make your entity listen for the event "healthdelta" (your first parameter) pushed by itself (your third parameter which is not provided, so the entity itself by default) and then tells it to execute the function "data.newpercent". It's a wonder it's not crashing because data.newpercent is not defined so I don't know what it's doing.

 

What you should do then

local function OnHealthDelta(src, data)     if data.newpercent <= 25 then          do your stuffs here     end endlocal fn = function(inst)     [...]     inst:ListenForEvent("healthdelta", OnHelthDelta)     [...]end

I wrote all of this from what I remember last time I used it so maybe I made a mistake but you should at least have the general idea.

Edited by ZupaleX
Link to comment
Share on other sites

@ZupaleX, Thank you for your answer, and I really don't mean to be clingy, but it still doesn't seem to work. Even copy/pasting what you wrote  doesn't work (changing "OnHelthDelta" to "OnHealthDelta", I assumed that's what you meant) because it gives me the error ')' expected near ',' . I got it not to crash by changing it to this:

local fn = function(inst)
isnt:ListenForEvent("healthdelta", OnHealthDelta)
end
local function OnHealthDelta(inst, data, src)
if data.newpercent <=25 then
   inst.OnDespawn = OnDespawn
inst.SpawnTerrorbeakpet = SpawnTerrorbeakpet
inst:DoTaskInTime(0, function(inst) SpawnTerrorbeakpet(inst) end)  
end
end
But it still does nothing. I'm sorry if I'm bothering you with this but I'm really trying to get this to work.
 
I'll post my lua file, if it is of any help. 

keri.lua

Link to comment
Share on other sites

I obviously forgot the "function" between "local" and "OnHealthDelta" (btw, it was indeed a typo but it's just a name you give to your function so it won't make an issue when executed). I corrected it on my previous post.

 

The issue is that I don't know what you're trying to do with the lines

inst.OnDespawn = OnDespawninst.SpawnTerrorbeakpet = SpawnTerrorbeakpetinst:DoTaskInTime(0, function(inst) SpawnTerrorbeakpet(inst) end)  

Well, to be precise I do not know why you want to put that there.

 

I will download your keri.lua tomorrow and check it out, I guess it'll make more sense. But now I go to sleep :razz:

 

EDIT: I changed my mind and took a look at your file. Here is a modified version with comments.

Btw, I don't know what you want to achieve with all these "OldEat" stuffs but it's probably not doing what you want it do do.

keri.lua

Edited by ZupaleX
Link to comment
Share on other sites

@ZupaleX, Alright! Thank you so much for helping me out, you have no idea how happy I am with this! I tried getting this to work for 8 hours straight yesterday... Thinking back, I probably should have taken a break or three... Anyways, I completely forgot that 1 equals to 100 in Don't Starve. I don't know if my code would have worked with the 0.25 instead of 25, but thats fine!

 

Ps: the "OldEat" stuff makes it so that she gets a bit of sanity when eating certain foods (fruits) since there is no seperate "genre" for fruits like there are for veggies (I think). If I put it all on the same line ((dragonfruit, dragonfruit_cooked, berries) etc.), it still gave sanity when eating vegetables... Don't know why, but it works now, so I'm happy with it. 

 

Thanks again!

Link to comment
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
 Share

×
  • Create New...