• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[Spell] Please help with GUI Spell Trigger [MUI]

Status
Not open for further replies.
Level 4
Joined
May 27, 2020
Messages
12
Hello, I've been working on a spell in my map, an item spell to be specific. I've been having troubles with the MUI System.
This is how should my item spell work:

1. When a Hero attacks an enemy (either another Hero or just a unit) with 'this' item, he gains bonus attack speed (I created a custom ability that gives passive attack speed).
2. The bonus attack speed should last for only 5 seconds.
3. After the attack speed buff, there should be a cooldown to prevent gaining another attack speed buff.

These are my triggers:

  • MacheteAtk
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • PDD_damageType Equal to PDD_PHYSICAL
      • (PDD_source has an item of type Machete) Equal to True
      • Machete_IsOnCD[Machete_Index] Equal to False
    • Actions
      • Set Machete_Index = (Machete_Index + 1)
      • Set Machete_Attacker[Machete_Index] = PDD_source
      • Unit - Add AS (200%) (Machete) to Machete_Attacker[Machete_Index]
      • Set Machete_Duration[Machete_Index] = 5.00
      • Set Machete_CD[Machete_Index] = 30.00
      • Set Machete_IsOnCD[Machete_Loop] = True
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Machete_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on MacheteLoop <gen>
        • Else - Actions
  • MacheteLoop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer Machete_Loop) from 1 to Machete_Index, do (Actions)
        • Loop - Actions
          • Set Machete_Duration[Machete_Loop] = (Machete_Duration[Machete_Loop] - 0.10)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Machete_Duration[Machete_Loop] Less than or equal to 0.00
            • Then - Actions
              • Unit - Remove AS (200%) (Machete) from Machete_Attacker[Machete_Loop]
              • Set Machete_Attacker[Machete_Loop] = Machete_Attacker[Machete_Index]
              • Set Machete_Duration[Machete_Loop] = Machete_Duration[Machete_Index]
              • Set Machete_CD[Machete_Loop] = (Machete_CD[Machete_Loop] - 0.10)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Machete_CD[Machete_Loop] Equal to 0.00
                • Then - Actions
                  • Set Machete_IsOnCD[Machete_Loop] = False
                  • Set Machete_IsOnCD[Machete_Loop] = Machete_IsOnCD[Machete_Index]
                  • Set Machete_Index = (Machete_Index - 1)
                  • Set Machete_Loop = (Machete_Loop - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Machete_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
Variables:
1658539633000.png


I am using a Damage Detection System by looking_for_help: [vJASS] - [System] Physical Damage Detection
and the Dynamic Indexing by PurgeandFire: Visualize: Dynamic Indexing

I need help because the Duration and Cooldown of buff doesn't seem to be working right.
 
Last edited:
Here try this
  • BonusDmg
    • Events
      • Game - GDD_Event becomes Equal to 1.00
    • Conditions
      • (GDD_DamageSource has an item of type ....Periapt of Vitality) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (GDD_DamageSource has buff ...Bloodlust ) Equal to False
        • Then - Actions
          • Set TempLoc = (Position of GDD_DamageSource)
          • Unit - Create 1 dummy frost bolt 3 for Neutral Passive at TempLoc facing 0.00 degrees
          • Unit - Order (Last created unit) to Orc Shaman - Bloodlust GDD_DamageSource
          • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
          • Custom script: call RemoveLocation (udg_TempLoc)
          • Trigger - Turn off (This trigger)
          • Trigger - Turn on Untitled Trigger 001 <gen>
        • Else - Actions
  • Untitled Trigger 001
    • Events
      • Time - Every 15.00 seconds of game time
    • Conditions
    • Actions
      • Trigger - Turn on BonusDmg <gen>
      • Trigger - Turn off (This trigger)
Update
 

Attachments

  • sal2.1.w3x
    152.6 KB · Views: 6
Last edited:
Level 4
Joined
May 27, 2020
Messages
12
Here try this
  • BonusDmg
    • Events
      • Game - GDD_Event becomes Equal to 1.00
    • Conditions
      • (GDD_DamageSource has an item of type ....Periapt of Vitality) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (GDD_DamageSource has buff ...Bloodlust ) Equal to False
        • Then - Actions
          • Set TempLoc = (Position of GDD_DamageSource)
          • Unit - Create 1 dummy frost bolt 3 for Neutral Passive at TempLoc facing 0.00 degrees
          • Unit - Order (Last created unit) to Orc Shaman - Bloodlust GDD_DamageSource
          • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
          • Custom script: call RemoveLocation (udg_TempLoc)
          • Trigger - Turn off (This trigger)
          • Trigger - Turn on Untitled Trigger 001 <gen>
        • Else - Actions
  • Untitled Trigger 001
    • Events
      • Time - Every 15.00 seconds of game time
    • Conditions
    • Actions
      • Trigger - Turn on BonusDmg <gen>
      • Trigger - Turn off (This trigger)
Update
Unfortunately, this is not MUI/MPI but this is working and great for rpg single player maps. Thanks.
 
Unfortunately, this is not MUI/MPI but this is working and great for rpg single player maps. Thanks.
you can delete
  • Trigger - Turn off (This trigger)
  • Trigger - Turn on Untitled Trigger 001 <gen>
  • Untitled Trigger 001
    • Events
      • Time - Every 15.00 seconds of game time
    • Conditions
    • Actions
      • Trigger - Turn on BonusDmg <gen>
      • Trigger - Turn off (This trigger)
but you will need to find a better solution for the cooldown
 
Level 4
Joined
May 27, 2020
Messages
12
One way you could keep track of the item's cooldown (if it can't be given some spell that does nothing and then forcibly put on cooldown whenever this ability procs) would be to use a method like this: Passive ability with cooldown - Best method!

UPDATE:
I (sort of) found a solution on my problem thanks to this Passive ability with cooldown. I used the trick on Exhume Corpses on Item using the Spell Book etc etc. I just used a temporary variable here.

1. When an Hero attacks an enemy, the trigger checks if this Hero has 'this' item and if the Cooldown is on. In this case, I created a unit with an expiration timer and that unit is my cooldown which is the 'Machete_Attacker[4]'.
2. After checking, I added this Cargo Hold (Meat Wagon) ability to the Hero who proc'd the ability. This ability will trigger the Exhume Corpse based ability which is the 'Machete Passive' as well as start the 'visual' cooldown of the item (the dark spinning thing on icons).

  • MacheteAtkProc
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • PDD_damageType Equal to PDD_PHYSICAL
      • (PDD_source has an item of type Amulet of Spell Shield) Equal to True
      • (Machete_Attacker[4] is alive) Equal to False
    • Actions
      • Set Machete_Attacker[3] = PDD_source
      • Unit - Add Cargo Hold (Meat Wagon) to Machete_Attacker[3]
3. Now that the Machete Passive is triggered, I used that as an event for adding the bonus attack speed buff to my Hero.
4. I created a unit (Machete_Attacker[1]) that has a 5 seconds expiration timer. This will be the duration of my buff.

  • MacheteAtkSpd
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Machete Passive
    • Actions
      • Set Machete_Attacker[2] = (Casting unit)
      • Unit - Add AS (200%) (Machete) to Machete_Attacker[2]
      • Unit - Create 1 Peasant for (Owner of (Casting unit)) at (Position of (Casting unit)) facing Default building facing degrees
      • Set Machete_Attacker[1] = (Last created unit)
      • Unit - Add a 5.00 second Generic expiration timer to Machete_Attacker[1]
5. Then, this will check if the Machete_Attacker[1] died. When this unit dies, I will remove the buff and the Cargo Hold ability to stop the 'visual' cooldown on the item's icon.
6. Lastly, I created a unit that has 15 seconds expiration timer. This is actual cooldown of the ability that was mentioned in 1.

  • MacheteAtkRmv
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Dying unit) Equal to Machete_Attacker[1]
    • Actions
      • Unit - Remove AS (200%) (Machete) from Machete_Attacker[2]
      • Unit - Remove Cargo Hold (Meat Wagon) from Machete_Attacker[3]
      • Unit - Create 1 Footman for (Owner of (Casting unit)) at (Position of (Casting unit)) facing Default building facing degrees
      • Set Machete_Attacker[4] = (Last created unit)
      • Unit - Add a 15.00 second Generic expiration timer to Machete_Attacker[4]
These trigger only works on single player, single hero with single item (for now).
My new problem now is how to make this MUI or MPI.
Thanks everyone who helped, very much appreciated.
 
Level 39
Joined
Feb 27, 2007
Messages
5,031
There's no reason to keep track of the cooldowns that way using dummy units and manually removing an ability. You can read the remaining cooldown directly (I presume this works on item cooldowns or spellbook nested cooldowns but honestly I don't know) using something like Set Dur = (Ability Cooldown Remaining of (Triggering unit) for ability Animate Dead..). Have a dummy unit cast a modified Berserk or Unholy Frenzy on the unit to give it bonus attack speed for a set duration of 5s that you don't ahve to keep track of.

Boom, MUI.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,583
There's no reason to keep track of the cooldowns that way using dummy units and manually removing an ability. You can read the remaining cooldown directly (I presume this works on item cooldowns or spellbook nested cooldowns but honestly I don't know) using something like Set Dur = (Ability Cooldown Remaining of (Triggering unit) for ability Animate Dead..). Have a dummy unit cast a modified Berserk or Unholy Frenzy on the unit to give it bonus attack speed for a set duration of 5s that you don't ahve to keep track of.

Boom, MUI.
It looks like they're on an older version so I don't think they have access to the Get Remaining Cooldown and Start Unit Cooldown functions.

@chunchunmaru
You can use the shadowing method to handle this trigger. It makes a global variable act like a local variable (see MacheteUnit):
  • MacheteAtkProc
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • PDD_damageType Equal to PDD_PHYSICAL
      • (PDD_source has an item of type Amulet of Spell Shield) Equal to True
      • PDD_source is in MacheteGroup Equal to False
    • Actions
      • Custom script: local unit udg_MacheteUnit = udg_PDD_source
      • Unit - Add AS (200%) (Machete) to MacheteUnit
      • Unit Group - Add MacheteUnit to MacheteGroup
      • Wait 5.00 seconds
      • Unit - Remove AS (200%) (Machete) from MacheteUnit
      • Wait 25.00 seconds
      • Unit Group - Remove MacheteUnit from MacheteGroup
      • Custom script: set udg_MacheteUnit = null
Variables:
MacheteUnit = Unit
MacheteGroup = Unit Group

Local variables will retain their value throughout the trigger even after Waits. They also can't be changed from outside of the trigger unlike global variables. This is what makes the trigger MUI friendly. The Unit Group is there to act like a cooldown since units contained inside of it are unable to make it past the Conditions block. You can see that the attack speed lasts 5.00 seconds and the cooldown lasts 30.00 (5 + 25) seconds. Alternatively, you could use a Dummy unit + Bloodlust for the Attack Speed but then there's a buff involved which can be dispelled / stolen with control magic, so that's something to consider.

Note that the shadowing method has a flaw in that the shadowed variables cannot be referenced inside of the Conditions of an If Then Else statement.

Another issue with my suggested method is that it uses Waits which are imprecise and have other annoying issues. Timers don't have any of these issues which is why they're preferred. However, GUI timers are a pain to work with, especially for MUI cases, that's why I threw together a little system to help improve this process (feel free to ignore this if it's too much):
You need to create these variables. They are used by the system and referenced inside of the code:
GST_Unit1 = Unit
GST_Unit2 = Unit
GST_Integer1 = Integer
GST_Integer2 = Integer
GST_Integer3 = Integer
GST_Real1 = Real
GST_Real2 = Real
GST_Trigger = Trigger
GST_ParentKey = Integer
GST_ChildKey = Integer

And you need to create a custom script trigger and copy and paste this code into it:
vJASS:
globals
    hashtable GST_Hash = InitHashtable()
    timer GST_LoadedTimer
    integer GST_NewParentKey = 0
    integer GST_Index = 0
endglobals


// Used to destroy and clean up an expired repeating timer.
// The user must manually call this function:
function GST_DestroyTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    call FlushChildHashtable(GST_Hash, GetHandleId(t))
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
endfunction


// Used with the Key system to "restart" a timer.
// It destroys the previously created timer (if one is found).
// Then the new timer that was just created replaces it.
function GST_RestartTimer takes nothing returns nothing
    set GST_NewParentKey = (-1000000000 + (100000 * LoadInteger(GST_Hash, -1, GetHandleId(udg_GST_Trigger))))
    if (GST_NewParentKey != -1000000000) then
        // key already exists
        set GST_NewParentKey = GST_NewParentKey + udg_GST_ParentKey
    else
        // key doesn't exist, initialize it
        set GST_Index = GST_Index + 1
        set GST_NewParentKey = (-1000000000 + (100000 * GST_Index)) + udg_GST_ParentKey
        call SaveInteger(GST_Hash, -1, GetHandleId(udg_GST_Trigger), GST_Index)
    endif

    set GST_LoadedTimer = LoadTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey)

    // remove the old timer stored at these keys
    if (GST_LoadedTimer != null) then
        call PauseTimer(GST_LoadedTimer)
        call DestroyTimer(GST_LoadedTimer)
        call RemoveSavedInteger(GST_Hash, GST_NewParentKey, udg_GST_ChildKey)
    endif
endfunction


// Callback functions which run when a timer expires:
function GST_Int_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 2)
    local boolean repeating = LoadBoolean(GST_Hash, id, 1)
    set udg_GST_Integer1 = LoadInteger(GST_Hash, id, 0)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_IntInt_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 3)
    local boolean repeating = LoadBoolean(GST_Hash, id, 2)
    set udg_GST_Integer1 = LoadInteger(GST_Hash, id, 0)
    set udg_GST_Integer2 = LoadInteger(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_IntIntInt_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 4)
    local boolean repeating = LoadBoolean(GST_Hash, id, 3)
    set udg_GST_Integer1 = LoadInteger(GST_Hash, id, 0)
    set udg_GST_Integer2 = LoadInteger(GST_Hash, id, 1)
    set udg_GST_Integer3 = LoadInteger(GST_Hash, id, 2)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_Real_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 2)
    local boolean repeating = LoadBoolean(GST_Hash, id, 1)
    set udg_GST_Real1 = LoadReal(GST_Hash, id, 0)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_RealReal_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 3)
    local boolean repeating = LoadBoolean(GST_Hash, id, 2)
    set udg_GST_Real1 = LoadReal(GST_Hash, id, 0)
    set udg_GST_Real2 = LoadReal(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_IntReal_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 3)
    local boolean repeating = LoadBoolean(GST_Hash, id, 2)
    set udg_GST_Integer1 = LoadInteger(GST_Hash, id, 0)
    set udg_GST_Real1 = LoadReal(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_Unit_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 2)
    local boolean repeating = LoadBoolean(GST_Hash, id, 1)
    set udg_GST_Unit1 = LoadUnitHandle(GST_Hash, id, 0)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_UnitUnit_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 3)
    local boolean repeating = LoadBoolean(GST_Hash, id, 2)
    set udg_GST_Unit1 = LoadUnitHandle(GST_Hash, id, 0)
    set udg_GST_Unit2 = LoadUnitHandle(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_UnitReal_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 3)
    local boolean repeating = LoadBoolean(GST_Hash, id, 2)
    set udg_GST_Unit1 = LoadUnitHandle(GST_Hash, id, 0)
    set udg_GST_Real1 = LoadReal(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_UnitInt_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 3)
    local boolean repeating = LoadBoolean(GST_Hash, id, 2)
    set udg_GST_Unit1 = LoadUnitHandle(GST_Hash, id, 0)
    set udg_GST_Integer1 = LoadInteger(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction

function GST_Simple_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local trigger trig = LoadTriggerHandle(GST_Hash, id, 0)
    local boolean repeating = LoadBoolean(GST_Hash, id, 1)

    // run the GUI trigger
    call TriggerExecute(trig)

    // the timer is not repeating so destroy it
    if (repeating == false) then
        call FlushChildHashtable(GST_Hash, id)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    // clean up memory leaks
    set t = null
    set trig = null
endfunction


// Functions to start timers:
function GST_Real takes real r1, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveReal(GST_Hash, id, 0, r1)
    call SaveBoolean(GST_Hash, id, 1, repeating)
    call SaveTriggerHandle(GST_Hash, id, 2, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_Real_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_RealReal takes real r1, real r2, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveReal(GST_Hash, id, 0, r1)
    call SaveReal(GST_Hash, id, 1, r2)
    call SaveBoolean(GST_Hash, id, 2, repeating)
    call SaveTriggerHandle(GST_Hash, id, 3, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_RealReal_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_IntReal takes integer i1, real r1, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveInteger(GST_Hash, id, 0, i1)
    call SaveReal(GST_Hash, id, 1, r1)
    call SaveBoolean(GST_Hash, id, 2, repeating)
    call SaveTriggerHandle(GST_Hash, id, 3, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_IntReal_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_Int takes integer i1, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveInteger(GST_Hash, id, 0, i1)
    call SaveBoolean(GST_Hash, id, 1, repeating)
    call SaveTriggerHandle(GST_Hash, id, 2, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_Int_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_IntInt takes integer i1, integer i2, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveInteger(GST_Hash, id, 0, i1)
    call SaveInteger(GST_Hash, id, 1, i2)
    call SaveBoolean(GST_Hash, id, 2, repeating)
    call SaveTriggerHandle(GST_Hash, id, 3, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_IntInt_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_IntIntInt takes integer i1, integer i2, integer i3, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveInteger(GST_Hash, id, 0, i1)
    call SaveInteger(GST_Hash, id, 1, i2)
    call SaveInteger(GST_Hash, id, 2, i3)
    call SaveBoolean(GST_Hash, id, 3, repeating)
    call SaveTriggerHandle(GST_Hash, id, 4, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_IntIntInt_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_UnitInt takes unit u1, integer i1, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveUnitHandle(GST_Hash, id, 0, u1)
    call SaveInteger(GST_Hash, id, 1, i1)
    call SaveBoolean(GST_Hash, id, 2, repeating)
    call SaveTriggerHandle(GST_Hash, id, 3, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_UnitInt_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_UnitReal takes unit u1, real r1, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveUnitHandle(GST_Hash, id, 0, u1)
    call SaveReal(GST_Hash, id, 1, r1)
    call SaveBoolean(GST_Hash, id, 2, repeating)
    call SaveTriggerHandle(GST_Hash, id, 3, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_UnitReal_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_UnitUnit takes unit u1, unit u2, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveUnitHandle(GST_Hash, id, 0, u1)
    call SaveUnitHandle(GST_Hash, id, 1, u2)
    call SaveBoolean(GST_Hash, id, 2, repeating)
    call SaveTriggerHandle(GST_Hash, id, 3, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_UnitUnit_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

function GST_Unit takes unit u1, boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveUnitHandle(GST_Hash, id, 0, u1)
    call SaveBoolean(GST_Hash, id, 1, repeating)
    call SaveTriggerHandle(GST_Hash, id, 2, udg_GST_Trigger)

    // start timer
    call TimerStart(t, interval, repeating, function GST_Unit_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif

    // clean up memory leaks
    set t = null
endfunction

function GST_Simple takes boolean repeating, real interval returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    // save to hashtable
    call SaveTriggerHandle(GST_Hash, id, 0, udg_GST_Trigger)
    call SaveBoolean(GST_Hash, id, 1, repeating)

    // start timer
    call TimerStart(t, interval, repeating, function GST_Simple_Expire)

    // check for keys which are used to restart existing timers
    if udg_GST_ParentKey >= 0 then
        call GST_RestartTimer()
        // keep track of the new timer stored at these keys
        call SaveTimerHandle(GST_Hash, GST_NewParentKey, udg_GST_ChildKey, t)
        set udg_GST_ParentKey = -1
        set udg_GST_ChildKey = -1
    endif
 
    // clean up memory leaks
    set t = null
endfunction

Once that's done you can incorporate this system into the trigger I posted before like so:
  • MacheteAtkProc
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • PDD_damageType Equal to PDD_PHYSICAL
      • (PDD_source has an item of type Amulet of Spell Shield) Equal to True
      • PDD_source is in MacheteGroup Equal to False
    • Actions
      • Unit - Add AS (200%) (Machete) to PDD_source
      • Unit Group - Add PDD_source to MacheteGroup
      • Set VariableSet GST_Trigger = MacheteAtkTimer1 <gen>
      • Custom script: call GST_Unit(udg_PDD_source, false, 5.00)
      • Set VariableSet GST_Trigger = MacheteAtkTimer2 <gen>
      • Custom script: call GST_Unit(udg_PDD_source, false, 30.00)
This creates two local timers which are both One-shot (false) instead of Repeating (true). The first timer lasts 5.00 seconds and runs MacheteAtkTimer1 and the second timer lasts 30.00 seconds and runs MacheteAtkTimer2.

So when the 5.00 second timer expires it will run this trigger and GST_Unit1 will be equal to your Machete unit from before:
  • MacheteAtkTimer1
    • Events
    • Conditions
    • Actions
      • Unit - Remove AS (200%) (Machete) from GST_Unit1
And when the 30.00 second timer expires it will run this second trigger and GST_Unit1 will be equal to your Machete unit from before:
  • MacheteAtkTimer2
    • Events
    • Conditions
    • Actions
      • Unit Group - Remove GST_Unit1 from MacheteGroup
Hopefully that makes sense. I'd send you the demo map of the system but it requires the latest version of Warcraft 3.
 
Last edited:
Status
Not open for further replies.
Top