ID:159652
 
Well, I have a cooldown thing, and its like this
VarName="1"
sleep(300)
Varname="0"

It works fine for the cooldown part, but how do I display how much Sleep is left?

So it would say like "You need to wait 257 more seconds before you can use this again"
You'd need to establish a variable to represent the value in the sleep() delay. And for something like that, I'd recommend you use spawn loop() instead ;p That way, it won't interfere with any other processes being called by the player.

mob/var/delay //define a mob var to withhold the sleep delay value
mob/verb/Verby_Verby()
if(!VarName)
usr<<"You have [delay/10] seconds left!"
return
delay = 600 //1 minute
VarName = FALSE
spawn while(delay)
sleep(1)
delay--
if(!delay) VarName = TRUE


Untested, so it might have something funky with it.

EDIT
Woops, had the var precede its definition...
EDIT2
Fixed again...
VarName="1"
for(var/k in 300 to 1)
TimeRemaining = k
sleep(1)
VarName="0"
In response to Immibis
That for() won't work without step -1 added after the "300 to 1" and before the ")".
In response to Immibis
Xyphon101 wrote:
It works fine for the cooldown part, but how do I display how much Sleep is left?

So it would say like "You need to wait 257 more seconds before you can use this again"

Nice job answering that question >_>
In response to Jeff8500
Jeff8500 wrote:
That for() won't work without step -1 added after the "300 to 1" and before the ")".

I took that and put in the step -1. Now it displays 300 and only goes down like every minute!

Plus it always says "You have to wait before using it again"
In response to Xyphon101
Try using mine? >_>
In response to Spunky_Girl
Spunky_Girl wrote:
You'd need to establish a variable to represent the value in the sleep() delay. And for something like that, I'd recommend you use spawn loop() instead ;p That way, it won't interfere with any other processes being called by the player.

> mob/var/delay //define a mob var to withhold the sleep delay value
> mob/verb/Verby_Verby()
> if(!VarName)
> usr<<"You have [delay/10] seconds left!"
> return
> delay = 600 //1 minute
> VarName = FALSE
> spawn while(delay)
> sleep(1)
> delay--
> if(!delay) VarName = TRUE
>

Untested, so it might have something funky with it.

EDIT
Woops, had the var precede its definition...
EDIT2
Fixed again...

EDIT: Umm.. For some reason if I hit the button a lot it wont go to cool down until I wait before hitting again
So it would say like "You need to wait 257 more seconds before you can use this again"

Store world.time in a variable then the number of ticks the proc would have already been sleeping would be

world.time - storedValue

Doing this is a much more efficient solution than updating a count down every tick.
A dynamic list-based (since it's silly and messy to have multiple vars for each cooldown) solution resembling what others have posted could look like this <small>(this is of course assuming you're using delays that are whole seconds, since if you're using something like less-than-a-second delay it wouldn't make sense to check the remaining time)</small>:
mob
var/tmp/list/cooldowns
proc/StartCooldown(key,delay)
if(!src.cooldowns) src.cooldowns = new
cooldowns[key] = delay
spawn(-1) while(delay--)
//updating every tick is kind of a waste
sleep(10)
var/x = cooldowns[key]
if(x == 1) //if the final second passed
if(cooldowns.len == 1) //if it's the last item
cooldowns = null //get rid of the list (will be garbage collected)
else cooldowns -= key
else cooldowns[key] = x-1

#define TimeLeft(player,k) (k in player.cooldowns && player.cooldowns[k])
verb
Punch()
var/time = TimeLeft(src,"Punch")
world << time
if(time)
src << "You need to wait [time] seconds before using Punch again."
return
src.StartCooldown("Punch",1) //can't punch for one second now

src << "You punch!"
/*You could use a little pesky #define to make repeating
such code for each action painless and more manageable.
For example: */

#define COOLDOWN_CHECK(player,key,delay) \
var/_tl = TimeLeft(player,key); \
if(_tl) {player << "You need to wait [_tl] seconds before using [key] again.";return} \
player.StartCooldown(key,delay)


//Examples of usage...
mob/verb
Punch()
COOLDOWN_CHECK(src,"Punch",1)
src << "You punch!"
Kick()
COOLDOWN_CHECK(src,"Kick",2)
src << "You kick!!!"
Axe()
COOLDOWN_CHECK(src,"Axe",5)
src << "You swing an axe!!!"

Haven't slept for a while, and this is untested so it might not actually work as-is, but it's for illustration anyway. :P

There are of course other methods and various variations you may use. You could also use the fancier ActionLock snippet, where it doesn't update periodically, but updates everything whenever you call it. This is handy as if you need to output the time remaining to the player when he can't do an action, you can get it up-to-date (by directly accessing the associated value in the actionlock list). A different method could work by not needing any updating at all; for each cooldown (or lock) you'd just store the world.time value when it should expire (simply the current world.time plus the delay in ticks), then to check if the cooldown has expired you can subtract world.time from the stored time value (eg cooldowns[CooldownName]). If the result is 0 (or less), then the cooldown has expired; if it isn't, then the result is the time remaining (in ticks).
In response to Kaioken
Kaioken wrote:
A dynamic list-based (since it's silly and messy to have multiple vars for each cooldown) solution resembling what others have posted could look like this <small>(this is of course assuming you're using delays that are whole seconds, since if you're using something like less-than-a-second delay it wouldn't make sense to check the remaining time)</small>:
mob
> var/tmp/list/cooldowns
> proc/StartCooldown(key,delay)
> if(!src.cooldowns) src.cooldowns = new
> cooldowns[key] = delay
> spawn(-1) while(delay--)
> //updating every tick is kind of a waste
> sleep(10)
> var/x = cooldowns[key]
> if(x == 1) //if the final second passed
> if(cooldowns.len == 1) //if it's the last item
> cooldowns = null //get rid of the list (will be garbage collected)
> else cooldowns -= key
> else cooldowns[key] = x-1
>
> #define TimeLeft(player,k) (k in player.cooldowns && player.cooldowns[k])
> verb
> Punch()
> var/time = TimeLeft(src,"Punch")
> world << time
> if(time)
> src << "You need to wait [time] seconds before using Punch again."
> return
> src.StartCooldown("Punch",1) //can't punch for one second now
>
> src << "You punch!"
> /*You could use a little pesky #define to make repeating
> such code for each action painless and more manageable.
> For example: */

> #define COOLDOWN_CHECK(player,key,delay) \
> var/_tl = TimeLeft(player,key); \
> if(_tl) {player << "You need to wait [_tl] seconds before using [key] again.";return} \
> player.StartCooldown(key,delay)
>
> //Examples of usage...
> mob/verb
> Punch()
> COOLDOWN_CHECK(src,"Punch",1)
> src << "You punch!"
> Kick()
> COOLDOWN_CHECK(src,"Kick",2)
> src << "You kick!!!"
> Axe()
> COOLDOWN_CHECK(src,"Axe",5)
> src << "You swing an axe!!!"
>

Haven't slept for a while, and this is untested so it might not actually work as-is, but it's for illustration anyway. :P

There are of course other methods and various variations you may use. You could also use the fancier ActionLock snippet, where it doesn't update periodically, but updates everything whenever you call it. This is handy as if you need to output the time remaining to the player when he can't do an action, you can get it up-to-date (by directly accessing the associated value in the actionlock list). A different method could work by not needing any updating at all; for each cooldown (or lock) you'd just store the world.time value when it should expire (simply the current world.time plus the delay in ticks), then to check if the cooldown has expired you can subtract world.time from the stored time value (eg cooldowns[CooldownName]). If the result is 0 (or less), then the cooldown has expired; if it isn't, then the result is the time remaining (in ticks).




runtime error: bad index
proc name: StartCooldown (/mob/proc/StartCooldown) >.>
In response to Xyphon101
You should do what Theodis suggested. Storing the world time when you go to sleep and calculating the number.

It's not only easier to code, but it's more efficient.
In response to Xyphon101
Probably because he set the value to text, not a number. Remove the quotes from around the 0 and 1.