Four unique races to play as, huge universe to explore and conquer makes Warcraft III one of the largest Real Time Strategies of its day. Combine with this a modders ability to alter units, create new landscapes, new missions and you have one game which shall be attacked and enhanced by the huge modification following!

Post news Report RSS Hero Revival: An Excercise in Revision Part 2

Thus begins the legend of The Two Triggers. The story behind the creation of hero revival code continues.

Posted by on

My code wasn't good enough. Or rather, it wasn't cool enough; it functioned just fine. My desire to make an infinitely more spectacular means of hero revival spurred me into enduring an all-night Mexican stand-off with the World Editor and it's wiley trigger editor. But the lack of sleep was worth it, as, many ridiculous hours of revision in, I finally completed a working trigger that functioned exactly as I'd dreamed.

We need to cover one little topic of programming before we can move forward: For loops. For loops repeat a set of actions a set number of times. This is useful in all kinds of ways, but for me, it was useful for reviving my fallen heroes. A For loop begins like this:

actionscript code:
For each (Integer A) from 1 to 5, do (Actions)
    Loop - Actions

Integer A is simply the name of the For loop, present to differentiate it from other For loops potentially running simultaneously. From integer to integer is how many times the For loop will repeat itself before moving on to further actions beyond the For loop. The actions within the For loop are nested within that "Loop - Actions" line.

My goal was to simplify my code as much as possible. I still needed two triggers, however. If you reference back to the previous post, the first trigger may seem extremely similar by comparison, but there is one big difference that is resolved in the second trigger.

You may notice that the If/Then/Else statement is missing from the bottom. The statement reset RedHeroesDeadCount to zero once it had become greater than five. No more! Know, all this trigger does is set each dying hero to a different array spot in the unit variable RedHeroesDead[]. It then sets the cooldown integer for the dying hero to zero, since he or she has just died.

The second trigger is where this gets interesting.

This trigger begins the same way, fired whenever player red's turn comes around. But then all heck breaks loose.

First, I set several new variables, all integers. RedRevBaseInt is set to one, and keeps track of which hero is being revived. RedRevReset begins as zero and resets each unit to a previous spot in the array when as the lower numbered units are revived. Finally, we have RedRevIntLoop. It is set to RedHeroesDeadCount, or, how many of Red's heroes are currently not amongst the living. This variable is needed so that I do not override RedHeroesDeadCount, which would throw off everything.

Then, I jump immediately into a For loop. The For loop runs from 1 to RedRevIntLoop, which you may recall is the number of units are currently dead. If three of Red's heroes are dead, this loop will run three times. All of the rest of the actions within this trigger are nested within the Integer A For loop.

The first action within the For loop ups the revival cooldown by one for RedRevBaseInt (which is initially 1, or the hero who had died first). Then the If/Then/Else statement begins. If the revival cooldown for RedRevBaseInt (the first hero who had died) is equal to three, that is, if the first hero has been dead for three turns, then run through the Then actions. If not, if the hero has been dead for two or fewer turns, then jump to the Else actions.

Let's assume the first hero who had died, who is RedHeroesDead[1], is ready to be revived. Well, then we'll instantly revive the hero at the Frontlines.

Here comes the tricky part. We run another For loop, this one Integer B. For loop Integer B runs from 1 to RedHeroesDeadCount minus 1 (or one fewer than the number of heroes that are dead). Remember earlier how I had removed that If/Then/Else statement from the Unit Dies trigger? This loop is what replaces that statement. Before, I needed to reset RedHeroesDeadCount to zero if it grew beyond five, since it need never be higher. Now, I move each hero down a notch. RedHeroesDead[1] was just revived. And let me be clear that RedHeroesDead[1] will always be the first to revive. Now, RedHeroesDead[1] is effectively empty, since that hero is now living and no longer in need of revival. Without this For loop, RedHeroesDeadCount and the array spot for RedHeroesDead would mount perpetually upward, ad infinitum, making, for example, the eleventh hero to die RedHeroesDead[11]. But this is sloppy and not in any way deserving of awesomeness.

So instead, I knock out one rung of the ladder and bring every presently-dead unit down a notch. RedHeroesDead[2] becomes RedHeroesDead[1]. RedHeroesDead[3] becomes RedHeroesDead[2]. Etc. The Integer B For Loop runs one less than however many heroes are currently dead, as instructed by "from 2 to RedHeroesDeadCount." The first action is to set RedRevReset plus one, making it (for the time being) one. It is necessary to use RedRevReset so that the array spot for RedHeroesDead[] continues to count upwards and does not continuously reset RedHeroesDead[1] to the next successive hero.

Next, I reset RedHeroesDead[RedRevReset] to the value of RedHeroesDead[RedRevReset + 1]. The first time this loop is run, this line of code looks like so:

  • Set RedHeroesDead[1] = Set RedHeroesDead[2]

RedHeroesDead[2] has now been copied and pasted onto RedHeroesDead[1], overriding the recently revived hero. Similarly, the next line resets the cooldown of the first RedHeroesDead to that of the second. And then the For Loop Integer B runs again. This time moving a potentially third dead hero to RedHeroesDead[2]. And again, if there is a fourth hero dead, he or she will be moved to RedHeroesDead[3]. Get the picture?

We're out of For loop Integer B. Phew! But this is still work to be done.

Continuing on, we reset RedHeroesDeadCount, subtracting one from the number of red heroes who are currently dead. We also reset RedRevBaseInt to 1. This is because all units have now been moved down a notch in the array. Meaning that next time we run the For loop Integer A, the cooldown for the second most recently dead hero is now housed without RedRevivalCooldown[1]. We also reset RedRevReset=0 for Integer B loop later on.

The trigger then returns to the top of For Integer A, essentially beginning back at one again, since all of our dead heroes have been moved down. The cooldown for RedHeroesDead[1] is increased by one. This time, let's assume that the second hero who is still dead this turn has been so for less than three turns and is not ready for revival. In this case, the loop jumps to the single Else action because the condition is not met. The else action adds one to RedRevBaseInt. If a third hero is dead, For loop integer A will run again. This time, it will add one to the cooldown of RedHeroesDead[2]. And, since RedHeroesDead[1] did not revive, clearly, [2] is also not ready for revival, since he had died at least on the same turn, if not afterwards. Naturally, the loop jumps to the else action and increases RedRevBaseInt by one.

But that's it! All of our dead heroes have either been revived or their cooldown has been increased. The trigger ends because For loop Integer A has run its course. Next red turn, the trigger will run again. Likewise, the next time a red hero dies, the other trigger will run, picking up where the revival had left off.

And thus ends the saga. Believe it or not, I had to rewrite my revival code again while in the middle of writing this very article. Though I had believed it to be airtight, the code was certainly not. Now, who knows. I've tested it thoroughly, but I seriously wouldn't be surprised if there were more errors. I hope you enjoyed the articles and thanks for stopping by.

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: