Operating special effect orientation

Level 13
Mar 29, 2012
Hello guys

I'm back wrestling with special effect, now with the orientation.

I used this library:
library OrientEffect

//OrientEffect by Cyclotrutan

//This function sets the orientation of a special effect such that it points towards the input
//direction. The special effect model must be pointing towards x-direction by default, such as
//most missile models. It will not work on vertically oriented effects such as StarfallCaster.

//Using the standard definition of yaw, pitch, and roll (which is different from Blizzard's
//definition), the special effect's intrinsic rotation will correspond to roll = 0. As a
//result, there is a discontinuity when the special effect is oriented towards the z-axis.

//There are three possible input functions:

//OrientEffectVector(whichEffect,x,y,z) orients the special effect in the direction of a
//vector with arbitrary length.

//OrientEffectCoordinates(whichEffect,x,y,z) subtracts the special effect's own position and
//orients the special effect in the direction of the input coordinates on the map.

//OrientEffectAngle(whichEffect,phi,theta) orients the special effect towards the azimuthal
//angle phi ranging from 0 to 2pi and the polar angle theta ranging from -pi/2 to pi/2.


private function OrientEffect takes effect whichEffect, real x, real y, real z returns nothing
    local real norm
    local real yaw //normal people yaw, blizzard roll
    local real pitch
    local real roll //normal people roll, blizzard yaw
    local real N
    local real cp

    set norm = 1.00001*SquareRoot(x*x + y*y + z*z)

    if norm == 0 then

    set x = x/norm
    set y = y/norm
    set z = z/norm

    set N = SquareRoot(x*x + y*y)

    if N == 0 then
        if z > 0 then
            call BlzSetSpecialEffectOrientation( whichEffect , 0 , -bj_PI/2 , 0 )
            call BlzSetSpecialEffectOrientation( whichEffect , 0 , bj_PI/2 , 0 )

    if y >= 0 then
        set pitch = -Asin(x*z/N)
        set cp = Cos(pitch)
        set roll = Asin(y*z/(N*cp))
        set yaw = Acos(x/cp)
        set pitch = Asin(x*z/N) + bj_PI
        set cp = Cos(pitch)
        set roll = -Asin(y*z/(N*cp)) + bj_PI
        set yaw = Acos(x/cp)

    call BlzSetSpecialEffectOrientation( whichEffect , roll , pitch , yaw )

function OrientEffectVector takes effect whichEffect, real x, real y, real z returns nothing
    call OrientEffect(whichEffect , x , y , z)

function OrientEffectCoordinates takes effect whichEffect, real x, real y, real z returns nothing
    call OrientEffect(whichEffect , x - BlzGetLocalSpecialEffectX(whichEffect) , y - BlzGetLocalSpecialEffectY(whichEffect) , z - BlzGetLocalSpecialEffectZ(whichEffect))

function OrientEffectAngle takes effect whichEffect, real phi, real theta returns nothing
    call OrientEffect(whichEffect , Cos(phi)*Cos(theta) , Sin(phi)*Cos(theta) , Sin(theta))

And have these three elements in variables: roll, pitch, and yaw.

I wanted to make the effect turn with specific TURN_RATE.
So far... this:
set angle = GetAngleXY(vec.vx[1], vec.vy[1])
set angleZ = GetAnglePointsZ(GetDistance2D(vec.vx[1], vec.vy[1]), vec.vz[1])
// vec.vx[1] -> [target x] - [current position x]
// vec.vy[1] -> [target y] - [current position y]

set .roll = AbsRad(.roll + TURN_RATE * Cos(angle) * Cos(angleZ))
set .pitch = AbsRad(.pitch + TURN_RATE * Sin(angle) * Cos(angleZ))
//AbsRad is used to keep the value between 0-2π (full circle angle)

call OrientEffectAngle(.missile, .roll, .pitch)
But the effect just spinning around smoothly.
Level 36
Feb 27, 2007
Blizzard fixed their angle definitions in a patch so you can use the pitch/yaw/roll natives directly. No need for this library, which will instead rotate in incorrect ways since the math is different.

Why are you multiplying two wines/cosines together? Your angle should just go up by TURN_RATE*timerperiod every interval. Those angles shouldn’t be involved at all.