HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Glacier Lunge Spell

01-09-2010, 04:11 AM#1
heartadriel
What's wrong with my code? The test map is attached.
The documentation for v2 is not yet available.

For the mode, only red player can choose
either:
/gg , /tb or /sb with arguments x
(/gg 25 for Greed is Good mode, 25 rounds or /sb 5 for Single Battle, 5 minutes)

No code for evade yet, but the main concern is Glacier Lunge.

The bug is, after about 2 minutes of usage (playing with 3 bots with /aion), the caster just stops (due to PauseUnit) and never resumes. It doesn't even trigger the lunge function.

Here is the code:

Collapse JASS:
scope GL initializer GL_b

globals
//Sets Constant Spell Data
private constant real Distance = 575.
private constant real Speed = 3750.
private constant real Period = 0.01
private constant real Cap = 700.
private constant real AoE = 132.
private constant real Damage = 87.
private constant real Delay = 20
private constant string FX1 = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl"
private constant string FX2 = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
private constant string FX3 = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathMissile.mdl"
private constant string FX4 = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
private constant integer EVADE = 'B004'
private constant integer DSENTENCE = 'B001'
private constant integer POWER = 'B002'
private constant integer TITAN = 'B005'
private constant integer TRAVEL = 'B006'
private constant integer DSPELL = 'A00G'

//Global Variables for the Spell

endglobals

private struct GL
//First Function Structs
unit u
unit t
real x1
real y1
integer int

//Second Function Structs
real x2
real y2
integer i1

//Third Function Structs
real x3
real y3
integer i2
endstruct

function GL_e takes nothing returns boolean
return IsUnitAliveBJ(GetFilterUnit()) and GetFilterUnit()!=bj_ghoul[1] and IsUnitInGroup(GetFilterUnit(), Heroes)
endfunction

function GL_c takes nothing returns boolean
return GetSpellAbilityId()==GLID
endfunction

function GL_push takes nothing returns nothing
//Initializes Local Variables
local timer t = GetExpiredTimer()
local GL g = GL.create()

local real x
local real y

//Initialize Timer Structs
set g = GetTimerData(t)

//Initialize Main Function
set x = GetUnitX(g.t) + g.x3
set y = GetUnitY(g.t) + g.y3
call SetUnitPosition(g.t, x, y)
call DestroyEffect(AddSpecialEffect(FX1, x, y))
set g.i2 = g.i2 - 1
if g.i2 <= 0 then
    if(not(RectContainsUnit(gg_rct_Play, g.t))) then
        call DestroyEffect(AddSpecialEffectLoc(FX4, GetUnitLoc(g.t)))
        call UnitDamageTarget(g.u, g.t, 999999, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS)
    endif
    call SetUnitPathing(g.t, true)
    call g.destroy()
    call ReleaseTimer(t)
endif
endfunction

function GL_lunge takes nothing returns nothing
//Initializes Local Variables
local GL g = GL.create()
local timer t1 = GetExpiredTimer()
local timer t2 = NewTimer()

local real finDmg
local real x1
local real y1
local real x2
local real y2
local real x3
local real y3
local real a
local real d

local group check = CreateGroup()
local unit u

local location l1
local location l2

//Initializes Timer Structs
set g = GetTimerData(t1)

//Initializes Main Function
call PauseUnit(g.u, false)
set l1 = GetUnitLoc(g.u)
set x1 = GetUnitX(g.u)+g.x2
set y1 = GetUnitY(g.u)+g.y2
call SetUnitPosition(g.u, x1, y1)
call DestroyEffect(AddSpecialEffect(FX1, x1, y1))
set bj_ghoul[1] = g.u
call GroupEnumUnitsInRangeOfLoc(check, GetUnitLoc(g.u), AoE, function GL_e)
set g.t = FirstOfGroup(check)
call DestroyGroup(check)

if not(g.t==null) then
    set x2 = GetUnitX(g.t)
    set y2 = GetUnitX(g.t)
    //Checks for Evade Buff
    if UnitHasBuffBJ(g.t, EVADE) then
        call DestroyEffect(AddSpecialEffect(FX3, x2, y2))
        call UnitRemoveBuffBJ(EVADE, g.t)
        call Miss(g.u)
        call SetUnitPositionLocFacingLocBJ(g.t, PolarProjectionBJ(GetUnitLoc(g.u), -50, GetUnitFacing(g.t)), GetUnitLoc(g.t))
        call DestroyEffect(AddSpecialEffectLoc(FX3, GetUnitLoc(g.t)))
    else
        //Checks for Buffs
        if UnitHasBuffBJ(g.u, TITAN) then
            set finDmg = (Damage + I2R(g.int * 3)) * 1.25
        else
            set finDmg = (Damage + I2R(g.int * 3))
        endif
        if UnitHasBuffBJ(g.u, DSENTENCE) then
            call UnitRemoveBuffBJ(DSENTENCE, g.u)
            set u = CreateUnit(GetOwningPlayer(g.u), DummyID, x2, y2, 0)
            call UnitApplyTimedLife(u, 'BTLF', .5)
            call UnitAddAbility(u, DSPELL)
            call IssueTargetOrder(u, "shadowstrike", g.t)
            set u = null
        endif
        if UnitHasBuffBJ(g.u, POWER) then
            set d = 1.25*(1.2*(Cap - SquareRoot((Pow((g.x1 - x2), 2))+Pow((g.y1-y2), 2))))
        else
            set d = 1.2*(Cap - SquareRoot((Pow((g.x1 - x2), 2))+Pow((g.y1-y2), 2)))
        endif
        //Resumes Function
        call Unit(g.t, I2S(R2I(finDmg)), PColor[GetConvertedPlayerId(GetOwningPlayer(g.u))])
        call UnitDamageTarget(g.u, g.t, finDmg, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS)
        call DestroyEffect(AddSpecialEffect(FX2, x2, y2))
        set l2 = PolarProjectionBJ(l1, d, GetUnitFacing(g.u))
        set x3 = GetLocationX(l2) - GetUnitX(g.t)
        set y3 = GetLocationY(l2) - GetUnitY(g.t)
        set a = Atan2(y3, x3)
        set g.i2 = R2I(d) / R2I((Speed+1000) * Period)
        set g.x3 = ((Speed + 1000) * Period) * Cos(a)
        set g.y3 = ((Speed + 1000) * Period) * Sin(a)
        call SetUnitPathing(g.u, true)
        call SetUnitPathing(g.t, false)
        call SetTimerData(t2, g)
        call TimerStart(t2, Period, true, function GL_push)
        call ReleaseTimer(t1)
        set l1 = null
        set l2 = null
    endif
else
    set g.i1 = g.i1 - 1
    if g.i1 <= 0 then
        if not(RectContainsUnit(gg_rct_Play, g.u)) then
            call DestroyEffect(AddSpecialEffectLoc(FX4, GetUnitLoc(g.u)))
            call UnitDamageTarget(g.u, g.u, 999999, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS)
        endif
        call SetUnitPathing(g.u, true)
        call g.destroy()
        call ReleaseTimer(t1)
        call ReleaseTimer(t2)
    endif
endif
endfunction

function GL_d takes nothing returns nothing
//Initializes Local Variables
local GL g = GL.create()
local timer t1 = GetExpiredTimer()
local timer t2 = NewTimer()
local real x
local real y
local real a
local real d
local location l1
local location l2

//Initializes Timer Structs
set g = GetTimerData(t1)

//Initializes Main Data
set l1 = GetUnitLoc(g.u)
set a = GetUnitFacing(g.u)
set l2 = PolarProjectionBJ(l1, Distance, a)
set x = GetLocationX(l2) - GetLocationX(l1)
set y = GetLocationY(l2) - GetLocationY(l1)
call RemoveLocation(l1)
call RemoveLocation(l2)

//Checks for buffs
if UnitHasBuffBJ(g.u, TRAVEL) then
    set d = Distance * 1.25
else
    set d = Distance
endif

//Resume Function
set g.i1 = R2I(d) / R2I(Speed * Period)
set a  = Atan2(y, x)
set g.x2 = (Speed*Period) * Cos(a)
set g.y2 = (Speed*Period) * Sin(a)

//Initializes Next Timer
call SetTimerData(t2, g)
call TimerStart(t2, Period, true, function GL_lunge)

//Destroys Timers
call ReleaseTimer(t1)
set t1 = null
set t2 = null
endfunction

function GL_a takes nothing returns nothing
//Initializes Local Variables
local GL g = GL.create()
local timer t = NewTimer()
local integer i

//Initializes the Timer Structs
set i = GetUnitIndex(GetTriggerUnit())
set g = i
call SetTimerData(t, g)

//Initializes Caster Information
set g.u = GetTriggerUnit()
set g.int = GetHeroInt(g.u, true)
set g.x1 = GetUnitX(g.u)
set g.y1 = GetUnitY(g.u)
call PauseUnit(g.u, true)
call SetUnitPathing(g.u, false)
call SetUnitAnimation(g.u, "attack")

//Starts the Timer
call TimerStart(t, Delay/100, false, function GL_d)
set t = null

endfunction

function GL_b takes nothing returns nothing
local trigger T = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(T, Condition(function GL_c))
call TriggerAddAction(T, function GL_a)
set T = null
endfunction
endscope

Any help will be appreciated. Thanks!
01-09-2010, 10:34 PM#2
blanc_dummy
you protect your map. we can't see the triggers..

and it seems you reach the struct limit, because you always create new struct every callback function, but never destroy it.

in GL_lunge, and GL_push you create new struct

Collapse JASS:
local GL g = GL.create()

you should do this:

Collapse JASS:
local timer t1 = GetExpiredTimer()
local GL g = GL(GetTimerData(t1))

instead create the new one.
01-10-2010, 12:01 AM#3
heartadriel
I've fixed it already. Anyway, thanks for your reply :)