//**********************************************************************************************
//**********************************************************************************************
//**********************************************************************************************
//**************** SPELL WRITTEN BY ITACHI009 *********************************************
//*************************** NN CREDITS BUT PLS DONT DELETE THE HEADER *******************
//******************** SPELL IS MUI, LEAKLESS AND LAGLESS *********************************
//**********************************************************************************************
//**********************************************************************************************
//**********************************************************************************************
//**********************************************************************************************
// you can change the CONSTANTS ONLY here in order to change the spell
// note: a constant is a line with the keyword "constant" in front of it :P
// the reason why i didnt made a scope is that it is unneeded :O, the names are clearly !
// and the names will never collide with other spells...
globals
// SETUP
constant integer ARCANE_EXPLOSION_ABILITY_ID = 'A003'
constant real ARCANE_EXPLOSION_COLLISION_SIZE = 80
constant real ARCANE_EXPLOSION_DISTANCE = 600
constant integer ARCANE_EXPLOSION_MISSILE_AMOUNT = 40
constant string ARCANE_EXPLOSION_MISSILE_ART = "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl"
constant integer ARCANE_EXPLOSION_MISSILE_ID = 'h001'
constant real ARCANE_EXPLOSION_MISSILE_SPEED = 400
constant real ARCANE_EXPLOSION_TIMEOUT = 0.02
// ENDSETUP
player ARCANE_EXPLOSION_ENUM_PLAYER
boolexpr ARCANE_EXPLOSION_FILTER
group ARCANE_EXPLOSION_GROUP
group ARCANE_EXPLOSION_GROUP2
hashtable ARCANE_EXPLOSION_TABLE
endglobals
constant function Arcane_Explosion_Conditions takes nothing returns boolean
return GetSpellAbilityId( ) == ARCANE_EXPLOSION_ABILITY_ID
endfunction
function Arcane_Explosion_Targets_Allowed takes nothing returns boolean
local unit filterUnit = GetFilterUnit( )
if GetUnitState( filterUnit, UNIT_STATE_LIFE ) > 0.405 and IsUnitEnemy( filterUnit, ARCANE_EXPLOSION_ENUM_PLAYER ) and not IsUnitType( filterUnit, UNIT_TYPE_FLYING ) then
set filterUnit = null
return true
endif
set filterUnit = null
return false
endfunction
function Arcane_Explosion_Second_Loop takes nothing returns nothing
local timer t = GetExpiredTimer( )
local integer parentKey = GetHandleId( t )
local real x = LoadReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "x" ) )
local real y = LoadReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "y" ) )
local real distance = LoadReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "distance" ) ) - ARCANE_EXPLOSION_MISSILE_SPEED * ARCANE_EXPLOSION_TIMEOUT
local unit array missile
local unit target
local real tx
local real ty
local real angle
set bj_forLoopAIndex = 0
loop
set missile[bj_forLoopAIndex] = LoadUnitHandle( ARCANE_EXPLOSION_TABLE, parentKey, bj_forLoopAIndex )
call SetUnitX( missile[bj_forLoopAIndex], x + distance * Cos( ( bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT ) * bj_PI / 180 ) )
call SetUnitY( missile[bj_forLoopAIndex], y + distance * Sin( ( bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT ) * bj_PI / 180 ) )
set missile[bj_forLoopAIndex] = null
set bj_forLoopAIndex = bj_forLoopAIndex + 1
exitwhen bj_forLoopAIndex >= ARCANE_EXPLOSION_MISSILE_AMOUNT
endloop
set ARCANE_EXPLOSION_ENUM_PLAYER = LoadPlayerHandle( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "id" ) )
call GroupEnumUnitsInRange( ARCANE_EXPLOSION_GROUP, x, y, distance + ARCANE_EXPLOSION_COLLISION_SIZE / 2, ARCANE_EXPLOSION_FILTER )
call GroupEnumUnitsInRange( ARCANE_EXPLOSION_GROUP2, x, y, distance - ARCANE_EXPLOSION_COLLISION_SIZE / 2, ARCANE_EXPLOSION_FILTER )
set bj_groupRemoveGroupDest = ARCANE_EXPLOSION_GROUP
call ForGroup( ARCANE_EXPLOSION_GROUP2, function GroupRemoveGroupEnum )
loop
set target = FirstOfGroup( ARCANE_EXPLOSION_GROUP )
exitwhen target == null
set tx = GetUnitX( target )
set ty = GetUnitY( target )
set angle = Atan2( ty - y, tx - x )
call SetUnitX( target, x + distance * Cos( angle ) )
call SetUnitY( target, y + distance * Sin( angle ) )
call GroupRemoveUnit( ARCANE_EXPLOSION_GROUP, target )
endloop
if distance <= 100 then
call PauseTimer( t )
call DestroyTimer( t )
call FlushChildHashtable( ARCANE_EXPLOSION_TABLE, parentKey )
else
call SaveReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "distance" ), distance )
endif
set t = null
set target = null
endfunction
function Arcane_Explosion_Loop takes nothing returns nothing
local timer t = GetExpiredTimer( )
local integer parentKey = GetHandleId( t )
local real x = LoadReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "x" ) )
local real y = LoadReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "y" ) )
local real distance = LoadReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "distance" ) ) + ARCANE_EXPLOSION_MISSILE_SPEED * ARCANE_EXPLOSION_TIMEOUT
local unit array missile
set bj_forLoopAIndex = 0
loop
set missile[bj_forLoopAIndex] = LoadUnitHandle( ARCANE_EXPLOSION_TABLE, parentKey, bj_forLoopAIndex )
call SetUnitX( missile[bj_forLoopAIndex], x + distance * Cos( ( bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT ) * bj_PI / 180 ) )
call SetUnitY( missile[bj_forLoopAIndex], y + distance * Sin( ( bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT ) * bj_PI / 180 ) )
set missile[bj_forLoopAIndex] = null
set bj_forLoopAIndex = bj_forLoopAIndex + 1
exitwhen bj_forLoopAIndex >= ARCANE_EXPLOSION_MISSILE_AMOUNT
endloop
if distance >= ARCANE_EXPLOSION_DISTANCE + 100 then
call PauseTimer( t )
call TimerStart( t, ARCANE_EXPLOSION_TIMEOUT, true, function Arcane_Explosion_Second_Loop )
else
call SaveReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "distance" ), distance )
endif
set t = null
endfunction
function Arcane_Explosion_Actions takes nothing returns nothing
local timer t = CreateTimer( )
local integer parentKey = GetHandleId( t )
local unit caster = GetTriggerUnit( )
local player id = GetOwningPlayer( caster )
local real x = GetUnitX( caster )
local real y = GetUnitY( caster )
local unit array missile
set bj_forLoopAIndex = 0
loop
set missile[bj_forLoopAIndex] = CreateUnit( id, ARCANE_EXPLOSION_MISSILE_ID, x + 100 * Cos( bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT ), y + 100 * Sin( bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT ), bj_forLoopAIndex * 360 / ARCANE_EXPLOSION_MISSILE_AMOUNT )
call AddSpecialEffectTarget( ARCANE_EXPLOSION_MISSILE_ART, missile[bj_forLoopAIndex], "origin" )
call SaveUnitHandle( ARCANE_EXPLOSION_TABLE, parentKey, bj_forLoopAIndex, missile[bj_forLoopAIndex] )
call UnitApplyTimedLife( missile[bj_forLoopAIndex], 'BTLF', ARCANE_EXPLOSION_DISTANCE / ARCANE_EXPLOSION_MISSILE_SPEED * 2 )
set missile[bj_forLoopAIndex] = null
set bj_forLoopAIndex = bj_forLoopAIndex + 1
exitwhen bj_forLoopAIndex >= ARCANE_EXPLOSION_MISSILE_AMOUNT
endloop
call SavePlayerHandle( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "id" ), id )
call SaveReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "x" ), x )
call SaveReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "y" ), y )
call SaveReal( ARCANE_EXPLOSION_TABLE, parentKey, StringHash( "distance" ), 100 )
call TimerStart( t, ARCANE_EXPLOSION_TIMEOUT, true, function Arcane_Explosion_Loop )
set t = null
set caster = null
endfunction
//===========================================================================
function InitTrig_Arcane_Explosion takes nothing returns nothing
local trigger trg = CreateTrigger( )
set bj_forLoopAIndex = 0
loop
call TriggerRegisterPlayerUnitEvent( trg, Player( bj_forLoopAIndex ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )
set bj_forLoopAIndex = bj_forLoopAIndex + 1
exitwhen bj_forLoopAIndex == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition( trg, Condition( function Arcane_Explosion_Conditions ) )
call TriggerAddAction( trg, function Arcane_Explosion_Actions )
set ARCANE_EXPLOSION_FILTER = Condition( function Arcane_Explosion_Targets_Allowed )
set ARCANE_EXPLOSION_GROUP = CreateGroup( )
set ARCANE_EXPLOSION_GROUP2 = CreateGroup( )
set ARCANE_EXPLOSION_TABLE = InitHashtable( )
call Preload( ARCANE_EXPLOSION_MISSILE_ART )
call PreloadStart( )
set trg = null
endfunction