Hello. I've been trying to make a spell, which throws projectiles (dummy units) into air around the caster, and damages enemies when they land. So far, the spell works fine, there's just one thing that has to be fixed: on some rare cases, a dummy unit is created and it isn't moved and therefore it isn't removed either. This code isn't even nearly optimal, but I can't find any clear errors. Here's the trigger:
I believe that the mistake is somewhere in the first loop of the Loop function. I'd be grateful if anyone could spot the mistake. Any other improvement ideas are also welcome.
JASS:
scope SeedFlare initializer init
private struct Data
unit u
real damage
integer executions
endstruct
private struct Dummy
unit u
real dist
real d
real dx
real dy
unit c
real damage
endstruct
globals
private Data array DataList
private Dummy array DummyList
private integer Count = 0
private integer DummyCount = 0
private timer T = CreateTimer()
private real Area = 1000
private real Height = 1500
private real Speed = 1.5
endglobals
private function True takes nothing returns boolean
return true
endfunction
private function Loop takes nothing returns nothing
local Data dat
local Dummy dum
local integer i = 0
local location p
local group g
local unit u
local real angle
local real dist
local real x
local real y
loop
exitwhen i >= Count
set dat = DataList[i]
set angle = GetRandomReal(0, 2*bj_PI)
set dum = Dummy.create()
set dum.dist = GetRandomReal(1, Area)
set dum.u = CreateUnit(GetOwningPlayer(dat.u), 'n00Z', GetUnitX(dat.u), GetUnitY(dat.u), angle)
set dum.d = 0
set dum.damage = dat.damage
set dum.c = dat.u
set dum.dx = Cos(angle) * dum.dist * Speed * 0.01
set dum.dy = Sin(angle) * dum.dist * Speed * 0.01
set DummyList[DummyCount] = dum
set DummyCount = DummyCount + 1
set dat.executions = dat.executions - 1
if dat.executions == 0 then
call dat.destroy()
set Count = Count - 1
set DataList[i] = DataList[Count]
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i >= DummyCount
set dum = DummyList[i]
call SetUnitX(dum.u, GetUnitX(dum.u) + dum.dx)
call SetUnitY(dum.u, GetUnitY(dum.u) + dum.dy)
set dum.d = dum.d + SquareRoot(dum.dx*dum.dx + dum.dy*dum.dy)
call SetUnitFlyHeight(dum.u, Parabola(dum.dist, Height, dum.d), 0)
set x = GetUnitX(dum.u)
set y = GetUnitY(dum.u)
if dum.d > dum.dist then
set p = Location(x, y)
set g = GetUnitsInRangeOfLocMatching(100, p, Filter(function True))
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl", x, y))
loop
set u = FirstOfGroup(g)
exitwhen u == null
if IsPlayerEnemy(GetOwningPlayer(u), GetOwningPlayer(dum.c)) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dum.c, u, dum.damage,true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(g, u)
endloop
call RemoveLocation(p)
call DestroyGroup(g)
call RemoveUnit(dum.u)
call dum.destroy()
set DummyCount = DummyCount - 1
set DummyList[i] = DummyList[DummyCount]
endif
set i = i + 1
endloop
if DummyCount == 0 then
call PauseTimer (T)
endif
endfunction
private function Actions takes nothing returns nothing
local Data dat = Data.create()
set DataList[Count] = dat
set dat.u = GetTriggerUnit()
set dat.executions = 50
set dat.damage = (30 + GetHeroInt(dat.u,true)) * (1 + 0.2 * GetUnitAbilityLevel(dat.u, 'A027'))
set Count = Count + 1
if Count == 1 then
call TimerStart(T, 0.04, true, function Loop)
endif
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A027'
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
I believe that the mistake is somewhere in the first loop of the Loop function. I'd be grateful if anyone could spot the mistake. Any other improvement ideas are also welcome.