- Joined
- Jul 28, 2008
- Messages
- 211
I made a spell:
The it should create 4 rocks that circle around the caster and damage enemy units they hit (they explode too).
Now, the spell works, but when I cast it 2 times with a same unit (while the effect is still on), the rocks all appear on the ground where the caster is standing, and they don't move. Sometimes they DO start moving after the rocks that are on the caster explode. But only sometimes.
So what's causing this to happen? And is there anything that could be changed to make the spell more efficient?
JASS:
scope Spell initializer Init
native UnitAlive takes unit u returns boolean
globals
private timer TIMER = CreateTimer()
private boolexpr b
private group G = CreateGroup()
private constant integer DUMMY_ID = 'h000'
private constant integer SPELL_ID = 'A000'
private constant real RADIUS = 100.00
private constant real PERIOD = 0.035
private constant real DURATION = 10.00
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
endglobals
private function GroupFilter takes nothing returns boolean
return (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and UnitAlive(GetFilterUnit())
endfunction
private function Damage takes integer level returns real
return I2R(level * 50 + 50)
endfunction
private struct Spells
static integer Total = 0
static Spells array ar
unit caster
unit array dummy [4]
integer level
real duration = 0
real array angle [4]
static method Loop takes nothing returns nothing
local integer i = 0
local integer count = 0
local unit temp
local real x
local real y
local Spells s
loop
exitwhen i >= Spells.Total
set s = Spells.ar[i]
if s.duration >= DURATION then
set s.caster = null
call KillUnit(s.dummy[0])
call KillUnit(s.dummy[1])
call KillUnit(s.dummy[2])
call KillUnit(s.dummy[3])
set s.dummy[0] = null
set s.dummy[1] = null
set s.dummy[2] = null
set s.dummy[3] = null
call s.destroy()
set Spells.Total = Spells.Total - 1
set Spells.ar[i] = Spells.ar[Spells.Total]
set i = i - 1
else
set s.duration = s.duration + PERIOD
loop
exitwhen count >= 4
set x = GetUnitX(s.caster) + 150 * Cos(s.angle[count] * bj_DEGTORAD)
set y = GetUnitY(s.caster) + 150 * Sin(s.angle[count] * bj_DEGTORAD)
set s.angle[count] = s.angle[count] + 7.5
call SetUnitX(s.dummy[count], x)
call SetUnitY(s.dummy[count], y)
call GroupEnumUnitsInRange(G, x, y, RADIUS, b)
loop
set temp = FirstOfGroup(G)
exitwhen temp == null
if IsUnitEnemy(temp, GetOwningPlayer(s.caster)) and s.dummy[count] != null then
call UnitDamageTarget(s.caster, temp, Damage(s.level), false, true, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call KillUnit(s.dummy[count])
set s.dummy[count] = null
endif
call GroupRemoveUnit(G, temp)
if s.dummy[0] == null and s.dummy[1] == null and s.dummy[2] == null and s.dummy[3] == null then
set s.caster = null
call s.destroy()
endif
endloop
set count = count + 1
endloop
endif
set i = i + 1
endloop
if Spells.Total == 0 then
call PauseTimer(TIMER)
endif
endmethod
static method Create takes unit caster returns nothing
local Spells s = Spells.allocate()
set s.caster = caster
set s.level = GetUnitAbilityLevel(caster, SPELL_ID)
//1
set s.dummy[0] = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, GetUnitX(caster), GetUnitY(caster), 0)
set s.angle[0] = 0
//2
set s.dummy[1] = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, GetUnitX(caster), GetUnitY(caster), 0)
set s.angle[1] = 90
//3
set s.dummy[2] = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, GetUnitX(caster), GetUnitY(caster), 0)
set s.angle[2] = 180
//4
set s.dummy[3] = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, GetUnitX(caster), GetUnitY(caster), 0)
set s.angle[3] = 270
if Spells.Total == 0 then
call TimerStart(TIMER, PERIOD, true, function Spells.Loop)
endif
set Spells.ar[Spells.Total] = s
set Spells.Total = Spells.Total + 1
endmethod
endstruct
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endfunction
private function Act takes nothing returns nothing
call Spells.Create(GetTriggerUnit())
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t, function Act)
call TriggerAddCondition(t, Condition(function Cond))
set b = Filter(function GroupFilter)
endfunction
endscope
The it should create 4 rocks that circle around the caster and damage enemy units they hit (they explode too).
Now, the spell works, but when I cast it 2 times with a same unit (while the effect is still on), the rocks all appear on the ground where the caster is standing, and they don't move. Sometimes they DO start moving after the rocks that are on the caster explode. But only sometimes.
So what's causing this to happen? And is there anything that could be changed to make the spell more efficient?