• Check out the results of the Techtree Contest #19!
  • 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.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

Missile Event

Level 14
Joined
Oct 28, 2019
Messages
536
Hi everyone, I'm building a Frost Mage character. I've already implemented Frost Bolt and Frost Arrow, and they’re working fine. Now, I’m trying to create a Frozen Orb (similar to the one in Diablo 2).

The logic is as follows: The mage casts a main Frozen Orb that travels forward, firing Frost Arrows in all directions as it moves. I'm using a missile/projectile system to handle collisions and physics. I’m also using a key-input system to trigger specific events.

  • MissileJainaButtonR
    • Events
      • Unit - A unit owned by Player 1 (Red) Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ice Orb
    • Actions
      • Trigger - Run Missile Configurate <gen> (ignoring conditions)
      • Set VariableSet Missile__TempLoc = ((Target point of ability being cast) offset by 500.00 towards (Facing of HeroVariableP1) degrees.)
      • Set VariableSet Missile__Source = (Casting unit)
      • Set VariableSet Missile__Owner = Player 1 (Red)
      • Set VariableSet Missile__Origin = (Position of Missile__Source)
      • Set VariableSet Missile__Impact = ((Target point of ability being cast) offset by 500.00 towards (Facing of HeroVariableP1) degrees.)
      • Set VariableSet Missile__ImpactZ = 100.00
      • Set VariableSet Missile__OriginZ = 100.00
      • Set VariableSet Missile__Speed = 800.00
      • Set VariableSet Missile__Collision = 50.00
      • Set VariableSet Missile__Arc = 0.00
      • Set VariableSet Missile__Damage = (Real(IntegerIntelligenceJaina))
      • Set VariableSet Missile__Model = Abilities\Weapons\FrostWyrmMissile\FrostWyrmMissile.mdl
      • Set VariableSet Missile__OnCollideUnit = Missile Collision Unit Jaina QButton <gen>
      • Set VariableSet Missile__OnCollideDestructable = Missile Collision Tree <gen>
      • Trigger - Run Missile <gen> (ignoring conditions)
      • Custom script: call RemoveLocation(udg_Missile__TempLoc)
  • CREATE UNITS
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Angle = (Random real number between 0.00 and 360.00)
      • Unit - Create 1 Wisp for Player 1 (Red) at (Position of Missile_Dummy[1]) facing Default building facing degrees
      • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
      • Unit - Order (Last created unit) to Orc Far Seer - Far Sight ((Position of Missile_Dummy[1]) offset by 500.00 towards (Angle + 100.00) degrees.)
My problem is with the variable declaration (specifically missile_dummy[1]). I don't know what to replace it with. Currently, it only handles the very first shot; subsequent arrows aren't firing or being tracked. How should I declare or structure this to allow multiple missiles to be spawned and tracked simultaneously from the moving Orb?

Thanks for the help!"
 
Well instead of creating a dummy unit you could just run the missile create gen every 0.20 seconds and create ur secondary missiles, following the same logic as your main cast trigger. Since the system inheritly tracks all the missiles and their position and handles everything within itself.
 
What DoomBlade said.

But if you need to track other data, you can use the Missile__Index variable to point to a specific Array [index].

Let's say for example you were using Bribe's Unit Indexer, you could use this Integer to track the Dummy:
  • Actions
    • Trigger - Run Missile Configurate <gen> (ignoring conditions)
    • -------- Do the rest of your Missile stuff... --------
    • Unit - Create 1 Dummy for (Triggering player) at (Position of (Triggering unit))
    • Set Variable Missile__Index = (Custom value of (Last created unit))
    • Set Variable Orb_Angle[Missile__Index] = 0.00
    • Set Variable Missile__OnPeriodic = Orb On Periodic <gen>
    • Trigger - Run Missile <gen> (ignoring conditions)
Then you can reference the Dummy in any Missile__ related trigger that you've defined beforehand:
  • Orb On Periodic
    • Events
    • Conditions
    • Actions
      • Set Variable Orb_Angle[Missile_Index] = (Orb_Angle[Missile_Index] + 45.00)
      • Unit - Move UDex_Units[Missile_Index] to Missile_Position
      • Unit - Order UDex_Units[Missile_Index] to Orc - Shockwave (Missile_Position offset by 10.00 towards (Orb_Angle[Missile_Index]) degrees.)
I also track the Angle which increases by 45.00 degrees each shot.

Of course you should probably just fire another custom Missile using this system rather than casting Shockwave. Also, I'm writing this from memory so some names might be slightly off.
 
Last edited:
Well instead of creating a dummy unit you could just run the missile create gen every 0.20 seconds and create ur secondary missiles, following the same logic as your main cast trigger. Since the system inheritly tracks all the missiles and their position and handles everything within itself.
Idk how to start

Uncle Im not using bribe´s unit index, so this way I cant do, but thanks for replay
 
Idk how to start
I posted triggers showing how to start and finish it.
Uncle Im not using bribe´s unit index, so this way I cant do, but thanks for replay
You can use any Unit Indexer, or any indexing concept. All you need is a unique Integer that points an [index] in an Array.

Then you tell the Missile to track this Integer. The result is that if you have access to the Missile you will also have access to the Integer. Which means that you'll also have access to any associated Arrays that are using that Integer as their [index].

Here's the same design without a Unit Indexer:
  • Orb Start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ice Orb
    • Actions
      • Trigger - Run Missile Configurate <gen> (ignoring conditions) <--- You may not even need this
      • -------- Do the rest of your Missile stuff... --------
      • Unit - Create 1 Dummy for (Triggering player) at (Position of (Triggering unit))
      • Set Variable Orb_Instance = (Orb_Instance + 1)
      • If Orb_Instance Greater than or equal to 32768 then Set Variable Orb_Instance = 0 Else do nothing
      • Set Variable Orb_Dummy[Orb_Instance] = (Last created unit)
      • Set Variable Orb_Angle[Orb_Instance] = 0.00
      • Set Variable Missile__Index = Orb_Instance
      • Set Variable Missile__OnPeriodic = Orb On Periodic <gen>
      • Trigger - Run Missile <gen> (ignoring conditions)
Then you can reference the Dummy in any Missile related trigger:
  • Orb On Periodic
    • Events
    • Conditions
    • Actions
      • Set Variable Orb_Angle[Missile_Index] = (Orb_Angle[Missile_Index] + 45.00)
      • Unit - Move Orb_Dummy[Missile_Index] to Missile_Position
      • Unit - Order Orb_Dummy[Missile_Index] to Orc - Shockwave (Missile_Position offset by 10.00 towards (Orb_Angle[Missile_Index]) degrees.)
I've added two new variables:
Orb_Instance = Integer
Orb_Dummy = Unit (array)

These variables allow you to have up to 32,768 Frozen Orbs active at any given moment. It's important not to go above [32,768] because that's the largest size that an Array index can be.
 
Last edited:
I believe the Missile system runs every 0.03 seconds, which I'm sure you can configure in the system settings. A value of 0.02 might be preferable.

But that's not even necessary, you can introduce a new Variable that tracks how much time has passed.

Look at how Orb_Angle increases by 45.00 degrees every period (0.03s). What if that only happened every 0.30 seconds?
  • Set Variable Orb_Timer[Missile_Index] = (Orb_Timer[Missile_Index] + 0.03)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Orb_Timer[Missile_Index] Greater than or equal to 0.30
    • Then - Actions
      • Set Variable Orb_Timer[Missile_Index] = 0.00
      • Set Variable Orb_Angle[Missile_Index] = (Orb_Angle[Missile_Index] + 45.00)
      • -------- Create a new missile --------
    • Else - Actions
Note that it'd be better to check a value like 0.29 since there can be floating point error.
  • Orb_Timer[Missile_Index] Greater than or equal to 0.29
Try to get into this pattern of creating a new Array variable to solve your issues. Some basic math and If Then Else statements go a long way.
 
  • MissileJainaButtonR Copy 2
    • Events
      • Unit - A unit owned by Player 1 (Red) Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ice Orb
    • Actions
      • Trigger - Run Missile Configurate <gen> (ignoring conditions)
      • Set VariableSet Missile__TempLoc = ((Target point of ability being cast) offset by 500.00 towards (Facing of HeroVariableP1) degrees.)
      • Set VariableSet Missile__Source = (Casting unit)
      • Set VariableSet Missile__Owner = Player 1 (Red)
      • Set VariableSet Missile__Origin = (Position of Missile__Source)
      • Set VariableSet Missile__Impact = ((Target point of ability being cast) offset by 500.00 towards (Facing of HeroVariableP1) degrees.)
      • Set VariableSet Missile__ImpactZ = 100.00
      • Set VariableSet Missile__OriginZ = 100.00
      • Set VariableSet Missile__Speed = 400.00
      • Set VariableSet Missile__Collision = 50.00
      • Set VariableSet Missile__Arc = 0.00
      • Set VariableSet Missile__Model = Abilities\Weapons\FrostWyrmMissile\FrostWyrmMissile.mdl
      • Set VariableSet Missile__OnFinish = Missile Collision End Orb <gen>
      • Trigger - Run Missile <gen> (ignoring conditions)
      • Set VariableSet Unit_Orb = (Last created unit)
      • Custom script: call RemoveLocation(udg_Missile__TempLoc)
  • CREATE UNITS Copy
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Angle = (Angle + 225.00)
      • Unit - Create 1 Wisp for Player 1 (Red) at (Position of Unit_Orb) facing Angle degrees
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Unit - Order (Last created unit) to Orc Tauren Chieftain - Shockwave ((Position of Unit_Orb) offset by 1000.00 towards Angle degrees.)

@Uncle
I made a workaround that is working perfectly; I'm going to add a key event to detect when the Hero presses 'R'. I couldn't do it the way you suggested because I couldn't find the 'missile_index' variable—there's only 'missile__index', so I'm not sure, but something didn't work right.

This system I created is fine, but I need to polish it to avoid bugs during gameplay. Is there anything wrong with this approach?
 
I couldn't find the 'missile_index' variable—there's only 'missile__index', so I'm not sure, but something didn't work right.
They're the same variable, I told you I was writing things from memory. So you want to use Missile_Index.

Anyway, your triggers won't work if you want things to be instanceable. Your Angle variable cannot be shared between multiple instances of casts, that would mean that every cast of the ability will be fighting over it's value. Also, you might want to cast Shockwave offset by say 10.00 distance instead of 1000.00, to help avoid cases where the Dummy targets somewhere impathable like out of the map bounds.

I highly suggest doing what I said if you want the spell to work no matter what.
 
Last edited:
Back
Top