Projectile Ability Crashes

Weyrling

New Member
Reaction score
25
The Setup code:
JASS:
function H2I takes handle h returns integer
    return h
    return 0
endfunction
function SetUnitZ takes unit u, real z returns nothing
    local location l = GetUnitLoc(u)
    local real lz = GetLocationZ(l)
    call SetUnitFlyHeight(u,z-lz,99999)
    call RemoveLocation(l)
endfunction
function CountGroup takes nothing returns nothing
    set udg_Integer = udg_Integer+1
endfunction
function IsEnemyOf takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true)
endfunction
function CheckforEnemies takes unit u, real dist returns integer
    local location l = GetUnitLoc(u)
    local group g = GetUnitsInRangeOfLocMatching(dist,l,Condition(function IsEnemyOf))
    call ForGroup(g,function CountGroup)
    call RemoveLocation(l)
    return udg_Integer
endfunction
// ===========================
function LocalVars takes nothing returns gamecache
    if udg_Cache == null then
               call FlushGameCache(InitGameCache("somename"))
               set udg_Cache = InitGameCache("somename")
    endif
    return udg_Cache
endfunction

function SetHandleHandle takes handle subject, string name, handle value returns nothing
    if value==null then
        call FlushStoredInteger(LocalVars(),I2S(H2I(subject)),name)
    else
        call StoreInteger(LocalVars(), I2S(H2I(subject)), name, H2I(value))
    endif
endfunction

function SetHandleInt takes handle subject, string name, integer value returns nothing
    if value==0 then
        call FlushStoredInteger(LocalVars(),I2S(H2I(subject)),name)
    else
        call StoreInteger(LocalVars(), I2S(H2I(subject)), name, value)
    endif
endfunction

function SetHandleBoolean takes handle subject, string name, boolean value returns nothing
    if value==false then
        call FlushStoredBoolean(LocalVars(),I2S(H2I(subject)),name)
    else
        call StoreBoolean(LocalVars(), I2S(H2I(subject)), name, value)
    endif
endfunction

function SetHandleReal takes handle subject, string name, real value returns nothing
    if value==0 then
        call FlushStoredReal(LocalVars(), I2S(H2I(subject)), name)
    else
        call StoreReal(LocalVars(), I2S(H2I(subject)), name, value)
    endif
endfunction

function SetHandleString takes handle subject, string name, string value returns nothing
    if value==null then
        call FlushStoredString(LocalVars(), I2S(H2I(subject)), name)
    else
        call StoreString(LocalVars(), I2S(H2I(subject)), name, value)
    endif
endfunction

function GetHandleHandle takes handle subject, string name returns handle
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleInt takes handle subject, string name returns integer
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleBoolean takes handle subject, string name returns boolean
    return GetStoredBoolean(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleReal takes handle subject, string name returns real
    return GetStoredReal(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleString takes handle subject, string name returns string
    return GetStoredString(LocalVars(), I2S(H2I(subject)), name)
endfunction

function GetHandleUnit takes handle subject, string name returns unit
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleLocation takes handle subject, string name returns location
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleTimer takes handle subject, string name returns timer
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleTrigger takes handle subject, string name returns trigger
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleEffect takes handle subject, string name returns effect
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleGroup takes handle subject, string name returns group
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleLightning takes handle subject, string name returns lightning
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction
function GetHandleWidget takes handle subject, string name returns widget
    return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
    return null
endfunction

function FlushHandleLocals takes handle subject returns nothing
    call FlushStoredMission(LocalVars(), I2S(H2I(subject)) )
endfunction
The Projectile Spawn and Move
JASS:
function Projectile_Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = GetHandleUnit(t,"u")
    local real xm = GetHandleReal(t,"xm")
    local real ym = GetHandleReal(t,"ym")
    local real zm = GetHandleReal(t,"zm")
    local real xn = GetUnitX(u)+xm
    local real yn = GetUnitY(u)+ym
    local real zn = GetUnitFlyHeight(u)+zm
    local integer i = GetHandleInt(t,"i")
    local integer en = CheckforEnemies(u,100)
    set udg_Integer = 0
    set en = 0
    if (en > 0) then
        call RemoveUnit(u)
        call PauseTimer(t)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        call UnitDamagePointLoc(u,0,150,GetUnitLoc(u),150,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL)
        call DisplayTextToPlayer(GetOwningPlayer(u),0,0,"DmgProjTrig")
    endif
    if (GetUnitFlyHeight(u) == 0) then
        call RemoveUnit(u)
        call PauseTimer(t)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    endif
    if (i <= 10) then
        call SetUnitX(u,xn)
        call SetUnitY(u,yn)
        call SetUnitZ(u,zn)
    else
        call RemoveUnit(u)
        call PauseTimer(t)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    endif
    set i = i+1
endfunction
function Spawn_Projectile takes unit c, location T, integer P returns nothing
    local timer t = CreateTimer()
    local location l = GetUnitLoc(c)
    local real a = AngleBetweenPoints(l,T)
    local location s = PolarProjectionBJ(l,200,a)
    local unit u = CreateUnitAtLoc(GetOwningPlayer(c),P,s,0)
    local real x1 = GetLocationX(l)
    local real y1 = GetLocationY(l)
    local real z1 = GetUnitFlyHeight(u)+GetLocationZ(GetUnitLoc(u))
    local real x2 = GetLocationX(T)
    local real y2 = GetLocationY(T)
    local real z2 = (GetLocationZ(T)+50)
    local real xm = x2-x1/10
    local real ym = y2-y1/10
    local real zm = z2-z1/10
    if (DistanceBetweenPoints(l,T)>(500+GetHeroStr(c,true) * 5)) then
        set T = PolarProjectionBJ(l,(500+GetHeroStr(c,true)*5),AngleBetweenPoints(l,T))
        set x2 = GetLocationX(T)
        set y2 = GetLocationY(T)
        set z2 = (GetLocationZ(T)+50)
    endif
    call SetUnitFlyHeight(u,GetUnitFlyHeight(c)+50,99999)
    call SetHandleHandle(t,"u",u)
    call SetHandleReal(t,"xm",xm)
    call SetHandleReal(t,"ym",ym)
    call SetHandleReal(t,"zm",zm)
    call SetHandleInt(t,"i",0)
    call TimerStart(t,.1,true,function Projectile_Move)
    call RemoveLocation(l)
    call RemoveLocation(s)
endfunction
The effect:
It spawns the projectile, freeze-lags for about 2 seconds, then crashes.
 

Builder Bob

Live free or don't
Reaction score
249
It spawns the projectile, freeze-lags for about 2 seconds, then crashes.
This description sounds like an infinite loop, but I couldn't find any.

call SetHandleHandle(t,"u",u)
changing this to SetHandleUnit() might help. (and making the SetHandleUnit() function of course)
 

darkbeer

Beer is Good!
Reaction score
84
and again: you need to null locals, else they will leak ....

i checked your setup code (your part) in your other post, also moving units wont look very smooth with a 0.1 sec periode, use 0.03 or 0.04 if you want it to look good :)

JASS:
function Projectile_Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = GetHandleUnit(t,"u")
    local real xm = GetHandleReal(t,"xm")
    local real ym = GetHandleReal(t,"ym")
    local real zm = GetHandleReal(t,"zm")
    local real xn = GetUnitX(u)+xm
    local real yn = GetUnitY(u)+ym
    local real zn = GetUnitFlyHeight(u)+zm
    local integer i = GetHandleInt(t,"i")
    local integer en = CheckforEnemies(u,100)
    set udg_Integer = 0
    //set en = 0 this way en will never be greater 0 ^^

    if (en > 0) then
        call RemoveUnit(u)
        call PauseTimer(t)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        call UnitDamagePointLoc(u,0,150,GetUnitLoc(u),150,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL) // will leak a location
        call DisplayTextToPlayer(GetOwningPlayer(u),0,0,"DmgProjTrig")
 
    elseif (GetUnitFlyHeight(u) == 0) then // no need to do this when unit is already removed
        call RemoveUnit(u)
        call PauseTimer(t)
        call FlushHandleLocals(t)
        call DestroyTimer(t)

    elseif (i <= 10) then  // the unit will just move about 1 sec?
        call SetUnitX(u,xn)
        call SetUnitY(u,yn)
        call SetUnitZ(u,zn)
    else
        call RemoveUnit(u)
        call PauseTimer(t)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    endif

    set i = i+1
    call SetHandleInt(t, "i", i ) // you forgot this ^^ i think

// nulling again ....
    set t = null
    set u = null

endfunction

function Spawn_Projectile takes unit c, location T, integer P returns nothing
    local timer t = CreateTimer()
    local location l = GetUnitLoc(c)
    local real a = AngleBetweenPoints(l,T)
    local location s = PolarProjectionBJ(l,200,a)
    local unit u = CreateUnitAtLoc(GetOwningPlayer(c),P,s,0)
    local real x1 = GetLocationX(l)
    local real y1 = GetLocationY(l)
    local real z1 = GetUnitFlyHeight(u)+GetLocationZ(GetUnitLoc(u))
    local real x2 = GetLocationX(T)
    local real y2 = GetLocationY(T)
    local real z2 = (GetLocationZ(T)+50)
    local real xm = x2-x1/10
    local real ym = y2-y1/10
    local real zm = z2-z1/10

    if (DistanceBetweenPoints(l,T)>(500+GetHeroStr(c,true) * 5)) then
        set T = PolarProjectionBJ(l,(500+GetHeroStr(c,true)*5),AngleBetweenPoints(l,T))
        set x2 = GetLocationX(T)
        set y2 = GetLocationY(T)
        set z2 = (GetLocationZ(T)+50)
    endif

    call SetUnitFlyHeight(u,GetUnitFlyHeight(c)+50,99999)
    call SetHandleHandle(t,"u",u)
    call SetHandleReal(t,"xm",xm)
    call SetHandleReal(t,"ym",ym)
    call SetHandleReal(t,"zm",zm)
    call SetHandleInt(t,"i",0)
    call TimerStart(t, .1, true,function Projectile_Move)

    call RemoveLocation(l)
    call RemoveLocation(s)

    set l = null
    set s = null
    set t = null
    set u = null
endfunction


and you ever thought of moveing to structs?, will make your code much simpler and easier to read.

this is just a little optimization, check if the unit is really passed as builder_bob said.
 

Builder Bob

Live free or don't
Reaction score
249
I did some testing and found some things that can be a cause to your problem.

Code:
local integer en = CheckforEnemies(u,100)
set udg_Integer = 0

CheckforEnemies requires udg_Integer to be 0 to function properly, so they come in the wrong order. Change it to

Code:
local integer en
set udg_Integer = 0
en = CheckforEnemies(u,100)
---


Code:
local real xm = x2-x1/10
local real ym = y2-y1/10
local real zm = z2-z1/10

I think you meant to do the substraction before the division. Else the direction of the projectile will be wrong. Change to

Code:
local real xm = (x2-x1)/10
local real ym = (y2-y1)/10
local real zm = (z2-z1)/10

I think this is the real cause of the problem. Since this messes up where the projectile will go, it can get out of map bounds, crashing the game.
---


Code:
function IsEnemyOf takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true)
endfunction

GetTriggerUnit() returns null in this function. It did in my testing at least. Make a global unit variable and set it in the function CheckforEnemies before doing GetUnitsInRange.

IsEnemyOf will include dead units by the way. You might want to fix that by checking the filter unit's life.
---


darkbeer covered some other things you might want to look at. Especially the part about call SetHandleInt(t, "i", i )

I tested if call SetHandleHandle(t,"u",u) would save the unit correctly, and actually it did, so I don't think you need to change that after all.


Good luck
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top