Here is the JASS code
Spoiler:
Code: Select all
scope ShadowBlast
globals
constant integer SpellAbilityId='A000'
constant integer SpellDummyId='A001'
constant integer DummyUnitId='h000'
constant integer DummyCasterId='h002'
constant real BlastMoveSpeed=24
constant real BlastDistance=1200
constant real TimerInterval=0.03
constant real SpellAOE=225
constant string SpecialEffectString="Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl"
endglobals
private struct Data
unit Caster
unit Dummy
real angle
group g2
player p
integer level
endstruct
private function PickedUnitConditions takes nothing returns boolean
local timer t=GetExpiredTimer()
local Data d=Data(GetAttachedInt(t,"d"))
local boolean b1 = IsUnitAliveBJ(GetFilterUnit()) == true
local boolean b2 = IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(d.Caster)) == true
local boolean b3 = IsUnitInGroup(GetFilterUnit(), d.g2) == false
local boolean b4 = IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
local boolean b5 = IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false
return b1 and b2 and b3 and b4 and b5
endfunction
private function ShadowBlastMove takes nothing returns nothing
local timer t=GetExpiredTimer()
local Data d=Data(GetAttachedInt(t,"d"))
local group g
local unit pg
local real DummyX=GetUnitX(d.Dummy)
local real DummyY=GetUnitY(d.Dummy)
call CS_MoveUnitLoc(d.Dummy, PolarProjectionBJ(Location(DummyX,DummyY), BlastMoveSpeed, d.angle))
set g=GetUnitsInRangeOfLocMatching(SpellAOE,Location(DummyX,DummyY),Condition(function PickedUnitConditions))
loop
set pg = FirstOfGroup(g)
exitwhen pg == null
call GroupAddUnit(d.g2,pg)
call CreateNUnitsAtLoc( 1, DummyCasterId, d.p, GetUnitLoc(pg), bj_UNIT_FACING )
call UnitApplyTimedLifeBJ( 2.00, 'BTLF', GetLastCreatedUnit() )
call UnitAddAbilityBJ( SpellDummyId, GetLastCreatedUnit() )
call SetUnitAbilityLevelSwapped( SpellDummyId, GetLastCreatedUnit(), d.level )
call IssueTargetOrderBJ( GetLastCreatedUnit(), "shadowstrike", pg )
call AddSpecialEffectTargetUnitBJ( "chest", pg, SpecialEffectString )
call DestroyEffectBJ( GetLastCreatedEffectBJ() )
call GroupRemoveUnit(g,pg)
endloop
call DestroyGroup(g)
set pg=null
set t=null
endfunction
private function ShadowBlast_Actions takes nothing returns nothing
local unit Caster=GetTriggerUnit()
local player p=GetOwningPlayer(Caster)
local real x=GetUnitX(Caster)
local real y=GetUnitY(Caster)
local real angle=AngleBetweenPoints(Location(x,y),GetSpellTargetLoc())
local location CastLoc=PolarProjectionBJ(Location(x,y),5,angle)
local unit Dummy=CreateUnitAtLoc(p,DummyUnitId,CastLoc,angle)
local real x2=GetUnitX(Dummy)
local real y2=GetUnitY(Dummy)
local timer t=CreateTimer()
local Data d=Data.create()
call RemoveLocation(CastLoc)
set d.Caster=Caster
set d.Dummy=Dummy
set d.angle=angle
set d.p=p
set d.g2=CreateGroup()
set d.level=GetUnitAbilityLevelSwapped(SpellAbilityId, Caster)
call AttachInt(t,"d",d)
call TimerStart(t,TimerInterval,true,function ShadowBlastMove)
loop
exitwhen DistanceBetweenPoints(Location(x,y),Location(x2,y2))>= BlastDistance
call TriggerSleepAction(0)
set x2=GetUnitX(Dummy)
set y2=GetUnitY(Dummy)
endloop
call UnitApplyTimedLifeBJ( 0.15, 'BTLF', Dummy)
call CleanAttachedVars(t)
call DestroyTimer(t)
call Data.destroy(d)
set Caster=null
set Dummy=null
set p=null
endfunction
function ShadowBlast_Conditions takes nothing returns boolean
return GetSpellAbilityId()==SpellAbilityId
endfunction
function InitTrig_ShadowBlast takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition(t, Condition(function ShadowBlast_Conditions))
call TriggerAddAction(t, function ShadowBlast_Actions)
endfunction
endscope