Jump to content

Recommended Posts

Looking at the built-in components only seems to have made things more confusing, and there's no mod I can find that REALLY has what i'm looking for.

To address this point, you're not thinking abstractly enough. You should first think about what you need to have happen rather than start off looking for information about how to do it.

Here's how you should be thinking about this problem:

1. When sanity becomes low, I need to start draining health

2. When sanity is no longer low, I need to stop draining health

Now you have some things you need your code to be able to do:

1. Detect whenever sanity drops below a certain threshold

2. Detect whenever sanity goes above a certain threshold

3. Drain health periodically

Numbers 1 and 2 can be done by listening for the "sanitydelta" event. Number 3 can be done using DoPeriodicTask or a component Update function.

To address this point, you're not thinking abstractly enough. You should first think about what you need to have happen rather than start off looking for information about how to do it.

Here's how you should be thinking about this problem:

1. When sanity becomes low, I need to start draining health

2. When sanity is no longer low, I need to stop draining health

Now you have some things you need your code to be able to do:

1. Detect whenever sanity drops below a certain threshold

2. Detect whenever sanity goes above a certain threshold

3. Drain health periodically

Numbers 1 and 2 can be done by listening for the "sanitydelta" event. Number 3 can be done using DoPeriodicTask or a component Update function.

 

As for draining health periodically, that would be ideal, since he could just stop the task.

 

However, in the health component, DoDelta does has a parameter for overtime (which he is using), which doesn't seem to work as I would imagine.

Okay. Now it's an "attempt to index nil value error" on the same line. I tried including the function type in the parentheses but that didn't change anything.

That sounds about right. The player does not exist at the moment you want to listen for the event.

To fix it. You do the same thing as you did for addcomponent post init.

AddSimPostInit(function()

Global.........

end)

I don't know if that is the function. I know there is one fo sim post init.

Edited by RazvanM

As for draining health periodically, that would be ideal, since he could just stop the task.

 

However, in the health component, DoDelta does has a parameter for overtime (which he is using), which doesn't seem to work as I would imagine.

Not familiar with the overtime parameter, but that is still thinking too far ahead. No matter what, he's still going to to need to be able to start and stop draining health based on sanity level. That's what he should get working first, then he can move on to the more specific implementation details.

Silentdarkness1, here's a basic example of a possible implementation without using a component (as a component is not really necessary in this instance):

(note: this would all be in modmain.lua)

local function DrainHealthBasedOnSanity(inst)    local health_to_drain = 1    -- alter health_to_drain based on inst.components.sanity:GetPercent()    inst.components.health:DoDelta(-health_to_drain)endlocal health_drain_task = nillocal function OnSanityChange(inst, data)    local threshold = .5 -- 50 percent    local drain_period = 1 -- 1 second    -- if we are not draining health and sanity is below the threshold    if not health_drain_task and inst.components.sanity:GetPercent() <= threshold then        -- drain health        health_drain_task = inst:DoPeriodicTask(drain_period, DrainHealthBasedOnSanity)    -- if we are draining health and sanity is above the threshold    elseif health_drain_task and inst.components.sanity:GetPercent() > threshold then        -- stop draining health        health_drain_task:Cancel()        health_drain_task = nil    endendAddSimPostInit(function(inst)    -- inst is the player in a SimPostInit callback    inst:ListenForEvent("sanitydelta", OnSanityChange)end)
Edited by squeek

Thank you a bunch @squeek

 

NOW. What I want to be able to vary here, is the amount of health lost. To something much slower than is there right now. Delta would likely take care of things in the most accurate way. The lower the sanity, the more health drained per minute, starting at 1 HP per minute when at less than 50% maximum sanity, scaling up to 7 HP a minute when at 0 sanity.

 

For now, merely getting the damage to scale up at certain sanity thresholds would suffice.

Edited by Silentdarkness1

See the comment in DrainHealthBasedOnSanity and the drain_period variable in OnSanityChange.

You also need to figure out what "drain x health per minute" means. Is that a drain over time or is that x health lost in 60 second ticks? If you want health to be lost in 60 second intervals, just change drain_period to 60.

Edited by squeek

I want a drain over time. Complete with the down arrow on the health widget. I know that's a thing because I see it when the player is on fire.

 

Actually, the comments have very informational. Extra thanks for that.

Edited by Silentdarkness1

Simply a matter of setting up your conditionals correctly.

 

-- default valuelocal output_value = 1-- smallest firstif input_value <= 0.1 then    output_value = 8elseif input_value <= 0.25 then    output_value = 4elseif input_value <= 0.5 then    output_value = 2end
That'll make it so that 0-0.1 will set output_value to 8, 0.1-0.25 will set output_value to 4, 0.25-0.5 will set output_value to 2, and 0.5-1 will set output_value to 1.

You could also create an algorithm that converts the values automatically, something like:

local input_value = inst.components.sanity:GetPercent()-- output_value would be a smooth curve from 1 to 10output_value = 1 / math.max(0.1, input_value)
I may still be misunderstanding what you're asking, though, as I'm confused by your use of 'threshold' in your last post. A threshold is, by definition, a single value. Edited by squeek

Well, I call it threshold because that's what you labeled the variable.

 

A range, rather.

Yeah, but that variable only controls when health starts and stops being drained. You can't make that a "range", as you're either above or below the threshold at all times.

Note, though, that this line:

elseif health_drain_task and inst.components.sanity:GetPercent() > threshold then
takes into account ANY value above the threshold (and vice versa for the less than check).

I still don't really know what you're asking.

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
×
  • Create New...