• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Spell] Throw Hammer and Back

Level 5
Joined
Jun 16, 2009
Messages
50
Greetings,

I'm trying to create a spell where the hero throws a hammer (a projectile) and it returns to the hero, dealing damage in both travels. To be more specific, the same spell you see on Muradin Hero Concept (storm bolt). The thing is: I'm not familiar with jass, and my map ins't on lua, so I tried making a GUI version, also because the quoted system uses a library that I couldn't fit on my map.
With lots of struggle, I managed to design the first instance (very much similar to a shockwave type of spell), but making the projectile go back and deal damage is the most complicated part.

Here's what I got so far:

  • Hammer Throw Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Hammer Throw
    • Actions
      • Set VariableSet SW_Index = (SW_Index + 1)
      • -------- --------
      • Set VariableSet SW_Caster[SW_Index] = (Triggering unit)
      • -------- --------
      • Set VariableSet SW_Point[SW_Index] = (Position of SW_Caster[SW_Index])
      • Set VariableSet SW_TempPoint[1] = (Target point of ability being cast)
      • -------- --------
      • Special Effect - Create a special effect at SW_Point[SW_Index] using war3mapImported\Storm Bolt.mdx
      • Set VariableSet SW_Missile[SW_Index] = (Last created special effect)
      • Special Effect - Set Scale of SW_Missile[SW_Index] to 2.25
      • Set VariableSet SW_Angle[SW_Index] = (Angle from SW_Point[SW_Index] to SW_TempPoint[1])
      • Special Effect - Set Yaw of SW_Missile[SW_Index] to: (SW_Angle[SW_Index] x (Pi / 180.00))
      • Custom script: call RemoveLocation (udg_SW_TempPoint[1])
      • -------- --------
      • -------- ======================================== --------
      • Set VariableSet SW_Damage[SW_Index] = 150.00
      • Set VariableSet SW_DamageType[SW_Index] = Normal
      • Set VariableSet SW_AttackType[SW_Index] = Spells
      • Set VariableSet SW_Speed[SW_Index] = 39.50
      • Set VariableSet SW_Height[SW_Index] = 95.00
      • Set VariableSet SW_AoE[SW_Index] = 165.00
      • -------- --------
      • Set VariableSet SW_CounterMax[SW_Index] = 40
      • -------- ======================================== --------
      • -------- --------
      • Set VariableSet SW_Counter[SW_Index] = 0
      • Set VariableSet SW_Distance[SW_Index] = 0.00
      • Special Effect - Set Height of SW_Missile[SW_Index] to: ((Position - Z of SW_Missile[SW_Index].) + SW_Height[SW_Index])
      • Custom script: set udg_SW_HitGroup[udg_SW_Index] = CreateGroup()
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SW_Index Equal to 1
        • Then - Actions
          • Countdown Timer - Start SW_Timer as a Repeating timer that will expire in 0.03 seconds
        • Else - Actions
  • Hammer Throw Timer
    • Events
      • Time - SW_Timer expires
    • Conditions
    • Actions
      • For each (Integer SW_Loop) from 1 to SW_Index, do (Actions)
        • Loop - Actions
          • Set VariableSet SW_Distance[SW_Loop] = (SW_Distance[SW_Loop] + SW_Speed[SW_Loop])
          • Set VariableSet SW_TempPoint[1] = (SW_Point[SW_Loop] offset by SW_Distance[SW_Loop] towards SW_Angle[SW_Loop] degrees.)
          • Custom script: set udg_SW_Z = GetLocationZ(udg_SW_TempPoint[1])
          • Special Effect - Set Position of SW_Missile[SW_Loop] to x: (X of SW_TempPoint[1]), y: (Y of SW_TempPoint[1]), z: (SW_Z + SW_Height[SW_Loop])
          • -------- --------
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Units within SW_AoE[SW_Loop] of SW_TempPoint[1].) and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) belongs to an enemy of (Owner of SW_Caster[SW_Index]).) Equal to True
                  • ((Picked unit) is alive) Equal to True
                  • ((Picked unit) is A ground unit) Equal to True
                  • ((Picked unit) is Magic Immune) Equal to False
                  • ((Picked unit) is Mechanical) Equal to False
                  • ((Picked unit) is hidden) Equal to False
                  • ((Picked unit) is invulnerable) Equal to False
                  • ((Picked unit) is A structure) Equal to False
                  • ((Picked unit) is in SW_HitGroup[SW_Loop].) Equal to False
                • Then - Actions
                  • Unit Group - Add (Picked unit) to SW_HitGroup[SW_Loop]
                  • Unit - Cause SW_Caster[SW_Loop] to damage (Picked unit), dealing SW_Damage[SW_Loop] damage of attack type SW_AttackType[SW_Loop] and damage type SW_DamageType[SW_Loop]
                  • Special Effect - Create a special effect attached to the origin of (Picked unit) using Abilities\Weapons\ChimaeraLightningMissile\ChimaeraLightningMissile.mdl
                  • Special Effect - Destroy (Last created special effect)
                • Else - Actions
          • Custom script: call RemoveLocation (udg_SW_TempPoint[1])
          • -------- --------
          • Set VariableSet SW_Counter[SW_Loop] = (SW_Counter[SW_Loop] + 1)
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SW_Counter[SW_Loop] Equal to SW_CounterMax[SW_Loop]
            • Then - Actions
              • Special Effect - Destroy SW_Missile[SW_Loop]
              • Custom script: call RemoveLocation (udg_SW_Point[udg_SW_Loop])
              • Custom script: call DestroyGroup (udg_SW_HitGroup[udg_SW_Loop])
              • -------- --------
              • Set VariableSet SW_Caster[SW_Loop] = SW_Caster[SW_Index]
              • Set VariableSet SW_Point[SW_Loop] = SW_Point[SW_Index]
              • -------- --------
              • Set VariableSet SW_Angle[SW_Loop] = SW_Angle[SW_Index]
              • -------- --------
              • Set VariableSet SW_Missile[SW_Loop] = SW_Missile[SW_Index]
              • Set VariableSet SW_Speed[SW_Loop] = SW_Speed[SW_Index]
              • Set VariableSet SW_Height[SW_Loop] = SW_Height[SW_Index]
              • Set VariableSet SW_Counter[SW_Loop] = SW_Counter[SW_Index]
              • Set VariableSet SW_CounterMax[SW_Loop] = SW_CounterMax[SW_Loop]
              • Set VariableSet SW_Distance[SW_Loop] = SW_Distance[SW_Index]
              • Set VariableSet SW_Damage[SW_Loop] = SW_Damage[SW_Index]
              • Set VariableSet SW_AoE[SW_Loop] = SW_AoE[SW_Index]
              • Set VariableSet SW_HitGroup[SW_Loop] = SW_HitGroup[SW_Index]
              • -------- --------
              • Set VariableSet SW_Index = (SW_Index - 1)
              • Set VariableSet SW_Loop = (SW_Loop - 1)
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SW_Index Equal to 0
                • Then - Actions
                  • Countdown Timer - Pause SW_Timer
                • Else - Actions
            • Else - Actions

Any help will be much appreciated.
 

Attachments

  • hammer throw.w3m
    60.1 KB · Views: 3

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,877
You're pretty much there, you just need a few tweaks.

1) Create a new Boolean array variable called SW_Is_Reversing[]. Set it to FALSE in your Cast trigger.

2) Add an If Then Else to the Loop - Actions section of your Hammer Throw Timer trigger. This will check the state of the Boolean.

3) While SW_Is_Reversing is equal to FALSE you will run your standard movement logic that you're using now. Then once SW_Counter reaches SW_CounterMax you will instead Set this Boolean to TRUE and Empty the SW_HitGroup so that units can be hit again during the return flight.

4) While SW_Is_Reversing is equal to TRUE you will run new logic. Calculate the angle between the position of the hammer and the caster each cycle, then move the missile towards this new angle offset by it's SW_Speed. Then use a Distance check to see if the missile is close enough to the caster -> (If distance between X and Y is Less than or equal to 80.00). Once it's close enough to the caster you will run your standard clean up logic, destroying the missile, point, and group then swapping the index/loop variables.

5) Don't forget to "de-index" the new SW_Is_Reversing variable as well. That should do it.


Also, a wise optimization would be to replace the (Picked unit) function with a Variable:
  • Unit Group - Pick every unit in (Units within SW_AoE[SW_Loop] of SW_TempPoint[1].) and do (Actions)
    • Loop - Actions
      • Set VariableSet SW_Enemy = (Picked unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (SW_Enemy belongs to an enemy of (Owner of SW_Caster[SW_Index]).) Equal to True
          • ...
To avoid needing a new variable you can reuse the [0] index of SW_Caster[] for this job, although it'll be a bit misleading.
 
Last edited:
Top