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

Make a unit go around other unit...

Status
Not open for further replies.
Level 14
Joined
Aug 8, 2010
Messages
1,022
Hi! I want to ask how to make a unit spin around other unit (like the lightning bolts spin around the Shaman when Lightning shield is casted) here is what i tried, but it isn't working... Help???

  • Create lightning bolt
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Create electric balls [Electro]
    • Actions
      • Set CastLoc = (Position of (Casting unit))
      • Unit - Create 1 Lightning bolts for Player 1 (Red) at (CastLoc offset by 150.00 towards 18.00 degrees) facing Default building facing degrees
      • Set Dabolt = (Last created unit)
      • Set Circle = (CastLoc offset by (1.00, 20.00))
      • Trigger - Turn on Make it move <gen>
  • Make it move
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • Set Circle = (CastLoc offset by 150.00 towards ((X of CastLoc) + 18.00) degrees)
      • Unit - Order Dabolt to Move To Circle
 
Level 13
Joined
Jun 22, 2004
Messages
783
A simple sollution is to calculate the angle between the two objects. you could create an offset value that moves it away from that angle.

To make things easy for us blizz actually made such a function called
Math - Angle between points

So in conclusion you could do something like the following.

  • Set newLocation = ((Position of caster) offset by x towards ((Angle from (Position of caster) to (Position of projectile)) + offset) degrees)
  • Unit - Move projectile instantly to newLocation
If you get puzzled just let me know, and ill see if I can explain some things in that function a bit more detailed.

NOTE: if you use this action allot of times, you might want to do some cleanup on memory leaks.
if you want to know more about just do some searched on the site.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
like the lightning bolts spin around the Shaman when Lightning shield is casted
You will need a model editor for an effect like this. The model used by lightning shield was physically orbs rotating in a circle (as its stand animation).

You could get units to orbit another unit via triggers but be aware that removing units in any way leaks and that JASS is very slow (so a model soultion is fastest).
 
Level 14
Joined
Aug 8, 2010
Messages
1,022
Hey Maker, your aura is PERFECT! But can you tell me what means
  • For each (Integer A) from 1 to i1, do (Actions)
and things like
  • Hashtable - Save Handle Of(Last created unit) as (Key (sheep + (String((Integer A))))) of (Key (Triggering unit)) in Sheep_Hash
what means to save it as a key? What is a key? Sorry for my dumbness :D
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
This is the answer for second question.

Actions: For each (Integer A) from 1 to i1, do (Actions) create a loop that repeat X times. Where X means amount calculated from values you have entered in places: 'from' and 'to'.
Lets say you set it: from 1 to 8 => that means that your actions inside will loop 8 times. If you would enter from 0 to 8 it would be exactly 9 since loop would begin from number 0 and then folow through rest of values.

Integer A is default integer which is set to given number (time) the loop is running.

Lets elaborate a bit.
  • Init
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • unit[1] = footman
      • unit[2] = knight
      • unit[3] = rifleman
  • Loop
    • Events
      • Time - Every 30 seconds of game time
    • Conditions
    • Actions
      • Actions: For each (Integer A) from 1 to 3 do Actions
        • Unit - Create 1 unit[Integer A] for Player 1 Red at (Center of (Playable map area)) facing Default building facing
Your Loop will repeat 3 times since all INTEGER values between 1 and 3 are: 1,2,3.
Because of that, Integer A will have three differend values depending on which time given loop is running.
In first loop (1) Integer A will be set to 1 and because we create unit[Integer A] our trigger will create 1 footman.
Similar situaction occurs with second and third time our loop will be running but when Integer A takes value 3 and all actions are executed for that loop, loop ends since it do not considers higher value than 3 - its the condition for loop.

Its easier to see when we look how loop looks like:
JASS:
local integer i = 1
loop
  exitwhen i > 3
 //actions
      set i = i + 1
endloop
As you can see there are 3 important parts: keyword 'loop' starts the loop, then we got conditions (keyword 'exitwhen') that allows loop to run, but it also tells when loop should finish - end. endloop tells where the loop function ends - only actions inside can be reapeated/executed.
 
Level 14
Joined
Aug 8, 2010
Messages
1,022
I read some tutorials and i came up with something that isn't working and i don't know why... :D Triggs here:

  • Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Create electric balls [Electro]
    • Actions
      • Set BallzPoints[0] = (Position of (Triggering unit))
      • Set BallzPoints[1] = (BallzPoints[0] offset by 100.00 towards 0.00 degrees)
      • Unit - Create 1 Lightning bolts for (Owner of (Triggering unit)) at BallzPoints[1] facing Default building facing degrees
      • Set LBUnit = (Last created unit)
      • Trigger - Turn on LoopCast <gen>
  • LoopCast
    • Events
      • Time - Every 3.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 30, do (Actions)
        • Loop - Actions
          • Set BallzPoints[2] = (BallzPoints[0] offset by ((Real((Integer A))) x 12.00) towards 100.00 degrees)
          • Unit - Order LBUnit to Move To BallzPoints[2]
Map - below! (The event 'Time - Every 3.00 seconds of game time' should mean that the circle should be done in 3 seconds, right?)
 
Last edited:
Level 37
Joined
Mar 6, 2006
Messages
9,240
Every 3 seconds means that the trigger runs once per three seconds.

You don't want to loop 30 times in a row. You are calculating a new points instantly. Only the last one will have any real effect this way. The unit won't have time to move to the calculated points since you instantly order it move to the next calculated point.

Also, you're forming a straight line with that, not a circle. Modify the angle, not the offset to form a circle.

It's better to set the unit's coordinates and not order it to move, since moving takes the pathing algorithm into account, and it won't look good.
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
No, every 3 seconds does not mean that circle will be done in 3 seconds..
  • LoopCast
    • Events
      • Time - Every 3.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 30, do (Actions)
        • Loop - Actions
          • Set BallzPoints[2] = (BallzPoints[0] offset by ((Real((Integer A))) x 12.00) towards 100.00 degrees)
          • Unit - Order LBUnit to Move To BallzPoints[2]
You missunderstood Maker. Creating a point is always an instant action, but look on your trigger: in your actions you create a loop which will repeat 30 times, and since loop is repeated in an instant speed we can say that you've created line of locations instead of circle.

Your angle is aways 100, they only thing here that is changing is the offset, thats why it will create just a line.

Solution: Reduce the periodic of loop, and work with angles.
Remember that if you want to create a circle, offset from central point S is always the same, and only the angles are changing since to form full cirle you need excatly 360 degrees.

I wont do eveything for you but look on egzample (here I create an instant cirlce of impale):
  • init
    • Events
      • Unit - Starts the effect of ability
    • Conditions
      • (Ability being cast) Equal to CoLd Bon3
    • Actions
      • Set tempp = (Position of (Triggering unit)
      • For each (Integer A) from 1 to 12 do Actions
        • Unit - Create 1 dummy for Triggering player at tempp facing Default building facing degrees
        • Unit - Add 1 generic expiration timer to last created unit
        • Unit - Add Impale to last created unit
        • Set tempp2 = (tempp offset by 100 towards (30 x (Integer A)) degrees)
        • Unit - Order (last created unit) to Undead - Crypt Lord - Impale tempp2
        • Custom script: call RemoveLocation (udg_tempp2)
      • Custom script: call RemoveLocation (udg_tempp2)
It will form a circle of impale around the caster. Why 30 x Integer A degrees? Hmm.. what I've been talking about the cirlces while ago? Aah yes! Full circle is formed with 360 degrees, and since I want a nice circle I have to divide degrees with nomber of angles I will be working with. Number of 'private' angles means here an amount of impales that will go around. I wanted 12, so 360 / 12 = 30 degrees => means that each impale will be away form another exactly by 30 degrees.

This should help you do your move circle on your own.
Last advice: to get unit coordinates
  • Custom script: set udg_x = GetUnitX (udg_yourUnit)
  • Custom script: set udg_y = GetUnitY (udg_yourUnit)
 
Level 14
Joined
Aug 8, 2010
Messages
1,022
Ok! Thank you guys! I have now my own trigger with succesfully rotating electric ball... but still it makes collision with other things... i make sure that i turn of the collision of the ball (from the triggs) and that i set 'Pathing - Collision size = 0'... Still my triggs are here, i will post my map as well

  • Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Create electric balls [Electro]
    • Actions
      • Set BallzPoints[0] = (Position of (Triggering unit))
      • Set BallzPoints[1] = (BallzPoints[0] offset by 100.00 towards 0.00 degrees)
      • Set ElectroCaster = (Triggering unit)
      • Unit - Create 1 Lightning bolts for (Owner of (Triggering unit)) at BallzPoints[1] facing Default building facing degrees
      • Set LBUnit = (Last created unit)
      • Unit - Turn collision for LBUnit Off
      • Set Blabalbla = 0
      • Trigger - Turn on LoopCast <gen>
  • LoopCast
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Set BallzPoints[0] = (Position of ElectroCaster)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Blabalbla Equal to 360
        • Then - Actions
          • Set Blabalbla = 0
          • Set BallzPoints[2] = (BallzPoints[0] offset by 100.00 towards 0.00 degrees)
        • Else - Actions
          • Set Blabalbla = (Blabalbla + 3)
          • Set BallzPoints[2] = (BallzPoints[0] offset by 100.00 towards (Real(Blabalbla)) degrees)
      • Unit - Move LBUnit instantly to BallzPoints[2]
and how to make the unit unselectable or something...?
 
Last edited:
Level 14
Joined
Aug 8, 2010
Messages
1,022
Ammm... i have another problem now... i want to have 2 electric balls in my spell, when i cast the first - everything is OK, but when i cast again - the second ball goes crazy, it is doing circles, but not around the hero... The trigger is the like the trigger for the first ball, but with different arrays and variables. Triggers below, map - below the triggers!
  • Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Create balls of energy [Electro]
    • Actions
      • Set ElectBallz = (ElectBallz + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ElectBallz Equal to 1
        • Then - Actions
          • Set BallzPoints[0] = (Position of (Triggering unit))
          • Set BallzPoints[1] = (BallzPoints[0] offset by 100.00 towards 0.00 degrees)
          • Set ElectroCaster = (Triggering unit)
          • Unit - Create 1 Lightning bolts for (Owner of (Triggering unit)) at BallzPoints[1] facing Default building facing degrees
          • Set LBUnit[0] = (Last created unit)
          • Unit - Turn collision for LBUnit[0] Off
          • Set ElecBallDegree[0] = 0
          • Trigger - Turn on LoopCastBall1 <gen>
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ElectBallz Equal to 2
        • Then - Actions
          • Set BallzPointsBall2[0] = (Position of (Triggering unit))
          • Set BallzPointsBall2[1] = (BallzPoints[0] offset by 100.00 towards ((Real(ElecBallDegree[0])) + 120.00) degrees)
          • Set ElectroCaster = (Triggering unit)
          • Unit - Create 1 Lightning bolts for (Owner of (Triggering unit)) at BallzPointsBall2[1] facing Default building facing degrees
          • Set LBUnit[1] = (Last created unit)
          • Unit - Turn collision for LBUnit[1] Off
          • Set ElecBallDegree[1] = 0
          • Trigger - Turn on LoopCastBall2 <gen>
        • Else - Actions
  • LoopCastBall1
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Set BallzPoints[0] = (Position of ElectroCaster)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ElecBallDegree[0] Equal to 360
        • Then - Actions
          • Set ElecBallDegree[0] = 0
          • Set BallzPoints[2] = (BallzPoints[0] offset by 100.00 towards 0.00 degrees)
        • Else - Actions
          • Set ElecBallDegree[0] = (ElecBallDegree[0] + 3)
          • Set BallzPoints[2] = (BallzPoints[0] offset by 100.00 towards (Real(ElecBallDegree[0])) degrees)
      • Unit - Move LBUnit[0] instantly to BallzPoints[2]
  • LoopCastBall2
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Set BallzPointsBall2[0] = (Position of ElectroCaster)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ElecBallDegree[1] Equal to 360
        • Then - Actions
          • Set ElecBallDegree[1] = 0
          • Set BallzPointsBall2[2] = (BallzPointsBall2[0] offset by 100.00 towards 0.00 degrees)
        • Else - Actions
          • Set ElecBallDegree[1] = (ElecBallDegree[1] + 3)
          • Set BallzPointsBall2[2] = (BallzPointsBall2[2] offset by 100.00 towards (Real(ElecBallDegree[1])) degrees)
      • Unit - Move LBUnit[1] instantly to BallzPointsBall2[2]
Please help?
EDIT: I solved my problem :D, but i will report if i have problems again
 
Last edited:
Status
Not open for further replies.
Top