Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//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=8
//TESH.alwaysfold=0
library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 3.1.0.1
One map, one hashtable. Welcome to NewTable 3.1
This library was originally called NewTable so it didn't conflict with
the API of Table by Vexorian. However, the damage is done and it's too
late to change the library name now. To help with damage control, I
have provided an extension library called TableBC, which bridges all
the functionality of Vexorian's Table except for 2-D string arrays &
the ".flush(integer)" method. I use ".flush()" to flush a child hash-
table, because I wanted the API in NewTable to reflect the API of real
hashtables (I thought this would be more intuitive).
API
------------
struct Table
| static method create takes nothing returns Table
| create a new Table
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush all stored values inside of it
|
| method remove takes integer key returns nothing
| remove the value at index "key"
|
| method operator []= takes integer key, $TYPE$ value returns nothing
| assign "value" to index "key"
|
| method operator [] takes integer key returns $TYPE$
| load the value at index "key"
|
| method has takes integer key returns boolean
| whether or not the key was assigned
|
----------------
struct TableArray
| static method operator [] takes integer array_size returns TableArray
| create a new array of Tables of size "array_size"
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush and destroy it
|
| method operator size takes nothing returns integer
| returns the size of the TableArray
|
| method operator [] takes integer key returns Table
| returns a Table accessible exclusively to index "key"
*/
globals
private integer less = 0 //Index generation for TableArrays (below 0).
private integer more = 8190 //Index generation for Tables.
//Configure it if you use more than 8190 "key" variables in your map (this will never happen though).
private hashtable ht = InitHashtable()
private key sizeK
private key listK
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return sizeK
endmethod
static method operator list takes nothing returns Table
return listK
endmethod
endstruct
private struct handles extends array
method has takes integer key returns boolean
return HaveSavedHandle(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedHandle(ht, this, key)
endmethod
endstruct
private struct agents extends array
method operator []= takes integer key, agent value returns nothing
call SaveAgentHandle(ht, this, key, value)
endmethod
endstruct
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$(ht, this, key, value)
endmethod
method has takes integer key returns boolean
return HaveSaved$SUPER$(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSaved$SUPER$(ht, this, key)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$Handle(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$Handle(ht, this, key, value)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//Run these textmacros to include the entire hashtable API as wrappers.
//Don't be intimidated by the number of macros - Vexorian's map optimizer is
//supposed to kill functions which inline (all of these functions inline).
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
struct Table extends array
// Implement modules for intuitive syntax (tb.handle; tb.unit; etc.)
implement realm
implement booleanm
implement stringm
implement playerm
implement widgetm
implement destructablem
implement itemm
implement unitm
implement abilitym
implement timerm
implement triggerm
implement triggerconditionm
implement triggeractionm
implement eventm
implement forcem
implement groupm
implement locationm
implement rectm
implement boolexprm
implement soundm
implement effectm
implement unitpoolm
implement itempoolm
implement questm
implement questitemm
implement defeatconditionm
implement timerdialogm
implement leaderboardm
implement multiboardm
implement multiboarditemm
implement trackablem
implement dialogm
implement buttonm
implement texttagm
implement lightningm
implement imagem
implement ubersplatm
implement regionm
implement fogstatem
implement fogmodifierm
implement hashtablem
method operator handle takes nothing returns handles
return this
endmethod
method operator agent takes nothing returns agents
return this
endmethod
//set this = tb[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key)
endmethod
//set tb[389034] = 8192
method operator []= takes integer key, Table tb returns nothing
call SaveInteger(ht, this, key, tb)
endmethod
//set b = tb.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key)
endmethod
//call tb.remove(294080)
method remove takes integer key returns nothing
call RemoveSavedInteger(ht, this, key)
endmethod
//Remove all data from a Table instance
method flush takes nothing returns nothing
call FlushChildHashtable(ht, this)
endmethod
//local Table tb = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set this = more + 1
set more = this
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this) //Clear hashed memory
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call tb.destroy()
//
method destroy takes nothing returns nothing
debug if dex.list[this] != -1 then
debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
debug return
debug endif
call this.flush()
set dex.list[this] = dex.list[0]
set dex.list[0] = this
endmethod
//! runtextmacro optional TABLE_BC_METHODS()
endstruct
//! runtextmacro optional TABLE_BC_STRUCTS()
struct TableArray extends array
//Returns a new TableArray to do your bidding. Simply use:
//
// local TableArray ta = TableArray[array_size]
//
static method operator [] takes integer array_size returns TableArray
local Table tb = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = tb[0] //The last-destroyed TableArray that had this array size
debug if array_size <= 0 then
debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
debug return 0
debug endif
if this == 0 then
set this = less - array_size
set less = this
else
set tb[0] = tb[this] //Set the last destroyed to the last-last destroyed
call tb.remove(this) //Clear hashed memory
endif
set dex.size[this] = array_size //This remembers the array size
return this
endmethod
//Returns the size of the TableArray
method operator size takes nothing returns integer
return dex.size[this]
endmethod
//This magic method enables two-dimensional[array][syntax] for Tables,
//similar to the two-dimensional utility provided by hashtables them-
//selves.
//
//ta[integer a].unit[integer b] = unit u
//ta[integer a][integer c] = integer d
//
//Inline-friendly when not running in debug mode
//
method operator [] takes integer key returns Table
static if DEBUG_MODE then
local integer i = this.size
if i == 0 then
call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
return 0
elseif key < 0 or key >= i then
call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
return 0
endif
endif
return this + key
endmethod
//Destroys a TableArray without flushing it; I assume you call .flush()
//if you want it flushed too. This is a public method so that you don't
//have to loop through all TableArray indices to flush them if you don't
//need to (ie. if you were flushing all child-keys as you used them).
//
method destroy takes nothing returns nothing
local Table tb = dex.size[this.size]
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
debug return
debug endif
if tb == 0 then
//Create a Table to index recycled instances with their array size
set tb = Table.create()
set dex.size[this.size] = tb
endif
call dex.size.remove(this) //Clear the array size from hash memory
set tb[this] = tb[0]
set tb[0] = this
endmethod
private static Table tempTable
private static integer tempEnd
//Avoids hitting the op limit
private static method clean takes nothing returns nothing
local Table tb = .tempTable
local integer end = tb + 0x1000
if end < .tempEnd then
set .tempTable = end
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
else
set end = .tempEnd
endif
loop
call tb.flush()
set tb = tb + 1
exitwhen tb == end
endloop
endmethod
//Flushes the TableArray and also destroys it. Doesn't get any more
//similar to the FlushParentHashtable native than this.
//
method flush takes nothing returns nothing
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
set .tempTable = this
set .tempEnd = this + this.size
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
call this.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=37
//TESH.alwaysfold=0
library StunSystem uses Table
//********************************************************************************
// Stun - Version 1.2.0.0 - By iAyanami aka Ayanami
//********************************************************************************
//
// Stun:
// - An easy to use system that stuns units
// - Able to keep track of the remaining stun duration
//
// Requirements:
// - JASS NewGen
// - Table
//
// Functions:
// - Stun.apply takes unit whichUnit, real duration, boolean stack returns nothing
// * whichUnit is the target to be stunned
// * duration is the duration of the stun
// * stack is to determine if the stun should be a stacking one or not
// * true - the stun will stack, the duration of the stun will add up with the previous duration
// * false - the stun will not stack, the unit will be stunned for the longer stun duration
//
// - Stun.getDuration takes unit whichUnit returns real
// * whichUnit is the target to check
// * returns the remaining stun duration
//
// - Stun.stop takes unit whichUnit returns nothing
// * removes stun from the target
//
// How to import:
// - Copy the whole "Stun" Trigger Folder into your map
// - Save the map. Close and re-opem the map.
// - You should have a new unit (Stun Dummy), ability (Stun (System)) and buff (Stun (System)) created
// - Read through the Configuration part of the code
//
// Credits:
// - Bribe for Table
//
//********************************************************************************
// CONFIGURABLES
//********************************************************************************
globals
// timer period. lower the value, the more accurate but might cause decrease in
// performance
private constant real PERIOD = 0.03125
// raw code of ability "Stun (System)"
private constant integer ABILID = 'ASTN'
// raw code of buff "Stun (System)"
private constant integer BUFFID = 'BSTN'
// raw code of unit "Stun Dummy"
private constant integer STUNID = 'sTUN'
endglobals
//********************************************************************************
// CODE
//********************************************************************************
// initialization
module Init
private static method onInit takes nothing returns nothing
set table = Table.create()
set caster = CreateUnit(Player(13), STUNID, 0, 0, 0)
call UnitAddAbility(caster, ABILID)
endmethod
endmodule
struct Stun extends array
private unit u
private real dur
private thistype next
private thistype prev
private static Table table
private static timer t = CreateTimer()
private static unit caster
private static integer count = 0
// remove the stun and deallocate
private method destroy takes nothing returns nothing
call UnitRemoveAbility(this.u, BUFFID)
if this.next != 0 then
set this.next.prev = this.prev
endif
set this.prev.next = this.next
set this.dur = 0
set this.prev = thistype(0).prev
set thistype(0).prev = this
if thistype(0).next == 0 then
call PauseTimer(t)
endif
call table.remove(GetHandleId(this.u))
endmethod
// iterating through all instances every PERIOD
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
// immediately removes stun for the specified unit
// ex: call Stun.stop(whichTarget)
static method stop takes unit u returns nothing
local integer id = GetHandleId(u)
if table.has(id) then
call thistype(table[id]).destroy()
endif
endmethod
// gets the duration left for stun, not stunned units always return 0
// ex: local real r = Stun.getDuration(whichTarget)
static method getDuration takes unit u returns real
return thistype(table[GetHandleId(u)]).dur
endmethod
// stunning specified target and to see if the stun is a stacking one or not
// ex: call Stun.apply(whichTarget, 5.0, false)
static method apply takes unit u, real dur, boolean b returns nothing
local thistype this
local integer id = GetHandleId(u)
if table.has(id) then
set this = table[id]
else
if thistype(0).prev == 0 then
set count = count + 1
set this = count
else
set this = thistype(0).prev
set thistype(0).prev = thistype(0).prev.prev
endif
if thistype(0).next == 0 then
call TimerStart(t, PERIOD, true, function thistype.iterate)
else
set thistype(0).next.prev = this
endif
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = thistype(0)
set table[id] = this
set this.u = u
set this.dur = 0
call IssueTargetOrder(caster, "firebolt", this.u)
endif
if b and dur > 0 then
set this.dur = this.dur + dur
else
if this.dur < dur then
set this.dur = dur
endif
endif
endmethod
implement Init
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//! external ObjectMerger w3a ACfb ASTN aani "" aart "" amat "" amsp "0" anam "Stun (System)" ansf "" Htb1 1 "0" aran 1 "99999" acdn 1 "0" ahdu 1 "99999" adur 1 "99999" abuf 1 "BSTN" amcs 1 "0" arac "other" atar 1 "" atp1 1 " " aub1 1 " "
//! external ObjectMerger w3h BPSE BSTN fart "ReplaceableTextures\CommandButtons\BTNStun.blp" fnsf "" fnam "Stun (System)" ftip "Stunned" fube "This unit is stunned; it cannot move nor attack temporarily."
//! external ObjectMerger w3u nalb sTUN 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 "Stun Dummy" utip " " utub " " usid 0 usin 0
//TESH.scrollpos=21
//TESH.alwaysfold=0
library WorldBounds /* v2.0.0.0
************************************************************************************
*
* struct WorldBounds extends array
* readonly static integer maxX
* readonly static integer maxY
* readonly static integer minX
* readonly static integer minY
* readonly static integer centerX
* readonly static integer centerY
* readonly static rect world
* readonly static region worldRegion
*
************************************************************************************/
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=GetWorldBounds()
set maxX=R2I(GetRectMaxX(world))
set maxY=R2I(GetRectMaxY(world))
set minX=R2I(GetRectMinX(world))
set minY=R2I(GetRectMinY(world))
set centerX=R2I((maxX+minX)/2)
set centerY=R2I((minY+maxY)/2)
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endmethod
endmodule
struct WorldBounds extends array
readonly static integer maxX
readonly static integer maxY
readonly static integer minX
readonly static integer minY
readonly static integer centerX
readonly static integer centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
*=================================================================================*
* Map Bounds 1.1 *
* By Adiktuz *
* *
* *
* This is a short snippet that provides some useful functions utilizing *
* the WorldBounds library created by Nestharus *
* *
* *
* Credits: *
* Nestharus for the WorldBounds library *
* Magtheridon96 for suggestions *
* *
* Functions: *
* *
* -> mapIncludeX(real x) returns boolean *
* -> mapIncludeY(real y) returns boolean *
* -> GetBoundedX(real x) returns real *
* -> GetBoundedY(real y) returns real *
* *
* *
* The mapIncludeX/Y functions return if the given x/y value is inside the map *
* *
* The GetBoundedX/Y checks if the given value is within the map. If it's *
* within the map, it will return the value given and if Not *
* it will return the value of the border that it will exceed *
* *
*=================================================================================*
*/
library MapBounds requires WorldBounds
function mapIncludeX takes real x returns boolean
return x < WorldBounds.maxX and x > WorldBounds.minX
endfunction
function mapIncludeY takes real y returns boolean
return y < WorldBounds.maxY and y > WorldBounds.minY
endfunction
function GetBoundedX takes real x returns real
if x > WorldBounds.maxX then
return I2R(WorldBounds.maxX)
elseif x < WorldBounds.minX then
return I2R(WorldBounds.minX)
endif
return x
endfunction
function GetBoundedY takes real y returns real
if y > WorldBounds.maxY then
return I2R(WorldBounds.maxY)
elseif y < WorldBounds.minY then
return I2R(WorldBounds.minY)
endif
return y
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Jump in Place version 1.02
by Adiktuz
Basically, this library handles jumping in place, but mainly for usage with the
impale system
It also allows the user to specify actions to be done after the jump is done
You're also allowed to choose what to do when a unit that is currently jumping
is re-jumped again by modifying the value of the jumptype parameter
You can use either:
JUMP_TYPE_STACK - stack each instance of jump for the unit
JUMP_TYPE_HEIGHT_STACK - stack only the jump height
JUMP_TYPE_RESET - stops the existing jump and resets unit height before doing the jump
JUMP_TYPE_NO_OVERWRITE - don't allow stacking
Disclaimer: Mixing these jump types might look weird...
Please take note that if you registered a StopEvent for the spell, and set the jumps to stack or reset,
the event will only run once when the unit hits the ground
How to Use:
call JumpInPlace.fire(unit flyUnit, unit causeUnit, real duration, real maxheight, integer abil, integer jumptype)
unit flyUnit -> unit that will jump
unit causeUnit -> the unit that caused the jump
real duration -> duration of jump
real maxheight -> maxheight of jump
integer abil -> rawcode of the ability that caused the jump
integer jumptype -> jump type
How to set action for when the unit returns to it's original height:
call JumpInPlace.registerStopEvent(integer abil, code action)
integer abil => the rawcode of the spell in which you want to add the action
use 0 if it won't be tied to any ability
code action => the function which will be run
You can also register global stop and start actions
call JumpInPlace.registerGlobalEndEvent(code action)
-> fires for any jump that finishes
call JumpInPlace.registerGlobalStartEvent(code action)
-> fires for any jump that starts
But before using them, make sure to set their correspoding variables to true on the globals block below
Variables you can use for the Event handlers
JumpInPlace.tmpFlyUnit => unit that triggered the event (the jumping unit)
JumpInPlace.tmpCauseUnit => the unit that caused the FlyUnit to jump
*/
library JumpInPlace requires T32, Table
globals
//Do you have an auto-fly library (like Magtheridon96's or Nestharus')?
private boolean AUTO_FLY = false
private constant integer FLY_ID = 'Amrf'
//Set to true if you're gonna use the global start event handler
private constant boolean USE_GLOBAL_START = false
//Set to true if you're gonna use the global end event handler
private constant boolean USE_GLOBAL_END = false
//Do not touch
constant integer JUMP_TYPE_STACK = 1
constant integer JUMP_TYPE_HEIGHT_STACK = 2
constant integer JUMP_TYPE_RESET = 3
constant integer JUMP_TYPE_NO_OVERWRITE = 4
endglobals
private module init
static method onInit takes nothing returns nothing
set FlyTable = Table.create()
set EventTable = Table.create()
static if USE_GLOBAL_START then
set globalStart = CreateTrigger()
endif
static if USE_GLOBAL_END then
set globalEnd = CreateTrigger()
endif
endmethod
endmodule
struct JumpInPlace extends array
private static integer instanceCount = 0
private static thistype recycle = 0
private thistype recycleNext
static Table FlyTable
static Table EventTable
static trigger globalEnd
static trigger globalStart
static unit tmpFlyUnit
static unit tmpCauseUnit
unit flyUnit
unit causeUnit
real maxheight
real hps
real height
real dfh
boolean up
integer abil
static method registerStopEvent takes integer abil, code toDo returns nothing
if not EventTable.handle.has(abil) then
set EventTable.trigger[abil] = CreateTrigger()
endif
call TriggerAddCondition(EventTable.trigger[abil], Filter(toDo))
endmethod
static method registerGlobalStartEvent takes code toDo returns nothing
call TriggerAddCondition(globalStart,Filter(toDo))
endmethod
static method registerGlobalEndEvent takes code toDo returns nothing
call TriggerAddCondition(globalEnd,Filter(toDo))
endmethod
method stop takes nothing returns nothing
call SetUnitFlyHeight(this.flyUnit, this.dfh, 0.0)
call this.stopPeriodic()
set thistype.tmpFlyUnit = this.flyUnit
set thistype.tmpCauseUnit = this.causeUnit
if EventTable.handle.has(this.abil) then
call TriggerEvaluate(EventTable.trigger[this.abil])
endif
static if USE_GLOBAL_END then
call TriggerEvaluate(globalEnd)
endif
set FlyTable[GetHandleId(this.flyUnit)] = 0
set recycleNext = recycle
set recycle = this
endmethod
method periodic takes nothing returns nothing
if this.up then
set this.height = this.height + hps
if this.height >= this.maxheight then
set this.up = false
endif
call SetUnitFlyHeight(this.flyUnit, this.height, 0.0)
else
set this.height = this.height - hps
call SetUnitFlyHeight(this.flyUnit, this.height, 0.0)
if this.height <= this.dfh then
set this.up = true
call this.stop()
endif
endif
endmethod
implement T32x
static method fire takes unit flyUnit, unit causeUnit, real duration, real maxheight, integer abil, integer jumptype returns nothing
local thistype this
local integer id = GetHandleId(flyUnit)
if FlyTable[id] == 0 or jumptype == 1 then
if (recycle == 0) then
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = recycle
set recycle = recycle.recycleNext
endif
set FlyTable[id] = this
static if not AUTO_FLY then
if UnitAddAbility(flyUnit, FLY_ID) and UnitRemoveAbility(flyUnit, FLY_ID) then
endif
endif
set this.abil = abil
set this.causeUnit = causeUnit
set this.flyUnit = flyUnit
set this.dfh = GetUnitDefaultFlyHeight(flyUnit)
set this.maxheight = maxheight + dfh
set this.hps = (maxheight*2/duration)*T32_PERIOD
set this.height = dfh
set this.up = true
call this.startPeriodic()
else
set this = FlyTable[id]
if jumptype == 2 then
static if not AUTO_FLY then
if UnitAddAbility(flyUnit, FLY_ID) and UnitRemoveAbility(flyUnit, FLY_ID) then
endif
endif
set this.abil = abil
set this.causeUnit = causeUnit
set this.maxheight = this.maxheight + maxheight
set this.hps = ((this.maxheight*2 - this.height)/duration)*T32_PERIOD
set this.up = true
elseif jumptype == 3 then
static if not AUTO_FLY then
if UnitAddAbility(flyUnit, FLY_ID) and UnitRemoveAbility(flyUnit, FLY_ID) then
endif
endif
set this.causeUnit = causeUnit
set this.abil = abil
call SetUnitFlyHeight(this.flyUnit, dfh, 0.0)
set this.maxheight = maxheight + dfh
set this.hps = (maxheight*2/duration)*T32_PERIOD
set this.height = dfh
set this.up = true
elseif jumptype == 4 then
return
endif
endif
set thistype.tmpFlyUnit = this.flyUnit
set thistype.tmpCauseUnit = this.causeUnit
static if USE_GLOBAL_START then
call TriggerEvaluate(globalStart)
endif
endmethod
implement init
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Impale System 1.1c requires T32, Table, JumpInPlace, StunSystem, *MapBound*
by Adiktuz
Credits to Bribe, Magtheridon96 and iAyanami for their system that were used
on this library and the sample spells
An impale system which allows you to create custom impale-like spells
Features:
- Allows creation of more than one-type of impale spell
- *Can multi-impale a unit (requires balancing with the settings of the JumpInPlace library)
- *Can easily change which units can be hit
- *Can easily change the way damage is dealt
- *Can set actions for when the impale wave ends and for when the unit falls
back to it's initial height (dependent on JumpInPlace library)
*Can be set per impale-type spell
How to Import:
1)If you don't have the dummy.mdx and a dummy unit yet,
export it and the Dummy unit and import into your map
2)Copy the whole Spell folder into your map
3)Enable the Objects Trigger
4)Save your map
5)Close map
6)Reopen map
7)Disable/Delete the objects trigger
8)Save your map
9)Edit the configurables below and read the How to use
10)Enjoy!
Stub methods:
//onStop action, can be overwritten by structs that extend this struct
stub method Stop takes nothing returns nothing
//place your actions here
//It is important that you don't remove these three function calls
call this.unitTable.destroy()
call this.stopPeriodic()
call this.destroy()
endmethod
//onDamage action, can be overwritten by structs that extend this struct
stub method onDamage takes unit target returns nothing
-placed it here so that they can change the way the damage and "flying" are done
We added the stun duration and the air-time duration for the real duration of the stun
since the given stun duration is counted after the unit lands but we will stun
it right after it is hit by impale-
call Stun.apply(target, this.duration + this.stduration, false)
call UnitDamageTarget(this.caster, target, GetRandomReal(this.lowdamage, this.highdamage), false, false, this.at, this.dt, null)
call JumpIP.Fire(target, this.caster, this.duration, this.maxheight, this.abil)
endmethod
//determines which units can be hit by impale, can be overwritten by structs that extend this struct
stub method hitFilter takes unit target returns boolean
return IsUnitEnemy(target, this.owner) and GetWidgetLife(target) > .405 and this.unitTable[GetHandleId(target)] == 0
endmethod
How to Use:
For normal usage (if you're not gonna replace any of the stub methods)
-> Impale.CreateFire()
-> Impale.CreateFireCID()
-> Impale.CreateFireEX()
call Impale.CreateFire(takes unit caster, integer level, string model, string modelhit,
real angle, real scale, real aoe, real distance, real distanceperwave,
real damage returns nothing)
unit Caster -> the unit that casted the impale
integer level -> level of the spell
string model -> path to the model of the impale wave
string modelhit -> path to the model of the hit effect
real angle -> angle to which the impale is going
real scale -> scale of each impale wave
real aoe -> filter aoe for each impale wave
real distance -> max range of the impale
real distanceperwave -> distance between each impale wave
real damage -> damage of the impale
call Impale.CreateFireCID(takes unit caster, integer level, string model, string modelhit,
real angle, real scale, real aoe, real distance, real distanceperwave,
real damage, intger abil returns nothing)
integer abil -> rawcode of the spell
call Impale.CreateFireEX(takes unit caster, integer level, string model, string modelhit, real x,real y,
real angle, real wave, real scale, real aoe, real distance, real distanceperwave,
real damagelow, real damagehigh, real stduration, real duration,
real maxheight, integer abil, attacktype at, damagetype dt, integer jumptype)
real x -> starting x coordinate of the impale
real y -> starting y coordinate of the impale
real wave -> time interval between each impale wave
real damagelow -> lower bound damage of the impale
real damagehigh -> higher bound damage of the impale
real stduration -> duration of stun (counted from after the unit lands)
real duration -> duration of the air-time
real maxheight -> max height of the air-time
integer abil -> rawcode of the spell
attacktype at -> attack type of the spell
damagetype dt -> damage type of the spell
integer jumptype -> jump type, refer to JIP library
For more info, look at the sample spells
If you're gonna replace the stub methods
Method list are same as above, but without the Create word
-> StructVariableName.Fire()
-> StructVariableName.FireCID()
-> StructVariableName.FireEX()
First you need to create a struct which extends the Impale struct
ex. struct A extends Impale
endstruct
then you create the replacement method for the stub method that you want to replace
without the stub word anymore
ex. struct A extends Impale
method onDamage takes unit target returns nothing
endmethod
endstruct
Note: make sure that they still have the same parameter list as the original method
else, it will cause an error
then you create a local variable of type Impale and set it to an instance of your
new struct, then use that local variable to call the function you need
ex. local Impale ex = A.create()
call ex.Fire()
Note: It is important that the type of the local variable should be Impale
You can view the Death Siphon trigger for a working example
How to set action for when the unit returns to it's original height:
call JumpIP.RegisterStopEvent(integer abil, code action)
integer abil => the rawcode of the spell in which you want to add the action
code action => the function which will be run
Variables you can use for the StopEvent
JumpIP.tmpFlyUnit => unit that triggered the StopEvent (the jumping unit)
JumpIP.tmpCauseUnit => the unit that caused the FlyUnit to jump
See the Death Siphon trigger for a working example
*/
library ImpaleSystem requires T32, Table, JumpInPlace, StunSystem, MapBounds
globals
//rawcode of dummy unit
private constant integer DUMMY_ID = 'e000'
/*
The next set of data is for impales created using the Fire and FireCID methods
*/
//sets the time interval for each impale wave
private constant real DEF_WAVE = .09
//sets the air-time duration
private constant real DEF_DURATION = 1.00
//sets the stun duration (counted from when the unit lands)
private constant real DEF_STDURATION = 1.00
//max height of the air-time
private constant real DEF_HEIGHT = 300.0
//default jump type
//see the JIP library for definition
private constant integer JUMP = JUMP_TYPE_HEIGHT_STACK
//used for registering stop event for the normal impales
//you can set it to the rawcode of the dummy stun spell
//since it won't probably be used to register an impale anyway
//or you can also use the rawcode of any passive/aura spell
private constant integer DUMMY_SPELL = 'A002'
//set this to false if you won't use the onEnd event for the default impales
private constant boolean USE_ON_END = false
//attack type of the impale
private constant attacktype DEF_AT = ATTACK_TYPE_MAGIC
//damage type of the impale
private constant damagetype DEF_DT = DAMAGE_TYPE_NORMAL
//required, DO NOT EDIT
private group tmpGroup = CreateGroup()
endglobals
//End of Configuration
struct Impale
unit caster
integer level
integer jumptype
string model
real wave
real waved
real scale
real aoe
real distance
real distx
real disty
real lowdamage
real highdamage
real duration
real stduration
real maxheight
real angle
real x
real y
real current
real total
player owner
integer abil
attacktype at
damagetype dt
string modelhit
Table unitTable
static unit tmpUnit
/*
registered as the stop action for all normal/simple impales
this is run after the air-time ends
make sure to set USE_ON_END to true if you're gonna put actions
into this method
*/
static method onEnd takes nothing returns nothing
endmethod
//onStop action, can be overwritten by structs that extend this struct
stub method stop takes nothing returns nothing
//It is important that you don't remove these three function calls
call this.unitTable.destroy()
call this.stopPeriodic()
call this.destroy()
endmethod
//onDamage action, can be overwritten by structs that extend this struct
stub method onDamage takes unit target returns nothing
/*
placed it here so that they can change the way the damage and "flying" are done
We added the stun duration and the air-time duration for the real duration of the stun
since the given stun duration is counted after the unit lands but we will stun
it right after it is hit by impale
*/
call Stun.apply(target, this.duration + this.stduration, false)
call UnitDamageTarget(this.caster, target, GetRandomReal(this.lowdamage, this.highdamage), false, false, this.at, this.dt, null)
call JumpInPlace.fire(target, this.caster, this.duration, this.maxheight, this.abil,this.jumptype)
endmethod
//determines which units can be hit by impale, can be overwritten by structs that extend this struct
stub method hitFilter takes unit target returns boolean
return IsUnitEnemy(target, this.owner) and GetWidgetLife(target) > .405 and this.unitTable[GetHandleId(target)] == 0
endmethod
method periodic takes nothing returns nothing
set this.current = this.current + T32_PERIOD
if this.current >= this.wave then
set this.wave = this.wave + this.waved
set this.x = this.x + this.distx
set this.y = this.y + this.disty
if not (mapIncludeX(this.x) and mapIncludeY(this.y))then
call this.stop()
return
endif
call GroupEnumUnitsInRange(tmpGroup, this.x,this.y,this.aoe, null)
set tmpUnit = CreateUnit(Player(15), DUMMY_ID, this.x, this.y, 0.0)
call SetUnitScale(tmpUnit, this.scale, 0, 0)
call UnitApplyTimedLife(tmpUnit, 'BTLF', 1.00)
call DestroyEffect(AddSpecialEffectTarget(this.model, tmpUnit, "origin"))
loop
set tmpUnit = FirstOfGroup(tmpGroup)
exitwhen tmpUnit == null
if this.hitFilter(tmpUnit) then
set this.unitTable[GetHandleId(tmpUnit)] = 1
//made the hit effect on the ground because attaching it to the unit
//causes visual bugs if the unit is hit by multiple impales
//and the effect stays for a while after the destroy is called (both effects will show)
call DestroyEffect(AddSpecialEffect(this.modelhit, GetUnitX(tmpUnit), GetUnitY(tmpUnit)))
call this.onDamage(tmpUnit)
endif
call GroupRemoveUnit(tmpGroup, tmpUnit)
endloop
if this.current >= this.total then
call this.stop()
endif
else
endif
endmethod
implement T32x
//Methods to be used if you're gonna replace any of the stub methods
method fireEX takes unit caster, integer level, string model, string modelhit, real x,real y, /*
*/real angle, real wave, real scale, real aoe, real distance, real distanceperwave,/*
*/real damagelow, real damagehigh, real stduration, real duration, /*
*/real maxheight, integer abil, attacktype at, damagetype dt,integer jumptype returns nothing
set this.caster = caster
set this.level = level
set this.model = model
set this.wave = wave
set this.angle = angle
set this.scale = scale
set this.aoe = aoe
set this.distance = distance
set this.distx = distanceperwave*Cos(this.angle)
set this.disty = distanceperwave*Sin(this.angle)
set this.lowdamage = damagelow
set this.highdamage = damagehigh
set this.stduration = stduration
set this.duration = duration
set this.maxheight = maxheight
set this.x = x
set this.y = y
set this.current = 0.0
set this.waved = this.wave
set this.total = (distance/distanceperwave)*this.wave
set this.unitTable = Table.create()
set this.at = at
set this.dt = dt
set this.owner = GetOwningPlayer(caster)
set this.modelhit = modelhit
set this.abil = abil
set this.jumptype = jumptype
call this.startPeriodic()
endmethod
method fire takes unit caster, integer level, string model, string modelhit,/*
*/real angle, real scale, real aoe, real distance, real distanceperwave,/*
*/real damage returns nothing
set this.caster = caster
set this.level = level
set this.model = model
set this.scale = scale
set this.angle = angle
set this.aoe = aoe
set this.distance = distance
set this.distx = distanceperwave*Cos(this.angle)
set this.disty = distanceperwave*Sin(this.angle)
set this.lowdamage = damage
set this.highdamage = damage
set this.duration = DEF_DURATION
set this.stduration = DEF_STDURATION
set this.maxheight = DEF_HEIGHT
set this.wave = DEF_WAVE
set this.x = GetUnitX(caster)
set this.y = GetUnitY(caster)
set this.current = 0.0
set this.waved = this.wave
set this.total = (distance/distanceperwave)*this.wave
set this.unitTable = Table.create()
set this.at = DEF_AT
set this.dt = DEF_DT
set this.owner = GetOwningPlayer(caster)
set this.modelhit = modelhit
set this.abil = DUMMY_SPELL
set this.jumptype = JUMP
call this.startPeriodic()
endmethod
method fireCID takes unit caster, integer level, string model, string modelhit,/*
*/real angle, real scale, real aoe, real distance, real distanceperwave,/*
*/real damage, integer abil returns nothing
set this.caster = caster
set this.level = level
set this.model = model
set this.scale = scale
set this.angle = angle
set this.aoe = aoe
set this.distance = distance
set this.distx = distanceperwave*Cos(this.angle)
set this.disty = distanceperwave*Sin(this.angle)
set this.lowdamage = damage
set this.highdamage = damage
set this.duration = DEF_DURATION
set this.stduration = DEF_STDURATION
set this.maxheight = DEF_HEIGHT
set this.wave = DEF_WAVE
set this.x = GetUnitX(caster)
set this.y = GetUnitY(caster)
set this.current = 0.0
set this.waved = this.wave
set this.total = (distance/distanceperwave)*this.wave
set this.unitTable = Table.create()
set this.at = DEF_AT
set this.dt = DEF_DT
set this.owner = GetOwningPlayer(caster)
set this.modelhit = modelhit
set this.abil = abil
set this.jumptype = JUMP
call this.startPeriodic()
endmethod
//Methods to be used if you're not gonna replace any of the stub methods
static method createFireEX takes unit caster, integer level, string model, string modelhit, real x,real y, /*
*/real angle, real wave, real scale, real aoe, real distance, real distanceperwave,/*
*/real damagelow, real damagehigh, real stduration, real duration, /*
*/real maxheight, integer abil, attacktype at, damagetype dt,integer jumptype returns nothing
local thistype this = .allocate()
set this.caster = caster
set this.level = level
set this.model = model
set this.wave = wave
set this.angle = angle
set this.scale = scale
set this.aoe = aoe
set this.distance = distance
set this.distx = distanceperwave*Cos(this.angle)
set this.disty = distanceperwave*Sin(this.angle)
set this.lowdamage = damagelow
set this.highdamage = damagehigh
set this.stduration = stduration
set this.duration = duration
set this.maxheight = maxheight
set this.x = x
set this.y = y
set this.current = 0.0
set this.waved = this.wave
set this.total = (distance/distanceperwave)*this.wave
set this.unitTable = Table.create()
set this.at = at
set this.dt = dt
set this.owner = GetOwningPlayer(caster)
set this.modelhit = modelhit
set this.abil = abil
set this.jumptype = jumptype
call this.startPeriodic()
endmethod
static method createFire takes unit caster, integer level, string model, string modelhit,/*
*/real angle, real scale, real aoe, real distance, real distanceperwave,/*
*/real damage returns nothing
local thistype this = .allocate()
set this.caster = caster
set this.level = level
set this.model = model
set this.scale = scale
set this.angle = angle
set this.aoe = aoe
set this.distance = distance
set this.distx = distanceperwave*Cos(this.angle)
set this.disty = distanceperwave*Sin(this.angle)
set this.lowdamage = damage
set this.highdamage = damage
set this.duration = DEF_DURATION
set this.stduration = DEF_STDURATION
set this.maxheight = DEF_HEIGHT
set this.wave = DEF_WAVE
set this.x = GetUnitX(caster)
set this.y = GetUnitY(caster)
set this.current = 0.0
set this.waved = this.wave
set this.total = (distance/distanceperwave)*this.wave
set this.unitTable = Table.create()
set this.at = DEF_AT
set this.dt = DEF_DT
set this.owner = GetOwningPlayer(caster)
set this.modelhit = modelhit
set this.abil = DUMMY_SPELL
call this.startPeriodic()
endmethod
static method createFireCID takes unit caster, integer level, string model, string modelhit,/*
*/real angle, real scale, real aoe, real distance, real distanceperwave,/*
*/real damage, integer abil returns nothing
local thistype this = .allocate()
set this.caster = caster
set this.level = level
set this.model = model
set this.scale = scale
set this.angle = angle
set this.aoe = aoe
set this.distance = distance
set this.distx = distanceperwave*Cos(this.angle)
set this.disty = distanceperwave*Sin(this.angle)
set this.lowdamage = damage
set this.highdamage = damage
set this.duration = DEF_DURATION
set this.stduration = DEF_STDURATION
set this.maxheight = DEF_HEIGHT
set this.wave = DEF_WAVE
set this.x = GetUnitX(caster)
set this.y = GetUnitY(caster)
set this.current = 0.0
set this.waved = this.wave
set this.total = (distance/distanceperwave)*this.wave
set this.unitTable = Table.create()
set this.at = DEF_AT
set this.dt = DEF_DT
set this.owner = GetOwningPlayer(caster)
set this.modelhit = modelhit
set this.abil = abil
set this.jumptype = JUMP
call this.startPeriodic()
endmethod
//I didn't use a module initializer because it returns an error
//on the impale samples
static method onInit takes nothing returns nothing
static if USE_ON_END then
call JumpInPlace.RegisterStopEvent(DUMMY_SPELL, function thistype.onEnd)
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//============================================================================
// SpellEffectEvent
// - Version 1.1.0.0
//
// API
// ---
// RegisterSpellEffectEvent(integer abil, code onCast)
//
// Requires
// --------
// RegisterPlayerUnitEvent: hiveworkshop.com/forums/showthread.php?t=203338
//
// Optional
// --------
// Table: hiveworkshop.com/forums/showthread.php?t=188084
//
library SpellEffectEvent requires RegisterPlayerUnitEvent optional Table
//============================================================================
private module M
static if LIBRARY_Table then
static Table tb
else
static hashtable ht = InitHashtable()
endif
static method onCast takes nothing returns nothing
static if LIBRARY_Table then
call TriggerEvaluate(.tb.trigger[GetSpellAbilityId()])
else
call TriggerEvaluate(LoadTriggerHandle(.ht, 0, GetSpellAbilityId()))
endif
endmethod
private static method onInit takes nothing returns nothing
static if LIBRARY_Table then
set .tb = Table.create()
endif
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endmodule
//============================================================================
private struct S extends array
implement M
endstruct
//============================================================================
function RegisterSpellEffectEvent takes integer abil, code onCast returns nothing
static if LIBRARY_Table then
if not S.tb.handle.has(abil) then
set S.tb.trigger[abil] = CreateTrigger()
endif
call TriggerAddCondition(S.tb.trigger[abil], Filter(onCast))
else
if not HaveSavedHandle(S.ht, 0, abil) then
call SaveTriggerHandle(S.ht, 0, abil, CreateTrigger())
endif
call TriggerAddCondition(LoadTriggerHandle(S.ht, 0, abil), Filter(onCast))
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.1.0.0
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must either
* return a boolean (false) or nothing. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
* - Don't destroy a trigger unless you really know what you're doing.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent takes playerunitevent whichEvent, code whichFunction returns nothing
* - Registers code that will execute when an event fires.
* - function RegisterPlayerUnitEventForPlayer takes playerunitevent whichEvent, code whichFunction, player whichPlayer returns nothing
* - Registers code that will execute when an event fires for a certain player.
* - function GetPlayerUnitEventTrigger takes playerunitevent whichEvent returns trigger
* - Returns the trigger corresponding to ALL functions of a playerunitevent.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 260 + 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function GetPlayerUnitEventTrigger takes playerunitevent p returns trigger
return t[GetHandleId(p)]
endfunction
endlibrary
//TESH.scrollpos=20
//TESH.alwaysfold=0
scope NormalImpale initializer init //Requires ImpaleSystem, SpellEvent
globals
private constant integer IMPALE_ID = 'A000'
private constant string IMPALE_MODEL = "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl"
private constant string IMPALE_HIT_MODEL = "Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl"
private constant real WAVE_DISTANCE = 200.0
private constant real WAVE_AOE = 100.0
endglobals
private function GetDamage takes unit u, integer level returns real
return 75.00*level
endfunction
private function GetDistance takes unit u, integer level returns real
return 400 + 200.00*level
endfunction
private function action takes nothing returns nothing
local unit caster = GetTriggerUnit()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real angle = Atan2(ty-y,tx-x)
local integer level = GetUnitAbilityLevel(caster, IMPALE_ID)
//Since were not gonna replace any stub method, we use the CreateFire method
call Impale.createFire(caster, level, IMPALE_MODEL,IMPALE_HIT_MODEL,/*
*/angle, 1.00, WAVE_AOE, GetDistance(caster,level), WAVE_DISTANCE,/*
*/GetDamage(caster,level))
set caster = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(IMPALE_ID,function action)
endfunction
endscope
//TESH.scrollpos=19
//TESH.alwaysfold=0
scope AquaBanisher initializer init //Requires AQUASystem, SpellEvent
//Take note that in this spell, units can be hit by more than 1 aqua banisher line
//meaning the damage and fly height can all stack-up.
//Units near the caster will experience the most number of hits on this case
globals
private constant integer AQUA_ID = 'A001'
private constant string AQUA_MODEL = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
private constant string AQUA_HIT_MODEL = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
private constant real WAVE_DISTANCE = 200.0
private constant real WAVE_AOE = 120.0
endglobals
private function GetDamage takes unit u, integer level returns real
return 75.00*level
endfunction
private function GetDistance takes unit u, integer level returns real
return 400 + 200.00*level
endfunction
struct Aqua extends Impale
//replaces the original Stop method
method Stop takes nothing returns nothing
call BJDebugMsg("Aqua Banisher End")
//It is important that you don't remove these three function calls
call this.unitTable.destroy()
call this.stopPeriodic()
call this.destroy()
endmethod
endstruct
private function action takes nothing returns nothing
local unit caster = GetTriggerUnit()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real angle = Atan2(ty-y,tx-x)
local integer level = GetUnitAbilityLevel(caster, AQUA_ID)
//we create an impale object and set it to an instance
//of our new struct in order for the stub methods to be
//replaceable
local Impale aqua = Aqua.create()
call aqua.fire(caster, level, AQUA_MODEL,AQUA_HIT_MODEL,/*
*/angle, 0.50, WAVE_AOE, GetDistance(caster,level), WAVE_DISTANCE,/*
*/GetDamage(caster,level))
set caster = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(AQUA_ID,function action)
endfunction
endscope
//TESH.scrollpos=39
//TESH.alwaysfold=0
scope DeathSiphon initializer init //Requires ImpaleSystem, SpellEvent
globals
private constant integer DS_ID = 'A003'
private constant string DS_MODEL = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"
private constant string DS_HIT_MODEL = "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl"
private constant real WAVE_DISTANCE = 200.0
private constant real WAVE_AOE = 100.0
endglobals
private function GetDamage takes unit u, integer level returns real
return 50.00*level
endfunction
private function GetDistance takes unit u, integer level returns real
return 400 + 200.00*level
endfunction
struct DS extends Impale
//replaces the onDamage stub method of the original Impale struct
method onDamage takes unit target returns nothing
//No stun here
call UnitDamageTarget(this.caster, target, this.lowdamage, false, false, this.at, this.dt, null)
call SetWidgetLife(this.caster, GetWidgetLife(this.caster) + this.lowdamage)
call DestroyEffect(AddSpecialEffectTarget(DS_HIT_MODEL, this.caster,"chest"))
call JumpInPlace.fire(target, this.caster, this.duration, this.maxheight, this.abil,this.jumptype)
endmethod
endstruct
private function onStop takes nothing returns nothing
call BJDebugMsg(GetUnitName(JumpInPlace.tmpFlyUnit) + " was Death Siphoned by " + GetHeroProperName(JumpInPlace.tmpCauseUnit))
endfunction
private function action takes nothing returns nothing
local unit caster = GetTriggerUnit()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real angle = Atan2(ty-y,tx-x)
local integer level = GetUnitAbilityLevel(caster, DS_ID)
//we create an impale object and set it to an instance
//of our new struct in order for the stub methods to be
//replaceable
local Impale Siphon = DS.create()
call Siphon.fireCID(caster, level, DS_MODEL,DS_HIT_MODEL,/*
*/angle, 0.75, WAVE_AOE, GetDistance(caster,level), WAVE_DISTANCE,/*
*/GetDamage(caster,level),DS_ID)
set caster = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(DS_ID,function action)
call JumpInPlace.registerStopEvent(DS_ID,function onStop)
endfunction
endscope
//TESH.scrollpos=22
//TESH.alwaysfold=0
scope BlindingFlash initializer init //Requires ImpaleSystem, SpellEvent
globals
private constant integer BF_ID = 'A006'
private constant string BF_MODEL = "Abilities\\Spells\\Human\\Invisibility\\InvisibilityTarget.mdl"
private constant string BF_HIT_MODEL = ""
private constant real WAVE_DISTANCE = 200.0
private constant real WAVE_AOE = 150.0
private constant integer DUMMY_ID = 'sTUN'
private constant integer BLIND_ID = 'ABLN'
//I used Drunken haze as a base because I can't seem to make the dummy units
//cast a curse-based spell
private constant string COMMAND = "drunkenhaze"
endglobals
private function GetDamage takes unit u, integer level returns real
return 200.00*level
endfunction
private function GetDistance takes unit u, integer level returns real
return 400 + 200.00*level
endfunction
struct BF
static unit dummycaster
static method onFall takes nothing returns nothing
call SetUnitAbilityLevel(dummycaster, BLIND_ID, GetUnitAbilityLevel(JumpInPlace.tmpCauseUnit,BF_ID))
call IssueTargetOrder(dummycaster, COMMAND, JumpInPlace.tmpFlyUnit)
endmethod
static method onInit takes nothing returns nothing
set dummycaster = CreateUnit(Player(13), DUMMY_ID,0.0, 0.0,0.0)
call UnitAddAbility(dummycaster, BLIND_ID)
endmethod
endstruct
private function action takes nothing returns nothing
local unit caster = GetTriggerUnit()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real angle = Atan2(ty-y,tx-x)
local integer level = GetUnitAbilityLevel(caster, BF_ID)
//we create an impale object and set it to an instance
//of our new struct in order for the stub methoBF to be
//replaceable
call Impale.createFireCID(caster, level, BF_MODEL,BF_HIT_MODEL,/*
*/angle, 0.75, WAVE_AOE, GetDistance(caster,level), WAVE_DISTANCE,/*
*/GetDamage(caster,level),BF_ID)
set caster = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent(BF_ID,function action)
call JumpInPlace.registerStopEvent(BF_ID,function BF.onFall )
endfunction
endscope