I’m trying to work up a generic method which I can use to manage all of my buffs: temporary status effects, permanent status effects, and effects over time (like DoTs or trickle heals). To this end, I have a base class StatusEffect, which has two public virtual functions: Apply, and Remove. Apply adds the specified effect to the player’s list of effects, while Remove removes the effect from the list.
Each buff has its own class, which extends StatusEffect and uses a public override void of the Apply and Remove classes to add stat changes, which is the central utility I need. This works perfectly for passive effects (“Strength + 5 until buff wears off”), but where I’m running into trouble is with active effects (“Lose 1HP every second”). I initially tried creating a bool activeEffect to indicate whether the buff’s effect should be applied once or every tick, but since Apply() includes a line that adds the effect to a list of effects, this produced an infinite loop. The way I’ve gotten around this is by using a separate version of Apply(), called Proc(), which contains all of Apply() except for the invocation of base.Apply() that adds the effect to the list. This works as desired, but it’s messy and full of conditionals and re-used code, which is bugging the heck out of me- is there a massively simpler way to refactor this that I’m not hitting on?
Base Effect class:
public int duration; //Measured in in-game minutes
public bool permanent;
public bool activeEffect = false;
public virtual void Apply(Character target){
if (activeEffect) {
target.activeEffects.Add(this);
}
else{
target.passiveEffects.Add(this);
}
}
public virtual void Proc(Character target){
}
public virtual void Remove (Character target){
if (activeEffect) {
target.activeEffects.Remove(this);
}
else{
target.passiveEffects.Remove(this);
}
}
}
Extension in a specific buff (Heal.cs, Poison.cs, etc)
public override void Apply(Character target){
base.Apply (target);
//Apply effects AND add to list
}
public override void Remove(Character target){
base.Remove (target);
//remove target from list, and remove effects
}
public override void Proc(Character target){
//Apply effects, but do not add to list
}
Processing active and passive buffs each tick:
void ApplyBuffs(Character character){
//Iterate through buffs/debuffs, and apply them
for (int i = 0; i < character.passiveEffects.Count; i++) { //Iterate through list of passive effects, decrement timer, and remove effects that have expired
if (character.passiveEffects[i].permanent == false && character.passiveEffects[i].duration > 0)
character.passiveEffects[i].duration -= 1;
else
character.passiveEffects[i].Remove(character);
}
}
void ApplyActiveEffects(Character character){
//Apply active effects
for (int i = 0; i < character.activeEffects.Count; i++) {
character.activeEffects[i].Proc(character);
}
}