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

Jump math

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
I'm trying to create an ability where the unit pops up from a large water spout and is shot in the air, landing shortly after.

(I wanted to find a way to make the unit sink underground just before, but I don't think WC3's engine allows that)

The way I have it set up is with a timer that periodically increases the units fly height at a decreasing value til it hits its apex. It then descends at an increasing rate until it reaches it's default fly height.

I don't know the formula for a smooth Jump animation, and have tried multiple ones. Can someone pass that on to me?

(The unfinished code in question:)
Code:
scope WaterRush initializer Init

globals
    private constant integer SPELLID    = 'A00M'
    private constant real TICK        = 0.035
endglobals

struct Data

    unit caster
    effect fx

    real rate = 2

    real x
    real y

    real xdir
    real ydir

    boolean transported = false
    boolean descending = false

    static method sinkPeriodic takes nothing returns nothing
     local thistype this = GetTimerData(GetExpiredTimer())
        if not .transported then
            call SetUnitX(.caster, .x)
            call SetUnitY(.caster, .y)
            set .transported = true
        elseif .transported and GetUnitFlyHeight(.caster) < 450 and not .descending then
            set .rate = .rate - 0.5
            call SetUnitFlyHeight(.caster, GetUnitFlyHeight(.caster)+(.rate*.rate), 1000)
            if IsTerrainWalkable( GetWidgetX(.caster)-1, GetWidgetY(.caster)-1 ) then
                call SetUnitX(.caster, GetWidgetX(.caster)-.xdir)
                call SetUnitY(.caster, GetWidgetY(.caster)-.ydir)
            endif
            if GetUnitFlyHeight(.caster) >= 450 then
                set .descending = true
            endif
        elseif .descending and GetUnitFlyHeight(.caster) <= GetUnitDefaultFlyHeight(.caster) then
            call ReleaseTimer(GetExpiredTimer())
            set .caster = null
            call .destroy()
        elseif .descending then
            set .rate = .rate + 0.5
            call SetUnitFlyHeight(.caster, GetUnitFlyHeight(.caster)-(.rate*.rate), 1000)
            if IsTerrainWalkable( GetWidgetX(.caster)-1, GetWidgetY(.caster)-1 ) then
                call SetUnitX(.caster, GetWidgetX(.caster)-.xdir)
                call SetUnitY(.caster, GetWidgetY(.caster)-.ydir)
            endif
        else
        endif
    endmethod

    static method actions takes nothing returns nothing
     local thistype this = thistype.allocate()
        if GetSpellAbilityId() == SPELLID then
            set .caster = GetTriggerUnit()
            set .x = GetSpellTargetX()
            set .y = GetSpellTargetY()
            set .xdir = GetRandomReal(-2, 2)
            set .ydir = GetRandomReal(-2, 2)
            if UnitAddAbility(.caster, 'Amrf') then
                call UnitRemoveAbility(.caster, 'Amrf')
            endif
            call SetUnitPathing(.caster,false)
            call TimerStart(NewTimerEx(this), TICK, true, function thistype.sinkPeriodic )
        endif
    endmethod

endstruct

private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction( t, function Data.actions )
set t = null
endfunction

endscope
 
Status
Not open for further replies.
Top