# How to apply effects that occur (or change) over time to characters in a game?

So assume that I have a system that applies Effects to Characters like so:

public class Character {
private Collection<Effect> _effects;

public void AddEffect (Effect e) {
e.ApplyTo(this);
}
public void RemoveEffect (Effect e) {
e.RemoveFrom(this);
_effects.Remove(e);
}
}

public interface Effect {
public void ApplyTo (Character character);
public void RemoveFrom (Character character);
}


Example Effect: Armor Buff for 5 seconds.

void someFunction() {
// Do Stuff ...
Timer armorTimer = new Timer(5 seconds);
ArmorBuff armorbuff = new ArmorBuff();
armorTimer.Start();
// Do more stuff ...
}

// Some where else in code
public void ArmorTimer_Complete() {
character.RemoveEffect(armorBuff);
}

public class ArmorBuff implements Effect {
public void applyTo(Character character) { character.changeArmor(20); }
public void removeFrom(Character character) { character.changeArmor(-20); }
}


Ok, so this example would buff the Characters armor for 5 seconds. Easy to get working. But what about effects that change over the duration of the effect being applied. Two examples come to mind:

Damage Over Time: 200 damage every second for 3 seconds. I could mimic this by applying an Effect that lasts for 1 second and has a counter set to 3, then when it is removed it could deal 200 damage, clone itself, decrement the counter of the clone, and apply the clone to the character. If it repeats this until the counter is 0, then you got a damage over time ability.

I'm not a huge fan of this approach, but it does describe the behavior exactly.

Degenerating Speed Boost: Gain a speed boost that degrades over 3 seconds until you return to your normal speed. This is a bit harder. I can basically do the same thing as above except having timers set to some portion of a second, such that they occur fast enough to give the appearance of degenerating smoothly over time (even though they are really just stepping down incrementally).

I feel like you could get away with only 12 steps over a second (maybe less, I would have to test it and see), but this doesn't seem very elegant to me. The only other way to implement this effect would be to change the system so that the Character checks the _effects collection for effects that alter any of the properties any time that they are being used. I could handle this in functions like getCurrentSpeed() and getCurrentArmor(), but you can imagine how much of a hassle it would be to have that kind of overhead every time you want to do a calculation with movement speed (which would be every time you move your character).

Is there a better way to deal with these kinds of effects or events?

I have something similar to your first option. However, it's a bit more self contained in a timed effect. Timed effects have some settings:

• Tick delay: The time before counting starts.

• Tick count: The number of times the effect ticks. Each tick is an event where some effect is calculated and applied.

• Tick time: The time between each tick.

• Effect: This is the effect to apply per tick. This is an object that contains info about what to change, by how much, a maximum/minimum total amount and so on.

I use this for one off effects too. Just set the tick count to 1 and the tick time to 0. The effect is applied immediately.

Since each tick is an event, I can calculate the potency of the effect based on the time elapsed since the effect was applied, the amount of whatever has been applied already and various other attributes.

• I like this for all of the timed effects, but what about effects that are caused by toggling a skill, an aura, or holding some point that give a buff? – Joshua Harris Nov 18 '12 at 17:15
• If you want to use the same class you can set tick time and tick count to -1, so the effect is processed when it's applied (or after tick delay expires) and then remains on. Otherwise have a toggle effect class that is much simpler and just turns on or off. – MichaelHouse Nov 18 '12 at 17:52