//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
TempPoint | location | No |
//TESH.scrollpos=13
//TESH.alwaysfold=0
//==============================================================================
// SHADOW FIELD SPELLPACK v1.4
// BY Ayanami
//==============================================================================
//==============================================================================
// REQUIREMENTS
//==============================================================================
//
// - JNGP
// - Alloc
// - RegisterPlayerUnitEvent
// - SpellEffectEvent
// - Timer32
// - WorldBounds
//
//==============================================================================
//==============================================================================
// IMPLEMENTATION
//==============================================================================
//
// 1) Copy the whole "Required Systems" Trigger folder & paste in map
// 2) Save the map, it will take a bit longer than usual
// 3) After saving, close the map and re-open it
// 4) Delete or disable the trigger "Objects"
// 5) Copy all 8 abilities under "Undead" & paste in map
// 6) Copy the single buff under "Undead" & paste in map
// 7) Ensure that the following abilities have their buff set properly:
// Presence of the Dark Lord - Presence of the Dark Lord
// 8) Copy the whole "Shadowfiend" Trigger folder
// 9) Go through all the spell Configurations
//
//==============================================================================
//TESH.scrollpos=187
//TESH.alwaysfold=0
library Shadowraze uses Alloc, RegisterPlayerUnitEvent, SpellEffectEvent, WorldBounds
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABSR' // raw code of ability "Shadowraze"
private constant integer ABILIDZ = 'ASR0' // raw code of ability "Shadowraze (Z)"
private constant integer ABILIDX = 'ASR1' // raw code of ability "Shadowraze (X)"
private constant integer ABILIDC = 'ASR2' // raw code of ability "Shadowraze (C)"
private constant integer DUMMYID = 'sHAD' // raw code of unit "Shadowraze Dummy", acts as the visual effect itself
private constant real ANIMDUR = 2.0 // duration of DUMMYID
private constant integer RED = 0 // red vertex color of DUMMYID
private constant integer GREEN = 0 // green vertex color of DUMMYID
private constant integer BLUE = 0 // blue vertex color of DUMMYID
private constant integer TRANS = 255 // transparency of DUMMYID, where 0 is fully transparent
private constant real SCALE = 1.2 // scale size of DUMMYID
private constant real PERIOD = 0.1 // checking period for dummy expiration
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 function GetDamage takes integer level returns real
return 75.0 * level
endfunction
// area of effect
private function GetArea takes integer level returns real
return 250.0
endfunction
// range of "Shadowraze (Z)"
private function GetRangeZ takes integer level returns real
return 200.0
endfunction
// range of "Shadowraze (X)"
private function GetRangeX takes integer level returns real
return 450.0
endfunction
// range of "Shadowraze (C)"
private function GetRangeC takes integer level returns real
return 700.0
endfunction
// target types allowed for dealing damage
private 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) // target is not a structure
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
globals
private constant player NEUTRAL_PASSIVE = Player(PLAYER_NEUTRAL_PASSIVE)
private group G = bj_lastCreatedGroup
endglobals
private struct Main extends array
implement Alloc
private thistype next
private thistype prev
private unit u
private real dur
private 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(thistype.linkTimer)
endif
call RemoveUnit(this.u)
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 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 unit caster = GetTriggerUnit()
local unit u
local integer spellid = GetSpellAbilityId()
local integer level
local real r
local real a
local real x
local real y
set level = GetUnitAbilityLevel(caster, ABILID)
if spellid == ABILIDZ then
set r = GetRangeZ(level)
elseif spellid == ABILIDX then
set r = GetRangeX(level)
else
set r = GetRangeC(level)
endif
set a = GetUnitFacing(caster) * bj_DEGTORAD
set x = GetUnitX(caster) + r * Cos(a)
set y = GetUnitY(caster) + r * Sin(a)
if x >= WorldBounds.minX and x <= WorldBounds.maxX and y >= WorldBounds.minY and y <= WorldBounds.maxY then
set this = thistype.allocate()
set this.u = CreateUnit(NEUTRAL_PASSIVE, DUMMYID, x, y, a * bj_RADTODEG)
set this.dur = ANIMDUR
set a = GetArea(level)
set r = GetDamage(level)
call SetUnitVertexColor(this.u, RED, GREEN, BLUE, TRANS)
call SetUnitScale(this.u, SCALE, SCALE, SCALE)
call GroupEnumUnitsInRange(G, x, y, a + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if GetFilter(caster, u) and IsUnitInRangeXY(u, x, y, a) then
call UnitDamageTarget(caster, u, r, true, false, ATK, DMG, null)
endif
endloop
if thistype(0).next == 0 then
call TimerStart(thistype.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
set caster = null
return false
endmethod
private static method onLearn takes nothing returns boolean
local unit u
local integer level
if ABILID == GetLearnedSkill() then
set u = GetTriggerUnit()
set level = GetUnitAbilityLevel(u, ABILID)
if level == 1 then
call UnitAddAbility(u, ABILIDZ)
call UnitAddAbility(u, ABILIDX)
call UnitAddAbility(u, ABILIDC)
else
call SetUnitAbilityLevel(u, ABILIDZ, level)
call SetUnitAbilityLevel(u, ABILIDX, level)
call SetUnitAbilityLevel(u, ABILIDC, level)
endif
endif
set u = null
return false
endmethod
private static method onInit takes nothing returns nothing
local unit u
call RegisterSpellEffectEvent(ABILIDZ, function thistype.onCast)
call RegisterSpellEffectEvent(ABILIDX, function thistype.onCast)
call RegisterSpellEffectEvent(ABILIDC, function thistype.onCast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_SKILL, function thistype.onLearn)
//preload
set u = CreateUnit(NEUTRAL_PASSIVE, DUMMYID, 0, 0, 0)
call UnitAddAbility(u, ABILIDZ)
call UnitAddAbility(u, ABILIDX)
call UnitAddAbility(u, ABILIDC)
call RemoveUnit(u)
set u = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=10
//TESH.alwaysfold=0
library Necromastery uses Alloc, RegisterPlayerUnitEvent, T32
globals
private integer array DAMAGEID[4]
endglobals
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABNe' // raw code of ability "Necromastery"
public constant integer DUMABILID = 'ANe0' // raw code of ability "Necromastery (Display)"
private constant integer DUMMYID = 'nECD' // raw code of unit "Necromastery Dummy"
private constant integer DAMAGE = 2 // damage bonus per soul
private constant real COL = 50.0 // collision size of the soul
private constant real SPEED = 500.0 // distance traveled by the soul per second
private constant real TRUESPEED = SPEED * T32_PERIOD // distance traveled by the soul per period
private constant string DEATHART = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl" // death art used upon soul expiration
private constant string DEATHARTPOINT = "chest" // attachment point of DEATHART
endglobals
private function InitFunc takes nothing returns nothing
local integer i = 0
local unit u = CreateUnit(Player(13), DUMMYID, 0, 0, 0)
set DAMAGEID[0] = 'dmg0' // raw code of ability "Damage (10000's) (Necromastery)"
set DAMAGEID[1] = 'dmg1' // raw code of ability "Damage (1000's) (Necromastery)"
set DAMAGEID[2] = 'dmg2' // raw code of ability "Damage (100's) (Necromastery)"
set DAMAGEID[3] = 'dmg3' // raw code of ability "Damage (10's) (Necromastery)"
set DAMAGEID[4] = 'dmg4' // raw code of ability "Damage (1's) (Necromastery)"
//preload
loop
exitwhen i > 4
call UnitAddAbility(u, DAMAGEID[i])
set i = i + 1
endloop
call UnitAddAbility(u, DUMABILID)
call RemoveUnit(u)
set u = null
endfunction
// maximum number of souls
private function GetMaxSoul takes integer level returns integer
if level == 1 then
return 8
elseif level == 2 then
return 15
elseif level == 3 then
return 23
elseif level == 4 then
return 30
endif
return 0
endfunction
// amount of souls lost on death, where 1.0 = 100%
private function GetSoulLost takes integer level returns real
return 0.50
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
globals
private constant real TRUE_COLLISION = COL * COL
endglobals
private struct Main extends array
implement Alloc
private unit killer
private unit dummy
private method destroy takes nothing returns nothing
call RemoveUnit(this.dummy)
call this.stopPeriodic()
call this.deallocate()
endmethod
private static method setDamage takes unit u returns nothing
local integer damage = DAMAGE * (GetUnitAbilityLevel(u, DUMABILID) - 1)
local integer factor = 10000
local integer level
local integer i = 0
loop
exitwhen i > 4
set level = damage / factor
call SetUnitAbilityLevel(u, DAMAGEID[i], level + 1)
set damage = damage - (level * factor)
set factor = factor / 10
set i = i + 1
endloop
endmethod
private method periodic takes nothing returns nothing
local integer level
local real x = GetUnitX(this.dummy)
local real y = GetUnitY(this.dummy)
local real dx = GetUnitX(this.killer) - x
local real dy = GetUnitY(this.killer) - y
local real a
local real height
local real dist = dx * dx + dy * dy
if dist <= TRUE_COLLISION then
set level = GetUnitAbilityLevel(this.killer, DUMABILID)
if level < GetMaxSoul(GetUnitAbilityLevel(this.killer, ABILID)) + 1 then
call UnitRemoveAbility(this.killer, DUMABILID)
call UnitAddAbility(this.killer, DUMABILID)
call SetUnitAbilityLevel(this.killer, DUMABILID, level + 1)
call setDamage(this.killer)
endif
call DestroyEffect(AddSpecialEffectTarget(DEATHART, this.killer, DEATHARTPOINT))
call this.destroy()
elseif IsUnitType(this.killer, UNIT_TYPE_DEAD) or GetUnitTypeId(this.killer) == 0 then
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))
set height = GetUnitFlyHeight(this.dummy)
call SetUnitFlyHeight(this.dummy, height + ((GetUnitFlyHeight(this.killer) + 100) - height) / (dist / TRUESPEED), 0)
endif
endmethod
implement T32x
private static method onDeath takes nothing returns boolean
local thistype this
local unit u = GetTriggerUnit()
local unit killer = GetKillingUnit()
local integer ulevel = GetUnitAbilityLevel(u, ABILID)
local integer klevel = GetUnitAbilityLevel(killer, ABILID)
local integer i
local real x
local real y
if ulevel > 0 then
set i = R2I((GetUnitAbilityLevel(u, DUMABILID) - 1) * GetSoulLost(ulevel))
call UnitRemoveAbility(u, DUMABILID)
call UnitAddAbility(u, DUMABILID)
call SetUnitAbilityLevel(u, DUMABILID, i + 1)
call setDamage(u)
elseif klevel > 0 then
set this = this.allocate()
set x = GetUnitX(u)
set y = GetUnitY(u)
set this.killer = killer
set this.dummy = CreateUnit(Player(13), DUMMYID, x, y, Atan2(GetUnitY(this.killer) - y, GetUnitX(this.killer) - x) * bj_RADTODEG)
call this.startPeriodic()
endif
set u = null
set killer = null
return false
endmethod
private static method onLearn takes nothing returns boolean
local unit u = GetTriggerUnit()
local integer i
if GetLearnedSkill() == ABILID then
if GetUnitAbilityLevel(u, DUMABILID) == 0 then
call UnitAddAbility(u, DUMABILID)
set i = 0
loop
exitwhen i > 4
call UnitAddAbility(u, DAMAGEID[i])
set i = i + 1
endloop
endif
endif
set u = null
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.onDeath)
call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_SKILL, function thistype.onLearn)
call InitFunc()
endmethod
endstruct
endlibrary
//TESH.scrollpos=65
//TESH.alwaysfold=0
library RequiemOfSouls uses Alloc, SpellEffectEvent, T32, WorldBounds, Necromastery
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABRS' // raw code of ability "Requiem of Souls"
private constant integer DUMABILID = 'ARS0' // raw code of ability "Requiem of Souls (Reduction)"
private constant integer DUMMYID = 'rOSD' // raw code of unit "Requiem of Souls Dummy"
private constant integer CASTERID = 'cAST' // raw code of unit "Caster Dummy"
private constant integer SOULCOUNT = 2 // number of souls required to create a "line"
private constant real SOULAOE = 150.0 // area of effect of each "line"
private constant real SPEED = 1000.0 // distance travelled by "line" per second
private constant real TRUESPEED = SPEED * T32_PERIOD // distance travelled by "line" per period
private constant real REDUCTIONAOE = 675.0 // area of effect where units will be affected by damage and move speed reduction
private constant real INTERVAL = 200.0 // distance interval where effect is spawned
private constant string EFFECT = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl" // effect spawned every interval
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
private function GetDamage takes integer level returns real
return 40.0 + (40.0 * level) // damage dealt per line of soul
endfunction
private function GetArea takes integer level returns real
return 1350.0 + (25.0 * level) // area of effect
endfunction
// target types allowed for dealing damage
private 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) // target is not a structure
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
globals
private constant player NEUTRAL_PASSIVE = Player(PLAYER_NEUTRAL_PASSIVE)
private group G = bj_lastCreatedGroup
endglobals
private struct Main extends array
implement Alloc
private unit u
private unit dummy
private group g
private real dmg
private real dist
private real a
private real interval
private static unit castDummy
private method destroy takes nothing returns nothing
call RemoveUnit(this.dummy)
call DestroyGroup(this.g)
call this.stopPeriodic()
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
local unit u
local real x = GetUnitX(this.dummy)
local real y = GetUnitY(this.dummy)
if this.dist <= 0 then
call DestroyEffect(AddSpecialEffect(EFFECT, x, y))
call this.destroy()
else
if this.interval <= 0 then
call DestroyEffect(AddSpecialEffect(EFFECT, x, y))
set this.interval = INTERVAL
else
set this.interval = this.interval - TRUESPEED
endif
set this.dist = this.dist - TRUESPEED
set x = x + TRUESPEED * Cos(this.a)
set y = y + TRUESPEED * Sin(this.a)
if x >= WorldBounds.minX and x <= WorldBounds.maxX and y >= WorldBounds.minY and y <= WorldBounds.maxY then
call SetUnitX(this.dummy, x)
call SetUnitY(this.dummy, y)
call GroupEnumUnitsInRange(G, x, y, SOULAOE + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if GetFilter(this.u, u) and not IsUnitInGroup(u, this.g) then
call UnitDamageTarget(this.u, u, this.dmg, true, false, ATK, DMG, null)
call GroupAddUnit(this.g, u)
endif
endloop
endif
endif
endmethod
implement T32x
private static method onCast takes nothing returns boolean
local thistype this
local unit caster = GetTriggerUnit()
local unit u
local integer level = GetUnitAbilityLevel(caster, ABILID)
local integer i = (GetUnitAbilityLevel(caster, Necromastery_DUMABILID) - 1) / SOULCOUNT
local real a = 0
local real aRate
local real x
local real y
if i > 0 then
set aRate = (2 * bj_PI) / i
endif
set x = GetUnitX(caster)
set y = GetUnitY(caster)
loop
exitwhen i == 0
set this = thistype.allocate()
set this.u = caster
set this.dummy = CreateUnit(GetTriggerPlayer(), DUMMYID, x, y, a)
set this.g = CreateGroup()
set this.dmg = GetDamage(level)
set this.dist = GetArea(level)
set this.a = a
set this.interval = INTERVAL
call this.startPeriodic()
set a = a + aRate
set i = i - 1
endloop
call SetUnitAbilityLevel(castDummy, DUMABILID, level)
call GroupEnumUnitsInRange(G, x, y, REDUCTIONAOE + ENUM_RADIUS, null)
loop
set u = FirstOfGroup(G)
exitwhen u == null
call GroupRemoveUnit(G, u)
if GetFilter(caster, u) and IsUnitInRangeXY(u, x, y, REDUCTIONAOE) then
call IssueTargetOrder(castDummy, "cripple", u)
endif
endloop
set caster = null
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(ABILID, function thistype.onCast)
set castDummy = CreateUnit(NEUTRAL_PASSIVE, CASTERID, 0, 0, 0)
call UnitAddAbility(castDummy, DUMABILID)
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
/**************************************************************
*
* 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=3
//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=73
//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=42
//TESH.alwaysfold=0
library WorldBounds
/*
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
*/
globals
private constant boolean USE_REGION = true
private constant boolean USE_RECT = true
private constant boolean USE_EXTREMA_COORDS = true
private constant boolean USE_CENTER_COORDS = true
endglobals
private module WorldBoundInit
private static method onInit takes nothing returns nothing
static if not USE_RECT then
local rect world=GetWorldBounds()
else
set world=GetWorldBounds()
endif
static if USE_EXTREMA_COORDS then
set maxX=GetRectMaxX(world)
set maxY=GetRectMaxY(world)
set minX=GetRectMinX(world)
set minY=GetRectMinY(world)
endif
static if USE_CENTER_COORDS then
set centerX=(maxX+minX)/2
set centerY=(minY+maxY)/2
endif
static if USE_REGION then
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endif
static if not USE_RECT then
call RemoveRect(world)
set world=null
endif
endmethod
endmodule
struct WorldBounds extends array
static if USE_EXTREMA_COORDS then
readonly static real maxX
readonly static real maxY
readonly static real minX
readonly static real minY
endif
static if USE_CENTER_COORDS then
readonly static real centerX
readonly static real centerY
endif
static if USE_RECT then
readonly static rect world
endif
static if USE_REGION then
readonly static region worldRegion
endif
implement WorldBoundInit
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//! textmacro CreateNec takes CODE, NAME, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN
//! external ObjectMerger w3a AItg dmg$CODE$ aart "" anam "Damage ($NAME$)" ansf "(Necromastery)" alev 10 Iatt 1 $ONE$ Iatt 2 $TWO$ Iatt 3 $THREE$ Iatt 4 $FOUR$ Iatt 5 $FIVE$ Iatt 6 $SIX$ Iatt 7 $SEVEN$ Iatt 8 $EIGHT$ Iatt 9 $NINE$ Iatt 10 $TEN$ aite 0
//! endtextmacro
//! runtextmacro CreateNec("0", "10000's", "0", "10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000")
//! runtextmacro CreateNec("1", "1000's", "0", "1000", "2000", "3000", "4000", "5000", "6000", "7000", "8000", "9000")
//! runtextmacro CreateNec("2", "100's", "0", "100", "200", "300", "400", "500", "600", "700", "800", "900")
//! runtextmacro CreateNec("3", "10's", "0", "10", "20", "30", "40", "50", "60", "70", "80", "90")
//! runtextmacro CreateNec("4", "1's", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9")
//! external ObjectMerger w3a Acri ARS0 aart "" alev 3 arac "other" areq "" arqa "" ansf "(Reduction)" anam "Requiem of Souls" Cri2 1 0 Cri3 1 0.15 Cri3 2 0.20 Cri3 3 0.25 Cri1 1 0.15 Cri1 2 0.20 Cri1 3 0.25 abuf 1 BRS0 abuf 2 BRS0 abuf 3 BRS0 aran 1 99999 aran 2 99999 aran 3 99999 acdn 1 0 ahdu 1 5 ahdu 2 5 ahdu 3 5 adur 1 5 adur 2 5 adur 3 5 amcs 1 0 atar 1 "" atp1 1 "" aub1 1 ""
//! external ObjectMerger w3h Bcri BRS0 fart "ReplaceableTextures\CommandButtons\BTNDizzy.blp" ftat "Abilities\Spells\Undead\Possession\PossessionTarget.mdl" fta0 "overhead" ftac 1 frac "other" fnam "Requiem of Souls" ftip "Requiem of Souls" fube "This unit has been hit by evil spirits; its movement speed and damage have been reduced."
//! external ObjectMerger w3u nalb nECD uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Abilities\Weapons\AvengerMissile\AvengerMissile.mdl" usca 1 ushu "None" util " " umvh 0 umvf 0 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Necromastery Dummy" utip " " utub " " usid 0 usin 0
//! external ObjectMerger w3u nalb sHAD uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Abilities\Spells\Undead\AnimateDead\AnimateDeadTarget.mdl" usca 1 ushu "None" util " " umvh 0 umvf 0 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Shadowraze Dummy" utip " " utub " " usid 0 usin 0
//! external ObjectMerger w3u nalb rOSD uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Objects\Spawnmodels\Undead\UndeadDissipate\UndeadDissipate.mdl" usca 1 ushu "None" util " " umvh 0 umvf 0 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Requiem of Souls Dummy" 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
//! 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