ID:270338
 
G'day to all you developers!

I've come here in an attempt to gain some assistance on a method of implementing a Timed Buff system.

Basicly each character class will have special skills that can be used to enhance an attribute for (x) ammount of time. For instance, a Priest has the ability to cast a buff to increase the players HP / Max HP for say 15 Minutes.


Now i've thought of ways to do this, such as having a "Buff Timer" var. When the skill is used, that players buff_time var would be changed to 9000 (15 Mintues =P).

Now i'm not sure if it would be better to just do a spawn(9000) then make the buff_time null and remove the extra HP, or if I should make a ticking proc, that every second would decrease the buff_time var. (So I would assume a while(buff_time) ?)

I would prefer usign a method that slowly ticks away, so that I could display a timer somewhere so the player knows how long their buff duration has left.

Also along with that, a way with dealing with people loging out. I would ALSO prefer that their buff_time is saved, and when they login it continues to tick to 0 and they retain their buff, but i'm not 100% about this part.


Any tips are greatly appreciated. I'm hoping to test a few methods to see which is efficient and which would work the best, but for those guru's out there that may have touched on such a subject and could offer some advice, that would b greatly appreciated!

Thanks guys and gals!
Do you mean somthing like that?
If you want it simpler tell me, I'll insert it into one verb =p

mob/verb/power()
var/a=input("How many power do you wish to use?")as null|num
if(a*10>=maxpower){src<<"You can't power that much!";return}
time=a
update()

mob/proc/update()
if(time>=1){time--;src<<"You have [time] minutes left for the power up.";sleep(600);update()}
else if(time<=1){src<<"Your muscles shrink as you sense that the buff's effect is over."}

//if you want the buff to slowly disappear when there is less time,
//just add stuff such as if(time<=number)maxpower-=100
In response to DivineO'peanut
Somewhat. What i'm currently using as a test is:

mob/var
old_max_hp
buff_time = 0
health_buff
hp_max = 50
hp = 50

mob/proc
Buff_Timer()
while(buff_time > 0)
buff_time -= 10
sleep(10)
src.health_buff = 0
src.hp -= src.hp_max - src.old_max_hp
src.hp_max = src.old_max_hp
src << "Buff's Gone!"

mob/verb
Health_Buff(mob/M in view(6))
set category = "Skills"

if(M.health_buff)
usr << "They already have that Buff!"
return

M.old_max_hp = M.hp_max

M.hp_max += 500
M.hp = M.hp_max
M.buff_time = 1500
M.health_buff = 1
Buff_Timer(M)

mob/Stat()
statpanel("Stats")
stat("HP:","[src.hp] / [src.hp_max]")
if(buff_time > 0)
stat("Buff Time Left:",src.buff_time / 10)

mob/Login()
if(src.buff_time > 0)
Buff_Timer(src)

client
New()
if(fexists("Player Saves/Save File.sav"))
var/savefile/load
load = new ("Player Saves/Save File.sav")
load["mob"] >> src.mob
..()
else
..()

Del()
var/savefile/save
save = new ("Player Saves/Save File.sav")
save["mob"] << src.mob
..()


I'm sure theres a better way to do this, hehe, and I can see an issue where if I plan on adding lots of buffs, it'll involved adding ALOT of new vars (like health_buff), so any tips on that would be appreciated =P

EDIT: Also, how would I go about formating the Buff Time Left stat, so that it'd show HH:MM:SS ? Thanks!
In response to Hant Teath
Well, instead of setting vars like "health_buff", "magic_buff", etc, just give your players a list, "buffs[]", and add the buffs to it as they are applied and remove them from it when they're over... Then, just check "if(src in M.buffs)" to see if that one is applied...

No need for hundreds of vars... Just one single list...

In response to SuperSaiyanGokuX
Ah, but he will still need vars such as
old_max_hp...
In response to DivineO'peanut
I use a status list, as SSGX suggests, but the actual effects in teh list are a specialized /status datum. The datum has a few variables such as the level of effect and time left. It also has several procs. One proc is called when the status is applied to a mob. Another proc is called each tick of it's lifespan and is in charge of decreasing the timer, periodic effects the status triggers, and calling the remove proc when the timer ends. The final proc is called when the effect is removed from the mob.

status
var
level = 1
timer
proc
apply(mob/target)
// this effect just began on target
tick(mob/target)
// called every cycle of the target's lifecycle
timer--
if(timer <= 0)
target.removestatus(src)
remove(mob/target)
// called when this effect ends on target

For example, an increase str buff would be:
status/strength
// no need to change tick()
apply(mob/target)
target.str += level
remove(mob/target)
target.str -= level

A regeneration buff might look like this:
status/regeneration
// no need to change apply() or remove()
tick(mob/target)
..() // default count down
// if we get here, regen must still be in effect
if(!(timer%5)) // every 5th cycle
hp = min(hp+1, maxhp)


Mobs have several procs to set, check, and remove status effects.

setstatus() is in charge of verifying that the status is not already effecting the target, creating the effect, and setting all it's variables based on the arguments you pass to setstatus(). It also calls the status datum's apply() proc.

removestatus() clears a status effect from the status list, calls the status effect's remove() proc, and deletes the status datum.

checkstatus() checks if a particular status effect is in the mob's status list and returns the datum if it is. This is useful for things that effect particular aspects of your code without setting up special flag variables. For instance, my game does checkstatus(/status/paralysis) to make sure the player isn't paralyzed before they attempt to walk.

This may seem a little complicated, but it is very simple to expand and extremely flexible.