• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Trigger] New and need help with a series of triggers.

Status
Not open for further replies.
Level 2
Joined
Jul 22, 2015
Messages
15
I'm designing a map that is a game with two different phases but it's proving difficult.

I want phase one to be where you send a hero to kill creeps for gold and exp, buy items, attacking units, and or defensive towers.
This phase I have already done.

The phase I'm having problems with...

I need to make it so that every X minutes gates open, unit building is suspended, creeps spawn in specific locations including a big boss, when the boss dies the heroes in the area are sent back to their town, the creeps in the Creep Town that you kill during the first phase respawn, the gates close, and in another X minutes this process repeats. If it were possible to make the boss scale based on the level of the heroes in play, that would be great too but I don't need anything that complex.

I've tried with the "wait" options and I got it all to work... kind of. But I can't figure out how to set a triggle to a boss that's not in play yet. Such as
Unit in (Region) dies.
If unit in (Region) equals (Boss Unit)
and
Unit in (Region) belongs to Player X
Move Units in Region instantly to (Player X Base Region)

I thought of making something like that with four different triggers with a each player... but I can't seem to get it to work right and I don't understand the language well enough to do any sort of complex / advanced triggers.

Any help would be appreciated and if you want you can add me on Skype.
Ellisar.Atranimus
I would greatly appreciate a walk through on how to do this.
 
Last edited:
Level 29
Joined
Sep 26, 2009
Messages
2,596
Every X minutes gates open
This can be accomplished in two way:
a) If it does not matter if current creep wave (with boss) is killed or not and the time should still be counting down for a new wave, you could use this event:
  • Time - Every 300.00 seconds of game time
That means the trigger with this event will fire every 5 minutes after game starts. So even if boss is not dead yet, this will still count down for the next wave.

b) If time should start counting down once boss is dead and phase 1 starts again, you will need to use timer. That means creating a timer variable - I will call it here NextWave.
So when boss dies, you would use this action:
  • Countdown Timer - Start NextWave as a One-shot timer that will expire in 300.00 seconds
and the trigger that spawns new creep wave with boss would have this event:
  • Time - NextWave expires

Resurrecting creeps in creep town:
You cannot resurrect normal units no matter what. However you can create same type of unit atop the dead one. That means you need to keep check of the creep's location and what type of creep it is. Note that this is a bit of an advanced triggering, but I added explanation to it so hopefully it will help you understand some stuff.
You have two options here depending on how you imagine creep respawning to work:
a) Once boss is dead, all creeps in creep town should be resurrected where they died.
For this you will need at least two variables with the "array"[1] option checked and an integer variable that keeps track of how many units you need to resurrect. One variable is a "unit-type" variable and the other is "point" variable. A "unit-type" variable keeps track of the type of unit that the creep is and the point variable keeps track of the location where the creep died. Because both are arrays, you need an integer variable serving as an index for saving units into specified slots in those arrays. Look at the trigger below that saves locations of dying creeps:
  • Creep Dies
    • Events
      • *Your "Unit dies" event*
    • Conditions
      • *Your conditions like which player the unit belongs to, etc*
    • Actions
      • Set Creep_Index = (Creep_Index + 1) //increases index so we don't save multiple units under same index, else the new unit's data would override the old unit's data
      • Set Creep_Type[Creep_Index] = (Unit-type of (Triggering unit)) //type of the dying unit, notice I use "Creep_Index" as the array's index
      • Set Creep_Loc[Creep_Index] = (Position of (Triggering unit)) //saves the location of the unit, again notice what I use for index
What this trigger does is that when creep dies, index is increased - so the first creep that dies will set the index to number 1. Then under this index we save the unit-type and the location of the creep in arrays. So basically this is how it would look when showing the value of index: Set Creep_Type[1] = *type*, Set Creep_Loc[1] = *location*

The second creep that dies would again increase index, so its value would be '2' and in array that creep would be represented as Creep_Type[2] and Creep_Loc[2], and so on for all other creep.

Now when boss dies and creeps in creep town should be resurrected, you will need to go through all units you saved in those arrays and recreate them at the locations you saved. For that you will need to utilize a loop[2] mechanism that will automatically go through each index of the array.
  • Creep Resurrection
    • Events
      • *Your event that detects when boss dies*
    • Conditions
      • *Your possible conditions*
    • Actions
      • For each (Integer LoopInt) from 1 to Creep_Index, do (Actions)
        • Loop - Actions
          • Unit - Create 1 Creep_Type[LoopInt] for *Creep player* at Creep_Loc[Creep_Index] facing Default building facing degrees //You recreate the unit-type at the location
          • Custom script: call RemoveLocation(udg_Creep_Loc[udg_LoopInt]) //You need to destroy the location once you don't need it to prevent memory leaks
      • Set Creep_Index = 0 //We no longer have any dead creeps, so we "reset" the index
Immediately notice two things:
1) In the loop (the line that starts with "For each..." we refer to Creep_Index as the maximum number this loop can go to. The reason is because each array actually has 8192 slots. You don't want to go through all 8192 slots when only 10 creeps died, right? Hence we stop at the value "Creep_Index". In case of 10 creeps the Creep_Index should also have value 10.

2) Notice when I create unit, I "create 1 Creep_Type at Creep_Loc". Notice that both arrays use "LoopInt" variable as index (LoopInt is an integer variable).

So what the loop does is that it will run the same code "Creep_Index"-times (e.g. for 10 creeps it will run 10 times), but each time referring to different slot in arrays, hence resurrecting (different type of) creep at the location you saved previously.

[1] - What is an "Array"?
A variable can by default hold only one value. For example in math, when you have variable x and you do x=2, then x has value 2. If you later did x=5, then you replace value 2 with value 5 for the variable x. As you can see, x refers to only one value at a time.
The same applies for variables in WCIII. A unit variable points at only one unit at a time. A timer variable at only one timer, an integer variable at only one integer number, etc.
You could say that the variable has only "1 slot" for 1 value (whatever that value is). Because it has only 1 slot, when you save new value into the variable, old values are replaced by new ones. An example of variable is this:
  • MyVariable
  • e.g.
  • Set MyVariable = some value
An array is a variable with multiple slots. Each slot can hold only 1 value. To be able to differentiate between individual slots, each has assigned an index starting with 0 and increasing by 1. For arrays, you always need to specify which index you're using. Array uses brackets '[', ']' for index. This is an example of an array
  • MyArray[index_goes_here]
  • e.g.
  • Set MyArray[1] = some value
In WCIII many people actually start with index 1 and omit index 0 for script simplicity. Each WCIII array has a maximum of 8192 slots (starting with 0 and ending with 8191).
Now the interesting thing about arrays is that you don't need to use only numeric value for index, but you can also use an integer variable. For example this:
  • Set X = 5
  • Set MyArray[X] = *some value*[TRIGGER]
  • In this example, we saved *some value* under index X and because variable X has value 5, we basically saved *some value* under index 5. This is the approach I am using here - an automatically increasing integer variable called Creep_Index which I use as index for both arrays.[/HIDDEN]
  • [COLOR="Red"][B][2][/B][/COLOR] - What is "Loop"?
  • [HIDDEN=Explanation]Loop is a mechanism that runs a specified amount of times (at least the GUI one shown below) and executes the same piece of script for each iteration of the loop. This is a loop:
  • [TRIGGER] For each (Integer X) from Y to Z, do (Actions)
Notice the 3 important parts there: X, Y and Z.
X refers the number of the current iteration
Y defines starting value - it is number 1 by default and defines the first value for X.
Z defines ending value - once value of X is greater than the value in Z, the loop ends.

For example this:
  • For each (Integer X) from 1 to 3, do (Actions)
Y = 1, Z = 3. When the loop starts, the variable X will has value 1 (value of Y) and the game executes the code inside the loop (there is none yet). After that it gets back, X increases its value by 1 and checks if that values is greater than 3 (value of Z). If it is, the game exits the loop, if not, it once again executes the code inside loop. This goes on until value of X is greater than value of Z (in this case, greater than 3).

Another example:
  • For each (Integer X) from 1 to 3, do (Actions)
    • Loop - Actions
      • *some action #1*
      • *some action #2*
  • *some action #3*
Notice the indentation of actions #1, #2 and #3. Actions #1 and #2 are inside the loop and thus will be executed with each iteration of the loop, however action #3 is outside the loop. That means that action will be executed once game exits the loop.

You do not need to put specific values in Y and Z - you can use variables instead of them. This is what I did in the loop trigger for creep resurrection. Since I don't know how many creeps will die each phase I cannot put specific number in the value for "Z", but throughout the game I keep track of it thanks to the "Creep_Index" variable, I used that variable in place of Z. And to go through each layer of an array, I referred to LoopInt variable as index for those arrays. LoopInt is in place of X.
That means for the first iteration LoopInt had value 1, so I referred to Creep_Loc[1] and Creep_Type[1], next iteration LoopInt had value 2, so I referred to Creep_Loc[2] and Creep_Type[2], etc.

b) Once boss is dead, all creeps in creep town should be resurrected at their original location (meaning where you placed them in world editor).
You will need at least 3 arrays here + index.
A "unit-type" array, a "unit" array and "point" array. When game starts, you go through all units in the creep town and save them.
  • Creep Saving
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: set bj_wantDestroyGroup = true //needed to prevent memory leak
      • Unit Group - Pick every unit in *region for creep town* matching *your conditions like who the owner is, etc.* and do (Actions)
        • Loop - Actions
          • Set Creep_Index = (Creep_Index + 1)
          • Set Creep_Unit[Creep_Index] = (Picked unit)
          • Set Creep_Type[Creep_Index] = (Unit-type of (Picked unit))
          • Set Creep_Loc[Creep_Index] = (Position of (Picked unit))
Unit group is something akin to a loop. Here it goes through each unit inside the group once and after the game went through all units it exits this loop. So each picked unit is saved inside arrays.

Once boss dies, you have to utilize a loop and go through each unit. You check if that unit is dead or if that slot refers to *no unit* (when the skeleton after dead creep disappears, that slot in array will refer to nothing, hence *no unit*. If once of the two is correct, you will recreate the unit at the location you saved. Here is a trigger for that:
  • Creep Resurrection
    • Events
      • *Your boss dies event*
    • Conditions
      • *Your conditions*
    • Actions
      • For each (Integer LoopInt) from 1 to Creep_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Creep_Unit[LoopInt] is dead) Equal to True
                  • Creep_Unit[LoopInt] Equal to No unit
            • Then - Actions
              • Unit - Create 1 Creep_Type[LoopInt] for Player 1 (Red) at Creep_Loc[Creep_Index] facing Default building facing degrees
              • Set Creep_Unit[LoopInt] = (Last created unit)
            • Else - Actions
What this does is that it executes a loop, each iteration of the loop checks if either one of the conditions is true - a boolean condition (unit is dead) or a unit condition (unit equals to no unit). If one of those conditions is true, the creep is recreated at its original location and that newly created unit is saved in the place of the old one.



Boss resurrection and level scaling
If you make your boss a hero, you can resurrect him - it is possible to revive heroes at specified locations. There is an action for that in the "Hero" submenu.
If your boss is a hero, you could set how much Str/Agi/Int he should get each level in the object editor. Then you can set his level to what you want via triggers. You could for example utilize an integer variable and set it to sum of levels of all heroes (Set value of the variable to 0 and then go through each player hero and do "Set var = var + level of hero). Once that is done, divide it by number of heroes and you get the average level of player heroes. Set level of boss to that value.
 
Level 2
Joined
Jul 22, 2015
Messages
15
I'm a little lost on the scaling hero integer thing. I don't know how to use those. Is there a tutorial or could you explain it in more detail? It might work if I could just make the hero level up rather than setting specific level. Also I need a way to send heroes back to their respective player's base. Note these heroes don't exist at the start of the game. Also I need a way to award lumber to whoever kills the big boss... I thought this would be a simple matter of changing the bounty in object editor, but there is no bounty data for lumber, only gold.
 
Last edited:

sentrywiz

S

sentrywiz

The phase I'm having problems with...

I need to make it so that every X minutes gates open, unit building is suspended, creeps spawn in specific locations including a big boss, when the boss dies the heroes in the area are sent back to their town, the creeps in the Creep Town that you kill during the first phase respawn, the gates close, and in another X minutes this process repeats. If it were possible to make the boss scale based on the level of the heroes in play, that would be great too but I don't need anything that complex.

I've tried with the "wait" options and I got it all to work... kind of. But I can't figure out how to set a triggle to a boss that's not in play yet. Such as
Unit in (Region) dies.
If unit in (Region) equals (Boss Unit)
and
Unit in (Region) belongs to Player X
Move Units in Region instantly to (Player X Base Region)

I thought of making something like that with four different triggers with a each player... but I can't seem to get it to work right and I don't understand the language well enough to do any sort of complex / advanced triggers.

I concur on everything that @Nichilus said, but if you're having trouble with that you might take tutorials on some basic gui triggering before trying his suggestion. As he stated, there are multiple ways of doing this, and possibly even more if you're innovative but for the sakes of simplicity i'll stick to the suggestions:

- time (every X of game-time) this is what you want as an event, it will trigger every X seconds of game time for all players. this is your event

- timers (setting a timer in one trigger and using the timer as an event "timer expires" in another) this is also a great way to make this, though in your case i would use the first way

Also as an advice, avoid using waits for anything (except in single player maps) because waits affect all players and if you have a trigger for each player, that means each wait can and will override the other waits, resulting in lag, bugs, dead-locks and eventually... crash. In multiplayer games it might also disconnect all other players
 
Level 2
Joined
Jul 22, 2015
Messages
15
Final Edit: Seems I have everything I need, thank you two for your help it was more than awesome.
The heroes who didn't kill the boss will just have to enter or exit the boss's region to be teleported back to their base but this isn't much of an issue.

I created a scaling boss by simply adding
Hero - Create Tome of Power and give it to <Boss>
In the phase trigger so that every time they revive they increase a level.

This is the first trigger, it starts when Possess Hero is cast. That's when somebody chooses a hero. The Boss (Soul Eater) which I placed earlier is moved to where the players start.
http://www.hiveworkshop.com/forums/...new-need-help-series-triggers-phase-begin.png

When the boss dies it does this.
http://www.hiveworkshop.com/forums/...w-need-help-series-triggers-phase-refresh.png

The gates are what keeps the heroes out of the boss area and the attackers out of the enemy bases.
 

Attachments

  • Phase Begin.png
    Phase Begin.png
    20 KB · Views: 78
  • Phase Refresh.png
    Phase Refresh.png
    49.6 KB · Views: 76
Last edited:
Status
Not open for further replies.
Top