1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Weave light to take you to your highest hopes - the 6th Special Effect Contest is here!
    Dismiss Notice
  4. Lead your forces to battle in the 15th Techtree Contest. The call is yours, commander!
    Dismiss Notice
  5. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Advanced homing projectile

Discussion in 'World Editor Help Zone' started by Ofel, Feb 23, 2019.

  1. Ofel

    Ofel

    Joined:
    Mar 29, 2012
    Messages:
    431
    Resources:
    10
    Spells:
    10
    Resources:
    10
    How to make a projectile to properly home-in to a target unit?
    My problem is about the mathematical calculation.

    Currently, I've managed to make the projectile move to a 3D point towards its facing direction with offset by [speed base] plus offset by [turn acceleration] towards the target unit --> on every frame update (32 iteration per second). But sometimes, if the projectile missed the target unit, it will just spin around the target because maybe the [turn acceleration] is too low to turn the projectile towards target.
    If I set [turn acceleration] to a higher value, the projectile would not have a good curve.
    How do I achieve this?

    Code (vJASS):
    set vectorX = .targetX - .posX
    set vectorY = .targetY - .posY
    set vectorZ = .targetZ - .posZ

    set dist = GetDistance2D(vectorX, vectorY)
    set angleZ = AngleZ(vectorX, vectorY)
    set anglePointsZ = AnglePointsZ(dist, vectorZ)

    set .posX = ((.posX + ROCKETS_SPEED_BASE[.node.level] * Cos(.roll) * Cos(.pitch))) + ROCKETS_TURN_ACCELERATION[.node.level] * Cos(angleZ) * Cos(anglePointsZ)
    set .posY = ((.posY + ROCKETS_SPEED_BASE[.node.level] * Sin(.roll) * Cos(.pitch))) + ROCKETS_TURN_ACCELERATION[.node.level] * Sin(angleZ) * Cos(anglePointsZ)
    set .posZ = ((.posZ + ROCKETS_SPEED_BASE[.node.level] * Sin(.pitch))) + ROCKETS_TURN_ACCELERATION[.node.level] * Sin(anglePointsZ)

    set vectorX = .posX - .lastPosX
    set vectorY = .posY - .lastPosY
    set vectorZ = .posZ - .lastPosZ

    call SetEffectOrientation3D(vectorX, vectorY, vectorZ)
    set .pitch = AnglePointsZ(GetDistance2D(vectorX, vectorY), vectorZ)

    Code (vJASS):
    function GetDistance2D takes real x, real y returns real
        return SquareRoot(x * x + y * y)
    endfunction

    function GetDistance3D takes real x, real y, real z returns real
        return SquareRoot(x * x + y * y + z * z)
    endfunction

    function AngleZ takes real x, real y returns real
        return Atan2(y, x)
    endfunction

    function AnglePointsZ takes real distance2D, real z returns real
        return Atan2(z, distance2D)
    endfunction

    function GetTerrainZ takes real x, real y returns real
        call MoveLocation(zLoc, x, y)
        return GetLocationZ(zLoc)
    endfunction

    function GetUnitTerrainZ takes unit targetUnit, real x, real y returns real
        local real height
       
        set height = GetUnitFlyHeight(targetUnit) + TARGET_CHEST_HEIGHT
       
        return height + GetTerrainZ(x, y)
    endfunction

    function GetDistanceToUnit3D takes real x, real y, real z, unit targetUnit returns real
        local real targetX = GetUnitX(targetUnit)
        local real targetY = GetUnitY(targetUnit)
        local real targetZ = GetUnitTerrainZ(targetUnit, targetX, targetY)
       
        return GetDistance3D(targetX-x, targetY-y, targetZ-z)
    endfunction

    function SetEffectOrientation3D takes real x, real y, real z returns nothing
        // by Wareditor
        local real ax
        local real ay
        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 .pitch = ay
        set .roll = Atan2(y, x)
       
        call BlzSetSpecialEffectOrientation(.rocket, ax, .lastPitch, .roll)
        call BlzSetSpecialEffectPitch(.rocket, .pitch)
        set .lastPitch = .pitch
    endfunction
     


    My current idea:
    I might make the [turn acceleration] to have dynamic value, for example, the farther the projectile is from the target unit, [turn acceleration] will accordingly increase. But I have no idea how to achieve this, mathematically.