scope AmumuQ initializer Init
globals
private constant real SPEED = 60 // Dummy and caster speed
private constant real BASIC_DAMAGE = 30 // Standard damage, how it's work? Watch to GetDamage function
private constant real DAMAGE_PER_LVL = 50 // Damage pre lvl
private constant real DISTANCE = 800 // Max distance
private constant real RANGE = 100 // Unit pick radius
private constant real MAGIC_NUMBER = 57.29 // Прост))00
private constant real PERIOD = .04 // Timeout timer
private constant string LIGHTNING_MODEL = "DRAL" // Lightning type
private constant integer ABILITY_ID = 'A000' // Spell ID
private constant integer DUMMY_CASTER_ID = 'h002' // Dummy caster
private constant integer STUN_ID = 'A005' // Stun spell id
private constant integer DUMMY_HEAD_ID = 'h001' // Head chain dummy ID
private constant boolean STUN = true // boolean for end spell, if stun = true then target is stunned
private constant boolean PRELOAD = true // give preload for stun ability?
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
/**/
private group GROUP = CreateGroup()
endglobals
//Target check
private function Q_Boolean takes unit u,unit e returns boolean
return /*
*/ IsUnitEnemy(e,GetOwningPlayer(u)) and /* // target enemy? true
*/ not IsUnitType(e,UNIT_TYPE_DEAD) and /* //Alive target?
*/ GetUnitTypeId(e) != 0 and /* // Alive target?
*/ not IsUnitType(e, UNIT_TYPE_STRUCTURE) and /* // target don't structure
*/ not IsUnitType(e, UNIT_TYPE_MECHANICAL) and /* // target don't mechanical
*/ not IsUnitType(e, UNIT_TYPE_MAGIC_IMMUNE) // target don't magic immune
endfunction
//Damage easy function
private function GetDamage takes unit u returns real
return BASIC_DAMAGE + (DAMAGE_PER_LVL * GetUnitAbilityLevel(u,ABILITY_ID))
endfunction
//This function checks the distance
function DistanceBetweenCoords takes real x1, real y1, real x2, real y2 returns real
return SquareRoot((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2))
endfunction
//Don't touch struct//////
/* */ private struct Q //
/* */ unit caster //
/* */ unit target //
/* */ unit dummy //
/* */ real damage //
/* */ real x //
/* */ real y //
/* */ real dis //
/* */ lightning l //
/* */endstruct //
//////////////////////////
private function SecondLoop takes nothing returns nothing
local timer t = GetExpiredTimer()
local Q data = GetTimerData(t)
local real x = GetUnitX(data.caster)
local real y = GetUnitY(data.caster)
local real X = x - SPEED * Cos(Atan2(GetUnitY(data.caster) - GetUnitY(data.target),GetUnitX(data.caster) - GetUnitX(data.target)))
local real Y = y - SPEED * Sin(Atan2(GetUnitY(data.caster) - GetUnitY(data.target),GetUnitX(data.caster) - GetUnitX(data.target)))
if DistanceBetweenCoords(x,y,GetUnitX(data.target),GetUnitY(data.target)) < 100 then
call RemoveUnit(data.dummy)
call DestroyLightning(data.l)
call data.destroy()
call ReleaseTimer(t)
set data.caster = null
set data.target = null
set data.dummy = null
set data.l = null
else
call SetUnitX(data.caster,X)
call SetUnitY(data.caster,Y)
call MoveLightning(data.l,true,x,y,GetUnitX(data.dummy),GetUnitY(data.dummy))
endif
set t = null
endfunction
private function FirstLoop takes nothing returns nothing
local timer t = GetExpiredTimer()
local Q data = GetTimerData(t)
local real x = GetUnitX(data.dummy)
local real y = GetUnitY(data.dummy)
local real X = x + SPEED * Cos(Atan2(data.y - GetUnitY(data.caster),data.x - GetUnitX(data.caster)))
local real Y = y + SPEED * Sin(Atan2(data.y - GetUnitY(data.caster),data.x - GetUnitX(data.caster)))
local unit e
if data.dis >= DISTANCE then
call RemoveUnit(data.dummy)
call DestroyLightning(data.l)
call data.destroy()
call ReleaseTimer(t)
set data.caster = null
set data.target = null
set data.dummy = null
set data.l = null
else
call SetUnitX(data.dummy,X)
call SetUnitY(data.dummy,Y)
call MoveLightning(data.l,true,GetUnitX(data.caster),GetUnitY(data.caster),x,y)
call GroupEnumUnitsInRange(GROUP,X,Y,RANGE, null)
loop
set e = FirstOfGroup(GROUP)
exitwhen(e == null)
call GroupRemoveUnit(GROUP,e)
if Q_Boolean(data.caster,e) then
call UnitDamageTarget(data.caster,e,data.damage,false,false,ATTACK_TYPE,DAMAGE_TYPE,null)
if STUN then
set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(data.caster),DUMMY_CASTER_ID,x,y,GetUnitFacing(data.target))
call UnitAddAbility(bj_lastCreatedUnit,STUN_ID)
call IssueTargetOrder(bj_lastCreatedUnit,"thunderbolt",e)
endif
call PauseTimer(t)
call TimerStart(t,.04,true,function SecondLoop)
set data.target = e
endif
endloop
endif
call GroupClear(GROUP)
set data.dis = data.dis + SPEED
set t = null
set e = null
endfunction
private function QAct takes nothing returns boolean
local Q data
if GetSpellAbilityId() == ABILITY_ID then
set data = Q.create()
set data.caster = GetTriggerUnit()
set data.dummy = CreateUnit(GetTriggerPlayer(),DUMMY_HEAD_ID,GetUnitX(data.caster),GetUnitY(data.caster),Atan2(GetSpellTargetY() - GetUnitY(data.caster),GetSpellTargetX() - GetUnitX(data.caster)) * MAGIC_NUMBER)
set data.damage = GetDamage(data.caster)
set data.l = AddLightning(LIGHTNING_MODEL,true,GetUnitX(data.caster),GetUnitY(data.caster),GetUnitX(data.dummy),GetUnitY(data.dummy))
set data.dis = 0.
set data.x = GetSpellTargetX()
set data.y = GetSpellTargetY()
call TimerStart(NewTimerEx(data),PERIOD,true,function FirstLoop)
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger trg = CreateTrigger()
static if PRELOAD then
set bj_lastCreatedUnit = CreateUnit(Player(0),DUMMY_CASTER_ID,0,0,0)
call UnitAddAbility(bj_lastCreatedUnit,STUN_ID)
endif
call TriggerRegisterAnyUnitEventBJ(trg,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trg,Condition(function QAct))
set trg = null
endfunction
endscope