HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

MakeUnitHover - Smoothness Problems

10-12-2008, 05:51 AM#1
Vestras
Collapse JASS:
library MakeUnitHover

private keyword Data

globals
    private constant integer ENABLE_FLY='Amrf'
    // The Raven Form ability which enables flying
    private constant real INTERVAL=0.03
    // The timer interval. 0.03 is suggested, less can cause lag
    private constant real DIVIDE=100
    // d.z is divided with this
    private constant real RATE=5000
    // The "time" the unit is about getting from and to the ground/fly height
// Necessary globals
private Data array D
private integer N=0
private timer T=CreateTimer()
private location l=Location(0,0) // For GetUnitZ()
endglobals

//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//! Real Snippet Code! 
//! Don't touch if you don't know what you are doing!
//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING

private struct Data
    unit swayer
    real z
    real max
    real min
    real height
    boolean hasReachedMax
endstruct

private function Parabola takes real dist, real maxdist, real curve returns real
    local real t=(dist*2)/maxdist-1
    return (-t*t+1)*(maxdist/curve)
endfunction

private function GetUnitZ takes unit whichUnit returns real
    call MoveLocation(l,GetUnitX(whichUnit),GetUnitY(whichUnit))
    return GetLocationZ(l)+GetUnitFlyHeight(whichUnit)
endfunction

private function Callback takes nothing returns nothing
    local Data d
    local integer i=N
    local real swayHeight=d.max-d.min-GetUnitZ(d.swayer)
    local real currentTime=RAbsBJ(((d.max-d.min)+1)/(d.max+1))
    local real totalTime=1
    local real zInc=RAbsBJ(Parabola(currentTime,totalTime,swayHeight)-GetUnitFlyHeight(d.swayer))
    call BJDebugMsg(R2S(zInc))
    loop
        exitwhen i<=0
        set d=D[i]
            if (d.z<d.min) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)+zInc,0)
                set d.hasReachedMax=false
            elseif (d.z>d.max) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)-zInc,0)
                set d.hasReachedMax=true
            elseif (d.z>d.min and d.hasReachedMax==false) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)+zInc,0)
            elseif (d.z>d.min) and (d.hasReachedMax==true) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)-zInc,0)
            endif
        set i=i-1
    endloop
endfunction

function MakeUnitHover takes unit whichUnit, real max, real min returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set d.height=GetUnitFlyHeight(whichUnit)
    call UnitAddAbility(whichUnit,ENABLE_FLY)
    call SetUnitFlyHeight(whichUnit,min,RATE)
    set d.z=min-1
    call UnitRemoveAbility(whichUnit,ENABLE_FLY)
    set d.max=max
    set d.min=min
    set d.hasReachedMax=false
    set N=N+1
    set D[N]=d
    if N==1 then
        call TimerStart(T,INTERVAL,true,function Callback)
    endif
endfunction

function StopUnitHover takes unit whichUnit returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i<=0
        set d=D[i]
        if d.swayer==whichUnit then
            if d.swayer==null then
                call BJDebugMsg("|cffff0000MakeUnitSway|r: invalid unit.")
                return
            endif
            set D[i]=D[N]
            set N=N-1
            if N==0 then
                call PauseTimer(T)
            endif
            call SetUnitFlyHeight(d.swayer,d.height,RATE)
            call d.destroy()
        endif
        set i=i-1
    endloop
endfunction

private function TimedCallback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i<=0
        set d=D[i]
        call StopUnitHover(d.swayer)
        set D[i]=D[N]
        set N=N-1
        set i=i-1
    endloop
    call DestroyTimer(GetExpiredTimer())
endfunction

function MakeUnitHoverTimed takes unit whichUnit, real max, real min, real duration returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set N=N+1
    set D[N]=d
        call MakeUnitHover(whichUnit,max,min)
        call TimerStart(CreateTimer(),duration,false,function TimedCallback)
endfunction

endlibrary

That's my code... Somehow, the debug msgs doesn't show, and the height stuff doesn't apply... (In the Callback function)

Ideas?
10-12-2008, 06:08 AM#2
Tide-Arc Ephemera
Are you using an event or a condition that's impossible to meet?
10-12-2008, 06:30 AM#3
Vestras
Quote:
Originally Posted by Tide-Arc Ephemera
Are you using an event or a condition that's impossible to meet?

No, I fixed the first one...
Okay, another problem - now the Hover guy goes from 0.00 height to 90.00 height extremely fast, then down to 0.00 again... endless loop.

Collapse JASS:
library MakeUnitHover

private keyword Data

globals
    private constant integer ENABLE_FLY='Amrf'
    // The Raven Form ability which enables flying
    private constant real INTERVAL=0.03
    // The timer interval. 0.03 is suggested, less can cause lag
    private constant real DIVIDE=100
    // d.z is divided with this
    private constant real RATE=5000
    // The "time" the unit is about getting from and to the ground/fly height
// Necessary globals
private Data array D
private integer N=0
private timer T=CreateTimer()
private location l=Location(0,0) // For GetUnitZ()
endglobals

//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//! Real Snippet Code! 
//! Don't touch if you don't know what you are doing!
//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING

private struct Data
    unit swayer
    real z
    real max
    real min
    real height
    boolean hasReachedMax
endstruct

private function Parabola takes real dist, real maxdist, real curve returns real
    local real t=(dist*2)/maxdist-1
    return (-t*t+1)*(maxdist/curve)
endfunction

private function GetUnitZ takes unit whichUnit returns real
    call MoveLocation(l,GetUnitX(whichUnit),GetUnitY(whichUnit))
    return GetLocationZ(l)+GetUnitFlyHeight(whichUnit)
endfunction

private function Callback takes nothing returns nothing
    local Data d
    local integer i=N
    local real swayHeight
    local real currentTime
    local real totalTime=1
    local real zInc
    loop
        exitwhen i<=0
        set d=D[i]
        set swayHeight=d.max-d.min-GetUnitZ(d.swayer)
        set currentTime=RAbsBJ(((d.max-d.min)+1)/(d.max+1))
        set zInc=RAbsBJ(Parabola(currentTime,totalTime,swayHeight)-GetUnitFlyHeight(d.swayer))
        call BJDebugMsg(R2S(zInc))
            if (zInc<d.min) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)+zInc,0)
                set d.hasReachedMax=false
            elseif (zInc>d.max) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)-zInc,0)
                set d.hasReachedMax=true
            elseif (zInc>d.min and d.hasReachedMax==false) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)+zInc,0)
            elseif (zInc>d.min) and (d.hasReachedMax==true) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,GetUnitFlyHeight(d.swayer)-zInc,0)
            endif
        set i=i-1
    endloop
endfunction

function MakeUnitHover takes unit whichUnit, real max, real min returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set d.height=GetUnitFlyHeight(whichUnit)
    call UnitAddAbility(whichUnit,ENABLE_FLY)
    call SetUnitFlyHeight(whichUnit,min,RATE)
    set d.z=min-1
    call UnitRemoveAbility(whichUnit,ENABLE_FLY)
    set d.max=max
    set d.min=min
    set d.hasReachedMax=false
    set N=N+1
    set D[N]=d
    if N==1 then
        call TimerStart(T,INTERVAL,true,function Callback)
    endif
endfunction

function StopUnitHover takes unit whichUnit returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i<=0
        set d=D[i]
        if d.swayer==whichUnit then
            if d.swayer==null then
                call BJDebugMsg("|cffff0000MakeUnitSway|r: invalid unit.")
                return
            endif
            set D[i]=D[N]
            set N=N-1
            if N==0 then
                call PauseTimer(T)
            endif
            call SetUnitFlyHeight(d.swayer,d.height,RATE)
            call d.destroy()
        endif
        set i=i-1
    endloop
endfunction

private function TimedCallback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i<=0
        set d=D[i]
        call StopUnitHover(d.swayer)
        set D[i]=D[N]
        set N=N-1
        set i=i-1
    endloop
    call DestroyTimer(GetExpiredTimer())
endfunction

function MakeUnitHoverTimed takes unit whichUnit, real max, real min, real duration returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set N=N+1
    set D[N]=d
        call MakeUnitHover(whichUnit,max,min)
        call TimerStart(CreateTimer(),duration,false,function TimedCallback)
endfunction

endlibrary
Attached Files
File type: w3mMakeUnitHover Smooth.w3m (19.2 KB)
10-12-2008, 06:35 AM#4
Tide-Arc Ephemera
If it's an endless loop, doesn't that kinda imply there IS a condition somewhere that's impossible to meet?
10-12-2008, 07:35 AM#5
Vestras
Quote:
Originally Posted by Tide-Arc Ephemera
If it's an endless loop, doesn't that kinda imply there IS a condition somewhere that's impossible to meet?

Possibly.