scope AquaticBlastLightning initializer Init
// Aquatic Blast by The_Witcher
//
// well not much to say look through/edit the setup part so they fit your wishes
//
// This lightning version has more eye candy but a coding which can cause lagg
// I think you can always use the Lightning version cause there will never be that many instances that it laggs but who knows^^
//
// The SETUP part
globals
// The rawcode of your ability
private constant integer AbiID = 'A001'
// The effect created at the target loc
private constant string GroundSFX = "Abilities\\Spells\\Human\\Brilliance\\Brilliance.mdl"
// The seconde effect created at the target loc
private constant string MainSFX = "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl"
// The effect created when the whole thing explodes
private constant string ExplodeSFX = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
// The effect shown on damaged units
private constant string DamageSFX = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl"
// The attachment point where the DamageSFX appears
private constant string DamagePoint = "chest"
// The lightning effect appearing on each pulled unit
private constant string Lightning = "DRAM"
// The interval (0.01 is smoothest but can lagg in huge maps)
private constant real interval = 0.01
// The boolean whether the spell affects only enemies or all units
private constant boolean EnemyOnly = true
endglobals
private function GetDamage takes integer level returns real
return 120.00 + 50 * (I2R(level) - 1) //120 on level 1, 170 on level 2, 220 on level 3,...
endfunction
private function GetMaxTime takes integer level returns real
return 3 + 2 * I2R(level) //5 on level 1, 7 on level 2, 9 on level 3,...
endfunction
private function GetRange takes integer level returns real
return 200 + 100 * I2R(level) //300 on level 1, 400 level 2, 500 level 3,...
endfunction
private function GetPullSpeed takes integer level returns real
return 2 + 0.5 * I2R(level) //2 on level 1, 2.5 level 2, 3 level 3,...
endfunction
// END OF SETUP PART
private struct data
real x
real y
real t = 0
real mt
real dmg
real r
real d
player pl
integer level
effect sfx1
effect sfx2
integer temp = 0
lightning array l[30]
unit array u[30]
integer a = 0
endstruct
globals
private timer tim = CreateTimer()
private data array DATAS
private integer total = 0
private boolexpr BoolExpr
private group g = CreateGroup()
private player Temp
endglobals
private function EnemyFilter takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), Temp)
endfunction
private function True takes nothing returns boolean
return true
endfunction
private function AngleBetweenCoords takes real x, real y, real xx, real yy returns real
return bj_RADTODEG * Atan2(yy - y, xx - x)
endfunction
private function DistanceBetweenCoords takes real x , real y , real xx , real yy returns real
return SquareRoot((x-xx)*(x-xx)+(y-yy)*(y-yy))+0.5
endfunction
private function FilterDeadUnits takes nothing returns nothing
if IsUnitType(GetEnumUnit(), UNIT_TYPE_DEAD) or GetUnitTypeId(GetEnumUnit()) == 0 then
call GroupRemoveUnit(g,GetEnumUnit())
endif
endfunction
private function execute takes nothing returns nothing
local integer i = 0
local integer ii = 0
local data dat
local unit b
local real x
local real y
local real r
loop
exitwhen i >= total
set dat = DATAS[i]
set Temp = dat.pl
set dat.t = dat.t + interval
call GroupEnumUnitsInRange(g, dat.x, dat.y, dat.r, BoolExpr)
call ForGroup(g, function FilterDeadUnits)
loop
exitwhen ii >= dat.a
if IsUnitInGroup(dat.u[ii],g) then
call MoveLightning(dat.l[ii], true,dat.x,dat.y,GetUnitX(dat.u[ii]),GetUnitY(dat.u[ii]))
call GroupRemoveUnit(g,dat.u[ii])
else
call GroupRemoveUnit(g,dat.u[ii])
set dat.a = dat.a - 1
set dat.u[ii] = dat.u[dat.a]
call DestroyLightning(dat.l[ii])
set dat.l[ii] = dat.l[dat.a]
set dat.l[ii] = null
endif
set ii = ii + 1
endloop
loop
set b = FirstOfGroup(g)
exitwhen b == null
set dat.u[dat.a] = b
set dat.l[dat.a] = AddLightningEx( Lightning,true, dat.x,dat.y,50,GetUnitX(b),GetUnitY(b),50)
set dat.a = dat.a + 1
call GroupRemoveUnit(g,b)
endloop
set ii = 0
loop
exitwhen ii >= dat.a
set b = dat.u[ii]
set r = AngleBetweenCoords(GetUnitX(b), GetUnitY(b), dat.x, dat.y) * bj_DEGTORAD
set x = GetUnitX(b) + dat.d * Cos(r)
set y = GetUnitY(b) + dat.d * Sin(r)
call SetUnitX(b,x)
call SetUnitY(b,y)
if DistanceBetweenCoords(x,y,dat.x,dat.y) < dat.d+1 then
call GroupClear(g)
call GroupEnumUnitsInRange(g, dat.x, dat.y, dat.r, BoolExpr)
loop
set b = FirstOfGroup(g)
exitwhen b == null
call SetWidgetLife(b, GetWidgetLife(b) - dat.dmg)
call DestroyEffect(AddSpecialEffectTarget(DamageSFX,b,DamagePoint))
call GroupRemoveUnit(g,b)
endloop
set dat.t = dat.mt+1
endif
set ii = ii + 1
endloop
if dat.t > dat.mt then
call DestroyEffect(AddSpecialEffect(ExplodeSFX,dat.x,dat.y))
call DestroyEffect(dat.sfx1)
call DestroyEffect(dat.sfx2)
set ii = 0
loop
exitwhen ii >= dat.a
call DestroyLightning(dat.l[ii])
set ii = ii + 1
endloop
set DATAS[i] = DATAS[total-1]
set total = total - 1
call dat.destroy()
endif
set i = i + 1
endloop
if total == 0 then
call PauseTimer(tim)
endif
set b = null
endfunction
private function cast takes nothing returns nothing
local data dat = data.create()
local unit u = GetTriggerUnit()
local unit b
set dat.x = GetSpellTargetX()
set dat.y = GetSpellTargetY()
set dat.sfx1 = AddSpecialEffect(MainSFX,dat.x,dat.y)
set dat.sfx2 = AddSpecialEffect(GroundSFX,dat.x,dat.y)
set dat.level = GetUnitAbilityLevel(u,AbiID)
set dat.mt = GetMaxTime(dat.level)
set dat.r = GetRange(dat.level)
set dat.dmg = GetDamage(dat.level)
set dat.d = GetPullSpeed(dat.level)
set dat.pl = GetOwningPlayer(u)
set DATAS[total] = dat
set total = total + 1
if total == 1 then
call TimerStart(tim, interval, true, function execute)
endif
call GroupEnumUnitsInRange(g, dat.x, dat.y, dat.r, BoolExpr)
loop
set b = FirstOfGroup(g)
exitwhen b == null
call IssueTargetOrder(b,"attack",u)
call GroupRemoveUnit(g,b)
endloop
set u = null
set b = null
endfunction
private function check takes nothing returns boolean
return GetSpellAbilityId() == AbiID
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerAddAction(t, function cast)
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition(t,Condition(function check))
if EnemyOnly then
set BoolExpr = Condition(function EnemyFilter)
else
set BoolExpr = Filter(function True)
endif
endfunction
endscope