HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Jump Spell

03-29-2009, 07:04 AM#1
wraithseeker
Collapse JASS:
function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private function fly takes nothing returns nothing
local unit u  = GetTriggerUnit()
call UnitAddAbility(//...storm crow form)
call UnitRemoveAbility(//...storm crow form)
//what now?
endfunction

Handwritten, expect errors.

How do I make a jump spell? I am using speed as the movement and not distance meaning
Collapse JASS:
set x = cx + d.speed * d.cos
set y = cy + d.speed * d.sin
set d.speed = d.speed - d.decrement
 if d.speed <= 0 then
// taken out, not needed to know.

I don't understand the jump formula much and don't know how to do it using the speed factor.
03-29-2009, 08:20 AM#2
0zyx0
You don't have to, and shouldn't use a variable speed. Use a constant speed, it is more realistic physically, and easier to code. In the ParabolaZ function, h = height of parabola, d = total length of parabola, and x = where in the parabola the z coordinate should come from. For example, ParabolaZ(100, 50, 25) will give the result 100, because the parabola is 100 high, and 50 long, and since the highest point is at 50/2=25, putting 25 as x will result in the highest possible value of the curve.

To do the actual movement, you have to use a loop, or even better, a timer. Since using a decreasing speed is bad, you would have to specify either the total time of the jump, or the length of it. I can give you an example script, but it will take some time.
03-29-2009, 09:27 AM#3
wraithseeker
How do you get the Z coordinate?
03-29-2009, 09:49 AM#4
Viikuna-
function ParabolaZ returns real
03-29-2009, 09:57 AM#5
wraithseeker
Collapse JASS:
set d.distance = -1 * speed * speed / (2 * -decrement / TIME)

Collapse JASS:
call SetUnitFlyHeight(u,ParabolaZ(500,d.distance,d.speed),0)

Doesn't work.
03-29-2009, 10:44 AM#6
0zyx0
Collapse JASS:
private constant function Interval takes nothing returns real
    return 0.05
endfunction

private function GetDistance takes real x1, real y1, real x2, real y2
    return SquareRoot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
endfunction

private function GetAngle takes real x1, real y1, real x2, real y2 returns real
    return Atan2(y2-y1, x2-x1)
endfunction

private function ParabolaZ takes real h, real d, real x returns real
    return (4 * h / d) * (d - x) * (x / d)
endfunction


function Jump takes unit u, real x, real y, real speed returns nothing
    local JumpData d = JumpData.create()
    local real distance = GetDistance(GetUnitX(u), GetUnitY(u), x, y)
    local real distint =   (distance/speed)*interval()
    local integer movecount = R2I(distint/distance)
    local real angle = GetAngle(GetUnitX(u), GetUnitY(u), x, y)
    local real dx = Cos(angle)*distint
    local real dy = Sin(angle)*distint
    local integer i = 0
    
    //Add the storm crow ability to the unit here
    
    loop
        exitwhen i == movecount
        call SetUnitFlyHeight(u, ParabolaZ(500, distance, distint*i)
        call SetUnitY(u, GetUnitY(u)+dy)        
        call SetUnitX(u, GetUnitX(u)+dx)
        set i = i+1
        call PolledWait(Interval())
    endloop

    //Remove the storm crow ability from the unit here
endfunction

This should describe how to use it. You can steal this script from me if you want to, but it is not very good, since PolledWait() is very inaccurate at short intervals. It could be replaced with a timer, but that would require a much more complex script.
03-29-2009, 10:59 AM#7
wraithseeker
Actually, what I want is the knockedback unit to fly, you look like you know quite alot about jumping, throwing the whole code in here for you to see.

Collapse JASS:
//Formula to calculate Distance = -1 * V * V / (2 * A / Interval)  Where variable V is speed and A is decrement.//
//                            Note! V must be positive and A must be negative!!!!                             //
//******************************************************************************
//*                     Formula to calculate the distance                      *
//*                      - 1 * V * V / ( 2 * A / Interval)                     *
//*              Variable V = The amount of speed the knockedback unit has     *
//*              Variable A = The amount of speed reduced per Interval         *
//*       Variable Interval = Located at the top of the Knockback System       *
//*                                                                            *
//*                   Some things to note about them                           *
//*                  Variable A must be a positive number                      *
//*                  Variable B must be a negative number                      *
//*                                                                            *
//*                                                                            *
//*                                                                            *
//*                                                                            *
//******************************************************************************
library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable, GroupUtils
globals
    private constant real TIME = 0.03
    private constant real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.75
    private constant string GROUND = "MDX\\Dust.mdx"
    private constant string WATER = "MDX\\SlideWater.mdx"
    private constant string COLLISION = "MDX\\DustAndRocks.mdx"
    private constant string ATTACHPOINT = "origin"
    private constant integer Invulnerable = 'Avul'
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private integer array Index
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
endglobals

private function CheckTrees takes nothing returns boolean
    if IsDestructableTree(GetFilterDestructable()) then
        return true
    endif
    return false
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private function ChainCheck takes nothing returns boolean
    return target != GetFilterUnit()
endfunction

function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private struct Knock
//! run textmacro PUI()
    unit source
    unit target
    integer EffectMode
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    real distance
    real MoveDistance
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    boolean Fly
    
    public method TerrainCheck takes Knock d returns integer
        local real x = GetUnitX(d.target)
        local real y = GetUnitY(d.target)
        
        if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod
        
    static method create takes unit source, unit target, real angle,real speed, real decrement, boolean KillTree, boolean Allowmove, boolean ConstantSpeed,boolean Chain,boolean fly returns Knock
        local Knock d = Knock.allocate()
        local real x
        local real y
        set d.source = source
        set d.target = target
        set d.Trees = KillTree
        set d.Fly = fly
        set d.constantspeed = ConstantSpeed
        set d.AllowMove = Allowmove
        set d.chain = Chain
        set d.hit = NewGroup()
        set x = GetUnitX(d.target)
        set y = GetUnitY(d.target)
        set d.speed = speed * TIME
        set d.decrement = decrement * TIME
        set d.sin = Sin(angle)
        set d.cos = Cos(angle)
        set d.EffectMode = d.TerrainCheck(d)
        set d.distance = -1 * speed * speed / (2 * -decrement / TIME)
        if d.EffectMode == 1 then
            set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
        endif
        if d.EffectMode == 2 then
            set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
        endif
        if d.EffectMode == 3 then
         set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
        endif
        return d
    endmethod
    
method onDestroy takes nothing returns nothing
        call DestroyEffect(this.effects)
        call ReleaseGroup(this.hit)
        set Index[GetUnitIndex(this.target)] = 0
endmethod

endstruct
        
private function Update takes nothing returns nothing
    local Knock d = 0
    local Knock c = 0
    local unit u
    local unit t
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    loop
        exitwhen i < 0
        set d = Knocker[i]
        set u = d.target
        set mode = d.EffectMode
        set cx = GetUnitX(u)
        set cy = GetUnitY(u)
        set d.MoveDistance = d.MoveDistance + d.speed

        if d.speed <= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count < 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker[i] = Knocker[Count]
            endif
        else
            set x = cx + d.speed * d.cos
            set y = cy + d.speed * d.sin
            set d.EffectMode = d.TerrainCheck(d)
            if d.AllowMove == true then
                call SetUnitX(u,x)
                call SetUnitY(u,y)
            else
                call SetUnitPosition(u,x,y)
            endif
            if d.Trees == true then
                call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
                call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
            endif
            if d.EffectMode == 1 and (mode == 2 or mode == 3) then
                call DestroyEffect(d.effects)
                set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
            elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
                call DestroyEffect(d.effects)
                set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
            elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
                call DestroyEffect(d.effects)
                set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
            endif
            set d.speed = d.speed - d.decrement
            if d.Fly == true then
                call UnitAddAbility(u,'amrf')
                call UnitRemoveAbility(u,'amrf')
                call SetUnitFlyHeight(u,ParabolaZ(500,d.distance,d.MoveDistance),0)
                call BJDebugMsg(R2S(d.MoveDistance))
            endif
              if d.chain == true then
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
                loop
                    set t = FirstOfGroup(ENUM_GROUP)
                    exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t,Atan2(cy-y,cx-x),(d.speed/TIME)*SPEEDFACTOR,(d.decrement/TIME),d.Trees,d.AllowMove,d.constantspeed,d.chain,d.Fly)
                        call GroupAddUnit(c.hit,u)
                        set Knocker[Count] = c
                        set Count = Count + 1
                    endif
                    call GroupRemoveUnit(ENUM_GROUP, t)
                endloop
            endif
        endif
        set i = i - 1
    endloop
        
    set u = null
    set t = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = Index[GetUnitIndex(target)]
    local boolean b = false
    if d != 0 then
        call d.destroy()
        set Count = Count - 1
        if Count < 0 then
            call PauseTimer(Timer)
            set Count = 0
        else
            set Knocker[i] = Knocker[Count]
        endif
        set b = true
    endif
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = Index[GetUnitIndex(target)]
    return d != 0
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain,boolean fly returns boolean
    local Knock d = 0
    if target == null or source == null or speed == null or decrement == null then
        call BJDebugMsg("Invalid Values!")
        return false
        endif
    set d = Knock.create(source,target,angle,speed,decrement,KillTree,AllowMove,ConstantSpeed,Chain,fly)
    set Index[GetUnitIndex(target)] = d
    if Count == 0 then
    call TimerStart(Timer,TIME,true,function Update)
    endif
    set Knocker[Count] = d
    set Count = Count + 1
    return true
endfunction

private function Init takes nothing returns nothing
    set TreeRect = Rect(0,0,1,1)
    set TreeCheck = Filter(function CheckTrees)
    set ChainFilter = Filter(function ChainCheck)
endfunction

endlibrary

Which doesn't works.

More detailed, Unit A knocks Unit B 600 feets away and then during that 600 feets, Unit B will fly and not Unit A flying.