ok i made this system:
JASS:
library Spin3D
struct Spin extends array
private static constant real timeout = 0.03125
private static thistype counter = 0
private static thistype firstToRecycle = 0
private thistype nextToRecycle
private boolean isAllocated
private static thistype first = 0
private thistype next
private unit spinner
private unit pivotUnit
real xOffset
real yOffset
real zOffset
private real sin_a
private real cos_a
private real sin_b
private real cos_b
private real sin_t
private real cos_t
private real x
private real y
private static method allocate takes nothing returns thistype
local thistype this
if firstToRecycle == 0 then
set counter = counter+1
set this = counter
else
set this = thistype.firstToRecycle
set thistype.firstToRecycle = this.nextToRecycle
set this.nextToRecycle = 0
endif
set next = thistype.first
set thistype.first = this
return this
endmethod
public static method add takes real azimuthAngle, real elevationAngle, unit spinner, real spinsPerSec, real distance, unit pivotUnit, real xOffset, real yOffset, real zOffset returns thistype
local real theta
local thistype this = thistype.allocate()
set this.spinner = spinner
set this.pivotUnit = pivotUnit
set theta = 2*bj_PI*(thistype.timeout/spinsPerSec)
set this.cos_t = Cos(theta)
set this.sin_t = Sin(theta)
set this.cos_a = Cos(elevationAngle*bj_DEGTORAD)
set this.sin_a = Sin(elevationAngle*bj_DEGTORAD)
set this.cos_b = Cos(azimuthAngle*bj_DEGTORAD)
set this.sin_b = Sin(azimuthAngle*bj_DEGTORAD)
set this.x = distance // this.cos_a*this.cos_b*distance
set this.y = 0 // -this.sin_b*distance
set this.xOffset = xOffset
set this.yOffset = yOffset
set this.zOffset = zOffset
call UnitAddAbility (spinner, 'Amrf')
call UnitRemoveAbility(spinner, 'Amrf')
call SetUnitPathing (spinner, false)
return this
endmethod
private method deallocate takes nothing returns nothing
set first = this.next
set this.next = 0
set nextToRecycle = thistype.firstToRecycle
set thistype.firstToRecycle = this
endmethod
public method destroy takes nothing returns nothing
set cos_t = 0
set sin_t = 0
set cos_a = 0
set sin_a = 0
set cos_b = 0
set sin_b = 0
set x = 0
set y = 0
set xOffset = 0
set xOffset = 0
set zOffset = 0
set spinner = null
set pivotUnit = null
call this.deallocate()
endmethod
private static method doSpins takes nothing returns nothing
local real xt
local thistype this = first
loop
exitwhen this == 0
set xt = cos_t*x - sin_t*y
set y = sin_t*x + cos_t*y
set x = xt
call SetUnitX(spinner, GetUnitX(pivotUnit) + xOffset + ( cos_a*cos_b*x - sin_b*y))
call SetUnitY(spinner, GetUnitY(pivotUnit) + yOffset + ( cos_a*sin_b*x + cos_b*y))
call SetUnitFlyHeight(spinner, GetUnitFlyHeight(pivotUnit) + ( sin_a*x + zOffset),0)
set this = this.next
endloop
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), timeout, true, function thistype.doSpins)
set thistype(0).next = 0
set thistype(0).nextToRecycle = 0
endmethod
endstruct
endlibrary
private static constant real timeout defines the frequency of the moves
the closer to 0 it is, the swifter the move looks but also the worse the performance is
explanation:
The system allows you to to spin units around other units 3D-wise with offset
This method makes a unit spin:
JASS:
Spin spin = Spin3D.add(azimuthAngle, elevationAngle, spinner, spinsPerSec,
distance, pivotUnit, xOffset, yOffset, zOffset)
The parameters:
spinner is the unit thats being spinned around a point
the coordinates of the pivotUnit added to the 3 offset coordinates make the spin point (xOffset = 0, yOffset = 0, zOffset = 100 will make the spinner spin around a point 100 units above the pivotUnit, which we call the spinpoint)
spinsPerSec is self explanatory (if you make it negative, it will spin into the other direction)
distance is the distance to the spinpoint
now for the 2 parameters that make the 3D spin: elevationAngle and azimuthAngle
imagine you look at the spinpoint from above (vertically)
then imagine a circle around the spinpoint with radius = distance
the spinner is spinning clockwise along this circle when azimuthAngle and elevationAngle are both 0
when you put other values into azimuthAngle and elevationAngle the circles orientation will change:
we call the elevationPoint the right border of the circle
the azimuthAngle now moves the elevationPoint anti-clockwise on the circle
the elevationAngle grabs the circle at the elevationPoint and lifts it into the air, so that the other side of the circle goes downwards
i've included a testmap
credits to Frankster, who created the fireball model used in the testmap
EDIT: changed local thistype this = 0 to this = 1 in method doSpins