scope RockSlide initializer init
//#####################
//### CONFIGURABLES ###
//#####################
globals
//speed is MOVEMENT_PER_ITERATION / TIMEOUT, = 500 with example values 20 and 0.04
private constant real MOVEMENT_PER_ITERATION = 20
private constant real TIMEOUT = 0.04
private constant integer ABIL_CODE = 'A027'
private constant real DISTANCE = 800
private constant integer DUMMY_ID = 'h00K'
//area, which is damaged around the boulder
private constant real AREA = 100
endglobals
private function CalculateDamage takes unit caster returns real
return 5.0 * (30 * GetUnitAbilityLevel(caster, ABIL_CODE) + GetHeroStr(caster,true))
endfunction
private function DamageConditions takes unit caster, unit matching returns boolean
return IsPlayerEnemy(GetOwningPlayer(matching), GetOwningPlayer(caster)) /*
*/ and not IsUnitType(matching, UNIT_TYPE_STRUCTURE)
endfunction
//#########################
//### CONFIGURABLES END ###
//#########################
private struct Data
unit caster
unit dummy
real damage
real x
real y
real xd
real yd
integer executions
endstruct
globals
private Data array DataList
private integer Count = 0
private timer T = CreateTimer()
endglobals
private function True takes nothing returns boolean
return true
endfunction
private function Loop takes nothing returns nothing
local Data dat
local integer i = 0
local location p
local group g
local unit u
loop
exitwhen i >= Count
set dat = DataList[i]
set dat.x = dat.x + dat.xd
set dat.y = dat.y + dat.yd
call SetUnitX(dat.dummy, dat.x)
call SetUnitY(dat.dummy, dat.y)
call BJDebugMsg("Count = " + I2S(Count) + ", heroloc = (" + R2S(GetUnitX(dat.caster)) + ", " + R2S(GetUnitY(dat.caster)) + /*
*/ "), dummyloc = (" + R2S(dat.x) + ", " + R2S(dat.y) + ")")
set p = Location(dat.x, dat.y)
set g = GetUnitsInRangeOfLocMatching(AREA, p, Filter(function True))
loop
set u = FirstOfGroup(g)
exitwhen u == null
if DamageConditions(dat.caster, u) then
call UnitDamageTarget(dat.caster, u, dat.damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(g, u)
endloop
call RemoveLocation(p)
call DestroyGroup(g)
set dat.executions = dat.executions - 1
if dat.executions == 0 then
call KillUnit(dat.dummy)
call dat.destroy()
set Count = Count - 1
set DataList[i] = DataList[Count]
endif
if Count == 0 then
call PauseTimer(T)
endif
set i = i + 1
endloop
set u = null
set p = null
set g = null
endfunction
private function Actions takes nothing returns nothing
local location loc = GetSpellTargetLoc()
local real xTarget= GetLocationX(loc)
local real yTarget = GetLocationY(loc)
local real a
local Data dat = Data.create()
set DataList[Count] = dat
set dat.caster = GetTriggerUnit()
set dat.executions = R2I(DISTANCE / MOVEMENT_PER_ITERATION)
set dat.x = GetUnitX(dat.caster)
set dat.y = GetUnitY(dat.caster)
set a = Atan2((yTarget-dat.y), (xTarget-dat.x))
set dat.xd = MOVEMENT_PER_ITERATION*Cos(a)
set dat.yd = MOVEMENT_PER_ITERATION*Sin(a)
set dat.damage = CalculateDamage(dat.caster)
set dat.dummy = CreateUnit(GetOwningPlayer(dat.caster), DUMMY_ID, dat.x, dat.y, Rad2Deg(a))
set Count = Count + 1
if Count == 1 then
call TimerStart(T, TIMEOUT, true, function Loop)
endif
call RemoveLocation(loc)
set loc = null
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABIL_CODE
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Actions)
endfunction
endscope