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

[Trigger] Excluding units from array index & other issues

Status
Not open for further replies.
Level 24
Joined
Feb 9, 2009
Messages
1,783
I want to replicate Teeth from Diablo 2
however as it stands you can pretty reliably shotgun units with 90% of missiles for ludicrous damage,
I like it but someone who wants stats from diablo 2 won't.
For those who are unaware, teeth fires a fan of projectiles towards a target location, the closer your cast point is the larger the spread of missiles will be, and the opposite will converge them onto a point, only one missile per cast can effect a unit.

I need to be able to exclude a unit from being hit after one projectile but not so immune that future waves or allied waves get caught in this exclusion, How would I achieve this?

From what I understand the options are:
- Unit Group
- Hashtable

Buff tagging is straight out of the question as ignoring units with a buff will simply result in invincibility frames where an ally could have their cast nullified by converging on their ally's earlier cast.

Secondly, I'm pretty sure there are leaks but I can't seem to find them, casting for a decent amount of time doesn't lag but upon exiting it will take some time depending on how many casts you've done.
I'd love some second set of eyes if i'm doing something wrong.


Triggers:
  • TeNe Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set TeNe_Ability[1] = Teeth
      • Set TeNe_Stats_Speed = 20.00
      • Set TeNe_Stats_Spread = 270.00
      • Set TeNe_Stats_Count = 5
      • Set TeNe_Stats_Count_PerLVL = 5
      • Set TeNe_Stats_DMG_Ratio[1] = 0.15
      • Set TeNe_Stats_DMG_Ratio_PerLVL[1] = 0.10
      • Set TeNe_Stats_Crit_Percentage[1] = 2.00
      • Set TeNe_Stats_Crit_Chance[1] = 0.01
      • Set TeNe_EffectPath[1] = Abilities\Weapons\SkeletalMageMissile\SkeletalMageMissile.mdl
      • Set TeNe_EffectPath[2] = Abilities\Weapons\FarseerMissile\FarseerMissile.mdl
  • TeNe Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to TeNe_Ability[1]
    • Actions
      • -------- ============================= --------
      • -------- Store the necessary values --------
      • -------- ============================= --------
      • For each (Integer TeNe_Cast_LOOP) from 1 to (TeNe_Stats_Count + (TeNe_Stats_Count_PerLVL x (Level of TeNe_Ability[1] for (Triggering unit)))), do (Actions)
        • Loop - Actions
          • Set TeNe_Index = (TeNe_Index + 1)
          • Set TeNe_Caster[TeNe_Index] = (Triggering unit)
          • Set TeNe_Point[1] = (Position of TeNe_Caster[TeNe_Index])
          • Set TeNe_Point[2] = (Target point of ability being cast)
          • Set TeNe_Point[3] = (TeNe_Point[1] offset by 25.00 towards (Angle from TeNe_Point[2] to TeNe_Point[1]) degrees)
          • Set TeNe_Point[4] = (TeNe_Point[3] offset by ((TeNe_Stats_Spread x 0.50) - ((TeNe_Stats_Spread / (Real(((TeNe_Stats_Count + (TeNe_Stats_Count_PerLVL x (Level of TeNe_Ability[1] for TeNe_Caster[TeNe_Index]))) + 1)))) x (Real(TeNe_Cast_LOOP)))) towards ((Angle from TeNe_Point[2] to)
          • -------- ============================= --------
          • -------- Create the dummy --------
          • -------- ============================= --------
          • Special Effect - Create a special effect at TeNe_Point[4] using TeNe_EffectPath[1]
          • Special Effect - Set Yaw of (Last created special effect) to: (Radians((Angle from TeNe_Point[3] to TeNe_Point[2])))
          • Set TeNe_Effect[TeNe_Index] = (Last created special effect)
          • Set TeNe_Height[TeNe_Index] = (Current flying height of TeNe_Caster[TeNe_Index])
          • Set TeNe_Facing[TeNe_Index] = (Angle from TeNe_Point[4] to TeNe_Point[2])
          • Set TeNe_Distance[TeNe_Index] = 1500.00
          • -------- ============================= --------
          • -------- Move on to the looping part --------
          • -------- ============================= --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TeNe_Index Equal to 1
            • Then - Actions
              • Trigger - Turn on Tene Periodic <gen>
            • Else - Actions
          • -------- ============================= --------
          • -------- Clean up the leaks --------
          • -------- ============================= --------
          • Custom script: call RemoveLocation(udg_TeNe_Point[1])
          • Custom script: call RemoveLocation(udg_TeNe_Point[2])
          • Custom script: call RemoveLocation(udg_TeNe_Point[3])
  • Tene Periodic
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer TeNe_Loop) from 1 to TeNe_Index, do (Actions)
        • Loop - Actions
          • -------- ============================= --------
          • -------- Store the necessary values --------
          • -------- ============================= --------
          • Set TeNe_Point[4] = (Point((Position - X of TeNe_Effect[TeNe_Loop]), (Position - Y of TeNe_Effect[TeNe_Loop])))
          • -------- ============================= --------
          • -------- Move the missile dummy --------
          • -------- ============================= --------
          • Set TeNe_Point[5] = (TeNe_Point[4] offset by TeNe_Stats_Speed towards TeNe_Facing[TeNe_Loop] degrees)
          • Set TeNe_Facing[TeNe_Loop] = (Angle from TeNe_Point[4] to TeNe_Point[5])
          • Custom script: set udg_TeNe_C_Height = GetLocationZ(udg_TeNe_Point[4])
          • Special Effect - Set Position of TeNe_Effect[TeNe_Loop] to x: (X of TeNe_Point[5]), y: (Y of TeNe_Point[5]), z: (TeNe_C_Height + 65.00)
          • Special Effect - Set Yaw of TeNe_Effect[TeNe_Loop] to: (Radians(TeNe_Facing[TeNe_Loop]))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • TeNe_Distance[TeNe_Loop] Less than or equal to 0.00
                  • (Terrain pathing at TeNe_Point[4] of type Walkability is off) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                • Then - Actions
                  • -------- ============================= --------
                  • Special Effect - Destroy TeNe_Effect[TeNe_Loop]
                  • Set TeNe_Facing[TeNe_Loop] = 0.00
                  • -------- ============================= --------
                  • Set TeNe_Caster[TeNe_Loop] = TeNe_Caster[TeNe_Index]
                  • Set TeNe_Effect[TeNe_Loop] = TeNe_Effect[TeNe_Index]
                  • Set TeNe_Height[TeNe_Loop] = TeNe_Height[TeNe_Index]
                  • Set TeNe_Facing[TeNe_Loop] = TeNe_Facing[TeNe_Index]
                  • Set TeNe_Distance[TeNe_Loop] = TeNe_Distance[TeNe_Index]
                  • Set TeNe_Distance[TeNe_Loop] = TeNe_Distance[TeNe_Index]
                  • Set TeNe_Loop = (TeNe_Loop - 1)
                  • Set TeNe_Index = (TeNe_Index - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TeNe_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
              • Set TeNe_Distance[TeNe_Loop] = (TeNe_Distance[TeNe_Loop] - TeNe_Stats_Speed)
              • -------- ============================= --------
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 50.00 of TeNe_Point[4]) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Or - Any (Conditions) are true
                        • Conditions
                          • ((Picked unit) is A structure) Equal to True
                          • ((Picked unit) is Magic Immune) Equal to True
                    • Then - Actions
                      • Set TeNe_Distance[TeNe_Loop] = 0.00
                    • Else - 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 TeNe_Caster[TeNe_Loop])) Equal to True
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                            • Then - Actions
                              • Set TeNe_Distance[TeNe_Loop] = 0.00
                              • Set TeNe_Point[6] = (Position of (Picked unit))
                              • -------- ============================= --------
                              • Set TeNe_Integer[1] = (Base Damage of TeNe_Caster[TeNe_Loop] for weapon index 0)
                              • Set TeNe_Integer[2] = (Dice Number of TeNe_Caster[TeNe_Loop] for weapon index 0)
                              • Set TeNe_Integer[3] = (Dice Sides of TeNe_Caster[TeNe_Loop] for weapon index 0)
                              • Set TeNe_Integer[4] = (Random integer number between (TeNe_Integer[1] + TeNe_Integer[2]) and (TeNe_Integer[1] + (TeNe_Integer[2] x TeNe_Integer[3])))
                              • Set TeNe_Real[1] = ((Real(TeNe_Integer[4])) x (TeNe_Stats_DMG_Ratio[1] + (TeNe_Stats_DMG_Ratio_PerLVL[1] x (Real((Level of TeNe_Ability[1] for TeNe_Caster[TeNe_Loop]))))))
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (Random real number between 0.01 and 1.00) Less than or equal to TeNe_Stats_Crit_Chance[1]
                                • Then - Actions
                                  • Set TeNe_Real[1] = (TeNe_Real[1] x TeNe_Stats_Crit_Percentage[1])
                                  • Special Effect - Create a special effect attached to the chest of (Picked unit) using TeNe_EffectPath[2]
                                  • Special Effect - Destroy (Last created special effect)
                                • Else - Actions
                              • Unit - Cause TeNe_Caster[TeNe_Loop] to damage (Picked unit), dealing TeNe_Real[1] damage of attack type Hero and damage type Normal
                              • -------- ============================= --------
                              • Custom script: call RemoveLocation(udg_TeNe_Point[6])
                            • Else - Actions
                        • Else - Actions
              • Destructible - Pick every destructible within 50.00 of TeNe_Point[4] and do (Actions)
                • Loop - Actions
                  • Set TeNe_Distance[TeNe_Loop] = 0.00
              • -------- ============================= --------
          • Custom script: call RemoveLocation(udg_TeNe_Point[4])
          • Custom script: call RemoveLocation(udg_TeNe_Point[5])

Lastly here's a video example
Video example:
 
Last edited:
Level 38
Joined
Feb 27, 2007
Messages
4,928
You're leaking point [4] in the second trigger. Also further down in the third trigger you have an If-block with no conditions. Because GUI does a convoluted 'if not conditions then false else true' for evaluating conditions the then actions are still always performed, but I don't understand why the if block is there at all.

The solution is, as you stated yourself, to store and use a group. You will also need two missile counter integer arrays (TeethCount and TeethCountPointer below) so the triggers know when a 'cast' is done (all missiles of a cast reach their endpoint or impact a unit or impact unwalkable terrain) so the proper group can be cleaned. Why two? because integers aren't pointers so all the teeth can't 'share' an integer the same way they can share the group; one array will act as a pointer to the other array. I'd rather not type it into your above trigger since it would be hard to see what I added where, and I know you're competent so here are the steps:

  • On cast, compute the total number of teeth for that cast and store it in a temp variable: TeNe_TotalTeeth = (TeNe_Stats_Count + (TeNe_Stats_Count_PerLVL x (Level of TeNe_Ability[1] for (Triggering unit)))). You can then use this variable as your upper loop bounds.

  • On cast, store the first used value of TeNe_Index (which will be the current value of it + 1 so it's 1 on the first cast) in another temp variable, call it TeNe_FirstIndex. Assign TeNe_TeethCount[TeNe_FirstIndex] = TeNe_TotalTeeth.

  • On cast, create 1 unit group and store it in a temp variable: set udg_TempGroup = CreateGroup(). This group will not need to be cleaned at the end of the trigger.

  • On tooth creation, assign TeNe_TeethGroup[TeNe_Index] = TempGroup. This means each tooth has its own indexed reference to the same group (not different groups for each tooth). Each tooth can now check if units are in that specific group when searching for damage targets.

  • On tooth creation, assign TeNe_TeethCountPointer[TeNe_Index] = TeNe_FirstIndex. Now this tooth knows which variable to decrease when it 'ends' its trajectory (for whatever reason).

  • When checking for valid targets, include a (Picked Unit is in TeNe_TeethGroup[TeNe_Index]) equal to false condition. When a valid target is found and damaged, make sure to add that unit to this group as well.

  • On tooth 'end' (for whatever reason), decrease TeNe_TeethCount[TeNe_TeethCountPointer[TeNe_Index]] by 1. If this count is now 0, then the cast that that tooth belonged to has 'finished' because all its teeth have ended their trajectories. At this time you can destroy TeNe_TeethGroup[TeNe_Index]. This only needs to be done once. The integer array data can be left as is since it will be overwritten on the next cast.

  • Make sure you also move the TeethCountPointer and TeethGroup information over when you juggle the array indices when a tooth has 'ended', just like you do the other variables. TeethCount itself does not need to be moved.
 
Level 24
Joined
Feb 9, 2009
Messages
1,783
Wah, thank you so much for your help Pyrogasm!
Do you mind If I pester you later for follow up?

ETA:
I think I followed your directions correctly!
I mean it works in the sense that it only afflicts on tooth per target, which is flipping amazing, but to be safe can you give it one last look to make sure I've got it correctly?

Additionally, i'm not sure how to go about destroying that unit group once, how would you approach it?

Here's the updated triggers
  • TeNe Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set TeNe_Ability[1] = Teeth
      • Set TeNe_Stats_Speed = 20.00
      • Set TeNe_Stats_Spread = 270.00
      • Set TeNe_Stats_Distance[1] = 1500.00
      • Set TeNe_Stats_Count = 5
      • Set TeNe_Stats_Count_PerLVL = 5
      • Set TeNe_Stats_DMG_Ratio[1] = 1.00
      • Set TeNe_Stats_DMG_Ratio_PerLVL[1] = 1.00
      • Set TeNe_Stats_Crit_Percentage[1] = 2.00
      • Set TeNe_Stats_Crit_Chance[1] = 0.05
      • Set TeNe_EffectPath[1] = Abilities\Weapons\SkeletalMageMissile\SkeletalMageMissile.mdl
      • Set TeNe_EffectPath[2] = Abilities\Weapons\FarseerMissile\FarseerMissile.mdl
  • TeNe Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to TeNe_Ability[1]
    • Actions
      • -------- ============================= --------
      • Custom script: set udg_TempGroup = CreateGroup()
      • Set TeNe_Total_Teeth = (TeNe_Stats_Count + (TeNe_Stats_Count_PerLVL x (Level of TeNe_Ability[1] for (Triggering unit))))
      • For each (Integer TeNe_Cast_LOOP) from 1 to TeNe_Total_Teeth, do (Actions)
        • Loop - Actions
          • Set TeNe_Index = (TeNe_Index + 1)
          • Set TeNe_FirstIndex = (TeNe_Index + 1)
          • Set TeNe_Count[TeNe_FirstIndex] = TeNe_Total_Teeth
          • Set TeNe_Caster[TeNe_Index] = (Triggering unit)
          • Set TeNe_Point[1] = (Position of TeNe_Caster[TeNe_Index])
          • Set TeNe_Point[2] = (Target point of ability being cast)
          • Set TeNe_Point[3] = (TeNe_Point[1] offset by 25.00 towards (Angle from TeNe_Point[2] to TeNe_Point[1]) degrees)
          • Set TeNe_Point[4] = (TeNe_Point[3] offset by ((TeNe_Stats_Spread x 0.50) - ((TeNe_Stats_Spread / (Real((TeNe_Total_Teeth + 1)))) x (Real(TeNe_Cast_LOOP)))) towards ((Angle from TeNe_Point[2] to TeNe_Point[1]) - 90.00) degrees)
          • -------- ============================= --------
          • -------- Create the dummy --------
          • -------- ============================= --------
          • Special Effect - Create a special effect at TeNe_Point[4] using TeNe_EffectPath[1]
          • Special Effect - Set Yaw of (Last created special effect) to: (Radians((Angle from TeNe_Point[3] to TeNe_Point[2])))
          • Set TeNe_TeethGroup[TeNe_Index] = TempGroup
          • Set TeNe_TeethCountPointer[TeNe_Index] = TeNe_FirstIndex
          • Set TeNe_Effect[TeNe_Index] = (Last created special effect)
          • Set TeNe_Height[TeNe_Index] = (Current flying height of TeNe_Caster[TeNe_Index])
          • Set TeNe_Facing[TeNe_Index] = (Angle from TeNe_Point[4] to TeNe_Point[2])
          • Set TeNe_Distance[TeNe_Index] = TeNe_Stats_Distance[1]
          • -------- ============================= --------
          • -------- Move on to the looping part --------
          • -------- ============================= --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TeNe_Index Equal to 1
            • Then - Actions
              • Trigger - Turn on Tene Periodic <gen>
            • Else - Actions
          • -------- ============================= --------
          • -------- Clean up the leaks --------
          • -------- ============================= --------
          • Custom script: call RemoveLocation(udg_TeNe_Point[1])
          • Custom script: call RemoveLocation(udg_TeNe_Point[2])
          • Custom script: call RemoveLocation(udg_TeNe_Point[3])
          • Custom script: call RemoveLocation(udg_TeNe_Point[4])
  • Tene Periodic
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer TeNe_Loop) from 1 to TeNe_Index, do (Actions)
        • Loop - Actions
          • -------- ============================= --------
          • -------- Store the necessary values --------
          • -------- ============================= --------
          • Set TeNe_Point[4] = (Point((Position - X of TeNe_Effect[TeNe_Loop]), (Position - Y of TeNe_Effect[TeNe_Loop])))
          • -------- ============================= --------
          • -------- Move the missile dummy --------
          • -------- ============================= --------
          • Set TeNe_Point[5] = (TeNe_Point[4] offset by TeNe_Stats_Speed towards TeNe_Facing[TeNe_Loop] degrees)
          • Set TeNe_Facing[TeNe_Loop] = (Angle from TeNe_Point[4] to TeNe_Point[5])
          • Custom script: set udg_TeNe_C_Height = GetLocationZ(udg_TeNe_Point[5])
          • Special Effect - Set Position of TeNe_Effect[TeNe_Loop] to x: (X of TeNe_Point[5]), y: (Y of TeNe_Point[5]), z: (TeNe_C_Height + 65.00)
          • Special Effect - Set Yaw of TeNe_Effect[TeNe_Loop] to: (Radians(TeNe_Facing[TeNe_Loop]))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • TeNe_Distance[TeNe_Loop] Less than or equal to 0.00
                  • (Terrain pathing at TeNe_Point[4] of type Walkability is off) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                • Then - Actions
                  • -------- ============================= --------
                  • Special Effect - Destroy TeNe_Effect[TeNe_Loop]
                  • Set TeNe_Facing[TeNe_Loop] = 0.00
                  • Set TeNe_Count[TeNe_TeethCountPointer[TeNe_Loop]] = (TeNe_Count[TeNe_TeethCountPointer[TeNe_Loop]] - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TeNe_Count[TeNe_TeethCountPointer[TeNe_Loop]] Equal to 0
                    • Then - Actions
                      • Custom script: call DestroyGroup(udg_TeNe_TeethGroup[udg_TeNe_Loop])
                    • Else - Actions
                  • -------- ============================= --------
                  • Set TeNe_Caster[TeNe_Loop] = TeNe_Caster[TeNe_Index]
                  • Set TeNe_Effect[TeNe_Loop] = TeNe_Effect[TeNe_Index]
                  • Set TeNe_Height[TeNe_Loop] = TeNe_Height[TeNe_Index]
                  • Set TeNe_Facing[TeNe_Loop] = TeNe_Facing[TeNe_Index]
                  • Set TeNe_Distance[TeNe_Loop] = TeNe_Distance[TeNe_Index]
                  • Set TeNe_TeethGroup[TeNe_Loop] = TeNe_TeethGroup[TeNe_Index]
                  • Set TeNe_TeethCountPointer[TeNe_Loop] = TeNe_Index
                  • Set TeNe_Loop = (TeNe_Loop - 1)
                  • Set TeNe_Index = (TeNe_Index - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TeNe_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
              • Set TeNe_Distance[TeNe_Loop] = (TeNe_Distance[TeNe_Loop] - TeNe_Stats_Speed)
              • -------- ============================= --------
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 50.00 of TeNe_Point[4]) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Or - Any (Conditions) are true
                        • Conditions
                          • ((Picked unit) is A structure) Equal to True
                          • ((Picked unit) is Magic Immune) Equal to True
                    • Then - Actions
                      • Set TeNe_Distance[TeNe_Loop] = 0.00
                    • Else - 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 TeNe_Caster[TeNe_Loop])) Equal to True
                          • ((Picked unit) is in TeNe_TeethGroup[TeNe_Loop]) Equal to False
                        • Then - Actions
                          • Set TeNe_Point[6] = (Position of (Picked unit))
                          • -------- ============================= --------
                          • Set TeNe_Integer[1] = (Base Damage of TeNe_Caster[TeNe_Loop] for weapon index 0)
                          • Set TeNe_Integer[2] = (Dice Number of TeNe_Caster[TeNe_Loop] for weapon index 0)
                          • Set TeNe_Integer[3] = (Dice Sides of TeNe_Caster[TeNe_Loop] for weapon index 0)
                          • Set TeNe_Integer[4] = (Random integer number between (TeNe_Integer[1] + TeNe_Integer[2]) and (TeNe_Integer[1] + (TeNe_Integer[2] x TeNe_Integer[3])))
                          • Set TeNe_Real[1] = ((Real(TeNe_Integer[4])) x (TeNe_Stats_DMG_Ratio[1] + (TeNe_Stats_DMG_Ratio_PerLVL[1] x (Real((Level of TeNe_Ability[1] for TeNe_Caster[TeNe_Loop]))))))
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (Random real number between 0.00 and 1.00) Less than or equal to TeNe_Stats_Crit_Chance[1]
                            • Then - Actions
                              • Set TeNe_Real[1] = (TeNe_Real[1] x TeNe_Stats_Crit_Percentage[1])
                              • Special Effect - Create a special effect at TeNe_Point[5] using TeNe_EffectPath[2]
                              • Special Effect - Set Position of (Last created special effect) to x: (X of TeNe_Point[5]), y: (Y of TeNe_Point[5]), z: (TeNe_C_Height + 65.00)
                              • Special Effect - Set Yaw of TeNe_Effect[TeNe_Loop] to: (Radians(TeNe_Facing[TeNe_Loop]))
                              • Special Effect - Destroy (Last created special effect)
                            • Else - Actions
                          • Unit - Cause TeNe_Caster[TeNe_Loop] to damage (Picked unit), dealing TeNe_Real[1] damage of attack type Hero and damage type Normal
                          • Unit Group - Add (Picked unit) to TeNe_TeethGroup[TeNe_Loop]
                          • -------- ============================= --------
                          • Set TeNe_Distance[TeNe_Loop] = 0.00
                          • Custom script: call RemoveLocation(udg_TeNe_Point[6])
                        • Else - Actions
              • Destructible - Pick every destructible within 50.00 of TeNe_Point[4] and do (Actions)
                • Loop - Actions
                  • Set TeNe_Distance[TeNe_Loop] = 0.00
              • -------- ============================= --------
          • Custom script: call RemoveLocation(udg_TeNe_Point[4])
          • Custom script: call RemoveLocation(udg_TeNe_Point[5])
 
Last edited:
Level 24
Joined
Feb 9, 2009
Messages
1,783
Excellent!
If you think it's ship shape enough, I'll go ahead and clean it up further with some config options and make it spell section approved.

I really appreciate your help Pyrogasm;
I kinda gave up the first time I attempted to make this.
 
Level 8
Joined
May 21, 2019
Messages
435
@Pyrogasm Is this solution MUI? Will it work if the same unit casts Teeth a second time before the first misiles are gone? I may be reading it wrong (only gave it a quick glance) but it kinda seems like the projectiles are being tracked in a global variable by indexes. Wouldn't a second teeth cast overwrite those indexes?

Also, serious probs to both of you, this is some high level shit.
 
Level 38
Joined
Feb 27, 2007
Messages
4,928
Yes. The indices are dynamically allocated on each cast. (Visualize: Dynamic Indexing)

Probably not a huge issue but if you don't also set TeNe_TeethGroup[TeNe_Index] = No Group (GUI's word for null) whenever any tooth ends, you can end up 'leaking' the handle id until the variable is overwritten upon a subsequent cast. You don't just need to do this when the group is destroyed, you need to do it for each tooth because each tooth has its own reference to the group (also has to happen sequentially after the group destroy line so you still properly destroy the group when the time comes). Really you are keeping that handle id in use if you don't flush it from your arrays. That they will be overwritten sort of solves this for you, but if you (for example) cast the spell a bunch of times simultaneouslyn and then never cast it that many times simultaneously again, the handle ids will be permanently allocated since the variables (in that case) would not be overwritten.
 
Level 8
Joined
May 21, 2019
Messages
435
Yes. The indices are dynamically allocated on each cast. (Visualize: Dynamic Indexing)

Probably not a huge issue but if you don't also set TeNe_TeethGroup[TeNe_Index] = No Group (GUI's word for null) whenever any tooth ends, you can end up 'leaking' the handle id until the variable is overwritten upon a subsequent cast. You don't just need to do this when the group is destroyed, you need to do it for each tooth because each tooth has its own reference to the group (also has to happen sequentially after the group destroy line so you still properly destroy the group when the time comes). Really you are keeping that handle id in use if you don't flush it from your arrays. That they will be overwritten sort of solves this for you, but if you (for example) cast the spell a bunch of times simultaneouslyn and then never cast it that many times simultaneously again, the handle ids will be permanently allocated since the variables (in that case) would not be overwritten.
Thanks for that link, very insightful.
One thing I noticed straight away is that the arrays are set to 1 in length on that guide. Does this mean that assigning indexes in an array beyond its limit will simply cause it to expand to that length? If so, why even give people the option to define the length? IIRC it's not possible to assign values to an array in the variable editor.
 
Level 38
Joined
Feb 27, 2007
Messages
4,928
Arrays are populated from 0 to SIZE with DEFAULT_VALUE on map init. That's the only thing length does. You can use all indices regardless of declared size in the variable editor. The only instance in which it matters is in group & force (player group) arrays where you want to pre-generate a bunch of empty groups you can add things to later. If you try to use group[x] where x > size it will fail because there isn't a group there to use. You can still assign a group to that index and then use it as normal. Setting size absurdly high for group/force arrays is effectively a memory leak since they will likely never be cleaned (of course, unless you do).
 
Status
Not open for further replies.
Top