- Joined
- Jun 26, 2020
- Messages
- 1,921
I made this spell to emulate the stampede but instead of lizzards, there are fire ball, I wanna test it but there is an infinite loop that I can't find, could you do it for me pls?
I'm using a custom Alloc and Table and a unit indexer
I'm using a custom Alloc and Table and a unit indexer
vJASS:
scope FireStorm initializer Init
struct FireStorm extends array
implement Alloc
static group g1=CreateGroup()
static group g2=CreateGroup()
static constant real INTERVAL=0.05
static constant real AREA_EFF=1000
static constant real AREA_COL=55
static constant real AREA_DMG=100
static constant real SPEED=500*thistype.INTERVAL
static constant integer MAX_DIS=R2I(thistype.AREA_EFF/thistype.SPEED)
static constant string MODEL="war3mapImported\\GreatElderHydraMoltenBreathV.196.mdx"
static effect array attached
static integer array reached
unit caster
player owner
integer counter
real damage
real x_offset
real y_offset
real face
real face_comp
Table next_fb
Table prev_fb
timer t
static method create takes unit caster, integer spell, integer level, real x, real y returns thistype
local thistype this=thistype.allocate()
//Set the data
set this.caster=caster
set this.owner=GetOwningPlayer(caster)
if spell=='A049' then
set this.damage=60
endif
set this.face=GetUnitFacing(caster)*bj_DEGTORAD
set this.face_comp=this.face-bj_PI/2
set this.x_offset=GetUnitX(caster)-thistype.AREA_EFF*Cos(this.face)
set this.y_offset=GetUnitY(caster)-thistype.AREA_EFF*Sin(this.face)
set this.counter=0
set t=NewTimerEx(this)
call TimerStart(this.t,thistype.INTERVAL,true,function thistype.callperiodic)
return this
endmethod
static method callperiodic takes nothing returns nothing
local thistype this=GetTimerData(GetExpiredTimer())
local integer i
local real r
if OrderId2String(GetUnitCurrentOrder(this.caster))=="stampede" then
//Create the fire ball
set r=GetRandomReal(-thistype.AREA_EFF,thistype.AREA_EFF)
set bj_lastCreatedUnit=GetRecycledUnit(this.owner/*
*/,'h013'/*
*/,this.x_offset+r*Cos(this.face_comp)/*
*/,this.y_offset+r*Sin(this.face_comp)/*
*/,this.face*bj_RADTODEG)
set i=GetUnitUserData(bj_lastCreatedUnit)
//Add to the list
set this.next_fb.integer[i]=0
set this.prev_fb.integer[i]=this.prev_fb.integer[0]
set this.next_fb.integer[this.prev_fb.integer[i]]=i
set this.prev_fb.integer[0]=i
set thistype.attached[i]=AddSpecialEffectTarget(thistype.MODEL,bj_lastCreatedUnit,"chest")
set thistype.reached[i]=0
set this.counter=this.counter+1
else
if this.counter==0 then
call this.destroy()
endif
endif
call this.move()
endmethod
method move takes nothing returns nothing
local integer i=this.next_fb.integer[0]
local real x
local real y
local unit u1
local unit u2
loop
exitwhen i==0
//Moving the fire ball
set x=GetUnitX(udg_UDexUnits[i])
set y=GetUnitY(udg_UDexUnits[i])
call SetUnitPosition(udg_UDexUnits[i],x+thistype.SPEED*Cos(this.face),y+thistype.SPEED*Sin(this.face))
//Check the units around the fire ball
call GroupEnumUnitsInRange(thistype.g1,x,y,thistype.AREA_COL,null)
loop
set u1=FirstOfGroup(thistype.g1)
exitwhen u1==null
if IsUnitEnemy(u1,this.owner) and IsUnitAliveBJ(u1) then
//If true then damage the nearby enemy units
call GroupEnumUnitsInRange(thistype.g2,x,y,thistype.AREA_DMG,null)
loop
set u2=FirstOfGroup(thistype.g2)
exitwhen u2==null
if IsUnitEnemy(u2,this.owner) and IsUnitAliveBJ(u2) then
call UnitDamageTarget(this.caster,u2,this.damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE,WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(thistype.g2,u2)
endloop
call GroupClear(thistype.g1)
call this.removeFromList(i)
endif
call GroupRemoveUnit(thistype.g1,u1)
endloop
//Remove if reaches the objective
set thistype.reached[i]=thistype.reached[i]+1
if thistype.reached[i]>=thistype.MAX_DIS then
call this.removeFromList(i)
endif
set i=this.next_fb.integer[i]
endloop
endmethod
method removeFromList takes integer i returns nothing
//Removing from list
set this.next_fb.integer[this.prev_fb.integer[i]]=this.next_fb.integer[i]
set this.prev_fb.integer[this.next_fb.integer[i]]=this.prev_fb.integer[i]
//Clear the data of the fire ball
set this.counter=this.counter-1
call DestroyEffect(thistype.attached[i])
set thistype.attached[i]=null
call RecycleUnitDelayed(udg_UDexUnits[i],0.27)
endmethod
method destroy takes nothing returns nothing
//Clear the data of the instance
call ReleaseTimer(this.t)
call this.next_fb.flush()
call this.prev_fb.flush()
set this.caster=null
set this.owner=null
set this.t=null
call this.deallocate()
endmethod
endstruct
private function Conditions takes nothing returns boolean
return Spell=='A049'
endfunction
private function Actions takes nothing returns nothing
call FireStorm.create(Caster,Spell,Level,GetSpellTargetX(),GetSpellTargetY())
endfunction
private function Init takes nothing returns nothing
set gg_trg_Fire_storm=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Fire_storm,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Fire_storm,Condition(function Conditions))
call TriggerAddAction(gg_trg_Fire_storm,function Actions)
endfunction
endscope