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

[Spell] Shockwave that pulls towards location over timeframe

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi guys,

I'm trying to create a shockwave that pulls enemy units in 200 range of the projectile 150 units towards the shockwave and towards the direction of the caster. I spell which captures the basic idea, but not exactly how I want it:

1) Currently, the enemy unit is pulled instantly do the new destination. However, I want the enemies to be moved to the destination over a timeframe, not instantly.

2) Currently, the enemy unit within 200 range of point X is pulled all the way to point X. However, I want to the unit to only travel 150 units towards point X (which is basically "towards the shockwave and towards the caster").

I strongly suspecting that these changes would require a lot more indexes than I currently have, but I don't know how to apply this. Can anyone help please?

  • Shockwave
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Shockwave (Magnus)
    • Actions
      • Set VariableSet Shockwave_Counts = (Shockwave_Counts + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Shockwave_Counts Greater than Universal_CountMaxSize
        • Then - Actions
          • Set VariableSet Shockwave_Counts = 1
        • Else - Actions
      • Set VariableSet Shockwave_Caster[Shockwave_Counts] = (Triggering unit)
      • Set VariableSet Shockwave_CasterLoc = (Position of Shockwave_Caster[Shockwave_Counts])
      • Set VariableSet Shockwave_TargetPoint = (Target point of ability being cast)
      • Set VariableSet Shockwave_Angle = (Angle from Shockwave_CasterLoc to Shockwave_TargetPoint)
      • Set VariableSet Shockwave_Damage[Shockwave_Counts] = (75.00 x (Real((Level of Shockwave (Magnus) for Shockwave_Caster[Shockwave_Counts]))))
      • Unit - Create 1 Shockwave Projectile for (Owner of Shockwave_Caster[Shockwave_Counts]) at Shockwave_CasterLoc facing Shockwave_Angle degrees
      • Unit - Set the custom value of (Last created unit) to Shockwave_Counts
      • Unit Group - Add (Last created unit) to Shockwave_StartGroup
      • Set VariableSet Shockwave_MaxDistance[Shockwave_Counts] = 1200.00
      • Set VariableSet Shockwave_DistanceTravel[Shockwave_Counts] = 0.00
      • Custom script: set udg_Shockwave_Damaged[udg_Shockwave_Counts] = CreateGroup()
      • Trigger - Turn on Shockwave Loop <gen>
      • Custom script: call RemoveLocation (udg_Shockwave_CasterLoc)
      • Custom script: call RemoveLocation (udg_Shockwave_TargetPoint)


  • Shockwave Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Shockwave_StartGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet Shockwave_Projectile = (Picked unit)
          • Set VariableSet Shockwave_CusValue = (Custom value of Shockwave_Projectile)
          • Set VariableSet Shockwave_DummyLoc = (Position of Shockwave_Projectile)
          • Set VariableSet Shockwave_Movement = (Shockwave_DummyLoc offset by 60.00 towards (Facing of Shockwave_Projectile) degrees.)
          • Unit - Move Shockwave_Projectile instantly to Shockwave_Movement
          • Set VariableSet Shockwave_DistanceTravel[Shockwave_CusValue] = (Shockwave_DistanceTravel[Shockwave_CusValue] + 60.00)
          • Set VariableSet Shockwave_UnitGroup = (Units within 200.00 of Shockwave_Movement.)
          • Unit Group - Pick every unit in Shockwave_UnitGroup and do (Actions)
            • Loop - Actions
              • Set VariableSet Shockwave_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Shockwave_TempUnit is A structure) Equal to False
                  • (Shockwave_TempUnit is alive) Equal to True
                  • (Shockwave_TempUnit belongs to an enemy of (Owner of Shockwave_Caster[Shockwave_CusValue]).) Equal to True
                  • (Shockwave_TempUnit has buff Shockwave ) Equal to False
                  • (Shockwave_TempUnit is in Shockwave_Damaged[Shockwave_CusValue].) Equal to False
                • Then - Actions
                  • Unit Group - Add Shockwave_TempUnit to Shockwave_Damaged[Shockwave_CusValue]
                  • Set VariableSet Shockwave_TempUnit_X = (X of Shockwave_Movement)
                  • Set VariableSet Shockwave_TempUnit_Y = (Y of Shockwave_Movement)
                  • Custom script: call SetUnitX(udg_Shockwave_TempUnit, udg_Shockwave_TempUnit_X)
                  • Custom script: call SetUnitY(udg_Shockwave_TempUnit, udg_Shockwave_TempUnit_Y)
                  • Special Effect - Create a special effect attached to the origin of (Picked unit) using war3mapImported\Void Rift II Orange.mdx
                  • Special Effect - Destroy (Last created special effect)
                  • Unit - Cause Shockwave_Caster[Shockwave_CusValue] to damage Shockwave_TempUnit, dealing Shockwave_Damage[Shockwave_CusValue] damage of attack type Spells and damage type Magic
                  • Unit - Create 1 Dummy (Ground/Speed 1) for (Owner of Shockwave_Caster[Shockwave_CusValue]) at Shockwave_Movement facing Default building facing degrees
                  • Set VariableSet Shockwave_Slower = (Last created unit)
                  • Unit - Add Shockwave (Slow) to Shockwave_Slower
                  • Unit - Order Shockwave_Slower to Human Sorceress - Slow Shockwave_TempUnit
                  • Unit - Add a 1.00 second Generic expiration timer to Shockwave_Slower
                • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • Shockwave_DistanceTravel[Shockwave_CusValue] Greater than or equal to Shockwave_MaxDistance[Shockwave_CusValue]
            • Then - Actions
              • Unit - Kill Shockwave_Projectile
              • Unit Group - Remove Shockwave_Projectile from Shockwave_StartGroup.
              • Custom script: call DestroyGroup(udg_Shockwave_Damaged[udg_Shockwave_CusValue])
            • Else - Actions
          • Custom script: call RemoveLocation (udg_Shockwave_DummyLoc)
          • Custom script: call RemoveLocation (udg_Shockwave_Movement)
          • Custom script: call DestroyGroup (udg_Shockwave_UnitGroup)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Shockwave_StartGroup) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
I don't understand what you mean when you say towards the caster AND towards the shockwave. Wouldn't it be one or the other? The caster could move anywhere on the map after casting the ability, so I assume you want the enmies to always move towards the Shockwave. This is the same exact mechanic as Magnus' Shockwave from DotA 2 which I'm assuming is what inspired you, and in that case it always pulls the enemies towards the center of the Shockwave.

Anyway, I would use Dynamic Indexing (link in my signature) to handle both effects, the shockwave movement and the shockwave pull.

You can use two separate Loop Triggers, and have two separate sets of Variables, one for the Shockwave movement, and another for the Pull movement.

Loop #1 runs every 0.03 seconds, moving the shockwave and checking for enemies. When an enemy is hit, Index them add them to the Loop #2 trigger which will apply the 150 distance pull.

There's a bit more to it than that, so maybe if I get the chance I'll throw it together.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Not entirely: The units should indeed move a) towards the Shockwave, but also b) towards the initial caster location. So essentially diagonally to both these points. And yes, it should work like in DotA 2 :p

Magnus
"Hit enemies are pulled towards the center of the Shockwave and towards Magnus."

Haa I feared the solution would be "dynamic indexing" (or hashtable, which I understand even less). But thanks for the link - will try to apply it!

edit: I’m still working on it, but the challenge currently is that it’s not just the units who have to be dynamically indexed, but also the points.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
So I started adjusting the trigger, but I think it's a lot more complicated than showed in the dynamic indexing page. The biggest issue is that the "counter" is not aligned across the point and the to be pulled unit, because not at every indexed point there necessarily is a unit.

So for example:
- On loop 1) you set counter = 1 / no unit found --> Result: Point [1]
- On loop 2) you set counter = 2 / no unit found --> Result: Point [2]
- On loop 3) you set counter = 3 / unit is in range --> Result: Point [3], Unit [1] --> in loop #2 unit [1] is pulled toward Point [1], instead of Point [3]

I thought maybe I can add an IF function so that the counter only increases if a unit is nearby, but then I don't have an integer to define the Point to which the projectile should move in the first place... hope you understand what I mean. I'm adding the map so you can see the initial trigger (it's under Magnataur)

(Chrono is not added in this version yet btw, I want to find find this "stuck" bug first)
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
So I took a custom shockwave spell I had laying around and modified it to apply a pulling effect. It's not the same as DotA 2's Shockwave, but it should lead you in the right direction.

How I did it:
I used the Unit Indexer approach, with a Unit Group and a few Pull variables to keep track of everything. When an enemy gets hit by the Shockwave, I add it to the Pull Group, and set some Pull-related variables like Pull Distance and Pull Angle. After roughly 0.20 seconds of movement the unit is removed from the Pull Group.

Because of this design, if an enemy gets hit by multiple shockwaves at a time then only the most recent shockwave will apply it's pull effect.
 

Attachments

  • Land of Legends v0.0.93 Shockwave 1.w3m
    42 MB · Views: 24
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Thank you so much! I adjusted it a bit because I didn't like that units who were right next or in front of Magnus were in some cases pulled behind him - which doesn't synergizes well with his cleave ability.

So in order to move units in very close proximity to a point in front of Magnus, I added 2 points (45 and 128 units in front of Magnus) to fake a "recangle" with 2 circles. So units on the side and in front which previously would be moved behind Magnus, would now instead be moved to the 128 point which is right at the attacking sweet spot.

Is there a way to do it more efficiently, or do you think the way I did it is OK?
 

Attachments

  • Land of Legends v0.0.94.w3m
    42 MB · Views: 27
Status
Not open for further replies.
Top