• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Understanding the order of triggers

Status
Not open for further replies.
Level 14
Joined
Aug 30, 2004
Messages
909
I have a map in which each player has a ship. This ship has a lot of variables (speed, turn rate, etc.) that are stored as arrays and indexed by the player number. For example, player 2's ship has speed: FlierSpeed[2], with turn rate: Turn[2], and so on.

I recently discovered what should be a bug in my map, but isn't. I'm confused as to why there is no problem. The triggers are very large but here's what happens:

Situation: the player gets a special mission, so I destroy his old ship and create a new one for him.

Trigger 1: the player selects a dialogue box and I first kill his old ship, and then create a new one. I then set up the data to match the new ship: FlierSpeed[2] = new ship's default speed, for example.

Trigger 2: fires every time any unit dies. It erases all the data in the variables, i.e. FlierSpeed[2] = 0.

So here is what I think should happen:

Trigger 1 is fired by the player clicking the dialogue box. It kills his old ship which will queue Trigger 2. But first, it writes in the new ship's data. Then Trigger 2 should fire, and erases the exact same data, setting FlierSpeed[2] = 0, for example.

That's not what happens though. Instead FlierSpeed[2] is still set to the new ship's speed. The position in the array (2 in this example) is stored as the custom value of each ship and is set to the player number (whenever Player 2 gets a new ship its custom value is set to 2). Here are the truncated triggers:

  • Sandpeople Button Blastboat
    • Events
      • Dialog - A dialog button is clicked for kidnapDialog
    • Conditions
      • (Clicked dialog button) Equal to kidnapBlastboat
    • Actions
      • Set tempInteger = (Player number of (Triggering player))
      • Dialog - Hide kidnapDialog for (Triggering player)
      • Unit - Hide Fliers[tempInteger]
      • Unit - Kill Fliers[tempInteger]
      • -------- -------------------- --------
      • -------- Make Blastboat --------
      • -------- -------------------- --------
      • Set CreationOpenSpot = tempInteger
      • Set CreationShipType = Blastboat
      • Set CreationPlayerOwner = (Player(CreationOpenSpot))
      • Set x = (Center X of SandpeopleExit <gen>)
      • Set y = (Center Y of SandpeopleExit <gen>)
      • Custom script: call MoveLocation(udg_LocationMove1, udg_x, udg_y)
      • Unit - Create 1 CreationShipType for CreationPlayerOwner at LocationMove1 facing CreationAngle degrees
      • Set Fliers[CreationOpenSpot] = (Last created unit)
      • Unit - Set the custom value of (Last created unit) to CreationOpenSpot
      • -------- -------------------- --------
      • Set FlierTurn[CreationOpenSpot] = 2.00
      • -------- -------------------- --------
      • -------- -------------------- --------
  • Ship dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is A Hero) Not equal to True
    • Actions
      • Set DeadUnit = (Triggering unit)
      • -------- --------- --------
      • Set deathInteger = (Custom value of DeadUnit)
      • Set Fliers[deathInteger] = No unit
      • Set FlierTurn[deathInteger] = 0.00
So for some reason, after the first trigger and then second trigger runs, FlierTurn[2] is still 2, not 0.

What's happening here? Does the second trigger run in the middle of trigger 1? I would think it would just queue up?
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Why not convert those triggers into one?

  • Sandpeople Button Blastboat
    • Events
      • Dialog - A dialog button is clicked for kidnapDialog
    • Conditions
      • (Clicked dialog button) Equal to kidnapBlastboat
    • Actions
      • Set tempInteger = (Player number of (Triggering player))
      • Dialog - Hide kidnapDialog for (Triggering player)
      • Unit - Hide Fliers[tempInteger]
      • Unit - Kill Fliers[tempInteger]
      • Set Fliers[tempInteger] = No unit
      • -------- --------- --------
      • Set CreationShipType = Blastboat
      • Set x = (Center X of SandpeopleExit <gen>)
      • Set y = (Center Y of SandpeopleExit <gen>)
      • Custom script: call MoveLocation(udg_LocationMove1, udg_x, udg_y)
      • Unit - Create 1 CreationShipType for (Triggering unit) at LocationMove1 facing CreationAngle degrees
      • Set Fliers[tempInteger] = (Last created unit)
      • Set FlierTurn[tempInteger] = 2.00
      • -------- -------------------- --------
I'm sorry if I got the purpose of those triggers wrong.
 
Level 14
Joined
Aug 30, 2004
Messages
909
Okay this is just weird! I made a test map to see if what seemed impossible was true, and it is: the "unit -dies" trigger fires and finishes before the other trigger continues. It's so strange. Here's the test map. I made a knight belonging to Player 1 and emptied the "Map initialization" trigger.

  • test
    • Events
      • Player - Player 1 (Red) types a chat message containing test as An exact match
    • Conditions
    • Actions
      • Game - Display to (All players) the text: begin
      • Unit - Kill Knight 0000 <gen>
      • Game - Display to (All players) the text: 1
      • Game - Display to (All players) the text: 2
  • dies
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Game - Display to (All players) the text: death trigger
When I run the map and type "test" the output is this:

begin
death trigger
1
2

I put the test map in the pastebin in case you want to check it out:
http://www.hiveworkshop.com/forums/pastebin_data/l9xl7h/_files/death trigger.w3x

This strikes me as something people must have known about before. It freaks me out though, as I don't know JASS and repeat the use of the same variables in different triggers assuming that since I don't use "wait" commands that no other trigger is busting into the order.
 
Level 13
Joined
Sep 13, 2010
Messages
550
Turn off the trigger that registers unit death while you are about to kill it. After that turn it on. Trigger wont fire, unit gets killed, you be happy only if there is no other bugs ;)

Btw you dont need to understand the order of triggers until you start learning Jass :)
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
It all depends on how the observer observable patern was implimented and how it interfaces with the JASS interpreter.

What I believe happens.
1. Button gets pressed.
2. Observable (dialog) notifies all listners (events) about the press.
3. Event object handles notification by readying the jass interpreter and evaluating the trigger.
4. Trigger handler code then kills a unit.
5. Observable (unit death) notifies all listners (events) about the death.
6. Event object handles notification by readying the jass interpreter by placing the old jass interpreter state onto stack and evaluating the trigger.
4. Trigger handler code then does stuff.
5. Trigger finishes evaluation so jass interpreter returns to previous state (first event handler) by poping stack.
6. Trigger finishes evaluation so jass interpreter returns to previous state (stand by).
7. Game engine resumes usual execution.

Facts to be made clear...
1. The JASS interpreter is single threaded (so only 1 piece of JASS code can run at any given time).
2. If WC3 obeys standard observer observable behaviour, JASS code that should trigger an event must interupt the current execution to handle the event.
 
Level 14
Joined
Aug 30, 2004
Messages
909
Btw you dont need to understand the order of triggers until you start learning Jass :)

I think I'm too old to start learning JASS, frankly. But I do need to know the order of triggers if I'm using the same variable in more than one trigger. To cut down on processing time I like to assign (triggering unit) to tempUnit, for example. And as long as I didn't use wait commands I just assumed that a trigger goes from start to finish without being interrupted. Now I know "Unit - Kill" interrupts a trigger if it sparks another. From what SuperGood is saying there could be others too...like triggers that respond when health goes below something.

I'm really surprised this hasn't caused problems for me before. I got lucky I guess.

Thanks for the help, you two. +rep to both.
 
Status
Not open for further replies.
Top