Making A Status Effect System
This is Justin Dooley and today I’m going to talk about the status effect system in Shadow Heroes: Vengeance in flames. When I sat down to put it together I wanted a status effect system that could work with essentially any game not just Shadow Heroes. This meant something that could change over time and be east to adapt. I also wanted it to be self-contained meaning It housed all its functionality. Well at first this seemed like a big task when sitting down to work on it, it actually fell together fairly quickly.
The core of the system is a status effect object. The status effect has an array of structs that contain a type (defined by an enum) and a value for that enum. You can add as many entries to this struct as you would like.
Figure 1 StatusMod Structure that is added to the array
Alongside that the status effect object contains some functional information that implements the status effects themselves. Things like Duration, Icon, The Effect Type and some optional particles. Bellow you can see an example of the Chanters Invocation effect. This provides +1 defence and lasts for 1.5 seconds. This effect stacks so the more chanters you have the more your defense climbs.
Figure 2 The chanters Invocation Buff ads 1 defense for 1.5 seconds
Now that the core object is in place we needed a way to track all the buffs on it. That’s where the concept of a floating link list came in. Each Status effect object would have a next and prev. object that is expecting another status effect object. This would let us use recursion to get all the elements in the list. But they needed to attach to something.
So for our units I created a null status effect variable and called it StatusEffectList. When adding a status effect to the character I would first check if the status effect is null, If it is assign it as a status effect and initialize it’s timers based on the duration. If it’s not null, It will call addToQueue and use recursion to find the first (and only) object that does not have a next object and assign the new object to that variable.
Figure 3 An effect is added when the “Next” variable is null
But when a cooldown reached its end the status effect is destroyed. So to handle this, Before it’s destroyed, It check if it has a previous. If it does it makes its previous look at its next instead of itself. And it’s next look at its previous instead of itself. This keeps the links in place and order does not matter. For end cases like the first or last elements being removed similar techniques are used.
Figure 4 Status effects clean up the Effect List before destroying themselves to prevent null pointers
Then to get the final results of the status effect we pass a stat as defined by the enum to the first element of the list (if there is one) and call GetStatusSum. This calls a recursive loop that sums all of the given stat and returns the result. Naming a status type is key here. We have some that are SE_ATTACK_MULTIPLIER and some that are SE_ATTACK_MAXIMUM. While the Attack multiplier might end up with a value or 2.55 the maximum might return something like 25. The name helps us implement the effect accordingly when we call the check.
Figure 5 The recursive Get Status Sum function
In the end the system is very abstract and could be used in virtually any game with status effects. It can be easily adapted for things like auras (which we have done and they are awesome J) or virtually anything. Just doing a bit of abstract planning beforehand can make all the difference in how you pursue a problem. It certenly was the case here. If you have any questions or comments please leave a comment on the UE4 forum post.