• 🏆 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!

[Trigger] Timer Window Issue

Level 4
Joined
Dec 19, 2023
Messages
16
Hi guys,

Been trying to figure out this timer and I'm a bit confused what I'm doing wrong.

So, I've got 4 custom units called Summoner Red/Blue/Green/Black, one timer and a quest. Each time one summoner dies, the timer will stop for a period of time and then continue, part which works as inteded. The issue is when all 4 summoners are dead. When they're all dead, timer stops but the window is still visible and, for some reason, it doesn't run the actions after that or maybe the trigger doesn't run at all? The summoners are defined as a real variable with the number of 4, each time one summoner dies, it goes down by one and when it's less than 1, it should run the trigger with the window close.

I define the Summoner variable in map initialization as Set Summoners = 4.00.

The 7 triggers that I have: Timer Setup, Summoner Dies x4, All Summoners Are Dead

Timer setup:
  • Events
  • Unit - A unit enters Region 003 <gen>
  • Conditions
  • (Triggering unit) Equal to Summoner Black 0314 <gen>
  • Actions
  • Countdown Timer - Start TimerSummoning as a One-shot timer that will expire in 3600.00 seconds
  • Set TimerSummoning = (Last started timer)
  • Countdown Timer - Create a timer window for TimerSummoning with title Summoning
  • Set CountdownTimerWindow = (Last created timer window)
Summoner Dies:

  • Events
  • Unit - Summoner Black 0314 <gen> Dies
  • Conditions
  • Actions
  • Set Summoners = (Summoners - 1.00)
  • Countdown Timer - Pause TimerSummoning
  • Trigger - Turn off BlueS <gen>
  • Wait 1200.00 seconds
  • Countdown Timer - Resume TimerSummoning
This trigger appears 4 times, one for each summoner.

Trigger BlueS is just to make the summoners run the animation that I need them to.

This is the trigger that doesn't run.

All summoners are dead:
  • Events
  • Time - Every 3.00 seconds of game time
  • Conditions
  • Summoners Less than 1.00
  • Actions
  • Countdown Timer - Destroy CountdownTimerWindow
  • Countdown Timer - Pause TimerSummoning
  • Quest - Display to (All enemies of Player 1 (Red)) the Quest Update message: The summoners have ...
  • Quest - Display to (All enemies of Player 2 (Blue)) the Quest Update message: Your summoners have...
I suppose I could make it with a UnitGroup if that's what is needed but it should work like this too, I think.

Let me know if you need more information related to the triggers etc.

Thank you,
Ashe
 
Level 11
Joined
Aug 11, 2009
Messages
594
First thing i would recommend is use Integer variable instead of Real, I have heard it can be unreliable with real.

You can also combine the last trigger with the death trigger.
After you set summoners = summoners -1, you create an if/then/else that checks if summoners=0.
Put the last triggers action under "Then" and the death actions under "else".

Event can be "generic unit dies" and then conditions is:
- Or multiple conditions
- Unit type of Triggering unit equal to black summoner (repeat for each summoner).

Hope it makes sense. I am at the phone so cant show trigger examples :)
 
Level 4
Joined
Dec 19, 2023
Messages
16
Hi Peace,

I've swapped to integer as you recommended. Didn't know it may cause issue.

And I've tried doing what you've said and same. It did manage to stop the animations from looping on 3 out of 4 of them but that's it. Quest isn't updated nor is the message shown.

I can't use "generic unit dies" as each summoner is it's own unit (due to different abilities). I'm thinking it might be the variable that doesn't count somehow. Might have to test it with messages, when Summoner = 3, show message X and so on.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
Hi Peace,

I've swapped to integer as you recommended. Didn't know it may cause issue.

And I've tried doing what you've said and same. It did manage to stop the animations from looping on 3 out of 4 of them but that's it. Quest isn't updated nor is the message shown.

I can't use "generic unit dies" as each summoner is it's own unit (due to different abilities). I'm thinking it might be the variable that doesn't count somehow. Might have to test it with messages, when Summoner = 3, show message X and so on.
So I see this often with less experienced modders. You're checking every 3 seconds to see if the Summoners are dead when you already know the exact moment that this happens. In your Summoner Dies triggers, after you Subtract 1 from Summoners, you will know whether this variable is equal to 0 or not - thus telling you whether they're dead or not. You should always try to use an Event-based approach like this to get exact precision and control over your triggers.

Also, your use of Waits is problematic since multiple of these Waits could be running at the same time. You want to Pause the timer for 1200 seconds (using a Wait) each time a Summoner dies but you haven't accounted for the fact that multiple Summoners can die before a previous Wait has finished. These Waits will be running together side by side, creating scrambled and buggy results.

Here's the trigger breakdown, applying what Peacehagen suggested:

This trigger looks risky. I'm assuming that this can only run once while the Summoners are alive, because if not then you're bound to have problems since it'll restart the Timer which could've already been running or Paused:
  • Events
    • Unit - A unit enters Region 003 <gen>
  • Conditions
    • (Triggering unit) Equal to Summoner Black 0314 <gen>
  • Actions
    • Countdown Timer - Start TimerSummoning as a One-shot timer that will expire in 3600.00 seconds
    • Set TimerSummoning = (Last started timer)
    • Countdown Timer - Create a timer window for TimerSummoning with title Summoning
    • Set CountdownTimerWindow = (Last created timer window)
You'll have to explain what you're trying to achieve here in more detail. Also, this trigger looks like the correct place to Set Summoners = 4.


Here's how you can handle the death of the Summoners as well as the "pausing" of the Timer in one single trigger:
  • Events
    • Unit - A unit Dies
  • Conditions
    • Or - Multiple conditions
      • (Triggering unit) Equal to Summoner Red <gen>
      • (Triggering unit) Equal to Summoner Blue <gen>
      • (Triggering unit) Equal to Summoner Green <gen>
      • (Triggering unit) Equal to Summoner Black <gen>
  • Actions
    • Set Summoners = (Summoners - 1)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • Summoners Greater than 0
      • Then - Actions
        • Countdown Timer - Start TimerSummoning as a One-shot timer that will expire in (Remaining time of TimerSummoning + 1200.00) seconds
      • Else - Actions
        • Countdown Timer - Destroy CountdownTimerWindow
        • Countdown Timer - Pause TimerSummoning
        • Quest - Display to (All enemies of Player 1 (Red)) the Quest Update message: The summoners have ...
        • Quest - Display to (All enemies of Player 2 (Blue)) the Quest Update message: Your summoners have...
        • Trigger - Turn off (this trigger)
In this case I'm actually adding 1200.00 seconds to the Timer rather than Pausing it. This is done using the Arithmetic function and one of the Countdown Timer functions. This is a much easier solution than pausing the Timer - which would actually need to involve a second Timer to do properly. This is being done inside an If Then Else action which lets us check for Conditions in the Actions section of our trigger. This is a very important Action to understand and use since it gives you a lot of control over when and how things happen.

Summary: We subtract 1 from Summoners when ANY of the 4 Summoner units die. Then we check the current value of Summoners. If it's > 0 then we add an additional 1200.00 seconds to the Timer. Otherwise (else), we know that Summoners is equal to 0 and we can finish the Quest.

Also, I almost ALWAYS use Generic unit events instead of Specific unit events. Generics offer greater control and are more loose which could help avoid problems in the future. For example, let's say you want to remove the pre-placed Summoners from your map and instead Create them during runtime. If you're relying on Specific unit events then you will break all of your triggers that directly reference these pre-placed Summoners. However, with the Generic approach the triggers don't care about the removal at all and will keep on working as intended. Note that in this case you would want to switch out the multiple Unit Conditions to be Unit-Type checks instead, since we will have lost our Specific references. OR you could use a Unit variable(s) to track each of the Summoners and reference those instead.
 
Last edited:
Level 4
Joined
Dec 19, 2023
Messages
16
So I see this often with less experienced modders. You're checking every 3 seconds to see if the Summoners are all dead when you already know the exact moment that all of these have died in your Summoner Dies triggers. When you Subtract 1 from Summoners you know immediately after that whether it's equal to 0 or not - thus telling you whether or not they're are all dead. You should always try to use an Event-based approach to get exact precision and control over your triggers. Also, your use of Waits is problematic since multiple of these Waits could be running at the same time. You want to Pause the timer for 1200 seconds each time a Summoner dies but you haven't accounted for the fact that multiple Summoners can die before a previous Wait has finished. These Waits will be running together side by side, creating scrambled and buggy results.

Here's the trigger breakdown, applying what Peacehagen suggested:

This trigger looks risky. I'm assuming that this can only run once while the Summoners are alive, because if not then you're bound to have problems since it'll restart the Timer which could've already been running or Paused:
  • Events
    • Unit - A unit enters Region 003 <gen>
  • Conditions
    • (Triggering unit) Equal to Summoner Black 0314 <gen>
  • Actions
    • Countdown Timer - Start TimerSummoning as a One-shot timer that will expire in 3600.00 seconds
    • Set TimerSummoning = (Last started timer)
    • Countdown Timer - Create a timer window for TimerSummoning with title Summoning
    • Set CountdownTimerWindow = (Last created timer window)
You'll have to explain what you're trying to achieve here in more detail. Also, this trigger looks like the correct place to Set Summoners = 4.


Here's how you can handle the death of the Summoners as well as the "pausing" of the Timer in one single trigger:
  • Events
    • Unit - A unit Dies
  • Conditions
    • Or - Multiple conditions
      • (Triggering unit) Equal to Summoner Red <gen>
      • (Triggering unit) Equal to Summoner Blue <gen>
      • (Triggering unit) Equal to Summoner Green <gen>
      • (Triggering unit) Equal to Summoner Black <gen>
  • Actions
    • Set Summoners = (Summoners - 1)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • Summoners Greater than 0
      • Then - Actions
        • Countdown Timer - Start TimerSummoning as a One-shot timer that will expire in (Remaining time of TimerSummoning + 1200.00) seconds
      • Else - Actions
        • Countdown Timer - Destroy CountdownTimerWindow
        • Countdown Timer - Pause TimerSummoning
        • Quest - Display to (All enemies of Player 1 (Red)) the Quest Update message: The summoners have ...
        • Quest - Display to (All enemies of Player 2 (Blue)) the Quest Update message: Your summoners have...
        • Trigger - Turn off (this trigger)
In this case I'm actually adding 1200.00 seconds to the Timer rather than Pausing it. This is done using the Arithmetic function and one of the Countdown Timer functions. This is a much easier solution than pausing the Timer - which would actually need to involve a second Timer to do properly. This is being done inside an If Then Else action which lets us check for Conditions in the Actions section of our trigger. This is a very important Action to understand and use since it gives you a lot of control over when and how things happen.

Summary: We subtract 1 from Summoners when ANY of the 4 Summoner units die. Then we check the current value of Summoners. If it's > 0 then we add an additional 1200.00 seconds to the Timer. Otherwise (else), we know that Summoners is equal to 0 and we can finish the Quest.

Also, I almost ALWAYS use Generic unit events instead of Specific unit events. Generics offer greater control and are more loose which could help avoid problems in the future. For example, let's say you want to remove the pre-placed Summoners from your map and instead Create them during runtime. If you're relying on Specific unit events then you will break all of your triggers that directly reference these pre-placed Summoners. However, with the Generic approach the triggers don't care about the removal at all and will keep on working as intended. In this case you would want to switch out the multiple Conditions to be Unit-Type checks instead, since we will have lost our Specific reference to them. OR you could use a Unit variable to track each of the Summoners and simply swap them out.
It worked! I mean of course it worked but woo!

Thank you, Uncle!

Now I understand what Py was saying. I tried to keep it simple rather than using variables for the summoners as they don't really do anything other than just being there and having a channel animation played. Seeing that they're meant to be killed (by the opposing players) and defended by the defending player, they're just meant to be there.

Good shout with adding seconds instead of pausing the timer, didn't know you can do that. You're the second person telling me to not use wait commands, think I'm gonna stop using them now.

Aa for the unit enters region, I forgot to turn off the trigger after that happens. The idea is that text will appear on screen, then shortly after it will disappear, the summoners get into position and the timer starts. I've put the Summoner = 4 in the initial map setup but you're right, if I pop it there, it'll keep things organised.

Again, thank you both!
 
Top