BP Logic Question - Filling Up A Stat

I am having trouble wrapping my head around some logic and I thought someone here might be able to help me out.

So I have the player and if he is walking he is generating points, lets call them Tired Points, that will determine his overall stamina. This is based on a 0-100% scale. So if he is walking he generates 1 of these points per second. It seems extreme but I will nail out the actual variables later. If he is running he generates 5 of these points per second. If he is standing still he loses 2 of these points per second.

The total percentage determines how tired he is and when a check has to be done it will be against that result. For instance at 80% he will lose the ability to run temporarily and if he hits 100% he will lose the ability to move.

Because people often try to put things in context, lets say the player is in a radioactive area and every movement has a consequence. This is a good case for why I need to calculate this.

So:

Player Variable: TiredPoints Float 0.0 - 100.0
Walking == +1/Sec
Running == +5/Sec
Idle== -2/Sec

Bool:
Can Run T (Able to run or walk)
Can Walk T (Can walk but no longer run) F (Can no longer move/idle)

I feel like this is simple logic but I just can’t seem to get it to work any way I try.

Are you range checking the current float variable to see where it is for the bool check?

So every time you add or subtract from your Tired Variable, it does a range check and sets the bools for running and walking.

IE, +1 tired, then if range 80-99 = true, then execute disable run.

Yes, Zeustiak, I have a range from 0-79, 80-99, 100. I manually set the Tired variable to test it. That part actually works. The problem I have is the actual calculation that adds to the variable.

So far today I tried using a timeline but you can’t add the way I want. Then I tried using math adding but it wasn’t ticking at a pace that I liked. Anyone out there have an ideas?

Have you tried using a delay node?

I need something to drive the system. If I use a tick I get into the 6 figures in the blink of an eye. If I use a delay node with the tick same problem.

Here, I made a simple example of how you could go about doing this:
774ab3da3c633367f2e9d940393e87cfa5abc6a0.jpeg
(it looks a bit messy but I wanted to make sure you could see where each node connects)

Of course there are many things that would need to be added, like a check in order to not exceed the max/min TiredPoints etc. but hopefully this will get you started.

Hey thanks TK. Your method is similar to my original system. I’m getting similar results though. What happens, similar to the tick but at a much slower speed, it is always increasing. The idle never seems to kick in. Now that I have seen to different systems with similar results I have a feeling I need to revisit my other systems such as the movement bool because I think there is a problem there. I will report back when I find it.

Thanks!

So the problem is more complex than I originally figured and it does a lot to solve why the numbers ticked improperly.

My default state is “Walking”. This is the case even if the player is not moving. So I have to set two more bools; bIsMoving and bIsIdle. So I made these. The problem no is that the default status has to be Idle and when I start moving the state moves to moving and then checks to see what kind of movement is happening. Then when the player stops moving it clicks back to Idle. This, to me, seems beyond the scope of the available nodes. Is this a case where I have to find s coder to design custom nodes or is there something I am missing or that I overlooked?

So no new progress on this. I need a function to detect if a player is moving or not. If I use a series of bools I start running into a lot of operations that either stack on top of one another or that cause logic conflicts…

The next attempt was to use an array to take all of the inputs and pass the variable isMoving as true. Surprisingly simple by design and alas it does not work. Is there not anyone out there that has any thoughts? Helpful tips or tricks?

So:

OnEventBeginPlay - Set Idle = Yes

On Key Press W,A,S,D - Set Walking = Yes, Set Idle = No

  • On Key Release - Set Idle = Yes

On Key Press Shift - Set Running = Yes

  • On Key Release - Set Running = No

You can make it so that Walking sets both Speed and Stamina use. Running merely multiplies it, so if not walking but shift is held down, you don’t move and there is no stamina use.

If you have different run states or multiple ways of setting speed you can get more complicated with the bool statements and it should be able to cover every case.

In case you didn’t know, you can run multiple executions from branches into the input of another branch. So true on Branch 1 goes to Branch 2, and False on Branch 3 also goes to Branch 2. (Edit: Though now I realize this is an OR node? Wish I had made that connection days ago… :stuck_out_tongue: Boolean Operations - C++ Tutorials FTW)

If none of this helps I am sorry, I may not understand the holdup at this point.

See this is why I am having such a hard time due to logic and what seems to be my lack of understanding of how to obtain and use certain information.

So you have it right in regards to what i am checking for but that is both over complicated and simple at the same time. See checking for a key down and a key up causes problems. Say I am moving up (W) and I quickly shift right (D). For a moment I may hold both keys down so I go from a bIsMoving to another bIsMoving and when I release (W) finally, I will set off a bIsIdle even though I am still moving. So an OR might not work in this case. Or at least the way I have tried it, did not work.

Then I tried an array input for OR. This is to say W [OR] A [OR] S [OR] D == bIsMoving. I assumed that would mean any individual key at any given time would overwrite the release of another key…but that was not the case.

I figured I could use a WHILE loop for a key press but no matter how I did it, I would create infinite loops or create situations where too much data was coming through. If I added any sort of delay it would be unrealistic.

Then I explored the possibility of a WHILE loop for, WHILE moving, and completely ignoring they key press. So WHILE the player is actually moving we would just release bIsIdle thus assuming we are moving and then begin the check for what kind of movement. Although this seemed the most realistic I was unsure how to do a check for movement. I thought by monitoring animations but so far I have been unable to do it.

I feel like this is a case where having a programmer might be best because the logic, for me at least, is not working in blueprints.

So an OR for WASD on, and an AND for WASD off?

Have you tried a WhileWithBreak?

You could probably do some velocity checks, but I haven’t delved into that area so I am not sure the exact procedure.

This is all entirely doable in blueprint. All your variables and everything else can wait. Just focus on the chunk that decides what the buttons do and when they do them. When you have your booleans firing properly just make it a function and tying it to everything else should be cake.

Thanks Zuestiak. I will play with it some more and see what I come up with…after I am done beating my face into the keyboard lol.

As far as I know (and I don’t know much about animation-related stuff) the walking and running “state” is determined based on the velocity of the character’s movement component (or something like that lol)… so the first thing I would personally try is base the addition/subtraction of the “TiredPoints” on the velocity.

For example…

First check if character is falling… if it’s not then start checking the velocity… if > than 0 but less than 50 (50 is just an example) then assume that the character is walking so do the appropriate action… if the velocity is higher then assume the character is running… if the speed is ~0 then assume it’s idle etc. etc. :stuck_out_tongue:

I have no idea if that would work properly but probably worth looking into it.

A lot of cases are coming back to velocity so I am in the process of working it out that way to see the results. I want to get this to work in its current simple form and this might do it but I also have to leave it open for greater complexity later. I had a few people send me demonstrations of similar types of work but they were not built to go very advanced and could create nasty redundancies and never ending loops spinning out of control very quickly. I suppose that is why I keep this thread alive so I can find the best way.

Hopefully this evening I will post my newest results.

Thanks all so far!

you need to break it down to simplest form, and use events(including ticks) to drive and update it.
Since your case involve using a variable to control player status, and player status also affect the amount of variable, you will need to break these 2 parts clean(to avoid events call update status, and then call update variable, circular triggering.)
It’s not “simple” if you want to also expand it later on(ie food poison, buff state[regeneration for -5 tire every 1 second, and last 10 seconds], permanent state like injured[always tired, set tireMin to like 80+ ] before you get healed.).

So what can get you most flexibility? It lies in never update status and variable in the same execution line, and use functions and events to drive one at a time.
Say for update the variable, in the tick event, you call function to update it in a stream,(-> means white execution line) tick->MovementCause( check for walk/run/idle)->ItemCause(check if buff/poison)->PermaCause(check injury)
In each function you update respectively to add/reduce value. That’s the tick update part.

On the status change, you always drive with non-tick based events.
For movement input events, you query tire value to preset condition(bCanWalk(0~90)/bCanRun(0~60)), and then update your speed, and then decide your current status base on speed(idle/exhausted/walking/running through another function).
Since the moving status are mutually exclusive, you can use a enum.(need to check if is falling)

gotta go, will be back.

I finished one that does 5 status, (idle, falling, walking, running, exhausted), with a hud bar/and walking speed to reflect status change.(ie Monster Hunter stamina bar, the only difference is walking still reduce stamina)
I have one enum that have all 5 status, have one walking bool to let user force walking, one exhausted bool to make sure pawn can’t move until stamina recover to certain level, I’ve also created 2 bool(can walk/can run) but doesn’t seems to be used and only sets them.

Concept is roughly what I outlined above, but I still think it’s not that scalable yet.
I have 3 blob of graph, but unlike what I said, they are essentially in the tick line(since event gets called in tick line), so sorry about that.
first blob after tick updates stamina change based on what enum says character state is in, then 2nd blob is to call a branch graph that base on stamina changed, checks and sets conditon(exhausted/walking)/limits(max walking speed).
third blob after event call, use speed and condition(exhausted/falling[from character movemenet function]), to set respective enum status.

There is one really important part about this whole line, is it never sets or limits how you should move, it only drives state changes(maxwalkspeed is part of state).
I’ll review my BP a bit tomorrow and see if I can improve it even further and maybe throw in buff/poison effects as well.

So I finally figured it out…Well part of it. I check the vector of the character to make sure he is moving. If he is moving I then check the speed that i set based on the control input. I use the same speed variable to set the bool based on speed instead of the speed based on the bool. I think that was my original mistake.

&stc=1

Screen Shot 2014-04-28 at 7.09.52 PM.png&stc=1

&stc=1

The only thing I need to do now is manage the variables to prevent them from going outside of 0-100. Tried a while loop but that is not going to cut it. Back to the drawing board :slight_smile: