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

Dealing with special effect orientation (new functions)

Status
Not open for further replies.
Level 13
Joined
Mar 29, 2012
Messages
530
I would like to use special effect as my projectile missile rather than dummy unit. The problem here is about the orientation.
I used this to change the dummy unit orientation:
JASS:
function SetUnitPitch takes unit targetUnit, real pitch returns nothing
    local integer i = R2I(pitch * bj_RADTODEG + 90.5)
    if (179 < i) then
        set i = 179
    elseif (0 > i) then
        set i = 0
    endif
    call SetUnitAnimationByIndex(targetUnit, i)
endfunction

But I would prefer to use the new function:
call BlzSetSpecialEffectOrientation(fx, 0, pitch, roll)
I don't find function to change the facing angle so I assumed that roll is equal to unit facing angle.

I tried testing this function on a single special effect, but I got a problem.
If I set pitch to 90 (with roll = 0), it works.
If I set pitch to 90 (with roll = 90), pitch won't change.
I can only change pitch to anything I want if roll is 0.

Download the test map below to try and see the experiment.
 

Attachments

  • special effect orientation test.w3x
    17.3 KB · Views: 53
Last edited:
WarEditor wrote a vjass function calcing the facing.

JASS:
    // movement is a Vector 3D
    // new is the target position (Vector 3D)
    // fx.position is the fx position (Vector 3D)
    set movement =  new - fx.position
    call fx.setOrientation(movement.angleX,movement.angleY,movement.angleZ)
    // those are the 'angle' method operators from the Vector 3D struct
    method operator angleZ takes nothing returns real
        return Atan2(this.y,this.x)
    endmethod
 
    method operator angleY takes nothing returns real
        local real ix = Math.abs(this.x)
        local real iy = Math.abs(this.y)
        local real px = (1-(iy/(ix+iy)))
        if not (this.x == 0) then
            return -Atan(this.z/this.x)*px
        else
            return 0.
        endif
    endmethod
 
    method operator angleX takes nothing returns real
        local real ix = Math.abs(this.x)
        local real iy = Math.abs(this.y)
        local real py = (1-(ix/(ix+iy)))
   
        if not (this.y == 0) then
            return Atan(this.z/this.y)*py
        else
            return 0.
        endif
    endmethod


I transformed it into normal jass.

call EffectFacing(eff, oldX, oldY, oldZ , newX, newY, newZ) Then the effect should face based on current movement.

JASS:
Credits: Wareditor who wrote the orginal version in vJass.

function angleX takes real x, real y, real z returns real
    local real ix =  RAbsBJ(x)
    local real iy = RAbsBJ(y)
    local real py = (1-(ix/(ix+iy)))
 
    if not (y == 0) then
        return Atan(z/y)*py
    else
        return 0.0
    endif
endfunction
function angleY takes real x, real y, real z returns real
    local real ix =  RAbsBJ(x)
    local real iy = RAbsBJ(y)
    local real px = (1-(iy/(ix+iy)))
    if not (x == 0) then
        return -Atan(z/x)*px
    else
        return 0.0
    endif
endfunction
function angleZ takes real x, real y, real z returns real
    return Atan2(y,x)
endfunction

function EffectFacing takes effect eff, real currentX, real currentY, real currentZ, real targetX, real targetY, real targetZ returns nothing
//calculate the change of x, y, z
    local real x = targetX - currentX
    local real y = targetY - currentY
    local real z = targetZ - currentZ
    call BlzSetSpecialEffectOrientation(eff, angleX(x,y,z), angleY(x,y,z), angleZ(x,y,z))
endfunction

Maybe one of this 2 is of use for you.
Edit: swaped the order of mine.
 
Last edited:
Level 13
Joined
Mar 29, 2012
Messages
530
WarEditor wrote a vjass function calcing the facing.

JASS:
    // movement is a Vector 3D
    // new is the target position (Vector 3D)
    // fx.position is the fx position (Vector 3D)
    set movement =  new - fx.position
    call fx.setOrientation(movement.angleX,movement.angleY,movement.angleZ)
    // those are the 'angle' method operators from the Vector 3D struct
    method operator angleZ takes nothing returns real
        return Atan2(this.y,this.x)
    endmethod
 
    method operator angleY takes nothing returns real
        local real ix = Math.abs(this.x)
        local real iy = Math.abs(this.y)
        local real px = (1-(iy/(ix+iy)))
        if not (this.x == 0) then
            return -Atan(this.z/this.x)*px
        else
            return 0.
        endif
    endmethod
 
    method operator angleX takes nothing returns real
        local real ix = Math.abs(this.x)
        local real iy = Math.abs(this.y)
        local real py = (1-(ix/(ix+iy)))
 
        if not (this.y == 0) then
            return Atan(this.z/this.y)*py
        else
            return 0.
        endif
    endmethod


I transformed it into normal jass.

call EffectFacing(eff, oldX, oldY, oldZ , newX, newY, newZ) Then the effect should face based on current movement.

JASS:
Credits: Wareditor who wrote the orginal version in vJass.

function EffectFacing takes effect eff, real currentX, real currentY, real currentZ, real targetX, real targetY, real targetZ returns nothing
//calculate the change of x, y, z
    local real x = targetX - currentX
    local real y = targetY - currentY
    local real z = targetZ - currentZ
    call BlzSetEffectOrientation(eff, angleX(x,y,z), angleY(x,y,z), angleZ(x,y,z))
endfunction

function angleX takes real x, real y, real z returns real
    local real ix =  RAbsBJ(x)
    local real iy = RAbsBJ(y)
    local real py = (1-(ix/(ix+iy)))
 
    if not (this.y == 0) then
        return Atan(z/y)*py
    else
        return 0.0
    endif
endfunction
function angleY takes real x, real y, real z returns real
    local real ix =  RAbsBJ(x)
    local real iy = RAbsBJ(y)
    local real px = (1-(iy/(ix+iy)))
    if not (this.x == 0) then
        return -Atan(z/x)*px
    else
        return 0.0
    endif
endfunction
function angleZ takes real x, real y, real z returns real
    return Atan2(y,x)
endfunction

Maybe one of this 2 is of use for you.
The x and y seems okay, but my projectile missile seems to have quite slower z speed.

JASS:
set tempX = targetX - sourceX
set tempY = targetY - sourceY
set tempZ = targetZ - sourceZ
// sourceX, sourceY, sourceZ are the last know position.
// targetX, targetY, targetZ are the where the missile is heading.

set dist = ClsR_GetMagnitude2D(tempX, tempY)
set angleZ = ClsR_AngleZ(tempX, tempY)
set anglePointsZ = ClsR_AnglePointsZ(dist, tempZ)

set targetX = sourceX + udg_ClsR_RocketsSpeedBase[udg_ClsR_Level[index]] * Cos(udg_ClsR_Facing[index]) * Cos(udg_ClsR_Pitch[index])
set targetY = sourceY + udg_ClsR_RocketsSpeedBase[udg_ClsR_Level[index]] * Sin(udg_ClsR_Facing[index]) * Cos(udg_ClsR_Pitch[index])
set targetZ = sourceZ + udg_ClsR_RocketsSpeedBase[udg_ClsR_Level[index]] * Sin(udg_ClsR_Pitch[index])
set udg_ClsR_posX[index] = targetX + udg_ClsR_RocketsTurnAcceleration[udg_ClsR_Level[index]] * Cos(angle) * Cos(angleZ)
set udg_ClsR_posY[index] = targetY + udg_ClsR_RocketsTurnAcceleration[udg_ClsR_Level[index]] * Sin(angle) * Cos(angleZ)
set udg_ClsR_posZ[index] = targetZ + udg_ClsR_RocketsTurnAcceleration[udg_ClsR_Level[index]] * Sin(angleZ)

set tempX = udg_ClsR_posX[index] - sourceX
set tempY = udg_ClsR_posY[index] - sourceY
set tempZ = udg_ClsR_posZ[index] - sourceZ

call ClsR_SetEffectOrientation(udg_ClsR_rocketFx[index], tempX, tempY, tempZ)
set udg_ClsR_Pitch[index] = udg_ClsR_newFxOrientationAngle[2]
set udg_ClsR_Facing[index] = udg_ClsR_newFxOrientationAngle[3]

JASS:
function ClsR_SetEffectOrientation takes effect fx, real x, real y, real z returns nothing
    local real ax
    local real ay
    local real az
    local real px
    local real py
   
    if x == 0 and y == 0 then
        if z > 0 then
            set ax = -bj_PI*0.5
        else 
            set ax = bj_PI*0.5
        endif
    elseif z != 0 then
        set ax = ClsR_RAbs(x)
        set ay = ClsR_RAbs(y)
        set px = ax / (ax + ay)
        set py = 1 - px
        if y == 0 then
            set ax = 0
        else
            set ax = Atan(z/y)*py
        endif
        if x == 0 then
            set ay = 0
        else 
            set ay = -Atan(z/x)*px
        endif
    endif
    set az = Atan2(y, x)
    call BlzSetSpecialEffectOrientation(fx, ax, ay, az)
    set udg_ClsR_newFxOrientationAngle[1] = ax
    set udg_ClsR_newFxOrientationAngle[2] = ay
    set udg_ClsR_newFxOrientationAngle[3] = az
endfunction
 
Last edited:
Level 13
Joined
Mar 29, 2012
Messages
530
Beg your pardon Ofel, but can you elaborate your solution for us?
This is the solution I found:
JASS:
//Credit goes to Wareditor
function SetEffectOrientation takes effect fx, real x, real y, real z returns nothing
    local real ax
    local real ay
    local real az
    local real px
    local real py
   
    if x == 0 and y == 0 then
        if z > 0 then
            set ax = -bj_PI*0.5
        else 
            set ax = bj_PI*0.5
        endif
    elseif z != 0 then
        set ax = RAbsBJ(x)
        set ay = RAbsBJ(y)
        set px = ax / (ax + ay)
        set py = 1 - px
        if y == 0 then
            set ax = 0
        else
            set ax = Atan(z/y)*py
        endif
        if x == 0 then
            set ay = 0
        else 
            set ay = -Atan(z/x)*px
        endif
    endif
    set az = Atan2(y, x)
    
    // ax = yaw angle
    // ay = pitch angle
    // az = roll angle
    call BlzSetSpecialEffectOrientation(fx, ax, ay, az)
endfunction

In my case:
JASS:
set vectorX = moveX - posX
set vectorY = moveY - posY
set vectorZ = moveZ - posZ
// (moveX, moveY, moveZ) is where the effect is going to move.
// (posX, posY, posZ) is the current position.

call SetEffectOrientation(fx, vectorX, vectorY, vectorZ)
 
Status
Not open for further replies.
Top