Alright, this is meant as a preview of an upcoming library of mine. It is a direct competitor to Anachron's CustomAura library, which can be found in the Spells section.
It doesnt come with any additional libraries.
You dont have to extend the struct provided by this library (you can however, should you find the need for additional features). You use function interfaces to respond to the various events this library features.
This library allows you to disable or destroy instances when the unit its locked on (the "origin" unit) dies, and re-enable the instance when it gets resurrected.
Instances get forcefully destroyed when the unit its locked on leaves the game (gets removed).
It also allows you to delay the removal of the aura from units that leave the area of the aura.
This library uses vJass, GroupUtils, TimerUtils, Table and AutoIndex (currently).
Once wc3c.net is back online, i will finish this library by using AutoEvents to detect resurrection. It already has support for hero revival.
Again: Note that this is a preview and in no way meant as a final version. If you find something you think would need improvement, dont hesitate to tell me.
It doesnt come with any additional libraries.
You dont have to extend the struct provided by this library (you can however, should you find the need for additional features). You use function interfaces to respond to the various events this library features.
This library allows you to disable or destroy instances when the unit its locked on (the "origin" unit) dies, and re-enable the instance when it gets resurrected.
Instances get forcefully destroyed when the unit its locked on leaves the game (gets removed).
It also allows you to delay the removal of the aura from units that leave the area of the aura.
This library uses vJass, GroupUtils, TimerUtils, Table and AutoIndex (currently).
Once wc3c.net is back online, i will finish this library by using AutoEvents to detect resurrection. It already has support for hero revival.
JASS:
// *************************************************************
// * LightweightAura -- Version 1.0.0
// * by Deaod
// *************************************************************
// *
// * CREDITS:
// * - grim001 (AutoIndex, AutoEvents)
// * - Rising_Dusk (GroupUtils)
// * - Vexorian (JassHelper, Table, TimerUtils)
// * - MindWorX and PitzerMike (JassNewGenPack)
// * - Pipedream (Grimoire)
// * - SFilip (TESH)
// *
// *************************************************************
library LightweightAura requires GroupUtils, TimerUtils, Table, AutoIndex
/**
*
* The following interface is only a description of the struct "Aura".
* It is not actually declared anywhere.
*
* interface Aura
* // destroys this aura after waiting auraPersistenceTime seconds. When destroyed,
* // the onRemoveFunc will be called for all remaining units affected by the aura.
* // while waiting for auraPersistenceTime seconds, the "destroyed" property of the Aura is true.
* public method destroy takes nothing returns nothing
*
* // creates a new Aura instance which follows the origin unit around
* public static method create takes unit origin, real range, AuraFilter filterFunc, AuraOnAdd onAddFunc, AuraOnRemove onRemoveFunc returns thistype
*
* // creates a new Aura instance which has a constant origin
* public static method createLoc takes real x, real y, real range, AuraFilter filterFunc, AuraOnAdd onAddFunc, AuraOnRemove onRemoveFunc returns thistype
*
* // this property is a function interface type. The function is executed every time a unit enters the range of the aura.
* public method operator filterFunc takes nothing returns AuraFilter
* public method operator filterFunc= takes AuraFilter func returns nothing
*
* function interface AuraFilter takes Aura a, unit target returns boolean
*
*
* // this function interface type is executed every time the aura is "refreshed", ie. new units are added to group and units out of range are removed.
* public method operator periodicFunc takes nothing returns AuraPeriodic
* public method operator periodicFunc= takes AuraPeriodic func returns nothing
*
* function interface AuraPeriodic takes Aura a returns nothing
*
*
* // this function interface type is executed whenever at least one unit is added to the affected units.
* // The group passed to it contains all new units affected.
* // You must release the group passed to it yourself (you have to use GroupUtils).
* public method operator onAddFunc takes nothing returns AuraOnAdd
* public method operator onAddFunc= takes AuraOnAdd func returns nothing
*
* function interface AuraOnAdd takes Aura a, group targets returns nothing
*
*
* // this function interface type is executed whenever at least one unit is removed from the affected units.
* // The group passed to it contains all removed units that were previously affected.
* // You must release the group passed to it yourself (you have to use GroupUtils).
* public method operator onRemoveFunc takes nothing returns AuraOnRemove
* public method operator onRemoveFunc= takes AuraOnRemove func returns nothing
*
* function interface AuraOnRemove takes Aura a, group targets returns nothing
*
*
* // this gets the current coordinates of the origin of the aura.
* // returns the position of the origin unit when periodicFunc was last run.
* public method operator originX takes nothing returns real
* public method operator originY takes nothing returns real
*
* // sets the origin of the aura to a constant point. Unbinds the aura from the current origin unit, if any.
* public method setOriginPos takes real x, real y returns nothing
*
* // gets or sets the origin unit of the aura.
* // If you set the origin to null, the position of the previous origin when the periodicFunc was last run will be used.
* public method operator origin takes nothing returns unit
* public method operator origin= takes unit new returns nothing
*
* // returns a group of all currently affected units.
* // avoid destroying/recycling this group at all costs. It will break the instance.
* public method operator targets takes nothing returns group
*
* // the range of the aura.
* public method operator range takes nothing returns real
* public method operator range= takes real new returns nothing
*
* // the interval between searching for new units/removing units out of range.
* // default is 1./4.
* public method operator period takes nothing returns real
* public method operator period= takes real new returns nothing
*
* // the time units have to be outside the range of the aura to be removed from its affected units.
* // default is 0.
* public method operator auraPersistenceTime takes nothing returns real
* public method operator auraPersistenceTime= takes real new returns nothing
*
* // returns true only when auraPersistenceTime is greater than 0 and you previously called destroy.
* // returns false otherwise
* public method operator destroyed takes nothing returns boolean
*
* // a disabled aura will not search for units in its range and will remove all units from its targets group
* // after auraPersistenceTime seconds
* // default is true.
* public method operator enabled takes nothing returns boolean
* public method operator enabled= takes boolean new returns nothing
*
* // whether or not to destroy this instance when the origin unit dies.
* // default is true.
* public method operator destroyOnDeath takes nothing returns boolean
* public method operator destroyOnDeath= takes boolean new returns nothing
*
* // whether or not to disable this instance when the origin unit dies.
* // destroyOnDeath takes precedence over this.
* // default is false.
* public method operator disableOnDeath takes nothing returns boolean
* public method operator disableOnDeath= takes boolean new returns nothing
*
* // whether or not to enable this instance again when the origin unit is resurrected.
* // default is false.
* public method operator enableOnResurrect takes nothing returns boolean
* public method operator enableOnResurrect= takes boolean new returns nothing
* endinterface
*/
globals
private constant real DEFAULT_PERIOD = 1./4
endglobals
// DO NOT TOUCH ANYTHING BELOW!
// unless of course you know what you're doing.
function interface AuraFilter takes Aura a, unit target returns boolean
function interface AuraPeriodic takes Aura a returns nothing
function interface AuraOnAdd takes Aura a, group targets returns nothing
function interface AuraOnRemove takes Aura a, group targets returns nothing
private struct DelayedAuraLoss
group targets
Aura a
endstruct
struct Aura
// Event Callbacks, may be registered individually.
private AuraFilter FilterFunc = 0 // filters each unit entering the Aura individually.
private AuraPeriodic PeriodicFunc = 0 // run every time the aura is refreshed.
private AuraOnAdd OnAddFunc = 0 // run when at least one new unit is added to the targets of the aura.
private AuraOnRemove OnRemoveFunc = 0 // run when at least one unit is removed from the targets of the aura.
// sets where the origin of the aura is.
private real OriginX
private real OriginY
private unit Origin
private boolean OriginUnit = true // if true, the origin will always be at the center of the unit, if false, it will always be at the given x and y coordinates.
// holds the current targets of the Aura, ie. the units under its influence
private group Targets
// Range settings, can be overwritten at runtime.
private real Range
// timer to base this orb off of.
private timer T
private real Period = DEFAULT_PERIOD // can be changed at runtime.
// how long the Aura will still affect the targets after they left the range
private real AuraPersistenceTime = 0
private boolean Destroyed = false
private boolean Enabled = true
private boolean DestroyOnDeath = true // destroys this instance when the origin unit dies.
private boolean DisableOnDeath = false // disables this instance when the origin unit dies.
private boolean EnableOnResurrect = false // re-enables this instance when the origin unit resurrects. DestroyOnDeath must be false for this to work.
private integer TablePos
// STATICS
private static Table UnitAuraTable
private static integer array UnitAuraCount
private static thistype tmpd // temporary data, used for group filtering
private static group tmpg // temporary group
private static method DelayedAuraLost takes nothing returns nothing
local DelayedAuraLoss dal=DelayedAuraLoss(GetTimerData(GetExpiredTimer()))
set bj_groupRemoveGroupDest=dal.a.Targets
call ForGroup(dal.targets, function GroupRemoveGroupEnum)
if dal.a.onRemoveFunc>0 then
call dal.a.onRemoveFunc.evaluate(dal.a, dal.targets)
endif
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method GroupAddFilter takes nothing returns boolean
local unit u=GetFilterUnit()
if not IsUnitInGroup(u, tmpd.targets) and (tmpd.filterFunc==0 or tmpd.filterFunc.evaluate(tmpd, u)) then
call GroupAddUnit(tmpd.targets, u)
set u=null
return true
endif
set u=null
return false
endmethod
private static method GroupLostFunc takes nothing returns nothing
local unit u=GetEnumUnit()
local real dx=GetUnitX(u)-tmpd.originX
local real dy=GetUnitY(u)-tmpd.originY
if dx*dx+dy*dy>tmpd.range*tmpd.range then
if tmpd.auraPersistenceTime<=0 then
call GroupRemoveUnit(tmpd.Targets, u)
endif
call GroupAddUnit(tmpg, u)
endif
set u=null
endmethod
private static method Callback takes nothing returns nothing
local thistype s=thistype(GetTimerData(GetExpiredTimer()))
local group newtargets=NewGroup()
local group losttargets=NewGroup()
// the next two are only used when the user wants the aura to remain on the target for some time
local timer t
local DelayedAuraLoss dal
if not s.destroyed and s.enabled then
if s.OriginUnit then
set s.OriginX=GetUnitX(s.origin)
set s.OriginY=GetUnitY(s.origin)
endif
set tmpd=s
set tmpg=losttargets
call ForGroup(s.Targets, function thistype.GroupLostFunc)
set tmpg=newtargets
call GroupEnumUnitsInRange(newtargets, s.originX, s.originY, s.range, function thistype.GroupAddFilter)
// now lets execute the events
if s.periodicFunc>0 then
call s.periodicFunc.evaluate(s)
endif
if FirstOfGroup(losttargets)!=null then // see if losttargets has at least one unit
if tmpd.auraPersistenceTime<=0 then // and check if the user wants to delay the removal of units outside the range
if s.onRemoveFunc>0 then
call s.onRemoveFunc.evaluate(s, losttargets)
endif
else
set dal=DelayedAuraLoss.create()
set dal.a=s
set dal.targets=losttargets
set t=NewTimer()
call SetTimerData(t, integer(dal))
call TimerStart(t, s.auraPersistenceTime, false, function thistype.DelayedAuraLost)
endif
else
call ReleaseGroup(losttargets)
endif
if FirstOfGroup(newtargets)!=null and s.onAddFunc>0 then // see if newtargets has at least one unit
call s.onAddFunc.evaluate(s, newtargets)
else
call ReleaseGroup(newtargets)
endif
elseif s.periodicFunc>0 then
call s.periodicFunc.evaluate(s)
endif
endmethod
private method DestroyAction takes nothing returns nothing
local group g
if FirstOfGroup(targets)!=null then
set g=NewGroup()
set bj_groupAddGroupDest=g
call ForGroup(Targets, function GroupAddGroupEnum)
call GroupClear(Targets)
if onRemoveFunc>0 then
call onRemoveFunc.evaluate(this, g)
endif
endif
call ReleaseTimer(T)
call ReleaseGroup(Targets)
call RemoveFromTable()
set Origin=null
call deallocate()
endmethod
private static method DestroyCallback takes nothing returns nothing
local thistype s=thistype(GetTimerData(GetExpiredTimer()))
call s.DestroyAction()
call ReleaseTimer(GetExpiredTimer())
endmethod
public method destroy takes nothing returns nothing
local timer t
if auraPersistenceTime>0 and FirstOfGroup(targets)!=null then
set t=NewTimer()
call SetTimerData(t, this)
call TimerStart(t, auraPersistenceTime, false, function thistype.DestroyCallback)
set Destroyed=true
else
call DestroyAction()
endif
endmethod
private method AddToTable takes nothing returns nothing
local integer id=GetUnitId(origin)
if id>0 then
set UnitAuraTable[id*8192+UnitAuraCount[id]]=this
set TablePos=UnitAuraCount[id]
set UnitAuraCount[id]=UnitAuraCount[id]+1
endif
endmethod
private method RemoveFromTable takes nothing returns nothing
local integer id=GetUnitId(origin)
if id>0 then
set UnitAuraCount[id]=UnitAuraCount[id]-1
set UnitAuraTable[id*8192+TablePos]=UnitAuraTable[id*8192+UnitAuraCount[id]]
set thistype(UnitAuraTable[id*8192+TablePos]).TablePos=TablePos
endif
endmethod
public static method create takes unit origin, real range, AuraFilter filterFunc, AuraOnAdd onAddFunc, AuraOnRemove onRemoveFunc returns thistype
local thistype s=allocate()
set s.origin=origin
set s.range=range
set s.filterFunc=filterFunc
set s.onAddFunc=onAddFunc
set s.onRemoveFunc=onRemoveFunc
set s.Targets=NewGroup()
set s.T=NewTimer()
call SetTimerData(s.T, integer(s))
call TimerStart(s.T, s.period, true, function thistype.Callback)
call s.AddToTable()
return s
endmethod
public static method createLoc takes real x, real y, real range, AuraFilter filterFunc, AuraOnAdd onAddFunc, AuraOnRemove onRemoveFunc returns thistype
local thistype s=allocate()
set s.origin=null
call s.setOriginPos(x, y)
set s.range=range
set s.filterFunc=filterFunc
set s.onAddFunc=onAddFunc
set s.onRemoveFunc=onRemoveFunc
set s.Targets=NewGroup()
set s.T=NewTimer()
call SetTimerData(s.T, integer(s))
call TimerStart(s.T, s.period, true, function thistype.Callback)
return s
endmethod
public method operator filterFunc takes nothing returns AuraFilter
return FilterFunc
endmethod
public method operator filterFunc= takes AuraFilter func returns nothing
set FilterFunc=func
endmethod
public method operator periodicFunc takes nothing returns AuraPeriodic
return PeriodicFunc
endmethod
public method operator periodicFunc= takes AuraPeriodic func returns nothing
set PeriodicFunc=func
endmethod
public method operator onAddFunc takes nothing returns AuraOnAdd
return OnAddFunc
endmethod
public method operator onAddFunc= takes AuraOnAdd func returns nothing
set OnAddFunc=func
endmethod
public method operator onRemoveFunc takes nothing returns AuraOnRemove
return OnRemoveFunc
endmethod
public method operator onRemoveFunc= takes AuraOnRemove func returns nothing
set OnRemoveFunc=func
endmethod
public method operator originX takes nothing returns real
return OriginX
endmethod
public method operator originY takes nothing returns real
return OriginY
endmethod
public method setOriginPos takes real x, real y returns nothing
set OriginX=x
set OriginY=y
set OriginUnit=false
call RemoveFromTable()
endmethod
public method operator origin takes nothing returns unit
return Origin
endmethod
public method operator origin= takes unit new returns nothing
call RemoveFromTable()
set Origin=new
call AddToTable()
set OriginUnit=new!=null
endmethod
public method operator targets takes nothing returns group
return Targets
endmethod
public method operator range takes nothing returns real
return Range
endmethod
public method operator range= takes real new returns nothing
set Range=new
endmethod
public method operator period takes nothing returns real
return Period
endmethod
public method operator period= takes real new returns nothing
set Period=new
call TimerStart(T, Period, true, function thistype.Callback)
endmethod
public method operator auraPersistenceTime takes nothing returns real
return AuraPersistenceTime
endmethod
public method operator auraPersistenceTime= takes real new returns nothing
set AuraPersistenceTime=new
endmethod
public method operator destroyed takes nothing returns boolean
return Destroyed
endmethod
private method DisableAction takes nothing returns nothing
local group g
set g=NewGroup()
set bj_groupAddGroupDest=g
call ForGroup(Targets, function GroupAddGroupEnum)
call GroupClear(Targets)
if onRemoveFunc>0 then
call onRemoveFunc.evaluate(this, g)
endif
endmethod
private static method DisableCallback takes nothing returns nothing
local thistype s=thistype(GetTimerData(GetExpiredTimer()))
call s.DisableAction()
call ReleaseTimer(GetExpiredTimer())
endmethod
public method operator enabled takes nothing returns boolean
return Enabled
endmethod
public method operator enabled= takes boolean new returns nothing
local timer t
if new==false and enabled==true and FirstOfGroup(targets)!=null then
// just got disabled and is affecting at least one unit
if auraPersistenceTime>0 then
set t=NewTimer()
call SetTimerData(t, this)
call TimerStart(t, auraPersistenceTime, false, function thistype.DisableCallback)
else
call DisableAction()
endif
endif
set Enabled=new
endmethod
public method operator destroyOnDeath takes nothing returns boolean
return DestroyOnDeath
endmethod
public method operator destroyOnDeath= takes boolean new returns nothing
set DestroyOnDeath=new
endmethod
public method operator disableOnDeath takes nothing returns boolean
return DisableOnDeath
endmethod
public method operator disableOnDeath= takes boolean new returns nothing
set DisableOnDeath=new
endmethod
public method operator enableOnResurrect takes nothing returns boolean
return EnableOnResurrect
endmethod
public method operator enableOnResurrect= takes boolean new returns nothing
set EnableOnResurrect=new
endmethod
private static method OnRemoved takes unit u returns nothing
local integer id=GetUnitId(u)
local integer i=UnitAuraCount[id]-1
loop
exitwhen i<0
call thistype(UnitAuraTable[id*8192+i]).destroy()
set i=i-1
endloop
endmethod
private static method OnDeath takes nothing returns nothing
local integer id=GetUnitId(GetTriggerUnit())
local integer i=UnitAuraCount[id]-1
local thistype s
loop
exitwhen i<0
set s=thistype(UnitAuraTable[id*8192+i])
if s.destroyOnDeath then
call s.destroy()
elseif s.disableOnDeath then
set s.enabled=false
endif
set i=i-1
endloop
endmethod
private static method OnResurrect takes unit u returns nothing
local integer id=GetUnitId(u)
local integer i=UnitAuraCount[id]-1
local thistype s
loop
exitwhen i<0
set s=thistype(UnitAuraTable[id*8192+i])
if s.enableOnResurrect then
set s.enabled=true
endif
set i=i-1
endloop
endmethod
private static method OnRevive takes nothing returns nothing
call OnResurrect(GetTriggerUnit())
endmethod
private static method onInit takes nothing returns nothing
local trigger t
set UnitAuraTable=Table.create()
call OnUnitDeindexed(thistype.OnRemoved)
set t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddAction(t, function thistype.OnDeath)
set t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_REVIVE_FINISH)
call TriggerAddAction(t, function thistype.OnRevive)
endmethod
endstruct
endlibrary
Again: Note that this is a preview and in no way meant as a final version. If you find something you think would need improvement, dont hesitate to tell me.