• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Reset/clear/null onDestroy?

Status
Not open for further replies.
Level 15
Joined
Nov 30, 2007
Messages
1,202
When destroying an instance of a struct are the variables inside also automatically nulled or what happens to them?
JASS:
        method onDestory takes nothing returns nothing
            if .target != null then
                call GroupRemoveUnit(.active, .target) // static
                set .target = null
            else
                call GroupRemoveUnit(.active, .flame) // static
                set .flame = null
            endif
            set .count = .count - 1 // static 
            set .stack_dmg = 0
            set .stack_time = 0
            call BJDebugMsg("destroyed")
        endmethod

for some reason the above doesn't function properly when I call it. .count is not reduced for example. The debug msg is never displayed.

JASS:
call fire[i].destroy()
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
onDestroy is only called in structs which do not extend array
.
Example: struct Example will evaluate onDestroy when destroy() is called.
Example: struct Example extends array destroy has to be written by yourself, onDestroy is not evaluated even if written in to code.

Nothing gets nulled automatically.
 
Last edited:
Level 15
Joined
Nov 30, 2007
Messages
1,202
onDestroy is only called in structs which do not extend array
.
Example: struct Example will evaluate onDestroy when destroy() is called.
Example: struct Example extends array destroy has be written by yourself, onDestroy is not evaluated even if written in to code.

Nothing gets nulled automatically.

I have not used extend array. It keeps counting even when it should've been removed.

Also what i mean is, if i destroy fire and then later create a new fire will the integers, units, etc. declared inside the old still be there?

JASS:
struct Fire 
        unit flame = null
        unit target = null
        real stack_dmg = 0
        integer stack_time = 0
        static integer count = 0
        static group active = CreateGroup()
        static trigger trgPeriodic = CreateTrigger()
        
        method stack takes real damage returns nothing
            set .stack_dmg = .stack_dmg + damage 
            set stack_time = STACK_DURATION
        endmethod
        
        static method create takes nothing returns Fire
            local thistype f = .allocate()
            return f
        endmethod
        
        method reset takes nothing returns nothing  // Temporary Solution
            call GroupRemoveUnit(.active, .target) 
            set .target = null
            set .count = .count - 1 
            set .stack_dmg = 0
            set .stack_time = 0
            call .deallocate()
        endmethod
        
        static method forLoop takes nothing returns nothing 
            local unit u = GetEnumUnit()
            local integer i = GetUnitUserData(u)
            set fire[i].stack_time = fire[i].stack_time - 1
            call BJDebugMsg(I2S(fire[i].stack_time) + " " + R2S(fire[i].stack_dmg))
            if fire[i].stack_time == 0 then
                call fire[i].reset()
                if .count == 0 then
                    call DisableTrigger(.trgPeriodic)
                    call DD.refresh()
                endif
            endif
            set u = null
        endmethod
        
        static method periodic takes nothing returns boolean
            call ForGroup(.active, function Fire.forLoop)
            return false 
        endmethod 
        
        static method onInit takes nothing returns nothing
            call TriggerRegisterTimerEvent(trgPeriodic, 1.0, true)
            call TriggerAddCondition(trgPeriodic, Condition(function Fire.periodic))
            call DisableTrigger(trgPeriodic)
        endmethod
    endstruct
 
Last edited:
Level 15
Joined
Nov 30, 2007
Messages
1,202
You can write a method called destroy, read the documentation.
The issue is your typo i guess.

Idk,
JASS:
method reset takes nothing returns nothing  // Temporary Solution
            call GroupRemoveUnit(.active, .target) 
            set .target = null
            set .count = .count - 1 
            set .stack_dmg = 0
            set .stack_time = 0
            call .destroy()
        endmethod

I get the error message Double free of type: Fire
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
JASS:
method destroy takes nothing returns nothing
   call GroupRemoveUnit(.active, .target) 
   set .target = null
   set .count = .count - 1 
   set .stack_dmg = 0
   set .stack_time = 0
   call .deallocate()
endmethod

Still doubly free of type: Fire, I'm sure its because you can't destroy it inside itself.

I mean... call function fire.SomeFunction inside fire.SomeFunction call .deallocate()

its a bit sketchy? :p
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
Well, show me the code where you call the destroy method then, i can't guess what you are doing.

I did. It's basically a periodic function calling the forLoop inside the struct as seen above. Updated the post with the whole struct. http://www.hiveworkshop.com/forums/2687250-post3.html

Outside of this struct there are two things happening 1) On attacking the unit gets added to damage detection. 2) if fire == null an instance is created. If Fire.count == 0 the periodic function is activated inside the struct.

Inside its supposed to remove fire when fire.stack_time == 0 and next time I attack this unit its supposed to re-create the instance again. But this last part doesn't happen as it is already created.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Well, it's obvious that we don't have the full code, for example the method forloop is not called anywhere.
The vjass debug is not accurate, double free could also mean you are trying to destroy an invalid struct instance (not allocated or just invalid number not beetween 1 and 8190 both included)
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
Fine here is the whole thing.

JASS:
library FireSystem initializer Init

    globals
        private constant integer STACK_DURATION     = 10
        private constant integer FIRE_DMG           = 'A000'
        Fire array fire
    endglobals


    private struct DD
        static group gr = CreateGroup()
        static trigger trg = null
        static code func
        
        static method add takes unit u returns nothing 
            if not IsUnitInGroup(u, .gr) then
                call GroupAddUnit(.gr, u)
                call TriggerRegisterUnitEvent(.trg, u, EVENT_UNIT_DAMAGED)
            endif
        endmethod
        
        static method refresh takes nothing returns nothing
            if .trg != null then
                call DestroyTrigger(.trg)
            endif
            set .trg = CreateTrigger()
            call TriggerAddCondition(.trg, Condition(.func))
            call GroupClear(.gr)
            call BJDebugMsg("refreshed")
        endmethod
    endstruct
    
    struct Fire 
        unit flame = null
        unit target = null
        real stack_dmg = 0
        integer stack_time = 0
        static integer count = 0
        static group active = CreateGroup()
        static trigger trgPeriodic = CreateTrigger()
        
        method stack takes real damage returns nothing
            set .stack_dmg = .stack_dmg + damage 
            set stack_time = STACK_DURATION
        endmethod
        
        static method create takes nothing returns Fire
            local thistype f = .allocate()
            return f
        endmethod
        
        method reset takes nothing returns nothing  // Temporary Solution
            call GroupRemoveUnit(.active, .target) 
            set .target = null
            set .count = .count - 1 
            set .stack_dmg = 0
            set .stack_time = 0
            call .deallocate()
        endmethod
        
        static method forLoop takes nothing returns nothing 
            local unit u = GetEnumUnit()
            local integer i = GetUnitUserData(u)
            set fire[i].stack_time = fire[i].stack_time - 1
            call BJDebugMsg(I2S(fire[i].stack_time) + " " + R2S(fire[i].stack_dmg))
            if fire[i].stack_time == 0 then
                call fire[i].reset()
                if .count == 0 then
                    call DisableTrigger(.trgPeriodic)
                    call DD.refresh()
                endif
            endif
            set u = null
        endmethod
        
        static method periodic takes nothing returns boolean
            call ForGroup(.active, function Fire.forLoop)
            return false 
        endmethod 
        
        static method onInit takes nothing returns nothing
            call TriggerRegisterTimerEvent(trgPeriodic, 1.0, true)
            call TriggerAddCondition(trgPeriodic, Condition(function Fire.periodic))
            call DisableTrigger(trgPeriodic)
        endmethod
    endstruct

    
    
    
    private function OnDamage takes nothing returns boolean
        local unit target = GetTriggerUnit()
        local unit source = GetEventDamageSource()
        local real damage = GetEventDamage()
        local integer i = GetUnitUserData(target)
        
        if fire[i].flame == null then
            call fire[i].stack(damage)
        endif
        return false 
    endfunction

    private function OnAttackFilter takes unit attacked, unit attacker returns boolean
        return IsUnitType(attacked, UNIT_TYPE_STRUCTURE) and GetUnitAbilityLevel(attacker, FIRE_DMG) > 0 
    endfunction
    
    private function OnAttack takes nothing returns boolean
        local unit attacked = GetTriggerUnit()
        local unit attacker = GetAttacker()
        local integer i = GetUnitUserData(attacked)
        
        if OnAttackFilter(attacked, attacker) then 
        
            if fire[i] == null then 
                set fire[i] = Fire.create()
                call BJDebugMsg("null")
            endif
            
            if fire[i].flame == null and fire[i].target == null then
                if Fire.count == 0 then
                    call EnableTrigger(Fire.trgPeriodic)
                endif
                
                call DD.add(attacked)
                set Fire.count = Fire.count + 1 
                call GroupAddUnit(Fire.active, attacked)
                set fire[i].target = attacked
                
            endif
        endif
        
        return false
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger t1 = CreateTrigger()
        local integer i = 0
        loop
            call TriggerRegisterPlayerUnitEvent(t1, Player(i), EVENT_PLAYER_UNIT_ATTACKED, null)
            set i = i + 1
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t1, Condition(function OnAttack))
        set DD.func = function OnDamage 
        call DD.refresh()
    endfunction
endlibrary
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
Your code is way too much splitted for me, it's hard to follow without running it, so sorry i give up.

I understand. Thanks for trying.

To shorten it all down. When I attack a unit fire is created. When i stop attacking it and the STACK_DURATION expires. I want it to be destroyed and when I re-attack that unit I want fire to be null again.
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
fire[i] == null should not compile as fire is of type integer. It's an invalid comparison.

When a unit is removed from the game, it is no longer part of a group it was added.

Why do you write create in struct Fire, it is automatically generated by the JassHelper for structs.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Not really true, null is valid for all jass types, for an integer it's the same as 0.

Also when an unit is removed of the game it's not removed of a group, we call them ghost units.
Hell, that's the main reason why i wrote UnitLL.

And about create method it's true, but that doesn't really matter that much.
 
Status
Not open for further replies.
Top