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

Linked Spark v1.02

Meatmuffin presents
Linked Spark

Tooltip

Links you and the target together with an electric chain. A spark travels through the chain, damaging the target once it reaches it and travels back to the caster. Each return to the caster increases it's speed and damage. The orb can be exploded if the caster walks close enough to the target. The chain breaks if the distance becomes greater than 2500.
Duration - 10/15/20 seconds
Primary damage - 30/40/50
Damage increment - 15/20/25
Primary speed - 350/400/450
Speed increment - 50/60/70
Cooldown - 15/12.5/10 seconds
Explosion AoE - 350/400/450

Triggers

Configuration:

  • Linked Spark Configuration
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Your ability --------
      • Set LS_Ability = Linked Spark
      • -------- Dummy model --------
      • Set LS_Dummy = Dummy (Vexorian/Infrane/Anitarf)
      • -------- Spark model --------
      • Set LS_SparkModel = Abilities\Weapons\FarseerMissile\FarseerMissile.mdl
      • -------- Orb model --------
      • Set LS_OrbModel = Abilities\Weapons\VengeanceMissile\VengeanceMissile.mdl
      • -------- Orb size (percentage) --------
      • Set LS_OrbSize[1] = 150.00
      • Set LS_OrbSize[2] = 175.00
      • Set LS_OrbSize[3] = 200.00
      • -------- Dummy player --------
      • Set LS_DummyPlayer = Neutral Extra
      • -------- Duration --------
      • Set LS_CDuration[1] = 10.00
      • Set LS_CDuration[2] = 15.00
      • Set LS_CDuration[3] = 20.00
      • -------- Primary damage --------
      • Set LS_PrimaryDamage[1] = 30.00
      • Set LS_PrimaryDamage[2] = 40.00
      • Set LS_PrimaryDamage[3] = 50.00
      • -------- Damage increment per destination --------
      • Set LS_DamageIncrement[1] = 15.00
      • Set LS_DamageIncrement[2] = 20.00
      • Set LS_DamageIncrement[3] = 25.00
      • -------- Damage special effect --------
      • Set LS_DamageSFX = Abilities\Weapons\Bolt\BoltImpact.mdl
      • -------- Primary speed (described in the first part of the arithmetic function) --------
      • Set LS_PrimarySpeed[1] = (350.00 x 0.03)
      • Set LS_PrimarySpeed[2] = (400.00 x 0.03)
      • Set LS_PrimarySpeed[3] = (450.00 x 0.03)
      • -------- Speed increment per destination (described in the first part of the arithmetic function) --------
      • Set LS_SpeedIncrement[1] = (50.00 x 0.03)
      • Set LS_SpeedIncrement[2] = (60.00 x 0.03)
      • Set LS_SpeedIncrement[3] = (70.00 x 0.03)
      • -------- Value increase special effect --------
      • Set LS_IncreaseSFX = Abilities\Spells\Items\AIim\AIimTarget.mdl
      • -------- Lightining color (1 = Red; 2 = Green; 3 = Blue) and transparency (4) --------
      • Set LS_LightningColor[1] = 1.00
      • Set LS_LightningColor[2] = 1.00
      • Set LS_LightningColor[3] = 1.00
      • Set LS_LightningColor[4] = 1.00
      • -------- Size increment per destination (percentage) --------
      • Set LS_SizeIncrement = 50.00
      • -------- Distance between the target and the orb which triggers the explosion. (Advised not to make it below 250 or it may bug) --------
      • Set LS_TriggerExplosion[1] = 300.00
      • Set LS_TriggerExplosion[2] = 400.00
      • Set LS_TriggerExplosion[3] = 500.00
      • -------- Explosion AoE --------
      • Set LS_AoE[1] = 350.00
      • Set LS_AoE[2] = 400.00
      • Set LS_AoE[3] = 450.00
      • -------- Explosion collected damage multiplier --------
      • Set LS_DMGMultiplier[1] = 2.00
      • Set LS_DMGMultiplier[2] = 2.00
      • Set LS_DMGMultiplier[3] = 2.00
      • -------- Damage and attack types --------
      • Set LS_DamageType = Normal
      • Set LS_AttackType = Spells
      • -------- Explosion damage and attack types --------
      • Set LS_EDamageType = Universal
      • Set LS_EAttackType = Chaos
      • -------- Distance needed to break the ability --------
      • Set LS_ChainBreak[1] = 2500.00
      • Set LS_ChainBreak[2] = 2500.00
      • Set LS_ChainBreak[3] = 2500.00
      • -------- Spell loop interval (0.03 and 0.04 are the most common, 0.02 in special cases) --------
      • Set LS_Interval = 0.03
      • -------- Can't touch this (hue) --------
      • Trigger - Add to Linked Spark Loop <gen> the event (Time - Every LS_Interval seconds of game time)


Initialization:

  • Linked Spark Initialization
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to LS_Ability
    • Actions
      • -------- Checking if there are no instances running. If not, turning on the loop. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • LS_MaxIndex Equal to 0
        • Then - Actions
          • Trigger - Turn on Linked Spark Loop <gen>
        • Else - Actions
      • Set LS_MaxIndex = (LS_MaxIndex + 1)
      • Set LS_Caster[LS_MaxIndex] = (Triggering unit)
      • Set LS_Target[LS_MaxIndex] = (Target unit of ability being cast)
      • -------- Getting the X/Y/Z coordinates of the caster and the target and the angle. --------
      • Custom script: set udg_LS_X = GetUnitX(udg_LS_Caster[udg_LS_MaxIndex])
      • Custom script: set udg_LS_Y = GetUnitY(udg_LS_Caster[udg_LS_MaxIndex])
      • Custom script: set udg_LS_Z = (GetUnitFlyHeight(udg_LS_Caster[udg_LS_TempIndex]) + 50.00)
      • Custom script: set udg_LS_X2 = GetUnitX(udg_LS_Target[udg_LS_MaxIndex])
      • Custom script: set udg_LS_Y2 = GetUnitY(udg_LS_Target[udg_LS_MaxIndex])
      • Custom script: set udg_LS_Z2 = (GetUnitFlyHeight(udg_LS_Target[udg_LS_TempIndex]) + 50.00)
      • Custom script: set udg_LS_Angle = Atan2((udg_LS_Y2 - udg_LS_Y), (udg_LS_X2 - udg_LS_X))
      • Set LS_Player[LS_MaxIndex] = (Triggering player)
      • Set LS_AbilityIndex[LS_MaxIndex] = (Level of LS_Ability for LS_Caster[LS_MaxIndex])
      • Set LS_Damage[LS_MaxIndex] = LS_PrimaryDamage[LS_AbilityIndex[LS_MaxIndex]]
      • Set LS_Speed[LS_MaxIndex] = LS_PrimarySpeed[LS_AbilityIndex[LS_MaxIndex]]
      • Set LS_Duration[LS_MaxIndex] = LS_CDuration[LS_AbilityIndex[LS_MaxIndex]]
      • Set LS_Size[LS_MaxIndex] = 100.00
      • Set LS_Boolean[LS_MaxIndex] = False
      • Set LS_TempPoint = (Position of LS_Caster[LS_MaxIndex])
      • Set LS_TempPoint2 = (Position of LS_Target[LS_MaxIndex])
      • Set LS_TempPoint3 = (LS_TempPoint offset by 150.00 towards LS_Angle degrees)
      • -------- Creating the spark dummy. --------
      • Unit - Create 1 LS_Dummy for LS_DummyPlayer at LS_TempPoint3 facing Default building facing degrees
      • Set LS_Spark[LS_MaxIndex] = (Last created unit)
      • Unit - Pause LS_Spark[LS_MaxIndex]
      • Special Effect - Create a special effect attached to the origin of LS_Spark[LS_MaxIndex] using LS_SparkModel
      • Set LS_SFX[LS_MaxIndex] = (Last created special effect)
      • Set LS_Distance[LS_MaxIndex] = (Distance between LS_TempPoint and LS_TempPoint2)
      • Set LS_TotalDistance[LS_MaxIndex] = (Distance between LS_TempPoint and LS_TempPoint2)
      • Set LS_DistanceTravelled[LS_MaxIndex] = 100.00
      • -------- Creating the orb dummy. --------
      • Custom script: call RemoveLocation(udg_LS_TempPoint3)
      • Set LS_TempPoint3 = (LS_TempPoint2 offset by LS_TriggerExplosion[LS_AbilityIndex[LS_MaxIndex]] towards LS_Angle degrees)
      • Unit - Create 1 Dummy (Vexorian/Infrane/Anitarf) for LS_DummyPlayer at LS_TempPoint3 facing Default building facing degrees
      • Set LS_Orb[LS_MaxIndex] = (Last created unit)
      • Unit - Pause LS_Orb[LS_MaxIndex]
      • Special Effect - Create a special effect attached to the origin of LS_Orb[LS_MaxIndex] using LS_OrbModel
      • Set LS_OrbSFX[LS_MaxIndex] = (Last created special effect)
      • Animation - Change LS_Orb[LS_MaxIndex]'s size to (LS_OrbSize[LS_AbilityIndex[LS_MaxIndex]]%, 0.00%, 0.00%) of its original size
      • -------- Creating the lightning effect. --------
      • Custom script: set udg_LS_Lightning[udg_LS_MaxIndex] = AddLightningEx("CHIM", false, udg_LS_X, udg_LS_Y, udg_LS_Z, udg_LS_X2, udg_LS_Y2, udg_LS_Z2)
      • Lightning - Change color of LS_Lightning[LS_MaxIndex] to (LS_LightningColor[1] LS_LightningColor[2] LS_LightningColor[3]) with LS_LightningColor[4] alpha
      • -------- Cleaning. --------
      • Custom script: call RemoveLocation(udg_LS_TempPoint)
      • Custom script: call RemoveLocation(udg_LS_TempPoint2)
      • Custom script: call RemoveLocation(udg_LS_TempPoint3)


Loop:

  • Linked Spark Loop
    • Events
    • Conditions
    • Actions
      • -------- Initializing the loop --------
      • For each (Integer LS_TempIndex) from 1 to LS_MaxIndex, do (Actions)
        • Loop - Actions
          • Set LS_Duration[LS_TempIndex] = (LS_Duration[LS_TempIndex] - LS_Interval)
          • -------- Checking if whether the duration has expired, the target has died, the caster has died or the chain distance has been exceeded. If yes, ends the ability instance. --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • LS_Duration[LS_TempIndex] Greater than 0.00
              • (LS_Target[LS_TempIndex] is alive) Equal to True
              • (LS_Caster[LS_TempIndex] is alive) Equal to True
              • LS_TotalDistance[LS_TempIndex] Less than LS_ChainBreak[LS_AbilityIndex[LS_TempIndex]]
            • Then - Actions
              • -------- Getting X/Y/Z of caster/target/spark and moving the lightning. --------
              • Custom script: set udg_LS_X = GetUnitX(udg_LS_Caster[udg_LS_TempIndex])
              • Custom script: set udg_LS_Y = GetUnitY(udg_LS_Caster[udg_LS_TempIndex])
              • Custom script: set udg_LS_Z = (GetUnitFlyHeight(udg_LS_Caster[udg_LS_TempIndex]) + 50.00)
              • Custom script: set udg_LS_X2 = GetUnitX(udg_LS_Target[udg_LS_TempIndex])
              • Custom script: set udg_LS_Y2 = GetUnitY(udg_LS_Target[udg_LS_TempIndex])
              • Custom script: set udg_LS_Z2 = (GetUnitFlyHeight(udg_LS_Target[udg_LS_TempIndex]) + 50.00)
              • Custom script: set udg_LS_X3 = GetUnitX(udg_LS_Spark[udg_LS_TempIndex])
              • Custom script: set udg_LS_Y3 = GetUnitY(udg_LS_Spark[udg_LS_TempIndex])
              • Custom script: call MoveLightningEx(udg_LS_Lightning[udg_LS_MaxIndex], false, udg_LS_X, udg_LS_Y, udg_LS_Z, udg_LS_X2, udg_LS_Y2, udg_LS_Z2)
              • -------- Calculating the current position of the spark in the lightning to make it move smoothly. --------
              • Custom script: set udg_LS_TotalDistance[udg_LS_TempIndex] = SquareRoot((udg_LS_Y2 - udg_LS_Y) * (udg_LS_Y2 - udg_LS_Y) + (udg_LS_X2 - udg_LS_X) * (udg_LS_X2 - udg_LS_X))
              • Custom script: set udg_LS_TempDistance = SquareRoot((udg_LS_Y - udg_LS_Y3) * (udg_LS_Y - udg_LS_Y3) + (udg_LS_X - udg_LS_X3) * (udg_LS_X - udg_LS_X3))
              • Set LS_Percentage = (LS_TempDistance / LS_TotalDistance[LS_TempIndex])
              • Set LS_DistanceTravelled[LS_TempIndex] = (LS_TotalDistance[LS_TempIndex] x LS_Percentage)
              • Set LS_DistanceTravelled[LS_TempIndex] = (LS_DistanceTravelled[LS_TempIndex] + LS_Speed[LS_TempIndex])
              • -------- Moving the spark dummy. --------
              • Custom script: set udg_LS_Angle = Atan2((udg_LS_Y2 - udg_LS_Y), (udg_LS_X2 - udg_LS_X))
              • Custom script: call SetUnitY(udg_LS_Spark[udg_LS_TempIndex], (udg_LS_Y + udg_LS_DistanceTravelled[udg_LS_TempIndex]*Sin(udg_LS_Angle)))
              • Custom script: call SetUnitX(udg_LS_Spark[udg_LS_TempIndex], (udg_LS_X + udg_LS_DistanceTravelled[udg_LS_TempIndex]*Cos(udg_LS_Angle)))
              • -------- Setting the height of the spark (to make it look like the spark is travelling through the chain). --------
              • Animation - Change LS_Spark[LS_TempIndex] flying height to ((LS_DistanceTravelled[LS_TempIndex] x LS_Z2) / LS_TotalDistance[LS_TempIndex]) at 0.00
              • -------- Damaging the target or increasing speed/damage values if the distance is reached. --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • LS_DistanceTravelled[LS_TempIndex] Less than or equal to 50.00
                      • LS_Boolean[LS_TempIndex] Equal to False
                  • Or - Any (Conditions) are true
                    • Conditions
                      • LS_DistanceTravelled[LS_TempIndex] Greater than or equal to (LS_TotalDistance[LS_TempIndex] - 50.00)
                      • LS_Boolean[LS_TempIndex] Equal to True
                • Then - Actions
                  • Set LS_Speed[LS_TempIndex] = (LS_Speed[LS_TempIndex] x -1.00)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • LS_Boolean[LS_TempIndex] Equal to False
                    • Then - Actions
                      • Unit - Cause LS_Caster[LS_TempIndex] to damage LS_Target[LS_TempIndex], dealing LS_Damage[LS_TempIndex] damage of attack type LS_AttackType and damage type LS_DamageType
                      • Special Effect - Create a special effect attached to the origin of LS_Target[LS_TempIndex] using LS_DamageSFX
                      • Special Effect - Destroy (Last created special effect)
                    • Else - Actions
                      • Set LS_Damage[LS_TempIndex] = (LS_Damage[LS_TempIndex] + LS_DamageIncrement[LS_AbilityIndex[LS_TempIndex]])
                      • Set LS_Speed[LS_TempIndex] = (LS_Speed[LS_TempIndex] + LS_SpeedIncrement[LS_AbilityIndex[LS_TempIndex]])
                      • Set LS_Size[LS_TempIndex] = (LS_Size[LS_TempIndex] + LS_SizeIncrement)
                      • Animation - Change LS_Spark[LS_TempIndex]'s size to (LS_Size[LS_TempIndex]%, 0.00%, 0.00%) of its original size
                      • Special Effect - Create a special effect attached to the origin of LS_Spark[LS_TempIndex] using LS_IncreaseSFX
                      • Special Effect - Destroy (Last created special effect)
                  • Custom script: set udg_LS_Boolean[udg_LS_TempIndex] = not udg_LS_Boolean[udg_LS_TempIndex]
                • Else - Actions
              • -------- Moving the orb just like we move the spark. --------
              • Custom script: call SetUnitY(udg_LS_Orb[udg_LS_TempIndex], (udg_LS_Y2 - udg_LS_TriggerExplosion[udg_LS_AbilityIndex[udg_LS_TempIndex]]*Sin(udg_LS_Angle)))
              • Custom script: call SetUnitX(udg_LS_Orb[udg_LS_TempIndex], (udg_LS_X2 - udg_LS_TriggerExplosion[udg_LS_AbilityIndex[udg_LS_TempIndex]]*Cos(udg_LS_Angle)))
              • Custom script: set udg_LS_TempDistance = SquareRoot((udg_LS_Y - GetUnitY(udg_LS_Orb[udg_LS_TempIndex])) * (udg_LS_Y - GetUnitY(udg_LS_Orb[udg_LS_TempIndex])) + (udg_LS_X - GetUnitX(udg_LS_Orb[udg_LS_TempIndex])) * (udg_LS_X - GetUnitX(udg_LS_Orb[udg_LS_TempIndex])))
              • Animation - Change LS_Orb[LS_TempIndex] flying height to ((LS_TempDistance x LS_Z2) / LS_TotalDistance[LS_TempIndex]) at 0.00
              • -------- Checking if the caster has passed the explosion point. If yes, the spark explodes. --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • LS_TotalDistance[LS_TempIndex] Less than or equal to LS_TriggerExplosion[LS_AbilityIndex[LS_TempIndex]]
                • Then - Actions
                  • Set LS_TempPoint = (Position of LS_Spark[LS_TempIndex])
                  • Set LS_Group = (Units within LS_AoE[LS_AbilityIndex[LS_TempIndex]] of LS_TempPoint)
                  • Unit Group - Pick every unit in LS_Group and do (Actions)
                    • Loop - Actions
                      • Set LS_PickedUnits = (Picked unit)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (LS_PickedUnits is A structure) Equal to False
                          • (LS_PickedUnits is alive) Equal to True
                          • (LS_PickedUnits belongs to an ally of LS_Player[LS_TempIndex]) Equal to False
                        • Then - Actions
                          • Unit - Cause LS_Caster[LS_TempIndex] to damage LS_PickedUnits, dealing (LS_DMGMultiplier[LS_AbilityIndex[LS_TempIndex]] x LS_Damage[LS_TempIndex]) damage of attack type LS_EAttackType and damage type LS_EDamageType
                          • Special Effect - Create a special effect attached to the origin of LS_PickedUnits using LS_DamageSFX
                          • Special Effect - Destroy (Last created special effect)
                        • Else - Actions
                  • Set LS_Duration[LS_TempIndex] = 0.00
                  • Custom script: call DestroyGroup(udg_LS_Group)
                  • Custom script: call RemoveLocation(udg_LS_TempPoint)
                • Else - Actions
            • Else - Actions
              • -------- Deindexing. --------
              • Unit - Kill LS_Spark[LS_TempIndex]
              • Set LS_Spark[LS_TempIndex] = LS_Spark[LS_MaxIndex]
              • Special Effect - Destroy LS_SFX[LS_TempIndex]
              • Set LS_SFX[LS_TempIndex] = LS_SFX[LS_MaxIndex]
              • Unit - Kill LS_Orb[LS_TempIndex]
              • Special Effect - Destroy LS_OrbSFX[LS_TempIndex]
              • Set LS_OrbSFX[LS_TempIndex] = LS_OrbSFX[LS_MaxIndex]
              • Set LS_Orb[LS_TempIndex] = LS_Orb[LS_MaxIndex]
              • Set LS_Target[LS_TempIndex] = LS_Target[LS_MaxIndex]
              • Set LS_Caster[LS_TempIndex] = LS_Caster[LS_MaxIndex]
              • Set LS_TotalDistance[LS_TempIndex] = LS_TotalDistance[LS_MaxIndex]
              • Set LS_Distance[LS_TempIndex] = LS_Distance[LS_MaxIndex]
              • Set LS_DistanceTravelled[LS_TempIndex] = LS_DistanceTravelled[LS_MaxIndex]
              • Set LS_Damage[LS_TempIndex] = LS_Damage[LS_MaxIndex]
              • Set LS_Speed[LS_TempIndex] = LS_Speed[LS_MaxIndex]
              • Set LS_Size[LS_TempIndex] = LS_Size[LS_MaxIndex]
              • Lightning - Destroy LS_Lightning[LS_TempIndex]
              • Set LS_Lightning[LS_TempIndex] = LS_Lightning[LS_MaxIndex]
              • Set LS_Player[LS_TempIndex] = LS_Player[LS_MaxIndex]
              • Set LS_Duration[LS_TempIndex] = LS_Duration[LS_MaxIndex]
              • Set LS_AbilityIndex[LS_TempIndex] = LS_AbilityIndex[LS_MaxIndex]
              • Set LS_Boolean[LS_TempIndex] = LS_Boolean[LS_MaxIndex]
              • Set LS_TempIndex = (LS_TempIndex - 1)
              • Set LS_MaxIndex = (LS_MaxIndex - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • LS_MaxIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off Linked Spark Loop <gen>
                • Else - Actions

Credits & Changelog

Credits:

Vexorian/Infrane/Anitarf for their dummy.


Changelog:

v1.00 - Initial release.
v1.01 - Basically did all the things Tank-Commander pointed out, though I haven't updated the sloppyness in GIF 1 of his comment.
v1.02 - Furtherly optimized the spell based on the second review of TC, but most importantly, the spark moves smoothly now.

As always, feedback is highly appreciated.

Keywords:
Linked Spark, Linked, Spark, Meatmuffin, lightning, blue, orb, increase, damage, explosion, unique, loop, GUI, MUI, kek
Contents

Linked Spark v1.02 (Map)

Reviews
22:34, 18th Feb 2016 Tank-Commander: v1.02 - Visual effect fixed and the code's looking much better, rating changed to 4/5 20:31, 14th Feb 2016 Tank-Commander: v1.01 - The spell is good and unique other than the notes I mention (see...

Moderator

M

Moderator

22:34, 18th Feb 2016
Tank-Commander: v1.02 - Visual effect fixed and the code's looking much better, rating changed to 4/5


20:31, 14th Feb 2016
Tank-Commander: v1.01 - The spell is good and unique other than the notes I mention (see: http://www.hiveworkshop.com/forums/spells-569/linked-spark-v1-01-a-275549/#post2787683)
It's in an approvable state but I'd like to see some cleanup of redundant parts in the loop and the odd visual effect I mentioned before in the first post (first GIF)

20:52, 10th Feb 2016
Tank-Commander: v1.00 - See my post http://www.hiveworkshop.com/forums/spells-569/linked-spark-v1-00-a-275549/#post2786024 for details, the primary issue is the efficiency of the program (moving the lightning effect and the orb)
 
Doing a very quick scan of the code

  • Set LS_OrbAngle[LS_TempIndex] = (Angle from LS_TempPoint2 to LS_TempPoint)
  • Set LS_TempPoint3 = (LS_TempPoint2 offset by LS_TriggerExplosion[LS_AbilityIndex[LS_TempIndex]] towards LS_OrbAngle[LS_TempIndex] degrees)
  • Set LS_XOfPoint = (X of LS_TempPoint3)
  • Set LS_YOfPoint = (Y of LS_TempPoint3)
  • Custom script: call SetUnitX(udg_LS_Orb[udg_LS_TempIndex], udg_LS_XOfPoint)
  • Custom script: call SetUnitY(udg_LS_Orb[udg_LS_TempIndex], udg_LS_YOfPoint)
There's a lot of redundancy here - there's no need to use points at all particularly for what you are doing (since you convert it all to co-ordinates anyway)
call SetUnitX(u, x + dist * Cos(angle))
call SetUnitY(u, y + dist * Sin(angle))
moves a unit from (x, y) to its new location by dist toward angle where angle is in radians
(which can be done via
set angle = Atan2(y2- y, x2 - x) where y2 and x2 are the target point and x, y are the current point)
this cuts down the lines of code from 6 to 3 and you done need to remove the location because you don't make one and fewer variables are used overall
(Using GetUnitX() and GetUnitY() functions can make this easier as well though if you use them twice on the same unit it's recommended to store it in a variable (udg_LS_X/YOfPoint in your case)

  • Set LS_DistanceTravelled[LS_TempIndex] = 0.00
This is done regardless of the boolean value

Since this uses 0.03 in a lot of places (the timer speed) it'd make sense to put it as a configurable and substitute the variable into all the appropriate places (if somebody changes it to run every 0.04 seconds for instance it will not work as intended)

  • Animation - Change LS_Orb[LS_MaxIndex]'s size to (175.00%, 175.00%, 175.00%) of its original size
This would do the same thing as
  • Animation - Change LS_Orb[LS_MaxIndex]'s size to (175.00%, 0%, 0%) of its original size
(May save you some processing later such as fetching LS_Size[LS_TempIndex] 3 times in one function call, also why is the starting size not configurable?

Could argue that there should be some z offset to the lightning - it looks a bit weird with the lightning being at the units' feet rather than their body
(I'd suggest looking at the function MoveLightningEx to do this)

You find pretty quickly with "advanced" spell making that locations are almost completely and utterly redundant and slow and are completely avoidable

I'll test the program for bugs and edit this post later

Edit: Testing went pretty well
- Object data, dummies etc. all good
- The only new "Issue" I found was in the first GIF I've attached below - While I'm aware why it happens (the unit moves further away making the orb visually stay in place) it does look a bit wrong for it to not continue moving at the same speed while not essential to change it does ruin the aesthetic a bit
- The second GIF kind of puts an emphasis on my previous point about the heights looking weird: the problem is significantly worse when targeting fliers and further ruins the effect of the spell (you can fix this the easy way: by making the ability only target ground units, meaning fliers should not really be damaged by the ability when doing AOE damage or the harder way: make the visual effect work for both ground and fliers (which would involve changing the fly height of the orb as it moves if the two units are of different heights)
 

Attachments

  • Sluggishness.gif
    Sluggishness.gif
    2.2 MB · Views: 230
  • Height Error.gif
    Height Error.gif
    400 KB · Views: 258
Last edited:
Level 11
Joined
Jul 25, 2014
Messages
490
About the sin/cos/atan calls, I'll make sure to study them, again, never used them before. Once I do, I will implement the new, more appropriate way of setting locations.

Configurable interval/primary size - will do.

Nulling DistanceTravelled[] and changing only 1 aspect of the size - will do.

MoveLightningEx - okay, will check up on that, since I noticed that it would be the same for air units and it would look... weird.

Thanks for the review.

EDIT:
Gif 1 - I'm aware of why that happens as well, though I'm not sure if I will try to implement a new way of moving the spark. It does seem to involve a tactic to the spell. However, it will not look pretty if the caster will move really fast or blink, if you will.
Gif 2 - Thought about that when creating lightnings, but making it only target ground units seems like a sloppy workaround. I'll try to use the MoveLightningEx for Z offset of units (I actually read up on that when making the ability). As for the spark itself, it will be a tad harder to constantly change the height of the spark, but I will try it.

Also there's a visual bug you did not test, if you cast it from range which is <TriggerExplosion[] the orb appears behind the caster and it looks a little odd, but since the spell instantly ends, I guess it's not that big of a deal.

I'll make sure to update the spell tomorrow.
 
You might wanna keep 1 location to call GetLocationZ + GetUnitFlyHeight on the lightning effect when using MoveLightningEx. I myself have been struggling to get lightning effects to connect properly to a unit on uneven terrain, but it should allow the lightning effects you use have proper height on even terrain and slopes at least.

Additionally, there's the problem of the dummy units moving along the lightning targeting air units. I don't see your changing your dummy units' flying height anywhere in your code, so it's something else to consider. I'm kinda bad at math, but my guesses is that Pythagoras theorem would be a good starting point.
 
Level 11
Joined
Jul 25, 2014
Messages
490
Update consists of all the things Tank-Commander pointed out, except for the sloppyness which can be seen in GIF 1 of his comment.

Used a lot of custom scripts, even where not needed, to improve readability.

EDIT: If anyone knows how could I make the offset without having the problem in that GIF, I'd appreciate if you'd tell me that.
 
Last edited:
Some further notes:
- The distance variable can be completely avoided (use of the total distance variable and an "or" condition)
- Speed can be multiplied by -1 at the relevant parts (removing the need for the first LS_Boolean check when done in combination with the above)
- If both of the above are done LS_Boolean becomes avoidable (nesting one total distance check result in the else of the other)

Other (unimportant):
- Further application of co-ordinate usage can remove the locations in the init trigger although this would be pushing further into the territory of using JASS over GUI
 
Top