Just Another Parabola Problem

Status
Not open for further replies.
Level 9
Joined
May 27, 2006
Messages
498
Right now I'm working on a "jump" for my map. The thing itself isn't that hard, I can make the unit move quite realistically over a flat terrain, or when there is a cliff going up or down.

But my problem is, what if there is an obstacle on the parabolas' path? Ie. terrain level at the start and end points is equal, but there is a lone cliff at some point, which makes the unit go higher due to the way Warcraft mechanics work.

In other words (or pictures);

859463flat.png
571525flatdown.png
.
637248flatup.png
866373flatupflat.png

Is it even remotely possible to "compensate" for the elevation and make the unit move naturally over such cliffs?

Oh, and regarding code, here are my failourus attempts (only the problematic part);
JASS:
function Knock_Child takes nothing returns nothing
    (...)
    local real z = GetLocationZ(p)
    local real z2 = GetLocationZ(p2)
    (...)
        if z > z2 then
            set comp = z - z2
            call SetUnitFlyHeight(u, h + comp, ((h + comp) / 0.1))
        else
            set comp = z2 - z
            call SetUnitFlyHeight(u, h + comp, ((h + comp) / 0.1))
        endif
    (...)
endfunction
h is flying height, comp is the difference between cliff heights

In theory, rate of (h + comp) / 0.1 should make the unit go higher/lower with 0.1 sec delay, making it look more smooth... But in practice it doesn't work, or the change is unnoticeable.
(I tried instantly changing units' flying height, it didn't work either)

I don't know, maybe it's my logic failing me in the time of need.
 
Last edited:
You really haven't shown enough code to provide any useful information. It is possible to use a unit with movement type Foot to move him properly over the terrain without any glitches in its height - flying units are impossible to deal with perfectly.

Please post more.
 
Well, the unit has that movement type, but it still gets affected by terrain. Tho, of course, Im giving it the crow form ability, so that I could change it's flying height, so maybe this classifies it as a flying unit.

I've been using other jump systems as examples while making the one I use, and all of them had the same problem, to bigger or lesser extent.

But, well, whatever.
JASS:
//Dark Gandalf's formula
function ParabolaZEx takes real x, real d, real h, real z0, real zd returns real
    return 4 * h * x * (d -x) / (d * d) + x * (zd-z0) / d + z0
endfunction

function Stop takes nothing returns nothing  //failed attempt to make the unit stop on cliffs that are too high
    call TriggerSleepAction(0.05) // waits a while, so that the unit actually "touches" the cliff
    set udg_bool[8] = true
endfunction

function KnockChild takes nothing returns nothing
    local unit u = udg_Player[21] //using globals to carry required information from "parent" function
    local location p = GetUnitLoc(u) //too lazy to use coords and polar projection "native"
    local location p2 = PolarProjectionBJ(p, 12, AngleBetweenPoints(udg_TempPoint3, p))
    local real z = GetLocationZ(p)
    local real z2 = GetLocationZ(p2)
    local real comp = 0
    local real h
    call RemoveLocation(udg_TempPoint3) // on the first run, this variable stores location of caster in order to find
    set udg_TempPoint3 = GetUnitLoc(u) // the proper angle to move the unit, later it stores "old" location of the unit being moved
    set udg_knock_dist[1] = udg_knock_dist[1] + 12.00
    set h = ParabolaZEx(udg_knock_dist[1], (600.0 * udg_knock_dist[2]), (150.0 * udg_knock_dist[2]), 0, 0) //probably i misunderstood the formula (the two zeros at the end)
    if udg_bool[8] == false then //if unit haven't met any cliff that is too high, keep it moving
        call SetUnitFlyHeight(u, h, 0.00)
        call SetUnitX(u, GetLocationX(p2))
        call SetUnitY(u, GetLocationY(p2))
        if z > z2 then
            set comp = z - z2
            call SetUnitFlyHeight(u, h + comp, ((h + comp) / 0.1))
        else
            set comp = z2 - z
            if comp > GetUnitFlyHeight(u) then // if cliff in front of unit is higher than it's flying height, attempt to stop the unit, as if it hit the obstacle
                call Stop()
            endif
            call SetUnitFlyHeight(u, h + comp, ((h + comp) / 0.1))
        endif
    endif
    call RemoveLocation(p)
    call RemoveLocation(p2)
    set u = null
endfunction

function Knock takes unit u, unit c returns nothing
    local timer tmr = CreateTimer()
    local timer t = CreateTimer()
    local location p = GetUnitLoc(u)
    local location p2 = GetUnitLoc(c)
    local location p3 = PolarProjectionBJ(p, 600, AngleBetweenPoints(p2, p))
    local real sz = GetLocationZ(p)
    local real fz = GetLocationZ(p3)
    local real w = 1.00
    set udg_bool[8] = false
    if sz >= fz then
        set w = w + ((sz-fz)*0.002) // a factor value, i use it to make the unit move longer and further when being knocked from a higher terrain towards lower terrain
    else
        set w = w - ((fz-sz)*0.002)
    endif
    call SetUnitPathing( u, false )
    call UnitAddAbility(u, 'Amrf')
    call UnitRemoveAbility(u, 'Amrf')
    call PauseUnit(u, true)
    set udg_knock_dist[2] = w // globals used to carry required information to the "child" function
    set udg_Player[21] = u
    set udg_TempPoint3 = GetUnitLoc(c)
    call TimerStart(tmr, w, false, null)
    call TimerStart(t, 0.02, true, function KnockChild)
    loop
        exitwhen TimerGetRemaining(tmr) == 0
        call TriggerSleepAction(0)
    endloop
    call PauseUnit(u, false)
    call SetUnitPathing( u, true )
    call RemoveLocation(udg_TempPoint3)
    call RemoveLocation(p)
    call RemoveLocation(p2)
    call RemoveLocation(p3)
    call DestroyTimer(tmr)
    call DestroyTimer(t)
    set udg_Player[21] = null
    set udg_knock_dist[1] = 0
endfunction
variables;
udg_knock_dist[1] - distance travelled
udg_knock_dist[2] - factor dependant on start and end point heights, modifies parabolas' height and max distance
udg_bool[8] - used to stop unit movement with a slight delay
Yeah, i know, no vJASS, having some problems installing it
 
I do not find the thread I have in mind at the moment where this was discussed but afaik the unit should have "none" as movement type and maybe Graphic - Elevation Points and Radius of zero to not be affected when you move it via SetUnitX/Y.

edit: And the unit should not walk normally meanwhile.
 
Status
Not open for further replies.
Back
Top