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

[TRIGGER] Dash Spell Bug?

Status
Not open for further replies.
Level 4
Joined
Jul 17, 2011
Messages
55
My problem here is that I wanted to make a dash spell. The dash is supposed to damage units when passed, ONLY ONCE! using group arrays. I searched for an alternative, which is to use local unit groups and hashtables together, which worked. my spell now damages once! for each unit, BUT ONLY AFTER IT'S BEEN CASTED ONCE! meaning, at first cast, it damages units multiple times periodically. the next time the spell is casted, it won't bug anymore. WHAT'S WRONG???:vw_wtf:

BY THE WAY, USING BRIBE's indexing system. works like a charm! :thumbs_up:

On Spell Cast

  • Cast Spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Bladespin
    • Actions
      • Custom script: local group dg = CreateGroup()
      • Set TempUnit = (Triggering unit)
      • Hashtable - Save Handle Of(Last created unit group) as 0 of ID in Hashtable
      • Set ID = (Custom value of (Triggering unit))
      • Set Duration_Index[ID] = 4.00
      • Set Angle_Index[ID] = (Facing of (Triggering unit))
      • Set Radius_Index[ID] = 250.00
      • Set Damage_Index[ID] = 50.00
      • Set Angle_Index[ID] = (Facing of (Triggering unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Group is empty) Equal to True
        • Then - Actions
          • Trigger - Turn on Loop Spell <gen>
        • Else - Actions
      • Unit Group - Add TempUnit to Group
[/SPOILER]

  • Loop Spell
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Group and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Picked unit)
          • Set ID = (Custom value of TempUnit)
          • Set TempLoc = (Position of TempUnit)
          • Set TempAngle = Angle_Index[ID]
          • Set TempOffset = (TempLoc offset by 22.00 towards TempAngle degrees)
          • Set TempRadius = Radius_Index[ID]
          • Set TempDamage = Damage_Index[ID]
          • Set Group_Damaged = (Load 0 of ID in Hashtable)
          • Game - Display to (All players) the text: (String((Number of units in Group_Damaged)))
          • Unit - Move TempUnit instantly to TempOffset
          • Animation - Play TempUnit's attack stand walk spin animation
          • Custom script: call RemoveLocation(udg_TempLoc)
          • Custom script: set udg_TempGroup = CreateGroup()
          • Set TempGroup = (Units within TempRadius of TempOffset matching ((((Matching unit) belongs to an enemy of (Owner of TempUnit)) Equal to True) and ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is dead) Equal to False) and (((Matching unit) is in Gr
          • Unit Group - Pick every unit in TempGroup and do (Actions)
            • Loop - Actions
              • Unit Group - Add (Picked unit) to Group_Damaged
              • Unit - Cause TempUnit to damage (Picked unit), dealing TempDamage damage of attack type Hero and damage type Normal
          • Hashtable - Save Handle OfGroup_Damaged as 0 of ID in Hashtable
          • Custom script: call DestroyGroup (udg_TempGroup)
          • Custom script: call RemoveLocation(udg_TempLoc)
          • Custom script: call RemoveLocation(udg_TempOffset)
          • Set Duration_Index[ID] = (Duration_Index[ID] - 0.03)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Duration_Index[ID] Less than or equal to 0.00
            • Then - Actions
              • Unit Group - Remove TempUnit from Group
              • Animation - Play TempUnit's stand animation
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Group is empty) Equal to True
                • Then - Actions
                  • Trigger - Turn off Loop Spell <gen>
                • Else - Actions
            • Else - ActionS
 
Last edited by a moderator:
Level 14
Joined
Apr 20, 2009
Messages
1,543
Am I missing something here or is ID not set the first time?
You save the handle in a hashtable, but ID is not defined before that the first time, and since Loop Spell is turned on after the first cast it should work the second time.

Change the position of:
  • Hashtable - Save Handle Of(Last created unit group) as 0 of ID in Hashtable
  • Set ID = (Custom value of (Triggering unit))
to:
  • Set ID = (Custom value of (Triggering unit))
  • Hashtable - Save Handle Of(Last created unit group) as 0 of ID in Hashtable
See if that works.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
You need to null this at the end of the trigger:
  • Custom script: local group dg = CreateGroup()
  • Custom script: set dg = null
Set this
  • Set ID = (Custom value of (Triggering unit))
before this
  • Hashtable - Save Handle Of(Last created unit group) as 0 of ID in Hashtable
Delete this:
  • Custom script: set udg_TempGroup = CreateGroup()
Delete this:
  • Hashtable - Save Handle OfGroup_Damaged as 0 of ID in Hashtable
Also:
  • If - Conditions
    • Duration_Index[ID] Less than or equal to 0.00
    • Then - Actions
      • Unit Group - Remove TempUnit from Group
      • Animation - Play TempUnit's stand animation
      • *destroy the stored group here*
      • *flush child hashtable*
    • Else - ActionS
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
OMG IT WORKED! thank you Hashjie and Maker!

but please do tell why it worked? except the setting of the ID before the Hashtable :D

I've already explained that in my post.

When you saved the handle in the hashtable, ID was undefined because it was not set before saving it in the hashtable. The second time it did work because ID was set.

On top of that maker pointed out some optimizations of your trigger.
Also, itterating through a unit group every 0.03 seconds is quite slow, it does work but it's not significantly fast.
You might want to use a work-around with arrays. But it's not nessecary...
 
Level 4
Joined
Jul 17, 2011
Messages
55
I've already explained that in my post.

When you saved the handle in the hashtable, ID was undefined because it was not set before saving it in the hashtable. The second time it did work because ID was set.

On top of that maker pointed out some optimizations of your trigger.
Also, itterating through a unit group every 0.03 seconds is quite slow, it does work but it's not significantly fast.
You might want to use a work-around with arrays. But it's not nessecary...

no no no, as i said above, i know why i should set the ID before the Hashtable.. other than what Maker told me to remove/change, i don't know what it's supposed to do.. like flushing of child hashtables? why not parent?

or removing this:
  • Hashtable - Save Handle OfGroup_Damaged as 0 of ID in Hashtable
etc.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
  • Custom script: set dg = null
A local variable needs to be nulled, else it would still have the group value inside of it even if it's not being used anymore.
Which means it takes up a small bit of memory. To improve efficiency and performance it's better to empty (null) a local variable.
Not every local variable needs to be nulled though. Only handles should be nulled. Integers, reals, booleans etc don't have to be.

  • Custom script: set udg_TempGroup = CreateGroup()
You don't have to create a group in Jass if it's a global GUI variable, since global GUI variables create the group when defined in the variable editor.

  • Hashtable - Save Handle OfGroup_Damaged as 0 of ID in Hashtable
Am not sure about this one :S

  • If - Conditions
  • Duration_Index[ID] Less than or equal to 0.00
  • Then - Actions
  • Unit Group - Remove TempUnit from Group
  • Animation - Play TempUnit's stand animation
  • *destroy the stored group here*
  • *flush child hashtable*
  • Else - ActionS
Destroy the group because else the group would have the same units added to the group over and over again, which increases the time for the loop: pick every unit in Group.

Destroying it and recreating would be better.

Flush the child hashtable because it takes up memory.


Please correct me if I'm wrong here :)
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Last created unit group does not refer to CreateGroup(), it creates a copy of a global group that gets cleared/filled when the GUI CreateUnit-actions are run.

JASS:
function GetLastCreatedGroupEnum takes nothing returns nothing
    call GroupAddUnit(bj_groupLastCreatedDest, GetEnumUnit())
endfunction

function GetLastCreatedGroup takes nothing returns group
    set bj_groupLastCreatedDest = CreateGroup()
    call ForGroup(bj_lastCreatedGroup, function GetLastCreatedGroupEnum)
    return bj_groupLastCreatedDest
endfunction

Result: The spell won't affect the last created units when the spell started because they are already in.
 
Status
Not open for further replies.
Top