1. Find your way through the deepest dungeon in the 18th Mini Mapping Contest Poll.
    Dismiss Notice
  2. A brave new world lies beyond the seven seas. Join the 34th Modeling Contest today!
    Dismiss Notice
  3. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
Hive 3 Remoosed BETA - NOW LIVE. Go check it out at BETA Hive Workshop! Post your feedback in this new forum BETA Feedback.
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Solved] Again hastables, multiple unit group + pick random unit and deal AoE damage

Discussion in 'Triggers & Scripts' started by DoomBlade, Aug 26, 2020.

  1. DoomBlade

    DoomBlade

    Joined:
    Feb 5, 2018
    Messages:
    365
    Resources:
    0
    Resources:
    0
    • Grand Illusion
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Grand Illusion (text not done)
      • Actions
        • -------- setting up --------
        • Set VariableSet GrandIllusion_Caster = (Triggering unit)
        • Set VariableSet GrandIllusion_Damage = ((Real((Level of Grand Illusion (text not done) for GrandIllusion_Caster))) x (125.00 + ((Real((Intelligence of GrandIllusion_Caster (Include bonuses)))) x 0.50)))
        • Game - Display to (All players) the text: (String(GrandIllusion_Damage))
        • -------- --------
        • Unit Group - Add GrandIllusion_Caster to GrandIllusion_CasterGroup
        • Unit Group - Pick every unit in GrandIllusion_CasterGroup and do (Actions)
          • Loop - Actions
            • Hashtable - Save 6.00 as 0 of (Key (Picked unit).) in GrandIllusion_Hash.
            • Hashtable - Save GrandIllusion_Damage as 2 of (Key (Picked unit).) in GrandIllusion_Hash.
        • Hashtable - Save Handle OfGrandIllusion_Caster as 1 of (Key (Triggering unit).) in GrandIllusion_Hash.
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Grand Illusion Loop <gen> is on) Equal to False
          • Then - Actions
            • Trigger - Turn on Grand Illusion Loop <gen>
          • Else - Actions

    • Grand Illusion Loop
      • Events
        • Time - Every 0.50 seconds of game time
      • Conditions
      • Actions
        • Unit Group - Pick every unit in GrandIllusion_CasterGroup and do (Actions)
          • Loop - Actions
            • Set VariableSet GrandIllusion_Time = (Load 0 of (Key (Picked unit).) from GrandIllusion_Hash.)
            • Set VariableSet GrandIllusion_Caster = (Load 1 of (Key (Picked unit).) in GrandIllusion_Hash.)
            • Set VariableSet GrandIllusion_Damage = (Load 2 of (Key (Picked unit).) from GrandIllusion_Hash.)
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • GrandIllusion_Time Greater than 0.00
                • (GrandIllusion_Caster is alive) Equal to True
              • Then - Actions
                • Set VariableSet GrandIllusion_Loc = (Position of GrandIllusion_Caster)
                • Set VariableSet GrandIllusion_DamageGroup = (Units within 600.00 of GrandIllusion_Loc.)
                • Hashtable - Save (GrandIllusion_Time - 0.50) as 0 of (Key (Picked unit).) in GrandIllusion_Hash.
                • -------- setting up unit group 1 --------
                • Unit Group - Pick every unit in GrandIllusion_DamageGroup and do (Actions)
                  • Loop - Actions
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • ((Picked unit) belongs to an enemy of (Owner of GrandIllusion_Caster).) Equal to True
                        • ((Picked unit) is alive) Equal to True
                        • ((Picked unit) is A structure) Equal to False
                        • ((Picked unit) is Mechanical) Equal to False
                        • ((Picked unit) is Magic Immune) Equal to False
                      • Then - Actions
                      • Else - Actions
                        • Unit Group - Remove (Picked unit) from GrandIllusion_DamageGroup.
                • -------- location clean up --------
                • Custom script: call RemoveLocation (udg_GrandIllusion_Loc)
                • -------- Picking random unit from group to create dummy --------
                • Unit Group - Pick every unit in (Random 1 units from GrandIllusion_DamageGroup) and do (Actions)
                  • Loop - Actions
                    • -------- setting target --------
                    • Set VariableSet GrandIllusion_Target = (Picked unit)
                    • -------- setting loc --------
                    • Set VariableSet GrandIllusion_Loc2 = (Position of GrandIllusion_Target)
                    • -------- dummy --------
                    • Unit - Create 1 Grand Illusion for (Owner of GrandIllusion_Caster) at GrandIllusion_Loc2 facing Default building facing degrees
                    • Set VariableSet GrandIllusion_Unit = (Last created unit)
                    • -------- --------
                    • -------- location clean up --------
                    • Custom script: call RemoveLocation (udg_GrandIllusion_Loc2)
                    • Unit - Order GrandIllusion_Unit to Night Elf Mountain Giant - Taunt.
                    • Unit - Add a 0.50 second Generic expiration timer to GrandIllusion_Unit
                    • Unit - Turn collision for GrandIllusion_Unit Off.
                    • Animation - Change GrandIllusion_Unit's vertex coloring to (0.00%, 75.00%, 100.00%) with 40.00% transparency
                    • -------- setting damage location --------
                    • Set VariableSet GrandIllusion_Loc3 = (Position of GrandIllusion_Unit)
                    • -------- setting damage group --------
                    • Set VariableSet GrandIllusion_DamageGroup2 = (Units within 300.00 of GrandIllusion_Loc3.)
                    • Unit Group - Pick every unit in GrandIllusion_DamageGroup2 and do (Actions)
                      • Loop - Actions
                        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                          • If - Conditions
                            • ((Picked unit) belongs to an enemy of (Owner of GrandIllusion_Caster).) Equal to True
                            • ((Picked unit) is alive) Equal to True
                            • ((Picked unit) is A structure) Equal to False
                            • ((Picked unit) is Mechanical) Equal to False
                            • ((Picked unit) is Magic Immune) Equal to False
                          • Then - Actions
                            • -------- damage --------
                            • -------- this sometimes deals around 900 damage --------
                            • -------- even that I checked that the damage is loaded correctly --------
                            • Game - Display to (All players) the text: (String(GrandIllusion_Damage))
                            • Unit - Cause GrandIllusion_Caster to damage GrandIllusion_Target, dealing GrandIllusion_Damage damage of attack type Spells and damage type Magic
                          • Else - Actions
                            • Unit Group - Remove (Picked unit) from GrandIllusion_DamageGroup2.
                • -------- location clean up --------
                • Custom script: call DestroyGroup (udg_GrandIllusion_DamageGroup)
                • Custom script: call DestroyGroup (udg_GrandIllusion_DamageGroup2)
                • Custom script: call RemoveLocation (udg_GrandIllusion_Loc3)
              • Else - Actions
                • -------- clean up --------
                • Unit Group - Remove GrandIllusion_Caster from GrandIllusion_CasterGroup.
                • Hashtable - Clear all child hashtables of child (Key (Picked unit).) in GrandIllusion_Hash.
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (Number of units in GrandIllusion_CasterGroup) Less than or equal to 0
              • Then - Actions
                • Trigger - Turn off (This trigger)
                • Unit Group - Remove all units of GrandIllusion_CasterGroup from GrandIllusion_CasterGroup.
              • Else - Actions


    Hello again hivers. The more you try, the more issues.

    So what I wanted this ability to do is:
    Pick units within 600 AoE of the Caster
    Creates an image to random unit - image casts skill that then deals damage to units within 300 AoE
    The taunt is only for eye candy, since the effect is pretty cool in reforged

    Issues:
    The units in DamageGroup2 don't take the damage, only one unit takes the damage.
    Dead units are not filtered out of DamageGroup2

    Sometimes one unit takes multiple times the damage it is supposed to take. Around 900 or even more sometimes.

    Sorry for the long triggers, I tried to add some comments this time to make it easier to read.

    Cheers! :)
     
  2. Devalut

    Devalut

    Joined:
    Feb 9, 2009
    Messages:
    1,490
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    Probably save some space by using the special effect line to achieve the taunt visual.

    Edit: also for the location variable, instead of creating three separate variables use the array to keep it simple.
     
    Last edited: Aug 26, 2020
  3. Uncle

    Uncle

    Joined:
    Aug 10, 2018
    Messages:
    2,471
    Resources:
    0
    Resources:
    0
    So based on what you said, this is how the spell works:
    -You cast the spell
    -Every 0.50 seconds a random nearby enemy unit is hit with an AoE nuke
    -After 6.00 seconds the effect ends

    I feel like you're over complicating things here. I don't see the need for saving the Caster in the Hashtable nor do I see the need for the DamageGroups. You should create/destroy a single Unit Group each time.

    Technically you don't need to save the Damage to the Hashtable either, as this could be determined prior to dealing the damage. Although this is up to you, as you may want to "snapshot" the damage upon spell cast.

    So I guess what i'm saying is that the Hashtable seems unnecessary. I attached an example map that uses a Unit Indexer instead of a Hashtable.
    • GI Cast
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
      • Actions
        • Set VariableSet GI_Caster = (Triggering unit)
        • Set VariableSet GI_CV = (Custom value of GI_Caster)
        • Set VariableSet GI_Duration[GI_CV] = 6.00
        • Set VariableSet GI_Damage[GI_CV] = 100.00
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (GI_Caster is in GI_CasterGroup.) Equal to False
          • Then - Actions
            • Unit Group - Add GI_Caster to GI_CasterGroup
          • Else - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (GI Loop <gen> is on) Equal to False
          • Then - Actions
            • Trigger - Turn on GI Loop <gen>
          • Else - Actions

    • GI Loop
      • Events
        • Time - Every 0.50 seconds of game time
      • Conditions
      • Actions
        • Unit Group - Pick every unit in GI_CasterGroup and do (Actions)
          • Loop - Actions
            • Set VariableSet GI_Caster = (Picked unit)
            • Set VariableSet GI_CV = (Custom value of GI_Caster)
            • -------- --------
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • GI_Duration[GI_CV] Greater than 0.00
                • (GI_Caster is alive) Equal to True
              • Then - Actions
                • Set VariableSet GI_Duration[GI_CV] = (GI_Duration[GI_CV] - 0.50)
                • Set VariableSet GI_Point = (Position of GI_Caster)
                • -------- --------
                • -------- Get nearby enemy units --------
                • Set VariableSet GI_EnemyGroup = (Units within 600.00 of GI_Point.)
                • Unit Group - Pick every unit in GI_EnemyGroup and do (Actions)
                  • Loop - Actions
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • ((Picked unit) is alive) Equal to True
                        • ((Picked unit) belongs to an enemy of (Owner of GI_Caster).) Equal to True
                      • Then - Actions
                      • Else - Actions
                        • Unit Group - Remove (Picked unit) from GI_EnemyGroup.
                • Set VariableSet GI_Target = No unit
                • Set VariableSet GI_Target = (Random unit from GI_EnemyGroup)
                • -------- --------
                • -------- Clean up leaks --------
                • Custom script: call RemoveLocation (udg_GI_Point)
                • Custom script: call DestroyGroup (udg_GI_EnemyGroup)
                • -------- --------
                • -------- Check if it found a valid target --------
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • GI_Target Not equal to No unit
                  • Then - Actions
                    • -------- Deal damage --------
                    • Set VariableSet GI_Point = (Position of GI_Target)
                    • Set VariableSet GI_EnemyGroup = (Units within 300.00 of GI_Point.)
                    • Unit Group - Pick every unit in GI_EnemyGroup and do (Actions)
                      • Loop - Actions
                        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                          • If - Conditions
                            • ((Picked unit) is alive) Equal to True
                            • ((Picked unit) belongs to an enemy of (Owner of GI_Caster).) Equal to True
                          • Then - Actions
                            • Unit - Cause GI_Caster to damage (Picked unit), dealing GI_Damage[GI_CV] damage of attack type Spells and damage type Normal
                          • Else - Actions
                    • -------- --------
                    • -------- Create special effect --------
                    • Special Effect - Create a special effect at GI_Point using Abilities\Spells\NightElf\Taunt\TauntCaster.mdl
                    • Special Effect - Destroy (Last created special effect)
                    • -------- --------
                    • -------- Clean up leaks --------
                    • Custom script: call RemoveLocation (udg_GI_Point)
                    • Custom script: call DestroyGroup (udg_GI_EnemyGroup)
                  • Else - Actions
              • Else - Actions
                • -------- Turn off --------
                • Unit Group - Remove GI_Caster from GI_CasterGroup.
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • (Number of units in GI_CasterGroup) Equal to 0
                  • Then - Actions
                    • Trigger - Turn off (This trigger)
                  • Else - Actions
     

    Attached Files:

    Last edited: Aug 26, 2020
  4. DoomBlade

    DoomBlade

    Joined:
    Feb 5, 2018
    Messages:
    365
    Resources:
    0
    Resources:
    0
    I used your version, it's alot smoother and runs as should. :)

    Lately, i've been using hashtables a lot, just to learn a bit more how to use them.

    Off-topic, do you think Unit indexer is superior to Hashtables?

    Might as well drop them, if using custom values is more efficient.

    And thanks again Uncle!
     
  5. DoomBlade

    DoomBlade

    Joined:
    Feb 5, 2018
    Messages:
    365
    Resources:
    0
    Resources:
    0
    Thank you for your suggestions, I for one like to use non-indexed locations to keep a better track of things.
     
  6. Uncle

    Uncle

    Joined:
    Aug 10, 2018
    Messages:
    2,471
    Resources:
    0
    Resources:
    0
    Use them both! I go with whichever is necessary.

    I personally find that dynamic indexing + unit indexing can do just about anything, however, that doesn't mean Hashtables aren't useful either.

    Note that there is a Hashtable limit of ~255, but that's quite a difficult number to reach.
     
    Last edited: Aug 26, 2020