//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
TempPoint | location | No | |
TempUnit | unit | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*******************************************************************************
ARTESIA SPELLPACK v1.1.1
BY Ayanami
********************************************************************************
********************************************************************************
REQUIREMENTS
********************************************************************************
- JNGP
- CTL
- RegisterPlayerUnitEvent
- SpellEffectEvent
* Table
- Unit Indexer
* Event
- World Bounds
********************************************************************************
********************************************************************************
IMPLEMENTATION
********************************************************************************
1) Copy the whole "Required Systems" Trigger folder & paste in map
2) Copy all 6 abilities under "Human" & paste in map
3) Copy all 2 buffs under "Human" & paste in map
4) Ensure that the following abilities have their buff set properly:
* Arcane Missile (Slow) - Arcane Missile
* Dance of Death (Visual) - Dance of Death
5) Copy all 2 units under "Human - Units" & paste in map
* Arcane Bolt Dummy
* Arcane Missile Dummy
5) Copy the whole "Artesia Spellpack" Trigger folder
6) Go through all the spell Configurations
*******************************************************************************/
//TESH.scrollpos=105
//TESH.alwaysfold=0
library ArcaneMissile uses CTL, SpellEffectEvent, UnitIndexer, WorldBounds, ArcaneBolts
/*******************************************************************************
CONFIGURABLES
*******************************************************************************/
globals
private constant integer ABIL_ID = 'ABAM' // raw code of ability "Arcane Missile"
private constant integer DUM_ABIL_ID = 'AAM0' // raw code of ability "Arcane Missile (Slow)"
private constant integer BUFF_ID = 'BBAM' // raw code of buff "Arcane Missile"
private constant integer DUMMY_ID = 'duAM' // raw code of unit "Arcane Missile Dummy"
private constant integer RED = 255 // red vertex color of spell projectile
private constant integer GREEN = 255 // green vertex color of spell projectile
private constant integer BLUE = 255 // blue vertex color of spell projectile
private constant integer TRANS = 255 // transparency of spell projectile, where 0 is fully transparent
private constant real SCALE = 1.5 // scale size of spell projectile
private constant real HEIGHT = 100. // flying height of spell projectile
private constant real SPEED = 700. // distance travelled per second by spell projectile
private constant real COLLISION = 100. // collision contact size of spell projectile
private constant real ANGLE_RATE = 60. // maximum turning degree of spell projectile per second
private constant string FX = "Abilities\\Spells\\Human\\SpellSteal\\SpellStealMissile.mdl" // special effect used when damgage is dealt
private constant string FX_AT = "chest" // attachment point of FX
private constant boolean PRELOAD = true // preloads resources if true
private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type
private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type
endglobals
// area of effect
private constant function GetArea takes integer level returns real
return 150.0
endfunction
// damage dealt
private constant function GetDamage takes integer level returns real
return 40. * level + 60.
endfunction
// distance travelled by missile
private constant function GetDistance takes integer level returns real
return 1200.
endfunction
// slow duration
private constant function GetDuration takes integer level returns real
return 3.
endfunction
// homing detection area
private constant function GetHomeArea takes integer level returns real
return 600.
endfunction
// target types allowed for dealing damage
private constant function GetFilter takes unit caster, unit target returns boolean
return /*
*/ not IsUnitType(target, UNIT_TYPE_DEAD) and /* target is alive
*/ IsUnitEnemy(target, GetOwningPlayer(caster)) and /* target is an enemy of caster
*/ not IsUnitType(target, UNIT_TYPE_STRUCTURE) and /* target is not a structure
*/ not IsUnitType(target, UNIT_TYPE_MECHANICAL) and /* target is not mechanic
*/ not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) /* target is not magic immune
*/
endfunction
/*******************************************************************************
END CONFIGURABLES
*******************************************************************************/
globals
private group G = bj_lastCreatedGroup
endglobals
private struct Slow extends array
private static constant real TIMEOUT = 0.031250000
private static integer array store
private unit u
private real dur
implement CTLExpire
set this.dur = this.dur - TIMEOUT
if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) or GetUnitTypeId(this.u) == 0 then
set thistype.store[GetUnitUserData(this.u)] = 0
call UnitRemoveAbility(this.u, DUM_ABIL_ID)
call UnitRemoveAbility(this.u, BUFF_ID)
call this.destroy()
endif
implement CTLEnd
public static method apply takes unit u, real dur returns nothing
local thistype this
local integer id = GetUnitUserData(u)
if thistype.store[id] == 0 then
set this = thistype.create()
set this.u = u
set thistype.store[id] = this
call UnitAddAbility(u, DUM_ABIL_ID)
call UnitMakeAbilityPermanent(u, true, DUM_ABIL_ID)
else
set this = thistype.store[id]
endif
set this.dur = dur
endmethod
endstruct
private struct Main extends array
private static constant real TIMEOUT = 0.031250000
private static constant real TRUE_SPEED = SPEED * TIMEOUT
private static constant real TRUE_ANGLE_RATE = ANGLE_RATE * TIMEOUT * bj_DEGTORAD
private static constant real PI_2 = bj_PI * 2
private unit u
private unit dummy
private unit target
private real area
private real dmg
private real dist
private real dur
private real homeArea
private real sin
private real cos
implement CTL
local unit u
local unit target
local boolean b = false
local real x
local real y
local real dx
local real dy
local real r
local real minDist
local real facing
implement CTLExpire
set target = null
set b = false
set x = GetUnitX(this.dummy)
set y = GetUnitY(this.dummy)
set minDist = this.homeArea * this.homeArea
call GroupEnumUnitsInRange(G, x, y, this.homeArea + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
set dx = GetUnitX(u) - x
set dy = GetUnitY(u) - y
set r = dx * dx + dy * dy
if GetFilter(this.u, u) and IsUnitInRangeXY(u, x, y, this.homeArea) and r < minDist then
if IsUnitInRangeXY(u, x, y, COLLISION) then
set b = true
call GroupClear(G)
exitwhen true
else
set minDist = r
set target = u
endif
endif
endloop
if b then
call GroupEnumUnitsInRange(G, x, y, this.area + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if GetFilter(this.u, u) and IsUnitInRangeXY(u, x, y, this.area) then
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_AT))
call UnitDamageTarget(this.u, u, this.dmg, true, false, ATK, DMG, null)
call Slow.apply(u, this.dur)
endif
endloop
call KillUnit(this.dummy)
call this.destroy()
else
set this.target = target
set facing = GetUnitFacing(this.dummy) * bj_DEGTORAD
if this.target != null then
set r = Atan2(GetUnitY(this.target) - y, GetUnitX(this.target) - x)
if r < 0 then
set r = r + PI_2
endif
if facing < r then
set facing = facing + PI_2
endif
if facing - r < bj_PI then
set facing = facing - TRUE_ANGLE_RATE
elseif facing - r > bj_PI then
set facing = facing + TRUE_ANGLE_RATE
else
set facing = r
endif
endif
set x = x + TRUE_SPEED * Cos(facing)
set y = y + TRUE_SPEED * Sin(facing)
call SetUnitFacing(this.dummy, facing * bj_RADTODEG)
if x > WorldBounds.minX and y > WorldBounds.minY and x < WorldBounds.maxX and y < WorldBounds.maxY then
call SetUnitX(this.dummy, x)
call SetUnitY(this.dummy, y)
endif
set this.dist = this.dist - TRUE_SPEED
if this.dist <= 0 then
call KillUnit(this.dummy)
call this.destroy()
endif
endif
implement CTLNull
set u = null
set target = null
implement CTLEnd
private static method onCast takes nothing returns boolean
local thistype this = thistype.create()
local integer level
local real a
set this.u = GetTriggerUnit()
set a = Atan2(GetSpellTargetY() - GetUnitY(this.u), GetSpellTargetX() - GetUnitX(this.u))
set this.dummy = CreateUnit(GetOwningPlayer(this.u), DUMMY_ID, GetUnitX(this.u), GetUnitY(this.u), a * bj_RADTODEG)
set this.target = null
set level = GetUnitAbilityLevel(this.u, ABIL_ID)
set this.area = GetArea(level)
set this.dmg = GetDamage(level)
set this.dist = GetDistance(level)
set this.dur = GetDuration(level)
set this.homeArea = GetHomeArea(level)
call SetUnitVertexColor(this.dummy, RED, GREEN, BLUE, TRANS)
call SetUnitScale(this.dummy, SCALE, 0, 0)
call SetUnitFlyHeight(this.dummy, HEIGHT, 0)
return false
endmethod
private static method onInit takes nothing returns nothing
static if PRELOAD then
local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0)
call UnitAddAbility(u, DUM_ABIL_ID)
call RemoveUnit(u)
set u = null
endif
call RegisterSpellEffectEvent(ABIL_ID, function thistype.onCast)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DanceOfDeath requires CTL, SpellEffectEvent, UnitIndexer, ArcaneBolts
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABIL_ID = 'ABDD' // raw code of ability "Dance of Death"
private constant integer DUM_ABIL_ID = 'ADD0' // raw code of ability "Dance of Death (Visual)"
private constant integer BUFF_ID = 'BBDD' // raw code of buff "Dance of Death"
private constant string ORDER_STRING = "absorb" // order id of ability "Dance of Death"
private constant boolean PRELOAD = true // preloads resources if true
endglobals
// amount healed per second
private function GetHeal takes integer level, unit u returns real
return (10. * level + 20.) + (0.05 * level + 0.05) * GetHeroInt(u, true)
endfunction
private function GetInterval takes integer level returns real
return 0.8 - 0.1 * level
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
private struct Main extends array
private static integer array store
private unit u
private integer level
private real amount
private real interval
private real intervalCount
implement CTL
local integer id = OrderId(ORDER_STRING)
implement CTLExpire
if GetUnitCurrentOrder(this.u) != id then
set thistype.store[GetUnitUserData(this.u)] = 0
call UnitRemoveAbility(this.u, DUM_ABIL_ID)
call UnitRemoveAbility(this.u, BUFF_ID)
call this.destroy()
else
if this.level > 0 then
if this.intervalCount <= 0 then
set this.intervalCount = this.interval
call ArcaneBolt.new(this.u, GetUnitX(this.u), GetUnitY(this.u))
else
set this.intervalCount = this.intervalCount - 0.031250000
endif
endif
call SetWidgetLife(this.u, GetWidgetLife(this.u) + this.amount)
endif
implement CTLEnd
private static method onCast takes nothing returns boolean
local thistype this
local unit u = GetTriggerUnit()
local integer id = GetUnitUserData(u)
local integer level = GetUnitAbilityLevel(u, ABIL_ID)
if thistype.store[id] == 0 then
set this = thistype.create()
set this.u = u
set thistype.store[id] = this
call UnitAddAbility(u, DUM_ABIL_ID)
else
set this = thistype.store[id]
endif
set this.level = GetUnitAbilityLevel(u, ArcaneBolt.ID)
set this.amount = GetHeal(level, u) * 0.031250000
set this.interval = GetInterval(level)
set this.intervalCount = this.interval
set u = null
return false
endmethod
private static method onInit takes nothing returns nothing
static if PRELOAD then
local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'hpea', 0, 0, 0)
call UnitAddAbility(u, DUM_ABIL_ID)
call RemoveUnit(u)
set u = null
endif
call RegisterSpellEffectEvent(ABIL_ID, function thistype.onCast)
endmethod
endstruct
endlibrary
//TESH.scrollpos=170
//TESH.alwaysfold=0
library ArcaneBolts uses CTL, SpellEffectEvent, UnitIndexer
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABIL_ID = 'ABAB' // raw code of ability "Arcane Bolts"
private constant integer DUMMY_ID = 'duAB' // raw code of unit "Arcane Bolts Dummy"
private constant integer RED = 255 // red vertex color of projectile
private constant integer GREEN = 255 // green vertex color of projectile
private constant integer BLUE = 255 // blue vertex color of projectile
private constant integer TRANS = 255 // transparency of projectile, where 0 is fully transparent
private constant real SCALE = 1. // scale size of projectile
private constant real HEIGHT = 100. // height of projectile
private constant real SPEED = 700. // distance travelled per second by projectile
private constant real COLLISION = 100. // collision contact size of projectile
private constant real ANGLE_RATE = 520. // maximum turning degree of projectile per second, set to 0 to disable projectile arc
private constant boolean RANDOM_SEEK = true // seeks target randomly if true, seeks closest target if false
private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
private constant boolean PRELOAD = true // preloads resources if true
private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type
private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type
endglobals
// area of effect
private constant function GetArea takes integer level returns real
return 700.0
endfunction
// number of bolts produced per spell cast
private constant function GetBoltCount takes integer level returns integer
return 2
endfunction
// damage dealt
private constant function GetDamage takes integer level returns real
return 15. * level + 10.
endfunction
// delay between bolts
private constant function GetDelay takes integer level returns real
return 0.8
endfunction
// target types allowed for dealing damage
private constant function GetFilter takes unit caster, unit target returns boolean
return /*
*/ not IsUnitType(target, UNIT_TYPE_DEAD) and /* // target is alive
*/ IsUnitEnemy(target, GetOwningPlayer(caster)) and /* // target is an enemy of caster
*/ not IsUnitType(target, UNIT_TYPE_STRUCTURE) and /* // target is not a structure
*/ not IsUnitType(target, UNIT_TYPE_MECHANICAL) and /* // target is not mechanic
*/ not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) //target is not magic immune
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
globals
private group G = bj_lastCreatedGroup
endglobals
private struct ArcaneBolt extends array
readonly static constant integer ID = ABIL_ID
private static constant real TRUE_SPEED = SPEED * 0.031250000
private static constant real TRUE_COLLISION = COLLISION * COLLISION
private static constant real PI_2 = bj_PI * 2
private static constant real TRUE_ANGLE_RATE = ANGLE_RATE * 0.031250000 * bj_DEGTORAD
private unit u
private unit dummy
private unit target
private real damage
private method fin takes nothing returns nothing
call KillUnit(this.dummy)
set this.u = null
set this.dummy = null
set this.target = null
call this.destroy()
endmethod
implement CTL
local real x
local real y
local real dx
local real dy
local real a
local real facing
implement CTLExpire
if IsUnitType(this.target, UNIT_TYPE_DEAD) or GetUnitTypeId(this.target) == 0 or GetUnitTypeId(this.u) == 0 then
call this.fin()
else
set x = GetUnitX(this.dummy)
set y = GetUnitY(this.dummy)
set dx = GetUnitX(this.target) - x
set dy = GetUnitY(this.target) - y
if dx * dx + dy * dy <= thistype.TRUE_COLLISION then
call UnitDamageTarget(this.u, this.target, this.damage, true, false, ATK, DMG, null)
call this.fin()
else
set a = Atan2(dy, dx)
if ANGLE_RATE > 0 then
set facing = GetUnitFacing(this.dummy) * bj_DEGTORAD
if a < 0 then
set a = a + thistype.PI_2
endif
if facing < a then
set facing = facing + thistype.PI_2
endif
if facing - a < bj_PI then
set a = facing - thistype.TRUE_ANGLE_RATE
elseif facing - a > bj_PI then
set a = facing + thistype.TRUE_ANGLE_RATE
endif
endif
set x = x + thistype.TRUE_SPEED * Cos(a)
set y = y + thistype.TRUE_SPEED * Sin(a)
call SetUnitFacing(this.dummy, a * bj_RADTODEG)
if x > WorldBounds.minX and y > WorldBounds.minY and x < WorldBounds.maxX and y < WorldBounds.maxY then
call SetUnitX(this.dummy, x)
call SetUnitY(this.dummy, y)
endif
endif
endif
implement CTLEnd
public static method new takes unit caster, real x, real y returns thistype
local thistype this
local unit u
local unit target = null
local integer level = GetUnitAbilityLevel(caster, ABIL_ID)
local real area = GetArea(level)
static if RANDOM_SEEK then
local integer rand = 0
call GroupEnumUnitsInRange(G, x, y, area + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if IsUnitInRange(u, caster, area) and GetFilter(caster, u) then
set rand = rand + 1
if GetRandomInt(1, rand) == 1 then
set target = u
endif
endif
endloop
else
local real dist = area * area
local real r
local real dx
local real dy
call GroupEnumUnitsInRange(G, x, y, area + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if IsUnitInRange(u, caster, area) and GetFilter(caster, u) then
set dx = GetUnitX(u) - x
set dy = GetUnitY(u) - y
set r = dx * dx + dy * dy
if r <= dist then
set target = u
set dist = r
endif
endif
endloop
endif
if target != null then
set this = thistype.create()
set this.u = caster
set this.dummy = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, x, y, GetRandomReal(0., 360.))
set this.target = target
set this.damage = GetDamage(level)
call SetUnitVertexColor(this.dummy, RED, GREEN, BLUE, TRANS)
call SetUnitScale(this.dummy, SCALE, 0, 0)
call SetUnitFlyHeight(this.dummy, HEIGHT, 0)
endif
set u = null
set target = null
return this
endmethod
endstruct
private struct Main extends array
private static thistype array store
private unit u
private integer boltCount
private real delay
implement CTLExpire
if GetUnitTypeId(this.u) == 0 or GetUnitAbilityLevel(this.u, ABIL_ID) == 0 then
set thistype.store[GetUnitUserData(this.u)] = 0
call this.destroy()
elseif this.boltCount > 0 then
if this.delay <= 0 then
set this.boltCount = this.boltCount - 1
set this.delay = GetDelay(GetUnitAbilityLevel(this.u, ABIL_ID))
call ArcaneBolt.new(this.u, GetUnitX(this.u), GetUnitY(this.u))
else
set this.delay = this.delay - 0.031250000
endif
endif
implement CTLEnd
private static method onCast takes nothing returns boolean
local thistype this = thistype.store[GetUnitUserData(GetTriggerUnit())]
if this != 0 then
set this.boltCount = this.boltCount + GetBoltCount(GetUnitAbilityLevel(this.u, ABIL_ID))
endif
return false
endmethod
private static method onLearn takes nothing returns boolean
local thistype this
local integer level = GetUnitAbilityLevel(GetTriggerUnit(), ABIL_ID)
if GetLearnedSkill() == ABIL_ID and level == 1 then
set this = thistype.create()
set this.u = GetTriggerUnit()
set this.boltCount = 0
set this.delay = GetDelay(level)
set thistype.store[GetUnitUserData(this.u)] = this
endif
return false
endmethod
private static method onInit takes nothing returns nothing
static if PRELOAD then
call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0))
endif
call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_SKILL, function thistype.onLearn)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CTL /* v1.2.0.2
*************************************************************************************
*
* CTL or Constant Timer Loop provides a loop for constant merged timers of timeout .03125
*
* Similar to T32 but pauses timer when no structs have instances and removes structs
* from timer trigger when those structs have no instances.
*
* This can also create new timers after destroying a previous timer and generates less
* code in the module. It also generates no triggers so long as the module is implemented
* at the top of the struct.
*
************************************************************************************
*
* module CTL
*
* Allows creation/destruction of timers in a struct. Provides instancing of those timers.
*
* - static method create takes nothing returns thistype
* - method destroy takes nothing returns nothing
*
* CTL (optional)
* local variables, code before running any timers
* CTLExpire (not optional)
* timer code
* CTLNull (optional)
* null any locals, runs after all timers
* CTLEnd (not optional)
*
* module CT32
*
* Converts struct into a timer group. Allows the timer group to be started and stopped.
* Instancing and looping through active timers is up to the user.
*
* - static method start takes nothing returns nothing
* - static method stop takes nothing returns nothing
*
* CT32 (not optional)
* timer code
* CT32End (not optional)
*
* struct TimerGroup32 extends array
*
* Allows for the creation of timer groups. Timer instancing and looping is entirely up
* to the user.
*
* - static method create takes code func returns thistype
* - method destroy takes nothing returns nothing
* - method start takes nothing returns nothing
* - method stop takes nothing returns nothing
*
************************************************************************************/
globals
private integer tgc = 0 //timer group count
private integer array tgr //timer group recycler
private integer ic=0 //instance count
private integer tc=0 //timer count
private integer array rf //root first
private integer array n //next
private integer array p //previous
private integer array th //timer head
private integer array ns //next stack
private trigger t=CreateTrigger()
private timer m=CreateTimer()
private triggercondition array ct
private conditionfunc array rc
private boolean array e32 //enabled
private integer array i32r //ct32 recycler
private integer i32cr = 0 //ct32 count recycler
private boolean array ir32 //is recycling
private boolean array id32 //is destroying
endglobals
private function E takes nothing returns nothing
local integer i=ns[0]
set ns[0]=0
loop
exitwhen 0==i
if (0==p[i]) then
if (0==n[i]) then
call TriggerRemoveCondition(t,ct[th[i]])
set ct[th[i]]=null
set tc=tc-1
set rf[th[i]]=0
else
set rf[th[i]]=n[i]
set p[n[i]]=0
endif
else
set p[n[i]]=p[i]
set n[p[i]]=n[i]
endif
set n[i]=n[0]
set n[0]=i
set i=ns[i]
endloop
loop
exitwhen 0 == i32cr
set i32cr = i32cr - 1
set i = i32r[i32cr]
if (not e32[i]) then
call TriggerRemoveCondition(t,ct[i])
set ct[i] = null
if (id32[i]) then
set tgr[i] = tgr[0]
set tgr[0] = i
set id32[i] = false
endif
set ir32[i] = false
endif
endloop
if (0==tc) then
call PauseTimer(m)
else
call TriggerEvaluate(t)
endif
endfunction
private function CT takes integer r returns integer
local integer i
local integer f
if (0==n[0]) then
set i=ic+1
set ic=i
else
set i=n[0]
set n[0]=n[i]
endif
set th[i]=r
set ns[i]=-1
set f=rf[r]
if (0==f) then
set n[i]=0
set p[i]=0
set rf[r]=i
set ct[r]=TriggerAddCondition(t,rc[r])
//set ct[r] = null
if (0==tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc=tc+1
else
set n[i]=f
set p[i]=0
set p[f]=i
set rf[r]=i
endif
return i
endfunction
private function DT takes integer t returns nothing
debug if (0>ns[t]) then
set ns[t]=ns[0]
set ns[0]=t
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"TIMER LOOP ERROR: ATTEMPT TO DESTROY NULL TIMER")
debug endif
endfunction
private function A takes code c returns integer
local integer i = tgr[0]
if (0 == i) then
set i = tgc + 1
set tgc = i
else
set tgr[0] = tgr[i]
endif
set rc[i]=Condition(c)
return i
endfunction
private function A32 takes integer i returns nothing
if (not (e32[i] or id32[i])) then
if (ir32[i]) then
set ir32[i] = false
else
set ct[i] = TriggerAddCondition(t, rc[i])
endif
if (0 == tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc = tc + 1
set e32[i] = true
endif
endfunction
private function SR32 takes integer i returns nothing
if (e32[i]) then
if (not (ir32[i] or id32[i])) then
set i32r[i32cr] = i
set i32cr = i32cr + 1
set ir32[i] = true
endif
set e32[i] = false
set tc = tc - 1
endif
endfunction
private function DT32 takes integer i returns nothing
if (not id32[i]) then
if (not ir32[i]) then
set ir32[i] = true
set tc = tc - 1
set i32r[i32cr] = i
set i32cr = i32cr + 1
set e32[i] = false
endif
set id32[i] = true
endif
endfunction
private keyword r
private keyword e
module CTL
static integer rctl32
static method create takes nothing returns thistype
return CT(rctl32)
endmethod
method destroy takes nothing returns nothing
call DT(this)
endmethod
static method ectl32 takes nothing returns boolean
local thistype this=rf[rctl32]
endmodule
module CTLExpire
implement CTL
loop
exitwhen 0==this
endmodule
module CTLNull
set this=n[this]
endloop
endmodule
module CTLEnd
implement CTLNull
return false
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
module CT32
static integer rctl32
static method ectl32 takes nothing returns boolean
endmodule
module CT32End
return false
endmethod
static method start takes nothing returns nothing
call A32(rctl32)
endmethod
static method stop takes nothing returns nothing
call SR32(rctl32)
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
struct TimerGroup32 extends array
static method create takes code c returns thistype
return A(c)
endmethod
method destroy takes nothing returns nothing
call DT32(this)
endmethod
method start takes nothing returns nothing
call A32(this)
endmethod
method stop takes nothing returns nothing
call SR32(this)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Event
//2.0.0.1
/////////////////////////////////////////////////////////////////////////
//function CreateEvent takes nothing returns integer
//function TriggerRegisterEvent takes trigger t, integer ev returns nothing
//function RegisterEvent takes boolexpr c, integer ev returns nothing
//function FireEvent takes integer ev returns nothing
//struct Event extends array
//static method create takes nothing returns thistype
//method registerTrigger takes trigger t returns nothing
//method register takes boolexpr c returns nothing
//method fire takes nothing returns nothing
/////////////////////////////////////////////////////////////////////////
globals
private real q=0
endglobals
struct Event extends array
private static integer w=0
private static trigger array e
static method create takes nothing returns thistype
set w=w+1
set e[w]=CreateTrigger()
return w
endmethod
method registerTrigger takes trigger t returns nothing
call TriggerRegisterVariableEvent(t,SCOPE_PRIVATE+"q",EQUAL,this)
endmethod
method register takes boolexpr c returns nothing
call TriggerAddCondition(e[this],c)
endmethod
method fire takes nothing returns nothing
set q=0
set q=this
call TriggerEvaluate(e[this])
endmethod
endstruct
function CreateEvent takes nothing returns Event
return Event.create()
endfunction
function TriggerRegisterEvent takes trigger t,Event ev returns nothing
call ev.registerTrigger(t)
endfunction
function RegisterEvent takes boolexpr c,Event ev returns nothing
call ev.register(c)
endfunction
function FireEvent takes Event ev returns nothing
call ev.fire()
endfunction
endlibrary
//TESH.scrollpos=21
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v4.1.0.0
* By Magtheridon96
*
* This library was made to replace that GTrigger
* monster by Jesus4Lyf at TheHelper. I would like
* to give a special thanks to Bribe and azlier for
* improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must
* return false. They can return nothing as well.
*
* API:
* ----
*
* function RegisterPlayerUnitEvent
* takes
* playerunitevent whichEvent : The event that will be registered.
* code whichFunction : The function that will fire when the event occurs.
* returns
* nothing
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
private boolexpr array b
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if null == t[i] then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen 0 == k
set k = k - 1
endloop
set b[i] = Filter(c)
else
call TriggerClearConditions(t[i])
set b[i] = Or(b[i], Filter(c))
endif
call TriggerAddCondition(t[i], b[i])
endfunction
endlibrary
//TESH.scrollpos=3
//TESH.alwaysfold=0
//============================================================================
// SpellEffectEvent
// - Version 1.0.0.1
//
// API
// ---
// RegisterSpellEffectEvent(integer abil, code onCast)
//
// Requires
// --------
// Table: hiveworkshop.com/forums/showthread.php?t=188084
// RegisterPlayerUnitEvent: hiveworkshop.com/forums/showthread.php?t=203338
//
library SpellEffectEvent requires RegisterPlayerUnitEvent, Table
globals
private Table tb
endglobals
//============================================================================
function RegisterSpellEffectEvent takes integer abil, code onCast returns nothing
if not tb.handle.has(abil) then
set tb.trigger[abil] = CreateTrigger()
endif
call TriggerAddCondition(tb.trigger[abil], Filter(onCast))
endfunction
//============================================================================
private module M
static method onCast takes nothing returns boolean
return TriggerEvaluate(tb.trigger[GetSpellAbilityId()])
endmethod
private static method onInit takes nothing returns nothing
set tb = Table.create()
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endmodule
//============================================================================
private struct S extends array
implement M
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 3.1.0.1
One map, one hashtable. Welcome to NewTable 3.1
This library was originally called NewTable so it didn't conflict with
the API of Table by Vexorian. However, the damage is done and it's too
late to change the library name now. To help with damage control, I
have provided an extension library called TableBC, which bridges all
the functionality of Vexorian's Table except for 2-D string arrays &
the ".flush(integer)" method. I use ".flush()" to flush a child hash-
table, because I wanted the API in NewTable to reflect the API of real
hashtables (I thought this would be more intuitive).
API
------------
struct Table
| static method create takes nothing returns Table
| create a new Table
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush all stored values inside of it
|
| method remove takes integer key returns nothing
| remove the value at index "key"
|
| method operator []= takes integer key, $TYPE$ value returns nothing
| assign "value" to index "key"
|
| method operator [] takes integer key returns $TYPE$
| load the value at index "key"
|
| method has takes integer key returns boolean
| whether or not the key was assigned
|
----------------
struct TableArray
| static method operator [] takes integer array_size returns TableArray
| create a new array of Tables of size "array_size"
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush and destroy it
|
| method operator size takes nothing returns integer
| returns the size of the TableArray
|
| method operator [] takes integer key returns Table
| returns a Table accessible exclusively to index "key"
*/
globals
private integer less = 0 //Index generation for TableArrays (below 0).
private integer more = 8190 //Index generation for Tables.
//Configure it if you use more than 8190 "key" variables in your map (this will never happen though).
private hashtable ht = InitHashtable()
private key sizeK
private key listK
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return sizeK
endmethod
static method operator list takes nothing returns Table
return listK
endmethod
endstruct
private struct handles extends array
method has takes integer key returns boolean
return HaveSavedHandle(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedHandle(ht, this, key)
endmethod
endstruct
private struct agents extends array
method operator []= takes integer key, agent value returns nothing
call SaveAgentHandle(ht, this, key, value)
endmethod
endstruct
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$(ht, this, key, value)
endmethod
method has takes integer key returns boolean
return HaveSaved$SUPER$(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSaved$SUPER$(ht, this, key)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$Handle(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$Handle(ht, this, key, value)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//Run these textmacros to include the entire hashtable API as wrappers.
//Don't be intimidated by the number of macros - Vexorian's map optimizer is
//supposed to kill functions which inline (all of these functions inline).
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
struct Table extends array
// Implement modules for intuitive syntax (tb.handle; tb.unit; etc.)
implement realm
implement booleanm
implement stringm
implement playerm
implement widgetm
implement destructablem
implement itemm
implement unitm
implement abilitym
implement timerm
implement triggerm
implement triggerconditionm
implement triggeractionm
implement eventm
implement forcem
implement groupm
implement locationm
implement rectm
implement boolexprm
implement soundm
implement effectm
implement unitpoolm
implement itempoolm
implement questm
implement questitemm
implement defeatconditionm
implement timerdialogm
implement leaderboardm
implement multiboardm
implement multiboarditemm
implement trackablem
implement dialogm
implement buttonm
implement texttagm
implement lightningm
implement imagem
implement ubersplatm
implement regionm
implement fogstatem
implement fogmodifierm
implement hashtablem
method operator handle takes nothing returns handles
return this
endmethod
method operator agent takes nothing returns agents
return this
endmethod
//set this = tb[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key)
endmethod
//set tb[389034] = 8192
method operator []= takes integer key, Table tb returns nothing
call SaveInteger(ht, this, key, tb)
endmethod
//set b = tb.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key)
endmethod
//call tb.remove(294080)
method remove takes integer key returns nothing
call RemoveSavedInteger(ht, this, key)
endmethod
//Remove all data from a Table instance
method flush takes nothing returns nothing
call FlushChildHashtable(ht, this)
endmethod
//local Table tb = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set this = more + 1
set more = this
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this) //Clear hashed memory
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call tb.destroy()
//
method destroy takes nothing returns nothing
debug if dex.list[this] != -1 then
debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
debug return
debug endif
call this.flush()
set dex.list[this] = dex.list[0]
set dex.list[0] = this
endmethod
//! runtextmacro optional TABLE_BC_METHODS()
endstruct
//! runtextmacro optional TABLE_BC_STRUCTS()
struct TableArray extends array
//Returns a new TableArray to do your bidding. Simply use:
//
// local TableArray ta = TableArray[array_size]
//
static method operator [] takes integer array_size returns TableArray
local Table tb = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = tb[0] //The last-destroyed TableArray that had this array size
debug if array_size <= 0 then
debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
debug return 0
debug endif
if this == 0 then
set this = less - array_size
set less = this
else
set tb[0] = tb[this] //Set the last destroyed to the last-last destroyed
call tb.remove(this) //Clear hashed memory
endif
set dex.size[this] = array_size //This remembers the array size
return this
endmethod
//Returns the size of the TableArray
method operator size takes nothing returns integer
return dex.size[this]
endmethod
//This magic method enables two-dimensional[array][syntax] for Tables,
//similar to the two-dimensional utility provided by hashtables them-
//selves.
//
//ta[integer a].unit[integer b] = unit u
//ta[integer a][integer c] = integer d
//
//Inline-friendly when not running in debug mode
//
method operator [] takes integer key returns Table
static if DEBUG_MODE then
local integer i = this.size
if i == 0 then
call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
return 0
elseif key < 0 or key >= i then
call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
return 0
endif
endif
return this + key
endmethod
//Destroys a TableArray without flushing it; I assume you call .flush()
//if you want it flushed too. This is a public method so that you don't
//have to loop through all TableArray indices to flush them if you don't
//need to (ie. if you were flushing all child-keys as you used them).
//
method destroy takes nothing returns nothing
local Table tb = dex.size[this.size]
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
debug return
debug endif
if tb == 0 then
//Create a Table to index recycled instances with their array size
set tb = Table.create()
set dex.size[this.size] = tb
endif
call dex.size.remove(this) //Clear the array size from hash memory
set tb[this] = tb[0]
set tb[0] = this
endmethod
private static Table tempTable
private static integer tempEnd
//Avoids hitting the op limit
private static method clean takes nothing returns nothing
local Table tb = .tempTable
local integer end = tb + 0x1000
if end < .tempEnd then
set .tempTable = end
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
else
set end = .tempEnd
endif
loop
call tb.flush()
set tb = tb + 1
exitwhen tb == end
endloop
endmethod
//Flushes the TableArray and also destroys it. Doesn't get any more
//similar to the FlushParentHashtable native than this.
//
method flush takes nothing returns nothing
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
set .tempTable = this
set .tempEnd = this + this.size
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
call this.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitIndexer /* v4.0.2.5
*************************************************************************************
*
* Assigns unique indexes to units via unit user data.
*
*************************************************************************************
*
* */uses/*
* */ WorldBounds /* hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
* */ Event /* hiveworkshop.com/forums/submissions-414/snippet-event-186555/
*
************************************************************************************
*
* SETTINGS
*/
globals
constant integer ABILITIES_UNIT_INDEXER = 'A001'
endglobals
/*
************************************************************************************
*
* Functions
*
* function RegisterUnitIndexEvent takes boolexpr codeToRegister, Event unitIndexEvent returns nothing
* function TriggerRegisterUnitIndexEvent takes trigger triggerToRegister, Event unitIndexEvent returns nothing
*
* function GetUnitById takes integer index returns unit
* - Returns unit given a unit index
* function GetUnitId takes unit u returns integer
* - Returns unit index given a unit
*
* function IsUnitIndexed takes unit u returns boolean
* function IsUnitDeindexing takes unit u returns boolean
*
* function GetIndexedUnitId takes nothing returns integer
* function GetIndexedUnit takes nothing returns unit
*
************************************************************************************
*
* module UnitIndexStruct
*
* - A pseudo module interface that runs a set of methods if they exist and provides
* - a few fields and operators. Runs on static ifs to minimize code.
*
* static method operator [] takes unit u returns thistype
* - Return GetUnitUserData(u)
*
* readonly unit unit
* - The indexed unit of the struct
* readonly boolean allocated
* - Is unit allocated for the struct
*
* Interface:
*
* - These methods don't have to exist. If they don't exist, the code
* - that calls them won't even be in the module.
*
* private method index takes nothing returns nothing
* - called when a unit is indexed and passes the filter.
* -
* - thistype this: Unit's index
* private method deindex takes nothing returns nothing
* - called when a unit is deindexed and is allocated for struct
* -
* - thistype this: Unit's index
* private static method filter takes unit unitToIndex returns boolean
* - Determines whether or not to allocate struct for unit
* -
* - unit unitToIndex: Unit being filtered
*
************************************************************************************
*
* struct UnitIndexer extends array
*
* - Controls the unit indexer system.
*
* static constant Event UnitIndexer.INDEX
* static constant Event UnitIndexer.DEINDEX
* - Don't register functions and triggers directly to the events. Register them via
* - RegisterUnitIndexEvent and TriggerRegisterUnitIndexEvent.
*
* static boolean enabled
* - Enables and disables unit indexing. Useful for filtering out dummy units.
*
************************************************************************************
*
* struct UnitIndex extends array
*
* - Constrols specific unit indexes.
*
* method lock takes nothing returns nothing
* - Locks an index. When an index is locked, it will not be recycled
* - when the unit is deindexed until all locks are removed. Deindex
* - events still fire at the appropriate times, the index just doesn't
* - get thrown into the recycler.
* method unlock takes nothing returns nothing
* - Unlocks an index.
*
************************************************************************************/
globals
private trigger q=CreateTrigger()
private trigger l=CreateTrigger()
private unit array e
private integer r=0
private integer y=0
private integer o=0
private boolean a=false
private integer array n
private integer array p
private integer array lc
endglobals
function GetIndexedUnitId takes nothing returns integer
return o
endfunction
function GetIndexedUnit takes nothing returns unit
return e[o]
endfunction
//! runtextmacro optional UNIT_LIST_LIB()
private struct PreLoader extends array
public static method run takes nothing returns nothing
call DestroyTimer(GetExpiredTimer())
set a=true
endmethod
public static method eval takes trigger t returns nothing
local integer f=n[0]
local integer d=o
loop
exitwhen 0==f
if (IsTriggerEnabled(t)) then
set o=f
if (TriggerEvaluate(t)) then
call TriggerExecute(t)
endif
else
exitwhen true
endif
set f=n[f]
endloop
set o=d
endmethod
public static method evalb takes boolexpr c returns nothing
local trigger t=CreateTrigger()
local thistype f=n[0]
local integer d=o
call TriggerAddCondition(t,c)
loop
exitwhen 0==f
set o=f
call TriggerEvaluate(t)
set f=n[f]
endloop
call DestroyTrigger(t)
set t=null
set o=d
endmethod
endstruct
//! runtextmacro optional UNIT_EVENT_MACRO()
private module UnitIndexerInit
private static method onInit takes nothing returns nothing
local integer i=15
local boolexpr bc=Condition(function thistype.onLeave)
local boolexpr bc2=Condition(function thistype.onEnter)
local group g=CreateGroup()
local player p
set INDEX=CreateEvent()
set DEINDEX=CreateEvent()
call TriggerRegisterEnterRegion(q,WorldBounds.worldRegion,bc2)
loop
set p=Player(i)
call TriggerRegisterPlayerUnitEvent(l,p,EVENT_PLAYER_UNIT_ISSUED_ORDER,bc)
call SetPlayerAbilityAvailable(p,ABILITIES_UNIT_INDEXER,false)
call GroupEnumUnitsOfPlayer(g,p,bc2)
exitwhen 0==i
set i=i-1
endloop
call DestroyGroup(g)
set bc=null
set g=null
set bc2=null
set p=null
call TimerStart(CreateTimer(),0,false,function PreLoader.run)
endmethod
endmodule
struct UnitIndex extends array
method lock takes nothing returns nothing
debug if (null!=e[this]) then
set lc[this]=lc[this]+1
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"UNIT INDEXER ERROR: ATTEMPT TO LOCK NULL INDEX")
debug endif
endmethod
method unlock takes nothing returns nothing
debug if (0<lc[this]) then
set lc[this]=lc[this]-1
if (0==lc[this] and null==e[this]) then
set n[this]=y
set y=this
endif
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"UNIT INDEXER ERROR: ATTEMPT TO UNLOCK UNLOCKED INDEX")
debug endif
endmethod
endstruct
struct UnitIndexer extends array
readonly static Event INDEX
readonly static Event DEINDEX
static boolean enabled=true
private static method onEnter takes nothing returns boolean
local unit Q=GetFilterUnit()
local integer i
local integer d=o
if (enabled and Q!=e[GetUnitUserData(Q)]) then
if (0==y) then
set r=r+1
set i=r
else
set i=y
set y=n[y]
endif
call UnitAddAbility(Q,ABILITIES_UNIT_INDEXER)
call UnitMakeAbilityPermanent(Q,true,ABILITIES_UNIT_INDEXER)
call SetUnitUserData(Q,i)
set e[i]=Q
static if not LIBRARY_UnitList then
if (not a)then
set p[i]=p[0]
set n[p[0]]=i
set n[i]=0
set p[0]=i
endif
else
set p[i]=p[0]
set n[p[0]]=i
set n[i]=0
set p[0]=i
call GroupAddUnit(g,e[i])
endif
set o=i
call FireEvent(INDEX)
set o=d
endif
set Q=null
return false
endmethod
private static method onLeave takes nothing returns boolean
static if LIBRARY_UnitEvent then
implement optional UnitEventModule
else
local unit u=GetFilterUnit()
local integer i=GetUnitUserData(u)
local integer d=o
if (0==GetUnitAbilityLevel(u,ABILITIES_UNIT_INDEXER) and u==e[i]) then
static if not LIBRARY_UnitList then
if (not a)then
set n[p[i]]=n[i]
set p[n[i]]=p[i]
endif
else
set n[p[i]]=n[i]
set p[n[i]]=p[i]
call GroupRemoveUnit(g,e[i])
endif
set o=i
call FireEvent(DEINDEX)
set o=d
if (0==lc[i]) then
set n[i]=y
set y=i
endif
set e[i]=null
endif
set u=null
endif
return false
endmethod
implement UnitIndexerInit
endstruct
//! runtextmacro optional UNIT_EVENT_MACRO_2()
function RegisterUnitIndexEvent takes boolexpr c,integer ev returns nothing
call RegisterEvent(c, ev)
if (not a and ev==UnitIndexer.INDEX and 0!=n[0]) then
call PreLoader.evalb(c)
endif
endfunction
function TriggerRegisterUnitIndexEvent takes trigger t,integer ev returns nothing
call TriggerRegisterEvent(t,ev)
if (not a and ev == UnitIndexer.INDEX and 0!=n[0]) then
call PreLoader.eval(t)
endif
endfunction
function GetUnitById takes integer W returns unit
return e[W]
endfunction
function GetUnitId takes unit u returns integer
return GetUnitUserData(u)
endfunction
function IsUnitIndexed takes unit u returns boolean
return u==e[GetUnitUserData(u)]
endfunction
function IsUnitDeindexing takes unit u returns boolean
return IsUnitIndexed(u) and 0==GetUnitAbilityLevel(u,ABILITIES_UNIT_INDEXER)
endfunction
module UnitIndexStruct
static method operator [] takes unit u returns thistype
return GetUnitUserData(u)
endmethod
method operator unit takes nothing returns unit
return e[this]
endmethod
static if thistype.filter.exists then
static if thistype.index.exists then
static if thistype.deindex.exists then
readonly boolean allocated
else
method operator allocated takes nothing returns boolean
return filter(e[this])
endmethod
endif
else
method operator allocated takes nothing returns boolean
return filter(e[this])
endmethod
endif
elseif (thistype.index.exists) then
static if thistype.deindex.exists then
readonly boolean allocated
else
method operator allocated takes nothing returns boolean
return this==GetUnitUserData(e[this])
endmethod
endif
else
method operator allocated takes nothing returns boolean
return this==GetUnitUserData(e[this])
endmethod
endif
static if thistype.index.exists then
private static method onIndexEvent takes nothing returns boolean
static if thistype.filter.exists then
if (filter(e[o])) then
static if thistype.deindex.exists then
set thistype(o).allocated=true
endif
call thistype(o).index()
endif
else
static if thistype.deindex.exists then
set thistype(o).allocated=true
endif
call thistype(o).index()
endif
return false
endmethod
endif
static if thistype.deindex.exists then
private static method onDeindexEvent takes nothing returns boolean
static if thistype.filter.exists then
static if thistype.index.exists then
if (thistype(o).allocated) then
set thistype(o).allocated=false
call thistype(o).deindex()
endif
else
if (filter(e[o])) then
call thistype(o).deindex()
endif
endif
else
static if thistype.index.exists then
set thistype(o).allocated=false
endif
call thistype(o).deindex()
endif
return false
endmethod
endif
static if thistype.index.exists then
static if thistype.deindex.exists then
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onIndexEvent),UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.onDeindexEvent),UnitIndexer.DEINDEX)
endmethod
else
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onIndexEvent),UnitIndexer.INDEX)
endmethod
endif
elseif thistype.deindex.exists then
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onDeindexEvent),UnitIndexer.DEINDEX)
endmethod
endif
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library WorldBounds
//struct WorldBounds extends array
//static readonly rect world
// same as GetWorldBounds()
//static readonly region worldRegion
// contains world for triggers
//static readonly real maxX
//static readonly real maxY
//static readonly real minX
//static readonly real minY
//static readonly real centerX
//static readonly real centerY
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=GetWorldBounds()
set maxX=GetRectMaxX(world)
set maxY=GetRectMaxY(world)
set minX=GetRectMinX(world)
set minY=GetRectMinY(world)
set centerX=(maxX+minX)/2
set centerY=(minY+maxY)/2
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endmethod
endmodule
struct WorldBounds extends array
readonly static real maxX
readonly static real maxY
readonly static real minX
readonly static real minY
readonly static real centerX
readonly static real centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
endlibrary