HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Leak in Missile Spell (I'm using HSAS)

10-22-2008, 12:56 AM#1
GALLED
Hello, I was creating a missile system to use it in a spell that is like the spirits of the Diablo's Necromancer (with some differences).

The spell launch a Phantom that seek the target or seek a target. When the target is damaged get a buff. All the ghosts that are created later seek the target with the buff.

All works fine, but i have a leak in some part, since whenever cast the spell the leaks are accumulated and accumulated.

There are my n00b system

Collapse JASS:
library Misiles needs HSAS


globals

private integer array Doodad_ID
endglobals

public function Setea takes nothing returns nothing
//Set the trees valid to destroy.
set Doodad_ID[1]='ATtr'
set Doodad_ID[2]='BTtw'
set Doodad_ID[3]='KTtw'
set Doodad_ID[4]='YTft'
set Doodad_ID[5]='JTct'
set Doodad_ID[6]='YTst'
set Doodad_ID[7]='YTct'
set Doodad_ID[8]='YTwt'
set Doodad_ID[9]='JTtw'
set Doodad_ID[10]='DTsh'
set Doodad_ID[11]='FTtw'
set Doodad_ID[12]='CTtr'
set Doodad_ID[13]='ITtw'
set Doodad_ID[14]='NTtw'
set Doodad_ID[15]='OTtw'
set Doodad_ID[16]='ZTtw'
set Doodad_ID[17]='WTst'
set Doodad_ID[18]='LTlt'
set Doodad_ID[19]='GTsh'
set Doodad_ID[20]='VTlt'
set Doodad_ID[21]='WTtw'
set Doodad_ID[22]='ATtc'
set Doodad_ID[23]='BTtc'
set Doodad_ID[24]='CTtc'
set Doodad_ID[25]='ITtc'
set Doodad_ID[26]='NTtc'
set Doodad_ID[27]='ZTtc'

endfunction

function mataarbol takes nothing returns nothing
local destructable d = GetEnumDestructable()
local integer i

    set i = 1
    loop
        exitwhen (i>27) or (GetDestructableTypeId(d)==Doodad_ID[i])
        set i = i+1
    endloop
 
    if (GetWidgetLife(d)> 0) and (i<=27) then
        call KillDestructable(d)
    endif
    
set d = null
endfunction

private function CadaINTERVAL takes nothing returns nothing
local timer t = GetExpiredTimer()
local Misil M = GetAttachedStruct1(t)
local unit v
local real a 
local boolean r = false
local real x1 = GetUnitX(M.proyectil)
local real y1 = GetUnitY(M.proyectil)
local real x2
local real y2

        if(M.HaceAlPasar)then
            set v = M.Busca(M.Area,x1,y1,false)
            if(v!=null)then
                call M.Impacta(v)
            endif
        endif
        
        set a = SquareRoot((M.x-x1)*(M.x-x1) + (M.y-y1)*(M.y-y1))
            
        if(M.MaxDistancia>0)then
            set M.distancia_misil = M.distancia_misil+SquareRoot((x1-M.x_temp)*(x1-M.x_temp) + (y1-M.y_temp)*(y1-M.y_temp))
            set M.x_temp   = x1
            set M.y_temp   = y1
        endif
            
        if(M.TiempoDeVida>0.0)then
            set M.i = M.i+M.velocidad
        endif
        
        if(M.victim!=null)then
            set x2 = GetUnitX(M.victim)
            set y2 = GetUnitY(M.victim)        
            set r = (SquareRoot((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))>50)
            set r = r and not((M.b) and (GetUnitAbilityLevel(M.victim,M.Spell_Buff) <= 0))
        else
            set r = (M.MaxDistancia-M.distancia_misil>50)            
        endif
        
        if (r) then
            if((M.i<=M.TiempoDeVida))then
            
                call M.mueve() //Mueve el proyectil
                if(M.DestroyImpact)then
                    set M.victim = M.Busca(M.Area,GetUnitX(M.proyectil),GetUnitY(M.proyectil),false)
                    if(M.victim!=null)then
                        call Misil.destroy(M)
                    endif
                endif
            else
                call Misil.destroy(M)
            endif
        else
            call Misil.destroy(M)
        endif
        
    set v = null
    set t = null
endfunction
    
struct Misil
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//                          CONFIGURACION DEL MISIL
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
         
real x                 = 0.0 //Point X towards where the Missile will go. Not to fill up if the missile seeks the target.
real y                 = 0.0 //Point Y towards where the Missile will go. Not to fill up if the missile seeks the target.

real damage            = 0.0  //Missile damage
real velocidad         = 0.03 //Time INTERVAL used in the timer.
real paso              = 20.0 //Distance that increases each INTERVAL determined in " velocidad".

string  Accion_Tipo    = "None" 
//None        : Do Nothing
//Target      : One target.
//MultiTarget : Many targets with one single dummy spell
//AoE         : AoE Spell with target point (Dummy Spell)
//AoESelf     : AoE Spell with no targets (Dummy Spell)
boolean Spell          = false
integer Spell_ID       = 0  //Missile Spell.
integer Spell_Buff     = 0  //Buff that verifies if victim already received the missile and no longer it is necessity that receives buff
string  Spell_Order    = "" //Spell dummy Order
string  Spell_FX       = "" //Special Effect when the missile impact the target
string  Misil_FX       = "" //Special Effect attached to the missile. Only Special Effects with Inmediate DestroyEffect.
string  Misil_End_FX   = "" //Special Effect when the missile die.
integer Spell_Nvl      = 1  //Level of Dummy Spell's Missile 

real   Area            = 200.0 //AoE of the Missile
real   TiempoDeVida    = 0.0   //Time life of the Missile
real   MaxDistancia    = 0.0   //If you want a maximum distance that it crosses the missile, without mattering if it reached or not to its objective.

boolean HaceAlPasar    = false //The missile damages all the creatures around, in an AoE of "Area" while it aproach.
boolean DestroyImpact  = false //The missile impact in the first creature it encounters.
boolean EsPersistente  = false //The missile still affects the creatures who already have been affected by the spell.
boolean MisilCamina    = false //The missile moves according to the movespeed determined in dummy creature of the missile
boolean DestroySinBuff = false //The missile will be destroyed if it followed an objective with buff and no longer it has buff suddenly.
boolean PasayMataArbol = false //The missile will destroy trees around.

damagetype TipoDanio   = DAMAGE_TYPE_MAGIC  //It determines the type of damage that does
attacktype TipoAtake   = ATTACK_TYPE_NORMAL //It determines the type of attack that does
boolean RemueveMisil   = false              //It determines if the missile is removed or it is killed. By defect it is killed.

unit victim           = null //Set a unit so the missile follows. 
                             //If is a missile that in line goes straight not to put anything.
string array Targets[14]     //Array of Targets that has the spell. To add " No_" it puts the filter to the inverse one in 
                            // each case.
//Alive
//Alied
//Mechanical 
//Structures
//Heroes
//Ilusion
//Summon
integer N_Targets      = 0   //Size of the Array of targets. Whatever of the allowed filters you have put.
                             //Put nothing if using the preset filters.

/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

unit proyectil        = null
timer t               = null
group g               = null
group g_aux           = null
player p              = null
rect tmp_rect         = null

real x_origen         = 0.0
real y_origen         = 0.0
real x_temp           = 0.0
real y_temp           = 0.0
real distancia_misil  = 0.0
real i                = 0.0
real angulo           = 0.0
boolean b             = false

    static method create takes player p, integer Misil_Model, real x, real y, real a returns Misil
    local Misil M = Misil.allocate()
        set M.p = p
        set M.proyectil = CreateUnit(p,Misil_Model,x,y,a)
        set M.g = CreateGroup()
        //We establish the filters by defect
        set M.N_Targets=3
        set M.Targets[1] = "Alive"
        set M.Targets[2] = "No_Mechanical" 
        set M.Targets[3] = "No_Alied"           
        
        return M
    endmethod
    
    method Vale takes unit u, boolean con_buff returns boolean
    local boolean r = ((GetUnitAbilityLevel(u,.Spell_Buff) > 0)==con_buff)
    local integer i = 1
    
        loop
            exitwhen i>.N_Targets
            if(.Targets[i]=="Alive")then
                set r = r and (GetWidgetLife(u)>0.405)
            elseif(.Targets[i]=="No_Alive")then
                set r = r and (GetWidgetLife(u)<=0.405)   
            elseif(.Targets[i]=="Alied")then
                set r = r and (IsUnitAlly(u,.p))
            elseif(.Targets[i]=="No_Alied")then
                set r = r and (IsUnitAlly(u,.p)==false)  
            elseif(.Targets[i]=="Mechanical")then
                set r = r and IsUnitType(u,UNIT_TYPE_MECHANICAL)                
            elseif(.Targets[i]=="No_Mechanical")then
                set r = r and (IsUnitType(u,UNIT_TYPE_MECHANICAL)==false)
            elseif(.Targets[i]=="Structures")then
                set r = r and IsUnitType(u,UNIT_TYPE_STRUCTURE)
            elseif(.Targets[i]=="No_Structures")then
                set r = r and (IsUnitType(u,UNIT_TYPE_STRUCTURE)==false)
            elseif(.Targets[i]=="Heroes")then
                set r = r and IsUnitType(u,UNIT_TYPE_HERO)
            elseif(.Targets[i]=="No_Heroes")then   
                set r = r and (IsUnitType(u,UNIT_TYPE_HERO)==false)
            elseif(.Targets[i]=="Ilusion")then
                set r = r and IsUnitIllusion(u)
            elseif(.Targets[i]=="No_Ilusion")then
                set r = r and (IsUnitIllusion(u)==false)
            elseif(.Targets[i]=="Summon")then
                set r = r and IsUnitType(u,UNIT_TYPE_SUMMONED)
            elseif(.Targets[i]=="No_Summon")then   
                set r = r and (IsUnitType(u,UNIT_TYPE_SUMMONED)==false)               
            endif
            set i = i+1
        endloop

        if(.HaceAlPasar)then
            return (r and not(IsUnitInGroup(u,.g_aux)))
        endif
        
    return r
    endmethod   

    method Busca takes real area, real x, real y, boolean con_buff returns unit
    local unit target = null
    
        call GroupEnumUnitsInRange(.g,x,y,area,null)
        loop
            set target = FirstOfGroup(.g)
            exitwhen (target==null) or this.Vale(target,con_buff)
            call GroupRemoveUnit(.g,target)
        endloop
        call GroupClear(.g)
        
    return target
    
    endmethod
    
    method Impacta takes unit v returns nothing
    local real x = GetUnitX(v)
    local real y = GetUnitY(v)    
    local unit d
    local unit j
    local effect e

        if (.Accion_Tipo == "Target") then
        
            if(.HaceAlPasar)then
                call GroupAddUnit(.g_aux,v)
            endif
            
            if(.Spell_FX!="")then
                set e = AddSpecialEffect(.Spell_FX,GetUnitX(v),GetUnitY(v))
                call DestroyEffectTimed(e,1.0)    
            endif
            
            set d = CreateUnit(.p,dunit(),x,y,0)
            if(.damage>0.0)then
                call UnitDamageTarget(d,v,.damage,true,false,.TipoAtake,.TipoDanio,null)
            endif
            call UnitApplyTimedLife(d,'BTLF',1.5)
            
            if(.Spell)then
                debug call BJDebugMsg("Buff "+I2S(GetUnitAbilityLevel(v,.Spell_Buff)))
                if (GetUnitAbilityLevel(v,.Spell_Buff) <= 0) or (.EsPersistente) then
                    debug call BJDebugMsg("Lanza el hechizos "+GetUnitName(v))
                    call UnitAddAbility(d,.Spell_ID)
                    call SetUnitAbilityLevel(d, .Spell_ID, .Spell_Nvl)
                    call IssueTargetOrder(d,.Spell_Order,v)
                endif
            endif
            
        elseif(.Accion_Tipo == "MultiTarget")then
            call GroupEnumUnitsInRange(.g,x,y,.Area,null)
            loop
                set j = FirstOfGroup(.g)
                exitwhen (j==null) 
                call GroupRemoveUnit(.g,j)
                
                if(this.Vale(j,false)) or (this.Vale(j,.EsPersistente)) then
                
                    if(.HaceAlPasar)then
                        call GroupAddUnit(.g_aux,j)
                    endif
                    
                    if(.Spell_FX!="")then
                        set e = AddSpecialEffect(.Spell_FX,GetUnitX(j),GetUnitY(j))
                        call DestroyEffectTimed(e,1.0)
                    endif
                    
                    set d = CreateUnit(.p,dunit(),GetUnitX(j),GetUnitY(j),0)
                    if(.damage>0.0)then                    
                        call UnitDamageTarget(d,j,.damage,true,false,.TipoAtake,.TipoDanio,null)
                    endif
                    call UnitApplyTimedLife(d,'BTLF',1.5)
            
                    if(.Spell)then
                        call UnitAddAbility(d,.Spell_ID)
                        call SetUnitAbilityLevel(d, .Spell_ID, .Spell_Nvl)
                        call IssueTargetOrder(d,.Spell_Order,j)
                    endif
                    
                endif
                
            endloop
            call GroupClear(.g)
            
        elseif(.Accion_Tipo == "AoE")then
        
            set d = CreateUnit(.p,dunit(),x,y,0)
            call UnitApplyTimedLife(d,'BTLF',1.5)
            call UnitAddAbility(d,.Spell_ID)
            call SetUnitAbilityLevel(d, .Spell_ID, .Spell_Nvl)
            call IssuePointOrder(d,.Spell_Order,x,y)
            
        elseif(.Accion_Tipo == "AoESelf")then
        
            set d = CreateUnit(.p,dunit(),x,y,0)
            call UnitApplyTimedLife(d,'BTLF',1.5)
            call UnitAddAbility(d,.Spell_ID)
            call SetUnitAbilityLevel(d, .Spell_ID, .Spell_Nvl)
            call IssueImmediateOrder(d,.Spell_Order)
            
        endif        
        
    set e = null
    set j = null    
    set d = null
    endmethod

    method onDestroy takes nothing returns nothing
    local effect e 
    
        if(.Misil_End_FX!="")then
            set e = AddSpecialEffect(.Misil_End_FX,GetUnitX(.proyectil),GetUnitY(.proyectil))
            call DestroyEffectTimed(e,1.0) 
        endif
        
        if(.victim!=null)then
            call this.Impacta(.victim)
        else
            set .victim = this.Busca(.Area,GetUnitX(.proyectil),GetUnitY(.proyectil), false)
            if(.victim!=null)then
                call this.Impacta(.victim)
            endif
        endif
        
        if(.RemueveMisil)then
            call RemoveUnit(.proyectil)
        else
            if(.Spell)then
                call UnitApplyTimedLife(.proyectil,'BTLF',0.4)
            else
                call KillUnit(.proyectil)
            endif
        endif
        
        call DestroyGroup(.g)
        call DestroyGroup(.g_aux)
        call RemoveRect(.tmp_rect)
        call PauseTimer(.t)
        call DestroyTimer(.t)

        set e = null
        set .tmp_rect = null
        set .proyectil = null
        set .t = null
        set .victim = null
        set .g = null
        set .g_aux = null
        set .p = null
    endmethod
    
    method mueve takes nothing returns nothing
    local real a = .angulo
    local real x
    local real y
    
        if(.Misil_FX!="")then
            call DestroyEffect(AddSpecialEffectTarget(.Misil_FX,.proyectil,"origin")) 
        endif
        
        if(.victim!=null)then
        //If victim exists, it will follow it to the missile
            set .x = GetUnitX(.victim)
            set .y = GetUnitY(.victim)
   
            set a = Atan2(.y-GetUnitY(.proyectil),.x-GetUnitX(.proyectil)) 
        endif    
        
        if(.MisilCamina)then
            call IssuePointOrder(.proyectil,"move",.x,.y)
        else
            set x = GetUnitX(.proyectil)+.paso*Cos(a) 
            set y = GetUnitY(.proyectil)+.paso*Sin(a)
            call SetUnitPosition(.proyectil,x,y)
            call SetUnitFacing(.proyectil,a*57.29583)
        endif
        
        if(.PasayMataArbol)then
            set .tmp_rect = Rect(x - (.Area/2), y - (.Area/2), x + (.Area/2), y + (.Area/2))
            call EnumDestructablesInRect(.tmp_rect, null, function mataarbol)
        endif
        
    endmethod

    static method dispara takes Misil M returns nothing
        set M.t = CreateTimer()
        
        if(M.HaceAlPasar)then
            set M.g_aux = CreateGroup()
        endif

        set M.x_origen = GetUnitX(M.proyectil)
        set M.y_origen = GetUnitY(M.proyectil)
        set M.x_temp   = GetUnitX(M.proyectil)
        set M.y_temp   = GetUnitY(M.proyectil)
        set M.angulo   = Atan2(M.y-M.y_origen,M.x-M.x_origen) 

        if(M.MaxDistancia<=0) then
            set M.MaxDistancia = SquareRoot((M.x-M.x_origen)*(M.x-M.x_origen) + (M.y-M.y_origen)*(M.y-M.y_origen))     
        endif
        
        set M.b = (M.victim!=null) //If victim already has been seteado. They boolean will be set.
        set M.b = M.b and (M.Spell_Buff!=0) //It detects if the Buff is defined
        set M.b = M.b and (GetUnitAbilityLevel(M.victim,M.Spell_Buff) > 0) //It detects if victim has buff
        set M.b = M.b and (M.DestroySinBuff)

        call AttachStruct1(M.t,M)
        call TimerStart(M.t,M.velocidad,true, function CadaINTERVAL)
    endmethod
    
endstruct

endlibrary

And there are my spell:

Collapse JASS:
scope Espiritus

globals

public trigger trig

private constant real INTERVAL = 0.25
private integer Spell__ID     = 'AOsh' //Spell
private integer Dummy_Model   = 'ugar' //Ghost Model
private integer Spell__Buff   = 'B02I' //Curse Buff's rawcode
private integer Spell_D       = 'A0CN'  //DummyCurse Spell 's rawcode
private real    Spell_AoE     = 200.0 //It looks for in that area by objectives to make damage if there is no a primary objective
private real    Spell_Dmg_Ini = -25.0 //Damage Base
private real    Spell_Dmg_Pro = 75.0 //Progresive Damage per Level
private string  Spell__FX      = "Abilities\\Spells\\Orc\\Disenchant\\DisenchantSpecialArt.mdl" //FX of the death of the phantom.
private string  Dummy_Order   = "cripple"

endglobals

private function Cond takes nothing returns boolean
    return GetSpellAbilityId() == Spell__ID
endfunction

private function Main takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x1 = GetUnitX(u)
local real y1 = GetUnitY(u)
local location loc = GetSpellTargetLoc()
local real x2 = GetLocationX(loc)
local real y2 = GetLocationY(loc)
local player p = GetOwningPlayer(u) 
local integer l = GetUnitAbilityLevel(u,Spell__ID)
local real ang = GetAngleBetweenPoints(x1,y1,x2,y2)
local Misil Phantom
call RemoveLocation(loc)
    
    set Phantom = Misil.create(p,Dummy_Model,PolarProjectionX(x1,100,ang),PolarProjectionY(y1,100,ang),ang)
    

    set Phantom.x              = x2
    set Phantom.y              = y2
    set Phantom.damage         = ( Spell_Dmg_Pro * l ) + Spell_Dmg_Ini + GetHeroInt(u,true)
    set Phantom.velocidad      = INTERVAL
    set Phantom.Accion_Tipo    = "Target" 
    set Phantom.Spell          = true
    set Phantom.Spell_ID       = Spell_D
    set Phantom.Spell_Buff     = Spell__Buff
    set Phantom.Spell_Order    = Dummy_Order
    set Phantom.Spell_FX       = Spell__FX
    set Phantom.Misil_End_FX   = Spell__FX
    set Phantom.TiempoDeVida   = 60.0
    set Phantom.MisilCamina    = true
    set Phantom.TipoDanio      = DAMAGE_TYPE_UNIVERSAL
    set Phantom.TipoAtake      = ATTACK_TYPE_NORMAL
    set Phantom.DestroySinBuff = true
    set Phantom.victim = Phantom.Busca(Spell_AoE,x2,y2,false)
    
    if( Phantom.victim==null)then
        set Phantom.victim =  Phantom.Busca(9000.0,0.0,0.0, true) //If there is no damn one in the point.
                                                                     //I look for one that has buff.
    else
        call GroupEnumUnitsInRange(Phantom.g,0.0,0.0,9000.0,null) //I look for those that have buff and them exempt buff
        loop
            set u = FirstOfGroup(Phantom.g)
            exitwhen (u==null)
            call GroupRemoveUnit(Phantom.g,u)
            if(Phantom.Vale(u,true))then
                call UnitRemoveAbility(u,Phantom.Spell_Buff)
            endif
        endloop
        call GroupClear(Phantom.g)
    endif
    
    call Misil.dispara(Phantom)

set p = null
set u = null
set loc = null
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set trig = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( trig, Condition( function Cond ) )
    call TriggerAddAction( trig, function Main )
    call Preload(Spell__FX)
    call Misiles_Setea()
endfunction

endscope

Thanks in advance.

P.D.: I'm using HSAS by Pandamine.
10-22-2008, 09:14 AM#2
the-thingy
In the HSAS documentation, (well, in the Usage spoiler in the HSAS thread) PandaMine indicated that you must null your struct members when they are no longer needed (i.e. in the onDestroy)
10-22-2008, 01:30 PM#3
GALLED
Quote:
Originally Posted by the-thingy
In the HSAS documentation, (well, in the Usage spoiler in the HSAS thread) PandaMine indicated that you must null your struct members when they are no longer needed (i.e. in the onDestroy)

Collapse JASS:
    method onDestroy takes nothing returns nothing
    local effect e 
    
        if(.Misil_End_FX!="")then
            set e = AddSpecialEffect(.Misil_End_FX,GetUnitX(.proyectil),GetUnitY(.proyectil))
            call DestroyEffectTimed(e,1.0) 
        endif
        
        if(.victim!=null)then
            call this.Impacta(.victim)
        else
            set .victim = this.Busca(.Area,GetUnitX(.proyectil),GetUnitY(.proyectil), false)
            if(.victim!=null)then
                call this.Impacta(.victim)
            endif
        endif
        
        if(.RemueveMisil)then
            call RemoveUnit(.proyectil)
        else
            if(.Spell)then
                call UnitApplyTimedLife(.proyectil,'BTLF',0.4)
            else
                call KillUnit(.proyectil)
            endif
        endif
        
        call DestroyGroup(.g)
        call DestroyGroup(.g_aux)
        call RemoveRect(.tmp_rect)
        call PauseTimer(.t)
        call DestroyTimer(.t)

        set e = null
        set .tmp_rect = null
        set .proyectil = null
        set .t = null
        set .victim = null
        set .g = null
        set .g_aux = null
        set .p = null
    endmethod

10-22-2008, 03:32 PM#4
the-thingy
Ah, my bad, didn't see the onDestroy method there
10-22-2008, 04:32 PM#5
WNxCryptic
Just out of curiosity, why are you designing a new system when there exist numerous (great) collision/missile systems?
10-22-2008, 04:37 PM#6
the-thingy
Quote:
Originally Posted by WNxCryptic
Just out of curiosity, why are you designing a new system when there exist numerous (great) collision/missile systems?
Learning? Perhaps the systems around the forum don't have the things that GALLED needs in a missile system? Perhaps he/she was just bored
10-22-2008, 05:10 PM#7
GALLED
Quote:
Originally Posted by the-thingy
Learning? Perhaps the systems around the forum don't have the things that GALLED needs in a missile system? Perhaps he/she was just bored

Yeah

BTW, please helpme.

P.D.0: Other systems don't work with HSAS, and I want learn to use HSAS.

P.D.1: I use => http://www.wc3campaigns.net/showthre...unction+DoTrue with the same fu@#ng leak.
10-22-2008, 09:29 PM#8
Gwypaas
Then HSAS isn't the problem :)

Try commenting out different parts of the spell and see how they affect your handle amount.
10-24-2008, 05:32 AM#9
GALLED
Quote:
Originally Posted by Gwypaas
Then HSAS isn't the problem :)

Try commenting out different parts of the spell and see how they affect your handle amount.

Sorry but I can't find the problem.
10-26-2008, 02:16 PM#10
GALLED
I already found leak. What happens is that I used the Shockwave for dummy spell. And when spell does not have model makes depressions in the map and when it does not have damage area, it accumulates leaks (fucking terrain deformation)