kingkingyyk3
Visitor (Welcome to the Jungle, Baby!)
- Reaction score
- 216
JASS:
library PushUnit initializer OnInit requires Table
/*
Push Unit v1.0.0
by kingkingyyk
- A library that supports multiple instances of sliding/knocking back on every single unit.
=========
APIs :
=========
PushUnit(unit,velocity,angle,time,func1) -> integer
- Push the unit with deceleration.
PushUnitLinear(unit,velocity,angle,time,func1) -> integer
- Push the unit uniformly.
*** Angle used must be in radian.
*** func1 will be fired when the slide/knockback is finished.
*** Function must have "take integer slide returns nothing" as parameter.
*** integer "slide" refers to the instance of the slide.
*** If you don't need the function(s), then just put 0 in it.
PushUnit_AttachData(integer slide, integer data)
- Attach data to the instance.
PushUnit_GetData(integer slide) -> integer
- Get the data from the instance.
PushUnit_SetGlobalTimeScale(real scale)
- Define the speed of time in this library.
- Lower scale will result in lower pushing.
PushUnit_GetGlobalTimeScale() -> real
- Get the current speed of time in this library.
PushUnit_SetTimeScale(unit, real scale)
- Define the speed of time for certain unit.
PushUnit_GetTimeScale(unit) -> real
- Get the current speed of time for certain unit.
*** The default time scale is 1.0
GetPushedUnit(integer slide) -> unit
- Get the pushed unit from the instance
IsUnitBeingPushed(unit) -> boolean
- Is unit being pushed currently?
GetUnitPushSpeed(unit) -> real
- Return the current speed of pushing on the unit.
GetUnitPushAngle(unit) -> real
- Return the current angle of pushing on the unit.
*** Angle returned is in radian form.
----------Calculations for non-linear pushing-----------
GetTime_DispVel(displacement, velocity) -> real
- Calculate the time with given displacement and velocity.
GetDisp_VelTime(velocity, time) -> real
- Calculate the displacement with given velocity and time.
GetVel_DispTime(displacement, time) -> real
- Calculate the velocity with given displacement and time.
--------Calculations for linear pushing----------
Formula : Displacement = Velocity x time
- Arrange the equation and get your needs.
==================
Story behind :
==================
This library utilizes the very simplest of physics, vectors, motion, and energy.
Equations of motion :
v=u+at
s=ut+0.5at^2
v^2=u^2+2as
s=0.5(u+v)t
where u=initial velocity, v=final velocity, a=acceleration, t=time of motion, s=displacement
Equations of energy :
E=0.5mv^2 (For kinetic energy)
E=mgh (For potential energy)
where m=mass of body, g=gravitional acceleration, h=delta height
==================
Configurables :
================== */
globals
private constant real TIMER_PERIOD=0.03125
// -> Period of timer. Default is 0.03125 / 32Hz
private constant boolean HEIGHT_SENSITIVE=true
// -> If enabled, this library will obey the principle of conservation of energy.
private constant real GRAVITATIONAL_ACC=9.81
// -> Needless to touch unless you know what exactly it is.
endglobals /*
==================
Requirements :
==================
Table - Vexorian
Latest version of Jasshelper (Working correctly with 7 January 2012, cohadar's version)
***It is recommended to use BoundSentinel when using this library.
*/
globals
private real TimeScale=1.0
private HandleTable UnitAttachment=0
private location TempLoc=Location(0.0,0.0)
endglobals
private function GetLocZ takes real x, real y returns real
call MoveLocation(TempLoc,x,y)
return GetLocationZ(TempLoc)
endfunction
private struct UnitData
private static timer Timer=CreateTimer()
thistype prev
thistype next
unit unit
real x
real y
real lastZ
integer stackLevel
real timeScale
static method operator [] takes unit u returns thistype
local thistype this=UnitAttachment<u>
if this==0 then
set this=thistype.create()
set this.unit=u
set this.lastZ=GetLocZ(GetUnitX(this.unit),GetUnitY(this.unit))
set this.timeScale=TimeScale
set UnitAttachment<u>=this
endif
return this
endmethod
private static method periodic takes nothing returns nothing
local thistype this=thistype(0).next
local real currZ
local real dz
local real vel
local real angle
local real gravity
loop
exitwhen this==0
call SetUnitX(this.unit,GetUnitX(this.unit)+this.x)
call SetUnitY(this.unit,GetUnitY(this.unit)+this.y)
static if HEIGHT_SENSITIVE then
set currZ=GetLocZ(GetUnitX(this.unit),GetUnitY(this.unit))
set gravity=GRAVITATIONAL_ACC*TIMER_PERIOD*this.timeScale
if currZ!=this.lastZ then
set dz=currZ-this.lastZ
if dz>0.0 then
set vel=SquareRoot(2*gravity*dz)
set angle=Atan2(this.y,this.x)
set this.x=this.x-(vel*Cos(angle))
set this.y=this.y-(vel*Sin(angle))
else
set vel=SquareRoot(2*gravity*-dz)
set this.x=this.x+(vel*Cos(angle))
set this.y=this.y+(vel*Sin(angle))
endif
set this.lastZ=currZ
endif
endif
set this=this.next
endloop
endmethod
method increment takes nothing returns nothing
set this.stackLevel=this.stackLevel+1
if this.stackLevel==1 then
set thistype(0).prev.next=this
set this.prev=thistype(0).prev
set this.next=thistype(0)
set thistype(0).prev=this
if thistype(0).next==this then
call TimerStart(thistype.Timer,TIMER_PERIOD,true,function thistype.periodic)
endif
endif
endmethod
method decrement takes nothing returns nothing
set this.stackLevel=this.stackLevel-1
if this.stackLevel==0 then
set UnitAttachment[this.unit]=0
set this.x=0.0
set this.y=0.0
set this.prev.next=this.next
set this.next.prev=this.prev
call this.destroy()
if thistype(0).next==0 then
call PauseTimer(thistype.Timer)
endif
endif
endmethod
endstruct
private function interface SlideFunc takes integer slide returns nothing defaults nothing
private struct SlideData
private static timer Timer=CreateTimer()
thistype prev
thistype next
boolean isLinear
real accX
real accY
integer tick
unit target
timer t
SlideFunc onStop
integer attachment
real timeScale
private static method periodic takes nothing returns nothing
local thistype this=thistype(0).next
loop
exitwhen this==0
set this.tick=this.tick-1
if this.tick>0 then
if this.isLinear==false then
set UnitData[this.target].x=UnitData[this.target].x-this.accX
set UnitData[this.target].y=UnitData[this.target].y-this.accY
endif
else
call this.onStop.evaluate(this)
call UnitData[this.target].decrement()
set this.prev.next=this.next
set this.next.prev=this.prev
call this.destroy()
endif
set this=this.next
endloop
if thistype(0).next==0 then
call PauseTimer(thistype.Timer)
endif
endmethod
method startPeriodic takes nothing returns nothing
set thistype(0).prev.next=this
set this.prev=thistype(0).prev
set this.next=thistype(0)
set thistype(0).prev=this
if thistype(0).next==this then
call TimerStart(thistype.Timer,TIMER_PERIOD,true,function thistype.periodic)
endif
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(thistype.Timer,TIMER_PERIOD,true,function thistype.periodic)
endmethod
endstruct
function GetPushedUnit takes SlideData dat returns unit
return dat.target
endfunction
function IsUnitBeingPushed takes unit u returns boolean
return UnitData<u>.stackLevel>0
endfunction
public function GetData takes SlideData dat returns integer
return dat.attachment
endfunction
public function AttachData takes SlideData dat, integer toAttach returns nothing
set dat.attachment=toAttach
endfunction
public function SetGlobalTimeScale takes real scale returns nothing
local SlideData dat=SlideData(0).next
local UnitData ud=UnitData(0).next
local real multiplier
loop
exitwhen dat==0
set multiplier=scale/dat.timeScale
set dat.timeScale=scale
set dat.accX=dat.accX*multiplier
set dat.accY=dat.accY*multiplier
set dat.tick=R2I(I2R(dat.tick)/multiplier)
set dat=dat.next
endloop
loop
exitwhen ud==0
set multiplier=scale/ud.timeScale
set ud.timeScale=scale
set ud.x=ud.x*multiplier
set ud.y=ud.y*multiplier
set ud=ud.next
endloop
set TimeScale=scale
endfunction
public function GetGlobalTimeScale takes nothing returns real
return TimeScale
endfunction
public function SetTimeScale takes unit u, real scale returns nothing
local SlideData dat=SlideData(0).next
local UnitData ud=UnitData<u>
local real multiplier
loop
exitwhen dat==0
if dat.target==u then
set multiplier=scale/dat.timeScale
set dat.timeScale=scale
set dat.accX=dat.accX*multiplier
set dat.accY=dat.accY*multiplier
set dat.tick=R2I(I2R(dat.tick)/multiplier)
endif
set dat=dat.next
endloop
set multiplier=scale/ud.timeScale
set ud.timeScale=scale
set ud.x=ud.x*multiplier
set ud.y=ud.y*multiplier
endfunction
public function GetTimeScale takes unit u returns real
return UnitData<u>.timeScale
endfunction
function GetUnitPushSpeed takes unit u returns real
local real x=(UnitData<u>.x/TIMER_PERIOD)*UnitData<u>.timeScale
local real y=(UnitData<u>.y/TIMER_PERIOD)*UnitData<u>.timeScale
return SquareRoot(x*x+y*y) //Resultant vector.
endfunction
function GetUnitPushAngle takes unit u returns real
return Atan2(UnitData<u>.y,UnitData<u>.x)
endfunction
function PushUnit takes unit u, real vel, real angle, real time, SlideFunc stop returns integer
local SlideData dat=0
local real x
local real y
if u!=null and vel!=0.0 and time>0.0 then
set dat=SlideData.create()
set dat.timeScale=UnitData<u>.timeScale
set x=((vel*Cos(angle))*TIMER_PERIOD)*dat.timeScale
set y=((vel*Sin(angle))*TIMER_PERIOD)*dat.timeScale
set dat.target=u
set dat.tick=R2I((time/TIMER_PERIOD)/dat.timeScale)
set dat.accX=(x/(time/TIMER_PERIOD))*dat.timeScale
set dat.accY=(y/(time/TIMER_PERIOD))*dat.timeScale
set dat.onStop=stop
set dat.isLinear=false
set UnitData<u>.x=UnitData<u>.x+x
set UnitData<u>.y=UnitData<u>.y+y
call UnitData<u>.increment()
call dat.startPeriodic()
endif
return dat
endfunction
function PushUnitLinear takes unit u, real vel, real angle, real time, SlideFunc stop returns integer
local SlideData dat=0
if u!=null and vel!=0.0 and time>0.0 then
set dat=SlideData.create()
set dat.timeScale=UnitData<u>.timeScale
set dat.accX=((vel*Cos(angle))*TIMER_PERIOD)*dat.timeScale
set dat.accY=((vel*Sin(angle))*TIMER_PERIOD)*dat.timeScale
set dat.target=u
set dat.tick=R2I((time/TIMER_PERIOD)/dat.timeScale)
set dat.onStop=stop
set dat.isLinear=true
set UnitData<u>.x=UnitData<u>.x+dat.accX
set UnitData<u>.y=UnitData<u>.y+dat.accY
call UnitData<u>.increment()
call dat.startPeriodic()
endif
return dat
endfunction
function GetTime_DispVel takes real disp, real vel returns real
return (2*disp)/vel
endfunction
function GetDisp_VelTime takes real vel, real time returns real
return (vel*time)/2
endfunction
function GetVel_DispTime takes real disp, real time returns real
return (2*disp)/time
endfunction
private function OnInit takes nothing returns nothing
set UnitAttachment=HandleTable.create()
endfunction
endlibrary
</u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u></u>
Still feeling "what the heck it does?" after reading the documentation?
Try the demo map, it speaks all.
Changelog :
- v1.0.0 - First release