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

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

Status
Not open for further replies.
Level 12
Joined
Feb 5, 2018
Messages
521
  • 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! :)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
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
 

Attachments

  • Grand Illusion Example 1.w3m
    24 KB · Views: 27
Last edited:
Level 12
Joined
Feb 5, 2018
Messages
521
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!
 
Level 12
Joined
Feb 5, 2018
Messages
521
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.

Thank you for your suggestions, I for one like to use non-indexed locations to keep a better track of things.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
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!
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:
Status
Not open for further replies.
Top