library_once IsWalking initializer init
//=====================================================================================================//
// Is Walking v0.01 //
// by //
// cedi //
//=====================================================================================================//
//This system tells you when an unit walks, but for that you need to add the unit to the walkers. For
//that you have the Add function:
//call IsWalking_Add( unit walker )
//When you want to remove the unit from the group use:
//call IsWalking_Remove( unit walker )
//
//Now can you use these functions:
//
//call IsWalking_Moving( unit walker ) returns boolean. ( true the unit walks false it stays around )
//call IsWalking_Distance( unit walker ) returns real. ( returns the distance since the unit walked
//since last stop )
//call IsWalking_LastDistance( unit walker ) returns real. ( returns the distance walked at the last interval )
//call IsWalking_Duration( unit walker ) returns real. ( returns the time the unit walks )
//
//WARNING: when a walker dies the system removes the unit from the system. But when you don't want this
//( for heros for example ) use:
//call IsWalking_Protect( unit walker )
//when you want to unprotect use this:
//call IsWalking_UnProtect( unit walker )
//
//There is the possibility to add events to the system. Use these functions:
//Event e is a function interface which takes Walking w and returns nothing
//
//call IsWalking_EventOnStart( Event e, unit walker ) Triggers when the walker starts to walk.
//call IsWalking_EventOnStop( Event e, unit walker ) Triggers when the walker stops to walk.
//call IsWalking_EventOnWalk( Event e, unit walker ) Triggers when the walker walks ( each TIMER_INTERVAL ).
//
//Use the functions with Event e == 0 to remove the events.
//
//Below are some values:
globals
private constant real TIMER_INTERVAL = 0.035
//Interval of the check timer
private constant real MIN_WALK_TIME = 0.10
//The minimum time the unit has to walk.
private constant real MIN_WALK_DISTANCE = 0.20
//The minimum distance the unit has to walk. ( don't use 0 )
private constant real MAX_WALK_DISTANCE = 50.00
//The max distance the unit can walk. ( Protection for teleport )
private constant boolean TEST_MODE = true
//Should the test mode be on ( creates an effect above walkers when they walk ).
// End of Setup, don't change anything below!
private boolean ON = false
private unit TEMP_UNIT
private timer TIMER
private group WALKERS = CreateGroup()
private group TEMP_GROUP = CreateGroup()
private hashtable HASH = InitHashtable()
endglobals
private keyword Walking
public function interface Event takes Walking w returns nothing
private function OutControl takes nothing returns nothing
local unit u
local Walking w
call GroupAddGroup( WALKERS, TEMP_GROUP )
loop
set u = FirstOfGroup( TEMP_GROUP )
exitwhen u == null
call GroupRemoveUnit( TEMP_GROUP, u )
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
call w.Control()
endloop
endfunction
//Use IsWalking_EventOnStop from the outside of the scope
public function EventOnStop takes Event e, unit u returns nothing
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
set w.onstop = e
else
debug call BJDebugMsg( "Not in group" )
endif
endfunction
//Use IsWalking_EventOnStart from the outside of the scope
public function EventOnStart takes Event e, unit u returns nothing
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
set w.onstart = e
else
debug call BJDebugMsg( "Not in group" )
endif
endfunction
//Use IsWalking_EventOnWalk from the outside of the scope
public function EventOnWalk takes Event e, unit u returns nothing
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
set w.onwalk = e
else
debug call BJDebugMsg( "Not in group" )
endif
endfunction
//Use IsWalking_UnProtect from the outside of the scope
public function UnProtect takes unit u returns nothing
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
set w.protect = false
else
debug call BJDebugMsg( "Not in group" )
endif
endfunction
//Use IsWalking_Protect from the outside of the scope
public function Protect takes unit u returns nothing
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
set w.protect = true
else
debug call BJDebugMsg( "Not in group" )
endif
endfunction
//Use IsWalking_Duration from the outside of the scope
public function Duration takes unit u returns real
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
return w.walktime
else
debug call BJDebugMsg( "Not in group" )
endif
return 0.00
endfunction
//Use IsWalking_Distance from the outside of the scope
public function Distance takes unit u returns real
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
return w.distance
else
debug call BJDebugMsg( "Not in group" )
endif
return 0.00
endfunction
//Use IsWalking_LastDistance from the outside of the scope
public function LastDistance takes unit u returns real
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
return w.distance_since
else
debug call BJDebugMsg( "Not in group" )
endif
return 0.00
endfunction
//Use IsWalking_Moving from the outside of the scope
public function Moving takes unit u returns boolean
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
return w.walking
else
debug call BJDebugMsg( "Not in group" )
endif
return false
endfunction
//Use IsWalking_Remove from the outside of the scope
public function Remove takes unit u returns nothing
local Walking w
if IsUnitInGroup( u, WALKERS ) then
set w = LoadInteger( HASH, GetHandleId( u ), 1 )
call w.destroy()
else
debug call BJDebugMsg( "Not in group" )
endif
endfunction
//Use IsWalking_Add from the outside of the scope
public function Add takes unit u returns nothing
local Walking w
if not IsUnitInGroup( u, WALKERS ) then
set w = Walking.create( u )
call SaveInteger( HASH, GetHandleId( u ), 1, w )
if not ON then
call TimerStart( TIMER, TIMER_INTERVAL, true, function OutControl )
set ON = true
endif
else
debug call BJDebugMsg( "Already in group" )
endif
endfunction
private struct Walking
unit walker = null
real distance = 0.00
real distance_since = 0.00
real startx = 0.00
real starty = 0.00
real lastx = 0.00
real lasty = 0.00
real walktime = 0.00
boolean walking = false
boolean protect = false
effect sfx = null
Event onwalk = 0
Event onstart = 0
Event onstop = 0
method onDestroy takes nothing returns nothing
call FlushChildHashtable( HASH, GetHandleId( .walker ) )
set .walker = null
call GroupRemoveUnit( WALKERS, .walker )
if TEST_MODE and .sfx != null then
call DestroyEffect( .sfx )
set .sfx = null
endif
set TEMP_UNIT = FirstOfGroup( WALKERS )
if TEMP_UNIT == null then
call PauseTimer( TIMER )
set ON = false
else
set TEMP_UNIT = null
endif
endmethod
method Control takes nothing returns nothing
local real x = GetUnitX( .walker )
local real y = GetUnitY( .walker )
local real dx = x - .lastx
local real dy = y - .lasty
if IsUnitType( .walker, UNIT_TYPE_DEAD ) and not .protect then
call .destroy()
return
endif
set .distance_since = SquareRoot( dx * dx + dy * dy )
set .lastx = x
set .lasty = y
if .distance_since > MAX_WALK_DISTANCE then
debug call BJDebugMsg( "Teleporting" )
return
endif
if .distance_since < MIN_WALK_DISTANCE then
set .distance_since = 0.00
set .distance = 0.00
if .onstop != 0 and .walking then
call .onstop.execute( this )
endif
set .walking = false
set .startx = x
set .starty = y
set .walktime = 0.00
if TEST_MODE then
call DestroyEffect( .sfx )
set .sfx = null
endif
else
set .walktime = .walktime + TIMER_INTERVAL
if not .walking and .walktime >= MIN_WALK_TIME then
if .onstart != 0 then
call .onstart.execute( this )
endif
set .walking = true
if TEST_MODE then
set .sfx = AddSpecialEffectTarget( "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", .walker, "overhead" )
endif
endif
set .distance = .distance + .distance_since
if .onwalk != 0 then
call .onwalk.execute( this )
endif
endif
endmethod
static method create takes unit walker returns thistype
local thistype this = thistype.allocate()
set .walker = walker
set .startx = GetUnitX( walker )
set .starty = GetUnitY( walker )
set .lastx = .startx
set .lasty = .starty
call GroupAddUnit( WALKERS, walker )
return this
endmethod
endstruct
private function init takes nothing returns nothing
set TIMER = CreateTimer()
call TimerStart( TIMER, TIMER_INTERVAL, true, function OutControl )
endfunction
endlibrary[/hidden]