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

First time using Hashtable - Need advice

Status
Not open for further replies.
Level 6
Joined
Oct 26, 2005
Messages
190
I had a GUI spell made and, because of its complexity, wanted to try using the Hashtable for the first time with it as a challenge. Now I don't really know if I'm doing it properly and what's missing and what needs to be removed and the leaks, you just tell me. It is implied I already set the Hashtable variable. There are 3 triggers.
EDIT: I already took care of part of the trigger for better efficiency, however I'm still not sure if everything's alright. Hope you can help me:

  • Meltdown
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Meltdown
    • Actions
      • Set Meltdown_Caster = (Triggering unit)
      • Set Meltdown_Angle = (Facing of Meltdown_Caster)
      • Set Meltdown_Points[0] = (Position of (Triggering unit))
      • Set Meltdown_Points[1] = (Meltdown_Points[0] offset by 150.00 towards Meltdown_Angle degrees)
      • Trigger - Turn on Meltdown Timer <gen>
      • -------- Hashes --------
      • Hashtable - Save ((2.00 x (Real((Level of Meltdown for (Triggering unit))))) + (0.50 x (Real((Strength of (Triggering unit) (Include bonuses)))))) as (Key dmg) of (Key (Triggering unit)) in Meltdown_Hash
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) is in Meltdown_CasterPick) Equal to False
        • Then - Actions
          • Unit Group - Add (Triggering unit) to Meltdown_CasterPick
        • Else - Actions
  • Meltdown Timer
    • Events
      • Time - Every 0.30 seconds of game time
    • Conditions
    • Actions
      • Unit - Create 1 Meltdown Dummy for (Owner of Meltdown_Caster) at Meltdown_Points[1] facing Meltdown_Angle degrees
      • Unit - Add Meltdown Effect to (Last created unit)
      • Unit - Order (Last created unit) to Neutral - Slam
      • Custom script: call RemoveLocation (udg_Meltdown_Points[1])
      • Set Meltdown_Timer = (Meltdown_Timer + 1)
      • Set Meltdown_Points[1] = (Meltdown_Points[0] offset by (150.00 x (Real(Meltdown_Timer))) towards Meltdown_Angle degrees)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Meltdown_Timer Equal to 5
        • Then - Actions
          • Set Meltdown_Timer = 0
          • Unit Group - Pick every unit in Meltdown_BuffPick and do (Actions)
            • Loop - Actions
              • Unit - Create 1 Dummy for (Owner of Meltdown_Caster) at Meltdown_Points[1] facing 0.00 degrees
              • Unit - Add Meltdown Armor Penalty to (Last created unit)
              • Unit - Set level of Meltdown Armor Penalty for (Last created unit) to (Level of Meltdown for Meltdown_Caster)
              • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Picked unit)
              • Unit - Remove Meltdown (Fake Buff) buff from (Picked unit)
              • Unit Group - Add (Picked unit) to Meltdown_GroupDPS
              • Hashtable - Save 10.00 as (Key dur) of (Key (Picked unit)) in Meltdown_Hash
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Meltdown DPS <gen> is on) Equal to False
            • Then - Actions
              • Trigger - Turn on Meltdown DPS <gen>
            • Else - Actions
          • Set Meltdown_Caster = No unit
          • Custom script: call DestroyGroup (udg_Meltdown_Pick[1])
          • Custom script: call RemoveLocation (udg_Meltdown_Points[0])
          • Custom script: call RemoveLocation (udg_Meltdown_Points[1])
          • Trigger - Turn off (This trigger)
        • Else - Actions
  • Meltdown DPS
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Meltdown_CasterPick and do (Actions)
        • Loop - Actions
          • Set Meltdown_Picked = (Picked unit)
          • Set Meltdown_DMG = (Load (Key dmg) of (Key (Picked unit)) from Meltdown_Hash)
          • Unit Group - Pick every unit in Meltdown_GroupDPS and do (Actions)
            • Loop - Actions
              • Set Meltdown_Dur = (Load (Key dur) of (Key (Picked unit)) from Meltdown_Hash)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Meltdown_Dur Greater than 0.00
                • Then - Actions
                  • Unit - Cause Meltdown_Picked to damage (Picked unit), dealing (Meltdown_DMG + (((Real((Level of Resist Fire for (Picked unit)))) x (Meltdown_DMG x -0.50)) + ((Real((Level of Weak to Fire for (Picked unit)))) x 0.50))) damage of attack type Chaos and damage type Fire
                  • Hashtable - Save (Meltdown_Dur - 1.00) as (Key dur) of (Key (Picked unit)) in Meltdown_Hash
                • Else - Actions
                  • Unit Group - Remove (Picked unit) from Meltdown_GroupDPS
                  • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Meltdown_Hash
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Number of units in Meltdown_GroupDPS) Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
          • Set Meltdown_Picked = No unit
I already took some suggestions from Dr Super Good and I hope I got them right. Now I know this spell may not bet completely efficient in coding, I would take any suggestion for better coding EXCEPT if you say "use JASS" since that's not my goal.

P.S. The dummies have negative regen so they automatically die.
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Resist Fire for (Picked unit)) Equal to 1
Then - Actions
Unit - Cause Meltdown_Picked to damage (Picked unit), dealing (Meltdown_DMG / 2.00) damage of attack type Chaos and damage type Fire
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Weak to Fire for (Picked unit)) Equal to 1
Then - Actions
Unit - Cause Meltdown_Picked to damage (Picked unit), dealing (Meltdown_DMG x 1.50) damage of attack type Chaos and damage type Fire
Else - Actions
Unit - Cause Meltdown_Picked to damage (Picked unit), dealing (Meltdown_DMG x 1.00) damage of attack type Chaos and damage type Fire

You have a lot of procedural coupling. As you are only changing the multiplyer value based on weakness, you need not duplicate the actual damage call for each case. Instead you could use a case like structure to set up a multiplyer local real and then use that in a single call to the damage native which will prevent unnescescary procedural coupling.

Unit - Cause Meltdown_Picked to damage (Picked unit), dealing (Meltdown_DMG x 1.00) damage of attack type Chaos and damage type Fire
Also I advise reading up about damage and weapon types. Fire is nothing special and only exists due to mechanics that were removed from WC3.

Meltdown_Timers[1]
Meltdown_Pick[0]
This is not appropiate use of arrays. Arrays are meant to provide functionality when you need what variable you are referencing to change based on another value. In this case your array indicies are constant and so for all purposes the variables need not be arrays. Making them arrays infact is slow because it means that extra bytes have to be loaded for the index. It is even worse in WC3 as they are dynamic arrays so there is a whole lot of code behind array access.

Events
Time - Every 1.00 seconds of game time
Conditions
(Number of units in Meltdown_Group) Greater than 0
This is a bad way to run code. Every second of game time you count the number of units in the group (an O(n) opperation of slow BJ calls) even if the group is empty or may never be filled.
The fast way for checking if a group is empty is to see if the top unit is equal to the null value. On top of that you can pause the trigger when the group is empty and resume it only when you add stuff to the group again (afterall why run at all when you know the group is empty and you always can start it then when you know you are adding a unit to an emptry group).
 
Level 6
Joined
Oct 26, 2005
Messages
190
You have a lot of procedural coupling. As you are only changing the multiplyer value based on weakness, you need not duplicate the actual damage call for each case. Instead you could use a case like structure to set up a multiplyer local real and then use that in a single call to the damage native which will prevent unnescescary procedural coupling.

I didn't really understand all of this. I mean, English is not my native language and I tend to get lost to certain terms. You mean for example assign a loop, maybe?

Also I advise reading up about damage and weapon types. Fire is nothing special and only exists due to mechanics that were removed from WC3.

I know, I just wanted to set it as fire (or is it better to not do it?). The damage type is detected by the abilities not the standard Damage/Armor values, that's why I set Chaos.

This is not appropiate use of arrays. Arrays are meant to provide functionality when you need what variable you are referencing to change based on another value. In this case your array indicies are constant and so for all purposes the variables need not be arrays. Making them arrays infact is slow because it means that extra bytes have to be loaded for the index. It is even worse in WC3 as they are dynamic arrays so there is a whole lot of code behind array access.

I didn't know this at all, but I did noticed it screwed part of the trigger (except for these). Changing it...

This is a bad way to run code. Every second of game time you count the number of units in the group (an O(n) opperation of slow BJ calls) even if the group is empty or may never be filled.
The fast way for checking if a group is empty is to see if the top unit is equal to the null value. On top of that you can pause the trigger when the group is empty and resume it only when you add stuff to the group again (afterall why run at all when you know the group is empty and you always can start it then when you know you are adding a unit to an emptry group).

That sounds good enough for a fix, gonna do that.

Thanks for all your support, man. You really are a master on all this. Maybe I should post part of the other triggers and the update so you can give me a hand with those too?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Hashtable - Save 10.00 as (Key dur) of (Key (Picked unit)) in Meltdown_Hash
Set Meltdown_DMG = (Load (Key dmg) of (Key (Picked unit)) from Meltdown_Hash)
Meltdown_Dur Greater than 0.00
Hashtable - Save (Meltdown_Dur - 1.00) as (Key dur) of (Key (Picked unit)) in Meltdown_Hash
As you are using whole numbers, you should rather use the integer type. Computers are faster at integer computation than floating point computation.
 
Status
Not open for further replies.
Top