Nestharus
o-o
- Reaction score
- 84
Unit Event
v1.0.2.1
By Nestharus
By Nestharus
Introduction
Unit Event is a lot like AutoEvent in that it adds new unit events to the game that aren't normally possible. For example, resurrection and reincarnating events.
This one is the most efficient Unit Event library to date (not much competition though is there? o-o). For example, AutoEvent uses hooks to handle some of its events as well as a slew of timers and loops. This one does no such thing : ).
- events are death, remove, decay, explode, resurrect, reincarnate, animate
- It has extremely efficient event handling
- Only works with indexed units
- Will eventually have an AutoEvent API to support things running on that system : D.
System Code
JASS:
library UnitEvent initializer init uses UnitIndexer, GameTime
//Unit Indexer- thehelper.net/forums/showthread.php?t=153034
//Game Time- thehelper.net/forums/showthread.php?t=134432
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Unit Event ~~ By Nestharus ~~ Version 1.0.2.2 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Description:
// Unit Event is a system that handles events that aren't normally possible in Warcraft 3.
// It retrieves them by using undefend.
//
// This system will only fire units that are indexed. Any unit that is not indexed is treated
// as an unexisting unit.
//
// Events: death, remove, decay, explode, resurrect, reincarnate, animate
//
//API:
//////////////////////////////////////////////////////////////
// -function IsUnitDead takes integer index returns boolean
// Returns a boolean determining whether the unit is dead or not.
//
// -function IsUnitReincarnating takes integer index returns boolean
// Returns a boolean determining whether the unit is reincarnating or not.
//
// -function IsUnitAnimated takes integer index returns boolean
// Returns a boolean determining whether a unit is animated or not.
//
//Events:
//////////////////////////////////////////////////////////////
// Each event is a struct that extends array.
//
// -API
// -static method add takes boolexpr c returns nothing
// Adds code to be run at event.
//
// -function GetEventUnit takes nothing returns unit
// Returns the triggering unit.
//
// -function GetEventUnitId takes nothing returns integer
// Returns the index of the tiggering unit.
//
// -Structs
// -UnitDeathEvent
// Fires whenever a unit dies.
//
// -UnitRemoveEvent
// Fires whenever a unit is removed.
//
// -UnitDecayEvent
// Fires whenever a unit decays.
//
// -UnitExplodeEvent
// Fires whenever a unit's animation expires.
//
// -UnitResurrectEvent
// Fires whenever a unit is resurrected.
//
// -UnitReincarnateEvent
// Fires whenever a unit is reincarnated.
//
// -UnitAnimateEvent
// Fires whenever a unit is animated.
//
//Unit Event Struct Module:
//////////////////////////////////////////////////////////////
// A module that will automatically call unit event methods for you as well
// as automatically check against a unit indexer filter. It runs completely off of static ifs,
// so there are minimal calls and there is minimal code.
//
// module UnitEventStruct
// readonly unit eventUnit
// The indexed event unit of the struct. Use this over unit when dealing with the
// events.
//
// Interface:
// private method unitDeath takes nothing returns nothing
// Fires when an indexed unit dies. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//
// private method unitRemove takes nothing returns nothing
// Fires when an indexed unit is removed. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//
// private method unitDecay takes nothing returns nothing
// Fires when an indexed unit decays. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//
// private method unitExplode takes nothing returns nothing
// Fires when an indexed unit explodes. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//
// private method unitResurrect takes nothing returns nothing
// Fires when an indexed unit is resurrected. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//
// private method unitReincarnate takes nothing returns nothing
// Fires when an indexed unit reincarnates. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//
// private method unitAnimate takes nothing returns nothing
// Fires when an indexed unit is animated. Will only fire
// if the struct is allocated.
//
// Structs are allocated when the indexing filter of the struct
// returns true. If the indexing filter doesn't exist, a struct
// is always allocated.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
native UnitAlive takes unit id returns boolean
globals
//events
private trigger onDeath = CreateTrigger()
private trigger onRemove = CreateTrigger()
private trigger onDecay = CreateTrigger()
private trigger onExplode = CreateTrigger()
private trigger onResurrect = CreateTrigger()
private trigger onReincarnate = CreateTrigger()
private trigger onAnimate = CreateTrigger()
private integer array events
private integer eventIndex = 0
private trigger undefend = CreateTrigger()
private trigger death = CreateTrigger()
private boolean array animated
private boolean array dead
private boolean array reincarnating
private real array timeStamp
private unit array holdUnit
private boolean array allocated
private boolean array exploded
//this is auto determined
private real decayTime = 1000
private unit decayUnit = null
endglobals
struct UnitDeathEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onDeath, c)
endmethod
endstruct
struct UnitRemoveEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onRemove, c)
endmethod
endstruct
struct UnitDecayEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onDecay, c)
endmethod
endstruct
struct UnitExplodeEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onExplode, c)
endmethod
endstruct
struct UnitResurrectEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onResurrect, c)
endmethod
endstruct
struct UnitReincarnateEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onReincarnate, c)
endmethod
endstruct
struct UnitAnimateEvent extends array
public static method add takes boolexpr c returns nothing
call TriggerAddCondition(onAnimate, c)
endmethod
endstruct
function GetEventUnit takes nothing returns unit
return holdUnit[events[eventIndex]]
endfunction
function GetEventUnitId takes nothing returns integer
return events[eventIndex]
endfunction
function IsUnitDead takes integer index returns boolean
return dead[index]
endfunction
function IsUnitReincarnating takes integer index returns boolean
return reincarnating[index]
endfunction
function IsUnitAnimated takes integer index returns boolean
return (animated[index])
endfunction
private function OnUndefend takes nothing returns boolean
local unit u = GetFilterUnit()
local integer i = GetUnitUserData(u)
if (holdUnit<i> == u and allocated<i>) then
if (GetUnitAbilityLevel(u, 039;OUIN039;) == 0) then
set allocated<i> = false
set reincarnating<i> = false
set animated<i> = false
if (not exploded<i>) then
set eventIndex = eventIndex + 1
set events[eventIndex] = i
if (dead<i> and GetElapsedGameTime()-timeStamp<i> >= decayTime) then
set dead<i> = false
call TriggerEvaluate(onDecay)
else
set dead<i> = false
call TriggerEvaluate(onRemove)
endif
else
set dead<i> = false
set exploded<i> = false
endif
set eventIndex = eventIndex - 1
set holdUnit<i> = null
call UnlockUnitIndex(i)
elseif (UnitAlive(u)) then
if (reincarnating<i>) then
set eventIndex = eventIndex + 1
set events[eventIndex] = i
call TriggerEvaluate(onReincarnate)
set reincarnating<i> = false
set eventIndex = eventIndex - 1
elseif (dead<i>) then
set dead<i> = false
set eventIndex = eventIndex + 1
set events[eventIndex] = i
if (IsUnitType(u, UNIT_TYPE_SUMMONED)) then
set animated<i> = true
call TriggerEvaluate(onAnimate)
else
call TriggerEvaluate(onResurrect)
endif
set eventIndex = eventIndex - 1
endif
else
set reincarnating<i> = true
endif
elseif (u == decayUnit and GetElapsedGameTime() != 0) then
set decayTime = GetElapsedGameTime()-.9375 //cleaning takes up to 3 passes standard
//cleaning in around .3125 intervals
//.3125 * 3
set decayUnit = null
endif
set u = null
return false
endfunction
private function OnDeath takes nothing returns boolean
local unit u = GetTriggerUnit()
local integer i = GetUnitUserData(u)
if (holdUnit<i> == u) then
set dead<i> = true
set reincarnating<i> = false
set eventIndex = eventIndex + 1
set events[eventIndex] = i
if (not animated<i>) then
set timeStamp<i> = GetElapsedGameTime()
call TriggerEvaluate(onDeath)
else
set exploded<i> = true
set animated<i> = false
call TriggerEvaluate(onExplode)
endif
set eventIndex = eventIndex - 1
endif
set u = null
return false
endfunction
private function OnEnter takes nothing returns boolean
call LockUnitIndex(GetIndexedUnitId())
set allocated[GetIndexedUnitId()] = true
set holdUnit[GetIndexedUnitId()] = GetIndexedUnit()
return false
endfunction
private struct UnitEventX extends array
private static method onInit takes nothing returns nothing
local integer i = 15
local boolexpr bc = Condition(function OnUndefend)
loop
call TriggerRegisterPlayerUnitEvent(undefend, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, bc)
call TriggerRegisterPlayerUnitEvent(death, Player(i), EVENT_PLAYER_UNIT_DEATH, null)
exitwhen i == 0
set i = i - 1
endloop
call TriggerAddCondition(death, Condition(function OnDeath))
call UnitIndexEvent.add(Condition(function OnEnter))
set bc = null
endmethod
endstruct
//must be done at init or it will still be indexed in the enumeration
private function init takes nothing returns nothing
local rect r = GetWorldBounds()
call EnableUnitIndexing(false)
set decayUnit = CreateUnit(Player(14), 039;hpea039;, GetRectMaxX(r), GetRectMaxY(r), 0)
call KillUnit(decayUnit)
call UnitAddAbility(decayUnit, 039;OUIN039;)
call ShowUnit(decayUnit, false)
call EnableUnitIndexing(true)
call RemoveRect(r)
set r = null
endfunction
//! textmacro UNIT_EVENT_STRUCT_INIT
private static method enteringEvent takes nothing returns boolean
set thistype(GetIndexedUnitId()).allocated = thistype(GetIndexedUnitId()).indexAllocated
return false
endmethod
private static method onInit takes nothing returns nothing
static if thistype.unitDeath.exists then
call UnitDeathEvent.add(Condition(function thistype.onDeathEvent))
endif
static if thistype.unitRemove.exists then
call UnitRemoveEvent.add(Condition(function thistype.onRemoveEvent))
endif
static if thistype.unitDecay.exists then
call UnitDecayEvent.add(Condition(function thistype.onDecayEvent))
endif
static if thistype.unitExplode.exists then
call UnitExplodeEvent.add(Condition(function thistype.onExplodeEvent))
endif
static if thistype.unitResurrect.exists then
call UnitResurrectEvent.add(Condition(function thistype.onResurrectEvent))
endif
static if thistype.unitReincarnate.exists then
call UnitReincarnateEvent.add(Condition(function thistype.onReincarnateEvent))
endif
static if thistype.unitAnimate.exists then
call UnitAnimateEvent.add(Condition(function thistype.onAnimateEvent))
endif
call UnitIndexEvent.add(Condition(function thistype.enteringEvent))
endmethod
//! endtextmacro
module UnitEventStruct
implement UnitIndexStruct //results in no code if not used, so might as well
private boolean allocated //because indexAllocated runs first
static if thistype.unitDeath.exists then
private static method onDeathEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).unitDeath()
endif
return false
endmethod
endif
static if thistype.unitRemove.exists then
private static method onRemoveEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
set thistype(GetEventUnitId()).allocated = false
call thistype(GetEventUnitId()).unitRemove()
endif
return false
endmethod
endif
static if thistype.unitDecay.exists then
private static method onDecayEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
set thistype(GetEventUnitId()).allocated = false
call thistype(GetEventUnitId()).unitDecay()
endif
return false
endmethod
endif
static if thistype.unitExplode.exists then
private static method onExplodeEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
set thistype(GetEventUnitId()).allocated = false
call thistype(GetEventUnitId()).unitExplode()
endif
return false
endmethod
endif
static if thistype.unitResurrect.exists then
private static method onResurrectEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).unitResurrect()
endif
return false
endmethod
endif
static if thistype.unitReincarnate.exists then
private static method onReincarnateEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).unitReincarnate()
endif
return false
endmethod
endif
static if thistype.unitAnimate.exists then
private static method onAnimateEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).unitAnimate()
endif
return false
endmethod
endif
static if thistype.unitDeath.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
elseif thistype.unitRemove.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
elseif thistype.unitDecay.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
elseif thistype.unitExplode.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
elseif thistype.unitResurrect.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
elseif thistype.unitReincarnate.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
elseif thistype.unitAnimate.exists then
//! runtextmacro UNIT_EVENT_STRUCT_INIT()
endif
public method operator eventUnit takes nothing returns unit
return holdUnit[this]
endmethod
endmodule
endlibrary
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
Demo Code
JASS:
struct UnitEventDemo extends array
private static real x
private static real y
private method unitDeath takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " died")
endmethod
private method unitRemove takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " removed")
endmethod
private method unitDecay takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " decayed")
endmethod
private method unitExplode takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " exploded")
endmethod
private method unitResurrect takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " resurrected")
endmethod
private method unitReincarnate takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " reincarnated")
endmethod
private method unitAnimate takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(this)+":"+ GetUnitName(eventUnit) + " animated")
endmethod
private static method unitIndexFilter takes unit u returns boolean
//normally
//return (GetUnitTypeId(u) == 'hkni')
if (GetUnitTypeId(u) == 039;hkni039;) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetUnitName(u) + " was filtered")
return false
endif
return true
endmethod
private static method remove takes nothing returns nothing
call RemoveUnit(CreateUnit(Player(0), 039;hkni039;, x, y, 0))
endmethod
private static method onInit takes nothing returns nothing
local unit u
set x = GetRectCenterX(bj_mapInitialPlayableArea)
set y = GetRectCenterY(bj_mapInitialPlayableArea)
call PanCameraTo(x, y)
call CreateUnit(Player(0), 039;hfoo039;, x, y, 0)
call CreateUnit(Player(0), 039;hpea039;, x, y, 0)
call CreateUnit(Player(0), 039;hfoo039;, x, y, 0)
call CreateUnit(Player(0), 039;hpea039;, x, y, 0)
call CreateUnit(Player(0), 039;hfoo039;, x, y, 0)
call CreateUnit(Player(0), 039;hpea039;, x, y, 0)
set u = CreateUnit(Player(0), 039;Hpal039;, x, y, 0)
call SetHeroLevel(u, 10, false)
call SetHeroAgi(u, 8000, true)
call SetHeroInt(u, 8000, true)
call SetHeroStr(u, 8000, true)
set u = CreateUnit(Player(0), 039;Udea039;, x, y, 0)
call SetHeroLevel(u, 10, false)
call SetHeroAgi(u, 8000, true)
call SetHeroInt(u, 8000, true)
call SetHeroStr(u, 8000, true)
set u = CreateUnit(Player(0), 039;Otch039;, x, y, 0)
call SetHeroLevel(u, 10, false)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Creating and Removing a unit in 5 seconds\n\n")
call TimerStart(CreateTimer(), 5, false, function thistype.remove)
set u = null
endmethod
implement UnitEventStruct
endstruct