Triggers

From Staredit Network Wiki
Revision as of 21:36, 12 March 2015 by Zurg (Talk) (Trigger cycles: (re?)correct)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

A StarCraft trigger is a set of commands that are executed by the game when a UMS map is played. They consist of three main sections: The players that own the trigger, the conditions under which the players run, and the actions the trigger will execute. A trigger will run for the specified players when all of its conditions are met. Its actions will be executed in order from top to bottom.

Owners

Triggers can be set to run for specific players. These players "own" the triggers. Only Players 1 through 8 can own triggers, and the only valid player groups that can own triggers are Forces and All Players. Triggers for Players 9 through 11, Neutral, Allies, Foes, Current Player, etc., are ignored by StarCraft.

When creating a StarCraft trigger, your map editor will present you with a list of all players and player groups (including, depending on the editor, those that cannot execute triggers). Each player and group will have a checkbox; the checked players own the trigger. If a Force owns a trigger, then the trigger is treated as though it were owned by the players in that Force. If All Players owns a trigger, then the trigger is treated as though it were owned by Players 1 through 8.

TriggerOwners.jpg

In the picture above, Force 1, Player 5 and Player 6 own this trigger. If Players 1, 2, and 3 are in Force 1, then it is equivalent to having a check mark for Players 1, 2, 3, 5, and 6 in this window.

Conditions

Conditions are the criteria required for the trigger to run. A trigger will only execute if all conditions have been satisfied. StarCraft will read the conditions one at a time from top to bottom until it finds a false one. If the game finds a false condition, it will not execute that trigger (or even check the other conditions).

When creating maps with large amounts of triggers (>500), ordering the conditions correctly may help to reduce lag. Some conditions, like Bring, require much more processing power to check since StarCraft must read a lot of data to determine where units are. Other conditions, like Deaths, are simply numerical comparisons and happen much quicker. When ordering a trigger, it is better to have Deaths conditions get checked first; if they return false and are positioned before more memory-intensive conditions, then StarCraft won't even bother checking the more "expensive" conditions. This, as you might expect, saves time and memory.

If all of the conditions of a trigger return true, then StarCraft will begin to execute the actions of that trigger.

Actions

Once all the conditions for a trigger have been filled, the actions of a trigger will execute. These actions execute in order from top to bottom within the trigger, so be careful when the order of execution matters. If the trigger does not use the Preserve Trigger action, then it will only fire once for each viable player that owns it, as after firing in its respective trigger cycle, it will be deleted from memory.

The Preserve Trigger action will work correctly no matter where its position is within the trigger actions.

Trigger lists

Every map contains a trigger list -- that is, an ordered list of its triggers. When playing the map, StarCraft reads the list and sorts the triggers by player before checking them. (Meaning that triggers owned by Player 1 will be checked first, followed by triggers owned by Player 2, and so on.) This, of course, means that the order the triggers appear in map editors is not the order they will be executed in. But you can view only one player at a time to see the order their triggers will fire in. You can also display all triggers owned by a playergroup, such as Forces and All Players.

To access a map's trigger list in SCMDraft 2, either:

  • Open Text Trigedit by going to Triggers > Trigger Editor.
  • Open Classic Trigedit by going to Triggers > Classic Map Triggers, and then select all players in the player selection box at the top of the window.

An image showing the menu sequence for opening Text Trigedit.

The text trigger editor looks like this:

SCMDraft 2 Text Trigedit.png

Text Trigedit shows every trigger in your map in the order that StarCraft will read them when the game begins. It is important to note that the triggers will execute in a different order, explained in the next section. The list is not necessarily sorted by player, but you can manually sort it. The utility explained here: http://www.staredit.net/topic/7694/ can help you sort your triggers by player.

Trigger cycles

StarCraft processes the trigger list every two game seconds (approximately 1.5 real-time seconds on the Fastest game speed), though some maps use triggers called hyper triggers to shorten that time interval. This processing is called a trigger cycle.

During a trigger cycle, only trigger actions happen -- nothing else occurs in the game. We cannot see the game stop, however, because a single trigger cycle can occur during the span of a few milliseconds. This means that if you are, for example, trying to detect the presence of a unit in a given location, you do not have to worry about it exiting the location during a trigger cycle (and being missed by your trigger). It will only move if a trigger action moves it.

StarCraft checks this trigger list in a very particular order. It starts at the top of the list and begins to search for Player 1 triggers. (This includes triggers owned by All Players and triggers owned by whichever Force contains Player 1.) When it finds one of these triggers, it checks the conditions for that trigger, and if the conditions are all true, it executes the trigger. Once StarCraft has reached the end of the trigger list, it returns to the top of the list and repeats the process for Players 2, 3, 4, 5, 6, 7, and 8. The trigger cycle ends when StarCraft finishes checking triggers for Player 8. Note that the game will not run triggers owned by players who have left (or were never in) the game. (Triggers owned by multiple players will still be checked, but not for any owners that are no longer present.)

Any use of "Current Player" in trigger actions or conditions is dependent upon which player StarCraft is currently running triggers for. When, for example, StarCraft is running Player 1 triggers, it will treat Current Player as Player 1. Also remember what has been said earlier: Triggers for Forces and All Players are split into their respective players so each of them owns a copy of the trigger.

Here is an example of a trigger cycle works.

  • Start the trigger cycle by checking triggers for Player 1.
    • Is trigger 1 owned by Player 1?
      • If no, then ignore it.
      • If yes, then is Player 1 in the game?
        • If no, then ignore it.
        • If yes, check if all conditions are true
          • If no, then ignore it.
          • If yes, run each of the trigger's actions in order and then move on to the next trigger..
    • Is trigger 2 owned by Player 1?
      • If no, then ignore it.
      • If yes, then is Player 1 in the game?
        • If no, then ignore it.
        • If yes, check if all conditions are true
          • If no, then ignore it.
          • If yes, run each of the trigger's actions in order and then move on to the next trigger..
    • And so on.
  • All triggers have been checked for Player 1. Re-check them for Player 2.
    • Is trigger 1 owned by Player 2?
      • If no, then ignore it.
      • If yes, then is Player 2 in the game?
        • If no, then ignore it.
        • If yes, check if all conditions are true
          • If no, then ignore it.
          • If yes, run each of the trigger's actions in order and then move on to the next trigger..
    • And so on. Run the checks again for Players 3 through 8.
  • All triggers have been checked for Player 8. End of trigger cycle.

Flowcharts can also be found here and here.

Common trigger-related bugs

Why does my map spawn several Terran Marines for each player instead of just one?

When a trigger is owned by a Force, each player in the force will execute that trigger during their section of the trigger cycle, as long as the conditions are still valid. So your actions probably look something like this:

When the trigger runs for Player 1, a Marine will be created for each member of the Force (if they are in the game). Furthermore, the trigger will run for each member of the Force. (So if Force 1 has three players in it, then all three players get three Terran Marines each, for a total of nine Marines.) The best way to fix this is by using Current Player:

  • Create 1 Terran Marine at Anywhere for Current Player.

Now, the trigger will only create 1 Marine for each player that activates it.

Why does my map spawn Terran Marines even if that player is not in the game? And why do they attack me even though I allied them?

You have created a unit for a specific inactive player, but have it owned by another (active) player. Lets assume P8 is a computer in your map and P1-3 are members of Force 1 while Player 3 left the game. Then your trigger will look something like this:

StarCraft Trigger [template]
Players:
  • Player 8 (Computer)
Conditions:
  • [any]
Actions:
  • Create 1 Terran Marine at Anywhere for Player 1.
  • Create 1 Terran Marine at Anywhere for Player 2.
  • Create 1 Terran Marine at Anywhere for Player 3.

Since you specifically used Players 1-3, the game will create units for them even if they are not playing. The unit for P3 (not playing) will be given to a "ghost" player who is hostile to anyone, ignoring all AIs, including alliances. Use Current Player instead, so the players create the units for themselves; since absent players can't run triggers, the problem will be solved:

StarCraft Trigger [template]
Players:
  • Force 1 (P1-3)
Conditions:
  • [any]
Actions:
  • Create 1 Terran Marine at Anywhere for Current Player.

As you can see it makes the trigger shorter and you don't need the computer player anymore. But be careful as this can change the order in which the triggers are fired, since now the units are created in Player 1's (and P2-P3's respectively) section of the trigger cycle instead of P8 which fires his triggers last. So an alternative solution would be to create for the Force:

StarCraft Trigger [template]
Players:
  • Player 8 (Computer)
Conditions:
  • [any]
Actions:
  • Create 1 Terran Marine at Anywhere for Force 1.

StarCraft automatically checks if players are present if you use Force x and skips it for inactive players.


Why does my map spawn one Terran Marine instead of multiple?

If a trigger is owned by a Force, each player in the force will execute that trigger separately during their section of the trigger cycle. So, if one of the actions of the trigger invalidates the conditions of the trigger, then when StarCraft checks the trigger's conditions for the next player in the Force, they will return false and the trigger will not execute for that player.

Let's use an example. Here is a trigger that might be used to create a Terran Marine for a member of Force 1 when they set a switch.

StarCraft Trigger [template]
Players:
  • Force 1 (P1-3)
Conditions:
  • Switch 1 is Set
Actions:
  • Create 1 Terran Marine at Anywhere for Current Player.
  • Clear Switch 1.

The problem is that when a member of Force 1 runs the trigger, it will be invalidated for the other members of Force 1 (because switches are global, and not specific to a player). It will not execute for them. The solution is to use a death counter owned by Current Player instead of a global switch. We would change the trigger to this (where "[unused unit]" is any unit that cannot normally appear on a map):

StarCraft Trigger [template]
Players:
  • Force 1 (P1-3)
Conditions:
  • Current Player has suffered exactly 1 death of [unused unit].
Actions:
  • Create 1 Terran Marine at Anywhere for Current Player.
  • Set deaths for Current Player: Set to 0 for [unused unit].

Now, the trigger runs separately for each member of Force 1. To activate it, we set a player's death counter (for [unused unit]) to 1.


Bring condition update

The Bring condition may return false positives and false negatives in some cases. This is because StarCraft does not refresh location data during a trigger cycle. If a trigger invalidates that data, then it may cause false results to occur for triggers that use that data. We can force the data for a given location to update however, by using any of these trigger actions:

  • Kill Unit
  • Kill Unit at Location
  • Remove Unit
  • Remove Unit At Location
  • Move Location
  • Move Unit