- Joined
- Nov 25, 2008
- Messages
- 1,309
Below is the system for projectiles and effects that I am working on for a map. Within one of these systems there are leaks. I can tell there are leaks by the way because of degrading performance on the map when testing it with a spell that spawns 80 projectiles and each projectile spawns an effect when it dies. The spell itself, when cast the first time, causes no lag on my machine so I am sure that the spell itself is not the source of the degrading performance.
If you would like to see the trigger that adds a few spells, I can post those as well.
JASS:
globals
boolean udg_Bool
group udg_Effects
timer udg_EffectTimer
real udg_SpellA
unit udg_SpellC
trigger udg_Spellcast
hashtable udg_SpellData
hashtable udg_SpellIndex
player udg_SpellP
group udg_Spells
timer udg_SpellTimer
unit udg_SpellTU
real udg_SpellTX
real udg_SpellTY
real udg_SpellX
real udg_SpellY
unit udg_Unit
unit udg_Unit2
endglobals
JASS:
function ProjHit takes nothing returns boolean
local unit U=GetFilterUnit()
local player P=GetOwningPlayer(U)
local integer id=GetHandleId(udg_Unit)
local real dmg=LoadReal(udg_SpellData,id,1)
local unit C=LoadUnitHandle(udg_SpellData,id,0)
if GetWidgetLife(U)>0.405and IsUnitEnemy(udg_Unit,P)then
set udg_Bool=true
call SetWidgetLife(U,GetWidgetLife(U)-dmg)
call SetHeroXP(C,GetHeroXP(C)+R2I(dmg),true)
endif
set C=null
set U=null
set P=null
return false
endfunction
function Spell_Tick takes nothing returns nothing
local group G=CreateGroup()
local boolean E=false
local real ang
local real x
local real y
local real spd
local real lif
local integer id
local group hit=CreateGroup()
local conditionfunc con=Condition(function ProjHit)
local integer i
local player P
local unit U
local unit C
call GroupAddGroup(udg_Spells,G)
loop
set udg_Unit=FirstOfGroup(G)
exitwhen udg_Unit==null
set E=true
// projectile code
set lif=GetWidgetLife(udg_Unit)
set id=GetHandleId(udg_Unit)
set ang=GetUnitFacing(udg_Unit)
set spd=LoadReal(udg_SpellData,id,2)*0.03
set x=GetUnitX(udg_Unit)+spd*Cos(ang*bj_DEGTORAD)
set y=GetUnitY(udg_Unit)+spd*Sin(ang*bj_DEGTORAD)
if lif>0.405then
set udg_Bool=false
call GroupEnumUnitsInRange(hit,x,y,LoadReal(udg_SpellData,id,3),con)
if udg_Bool or IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY)or GetTerrainType(x,y)=='Xhdg'then
call SetWidgetLife(udg_Unit,0)
else
// Trail
if LoadBoolean(udg_SpellData,id,5)then
if GetRandomReal(0,1)<=LoadReal(udg_SpellData,id,70)then
set i=LoadInteger(udg_SpellData,id,72)
set P=GetOwningPlayer(udg_Unit)
loop
set U=CreateUnit(P,LoadInteger(udg_SpellData,id,71),x,y,ang)
if GetUnitAbilityLevel(U,'A001')>0then
set C=LoadUnitHandle(udg_SpellData,id,0)
call SaveUnitHandle(udg_SpellData,GetHandleId(U),0,C)
set C=null
endif
set U=null
set i=i-1
exitwhen i<1
endloop
endif
endif
call SetUnitX(udg_Unit,x)
call SetUnitY(udg_Unit,y)
call SetWidgetLife(udg_Unit,lif-spd)
endif
else // It died...
// Explode
if LoadBoolean(udg_SpellData,id,4)then
call SaveReal(udg_SpellData,id,1,LoadReal(udg_SpellData,id,51))
call GroupEnumUnitsInRange(hit,x,y,LoadReal(udg_SpellData,id,50),con)
endif
// Split
if LoadBoolean(udg_SpellData,id,6)then
set i=LoadInteger(udg_SpellData,id,91)
set P=GetOwningPlayer(udg_Unit)
loop
set U=CreateUnit(P,LoadInteger(udg_SpellData,id,90),x,y,ang)
if GetUnitAbilityLevel(U,'A001')>0then
set C=LoadUnitHandle(udg_SpellData,id,0)
call SaveUnitHandle(udg_SpellData,GetHandleId(U),0,C)
set C=null
endif
set U=null
set i=i-1
exitwhen i<1
endloop
endif
// Remove It
call FlushChildHashtable(udg_SpellData,id)
call GroupRemoveUnit(udg_Spells,udg_Unit)
endif
// -----
call GroupRemoveUnit(G,udg_Unit)
endloop
call DestroyGroup(G)
set G=null
call DestroyGroup(hit)
set hit=null
call DestroyCondition(con)
set con=null
set P=null
set U=null
set C=null
if E then
call TimerStart(udg_SpellTimer,0.03,false,function Spell_Tick)
endif
endfunction
JASS:
function EffHit takes nothing returns boolean
local unit U=GetFilterUnit()
local player P=GetOwningPlayer(U)
local integer id=GetHandleId(udg_Unit2)
local real dmg=LoadReal(udg_SpellData,id,-1)*0.25
local unit C=LoadUnitHandle(udg_SpellData,id,0)
if GetWidgetLife(U)>0.405and IsUnitEnemy(udg_Unit2,P)then
call SetWidgetLife(U,GetWidgetLife(U)-dmg)
call SetHeroXP(C,GetHeroXP(C)+R2I(dmg),true)
endif
set C=null
set U=null
set P=null
return false
endfunction
function Effect_Tick takes nothing returns nothing
local group G=CreateGroup()
local boolean E=false
local real lif
local group hit=CreateGroup()
local conditionfunc con=Condition(function EffHit)
local integer id
call GroupAddGroup(udg_Effects,G)
loop
set udg_Unit2=FirstOfGroup(G)
exitwhen udg_Unit2==null
set E=true
set id=GetHandleId(udg_Unit2)
// effect code
set lif=GetWidgetLife(udg_Unit2)
if lif>0.405then
call GroupEnumUnitsInRange(hit,GetUnitX(udg_Unit2),GetUnitY(udg_Unit2),LoadReal(udg_SpellData,id,-2),con)
call SetWidgetLife(udg_Unit2,lif-0.25)
else
call FlushChildHashtable(udg_SpellData,id)
call GroupRemoveUnit(udg_Effects,udg_Unit2)
endif
// -----
call GroupRemoveUnit(G,udg_Unit2)
endloop
call DestroyGroup(G)
set G=null
call DestroyGroup(hit)
set hit=null
call DestroyCondition(con)
set con=null
if E then
call TimerStart(udg_EffectTimer,0.25,false,function Effect_Tick)
endif
endfunction
JASS:
function Spellcast takes nothing returns nothing
local integer sid=GetSpellAbilityId()
local triggercondition Tc
if LoadBoolean(udg_SpellIndex,sid,0)then
set udg_SpellC=GetSpellAbilityUnit()
set udg_SpellP=GetOwningPlayer(udg_SpellC)
set udg_SpellX=GetUnitX(udg_SpellC)
set udg_SpellY=GetUnitY(udg_SpellC)
set udg_SpellTX=GetSpellTargetX()
set udg_SpellTY=GetSpellTargetY()
set udg_SpellTU=GetSpellTargetUnit()
set udg_SpellA=bj_RADTODEG*Atan2(udg_SpellTY-udg_SpellY,udg_SpellTX-udg_SpellX)
set Tc=TriggerAddCondition(udg_Spellcast,LoadBooleanExprHandle(udg_SpellIndex,sid,1))
call TriggerEvaluate(udg_Spellcast)
call TriggerRemoveCondition(udg_Spellcast,Tc)
call TimerStart(udg_SpellTimer,0.03,false,function Spell_Tick)
set udg_SpellC=null
set udg_SpellP=null
set udg_SpellTU=null
endif
set Tc=null
endfunction
function InitTrig_Spellcast takes nothing returns nothing
local integer i=15
set gg_trg_Spellcast=CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(gg_trg_Spellcast,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i=i-1
exitwhen i<0
endloop
call TriggerAddCondition(gg_trg_Spellcast,Condition(function Spellcast))
endfunction
If you would like to see the trigger that adds a few spells, I can post those as well.