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


    Mar 29, 2012
    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)

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

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

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

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

    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)

    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)

    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
                set ax = bj_PI*0.5
        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
                set ax = Atan(z/y)*py
            if x == 0 then
                set ay = 0
                set ay = -Atan(z/x)*px
        set .pitch = ay
        set .roll = Atan2(y, x)
        call BlzSetSpecialEffectOrientation(.rocket, ax, .lastPitch, .roll)
        call BlzSetSpecialEffectPitch(.rocket, .pitch)
        set .lastPitch = .pitch

    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.