/*
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