ID:2480619
 
(See the best response by Ter13.)
I am currently writing a running and stamina script
I have so far got a pretty good stamina drain
And regenerate script down however I need for
My Staminadrain() pro to have an if statement to see
If the player is moving.
Any ideas?
You'd likely want to do it in something like Move(), which is called when the player moves.

Or if you're doing something like a movement loop you can hook into that. BYOND doesn't really provide something that says whether you're moving or not, just things that are triggered as you do so.

If you wanted you could even have a simple "moving" variable that gets set to 1/true when moving and 0/false when they stop and check that.

Plenty of options.
Okay Ill try adding macros that turning isMoving to on if the player is pressing one of the movement keys
and to off if they release it. Thanks
You don't even need to do that in a macro level, just literally in your movement, like Move() like Nadrew suggested.

Here's a pro-tip, take the time to logically think about the problem and what possible solutions are.

Problem: Need to check if is-moving.
Solution: Player activates a move, go into what allows the player to move, and then make an if() check if they're moving, and then forward/output the results to what you need done.

You can solve a lot of problems/questions just based on purely typing what you need in normal speaking/typing language and then logically converting it into programming language.

Need Check Move = Use if() to check player.is_moving
What Causes Player To Move = Move() or a keyboard/mouse input.
Solution: Combine if() with Move().
Managed to solve this by hooking into my pixel movement which toggles one of 4 switches on or off for WASD and also ismoving to on and then on button release checks if the other ones are on or off then turns off ismoving if they are.

now having fun tracking down looping code.

EDIT: Found it with some usr<<"" output debugging. not sure why this piece of code was looping even though usr.stamina was above the threshold but fixed it with a return on the end.

if(usr.stamina <= 98)
usr.stamina+=5
sleep 2
RegenStam()
Best response
@maximus/Nadrew neither of your solutions are actually going to work for what OP wants. Nadrew, yours lacks the granularity OP needs, Maximus, yours is just methodologically flawed.

OP wants to reduce the player's stamina every X seconds while running. Think about it for a second. is_moving won't be true anymore when the code execution returns to his stamina drain proc. You guys have answered the title, not the question.

@OP: I would actually suggest a different system for the sake of sanity:

1) The player regenerates Z stamina per second. 0% when running, 50% when walking, 100% after Y seconds of standing still.

2) The player loses X stamina per tile moved while running. The player is unable to run for a set time after reaching exhaustion.



Let's take a look at what this stamina system would look like:

#define clamp(v,l,h) min(max(v,l),h)

mob
var
stamina = 100
max_stamina = 100

tmp
exhaust_time = -1#INF
last_step = -1#INF
last_run = -1#INF

proc
StaminaRegen()
set waitfor = 0 //don't wait on this proc when calling it.
var/regen_factor
var/time
while(src)
if(stamina<max_stamina)
time = world.time

//don't regenerate while exhausted or running
if(time - exhaust_time >= EXHAUSTION_DELAY && time - last_run >= RUN_REGEN_DELAY) //replace EXHAUSTION_DELAY with the time it takes to start regenerating stamina after reaching 0, RUN_REGEN_DELAY with the time it takes to start regenerating stamina after stopping running.

//regenerate at half speed for a set time after walking
if(time - last_step < WALK_REGEN_DELAY) //replace WALK_REGEN_DELAY with the time it takes to reach full regen speed after taking a step.
regen_factor = 0.5

else
regen_factor = 1

stamina = clamp(stamina + BASE_REGEN_SPEED * regen_factor, 0, max_stamina) //you'll need to replace BASE_REGEN_SPEED with whatever value you will use

sleep(10)


And here's the movement portion of the system:

#define MOVE_TELEPORT 0
#define MOVE_WALKING 1
#define MOVE_RUNNING 2

mob
var
move_mode = MOVE_WALKING
moving_mode = MOVE_TELEPORT

proc
Step(dir,spd,mode=move_mode)
step_size = spd
moving_mode = mode

. = step(src,dir,spd)

last_step = world.time

//keep track of stamina-related values if running
if(mode==MOVE_RUNNING) //remember moving_mode is unreliable after step() calls Move().
last_run = last_step

stamina -= RUN_STAMINA_DRAIN //you need to define this value yourself
if(stamina<=0) //check if we just exhausted ourselves
stamina = 0
exhaust_time = last_run

moving_mode = MOVE_TELEPORT



The gist of this system is that you are using world.time to keep track of things that happen to the player's stamina regeneration.

Your solution of adding it at the macro level was correct --provided the mob is always controlled by a player. This isn't always going to be the case, and you'd have to write two systems to handle your approach: one for AI and one for players, so I figured I would show you the approach that the other two with their dirty booleans were missing. Code cannot run simultaneously, so Nadrew and Maximus' answers would not work for your actual question. They were answering the literal question that you asked though, so don't think that they were wrong. They just weren't responding to your actual intended question.
Very much appreciate the time you took to write that out, I have managed to get it up and running already.
using the pixel movement script that I have, when you press was or d (or the arrow keys) it will set a player variable of wispressed to on and then also set playerIsmoving to on.
When a key is released it sets wispressed to off and then checks the other three to see if they are on.
This allows me to set a stamina regen on the character when they stop moving. This also hellpswith linking into making sound effects for my character as they move every 2 ticks the players stepcounter goes up, when it reaches a certain amount a sound is generatedthen the counter goes back down.

May i also ask how you show code properly? Thanks
Thank you.
Okay so im redoing my stamina script with the one you provided, im looking at it right now and trying to figure out how i would get the player to run.
I have tried making a verb like this
mob/verb/Run()
move_mode = MOVE_RUNNING



forgive me for being a bit dense but there is a lot of code there that is new to me.
Right. So, how I do it in my systems is that I actually use an input polling loop on the client and track key presses and key releases.

A less generalized way to do this:

client/var
list/keybinds = list()
client/verb
onRunKey(state as num|null)
set hidden = 1, set instant = 1
if(state)
mob.move_mode = MOVE_RUNNING
else
mob.move_mode = MOVE_WALKING


You would need to define two macros in your skin:

SPACE - onRunKey 1
SPACE+UP - onRunKey 0

To be honest though, I've got a pending Snippet Sunday that you might find more interesting on this subject.
Alright I'll take a look with this code today see what I can't do. Thanks.
I came up with another solution as i could not get this to work for now.