scope FieryRage initializer init
globals
//The Spell ID. Click ctrl+d in object editor to check if your's is the right.
private constant integer SpellID = 'A000'
//The ID of the dummy unit, which has to be imported.
private constant integer DummyID = 'h000'
//Just neccesary, if you modified existing skills.
private constant integer CrowFormID = 'Amrf'
//The SFX attached to the first dummies, which are flying in a hilf circle from the caster to the target.
private constant string Dummy1attach1 = "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl"
//See above
private constant string Dummy1attach2 = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
//The SFX attached to the second dummies, which are flying at changing heights, away from the detonation center.
private constant string Dummy2attach1 = "Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl"
//See above
private constant string Dummy2attach2 = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
//The SFX attached to the third dummies, which are generated out of the second ones.
private constant string Dummy3attach = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
//The SFX shown, when the first dummies arrive.
private constant string SFX1 = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
//The SFX shown, when the second dummies arrive.
private constant string SFX2 = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
//See above
private constant string SFX3 = "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl"
//The SFX which is shown on every unit (with a 10% chance) every TimerInt, when they are near a projectile.
private constant string SpamSFX = "Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl"
//The size of the first SFX, whereas 1. would be the normal size.
private constant real SFX1size = 1.5
//Quite self-explanatory, isn't it?
private constant real TimerInt = .03
//Damage Setup
private constant boolean Attack = false
//Damage Setup
private constant boolean Ranged = false
//Damage Setup
private constant attacktype AttackType = ATTACK_TYPE_NORMAL
//Damage Setup
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL
//Damage Setup
private constant weapontype WeaponType = WEAPON_TYPE_WHOKNOWS
//The steps, the first dummies take to reach their target, so less steps mean more speed.
private constant integer Steps1 = 40
//The steps, the second dummies take to reach their target, so less steps mean more speed.
private constant integer Steps2 = 20
//The steps, the third dummies take to reach their target, so less steps mean more speed.
private constant integer Steps3 = 16
endglobals
//The number of the first dummies. This should be an uneven number, so you have one missile flying in the middle.
//Else it will look awkward.
private function Dummys1 takes integer lev returns integer
return 5
endfunction
//The number of the second dummies.
private function Dummys2 takes integer lev returns integer
return 10
endfunction
//The number of the first dummies. It should be divideable by Dummys2, since every Dummy3 has its origin in a Dummy2.
private function Dummys3 takes integer lev returns integer
return Dummys2(0)*3
endfunction
//The damage done, when the first dummies reach their target.
private function Damage1 takes real dist, integer lev returns real
return lev*100.
endfunction
//The damage done, when the second dummies reach their target.
private function Damage2 takes real dist, integer lev returns real
return lev*25.
endfunction
//The damage done, when the unit is near a projectile.
private function DamagePerSec takes real dist, integer lev returns real
return lev*10.*TimerInt
endfunction
//The Aoe of Damage1.
private function AoE1 takes real dist, integer lev returns real
return dist/2.
endfunction
//The Aoe of Damage2.
private function AoE2 takes real dist, integer lev returns real
return dist/3.
endfunction
//The maximum flying height of the second dummies.
private function Dummy2maxHeight takes real dist, integer lev returns real
return AoE2(dist, 0)
endfunction
//The flying height of the third dummies. I chose a random number to imitate an explosion (scatters flying around).
private function Dummy3maxHeight takes real dist, integer lev returns real
return GetRandomReal(0., 300.)
endfunction
//The AoE of Damage3.
private function DamagePerSecAoe takes real dist, integer lev returns real
return 220.
endfunction
//Ignore the following 5 lines.
globals
private player p
private boolean heightcheck
private real heighttolerance = 20.
endglobals
//Setup continues
//The Filter for units.
private function UnitFilter takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), p) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) and GetWidgetLife(GetFilterUnit())>.405
endfunction
//End of Setup
globals
private boolexpr b
private group g = CreateGroup()
endglobals
private struct data
unit cast
unit array dum [50]
real dist
real curdist
real aoe1
real aoe2
real aoe3
real dmg1
real dmg2
real dmg3
real cx
real cy
real tx
real ty
real ang
real array dumang [50]
real formula
real maxheight2
real array maxheight3 [50]
integer step
integer dummys1
integer dummys2
integer dummys3
effect e0
effect array e1 [50]
effect array e2 [50]
static data array ar
static timer tim = CreateTimer()
static integer total = 0
static real dam
static unit cas
static real h
static method groupdamage takes nothing returns nothing
local unit u = GetEnumUnit()
if heightcheck then
if GetUnitFlyHeight(u)>data.h-heighttolerance and GetUnitFlyHeight(u)<data.h+heighttolerance then
call UnitDamageTarget(data.cas, u, data.dam, Attack, Ranged, AttackType, DamageType, WeaponType)
if GetRandomInt(1, 10) == 10 then
call DestroyEffect(AddSpecialEffect(SpamSFX, GetUnitX(u), GetUnitY(u)))
endif
call GroupRemoveUnit(g, u)
endif
else
call UnitDamageTarget(data.cas, u, data.dam, Attack, Ranged, AttackType, DamageType, WeaponType)
if GetRandomInt(1, 10) == 10 then
call DestroyEffect(AddSpecialEffect(SpamSFX, GetUnitX(u), GetUnitY(u)))
endif
call GroupRemoveUnit(g, u)
endif
set u = null
endmethod
static method periodic takes nothing returns nothing
local data d
local integer i = 0
local integer ii = 0
local integer iii = 0
local real x = .0
local real y = .0
local unit u
loop
exitwhen i >= d.total
set d = d.ar[i]
if d.step == 0 then
loop
exitwhen ii >= d.dummys1
set ii = ii + 1
set d.dum[ii] = CreateUnit(Player(15), DummyID, d.cx, d.cy, d.ang)
call PauseUnit(d.dum[ii], true)
set d.e1[ii] = AddSpecialEffectTarget(Dummy1attach1 , d.dum[ii], "chest")
set d.e2[ii] = AddSpecialEffectTarget(Dummy1attach2 , d.dum[ii], "origin")
call UnitAddAbility(d.dum[ii], CrowFormID)
endloop
set d.formula = bj_PI/2.
set ii = 0
set d.step = 1
endif
if d.step == 1 then
set d.formula = d.formula + bj_PI/(Steps1*2.)
loop
exitwhen ii >= d.dummys1
set ii = ii + 1
set d.curdist = d.curdist + d.dist/(Steps1*5.)
set x = d.cx+d.curdist*Cos(d.ang+Sin(d.formula)*(bj_PI/2.)*(I2R(ii-(d.dummys1/2+1))/2.))
set y = d.cy+d.curdist*Sin(d.ang+Sin(d.formula)*(bj_PI/2.)*(I2R(ii-(d.dummys1/2+1))/2.))
call SetUnitPosition(d.dum[ii], x, y)
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
set d.dam = d.dmg3
set d.cas = d.cast
set heightcheck = false
call ForGroup(g, function data.groupdamage)
if d.formula >= bj_PI then
set d.step = 2
call DestroyEffect(d.e1[ii])
call DestroyEffect(d.e2[ii])
call RemoveUnit(d.dum[ii])
endif
endloop
set ii = 0
endif
if d.step == 2 then
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, d.tx, d.ty, d.aoe1, b)
set d.dam = d.dmg1
set d.cas = d.cast
set heightcheck = false
call ForGroup(g, function data.groupdamage)
set u = CreateUnit(Player(15), DummyID, d.tx, d.ty, .0)
call SetUnitScale(u, SFX1size, SFX1size, SFX1size)
set d.e0 = AddSpecialEffectTarget(SFX1, u, "chest")
call UnitApplyTimedLife(u, 'BTLF', 1.)
call PauseUnit(u, true)
set u = null
loop
exitwhen ii >= d.dummys2
set ii = ii + 1
set d.dum[ii] = CreateUnit(Player(15), DummyID, d.tx, d.ty, d.ang)
call PauseUnit(d.dum[ii], true)
set d.e1[ii] = AddSpecialEffectTarget(Dummy2attach1 , d.dum[ii], "chest")
set d.e2[ii] = AddSpecialEffectTarget(Dummy2attach2 , d.dum[ii], "origin")
call UnitAddAbility(d.dum[ii], CrowFormID)
set d.dumang[ii] = bj_PI*2./ii
endloop
set ii = 0
set d.step = 3
set d.formula = 0.
set d.curdist = 0.
endif
if d.step == 3 then
set d.formula = d.formula + bj_PI/Steps2
set d.curdist = d.curdist + d.aoe2/Steps2
loop
exitwhen ii >= d.dummys2
set ii = ii + 1
set x = d.tx+d.curdist*Cos(bj_PI*2./d.dummys2*ii)
set y = d.ty+d.curdist*Sin(bj_PI*2./d.dummys2*ii)
call SetUnitPosition(d.dum[ii], x, y)
call SetUnitFlyHeight(d.dum[ii], d.maxheight2*Sin(d.formula), 0.)
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
set d.dam = d.dmg3
set d.cas = d.cast
set d.h = GetUnitFlyHeight(d.dum[ii])
set heightcheck = true
call ForGroup(g, function data.groupdamage)
endloop
set ii = 0
if d.formula >= bj_PI then
set d.step = 4
endif
endif
if d.step == 4 then
call DestroyEffect(d.e0)
loop
exitwhen ii == d.dummys2
set ii = ii + 1
set x = GetUnitX(d.dum[ii])
set y = GetUnitY(d.dum[ii])
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
set d.dam = d.dmg2
set d.cas = d.cast
set heightcheck = false
call ForGroup(g, function data.groupdamage)
call DestroyEffect(AddSpecialEffect(SFX2, x, y))
call DestroyEffect(AddSpecialEffect(SFX3, x, y))
call DestroyEffect(d.e1[ii])
call DestroyEffect(d.e2[ii])
call RemoveUnit(d.dum[ii])
endloop
set ii = 0
set d.step = 5
endif
if d.step == 5 then
loop
exitwhen ii == d.dummys2
set ii = ii + 1
set x = d.tx+d.aoe2*Cos(bj_PI*2./d.dummys2*ii)
set y = d.ty+d.aoe2*Sin(bj_PI*2./d.dummys2*ii)
loop
exitwhen iii == d.dummys3/d.dummys2
set iii=iii+1
set d.dum[iii] = CreateUnit(Player(15), DummyID, x, y, (ii*(bj_PI*2.)/3.))
call PauseUnit(d.dum[ii], true)
set d.e1[iii] = AddSpecialEffectTarget(Dummy3attach , d.dum[iii], "chest")
call UnitAddAbility(d.dum[iii], CrowFormID)
set d.maxheight3[iii] = Dummy3maxHeight(d.dist, GetUnitAbilityLevel(d.cast, SpellID))
endloop
endloop
set d.formula = 0.
set ii = 0
set iii = 0
set d.step = 6
endif
if d.step == 6 then
set d.formula = d.formula+1./Steps3
loop
exitwhen ii == d.dummys3
set ii = ii + 1
set x = GetUnitX(d.dum[ii])+d.aoe3/20.*Cos(ii*(bj_PI*2.)/3.)
set y = GetUnitY(d.dum[ii])+d.aoe3/20.*Sin(ii*(bj_PI*2.)/3.)
call SetUnitPosition(d.dum[ii], x, y)
call SetUnitFlyHeight(d.dum[ii], d.maxheight3*d.formula, 0.)
set p = GetOwningPlayer(d.cast)
set d.cas = d.cast
set d.dam = d.dmg3
set heightcheck = true
set d.h = GetUnitFlyHeight(d.dum[ii])
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
call ForGroup(g, function data.groupdamage)
endloop
set ii = 0
if d.formula >= 1. then
loop
exitwhen ii == d.dummys3
set ii = ii + 1
call DestroyEffect(d.e1[ii])
call RemoveUnit(d.dum[ii])
endloop
set ii = 0
set d.formula = 0
set d.curdist = 0
set d.total = d.total - 1
set d.ar[i] = d.ar[d.total]
call d.destroy()
set i = i - 1
endif
endif
set i = i + 1
endloop
if d.total == 0 then
call PauseTimer(d.tim)
endif
endmethod
static method actions takes nothing returns nothing
local data d = data.allocate()
local integer lev = GetUnitAbilityLevel(GetTriggerUnit(), SpellID)
set d.tx = GetSpellTargetX()
set d.ty = GetSpellTargetY()
set d.cast = GetTriggerUnit()
set d.cx = GetUnitX(d.cast)
set d.cy = GetUnitY(d.cast)
set d.ang = Atan2(d.ty-d.cy, d.tx-d.cx)
set d.dist = SquareRoot(Pow(d.tx-d.cx, 2.)+Pow(d.ty-d.cy,2.))
set d.aoe1 = AoE1(d.dist, lev)
set d.aoe2 = AoE2(d.dist, lev)
set d.aoe3 = DamagePerSecAoe(d.dist, lev)
set d.dmg1 = Damage1(d.dist, lev)
set d.dmg2 = Damage2(d.dist, lev)
set d.dmg3 = DamagePerSec(d.dist, lev)
set d.maxheight2 = Dummy2maxHeight(d.dist, lev)
set d.step = 0
set d.dummys1 = Dummys1(lev)
set d.dummys2 = Dummys2(lev)
set d.dummys3 = Dummys3(lev)
if d.total == 0 then
call TimerStart(d.tim, TimerInt, true, function data.periodic)
endif
set d.ar[d.total] = d
set d.total = d.total + 1
endmethod
endstruct
private function condition takes nothing returns boolean
return GetSpellAbilityId()==SpellID
endfunction
private function noleakfilter takes nothing returns boolean
return true
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local filterfunc ff = Filter(function noleakfilter)
loop
exitwhen i >= bj_MAX_PLAYER_SLOTS
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
set i = i + 1
endloop
set i = 0
call TriggerAddAction(t, function data.actions)
call TriggerAddCondition(t, Condition(function condition))
set b = Condition(function UnitFilter)
call DestroyFilter(ff)
set ff = null
endfunction
endscope