- Joined
- Aug 16, 2010
- Messages
- 97
Hello everyone.
By the request of a mod, I changed my spell's script so it uses one timer for the whole spell. hence less performance issue. But since I used that method, a new problem has popped up. The caster, with every cast, moves faster and faster, while he should maintain the same speed. I have read thorugh this but haven't found a clue as to what causes this weird problem. Would be glad if you could tell me.
Thanks in advance.
[JASS="Spell Code"] library ZSlash requires UnitIndexer, TimerUtils, SpellEffectEvent, IsTerrainWalkable
//====================================================================================================================================
//
// By Dr.Killer
//
//====================================================================================================================================
//====================================================================================================================================
// Introduction: The hero launches himself forward, slashing enemies along his path and wounding them. Then he proceeds to slash
// more enemies in a Z pattern.
//====================================================================================================================================
//====================================================================================================================================
// Requirements:
//
// - CTL
// http://www.hiveworkshop.com/forums/jass-resources-412/snippet-constant-timer-loop-32-a-201381/
//
// - TimerUtils (Vexorian's version)
// http://www.wc3c.net/showthread.php?t=101322
//
// - UnitIndexer
// http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
//
// - SpellEffectEvent
// http://www.hiveworkshop.com/forums/...pelleffectevent-187193/?highlight=spelleffect
//
// - IsPathable
// http://http://www.hiveworkshop.com/forums/jass-resources-412/snippet-pathable-199131/
//
// The following libraries are required by the above systems:
//
// - RegisterPlayerUnitEvent
// http://hiveworkshop.com/forums/showthread.php?t=203338
//
// - Event
// http://hiveworkshop.com/forums/submissions-414/snippet-event-186555/
//
// - WorldBounds
// http://hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
//====================================================================================================================================
//====================================================================================================================================
// Credits
//
// - Vexorian for TimerUtils, JassHelper and contributions to WC3 modding in general
// - Nestharus for UnitIndexer, Event, WorldBounds, CTL
// - Magtheridon96 for his awesome MeatMash spell from which I learned a lot (and copied a bit) and RegisterPlayerUnitEvent
// - Bribe for SpellEffectEvent
//
//====================================================================================================================================
//====================================================================================================================================
// Important Notice
//
// Feel free to edit, modify, revise or anything that comes to your mind, just remember to credit me as the original creator
// wherever you use this.
//====================================================================================================================================
//=============================================================
// Configuration
//=============================================================
globals
//Editor stuff
private constant integer ABIL_CODE = 'A001'
//Spell stuff
private constant boolean LIMIT_TARGETS = false //Should the maximum number of slashed enemies be limited?
private constant boolean LIMIT_INJURY = true //Should a victim be abale to be damaged more than once?
private constant boolean INV = true //Should the caster turn invulnerable during the spell?
private constant boolean PAN = true //Should I pan the camera to hero's location in the end?
private constant real JUMP_DIST = 450. //How far the hero launches himself forward (Affects the size of Z)
private constant real Z_ANGLE = (bj_PI) / 4. //The angle between Z's horizontal and diagonal line. Best looking at Pi/4.
private constant real DUR = .9 //How long it takes the hero to reach the end of each line in Z
private constant real INTERVAL = 0.03 //Interval between hero's movements. A lower amount results in a smooth
//movement but is more demanding.
private constant real D_JUMP_DIST = JUMP_DIST/Sin(Z_ANGLE)
private constant real TRAVEL_1 = JUMP_DIST / (DUR/INTERVAL)
private constant real TRAVEL_2 = D_JUMP_DIST / (DUR/INTERVAL)
private constant real PATH_OFFSET = 64. //Used when the hero gets stuck somewhere in the end of the spell.
//That's how much the hero's moved to find a walkable ground
private constant real RADIUS = 105.
private constant integer RED = 255
private constant integer GREEN = 255
private constant integer BLUE = 255
private constant integer ALPHA = 130
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
private constant string EFFECT_PATH = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
private constant string BLOOD_EFFECT_PATH = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodFootman.mdl"
private constant string ATTACH_POINT = "chest"
endglobals
//How much damage is dealt upon a slash
private function DamageOnSlash takes integer lvl returns real
return I2R(lvl*100)
endfunction
//Here you can decide what units will be affected by this spell
private function TargetFilter takes unit target, unit caster returns boolean
return IsUnitEnemy(target, GetOwningPlayer(caster)) and not (IsUnitType(target, UNIT_TYPE_DEAD) or IsUnitType(target, UNIT_TYPE_MECHANICAL) or IsUnitType(target, UNIT_TYPE_FLYING))
endfunction
//=============================================================
// End of Configuration
//=============================================================
//=============================================================
// Spell Code
//=============================================================
private struct Z extends array
private static integer array rn
private static integer ic = 0
private static unit array hero
private static real array totalTravel
private static integer array travelStage
private static real array angle
private static effect array sfx
private static real array dx
private static real array dy
//These coordinates are used to prevente our hero form getting stuck in the trees, etc.
private static group tempGroup //Used for unit enumeration
private static method onPeriod takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = 1
local real x
local real y
local real hero_X
local real hero_Y
local unit tempUnit
//Iterate over all spell instances
loop
exitwhen integer(this)>ic
set hero_X = GetUnitX(hero[this])
set hero_Y = GetUnitY(hero[this])
if hero[this] != null then
if travelStage[this] == 1 then //We're running along the first line
//call BJDebugMsg("ic: "+I2S(ic))
if totalTravel[this] < JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]
call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)
set totalTravel[this] = totalTravel[this] + (JUMP_DIST / (DUR/INTERVAL))
call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null
if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
call BJDebugMsg("i: "+I2S(this))
else
set totalTravel[this] = 0.
set travelStage[this] = travelStage[this] + 1
set angle[this] = angle[this] + bj_PI + Z_ANGLE
set dx[this] = D_JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = D_JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//call BJDebugMsg("first ende")
endif
elseif travelStage[this] == 2 then
if totalTravel[this] < D_JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]
call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)
set totalTravel[this] = totalTravel[this] + (D_JUMP_DIST / (DUR/INTERVAL))
call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null
if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
//call BJDebugMsg("this: "+I2S(this))
else
set totalTravel[this] = 0.
set travelStage[this] = travelStage[this] + 1
set angle[this] = angle[this] - bj_PI - Z_ANGLE
set dx[this] = JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//call BJDebugMsg("second ende")
endif
else
//Third travel stage
if totalTravel[this] < JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]
call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)
set totalTravel[this] = totalTravel[this] + (JUMP_DIST / (DUR/INTERVAL))
call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null
if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
//call BJDebugMsg("this: "+I2S(this))
else
//call BJDebugMsg("third ende")
//Spell has ended
call SetUnitInvulnerable(hero[this], false)
if GetLocalPlayer() == GetOwningPlayer(hero[this]) then
call SelectUnit(hero[this], true)
if PAN then
call PanCameraTo(hero_X, hero_Y)
endif
endif
call DestroyEffect(sfx[this])
call SetUnitVertexColor(hero[this], 255, 255, 255, 255)
//Cleanup
set hero[this] = null
set sfx[this] = null
set dx[this] = 0.
set dy[this] = 0.
//Deallocate this instance
set rn[this] = rn[0]
set rn[0] = this
endif
endif
endif
set this = this+1
endloop
//Cleanup Section
set tempUnit = null
set t = null
endmethod
private static method onCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local thistype this = rn[0]
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real cx //These are used for geometric calculations and determining the path of hero
local real cy //They actually help draw my Z
local integer lvl = GetUnitAbilityLevel(u, ABIL_CODE)
if this == 0 then
set ic = ic + 1
set this = ic
else
set rn[0] = rn[this]
endif
set hero[this] = u
set cx = GetUnitX(u)
set cy = GetUnitY(u)
set angle[this] = Atan2(ty-cy, tx-cx)
set totalTravel[this] = 0.
set travelStage[this] = 1
set u = null
set dx[this] = JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//Apply invunerability
if INV then
call SetUnitInvulnerable(hero[this], true)
endif
//Make hero transparent
call SetUnitVertexColor(hero[this], RED, GREEN, BLUE, ALPHA)
//Apply eyecandy
set sfx[this] = AddSpecialEffectTarget(EFFECT_PATH, hero[this], ATTACH_POINT)
//De-select the hero
if GetLocalPlayer() == GetOwningPlayer(hero[this]) then
call SelectUnit(hero[this], false)
endif
//First damage nearby enemies
call GroupEnumUnitsInRange(tempGroup, cx, cy, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set u = FirstOfGroup(tempGroup)
exitwhen u==null
if TargetFilter(u, hero[this]) then
call UnitDamageTarget(hero[this], u, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, u, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, u)
endloop
//Now we start the Stage 1 timer that moves our hero every INTEVAL seconds along the top most line of Z
if integer(this) == 1 then
call TimerStart(NewTimer(), INTERVAL, true, function thistype.onPeriod)
endif
//Cleanup
set u = null
endmethod
private static method onInit takes nothing returns nothing
set tempGroup = CreateGroup()
call RegisterSpellEffectEvent(ABIL_CODE, function thistype.onCast)
endmethod
endstruct
endlibrary
[/code]
By the request of a mod, I changed my spell's script so it uses one timer for the whole spell. hence less performance issue. But since I used that method, a new problem has popped up. The caster, with every cast, moves faster and faster, while he should maintain the same speed. I have read thorugh this but haven't found a clue as to what causes this weird problem. Would be glad if you could tell me.
Thanks in advance.
[JASS="Spell Code"] library ZSlash requires UnitIndexer, TimerUtils, SpellEffectEvent, IsTerrainWalkable
//====================================================================================================================================
//
// By Dr.Killer
//
//====================================================================================================================================
//====================================================================================================================================
// Introduction: The hero launches himself forward, slashing enemies along his path and wounding them. Then he proceeds to slash
// more enemies in a Z pattern.
//====================================================================================================================================
//====================================================================================================================================
// Requirements:
//
// - CTL
// http://www.hiveworkshop.com/forums/jass-resources-412/snippet-constant-timer-loop-32-a-201381/
//
// - TimerUtils (Vexorian's version)
// http://www.wc3c.net/showthread.php?t=101322
//
// - UnitIndexer
// http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
//
// - SpellEffectEvent
// http://www.hiveworkshop.com/forums/...pelleffectevent-187193/?highlight=spelleffect
//
// - IsPathable
// http://http://www.hiveworkshop.com/forums/jass-resources-412/snippet-pathable-199131/
//
// The following libraries are required by the above systems:
//
// - RegisterPlayerUnitEvent
// http://hiveworkshop.com/forums/showthread.php?t=203338
//
// - Event
// http://hiveworkshop.com/forums/submissions-414/snippet-event-186555/
//
// - WorldBounds
// http://hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
//====================================================================================================================================
//====================================================================================================================================
// Credits
//
// - Vexorian for TimerUtils, JassHelper and contributions to WC3 modding in general
// - Nestharus for UnitIndexer, Event, WorldBounds, CTL
// - Magtheridon96 for his awesome MeatMash spell from which I learned a lot (and copied a bit) and RegisterPlayerUnitEvent
// - Bribe for SpellEffectEvent
//
//====================================================================================================================================
//====================================================================================================================================
// Important Notice
//
// Feel free to edit, modify, revise or anything that comes to your mind, just remember to credit me as the original creator
// wherever you use this.
//====================================================================================================================================
//=============================================================
// Configuration
//=============================================================
globals
//Editor stuff
private constant integer ABIL_CODE = 'A001'
//Spell stuff
private constant boolean LIMIT_TARGETS = false //Should the maximum number of slashed enemies be limited?
private constant boolean LIMIT_INJURY = true //Should a victim be abale to be damaged more than once?
private constant boolean INV = true //Should the caster turn invulnerable during the spell?
private constant boolean PAN = true //Should I pan the camera to hero's location in the end?
private constant real JUMP_DIST = 450. //How far the hero launches himself forward (Affects the size of Z)
private constant real Z_ANGLE = (bj_PI) / 4. //The angle between Z's horizontal and diagonal line. Best looking at Pi/4.
private constant real DUR = .9 //How long it takes the hero to reach the end of each line in Z
private constant real INTERVAL = 0.03 //Interval between hero's movements. A lower amount results in a smooth
//movement but is more demanding.
private constant real D_JUMP_DIST = JUMP_DIST/Sin(Z_ANGLE)
private constant real TRAVEL_1 = JUMP_DIST / (DUR/INTERVAL)
private constant real TRAVEL_2 = D_JUMP_DIST / (DUR/INTERVAL)
private constant real PATH_OFFSET = 64. //Used when the hero gets stuck somewhere in the end of the spell.
//That's how much the hero's moved to find a walkable ground
private constant real RADIUS = 105.
private constant integer RED = 255
private constant integer GREEN = 255
private constant integer BLUE = 255
private constant integer ALPHA = 130
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
private constant string EFFECT_PATH = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
private constant string BLOOD_EFFECT_PATH = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodFootman.mdl"
private constant string ATTACH_POINT = "chest"
endglobals
//How much damage is dealt upon a slash
private function DamageOnSlash takes integer lvl returns real
return I2R(lvl*100)
endfunction
//Here you can decide what units will be affected by this spell
private function TargetFilter takes unit target, unit caster returns boolean
return IsUnitEnemy(target, GetOwningPlayer(caster)) and not (IsUnitType(target, UNIT_TYPE_DEAD) or IsUnitType(target, UNIT_TYPE_MECHANICAL) or IsUnitType(target, UNIT_TYPE_FLYING))
endfunction
//=============================================================
// End of Configuration
//=============================================================
//=============================================================
// Spell Code
//=============================================================
private struct Z extends array
private static integer array rn
private static integer ic = 0
private static unit array hero
private static real array totalTravel
private static integer array travelStage
private static real array angle
private static effect array sfx
private static real array dx
private static real array dy
//These coordinates are used to prevente our hero form getting stuck in the trees, etc.
private static group tempGroup //Used for unit enumeration
private static method onPeriod takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = 1
local real x
local real y
local real hero_X
local real hero_Y
local unit tempUnit
//Iterate over all spell instances
loop
exitwhen integer(this)>ic
set hero_X = GetUnitX(hero[this])
set hero_Y = GetUnitY(hero[this])
if hero[this] != null then
if travelStage[this] == 1 then //We're running along the first line
//call BJDebugMsg("ic: "+I2S(ic))
if totalTravel[this] < JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]
call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)
set totalTravel[this] = totalTravel[this] + (JUMP_DIST / (DUR/INTERVAL))
call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null
if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
call BJDebugMsg("i: "+I2S(this))
else
set totalTravel[this] = 0.
set travelStage[this] = travelStage[this] + 1
set angle[this] = angle[this] + bj_PI + Z_ANGLE
set dx[this] = D_JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = D_JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//call BJDebugMsg("first ende")
endif
elseif travelStage[this] == 2 then
if totalTravel[this] < D_JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]
call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)
set totalTravel[this] = totalTravel[this] + (D_JUMP_DIST / (DUR/INTERVAL))
call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null
if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
//call BJDebugMsg("this: "+I2S(this))
else
set totalTravel[this] = 0.
set travelStage[this] = travelStage[this] + 1
set angle[this] = angle[this] - bj_PI - Z_ANGLE
set dx[this] = JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//call BJDebugMsg("second ende")
endif
else
//Third travel stage
if totalTravel[this] < JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]
call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)
set totalTravel[this] = totalTravel[this] + (JUMP_DIST / (DUR/INTERVAL))
call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null
if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
//call BJDebugMsg("this: "+I2S(this))
else
//call BJDebugMsg("third ende")
//Spell has ended
call SetUnitInvulnerable(hero[this], false)
if GetLocalPlayer() == GetOwningPlayer(hero[this]) then
call SelectUnit(hero[this], true)
if PAN then
call PanCameraTo(hero_X, hero_Y)
endif
endif
call DestroyEffect(sfx[this])
call SetUnitVertexColor(hero[this], 255, 255, 255, 255)
//Cleanup
set hero[this] = null
set sfx[this] = null
set dx[this] = 0.
set dy[this] = 0.
//Deallocate this instance
set rn[this] = rn[0]
set rn[0] = this
endif
endif
endif
set this = this+1
endloop
//Cleanup Section
set tempUnit = null
set t = null
endmethod
private static method onCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local thistype this = rn[0]
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real cx //These are used for geometric calculations and determining the path of hero
local real cy //They actually help draw my Z
local integer lvl = GetUnitAbilityLevel(u, ABIL_CODE)
if this == 0 then
set ic = ic + 1
set this = ic
else
set rn[0] = rn[this]
endif
set hero[this] = u
set cx = GetUnitX(u)
set cy = GetUnitY(u)
set angle[this] = Atan2(ty-cy, tx-cx)
set totalTravel[this] = 0.
set travelStage[this] = 1
set u = null
set dx[this] = JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//Apply invunerability
if INV then
call SetUnitInvulnerable(hero[this], true)
endif
//Make hero transparent
call SetUnitVertexColor(hero[this], RED, GREEN, BLUE, ALPHA)
//Apply eyecandy
set sfx[this] = AddSpecialEffectTarget(EFFECT_PATH, hero[this], ATTACH_POINT)
//De-select the hero
if GetLocalPlayer() == GetOwningPlayer(hero[this]) then
call SelectUnit(hero[this], false)
endif
//First damage nearby enemies
call GroupEnumUnitsInRange(tempGroup, cx, cy, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set u = FirstOfGroup(tempGroup)
exitwhen u==null
if TargetFilter(u, hero[this]) then
call UnitDamageTarget(hero[this], u, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, u, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, u)
endloop
//Now we start the Stage 1 timer that moves our hero every INTEVAL seconds along the top most line of Z
if integer(this) == 1 then
call TimerStart(NewTimer(), INTERVAL, true, function thistype.onPeriod)
endif
//Cleanup
set u = null
endmethod
private static method onInit takes nothing returns nothing
set tempGroup = CreateGroup()
call RegisterSpellEffectEvent(ABIL_CODE, function thistype.onCast)
endmethod
endstruct
endlibrary
[/code]