For those that didn’t grow up modding Warcraft III: a “buff” is some lasting effect that is applied to a unit, such as it being stunned or on fire. Needless to say, Exon has lasting effects too. It’s not all impact-and-forget; mechs need to get stunned and corroded and all sorts of other things I haven’t thought of yet.
How hard can it be? You just stick the thing in a list and count down the timer until you turn it off… right?
I’ve had a basic form of buff in Exon for quite a while, but in adding a new form of trap I needed to extend it and that’s (as always) where the story goes awry.
For me, a buff is composed of two parts: a “type” that has some basic meta-data and a prefabricated blob that actually gets attached to the target. When a buff type is a applied to a unit, it spawns the prefab with all its artwork and applies some changes to the unit’s properties, such as disabling its controls and turning on the electric overlay for being stunned by an EMP.
The first question is: what happens when you get stunned twice — if you are stunned by one EMP attack, and then hit by another? It does not make sense for you to literally be stunned twice, and if one stopped before the other, then who takes charge of unfreezing the unit and turning off the visuals?
So fine, if the unit already has the same buff type on it, instead of adding it again, reset its duration. (If the new attack would stun for a shorter duration than the old one still has remaining, I can quietly not reset the duration at all.) This works very well for stuns and other fire-and-forget effects that are just splattered onto a unit by some kind of attack and forgotten about.
Except I have a second situation, where a buff is not attached by some impact but rather by the movement of a unit into a zone. Consider water: as you wade through it you can’t run and there are nice ripple rings following your movement. The effect of being in water does not have a finite duration — it lasts up until the moment when you step out again.
Superficially, this isn’t too big a deal. As you enter the water, the buff goes on as normal, with an extra “pause the timer” signal. The buff remains attached and your mech remains slow until you leave the water zone, whereupon it unpauses the timer. (It unpauses the timer and detaches the buff, rather than destroying it immediately, so the last ripple particles have time to dissipate.)
Which leads me to gas clouds, which have a few more irritating edge cases.
Gas clouds are caustic and erode your mech’s health while you stand in them, plus a few seconds after you leave (as the remaining acid burns off). The damaging buff then has the same property as water, in that you take damage and spray some nice particle effects for as long as you’re in the cloud — the duration is not set on impact, but is potentially infinite until the player takes some action.
Unlike water, however, gas clouds come and go. This means that they may overlap. Since they come from transgenic plants or barrels that are very likely to come in clumps, it’s going to be common that two utterly independent gas cloud zones may wish to apply the caustic damage buff to the same unit. The player may then enter and leave one or the other while they are overlapping. Eep.
As is usually the answer with such things, I count up the number of times a unit has had an untimed buff applied or removed. While I can fire-and-forget the traditional time-limited buffs, this counter means the last gas cloud you leave will be the one that actually relinquishes the caustic damage. Job done! (Assuming you always evenly enter and leave clouds; I’m fairly confident that a cloud dissipating still fires the leaving logic so I think it’s fine… though I don’t really want to think about what will happen if you transition to a different level from inside a cloud to not inside a cloud.)
I did have a minor panic when I was working on this, as I noticed that my “zone” logic was totally missing anything to do with the save/load system. No record of which units were inside the zone, no restoration of buffs when they come back again…
I realised, though, this was actually intentional. You see, when things are recreated during loading, this fires their OnTriggerEnter callbacks — thus any untimed buffs are created automatically as if the player had just walked in normally! So if I did save and restore any of this data, it would end up double-counting and there would be chaos. Needless to say, I left myself a great big comment explaining this, so I won’t suffer the same panic again.
Now, time to add more things that drop acid clouds…