- Joined
- Sep 26, 2009
- Messages
- 9,507
JASS:
library IsUnitMoving requires optional UnitIndexer, optional AIDS, Event
//===========================================================================
// IsUnitMoving
// ============ Created by Xiliger with some script improvements by Bribe
//
//
// This library provides a helpful function that can be used to detect when
// a unit is moving.
//
// API:
//
// function IsUnitMoving takes unit u returns boolean
// function GetMovingUnit takes nothing returns unit
// function GetMovingUnitId takes nothing returns integer
//
// Struct API:
//
// static constant Event MOVE
// > Fires when a unit starts moving.
//
// static constant Event STOP
// > Fires when a unit stops moving.
//
// readonly boolean moving
// > Quick-check if a unit is moving.
//
// readonly boolean allocated
// > Was the unit allocated in the first place?
//
// readonly real x
// > Unit's last-checked x
//
// readonly real y
// > Unit's last-checked y
//
// Requires either:
// UnitIndexer: hiveworkshop.com/forums/showthread.php?t=172090
// or:
// AIDS: thehelper.net/forums/showthread.php?t=130752
// Event: thehelper.net/forums/showthread.php?t=126846
//
// Thanks to Jesus4Lyf for the extremely efficient Timer32 linked-list model
// and to Nestharus for ideas that give IsUnitMoving more power.
//
globals
//-----------------------------------------------------------------------
// Time between coordinate scans. You should increase it if you have move-
// ment-oriented spells/systems with slower timers.
//
private constant real TIMEOUT = 0.03125
private UnitMoving get = 0 // Reference
endglobals
private function GetUnit takes integer id returns unit
static if LIBRARY_UnitIndexer then
return GetUnitById(id)
elseif LIBRARY_AIDS then
return GetIndexUnit(id)
endif
endfunction
private function GetNew takes nothing returns integer
static if LIBRARY_UnitIndexer then
return GetIndexedUnitId()
elseif LIBRARY_AIDS then
return AIDS_GetIndexOfEnteringUnit()
endif
endfunction
private function GetOld takes nothing returns integer
static if LIBRARY_UnitIndexer then
return GetIndexedUnitId()
elseif LIBRARY_AIDS then
return AIDS_GetDecayingIndex()
endif
endfunction
//***************************************************************************
//*
//* Users' API
//*
//***************************************************************************
//===========================================================================
// Returns true when a unit is moving via orders or triggered actions, false
// if the unit is not moving.
//
function IsUnitMoving takes unit u returns boolean
return UnitMoving(GetUnitUserData(u)).moving
endfunction
// Use within a registered event-response to get the moving or stopping unit.
function GetMovingUnit takes nothing returns unit
return GetUnit(get)
endfunction
function GetMovingUnitId takes nothing returns UnitMoving
return get
endfunction
//***************************************************************************
//*
//* System Struct
//*
//***************************************************************************
private module Init
private static method onInit takes nothing returns nothing
set thistype.MOVE = Event.create()
set thistype.STOP = Event.create()
static if LIBRARY_UnitIndexer then
call RegisterUnitIndexEvent(Filter(function thistype.index), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Filter(function thistype.deindex), UnitIndexer.DEINDEX)
elseif LIBRARY_AIDS then
call AIDS_RegisterOnEnter(Filter(function thistype.index))
call AIDS_RegisterOnDeallocate(Filter(function thistype.deindex))
endif
call TimerStart(CreateTimer(), TIMEOUT, true, function thistype.scan)
endmethod
endmodule
struct UnitMoving extends array
readonly static Event MOVE = 0
readonly static Event STOP = 0
readonly real x
readonly real y
readonly boolean moving
readonly boolean allocated
readonly thistype next
readonly thistype prev
private static method index takes nothing returns boolean
local thistype u = GetNew()
if 0 != GetUnitAbilityLevel(GetUnit(u), 'Amov') then
set thistype(0).next.prev = u
set u.next = thistype(0).next
set thistype(0).next = u
set u.x = GetUnitX(GetUnit(u))
set u.y = GetUnitY(GetUnit(u))
set u.allocated = true
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local thistype u = GetOld()
if u.allocated then
set u.moving = false
set u.allocated = false
set u.prev.next = u.next
set u.next.prev = u.prev
set u.prev = 0
endif
return false
endmethod
private static method scan takes nothing returns nothing
local thistype u = thistype(0).next
local real x
local real y
loop
exitwhen 0 == u
set x = GetUnitX(GetUnit(u))
set y = GetUnitY(GetUnit(u))
if x != u.x or y != u.y then
set u.x = x
set u.y = y
if not u.moving then
// The unit was stopped but is now moving.
set u.moving = true
set get = u
call thistype.MOVE.fire()
endif
elseif u.moving then
// The unit was moving but is now stopped.
set u.moving = false
set get = u
call thistype.STOP.fire()
endif
set u = u.next
endloop
endmethod
implement Init
endstruct
endlibrary
Example usage:
JASS:
library Motion initializer init requires IsUnitMoving
private function onMove takes nothing returns boolean
call BJDebugMsg(GetUnitName(GetMovingUnit()) + " has started moving!")
return false
endfunction
private function onMove takes nothing returns boolean
call BJDebugMsg(GetUnitName(GetMovingUnit()) + " has stopped moving!")
return false
endfunction
private function init takes nothing returns nothing
call UnitMoving.MOVE.register(Filter(function onMove))
call UnitMoving.STOP.register(Filter(function onStop))
endfunction
endlibrary
Last edited: