• 🏆 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] Dynamic Countdown Timer

Status
Not open for further replies.
Level 2
Joined
May 21, 2013
Messages
12
so I'm trying to make a dynamic timer or something, a Countdown Timer that keeps changing when a unit is killed but for some reason it doesn't work and I kept trying to fix it, change it and workarounds and stuff but It still doesn't work. Now I'm asking help from you guys, hoping that you guys know what's wrong with my trigger.

The Countdown timer is for spawning creeps.

So here's the first trigger that starts a Repeating Timer..
  • Z start
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • Countdown Timer - Start balancZation as a Repeating timer that will expire in 120.00 seconds
      • Countdown Timer - Create a timer window for (Last started timer) with title balanZ
      • Game - Set the time of day to 8.00
Second one is the "balancZation" ( xD I just created that word) which I don't think you'll understand until you read the next triggers. That display to all players stuff is for testing purposes only.

  • balancZation
    • Events
      • Time - balancZation expires
    • Conditions
    • Actions
      • Set IndexbalancZ = (IndexbalancZ + 1)
      • Set playerZ = (All players)
      • Game - Display to playerZ for 10.00 seconds the text: (Exec count of balancZation is + (String(IndexbalancZ)))
This is the trigger that is the Countdown Timer I'm having problem with

  • shinra timer
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • -------- angel --------
      • Countdown Timer - Start shinraTimer as a Repeating timer that will expire in (45.00 + shinraDead[IndexAngel]) seconds
      • Countdown Timer - Create a timer window for (Last started timer) with title Angel
      • Set shinratensei = (Last created timer window)
      • Countdown Timer - Show shinratensei
This trigger here is the one responsible for the detection of killed units

  • shinraDies
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to (==) Shinra
    • Actions
      • Set shinraDead[IndexAngel] = (shinraDead[IndexbalancZ] - 1.75)
This is the last trigger that is responsible for spawning creeps. Don't bother about the movement of the creeps, just the Index.

  • angel
    • Events
      • Time - shinraTimer expires
    • Conditions
    • Actions
      • Set IndexAngel = (IndexAngel + 1)
      • Set angelspawn = (Center of angelspawn <gen>)
      • Set angelspawn_2 = (Center of angelspawn 2 <gen>)
      • Unit - Create 4 Shinra for Player 12 (Brown) at angelspawn facing 271.00 degrees
      • Unit Group - Order (Last created unit group) to Attack-Move To angelspawn_2
      • Custom script: call RemoveLocation(udg_angelspawn)
      • Custom script: call RemoveLocation(udg_angelspawn_2)
If you get what I'm trying to do, can you please help me with this. If not I can give you more details if requested (But it's a a pain doing it xD )

I placed the showed "Timer Windows" of the Countdowns for testing purposes

I also tried "Trigger - Execution Count" but it doesn't seem to work, so I used + 1 instead after everytime a runs on specific triggers
 
Last edited:
Level 25
Joined
Sep 26, 2009
Messages
2,381
I don't really see anything that would help you solve your problem, but there's one thing that will bug your triggers later on.

In second trigger:
  • Set playerZ = (All players)
  • ... some actions ...
  • Custom script: call DestroyForce(udg_playerZ)
If I'm not mistaken, (All players) is already a player group.
If you set playerZ = (All players), then you will have 2 ways to point at that player group -> the (All player) function and the playerZ variable.
So if you destroy what playerZ variable points to, you ultimately destroy what (All players) return, hence the next time no player will be picked.

(just don't destroy the player group when it's all players)
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
Just don't destroy that player group, that's all there is to it.

Why it doesn't leak...

Memory leak occurs when some object (for which you have no more use) takes your memory space and you lose all reference to this object - hence you have no way to remove it and it will take that bit of memory unless you turn your game off.

In case of (All players) the reference to that player group is the function (All players) which returns pointer to this player group (thus it does not leak, because the player group is still useful to us and we didn't lose all reference to it).

If you do it with the variable, it will save the pointer inside said variable (= this is better efficiency-wise, as you don't need to call the same function multiple times).

Even if the (All player) is saved into variable, it doesn't leak (even if you overwrite it).
However if you are troubled by having it saved inside variable when you don't want to, you can do this:
  • Custom script: set udg_YourVariable = null
This will make the variable point at "nothing" or "null", but does not remove the object it pointed at.
 
Last edited:
Level 2
Joined
May 21, 2013
Messages
12
thanks for thoroughly explaning it to me. But about what I'm trying to do, do you have any ideas on it? IDK what to do with it anymore ... until I really try to do something about it xD. And the "balancZation" trigger, where the "Display to playerZ" part, somehow doesn't work. :vw_wtf:
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
Where do you set values for each layer of shinraDead variable? What values do they have by default?

The only reference where you change values in taht variable is
  • Set shinraDead[IndexAngel] = (shinraDead[IndexbalancZ] - 1.75)
Also:
what purpose does
  • SetIndexbalancZ = (IndexbalancZ + 1)
serve?
 
Level 2
Joined
May 21, 2013
Messages
12
I don't much understand ur first question, do you mean by when are they gonna keep changing? Well they keep changing when a unit type of "Shinra dies". Their default values is "zero".

  • Set shinraDead[IndexAngel] = (shinraDead[IndexbalancZ] - 1.75)
And yeah it's gonna change there. I'm expecting that when a unit dies, the value of "shinraDead" changes, therefore also changing the Remaining Time of the Countdown Timer to what has changed (minus by 1.75). But it doesn't seem to work.

  • SetIndexbalancZ = (IndexbalancZ + 1)
And like I said in my first post, I first used
  • Trigger - Execution Count
as an Index but I don't know if it worked or not because the Countdown Timer didn't change so I changed it into that
  • SetIndexbalancZ = (IndexbalancZ + 1)
so that after everytime the Countdown Timer "balancZation" expires.

Read this again
  • balancZation
    • Events
    • Time - balancZation expires
    • Conditions
    • Actions
    • Set IndexbalancZ = (IndexbalancZ + 1)
    • Set playerZ = (All players)
    • Game - Display to playerZ for 10.00 seconds the text: (Exec count of balancZation is + (String(IndexbalancZ)))
I used it as an index for this here
  • shinraDies
  • Events
  • Unit - A unit Dies
  • Conditions
  • (Unit-type of (Triggering unit)) Equal to (==) Shinra
  • Actions
  • Set shinraDead[IndexAngel] = (shinraDead[IndexbalancZ] - 1.75)
so that the Countdown Timer "shinraTimer" doesn't get reduced to "zero" where units keeps spawning until the game crashes because of that.

I can just change it back to "Trigger - Execution Count" anytime but using
  • SetIndexbalancZ = (IndexbalancZ + 1)
is something that I'm sure will work because I myself am not sure of what "Trigger - Execution Count" means xD.

But I tried trying to know if it worked or not so I placed
  • Game - Display to playerZ for 10.00 seconds the text: (Exec count of balancZation is + (String(IndexbalancZ)))
but when I tried it ingame nothing appears when the Countdown Expires where this message is suppose to appear. I also tried
  • Game - Display to playerZ for 10.00 seconds the text: (Exec count of balancZation is + (String(Execution Count of (This Trigger))))
but nothing appeared too :vw_wtf:
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
Ok, so I recreated triggers posted in the first post.
So if I understand this whole thing correctly, you want to create something akin to dynamic timer that keeps changing its time while it counts down?

E.g. Base spawn timer is 45 second -> 4 units are spawned and the timer starts counting down. Now every dead unit decreases timer by 1,75... so let's say that when 38 seconds are remaining till the timer finishes, you kill a unit, so now the timer immediately changes remaining time from 38 seconds to 36,25 (=> 38-1,75) ?
Is this what you are trying to achieve?
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
the reason why it doesn't work is because repeating timer takes the time parameter only once - when it is started. Since the timer is repeating, it never updates the time parameter, hence why it doesn't work.
Even if the time parameter uses variable that changes value throughout the game, it has no effect on it, it only checks that variable when it is started.


I created the whole thing anew. At the bottom of this post I attached a test map with the system.

First off, all you really need are 3 variables - for timer, for timer window and for unit group. Then you need another 2 point variables for spawning and ordering units (these can be - or rather: should be - temporal variables).
Triggers are in the hidden tab below.

Triggers
  • first start
    • Events
      • Time - Elapsed game time is 2.00 seconds
    • Conditions
    • Actions
      • Countdown Timer - Start SpawnTimer as a One-shot timer that will expire in 5.00 seconds
      • Countdown Timer - Create a timer window for SpawnTimer with title Angel
      • Set TimerWindow = (Last created timer window)
      • Visibility - Create an initially Enabled visibility modifier for Player 1 (Red) emitting Visibility across (Playable map area)
Explanation:
First off in this trigger I start the timer after 2 seconds game time, set the timer for 5 seconds instead of 45 (so I don't have to wait that long for the first wave) and created visibility emitter across whole map (so I don't have to use cheats)

Notice, how I use a One-shot timer instead of repeating it -> that means that I have to manually order the timer to start once again. This is good for me, because I still need to manually update the timer.
  • timer expires
    • Events
      • Time - SpawnTimer expires
    • Conditions
    • Actions
      • Set p1 = (Center of spawn <gen>)
      • Set p2 = (Center of target <gen>)
      • Unit - Create 4 Footman for Player 2 (Blue) at p1 facing Default building facing degrees
      • Custom script: call DestroyGroup(udg_UnitGroup)
      • Set UnitGroup = (Last created unit group)
      • Unit Group - Order UnitGroup to Attack-Move To p2
      • Countdown Timer - Start SpawnTimer as a One-shot timer that will expire in 45.00 seconds
Explanation:
This trigger fires when the timer expires. p1 and p2 are temp point variables; Footmen are just some random units that are spawned instead of your Shinra units.
In this case, the timer starts with 45 seconds as was in your own triggers.

Now, I wasn't sure if you wanted units of an older wave to decrease the time when new wave was spawned... here I assumed you didn't want previous wave of units to decrease the time. This is what the unit group UnitGroup stands for - only units in this unit group can change the timer and whenever new wave is spawned, the previous group is destroyed and a new one is created (this new one consists only of the new wave of creeps).

However if you want any unit to decrease the timer (and it doesn't matter if they are from the current wave or from previous ones), then just delete the unit group and the custom script (but don't forget to change the Unit Group - Issue order, as it uses that unit group variable).
  • unit dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Footman
      • ((Triggering unit) is in UnitGroup) Equal to True
    • Actions
      • Countdown Timer - Start SpawnTimer as a One-shot timer that will expire in ((Remaining time for SpawnTimer) - 5.00) seconds
Explanation:
This third trigger changes the remaining time for the timer whenever unit dies.
Notice how the conditions check if the unit is in the UnitGroup - so only units of the current wave can decrease the timer, not the units from any previous wave. As I wrote above, if it doesn't matter in which wave the unit was spawned, delete this condition (the one which checks if unit is in unit group).

When unit dies, I start the timer anew, however I use the function "Countdown Timer - Remaining Time" and an arithmetic function to decrease that time by 5 seconds.
While you were decreasing time by 1,75 seconds, I changed it to 5 seconds because that change is easier to see in the timer window.



Attached test map:
 

Attachments

  • DynamicTimer.w3x
    17.8 KB · Views: 44
Level 2
Joined
May 21, 2013
Messages
12
thanks! I actually thought of this idea while I was waiting . What I did was that I kept destroying this timer then another timer starts with the remaining time minus by "x". And it worked but it wasn't as efficient as yours. I didn't know that you can actually just keep "start"ing the timer, without making stop or destroying it. Anyway thanks man! +REP

And Can I ask you something?. I can use Trigger - Execution Count of <Trigger> as an index right, like what I want to in my previous posts?
 
Status
Not open for further replies.
Top