//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
TempPoint | location | No |
//TESH.scrollpos=7
//TESH.alwaysfold=0
//==============================================================================
// SHADOW STING SPELLPACK v1.3
// BY Ayanami
//==============================================================================
//==============================================================================
// REQUIREMENTS
//==============================================================================
// - Alloc
// - DamageEvent
// - SpellEffectEvent
// - T32
// - Table
// - Unit Indexer
//==============================================================================
//==============================================================================
// IMPLEMENTATION
//==============================================================================
// 1) Copy the whole "Required Systems" Trigger folder
// 2) Save the map, it will take a bit longer than usual
// 3) Close the map and re-open it, then disable or delete the trigger "Objects"
// 4) Go to the Import Manager and export all resources, then import into map
// 5) Copy all 3 abilities under "Night Elf - Heroes"
// 6) Copy the whole "Shadow Sting Spellpack" Trigger folder
//==============================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library EagleEye uses Alloc, DamageEvent, SpellEffectEvent, UnitIndexer
globals
private integer array ARMORID
endglobals
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABEE' // raw code of ability "Eagle Eye"
private constant integer DUMABILID = 'AEE0' // raw code of ability "Eagle Eye (Buff)"
private constant integer BUFFID = 'BEE0' // raw code of buff "Eagle Eye"
private constant integer PRELOADID = 'prel' // raw code of unit "Preloader"
private constant string FX = "Abilities\\Spells\\Items\\SpellShieldAmulet\\SpellShieldCaster.mdl" // effect on target when damaged
private constant string FX_AT = "chest" // attachment point of FX
private constant real PERIOD = 0.10 // timer update frequency for buff checking
endglobals
private function InitFunc takes nothing returns nothing
local unit u
local integer i = 0
set ARMORID[0] = 'dEE4' // raw code of ability "Eagle Eye (Armor - -10000's)"
set ARMORID[1] = 'dEE3' // raw code of ability "Eagle Eye (Armor - -1000's)"
set ARMORID[2] = 'dEE2' // raw code of ability "Eagle Eye (Armor - -100's)"
set ARMORID[3] = 'dEE1' // raw code of ability "Eagle Eye (Armor - -10's)"
set ARMORID[4] = 'dEE0' // raw code of ability "Eagle Eye (Armor - -1's)"
//preload resources
set u = CreateUnit(Player(13), PRELOADID, 0, 0, 0)
call UnitAddAbility(u, DUMABILID)
loop
exitwhen i > 4
call UnitAddAbility(u, ARMORID[i])
set i = i + 1
endloop
call RemoveUnit(u)
set u = null
endfunction
// duration of buff on caster
private constant function GetDuration takes integer level returns real
return 7. + level
endfunction
// duration of armor penalty
private constant function GetTargetDuration takes integer level returns real
return 5.
endfunction
// percentage of damage taken as armor penalty, where 1.00 = 100%
private constant function GetArmorPenalty takes integer level returns real
return 0.002 + (0.002 * level)
endfunction
// maximum armor penalty (supports up to 99999 armor reduction)
private constant function GetMaxPenalty takes integer level returns integer
return 15
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
private struct Main extends array
implement Alloc
thistype next
thistype prev
unit u
real dur
static timer linkTimer = CreateTimer()
static integer array store
private method destroy takes nothing returns nothing
set this.next.prev = this.prev
set this.prev.next = this.next
set store[GetUnitId(this.u)] = 0
if thistype(0).next == 0 then
call PauseTimer(linkTimer)
endif
call UnitRemoveAbility(this.u, DUMABILID)
call UnitRemoveAbility(this.u, BUFFID)
call this.deallocate()
endmethod
private static method iterate takes nothing returns nothing
local thistype this = thistype(0)
loop
set this = this.next
exitwhen this == 0
if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) or GetUnitTypeId(this.u) == 0 then
call this.destroy()
else
set this.dur = this.dur - PERIOD
endif
endloop
endmethod
private static method onCast takes nothing returns boolean
local thistype this
local integer id = GetUnitId(GetTriggerUnit())
if store[id] > 0 then
set this = store[id]
else
if thistype(0).next == 0 then
call TimerStart(linkTimer, PERIOD, true, function thistype.iterate)
endif
set this = thistype.allocate()
set thistype(0).next.prev = this
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = thistype(0)
set this.u = GetTriggerUnit()
call UnitAddAbility(this.u, DUMABILID)
endif
set this.dur = GetDuration(GetUnitAbilityLevel(this.u, ABILID))
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(ABILID, function thistype.onCast)
call InitFunc()
endmethod
endstruct
private struct Damage extends array
implement Alloc
thistype next
thistype prev
unit u
real amount
real dur
static timer linkTimer = CreateTimer()
static integer array store
private method destroy takes nothing returns nothing
local integer i
set this.next.prev = this.prev
set this.prev.next = this.next
set store[GetUnitId(this.u)] = 0
if thistype(0).next == 0 then
call PauseTimer(linkTimer)
endif
set i = 0
loop
exitwhen i > 4
call SetUnitAbilityLevel(this.u, ARMORID[i], 1)
set i = i + 1
endloop
call this.deallocate()
endmethod
private static method iterate takes nothing returns nothing
local thistype this = thistype(0)
local integer i
loop
set this = this.next
exitwhen this == 0
if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) or GetUnitTypeId(this.u) == 0 then
call this.destroy()
else
set this.dur = this.dur - PERIOD
endif
endloop
endmethod
private static method onDamage takes nothing returns boolean
local thistype this
local unit u = DamageEvent.source
local integer level
local integer id
local integer max
local integer value
local integer factor
local integer i
if GetUnitAbilityLevel(u, DUMABILID) == 1 then
set level = GetUnitAbilityLevel(u, ABILID)
set id = GetUnitId(DamageEvent.target)
set max = GetMaxPenalty(level)
if store[id] > 0 then
set this = store[id]
set this.amount = this.amount + (DamageEvent.amount * GetArmorPenalty(level))
else
if thistype(0).next == 0 then
call TimerStart(linkTimer, PERIOD, true, function thistype.iterate)
endif
set this = thistype.allocate()
set thistype(0).next.prev = this
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = thistype(0)
set this.u = DamageEvent.target
set this.amount = DamageEvent.amount * GetArmorPenalty(level)
set store[id] = this
endif
set this.dur = GetTargetDuration(level)
if this.amount > max then
set this.amount = max
endif
call DestroyEffect(AddSpecialEffectTarget(FX, this.u, FX_AT))
set value = R2I(this.amount)
set factor = 10000
set i = 0
loop
exitwhen i > 4
if GetUnitAbilityLevel(this.u, ARMORID[i]) == 0 then
call UnitAddAbility(this.u, ARMORID[i])
endif
set level = value / factor
call SetUnitAbilityLevel(this.u, ARMORID[i], level + 1)
set value = value - (level * factor)
set factor = factor / 10
set i = i + 1
endloop
endif
set u = null
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterEvent(Condition(function thistype.onDamage), DamageEvent.ANY)
endmethod
endstruct
endlibrary
//TESH.scrollpos=273
//TESH.alwaysfold=0
library Heartbreaker uses Alloc, SpellEffectEvent, T32, Table
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABHe' // raw code of ability "Heartbreaker"
private constant integer DUM_ABILID_1 = 'AHe0' // raw code of ability "Heartbreaker (Stun)"
private constant integer DUM_ABILID_2 = 'AHe1' // raw code of ability "Heartbreaker (Buff)"
private constant integer BUFFID_1 = 'BHe0' // raw code of buff "Heartbreaker (Stun)"
private constant integer BUFFID_2 = 'BHe1' // raw code of buff "Heartbreaker (Buff)"
private constant integer DUMMYID = 'dHEA' // raw code of unit "Heartbreaker Dummy"
private constant integer CASTERID = 'cAST' // raw code of unit "Caster Dummy"
private constant integer PRELOADID = 'prel' // raw code of unit "Preloader"
private constant string FX = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl" // effect used upon being stunned
private constant string FX_AT = "origin" // attachment point of FX
private constant string PROJ_FX = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl" // effect used upon projectile impact
private constant boolean SHOWTEXT = true // true if floating text (displaying stun duration) is displayed
private constant string COLOR = "|cffff0000" // color code for floating text
private constant real SPEED = 1000.0 // distance traveled by projectile per second
private constant real TRUESPEED = SPEED * T32_PERIOD // distance per interval
private constant real COL_SIZE = 50. // collision size of projectile
private constant real PERIOD = 0.1 // timer update frequency for stun
private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type of damage
private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type of damage
endglobals
// damage dealt
private constant function GetDamage takes integer level returns real
return 50. * level
endfunction
// damage limit for curse
private constant function GetDamageLimit takes integer level returns real
return 100. * level
endfunction
// stun limit for curse
private constant function GetStunLimit takes integer level returns real
return 1. * level
endfunction
// delay time before curse takes effect
private constant function GetDelayTime takes integer level returns real
return 3.
endfunction
// curse area of effect
private constant function GetArea takes integer level returns real
return 400.
endfunction
// target filter
private constant function GetFilter takes unit c, unit u returns boolean
return /*
*/ not IsUnitType(u, UNIT_TYPE_DEAD) /* // target is alive
*/ and IsUnitEnemy(u, GetOwningPlayer(c)) /* // target is an enemy
*/ and not IsUnitType(u, UNIT_TYPE_STRUCTURE) /* // target is not a structure
*/
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
globals
private constant real TRUE_COL_SIZE = COL_SIZE * COL_SIZE
private group G = bj_lastCreatedGroup
endglobals
private struct Curse extends array
implement Alloc
thistype next
thistype prev
unit u
unit tar
trigger trig
integer level
real damage
real damagelimit
real dur
static unit castDummy
static Table table
static timer linkTimer = CreateTimer()
private method destroy takes nothing returns nothing
set this.next.prev = this.prev
set this.prev.next = this.next
if thistype(0).next == 0 then
call PauseTimer(linkTimer)
endif
call UnitRemoveAbility(this.tar, BUFFID_1)
call this.deallocate()
endmethod
private static method iterate takes nothing returns nothing
local thistype this = thistype(0)
loop
set this = this.next
exitwhen this == 0
if this.dur <= 0 or IsUnitType(this.tar, UNIT_TYPE_DEAD) or GetUnitTypeId(this.tar) == 0 then
call this.destroy()
else
if GetUnitAbilityLevel(this.tar, BUFFID_1) == 0 then
call IssueTargetOrder(castDummy, "firebolt", this.tar)
endif
set this.dur = this.dur - PERIOD
endif
endloop
endmethod
private method periodic takes nothing returns nothing
local texttag t
local integer digitone
local integer digittwo
local integer id
if this.dur <= 0 or this.damage >= this.damagelimit or IsUnitType(this.tar, UNIT_TYPE_DEAD) then
if not IsUnitType(this.tar, UNIT_TYPE_DEAD) and this.damage > 0 then
if this.damage > this.damagelimit then
set this.damage = this.damagelimit
endif
set this.dur = (this.damage / this.damagelimit) * GetStunLimit(this.level)
static if SHOWTEXT then
set digitone = R2I(this.dur)
set digittwo = R2I((this.dur - digitone) * 10)
set t = CreateTextTag()
call SetTextTagText(t, COLOR + I2S(digitone) + "." + I2S(digittwo) + "!|r", 0.0253)
call SetTextTagPosUnit(t, this.tar, 0)
call SetTextTagColor(t, 255, 255, 255, 255)
call SetTextTagVelocity(t, 0.0355 * Cos(bj_PI / 2), 0.0355 * Sin(bj_PI / 2))
call SetTextTagPermanent(t, false)
call SetTextTagLifespan(t, 2.50)
endif
call IssueTargetOrder(castDummy, "firebolt", this.tar)
call DestroyEffect(AddSpecialEffectTarget(FX, this.tar, FX_AT))
if thistype(0).next == 0 then
call TimerStart(linkTimer, PERIOD, true, function thistype.iterate)
endif
set thistype(0).next.prev = this
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = thistype(0)
endif
call UnitRemoveAbility(this.tar, DUM_ABILID_2)
call UnitRemoveAbility(this.tar, BUFFID_2)
call table.remove(GetHandleId(this.trig))
call DestroyTrigger(this.trig)
call this.stopPeriodic()
if IsUnitType(this.tar, UNIT_TYPE_DEAD) then
call this.deallocate()
endif
else
set this.dur = this.dur - T32_PERIOD
endif
set t = null
endmethod
implement T32x
private static method onDamage takes nothing returns boolean
local thistype this = table[GetHandleId(GetTriggeringTrigger())]
if this.tar == GetTriggerUnit() then
set this.damage = this.damage + GetEventDamage()
endif
return false
endmethod
public static method create takes unit u, unit tar, integer level returns thistype
local thistype this = thistype.allocate()
set this.u = u
set this.tar = tar
set this.trig = CreateTrigger()
set this.level = level
set this.damage = 0
set this.damagelimit = GetDamageLimit(this.level)
set this.dur = GetDelayTime(this.level)
call UnitAddAbility(this.tar, DUM_ABILID_2)
call TriggerRegisterUnitEvent(this.trig, this.tar, EVENT_UNIT_DAMAGED)
call TriggerAddCondition(this.trig, Condition(function thistype.onDamage))
set table[GetHandleId(this.trig)] = this
call this.startPeriodic()
return this
endmethod
private static method onInit takes nothing returns nothing
set table = Table.create()
set castDummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CASTERID, 0, 0, 0)
call UnitAddAbility(castDummy, DUM_ABILID_1)
endmethod
endstruct
private struct Main extends array
implement Alloc
unit u
unit tar
unit dummy
integer level
private method destroy takes nothing returns nothing
call KillUnit(this.dummy)
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
local real x = GetUnitX(this.dummy)
local real y = GetUnitY(this.dummy)
local real dx = GetUnitX(this.tar) - x
local real dy = GetUnitY(this.tar) - y
local real a
local unit u
if dx * dx + dy * dy <= TRUE_COL_SIZE then
set dx = dx + x
set dy = dy + y
set a = GetArea(this.level)
call DestroyEffect(AddSpecialEffect(PROJ_FX, x, y))
call UnitDamageTarget(this.u, this.tar, GetDamage(this.level), true, false, ATK, DMG, null)
call GroupEnumUnitsInRange(G, dx, dy, a + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if IsUnitInRangeXY(u, dx, dy, a) and GetFilter(this.u, u) then
call Curse.create(this.u, u, this.level)
endif
endloop
call this.stopPeriodic()
call this.destroy()
else
set a = Atan2(dy, dx)
call SetUnitX(this.dummy, x + TRUESPEED * Cos(a))
call SetUnitY(this.dummy, y + TRUESPEED * Sin(a))
call SetUnitFacing(this.dummy, a * bj_RADTODEG)
endif
endmethod
implement T32x
private static method onCast takes nothing returns boolean
local thistype this
local real x
local real y
set this = thistype.allocate()
set this.u = GetTriggerUnit()
set this.tar = GetSpellTargetUnit()
set x = GetUnitX(this.u)
set y = GetUnitY(this.u)
set this.dummy = CreateUnit(GetOwningPlayer(this.u), DUMMYID, x, y, Atan2(GetUnitY(this.tar) - y, GetUnitX(this.tar) - x) * bj_RADTODEG)
set this.level = GetUnitAbilityLevel(this.u, ABILID)
call this.startPeriodic()
return false
endmethod
private static method onInit takes nothing returns nothing
local unit u
call RegisterSpellEffectEvent(ABILID, function thistype.onCast)
// preload
set u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CASTERID, 0, 0, 0)
call UnitAddAbility(u, DUM_ABILID_1)
call UnitAddAbility(u, DUM_ABILID_2)
call RemoveUnit(u)
call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYID, 0, 0, 0))
set u = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=122
//TESH.alwaysfold=0
library BoltSequence uses Alloc, SpellEffectEvent, T32
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABBS' // raw code of ability "Bolt Sequence"
private constant string ORDERID = "blight" // order ID of "Bolt Sequence"
private constant integer DUMMYID = 'dBOL' // raw code of unit "Bolt Sequence Dummy"
private constant real ANIMTIME = 1.334 // this value is the attack animation time of the model
private constant real COLLISION = 50.0 // collision check for arrow impact
private constant real TRUECOL = COLLISION * COLLISION // square of COLLISION
private constant real SPEED = 1000.0 // distance traveled by projectile per second
private constant real TRUESPEED = SPEED * T32_PERIOD // distance per interval
private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
private constant attacktype ATK = ATTACK_TYPE_CHAOS // attack type of damage
private constant damagetype DMG = DAMAGE_TYPE_NORMAL // damage type of damage
endglobals
// area of effect
private constant function GetArea takes integer level returns real
return 400.
endfunction
// damage per wave
private constant function GetDamage takes integer level returns real
return 15. * level + 20.
endfunction
// interval per wave
private constant function GetWaves takes integer level returns real
return 0.5
endfunction
// target filter
private constant function GetFilter takes unit c, unit u returns boolean
return /*
*/ not IsUnitType(u, UNIT_TYPE_DEAD) /* // target is alive
*/ and IsUnitEnemy(u, GetOwningPlayer(c)) /* // target is an enemy
*/ and not IsUnitType(u, UNIT_TYPE_STRUCTURE) /* // target is not a structure
*/
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
globals
private group G = bj_lastCreatedGroup
endglobals
private struct Projectile extends array
implement Alloc
unit u
unit tar
unit dummy
real damage
private method destroy takes nothing returns nothing
call KillUnit(this.dummy)
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
local real x = GetUnitX(this.dummy)
local real y = GetUnitY(this.dummy)
local real dx = GetUnitX(this.tar) - x
local real dy = GetUnitY(this.tar) - y
local real a
if dx * dx + dy * dy <= TRUECOL then
call UnitDamageTarget(this.u, this.tar, this.damage, true, false, ATK, DMG, null)
call this.destroy()
call this.stopPeriodic()
else
set a = Atan2(dy, dx)
call SetUnitX(this.dummy, x + TRUESPEED * Cos(a))
call SetUnitY(this.dummy, y + TRUESPEED * Sin(a))
call SetUnitFacing(this.dummy, a * bj_RADTODEG)
endif
endmethod
implement T32x
static method create takes unit u, unit tar, real damage returns thistype
local thistype this = thistype.allocate()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
set this.u = u
set this.tar = tar
set this.dummy = CreateUnit(GetOwningPlayer(this.u), DUMMYID, x, y, Atan2(GetUnitY(tar) - y, GetUnitX(tar) - x) * bj_RADTODEG)
set this.damage = damage
call this.startPeriodic()
return this
endmethod
endstruct
private struct Main extends array
implement Alloc
unit u
real area
real damage
real interval
real count
real x
real y
private method destroy takes nothing returns nothing
call SetUnitTimeScale(this.u, 1.)
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
local unit u
if this.count <= 0 then
call GroupEnumUnitsInRange(G, this.x, this.y, this.area + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if IsUnitInRangeXY(u, this.x, this.y, this.area) and GetFilter(this.u, u) then
call Projectile.create(this.u, u, this.damage)
endif
endloop
set this.count = this.interval - T32_PERIOD
else
set this.count = this.count - T32_PERIOD
endif
if (GetUnitCurrentOrder(this.u)) != OrderId(ORDERID) then
call this.stopPeriodic()
call this.destroy()
endif
endmethod
implement T32x
private static method onCast takes nothing returns boolean
local thistype this
local unit u
local integer level
set this = thistype.allocate()
set this.u = GetTriggerUnit()
set level = GetUnitAbilityLevel(this.u, ABILID)
set this.area = GetArea(level)
set this.damage = GetDamage(level)
set this.interval = GetWaves(level)
set this.count = this.interval
set this.x = GetSpellTargetX()
set this.y = GetSpellTargetY()
call GroupEnumUnitsInRange(G, this.x, this.y, this.area + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if IsUnitInRangeXY(u, this.x, this.y, this.area) and GetFilter(this.u, u) then
call Projectile.create(this.u, u, this.damage)
endif
endloop
call SetUnitTimeScale(this.u, ANIMTIME / this.interval)
call this.startPeriodic()
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(ABILID, function thistype.onCast)
//preload
call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYID, 0, 0, 0))
endmethod
endstruct
endlibrary
//TESH.scrollpos=31
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Alloc ~~ By Sevion ~~ Version 1.09 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Alloc?
// - Alloc implements an intuitive allocation method for array structs
//
// =Pros=
// - Efficient.
// - Simple.
// - Less overhead than regular structs.
//
// =Cons=
// - Must use array structs (hardly a con).
// - Must manually call OnDestroy.
// - Must use Delegates for inheritance.
// - No default values for variables (use onInit instead).
// - No array members (use another Alloc struct as a linked list or type declaration).
//
// Methods:
// - struct.allocate()
// - struct.deallocate()
//
// These methods are used just as they should be used in regular structs.
//
// Modules:
// - Alloc
// Implements the most basic form of Alloc. Includes only create and destroy
// methods.
//
// Details:
// - Less overhead than regular structs
//
// - Use array structs when using Alloc. Put the implement at the top of the struct.
//
// - Alloc operates almost exactly the same as default structs in debug mode with the exception of onDestroy.
//
// How to import:
// - Create a trigger named Alloc.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Nestharus for the method of allocation and suggestions on further merging.
// - Bribe for suggestions like the static if and method names.
// - PurgeandFire111 for some suggestions like the merging of Alloc and AllocX as well as OnDestroy stuff.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Alloc
module Alloc
private static integer instanceCount = 0
private thistype recycle
static method allocate takes nothing returns thistype
local thistype this
if (thistype(0).recycle == 0) then
debug if (instanceCount == 8190) then
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
debug return 0
debug endif
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = thistype(0).recycle
set thistype(0).recycle = thistype(0).recycle.recycle
endif
debug set this.recycle = -1
return this
endmethod
method deallocate takes nothing returns nothing
debug if (this.recycle != -1) then
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")
debug return
debug endif
set this.recycle = thistype(0).recycle
set thistype(0).recycle = this
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DamageEvent uses /*
*/UnitIndexer /*hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
*/Event //hiveworkshop.com/forums/submissions-414/snippet-event-186555/
//Version 2.1.0.7
//struct DamageEvent extends array
//static constant Event ANY
//readonly static integer targetId
//readonly static integer sourceId
//readonly static unit target
//readonly static unit source
//readonly static real amount
//static method disable takes nothing returns nothing
//static method enable takes nothing returns nothing
//static method operator enabled takes nothing returns boolean
globals
private constant integer MAX_WASTED = 15
endglobals
//! runtextmacro optional ADV_DAMAGE_EVENT_EXT_GLOB_1()
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_0()
private module DamageEventMod
readonly static Event ANY = 0
readonly static UnitIndex targetId = 0
readonly static UnitIndex sourceId = 0
readonly static real amount = 0
private thistype next
private thistype previous
private static trigger trig = CreateTrigger()
private static integer wasted = 0
private static integer count = 0
private static boolexpr dmg = null
static method operator target takes nothing returns unit
return GetUnitById(targetId)
endmethod
static method operator source takes nothing returns unit
return GetUnitById(sourceId)
endmethod
static method disable takes nothing returns nothing
call DisableTrigger(trig)
endmethod
static method enable takes nothing returns nothing
call EnableTrigger(trig)
endmethod
static method operator enabled takes nothing returns boolean
return IsTriggerEnabled(trig)
endmethod
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_2()
private static method damage takes nothing returns boolean
static if not LIBRARY_AdvDamageEvent then
local integer prev = targetId
local integer prev2 = sourceId
local real prev3 = amount
set targetId = GetUnitUserData(GetTriggerUnit())
set sourceId = GetUnitUserData(GetEventDamageSource())
set amount = GetEventDamage()
if (0 != targetId) then
call targetId.lock()
endif
if (0 != sourceId) then
call sourceId.lock()
endif
else
local UnitIndex targetId = GetUnitUserData(GetTriggerUnit())
local UnitIndex sourceId = GetUnitUserData(GetEventDamageSource())
local real amount = GetEventDamage()
local real life
local boolean update = false
local integer i = eventCount
endif
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_4()
static if not LIBRARY_AdvDamageEvent then
call ANY.fire()
if (0 != targetId) then
call targetId.unlock()
endif
if (0 != sourceId) then
call sourceId.unlock()
endif
set targetId = prev
set sourceId = prev2
set amount = prev3
endif
return false
endmethod
private static method index takes nothing returns boolean
local thistype this = GetIndexedUnitId()
set previous = thistype(0).previous
set next = 0
set thistype(0).previous.next = this
set thistype(0).previous = this
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_6()
set count = count + 1
if (count > MAX_WASTED and wasted > count) then
set count = 0
set wasted = 0
call DestroyTrigger(trig)
set trig = CreateTrigger()
call TriggerAddCondition(trig, dmg)
set this = thistype(0).next
loop
call TriggerRegisterUnitEvent(trig, GetUnitById(this), EVENT_UNIT_DAMAGED)
set count = count + 1
set this = next
exitwhen this == 0
endloop
else
call TriggerRegisterUnitEvent(trig, GetUnitById(this), EVENT_UNIT_DAMAGED)
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local thistype this = GetIndexedUnitId()
set wasted = wasted + 1
set count = count - 1
set previous.next = next
set next.previous = previous
return false
endmethod
private static method onInit takes nothing returns nothing
set dmg = Condition(function thistype.damage)
call TriggerAddCondition(trig, dmg)
set ANY = CreateEvent()
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_7()
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
endmethod
endmodule
struct DamageEvent extends array
implement DamageEventMod
endstruct
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_1()
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=0
//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=0
//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=1
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Timer32 ~~ By Jesus4Lyf ~~ Version 1.06 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Timer32?
// - Timer32 implements a fully optimised timer loop for a struct.
// - Instances can be added to the loop, which will call .periodic every
// PERIOD until .stopPeriodic() is called.
//
// =Pros=
// - Efficient.
// - Simple.
//
// =Cons=
// - Only allows one period.
// - The called method must be named ".periodic".
//
// Methods:
// - struct.startPeriodic()
// - struct.stopPeriodic()
//
// - private method periodic takes nothing returns nothing
//
// This must be defined in structs that implement Periodic Module.
// It will be executed by the module every PERIOD until .stopPeriodic() is called.
// Put "implement T32x" BELOW this method.
//
// Modules:
// - T32x
// Has no safety on .stopPeriodic or .startPeriodic (except debug messages
// to warn).
//
// - T32xs
// Has safety on .stopPeriodic and .startPeriodic so if they are called
// multiple times, or while otherwise are already stopped/started respectively,
// no error will occur, the call will be ignored.
//
// - T32
// The original, old version of the T32 module. This remains for backwards
// compatability, and is deprecated. The periodic method must return a boolean,
// false to continue running or true to stop.
//
// Details:
// - Uses one timer.
//
// - Do not, within a .periodic method, follow a .stopPeriodic call with a
// .startPeriodic call.
//
// How to import:
// - Create a trigger named T32.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Infinitegde for finding a bug in the debug message that actually altered
// system operation (when in debug mode).
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library T32 initializer OnInit
globals
public constant real PERIOD=0.03125
public constant integer FPS=R2I(1/PERIOD)
public integer Tick=0 // very useful.
//==============================================================================
private trigger Trig=CreateTrigger()
endglobals
//==============================================================================
// The standard T32 module, T32x.
//
module T32x
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
method stopPeriodic takes nothing returns nothing
debug if this.prev==0 and thistype(0).next!=this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had stopPeriodic called while not running!")
debug endif
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The standard T32 module with added safety checks on .startPeriodic() and
// .stopPeriodic(), T32xs.
//
module T32xs
private thistype next
private thistype prev
private boolean runningPeriodic
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
if not this.runningPeriodic then
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
set this.runningPeriodic=true
endif
endmethod
method stopPeriodic takes nothing returns nothing
if this.runningPeriodic then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
set this.runningPeriodic=false
endif
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The original T32 module, for backwards compatability only.
//
module T32 // deprecated.
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
if this.periodic() then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endif
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// System Core.
//
private function OnExpire takes nothing returns nothing
set Tick=Tick+1
call TriggerEvaluate(Trig)
endfunction
private function OnInit takes nothing returns nothing
call TimerStart(CreateTimer(),PERIOD,true,function OnExpire)
endfunction
endlibrary
//TESH.scrollpos=213
//TESH.alwaysfold=0
library Table // made by Bribe, special thanks to Nestharus, version 3.0.0.0
/*
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 hashtable ht = InitHashtable() //The last hashtable you need
private integer more = 2 //Index generation for Tables (above 2)
private integer less = 0 //Index generation for TableArrays (below 0)
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return 1
endmethod
static method operator list takes nothing returns Table
return 2
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
//! 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 type-syntax
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 = a[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key)
endmethod
// set a[389034] = 8192
method operator []= takes integer key, Table a returns nothing
call SaveInteger(ht, this, key, a)
endmethod
// set b = a.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key)
endmethod
// call a.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 a = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set more = more + 1
set this = more
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this)
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call a.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
endstruct
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 a = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = a[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 less = less - array_size
set this = less
else
set a[0] = a[this] //Set the last destroyed to the last-last destroyed
call a.remove(this) //Clear hash 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
//da[integer a].unit[integer b] = unit u
//da[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; assumed you'd call .flush()
//if you want it flushed too. This is public so that if you are flushing
//instances the whole time you don't waste efficiency when disposing the
//TableArray.
//
method destroy takes nothing returns nothing
local Table a = 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 a == 0 then
//Create an array to index recycled instances with their array size
set a = Table.create()
set dex.size[this.size] = a
endif
call dex.size.remove(this) //Clear the array size from hash memory
set a[this] = a[0]
set a[0] = this
endmethod
//All you need to know about this one is that it won't hit the op limit.
private static method clean takes Table a, integer end returns nothing
local integer i = a + 5000
if i < end then
call clean.evaluate(i, end)
set end = i
endif
loop
call a.flush()
set a = a + 1
exitwhen a == 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
local integer end = this.size + this
debug if this == end then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
call clean.evaluate(this, end)
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 = 'A000'
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
//TESH.scrollpos=4
//TESH.alwaysfold=0
//! external ObjectMerger w3a Adef AIDS anam "State Detection" ansf "(AIDS)" aart "" arac 0
//! external ObjectMerger w3a AIlz dprv anam "Life Bonus" ansf "(Damage System)" Ilif 1 500000 aite 0
//! textmacro CreateObj takes CODE, NAME, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN
//! external ObjectMerger w3a AId1 dEE$CODE$ aart "" anam "Eagle Eye" ansf "$NAME$" aite 0 alev 10 Idef 1 $ONE$ Idef 2 $TWO$ Idef 3 $THREE$ Idef 4 $FOUR$ Idef 5 $FIVE$ Idef 6 $SIX$ Idef 7 $SEVEN$ Idef 8 $EIGHT$ Idef 9 $NINE$ Idef 10 $TEN$
//! endtextmacro
//! runtextmacro CreateObj("0", "(Armor - -1's)", "0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9")
//! runtextmacro CreateObj("1", "(Armor - -10's)", "0", "-10", "-20", "-30", "-40", "-50", "-60", "-70", "-80", "-90")
//! runtextmacro CreateObj("2", "(Armor - -100's)", "0", "-100", "-200", "-300", "-400", "-500", "-600", "-700", "-800", "-900")
//! runtextmacro CreateObj("3", "(Armor - -1000's)", "0", "-1000", "-2000", "-3000", "-4000", "-5000", "-6000", "-7000", "-8000", "-9000")
//! runtextmacro CreateObj("4", "(Armor - -10000's)", "0", "-10000", "-20000", "-30000", "-40000", "-50000", "-60000", "-70000", "-80000", "-90000")
//! external ObjectMerger w3a Aasl AEE0 atat "war3mapImported\GrudgeAura.mdx" ata0 "origin" atac "1" Slo1 1 "0" aare 1 "0" abuf 1 "BEE0" arac "other" atar 1 "self" ansf "(Buff)" anam "Eagle Eye"
//! external ObjectMerger w3h Basl BEE0 fart "ReplaceableTextures\CommandButtons\BTNEagleEye.blp" ftat "" fnsf "" fnam "Eagle Eye" ftip "|cff00ff00Eagle Eye" fube "This unit is under the effects of Eagle Eye, it deals armor shattering damage."
//! external ObjectMerger w3a ACfb AHe0 aani "" aart "" amat "" amsp "0" anam "Heartbreaker (Stun)" ansf "" Htb1 1 "0" aran 1 "99999" acdn 1 "0" ahdu 1 "99999" adur 1 "99999" abuf 1 "BHe0" amcs 1 "0" arac "other" atar 1 "air,ground" atp1 1 " " aub1 1 " "
//! external ObjectMerger w3a Aasl AHe1 atat "Abilities\Spells\Human\Banish\BanishTarget.mdl" ata0 "origin" atac "1" Slo1 1 "0" aare 1 "0" abuf 1 "BHe1" arac "other" atar 1 "self" ansf "(Buff)" anam "Heartbreaker"
//! external ObjectMerger w3h BPSE BHe0 fart "ReplaceableTextures\CommandButtons\BTNHeartbreaker.blp" fnsf "" fnam "Heartbreaker (Stun)" ftip "Stunned" fube "This unit is stunned; it cannot move nor attack temporarily."
//! external ObjectMerger w3h Basl BHe1 fart "ReplaceableTextures\CommandButtons\BTNHeartbreaker.blp" ftat "" fnsf "" fnam "Heartbreaker (Buff)" ftip "Heartbreaker" fube "This unit has been cursed; it will be stunned after it fades."
//! external ObjectMerger w3u nalb dHEA uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Abilities\Spells\Other\BlackArrow\BlackArrowMissile.mdl" usca 1 ushu "None" util " " umvh 100 umvf 100 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Heartbreaker Dummy" utip " " utub " " usid 0 usin 0
//! external ObjectMerger w3u nalb dBOL uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Abilities\Weapons\MoonPriestessMissile\MoonPriestessMissile.mdl" usca 1 ushu "None" util " " umvh 100 umvf 100 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Bolt Sequence Dummy" utip " " utub " " usid 0 usin 0
//! external ObjectMerger w3u nalb prel uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "none.mdl" usca 0.1 ushu "None" util " " umvh 0 umvf 0 umvs 0 umas 0 umis 0 ucol 0 urac "human" unam "Preloader" utip " " utub " " usid 0 usin 0
//! external ObjectMerger w3u nalb cAST uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "none.mdl" usca 0.1 ushu "None" util " " umvh 0 umvf 0 umvs 0 umas 0 umis 0 ucol 0 urac "human" unam "Caster Dummy" utip " " utub " " usid 0 usin 0