1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Travel to distant realms and encounter scenes unknown to the common folk. The Greatest of Adventures is upon us with the 8th Cinematic Contest. Join in on a fun ride.
    Dismiss Notice
  4. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  5. The Secrets of Warcraft 3 have revealed interesting works. The RESULTS for Abelhawk's Mini-Mapping Contest #15 have come out!
    Dismiss Notice
  6. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  7. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  8. Night Rider gained several songs for his journey. The poll for the 12th Music Contest has started. Check it out!
    Dismiss Notice
  9. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  10. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

A Complete Beginners Guide to Hashtables

Discussion in 'Trigger (GUI) Editor Tutorials' started by Jazztastic, Jun 15, 2011.

  1. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7

    A Complete Beginners Guide to Hashtables



    Written because even after reading all the hashtable tutorials on this site, I still had questions.

    Table of Contents


    1. Requirements to Fully Appreciate this Tutorial
    2. Hashtables and You
    3. Handles and Hashtables
    4. Useful Examples of the Hashtable in Action
    5. Miscellaneous Hashtable Information
    6. Credits


    Requirements to Fully Appreciate this Tutorial


    • Basic knowledge of GUI scripting
    • The ability to follow directions
    • Full comprehension of the English language
    • A desire to learn
    • Patience

    Hashtables and You



    What is a Hashtable?


    Hashtables are data structures. A variable array works by storing multiple pieces of data, imagine it as the X axis in a graph. Now imagine a variable array that is complicated enough to store data not just along the X axis, but also the Y. This allows us to have a much more varied variable (pardon the wordplay) Hashtables work by saving the value of the variable until you need it later. It then loads the value of the variable so it can be used with the exact same data as before.

    Why use a Hashtable?


    Simply put, hashtables are easy ways to make your spells MUI. Spells that are not MUI will immediately be rejected from the Spells section of THW. Unless you only have a single instance of a unit on your map, not being MUI will cause multiple casts of the spell to malfunction. Hashtables have allowed me to advance worlds ahead of were I was when I started triggering. They are open ended and any spell that isn't instant will need hashtables or recycling.

    At the same time, using hashtables has its drawbacks. It is sometimes quite annoying to have to load every value, and if you make a mistake in a spell it can be quite a long time before you realize you didn't save or load a value correctly. Hashtables are also slower than arrays.

    Now let's look at how to make a hashtable.​
    Trigger
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set EX_Hash = (Last created hashtable)

    What does that Trigger Above Mean?


    Broken down, the trigger means that at the start of the map, a hashtable will be created. The hashtable will be assigned the variable EX_Hash. Most hashtables are going to be created at the start of the map. You need to assign the hashtable a variable name. This is because you will probably have multiple hashtables. If you import a spell or a system, it will probably have a hashtable associated with it. If you assign your variables to (last created hashtable) instead of your hashtable variable, you may accidently load a value from a different hashtable!​

    Handles and Hashtables



    What is a Handle?


    A handle is anything that is not a real, boolean, integer, or string. Handles can be saved with hashtables, allowing us to extract exact information portaining to that handle whenever we want to. Simply put, it's like saving a new variable for each handle, even if the variable is changed later, we can load the value of whatever the handle is and still have the original starting variable.

    Here is an example of a hashtable without handles. While it is still useful, it can be even better with them​
    Trigger
    • Events
      • Map initialization
      • Conditions
      • Actions
        • Hashtable - Create a hashtable
        • Set EX_Hash = (Last created hashtable)

    • Events
    • Conditions
    • Actions
      • Set EX_Real = 20.00
      • Hashtable - Save EX_Real as 1 of 1 in EX_Hash
      • Set EX_Real = 4566.00
      • Set EX_Real = 12345.00
      • Set EX_Real = 100000000.00
      • Set EX_Real = (Load 1 of 1 from EX_Hash)
    In this example, when the even happens, the real number 20 will be saved into value 1 of 1 in the hashtable EX_Hash. Afterwards, you can change the variable however you like, and it will not affect the value 1 of 1 in the hashtable. You can load the value after changing EX_Real, and the loaded value will be what you first saved it as, in this example the number is 20.​

    How can we use Handles Effectively?


    Handles are used in conjunction with hashtables. A handle describes the value being saved. If you were saving EX_Real to the triggering unit of an ability, you change it to say (key (triggering unit)). Key simply is a way of identifying handles. Let's look below at a simple damage over time spell that uses handles to correctly damage every unit targetted. Please note that leaks will be addressed fully in this example.​

    Trigger
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Damage Over Time
    • Actions
      • Set EX_Target = (Target unit of ability being cast)
      • Set EX_Damage = 20.00
      • Set EX_Timer = 5.00
      • Unit Group - Add (Target unit of ability being cast) to EX_Group
      • Hashtable - Save EX_Timer as 1 of (Key (Target unit of ability being cast)) in EX_Hash
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in EX_Group and do (Actions)
        • Loop - Actions
          • Set EX_Timer = (Load 1 of (Key (Picked unit)) from EX_Hash)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • EX_Timer Greater than 0.00
            • Then - Actions
              • Unit - Set life of (Picked unit) to ((Life of (Picked unit)) - EX_Damage)
              • Hashtable - Save (EX_Timer - 1.00) as 1 of (Key (Picked unit)) in EX_Hash
            • Else - Actions
              • Unit Group - Remove (Picked unit) from EX_Group
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in EX_Hash
    This is a lot to look at. Spend a minute or two trying to roughly get the idea of what is happening in this spell. The targetted unit of the ability "Damage Over Time" is being added to the group "EX_Group". Every second, members of the group are checked to see how much time they have left in the spell. If they are not done with the duration of the spell, they suffer twenty damage. If they are done with the duration of the spell, they are removed from the damage group, and the child hashtables are cleared. This means that all that extra data solely belonging to the picked unit is destroyed. It is the hashtable equivelent of destroying memory leaks. Always make sure to include it at the end of spells. The absolute most important thing to pay attention to right now is how the hashtable values are saved. They correspond to how you identify the unit. EX_Timer is saved in the first part as (key (target unit of ability being cast)). At the second trigger it is being referenced to with (key (picked unit)). This is because the unit is being selected as picked unit instead of target unit of ability being cast. This difference in handles is crucial to understanding the beast known as the hashtable. If you are going to use a trigger like this, please make it more efficient by assigning unit references (picked unit, for example) to variables and then calling them.

    Quick guide for recreating this trigger
    • EX_Timer is a real
    • EX_Group is a unit group
    • EX_Damage is a real


    Where can Handles Take You?


    Handles are quite possibly the most important parts of hashtables. It allows it to be MUI, and it gives hashtables their dynamic quality. You must learn to effectively use handles if you want your spells to be MUI.​

    Set udg_VARIABLE = GetHandleId(udg_UNIT)


    A great little line, this baby is highly important to hashtables. Used with custom script, this will automatically pick the correct key corresponding to the unit. In the custom script, VARIABLE will be the name of an Integer variable, while UNIT will be the name of the unit variable. Look below for an example of how to use this.

    • Set Unit = (Picked unit)
    • Custom script: set udg_Handle = GetHandleId(udg_Unit)
    • -------- Handle is my integer variable, Unit is my unit variable --------
    • Hashtable - Save Timer as 1 of Handle in Hash


    Useful Examples of the Hashtable in Action



    Please note that triggers are in the third section. Both spells are by Jazztastic, please give credit if used. Main purpose of these is to show examples of how hashtables and handles can be used effectively in spells

    Tank Attack!, a Spell With Movement


    Most spells use dummy units to deal damage and create visual effects for the spell. "Movement" is a term I use when talking about physically moving the dummy unit to help create effects for a spell.

    Provided for you is the trigger to "Tank Attack!", a spell that creates a horde of miniature tanks to run over your enemies. Tanks are created every 0.04 seconds. 25 tanks are created over 1 second.​

    Missile Launch, a Spell With Knockback


    Knockback is when a spell causes a unit to slide backwards from its spot. It is effectively stunned because it can take no actions. Knockback is a desireable effect to have in a map because it looks nice, and is more interesting than just a stun.

    Provided for you is the trigger to "Missile Launch", a spell that shoots a missile at target location. Upon coming within range of a unit, the missile explodes, damaging all units in X range and knocking them back a random distance between X and X. It is similar to Tank Attack! in that it uses movement, but I consider this a step up from Tank Attack!. I recommend using imported explosions for the explosion effects.

    The Triggers and Explainations for Tank Attack! and Missile Launch


    Trigger
    • Variables
      • Events
        • Map initialization
      • Conditions
      • Actions
        • -------- ------------------- --------
        • -------- Tank Attack --------
        • -------- ------------------- --------
        • Hashtable - Create a hashtable
        • Set TA_Hash = (Last created hashtable)
        • Set TA_Aoe = 100.00
        • Set TA_Damage = 1.00
        • -------- ------------------- --------
        • -------- Missile Launch --------
        • -------- ------------------- --------
        • Hashtable - Create a hashtable
        • Set ML_Hash = (Last created hashtable)
        • Set ML_Aoe = 120.00
    I personally like to keep my hashtables seperate for my spells. It is not necessary, but I recommend it to help keep track of your stuff. Also, a few variables that only need to be loaded once are present in this map init trigger​

    Tank Attack Trigger
    • Tank Attack Cast
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Copter Attack!
      • Actions
        • Set TA_Caster = (Triggering unit)
        • Sound - Play SteamTankBeep <gen>
        • Set TA_Level = (Level of (Ability being cast) for TA_Caster)
        • Set TA_Target = (Target point of ability being cast)
        • Set TA_Time = 1.00
        • Unit Group - Add TA_Caster to TA_Group1
        • Hashtable - Save TA_Level as 1 of (Key (Triggering unit)) in TA_Hash
        • Hashtable - Save TA_Time as 2 of (Key (Triggering unit)) in TA_Hash
        • Custom script: call RemoveLocation(udg_TA_Target)
        • Trigger - Turn on Tank Attack Loop <gen>
    • Tank Attack Loop
      • Events
        • Time - Every 0.04 seconds of game time
      • Conditions
      • Actions
        • Unit Group - Pick every unit in TA_Group1 and do (Actions)
          • Loop - Actions
            • Set TA_Level = (Load 1 of (Key (Picked unit)) from TA_Hash)
            • Set TA_Time = (Load 2 of (Key (Picked unit)) from TA_Hash)
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • TA_Time Greater than 0.00
              • Then - Actions
                • Set TA_Caster = (Picked unit)
                • Set TA_Point1 = (Position of TA_Caster)
                • Unit - Create 1 Mini Tank for (Owner of TA_Caster) at TA_Point1 facing ((Facing of TA_Caster) + (Random real number between -25.00 and 25.00)) degrees
                • Set TA_Tank = (Last created unit)
                • Unit - Add a 2.00 second Generic expiration timer to TA_Tank
                • Unit - Make TA_Tank Explode on death
                • Unit Group - Add TA_Tank to TA_Group2
                • Hashtable - Save TA_Level as 1 of (Key (Last created unit)) in TA_Hash
                • Hashtable - Save (TA_Time - 0.04) as 2 of (Key (Picked unit)) in TA_Hash
                • Custom script: call RemoveLocation(udg_TA_Point1)
                • Set TA_Loops = (TA_Loops + 1)
              • Else - Actions
                • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in TA_Hash
                • Unit Group - Remove (Picked unit) from TA_Group1
        • Unit Group - Pick every unit in TA_Group2 and do (Actions)
          • Loop - Actions
            • Sound - Play SteamTankMovement <gen>
            • Set TA_Level = (Load 1 of (Key (Picked unit)) from TA_Hash)
            • Set TA_Tank = (Picked unit)
            • Set TA_Point1 = (Position of TA_Tank)
            • Set TA_Point2 = (TA_Point1 offset by 25.00 towards (Facing of TA_Tank) degrees)
            • Unit - Move TA_Tank instantly to TA_Point2
            • Custom script: set bj_wantDestroyGroup = true
            • Unit Group - Pick every unit in (Units within TA_Aoe of TA_Point2 matching (((Matching unit) belongs to an enemy of (Owner of TA_Tank)) Equal to True)) and do (Actions)
              • Loop - Actions
                • Special Effect - Create a special effect attached to the chest of (Triggering unit) using Objects\Spawnmodels\Human\HumanBlood\BloodElfSpellThiefBlood.mdl
                • Special Effect - Destroy (Last created special effect)
                • Unit - Cause TA_Tank to damage (Picked unit), dealing (TA_Damage x (Real(TA_Level))) damage of attack type Spells and damage type Normal
    • Tank Attack End
      • Events
        • Unit - A unit Dies
      • Conditions
        • (Unit-type of (Triggering unit)) Equal to Mini Tank
      • Actions
        • Unit Group - Remove (Triggering unit) from TA_Group2
        • Hashtable - Clear all child hashtables of child (Key (Triggering unit)) in TA_Hash
        • Set TA_Loops = (TA_Loops - 1)
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • TA_Loops Less than or equal to 0
          • Then - Actions
            • Trigger - Turn off (This trigger)
          • Else - Actions
    In the first trigger, notice the sound being played. You will have to use the sound editor to get this sound from the game. In the second trigger it is important to notice that both the movement for the units and their creation run off the same timer.

    Quick guide for recreating this trigger
    • TA_Angle is a real
    • TA_Aoe is a real
    • TA_Caster is a unit
    • TA_Tank is a unit
    • TA_Damage is a real
    • TA_Group1 is a unit group
    • TA_Group2 is a unit group
    • TA_Hash is a hashtable
    • TA_Level is an integer
    • TA_Point1 is a point
    • TA_Point2 is a point
    • TA_Point3 is a point
    • TA_Target is a point
    • TA_Timer is a real
    • TA_Loops is an integer


    Following are the triggers for Missile Launch

    Missile Launch Triggers
    • Missile Launch Cast
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Missile Launch
      • Actions
        • Set ML_Caster = (Triggering unit)
        • Set ML_Point1 = (Position of ML_Caster)
        • Unit - Create 1 Missile for (Triggering player) at ML_Point1 facing (Facing of ML_Caster) degrees
        • Unit Group - Add (Last created unit) to ML_Group
        • Set ML_Timer = 2.00
        • Hashtable - Save ML_Timer as 1 of (Key (Last created unit)) in ML_Hash
        • Trigger - Turn on Missile Launch Loop <gen>
        • Custom script: call RemoveLocation(udg_ML_Point1)
    • Missile Launch Loop
      • Events
        • Time - Every 0.04 seconds of game time
      • Conditions
      • Actions
        • Unit Group - Pick every unit in ML_Group and do (Actions)
          • Loop - Actions
            • Set ML_Timer = (Load 1 of (Key (Picked unit)) from ML_Hash)
            • Set ML_Missile = (Picked unit)
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • ML_Timer Greater than 0.00
              • Then - Actions
                • Hashtable - Save (ML_Timer - 0.04) as 1 of (Key (Picked unit)) in ML_Hash
                • Set ML_Point1 = (Position of ML_Missile)
                • Set ML_Point2 = (ML_Point1 offset by 30.00 towards (Facing of ML_Missile) degrees)
                • Unit - Move ML_Missile instantly to ML_Point2
                • Custom script: set bj_wantDestroyGroup = true
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • (Number of units in (Units within ML_Aoe of ML_Point2 matching (((Matching unit) belongs to an enemy of (Owner of ML_Missile)) Equal to True))) Equal to 0
                  • Then - Actions
                    • Custom script: set bj_wantDestroyGroup = true
                    • Unit Group - Pick every unit in (Units within 300.00 of ML_Point2 matching (((Matching unit) belongs to an enemy of (Owner of ML_Missile)) Equal to True)) and do (Actions)
                      • Loop - Actions
                        • Unit - Cause ML_Missile to damage (Picked unit), dealing 250.00 damage of attack type Siege and damage type Demolition
                        • Unit Group - Add (Picked unit) to ML_Group2
                        • Set ML_Point3 = (Position of (Picked unit))
                        • Set ML_Angle = (Angle from ML_Point2 to ML_Point3)
                        • Set ML_Timer = 1.40
                        • Set ML_Distance = ((Random real number between 50.00 and 150.00) x 0.04)
                        • Hashtable - Save ML_Timer as 1 of (Key (Picked unit)) in ML_Hash
                        • Hashtable - Save ML_Angle as 2 of (Key (Picked unit)) in ML_Hash
                        • Hashtable - Save ML_Distance as 3 of (Key (Picked unit)) in ML_Hash
                        • Set ML_Loops = (ML_Loops + 1)
                        • Custom script: call RemoveLocation(udg_ML_Point3)
                    • Unit - Explode ML_Missile
                    • Special Effect - Create a special effect at ML_Point2 using war3mapImported\ExplosionBIG.mdx
                    • Special Effect - Destroy (Last created special effect)
                    • Set ML_Timer = 0.00
                    • Hashtable - Save ML_Timer as 1 of (Key (Picked unit)) in ML_Hash
                  • Else - Actions
                • Custom script: call RemoveLocation(udg_ML_Point1)
                • Custom script: call RemoveLocation(udg_ML_Point2)
              • Else - Actions
                • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in TA_Hash
                • Unit - Explode ML_Missile
                • Unit Group - Remove ML_Missile from ML_Group
        • Unit Group - Pick every unit in ML_Group2 and do (Actions)
          • Loop - Actions
            • Set ML_KnockBackUnit = (Picked unit)
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (ML_KnockBackUnit is alive) Equal to True
              • Then - Actions
                • Set ML_Timer = (Load 1 of (Key (Picked unit)) from ML_Hash)
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • ML_Timer Greater than 0.00
                  • Then - Actions
                    • Hashtable - Save (ML_Timer - 0.04) as 1 of (Key (Picked unit)) in ML_Hash
                    • Set ML_Angle = (Load 2 of (Key (Picked unit)) from ML_Hash)
                    • Set ML_Distance = (Load 3 of (Key (Picked unit)) from ML_Hash)
                    • Set ML_Point1 = (Position of ML_KnockBackUnit)
                    • Set ML_Point2 = (ML_Point1 offset by ML_Distance towards ML_Angle degrees)
                    • Unit - Move ML_KnockBackUnit instantly to ML_Point2
                    • Special Effect - Create a special effect attached to the origin of ML_KnockBackUnit using Abilities\Spells\Human\FlakCannons\FlakTarget.mdl
                    • Special Effect - Destroy (Last created special effect)
                    • Unit - Order ML_KnockBackUnit to Stop
                  • Else - Actions
                    • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in ML_Hash
                    • Unit Group - Remove (Picked unit) from ML_Group2
                    • Set ML_Loops = (ML_Loops - 1)
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • ML_Loops Less than or equal to 0
                      • Then - Actions
                        • Trigger - Turn off (This trigger)
                      • Else - Actions
              • Else - Actions
                • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in ML_Hash
                • Unit Group - Remove ML_KnockBackUnit from ML_Group2
                • Set ML_Loops = (ML_Loops - 1)
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • ML_Loops Less than or equal to 0
                  • Then - Actions
                    • Trigger - Turn off (This trigger)
                  • Else - Actions
    Quick guide for recreating this trigger
    • ML_Angle is a real
    • ML_Aoe is a real
    • ML_Caster is a unit
    • ML_Distance is a real
    • ML_Group1 is a unit group
    • ML_Group2 is a unit group
    • ML_Hash is a hashtable
    • ML_KnockBackUnit is a unit
    • ML_Missile is a unit
    • ML_Point1 is a point
    • ML_Point2 is a point
    • ML_Point3 is a point
    • ML_Timer is a real
    • ML_Loops is an integer


    Miscellaneous Hashtable Information


    • You are only allowed to have 256 hashtables
    • Having the creation of the hashtable in the trigger will not only make it innefficient, it will also make it NOT MUI
    • Multiple spells can use the same hashtable. You should have no more than 10 hashtables in your map
    • Hashtables are also useful for systems, not just spells

    Credits


    I would like to thank Wyrmlord for his awesome tutorial on hashtables. It helped get me going, but I didn't think it was clear enough, so heres mine :) I would also like to thank Dr. SuperGood and Maker for some information. Finally, I would like to thank Archangel for some trigger corrections. Please comment and rate, I like feedback.​

    Change Log


    v1.0 Uploaded tutorial to The Hive.
    v1.1 Fixed incorrect information, fixed example triggers, added Change Log and Future Changes to Come sections.
    v1.2 Put [goto] and [point] into the tutorial to link the table of contents to the corresponding section. [r] v1.3 [c] Put hidden ta gs around the triggers to increase readability. [r] v1.4 [c] Updated spells in the example section. They now work better and without leaks. [r] v1.5 [c] Added the Custom Script section.[/point]
    [point][/point]​
    [point]

    Future Changes to Come


    Any more feedback given by the community on information that is incorrect or needs to be added shall be considered. More example spells may follow.
    [/point]
     
    Last edited: Aug 13, 2011
  2. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Comment and rate please
     
    Last edited: Jun 15, 2011
  3. Archangel678

    Archangel678

    Joined:
    Apr 25, 2009
    Messages:
    246
    Resources:
    4
    Spells:
    4
    Resources:
    4
    Comments
    I'd suggest adding a key, or a link to separate parts. (Click here, scrolls to basic info, click here 2, scrolls to Tank Attack!

    Also, a map showing hashtables in action would help.

    Also, this little line can help alot with hashtables, as it makes it much more efficient:

    • Custom script: set udg_YOURINTEGER = GetHandleId(udg_UNIT)
    You probably should include linebreaks and documentation for your larger spells.

    I recommend using AnarchainBedlams miniature tank model, because multiple units casting this spell with the regular steam tank's model will cause massive lag!

    I'd suggest removing that line altogether, it can sound like advertising and has no major correlation with hashtables.

    =======Triggering Errors/Suggestions=======

    • And - All (Conditions) are true
    No point in that, its already set that way....

    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • ((Picked unit) is alive) Equal to True
        • Set ML_KnockBackUnit = (Picked unit)
    You could set ML_KnockBackUnit = (Picked Unit) before the if/then/else.

    • Custom script: set bj_wantDestroyGroup = true
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    What's the point of that? Remove the bj_wantDestroyGroup = true

    • If - ConditionAnd - All (Conditions) are true
    • Conditions
      • (ML_Group is empty) Equal to True
      • (ML_Group2 is empty) Equal to True
    You should use an integer and increase it when the spell is cast and decrease it when the spell is over so that you're not checking if the groups are empty every loop.


    This looks very good, very useful too.
     
    Last edited: Jun 15, 2011
  4. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Archangel I am fixing all your suggestions except for the last. I do not understand the method you are suggesting. How would using an integer be different, wouldn't you still have to check every loop whether the integer was zero or not?

    Maker, thank you for the information. My bad for begging for rep.

    I'm updating it now.

    EDIT: I have updated my tutorial, with everything mentioned by both Archangel and Maker except for that integer check thing. Most notable I added change log and future updates section.
     
  5. Archangel678

    Archangel678

    Joined:
    Apr 25, 2009
    Messages:
    246
    Resources:
    4
    Spells:
    4
    Resources:
    4
    Integer thingy

    Spell Cast:

    Increase integer by 1.
    Turn on loop

    Spell Ends:

    Decrease integer by 1.

    If integer = 0

    Turn off loop.
     
  6. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Do like this during the casting time...
    • Set EX_Target = (Target unit of ability being cast)
    • Custom script: set udg_ID = GetHandleId(udg_EXTarget)
    • Set EX_Damage = 20.00
    • Set EX_Timer = 5.00
    • Unit Group - Add (Target unit of ability being cast) to EX_Group
    • Hashtable - Save EX_Timer as 1 of udg_ID in EX_Hash


    While during the loop time...
    • Custom script: set udg_ID = GetHandleId(GetEnumUnit())
    • Set EX_Timer = (Load 1 of udg_ID from EX_Hash)


    Where ID is an integer variable

    But Maker said it's GUI so stick to GUI, but the above is more efficient and faster...
     
  7. Bannar

    Bannar

    Joined:
    Mar 19, 2008
    Messages:
    3,087
    Resources:
    20
    Spells:
    5
    Tutorials:
    1
    JASS:
    14
    Resources:
    20
    I won't reapet things already mentioned. However you could use hidden tags for triggers, making your tutorials cleaner and easier to step through.
     
  8. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    A very good and easy idea. Thank you

    While efficiency is very very important in coding, this tutorial was aimed more at noobs. But you are very correct, making the handles via custom script it more efficient. I'll certainly change it in my version of the spell.
     
  9. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,427
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    It looks really good to me. Nice job on the tutorial.

    ~Approved.
     
  10. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    HELL YES!:ogre_datass:
     
  11. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,193
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    In your tank attack cast trigger you save target point of ability into a variable and then into a hashtable. Then you immediately remove it. This means the point no longer exists. After that you try to use it in the looping trigger. You should remove it when you don't need it anymore, most likely right before you flush the child hashtable.

    Your number of units in xxx condition leaks.
     
  12. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    These triggers are old, I need to do some updating. The target point isn't even used in the loop, I need to repost the new triggers. Btw Maker, is there a function similar to set bj_wantDestroyGroup = true that can be used for conditions? Or do I have to assign the group to a variable and then clear? Efficiency matters :)
     
  13. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,193
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    Set the boolean to true before the condition :)
     
  14. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    I didn't quite get this part, but here's what I came up with:

    • Set ML_GroupCheck = (Units within ML_Aoe of ML_Point2 matching (((Matching unit) belongs to an enemy of (Owner of ML_Missile)) Equal to True))
    • Set ML_GroupCheckInteger = (Number of units in ML_GroupCheck)
    • If - Conditions
      • ML_GroupCheckInteger Greater than or equal to 1
    • Then - Actions
      • Do Stuff
    • Custom script: call DestroyForce(udg_ML_GroupCheck)


    I'm pretty sure it works, cause its just replacing the if with a variable which replaced another variable which was cleared. So there shouldn't be any leaks. I don't think it's very efficient tho :ogre_icwydt:
     
  15. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,193
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    • Custom script: set bj_wantDestroyGroup = true
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Number of units in (Units in (Playable map area))) Equal to 0
      • Then - Actions
      • Else - Actions
     
  16. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Facepalm

    . . . . . .. . . . . . . . . . . ,.-‘”. . . . . . . . . .``~.,
    . . . . . . . .. . . . . .,.-”. . . . . . . . . . . . . . . . . .“-.,
    . . . . .. . . . . . ..,/. . . . . . . . . . . . . . . . . . . . . . . ”:,
    . . . . . . . .. .,?. . . . . . . . . . . . . . . . . . . . . . . . . . .\,
    . . . . . . . . . /. . . . . . . . . . . . . . . . . . . . . . . . . . . . ,}
    . . . . . . . . ./. . . . . . . . . . . . . . . . . . . . . . . . . . ,:`^`.}
    . . . . . . . ./. . . . . . . . . . . . . . . . . . . . . . . . . ,:”. . . ./
    . . . . . . .?. . . __. . . . . . . . . . . . . . . . . . . . :`. . . ./
    . . . . . . . /__.(. . .“~-,_. . . . . . . . . . . . . . ,:`. . . .. ./
    . . . . . . /(_. . ”~,_. . . ..“~,_. . . . . . . . . .,:`. . . . _/
    . . . .. .{.._$;_. . .”=,_. . . .“-,_. . . ,.-~-,}, .~”; /. .. .}
    . . .. . .((. . .*~_. . . .”=-._. . .“;,,./`. . /” . . . ./. .. ../
    . . . .. . .\`~,. . ..“~.,. . . . . . . . . ..`. . .}. . . . . . ../
    . . . . . .(. ..`=-,,. . . .`. . . . . . . . . . . ..(. . . ;_,,-”
    . . . . . ../.`~,. . ..`-.. . . . . . . . . . . . . . ..\. . /\
    . . . . . . \`~.*-,. . . . . . . . . . . . . . . . . ..|,./.....\,__
    ,,_. . . . . }.>-._\. . . . . . . . . . . . . . . . . .|. . . . . . ..`=~-,
    . .. `=~-,_\_. . . `\,. . . . . . . . . . . . . . . . .\
    . . . . . . . . . .`=~-,,.\,. . . . . . . . . . . . . . . .\
    . . . . . . . . . . . . . . . . `:,, . . . . . . . . . . . . . `\. . . . . . ..__
    . . . . . . . . . . . . . . . . . . .`=-,. . . . . . . . . .,%`>--==``
    . . . . . . . . . . . . . . . . . . . . _\. . . . . ._,-%. . . ..`

    Did not know that set bj_wantDestroyGroup = true works before conditions.
     
  17. TDA

    TDA

    Joined:
    Oct 2, 2010
    Messages:
    73
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    Ok... I liked the tutorial and it was helpful, but there is one thing I belive that you compleetly left out

    I was lead to belive that when you Have a Campaign, u use Hashtables to save the information about your units

    and if I was to try to make a Campaign using hashtables after reading your Tutorial, I would still be shooting in the dark

    Please make a section about Using Hashtables in Campaigns
    Because some people might be reading this tutorial in order to make there campaign work properly.

    I would also want to know where exactly the Handle information is saved, because i still don't understand how hashtables don't collapse on them selfs when the same trigger is run twice at the same time

    Example:
    • Example Trigger
    • Events:
    • Unit - starts the effect of an abillity
    • Conditions:
    • Ability being cast equal to [Gauntlet of Ilusions]
    • Actions:
    • Set [Example Unit Variable] to [Triggering unit]
    • Hashtable: Save handle of [Example Unit Variable] as 1 of 1 in [Example Hashtable]
    • Wait: wait 8 Seconds
    • Set [Example Unit Variable] = to [Load 1 0f 1 in Example Hashtable]


    When a unit casts the ability this trigger runs, and then if another unit casts the same ability in the 8 second long gap, then the original 1 of 1 handle in Example Hashtable will be changed to the triggering unit of the second cast
    so 8 seconds later, both triggers will set example unit variable to the triggering unit of the second cast, instead of the triggering units of there own respective casts

    How do hashtables evoid that problem?

    Tank you for helping me understand hashtables
     
    Last edited: Jul 3, 2011
  18. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    TDA, I don't believe that hashtables are used in campaigns for what you want. To save/load your hero and items between campaigns I believe that requires game caches. I'd suggest looking up a tutorial on those because I am not knowledgeable in game caches.

    As far as your question regarding hashtable overwriting, hashtables avoid this by saving the value to another thing. If you click on the little tab when saving hashtables that says (get handle ID), it will say key ________. The ________ part contains tons and tons of things you can save the value to. When you load a hashtable value, you are loading the data saved to the handle. In your example trigger the value would be overwritten, because you don't use handles and you have a wait (you shouldn't use waits in spells unless you use local variables). Using two integers in hashtables is fine, but it doesn't utilize the power of handles.

    Handles make hashtables MUI and powerful. If you look at my example spells, you will see that values are saved as an integer (any whole number, WE doesn't use negatives tho), and then key (picked unit), or (triggering unit). I am saving the value TO the unit. When I need the value again, I have to load by identifying the unit that has the correct value. I think I properly explained this in the tutorial, but if it wasn't clear I shall try to elaborate.
     
  19. TDA

    TDA

    Joined:
    Oct 2, 2010
    Messages:
    73
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    I think your might be right about the Game Cache, because after all, I had no knolage in eather of the two b4 reading this tutorial and it would have been easy for me to get the two confused.

    Anyways what are Local Variables? (The name would sugest that they are variables saved to the trigger they run in and are not to be sheared with other triggers) However I have never heard of them. Just tought that such a thing would be very helpful in making Mui spells

    Can you point me to a tutorial in local Variables pls? cause if I'm right, they are just the thing I need

    I am curently creating the Biggest and Baddest of all spells I have ever created, and I find that the ordinary [Triggering Unit] [Target of ability being cast] etc. tags are not enough, because the spell cast stops while the trigger keeps on running, and all of the tags get destroyed.
    I tought I could use Hashtables to save them before they are lost, and then bring them back when I need them. what do you sugest I do?
     
  20. Jazztastic

    Jazztastic

    Joined:
    Apr 4, 2011
    Messages:
    895
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    I do suggest using hashtables for people who use GUI. While local variables are nice because they don't require a special method (hashtables or recycling) to make them MUI, they are hard to use because every function you want to use a variable in must be in custom script.

    I'm sure that if you post your triggers in the help section someone can help you make your awesome spell MUI. If it's a specific hashtable question, I can help you there.