• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Help me debug this trigger (spell)

Level 3
Joined
Jun 6, 2024
Messages
12
I need help with this because I haven't been able to find the cause of the bug. This trigger is based on a Fissure spell, but I modified it slightly by temporarily moving the affected units while I place the 'fissure shards' so that they always remain in a straight line. The trigger works fine initially, but only the first time. In subsequent invocations, the units are moved to the center of the map and do not return to their original position. It works fine without bugs if I recreate the hashtable entirely at the end of the trigger. So, I need to clean it up, I suppose, but using "Hashtable - Clear" doesnt resolve the problem. Although I don't quite understand why I would need to do this since the unique keys of the units should replace the previous values. I'm not quite sure what's happening.

  • Events
    • Unit - A unit Starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Fissure (Channel)
  • Actions
    • Set Fissure_Caster = (Triggering unit)
    • Set Fissure_Point = (Position of (Triggering unit))
    • Set Fissure_Point2[1] = (Target point of ability being cast)
    • Set Fissure_Angle = (Angle from Fissure_Point to Fissure_Point2[1])
    • Custom script: call RemoveLocation (udg_Fissure_Point2[1])
    • For each (Integer Fissure_Loop) from 1 to 10, do (Actions)
      • Loop - Actions
        • Set Fissure_Point2[Fissure_Loop] = (Fissure_Point offset by (80.00 x (Real(Fissure_Loop))) towards Fissure_Angle degrees)
        • Set Fissure_CheckAOEGroup = (Units within 200.00 of Fissure_Point2[Fissure_Loop] matching (((((Matching unit) is A structure) Equal to False) and (((Matching unit) is alive) Equal to True)) and ((((Matching unit) is in Fissure_Group) Equal to False) and ((Matching unit) Not equ
        • Unit Group - Add all units of Fissure_CheckAOEGroup to Fissure_Group
        • Unit Group - Pick every unit in Fissure_CheckAOEGroup and do (Actions)
          • Loop - Actions
            • Hashtable - Save (X of (Position of (Picked unit))) as (Key (Picked unit)) of 0 in Fissure_Hashtable
            • Hashtable - Save (Y of (Position of (Picked unit))) as (Key (Picked unit)) of 1 in Fissure_Hashtable
            • Unit - Move (Picked unit) instantly to (Center of (Playable map area))
    • For each (Integer Fissure_Loop) from 1 to 10, do (Actions)
      • Loop - Actions
        • Unit - Create 1 FissureShard (LEVEL 1) for (Owner of Fissure_Caster) at Fissure_Point2[Fissure_Loop] facing Default building facing degrees
        • Unit - Add a 8.00 second Generic expiration timer to (Last created unit)
    • Unit - Create 1 DummyUnit for (Triggering player) at Fissure_Point facing 0.00 degrees
    • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
    • Unit - Add Fissure (Stormbolt) to (Last created unit)
    • Unit - Set level of Fissure (Stormbolt) for (Last created unit) to (Level of (Ability being cast) for (Triggering unit))
    • Unit Group - Pick every unit in Fissure_Group and do (Actions)
      • Loop - Actions
        • Set X = (Load (Key (Picked unit)) of 0 from Fissure_Hashtable)
        • Set Y = (Load (Key (Picked unit)) of 1 from Fissure_Hashtable)
        • Set TempPoint1 = (Point(X, Y))
        • Unit - Move (Picked unit) instantly to TempPoint1
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • And - All (Conditions) are true
              • Conditions
                • ((Picked unit) is A ground unit) Equal to True
                • ((Picked unit) is A structure) Equal to False
                • ((Picked unit) belongs to an enemy of (Triggering player)) Equal to True
                • ((Picked unit) is alive) Equal to True
          • Then - Actions
            • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
            • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Fissure_Hashtable
          • Else - Actions
    • Unit Group - Remove all units from Fissure_CheckAOEGroup
    • Unit Group - Remove all units from Fissure_Group
    • Hashtable - Clear Fissure_Hashtable

If i add this at the end then it works as expected:

  • Hashtable - Create a hashtable
  • Set Fissure_Hashtable = (Last created hashtable)

Any help would be appreciated.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Where are you creating the Fissure_Hashtable otherwise? You need a trigger like this before you try to use the Hashtable:
  • Events
    • Time - Elapsed game time is 0.01 seconds
  • Conditions
  • Actions
    • Hashtable - Create a hashtable
    • Set Fissure_Hashtable = (Last created hashtable)
Anyway, you're making some other mistakes in the trigger, here's a cleaned up version that doesn't use a Hashtable:
  • Events
    • Unit - A unit Starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Fissure (Channel)
  • Actions
    • Set Fissure_Caster = (Triggering unit)
    • Set Fissure_Point[0] = (Position of Fissure_Caster)
    • Set Fissure_Point[1] = (Target point of ability being cast)
    • Set Fissure_Angle = (Angle from Fissure_Point[0] to Fissure_Point[1])
    • -------- --------
    • -------- The Dummy unit should be based on Locust with Movement Type = None and Speed Base = 0 --------
    • Unit - Create 1 DummyUnit for (Triggering player) at Fissure_Point[1] facing 0.00 degrees
    • Set Fissure_Dummy = (Last created unit)
    • Unit - Add a 1.00 second Generic expiration timer to Fissure_Dummy
    • Unit - Add Fissure (Stormbolt) to Fissure_Dummy
    • Unit - Set level of Fissure (Stormbolt) for Fissure_Dummy to (Level of (Ability being cast) for Fissure_Caster)
    • Custom script: call RemoveLocation( udg_Fissure_Point[1] )
    • -------- --------
    • -------- Create fissure --------
    • For each (Integer Fissure_Loop) from 1 to 10, do (Actions)
      • Loop - Actions
        • Set Fissure_Point[1] = (Fissure_Point[0] offset by (80.00 x (Real(Fissure_Loop))) towards Fissure_Angle degrees)
        • Set Fissure_CheckAOEGroup = (Units within 200.00 of Fissure_Point[1] matching (Matching unit) is A structure) Equal to False) and (Matching unit) is alive) Equal to True) and (Matching unit) is A ground unit) Equal to True and (Matching unit) belongs to an enemy of (Owner of Fissure_Caster) Equal to True)
        • Unit Group - Pick every unit in Fissure_CheckAOEGroup and do (Actions)
          • Loop - Actions
            • Unit Group - Add (Picked unit) to Fissure_Group
        • Custom script: call DestroyGroup( udg_Fissure_CheckAOEGroup )
        • -------- --------
        • -------- Create shard --------
        • Unit - Create 1 FissureShard (LEVEL 1) for (Owner of Fissure_Caster) at Fissure_Point[1] facing Default building facing degrees
        • Set Fissure_Shard = (Last created unit)
        • Unit - Add a 8.00 second Generic expiration timer to Fissure_Shard
        • Custom script: call SetUnitX( udg_Fissure_Shard, GetLocationX(udg_Fissure_Point[1]) )
        • Custom script: call SetUnitY( udg_Fissure_Shard, GetLocationY(udg_Fissure_Point[1]) )
        • Custom script: call RemoveLocation( udg_Fissure_Point[1] )
    • -------- --------
    • Custom script: call RemoveLocation( udg_Fissure_Point[0] )
    • -------- --------
    • -------- Move and Stun enemy units hit by the fissure --------
    • Unit Group - Pick every unit in Fissure_Group and do (Actions)
      • Loop - Actions
        • Set Fissure_Target = (Picked unit)
        • Unit - Order Fissure_Target to Stop
        • Unit - Order Fissure_Dummy to Human Mountain King - Storm Bolt Fissure_Target
    • Unit Group - Remove all units from Fissure_Group.
Although, I haven't tested it yet.

The idea is that the Shards will be forcibly positioned to their destination using the SetUnitX/Y functions. These coordinate-based functions should ignore collision when moving a Unit unlike "Move Unit Instantly". After that you Order all of the enemy units to "Stop" which should force a collision check and move them away from the Shards that they're clipped inside of. (You may want to do this to allied units clipped inside as well but keep in mind that it will interrupt them)

Also, there's a lot of misinformation out there about Dummy units. Here is how you should create yours:
1) Copy and paste the Locust. (Undead/Special)
2) Set it's Model = None (or ideally use Vexorian's dummy model), Shadow = None, Attacks Enabled = None, Movement Type = None, and Speed Base = 0.

All of these settings are needed to create a Dummy unit that can cast spells "instantly". That means no turning to face it's target or animation delays. You must also ensure that your Dummy's Ability has 99999 cast range, 0 mana cost, 0 cooldown, and no interfering Requirements/Targets Allowed.
 
Last edited:
Level 10
Joined
Jan 26, 2019
Messages
90
The trigger works fine initially, but only the first time. In subsequent invocations, the units are moved to the center of the map and do not return to their original position. It works fine without bugs if I recreate the hashtable entirely at the end of the trigger. So, I need to clean it up, I suppose, but using "Hashtable - Clear" doesnt resolve the problem. Although I don't quite understand why I would need to do this since the unique keys of the units should replace the previous values. I'm not quite sure what's happening.
As I understand it, this function
1721225244795.png
clears all hash table values and deletes the table itself, so you can't use it again and get 0.

I also think that you don’t need to check these conditions because the “Fissure group” already contains only those units that meet these conditions, you did it above.
1721225539061.png
Hash table can contain a huge number of values, so there is no point in making a separate hash table for one skill, you can use the same table for all skills.
However in this case you don't need to clear the values by the first key like you do here
1721225942714.png

The main key is usually used for a unit, and the second for specific values (for example abilities), so it is better to clear a specific value instead of all values by main key.
 
Top