HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

stucts

01-15-2008, 02:47 AM#1
StRoNgFoE_2000
When I declare a struct and do not destroy it or assign it, does it leak any data? I can't explain without an example.. Here is some script I made for a spell called exploding arrow. In the function "ArrowCountStart" I declare the struct (immoxstuct) a possible total of 400 times, but it's not created unless certain conditions are met, or is it? Is a stuct only created when I use .create() and not when I actually declare it like "local struct data" but no "struct.create()". I put a comment near the concerned area, just scroll down to the ArrowCountStart function.

Edit: Also if anyone has time.. can a method to remove these globals be explained to me? I use the globals because I'm not sure if you can alter any data in a struct without messing something up. Like, I'm using the globals to keep track of what loop in the timer im in. So when the function ends I'm not sure if you like, set an integer to a new value if its remembered next time around.

Collapse JASS:
// Description: Charges an arrow for 4 seconds on a target unit. Every second
// the arrow will be stronger. The arrow explodes on impact, creating fire on the 
// ground dealing damage over time.

globals
    real     array  IMMOCHECK
    integer  array  IMMOLEVEL
endglobals
struct immoxstruct
    timer    t  =  CreateTimer()
    unit     v                          // Target unit.
    player   p                          // Owner of Caster.
    integer  r                          // Set level of Immolation.
    method onDestroy takes nothing returns nothing
        call FlushHandleLocals(.t)
        call PauseTimer(.t)
        call DestroyTimer(.t)
    endmethod    
endstruct
struct immoarrow
    timer    t  =  CreateTimer()
    unit     u                          // Casting unit.
    unit     v                          // Target unit.
    player   p                          // Owner of caster.
    integer  i                          // Player number.
    integer  a                          // Level of ability.
    integer  d                          // Duration.
    real     x                          // X location of caster.
    real     y                          // Y location of caster.
    effect   e                          // Special effect on caster left hand.
    effect   f                          // Special effect on caster right hand.
    static method create takes nothing returns immoarrow
        local immoarrow data = immoarrow.allocate()
        set data.u = GetSpellAbilityUnit()
        set data.v = GetSpellTargetUnit()
        set data.p = GetOwningPlayer(data.u)
        set data.i = GetPlayerId(data.p)
        set data.x = GetUnitX(data.u)
        set data.y = GetUnitY(data.u)
        set data.a = GetUnitAbilityLevel(data.u, 'A00G')
        set data.e = AddSpecialEffectTarget("Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl", data.u, "left hand") 
        set data.f = AddSpecialEffectTarget("Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl", data.u, "right hand") 
        set IMMOCHECK[data.i] = 0
        set IMMOLEVEL[data.i] = 0
        return data
    endmethod
    method onDestroy takes nothing returns nothing
        call DestroyEffect(.e)
        call DestroyEffect(.f)
        call FlushHandleLocals(.t)
        call PauseTimer(.t)
        call DestroyTimer(.t)
    endmethod    
endstruct
function ExplodingArrowCond takes nothing returns boolean
    return GetSpellAbilityId() == 'A00G'
endfunction
function ExplodingArrowEffect takes nothing returns nothing
    local timer   t        = GetExpiredTimer()
    local immoxstruct data = GetHandleInt(t, "struct")
    local integer i        = 0
    local real    x        = GetUnitX(data.v)
    local real    y        = GetUnitY(data.v)
    local unit    u
    if GetUnitAbilityLevel(data.v, 'B004') > 0 then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl", data.v, "head"))
        loop
            exitwhen i > 8
            set x = GetUnitX(data.v) + 150 * Cos((i*45) * bj_DEGTORAD)
            set y = GetUnitY(data.v) + 150 * Sin((i*45) * bj_DEGTORAD)
            set u = CreateUnit(data.p, 'h00A', x, y, 270)
            call UnitApplyTimedLife(u, 'BTLF', 5)
            call UnitAddAbility(u, data.r)
            set i = i + 1
        endloop
        set x = GetUnitX(data.v)
        set y = GetUnitY(data.v)
        set u = CreateUnit(data.p, 'h00A', x, y, 270)
        call UnitApplyTimedLife(u, 'BTLF', 5)
        call UnitAddAbility(u, data.r)
        call data.destroy()
    endif
    set u = null
    set t = null
endfunction
function ArrowCountStart takes nothing returns nothing
    local timer   t        = GetExpiredTimer()
    local immoxstruct Data // THIS IS MY CONCERN, IS THIS LEAKING?
    local immoarrow data   = GetHandleInt(t, "struct")
    local unit    u      // Unit to cast dummy.
    local integer z      // The dummy arrow.
    local integer r      // The dummy immolation.
    set IMMOCHECK[data.i] = IMMOCHECK[data.i] + .10
    if IMMOCHECK[data.i] == 1 or IMMOCHECK[data.i] == 2 or IMMOCHECK[data.i] == 3 or IMMOCHECK[data.i] == 4 then
        set IMMOLEVEL[data.i] = IMMOLEVEL[data.i] + 1
    endif
    if not(GetUnitCurrentOrder(data.u) == OrderId("drain")) or IMMOCHECK[data.i] == 4 then
        call SetUnitAnimation(data.u, "stand")
        call SetUnitTimeScale(data.u, 1)
        if GetWidgetLife(data.v) > 0 and GetWidgetLife(data.u) > 0 then
            if IMMOLEVEL[data.i] == 0 then
                set IMMOLEVEL[data.i] = 1
            endif
            if data.a == 1 then
                set z = 'A00J'
                set r = 'A00P'
            elseif data.a == 2 then
                set z = 'A00I'
                set r = 'A00O'
            elseif data.a == 3 then
                set z = 'A00H'
                set r = 'A00N'
            elseif data.a == 4 then
                set z = 'A00K'
                set r = 'A00M'
            elseif data.a == 5 then
                set z = 'A00L'
                set r = 'A00Q'
            endif
            set u = CreateUnit(data.p, 'h007', data.x, data.y, 270)
            call UnitAddAbility(u, z)
            call SetUnitAbilityLevel(u, z, IMMOLEVEL[data.i])
            call IssueTargetOrder(u, "acidbomb", data.v)
            call UnitApplyTimedLife(u, 'BTLF', 3)

        // Sets the data for when the arrow makes impact.
            set Data   = immoxstruct.create() // HERE IS WHERE I CREATE IT.
            set Data.r = r
            set Data.v = data.v
            set Data.p = data.p
            call SetHandleInt(Data.t, "struct", data)
            call TimerStart(Data.t, .01, true, function ExplodingArrowEffect)
        endif
        call data.destroy()
    endif
    set u = null
    set t = null
endfunction
function ExplodingArrowCast takes nothing returns nothing
    local immoarrow data = immoarrow.create()
    call SetHandleInt(data.t, "struct", data)
    call TriggerSleepAction(.01)
    call SetUnitAnimation(data.u, "attack")
    call TriggerSleepAction(.10)
    call SetUnitTimeScale(data.u, .05)
    call TimerStart(data.t, .10, true, function ArrowCountStart)
endfunction
function InitTrig_RangerExplodingArrow takes nothing returns nothing
    set gg_trg_RangerExplodingArrow = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_RangerExplodingArrow, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddCondition(gg_trg_RangerExplodingArrow, Condition(function ExplodingArrowCond))
    call TriggerAddAction(gg_trg_RangerExplodingArrow, function ExplodingArrowCast)
endfunction
01-15-2008, 04:19 AM#2
Zandose
Quote:
When I declare a struct and do not destroy it or assign it, does it leak any data? I can't explain without an example.. Here is some script I made for a spell called exploding arrow. In the function "ArrowCountStart" I declare the struct (immoxstuct) a possible total of 400 times, but it's not created unless certain conditions are met, or is it? Is a stuct only created when I use .create() and not when I actually declare it like "local struct data" but no "struct.create()". I put a comment near the concerned area, just scroll down to the ArrowCountStart function.
I hope I get this right. Just making a local/global for a struct doesn't make a struct. If you look at the compiled code you'll see that "local StructName somename" is changed to "local integer somename", and the integer is just used as a ?pointer? to the struct itself. I think using the StructName is just a vJASS thing?

I don't know about the second question.
01-15-2008, 08:53 PM#3
Silvenon
Not assigning it doesn't leak, not destroying does (kinda).

Struct are just acting like types (unit, player, item.....), only thing: they are not handles, they actually act like integers.

Collapse JASS:
function MyFunc takes nothing returns nothing
    local MyStruct s
endfunction

Doesn't leak, but:

Collapse JASS:
function MyFunc takes nothing returns nothing
    local MyStruct s = MyStruct.create()
    // ...
    // no s.destroy() anywhere
endfunction

Does leak, think of it like this:

Collapse JASS:
function MyFunc takes nothing returns nothing
    local group g
endfunction

Doesn't leak, but:

Collapse JASS:
function MyFunc takes nothing returns nothing
    local group g = CreateGroup()
    // ...
    // no DestroyGroup(g) anywhere
endfunction

Does leak.

So a struct is only created when you use .create(), moreover, an instance of it is created with .create().

So in your example immoxstruct would leak if the conditions are true, because it isn't destroyed anywhere.

I dont' get the second question.
01-18-2008, 10:33 AM#4
StRoNgFoE_2000
Quote:
Originally Posted by Silvenon
So in your example immoxstruct would leak if the conditions are true, because it isn't destroyed anywhere.

It should be destroyed in the function "ExplodingArrowEffect". When the missile reaches the target it checks for the buff and performs those actions, with the destroy at the bottom.. I think this is correct?

And don't worry about my second question.. I didn't know what I was talking about anyway.
01-18-2008, 06:20 PM#5
Silvenon
Quote:
It should be destroyed in the function "ExplodingArrowEffect". When the missile reaches the target it checks for the buff and performs those actions, with the destroy at the bottom.. I think this is correct?

Oh, yes, sorry. I didn't see it :)