- Joined
- Jan 31, 2010
- Messages
- 3,552
Hey there!
I need help with changing these abilities for my project, the Legendary War. I have made tooltips as simplest as possible, and what I want as short and sharp I wanted them.
1. Inner Rage: Pushes away nearby enemies and deals damage to them.
What I want: It should pull enemies towards the caster, not push them outwards.
2. Deviousness: Each attack against enemy Heroes steals Agility, which is restored back in few seconds. Stacks with itself, but each strike has it's own timer (won't reset with each new hit).
What I want: It should use some sort of damage detection system, since I want it to have no cooldown. If I remove the wait functions in my triggers, the spell can be abused by canceling attacks, which I want to prevent.
3. Phase Cycle: Caster gains movement increase and full transparency. Additionally, upon cast and at the end of the duration, lunar blasts will damage EVERYTHING nearby.
What I want: I want to keep the movement gain, but I also want it to give unitwalking/zero collision while it lasts. I don't want transparency. I also want only one blast of energy, at the end of duration, which won't damage mechanical units, allies or self. Just enemies.
4. Punitive Surge: Caster moves forward targeted point, casting her shadows around herself that deal damage to enemies she encounters.
What I want: This spell has only one "problem", it uses pathing item, meaning that if you hit a building, cliff or doodad/destructible, you will stop. If you try to cast it while next to one of mentioned objects, the spell will go to waste without effects. I want to have no pathing in this spell, meaning that caster can travel through cliffs, buildings and doodads.
I need help with changing these abilities for my project, the Legendary War. I have made tooltips as simplest as possible, and what I want as short and sharp I wanted them.
1. Inner Rage: Pushes away nearby enemies and deals damage to them.
What I want: It should pull enemies towards the caster, not push them outwards.
2. Deviousness: Each attack against enemy Heroes steals Agility, which is restored back in few seconds. Stacks with itself, but each strike has it's own timer (won't reset with each new hit).
What I want: It should use some sort of damage detection system, since I want it to have no cooldown. If I remove the wait functions in my triggers, the spell can be abused by canceling attacks, which I want to prevent.
3. Phase Cycle: Caster gains movement increase and full transparency. Additionally, upon cast and at the end of the duration, lunar blasts will damage EVERYTHING nearby.
What I want: I want to keep the movement gain, but I also want it to give unitwalking/zero collision while it lasts. I don't want transparency. I also want only one blast of energy, at the end of duration, which won't damage mechanical units, allies or self. Just enemies.
4. Punitive Surge: Caster moves forward targeted point, casting her shadows around herself that deal damage to enemies she encounters.
What I want: This spell has only one "problem", it uses pathing item, meaning that if you hit a building, cliff or doodad/destructible, you will stop. If you try to cast it while next to one of mentioned objects, the spell will go to waste without effects. I want to have no pathing in this spell, meaning that caster can travel through cliffs, buildings and doodads.
-
Inner Rage
-
Events
- Unit - A unit Starts the effect of an ability
-
Conditions
- (Ability being cast) Equal to Inner Rage [FP]
-
Actions
- Set KB_Point[0] = (Position of (Triggering unit))
- Set KB_Group = (Units within 300.00 of KB_Point[0] matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) belongs to an ally of (Owner of (Triggering unit))) Equal to False) and ((((Matching unit) is A flying unit) Equal to False) and (((Matching
-
Unit Group - Pick every unit in KB_Group and do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- KB_Skip Equal to 0
-
Then - Actions
- Trigger - Turn on Knockback System <gen>
- Else - Actions
-
If - Conditions
- Set KB_Skip = (KB_Skip + 1)
- Set KB_Times = (KB_Times + 1)
- Set KB_Off[KB_Times] = True
- Set KB_Target[KB_Times] = (Picked unit)
- Set KB_Point[1] = (Position of (Picked unit))
- Set KB_Angle[KB_Times] = (Angle from KB_Point[1] to KB_Point[0])
- Set KB_Speed[KB_Times] = 20.00
- Set KB_Spam[KB_Times] = 5
- Set KB_Distance[KB_Times] = 300.00
- Custom script: call RemoveLocation(udg_KB_Point[1])
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
Loop - Actions
- Custom script: call RemoveLocation(udg_KB_Point[0])
- Custom script: call DestroyGroup(udg_KB_Group)
-
Events
-
Knockback System
-
Events
- Time - Every 0.02 seconds of game time
- Conditions
-
Actions
-
For each (Integer KB) from 1 to KB_Times, do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- KB_Off[KB] Equal to True
-
Then - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- KB_Distance[KB] Less than or equal to 0.00
-
Then - Actions
- Set KB_Off[KB] = False
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- KB Less than KB_Times
-
Then - Actions
- Set KB_Off[KB] = KB_Off[KB_Times]
- Set KB_Target[KB] = KB_Target[KB_Times]
- Set KB_Distance[KB] = KB_Distance[KB_Times]
- Set KB_Speed[KB] = KB_Speed[KB_Times]
- Set KB_Spam[KB] = KB_Spam[KB_Times]
- Set KB_Angle[KB] = KB_Angle[KB_Times]
- Else - Actions
-
If - Conditions
- Set KB = (KB - 1)
- Set KB_Skip = (KB_Skip - 1)
- Set KB_Times = (KB_Times - 1)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- KB_Times Equal to 0
-
Then - Actions
- Trigger - Turn off Knockback System <gen>
- Else - Actions
-
If - Conditions
-
Else - Actions
- Set KB_Point[2] = (Position of KB_Target[KB])
- Set KB_Point[3] = (KB_Point[2] offset by KB_Speed[KB] towards KB_Angle[KB] degrees)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Terrain pathing at KB_Point[3] of type Walkability is off) Equal to True
- ((Playable map area) contains KB_Point[3]) Not equal to True
-
Then - Actions
- Set KB_Distance[KB] = 0.00
-
Else - Actions
-
Destructible - Pick every destructible within 100.00 of KB_Point[3] and do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- ((Picked destructible) is alive) Equal to True
-
Then - Actions
- Set KB_Point[4] = (Position of (Picked destructible))
- Unit - Create 1 Casual Dummy for Neutral Passive at KB_Point[4] facing Default building facing degrees
- Unit - Add a 0.01 second Generic expiration timer to (Last created unit)
- Unit - Add Harvest (Ghouls Lumber) to (Last created unit)
- Unit - Order (Last created unit) to Harvest (Picked destructible)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Current order of (Last created unit)) Equal to (Order(harvest))
-
Then - Actions
- Destructible - Kill (Picked destructible)
- Else - Actions
-
If - Conditions
- Custom script: call RemoveLocation(udg_KB_Point[4])
- Else - Actions
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
Loop - Actions
- Custom script: call SetUnitX(udg_KB_Target[udg_KB], GetLocationX(udg_KB_Point[3]))
- Custom script: call SetUnitY(udg_KB_Target[udg_KB], GetLocationY(udg_KB_Point[3]))
-
Destructible - Pick every destructible within 100.00 of KB_Point[3] and do (Actions)
-
If - Conditions
- Set KB_Distance[KB] = (KB_Distance[KB] - KB_Speed[KB])
- Set KB_Spam[KB] = (KB_Spam[KB] + 1)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- KB_Spam[KB] Greater than or equal to 5
-
Then - Actions
- Set KB_Spam[KB] = 0
- Special Effect - Create a special effect at KB_Point[3] using Abilities\Spells\Human\FlakCannons\FlakTarget.mdl
- Special Effect - Destroy (Last created special effect)
- Else - Actions
-
If - Conditions
- Custom script: call RemoveLocation(udg_KB_Point[2])
- Custom script: call RemoveLocation(udg_KB_Point[3])
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
- Else - Actions
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
Loop - Actions
-
For each (Integer KB) from 1 to KB_Times, do (Actions)
-
Events
-
Deviousness
-
Events
- Unit - A unit Is attacked
-
Conditions
- (Level of Deviosness [EX] for (Attacking unit)) Greater than 0
-
Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Level of Deviosness [EX] for (Attacking unit)) Equal to 1
- ((Attacked unit) is A Hero) Equal to True
-
Then - Actions
- Hero - Modify Agility of (Attacking unit): Add 3
- Special Effect - Create a special effect attached to the head of (Attacking unit) using Abilities\Spells\Orc\Bloodlust\BloodlustTarget.mdl
- Special Effect - Destroy (Last created special effect)
- Hero - Modify Agility of (Attacked unit): Subtract 3
- Trigger - Turn off (This trigger)
- Wait 1.00 seconds
- Trigger - Turn on (This trigger)
- Wait 19.00 seconds
- Hero - Modify Agility of (Attacking unit): Subtract 3
- Hero - Modify Agility of (Attacked unit): Add 3
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Level of Deviosness [EX] for (Attacking unit)) Equal to 2
- ((Attacked unit) is A Hero) Equal to True
-
Then - Actions
- Hero - Modify Agility of (Attacking unit): Add 4
- Special Effect - Create a special effect attached to the head of (Attacking unit) using Abilities\Spells\Orc\Bloodlust\BloodlustTarget.mdl
- Special Effect - Destroy (Last created special effect)
- Hero - Modify Agility of (Attacked unit): Subtract 4
- Trigger - Turn off (This trigger)
- Wait 1.00 seconds
- Trigger - Turn on (This trigger)
- Wait 29.00 seconds
- Hero - Modify Agility of (Attacking unit): Subtract 4
- Hero - Modify Agility of (Attacked unit): Add 4
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Level of Deviosness [EX] for (Attacking unit)) Equal to 3
- ((Attacked unit) is A Hero) Equal to True
-
Then - Actions
- Hero - Modify Agility of (Attacking unit): Add 5
- Special Effect - Create a special effect attached to the head of (Attacking unit) using Abilities\Spells\Orc\Bloodlust\BloodlustTarget.mdl
- Special Effect - Destroy (Last created special effect)
- Hero - Modify Agility of (Attacked unit): Subtract 5
- Trigger - Turn off (This trigger)
- Wait 1.00 seconds
- Trigger - Turn on (This trigger)
- Wait 39.00 seconds
- Hero - Modify Agility of (Attacking unit): Subtract 5
- Hero - Modify Agility of (Attacked unit): Add 5
- Else - Actions
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
Events
JASS:
function RavynWaitPS takes real duration returns nothing
//Timer wait like thing
local timer t
local real timeRemaining
if (duration > 0) then
set t = CreateTimer()
call TimerStart(t, duration, false, null)
loop
set timeRemaining = TimerGetRemaining(t)
exitwhen (timeRemaining <= 0)
if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
call TriggerSleepAction(0.1 * timeRemaining)
else
call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
endif
endloop
call DestroyTimer(t)
endif
endfunction
function PSeffects takes real distance, location uloc returns nothing
//The eye candy, Creates the effect each effect is 30 degrees apart up to the 360 degree mark
//i.e. 360/30 = 18 Therefore 18 effects are created.
local unit u = GetTriggerUnit()
local real x = 0
local string effectstring = "Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl"
loop
set x = x + 60
call AddSpecialEffectLoc( effectstring, PolarProjectionBJ(uloc, distance, x))
exitwhen x >= 360
endloop
set x = 0
set u = null
set effectstring = ""
endfunction
function PSnova takes real aoesize returns nothing
//The damaging effect of the ability, Creates the effects by calling the effect trigger
//and damages units around the caster.
local integer x = 0
local integer abilityid = 'A03F'
local unit u = GetTriggerUnit()
local location uloc = GetUnitLoc(GetTriggerUnit())
local real damage = GetUnitAbilityLevel(u, abilityid) * 15
loop
set x = x + R2I(aoesize)/4
call UnitDamagePoint( u, 0, aoesize, GetLocationX(uloc), GetLocationY(uloc), damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
call PSeffects(x, uloc)
call RavynWaitPS(0.01)
exitwhen(x >= aoesize)
endloop
set x = 0
set u = null
set abilityid = 0
call RemoveLocation(uloc)
endfunction
function Trig_Phase_Shift_Actions takes nothing returns nothing
//The main function for Phase Shift, it determines whether or not the correct ability is case
//And moves through the main functions for Phase Shift. It creates the nova, the continues to
//double the units movement and make it invulnerable and quite transperant. It then sets
//the units visability back quickly at first then slower as A = A - (A/X) therefore as A gets
//smaller A decreses by smaller amounts. After that it creates another nova asswell it sets the
//unit back to its orignal visual state and removes the invulnerability
local integer x
local integer abilityid = 'A03F'
local real y
local real alpha
local unit u
local real aoesize = 256
if ( GetSpellAbilityId() == abilityid ) then
set u = GetTriggerUnit()
set alpha = 0
set x = 3
set y = GetUnitAbilityLevel(u, abilityid) * 1
call PSnova(aoesize)
call SetUnitVertexColor(u, 255, 255, 255, 5)
call SetUnitMoveSpeed(u, GetUnitMoveSpeed(u) * 1.5)
call RavynWaitPS(y)
set y = y / 20
loop
call RavynWaitPS(y)
set x = x - 1
set alpha = alpha - (alpha/x)
call SetUnitVertexColorBJ(u, 100, 100, 100, alpha )
exitwhen(x == 1)
endloop
call PSnova(aoesize)
call SetUnitMoveSpeed(u, GetUnitDefaultMoveSpeed(u))
call SetUnitVertexColor(u, 255, 255, 255, 255 )
set x = 0
set y = 0
set abilityid = 0
set alpha = 0
set u = null
set aoesize = 0
endif
endfunction
//===========================================================================
function InitTrig_Phase_Cycle takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddAction( t, function Trig_Phase_Shift_Actions )
set t = null
endfunction
JASS:
// * Punitive Surge v1.01 by Maker *
// * Spell idea by Apheraz Lucent *
// * The caster rushes to the targeted point *
// * executing a spinning attack damaging *
// * enemies. The caster leaves a quickly *
// * fading "tail" of shadows of himself. *
scope PunitiveSurge initializer Punitive_Surge
globals
// How fast the unit moves at the beginning
private constant real INITIAL_SPEED = 12.
// Speed multiplier between loops, how fast the unit accelerates
private constant real ACCELERATION = 1.08
// Maximum charge speed
private constant real MAX_SPEED = 30.
// Damage per ability level
private constant real DAMAGE = 75.
// Damage bonus per ability level, not applied at level 1
private constant real BONUS_DAMAGE = 75
// Update interval for moving loops. 1/loopTime = Frames per second
private constant real LOOP_TIME = 0.03125
// AoE of the spell
private constant real RADIUS = 150.
// Animation speed for the attack ( 1.00 = normal speed )
private constant real ANIMATION_SPEED = 0.75
// Raw code of the ability
private constant integer ABILITYCODE = 'A03G'
// The dummy's raw code
private constant integer DUMMYCODE = 'E005'
// The pathing item's raw code
private constant integer ITEMCODE = 'I01O'
// How transparent the dummies are at beginning, 255 means 100% visible, 177,5 = 50% visible
private constant integer DUMMY_INITIAL_FADE = 175
// How fast the dummies fade
private constant integer FADE_RATE = 10
// ^Play around with those values to get to desired^
// ^tail fade time and tail length^
// Vertex color values for dummy. Default caster color = 255, 255, 255
// 0 , 0 , 0 = completely black
private constant integer RED = 100
private constant integer GREEN = 100
private constant integer BLUE = 100
// The animation that the dummies play
private constant integer ANIMATION = 6
// Attack type of the ability
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
// Damage type of the attack
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
// Effect on targets hit
private constant string HIT_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodFootman.mdl"
// Effect on caster
private constant string CASTER_WEAPON_EFFECT = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
// Effect attachment points for caster
private constant string ATTACH_1 = "weapon"
private constant string ATTACH_2 = "right hand"
// Effect attachment point for targets
private constant string ATTACH_3 = "chest"
// How many different sound effects are used
private constant integer SOUNDS = 0
// How loud the sounds will be. 255 = 100% volume, 0 = 0% volume
private constant integer SOUND_VOLUME = 0
//** DONT CHANGE THE VARIABLES BELOW **//
private unit U
private real R
private player P
private group UG
private sound array sounds
private integer casters = 0
private integer dummies = 0
private timer casterTimer = CreateTimer()
private timer dummyTimer = CreateTimer()
private group casterGroup = CreateGroup()
private group dummyGroup = CreateGroup()
private item itemPathing
private hashtable rageHash = InitHashtable()
endglobals
// Retuns the damage done by the spell
private constant function getDamage takes integer i returns real
return DAMAGE + BONUS_DAMAGE * (i - 1)
endfunction
// Returns distance between two points
private function getDistance takes real x1 , real x2 , real y1 , real y2 returns real
local real dx = x2 - x1
local real dy = y2 - y1
return SquareRoot(dx * dx + dy * dy )
endfunction
// Returns an angle between two points
private function getAngle takes real x1 , real x2 , real y1 , real y2 returns real
return Atan2(y2 - y1 , x2 - x1 )
endfunction
// Playes a sound on unit
function playSoundOnUnit takes unit u , sound soundHandle returns nothing
call AttachSoundToUnit( soundHandle , u )
call SetSoundVolume( soundHandle , SOUND_VOLUME )
call StartSound( soundHandle )
endfunction
// Filters unwanted units from getting damaged
// Damages targets and applies sound and sfx
private function unitFilter takes nothing returns boolean
local unit v = GetFilterUnit()
local sound s = sounds[GetRandomInt(1 , SOUNDS)]
if not(IsUnitType( v , UNIT_TYPE_DEAD )) and IsUnitEnemy( v , P ) and not(IsUnitInGroup(v, UG )) and not (IsUnitType( v, UNIT_TYPE_STRUCTURE ) ) then
call UnitDamageTarget( U , v , R , false , false , ATTACK_TYPE , DAMAGE_TYPE , WEAPON_TYPE_WHOKNOWS )
call DestroyEffect(AddSpecialEffectTarget( HIT_EFFECT , v , "ATTACH_3" ) )
call GroupAddUnit( UG , v )
call playSoundOnUnit( v , s )
endif
set v = null
set s = null
return true
endfunction
// Fades out and removes dummies
private function dummyLoop takes nothing returns nothing
local unit u = GetEnumUnit()
local integer i1 = GetHandleId(u)
local integer i2 = LoadInteger(rageHash , i1 , StringHash("fade") )
if i2 > 0 then
set i2 = i2 - FADE_RATE
call SetUnitVertexColor(u , RED , GREEN , BLUE , i2 )
call SaveInteger(rageHash , i1 , StringHash("fade") , i2 )
else
set dummies = dummies - 1
call GroupRemoveUnit( dummyGroup , u )
call FlushChildHashtable(rageHash , i1)
call RemoveUnit(u)
if dummies == 0 then
call PauseTimer(dummyTimer)
endif
endif
set u = null
endfunction
private function dummyTimerExpire takes nothing returns nothing
call ForGroup( dummyGroup , function dummyLoop )
endfunction
// Moves caster and checks collision
private function casterLoop takes nothing returns nothing
local unit u = GetEnumUnit()
local unit v
local integer i1 = GetHandleId(u)
local integer i2
local boolean b = LoadBoolean(rageHash , i1 , StringHash("boolean") )
local group g = CreateGroup()
local real r1 = GetUnitX(u)
local real r2 = GetUnitY(u)
local real r3 = LoadReal(rageHash , i1 , StringHash("x") )
local real r4 = LoadReal(rageHash , i1 , StringHash("y") )
local real r5 = getDistance( r1 , r3 , r2 , r4 )
local real r6
local real r7
local real r8
// Checks that the caster isn't dead and that the caster isn't close to
// the cast target point yet
if not (IsUnitType( u , UNIT_TYPE_DEAD) ) and r5 > MAX_SPEED and b == true then
set r5 = LoadReal(rageHash , i1 , StringHash("speed") ) * ACCELERATION
set r6 = LoadReal(rageHash , i1 , StringHash("angle") )
// Limits max speed
if r5 > MAX_SPEED then
set r5 = MAX_SPEED
endif
call SaveReal(rageHash , i1 , StringHash("speed") , r5 )
// Pathability is done by moving an item to the point the caster
// is supposed to move to. If the item's coordinates after moving it
// do not match the move to point's coordinates, the point is unpathable.
// If the point is pathable, move the caster there.
// If not, stop the spell.
// Prevents the caster from passing strcutures, trees, cliffs, pathing
// blockers and going off the map.
set r7 = r1 + r5 * Cos(r6)
set r8 = r2 + r5 * Sin(r6)
call SetItemVisible( itemPathing , true )
call SetItemPosition( itemPathing , r7 , r8 )
set r5 = GetItemX(itemPathing)
set r6 = GetItemY(itemPathing)
call SetItemVisible( itemPathing , false )
if r7 == r5 and r8 == r6 then
call SetUnitX(u , r7)
call SetUnitY(u , r8)
// Set globals so they can be passed used in the filter function
set U = u
set R = getDamage(GetUnitAbilityLevel( u , ABILITYCODE ))
set P = GetOwningPlayer(u)
set UG = LoadGroupHandle(rageHash , i1 , StringHash("group") )
call GroupEnumUnitsInRange( g , r7 , r8 , RADIUS , function unitFilter )
// Create a fading "tail" dummy
set v = CreateUnit( Player(15) , DUMMYCODE , r1 , r2 , GetUnitFacing(u) )
set i2 = GetHandleId(v)
set dummies = dummies + 1
call GroupAddUnit( dummyGroup , v )
call SetUnitColor( v , GetPlayerColor( P ) )
call SetUnitTimeScale( v , ANIMATION_SPEED )
call SetUnitAnimationByIndex( v , ANIMATION )
call SetUnitVertexColor( v , RED , GREEN , BLUE , DUMMY_INITIAL_FADE )
call SaveInteger(rageHash , i2 , StringHash("fade") , DUMMY_INITIAL_FADE )
if dummies == 1 then
call TimerStart( dummyTimer , LOOP_TIME , true , function dummyTimerExpire )
endif
set v = null
else
call SaveBoolean(rageHash , i1 , StringHash("boolean") , false )
endif
else
set casters = casters - 1
call GroupRemoveUnit( casterGroup , u )
call DestroyGroup(LoadGroupHandle(rageHash, i1 , StringHash("group") ) )
call DestroyEffect(LoadEffectHandle(rageHash , i1 , StringHash("wEffect1") ) )
call DestroyEffect(LoadEffectHandle(rageHash , i1 , StringHash("wEffect2") ) )
call FlushChildHashtable(rageHash , i1)
if casters == 0 then
call PauseTimer(casterTimer)
endif
endif
call DestroyGroup(g)
set u = null
set g = null
endfunction
private function casterTimerExpire takes nothing returns nothing
call ForGroup( casterGroup , function casterLoop )
endfunction
// This runs when the caster begins casting the ability.
// Begins casting -event is chose over Starts the effect - event
// since there's casting delay betweeb those events (default = 0.5 seconds).
// Begins castin -event fires sooner. It does not bug even if the unit gets a stop
// order during the ast time.
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer i = GetHandleId(u)
local integer i2 = GetUnitAbilityLevel( u , ABILITYCODE )
local real x1 = GetUnitX(u)
local real y1 = GetUnitY(u)
local real x2 = GetSpellTargetX()
local real y2 = GetSpellTargetY()
local real r1 = getDamage(i2)
local real r2
local real r3
local real r4
// Checks that the target point is pathable.
// If not, use the nearest pathable point as the new
// target point.
call SetItemVisible( itemPathing , true )
call SetItemPosition( itemPathing , x2 , y2 )
set r3 = GetItemX(itemPathing)
set r4 = GetItemY(itemPathing)
if r3 == x2 and r4 == y2 then
set r2 = getAngle( x1 , x2 , y1 , y2 )
else
set r2 = getAngle( x1 , r3 , y1 , r4 )
set x2 = r3
set y2 = r4
endif
call SetUnitTimeScale( u , ANIMATION_SPEED )
call SetItemVisible( itemPathing , false )
call GroupAddUnit(casterGroup , u)
set casters = casters + 1
set UG = CreateGroup()
call SaveReal(rageHash , i , StringHash("x") , x2 )
call SaveReal(rageHash , i , StringHash("y") , y2 )
call SaveReal(rageHash , i , StringHash("angle") , r2 )
call SaveReal(rageHash , i , StringHash("damage") , r1 )
call SaveReal(rageHash , i , StringHash("speed") , INITIAL_SPEED )
call SaveGroupHandle(rageHash , i , StringHash("group") , UG )
call SaveBoolean(rageHash , i , StringHash("boolean") , true )
call SaveEffectHandle(rageHash , i , StringHash("wEffect1") , AddSpecialEffectTarget(CASTER_WEAPON_EFFECT , u , ATTACH_1 ) )
call SaveEffectHandle(rageHash , i , StringHash("wEffect2") , AddSpecialEffectTarget(CASTER_WEAPON_EFFECT , u , ATTACH_2 ) )
if casters == 1 then
call TimerStart( casterTimer , LOOP_TIME , true , function casterTimerExpire )
endif
set u = null
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABILITYCODE
endfunction
private function Punitive_Surge takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( t , Condition( function Conditions ) )
call TriggerAddAction( t , function Actions )
set itemPathing = CreateItem( ITEMCODE , 0 , 0 )
call SetItemVisible( itemPathing , false )
set t = null
endfunction
endscope