Hashtable Problems?

Jonnycakes

New Member
Reaction score
6
Hi, I am working on a skill that is for some reason STILL not working correctly...I think it has to do with the way I am indexing hashtables, but I can't seem to find what is going wrong.

This is a skill that is supposed to spawn a dummy wisp (with vision and true sight) above a tree when cast (the skill is based off of eat tree). When 3 wisps are already there and a 4th one is created, the 1st wisp is then destroyed. This works absolutely fine until the 6th time this ability is cast-then the old wisps stop disappearing. Why is this happening?

JASS:
scope wards initializer init

globals
    private integer wisps=0
    private hashtable h=InitHashtable()
    private unit array wards
endglobals

private function conditions takes nothing returns boolean
    return GetSpellAbilityId()=='A00N'
endfunction

private function destroy takes nothing returns nothing
    local integer i=GetHandleId(GetTriggerDestructable())
    local unit u=LoadUnitHandle(h, i, 0)
    local integer x=wisps-2
    
    set i=GetHandleId(u)
    
    call KillUnit(u)
    set wisps=wisps-1
    call FlushChildHashtable(h, i)
    call DestroyTrigger(GetTriggeringTrigger())
    set u=null
endfunction

private function actions takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local integer id=GetHandleId(u)
    local destructable tree=GetSpellTargetDestructable()
    local player p=GetOwningPlayer(u)
    local unit v=CreateUnit(p, 'h008', GetDestructableX(tree), GetDestructableY(tree), 0)
    local trigger t=CreateTrigger()
    local integer x=0
    
    call IssueImmediateOrder(GetTriggerUnit(), "stop")
    
    if wisps==3 then
    
        call DestroyTrigger(LoadTriggerHandle(h, GetHandleId(wards[0]), 0))
        call KillUnit(wards[0])
        loop
        
            exitwhen x==1
            set wards[x]=wards[x+1]
            set x=x+1
            
        endloop
        set wisps=wisps-1
        
    endif
    
    call BJDebugMsg("created..."+I2S(wisps+1))
    
    set wisps=wisps+1
    set wards[wisps-1]=v
    call RemoveSavedHandle(h, GetHandleId(tree), 0)
    call SaveUnitHandle(h, GetHandleId(tree), 0, v)
    call TriggerAddAction(t, function destroy)
    call TriggerRegisterDeathEvent(t, tree)
    call SaveTriggerHandle(h, GetHandleId(v), 0, t)
    
    set t=null
    set tree=null
    set u=null
    set v=null
    set p=null
endfunction
//===========================================================================
private function init takes nothing returns nothing
    local trigger t=CreateTrigger()
    local integer x=0
    call TriggerAddAction(t, function actions)
    call TriggerAddCondition(t, Condition(function conditions))
    loop
        exitwhen x==12
        call TriggerRegisterPlayerUnitEvent(t, Player(x), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set x=x+1
    endloop
    set t=null
endfunction

endscope
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Don't add action on dynamic trigger, else the handle stack will get corrupted(>1 handle has same handle it). You can only add condition to it.
 

Jonnycakes

New Member
Reaction score
6
By dynamic trigger do you mean a trigger created by another trigger's action function? (or do you mean a trigger that will be destroyed later?) Either way, I tested out changing the actions function into a conditions function that did everything the actions function did and returned false-I got the same effect. For the 6th ward it stops working. Could you clarify what you mean?
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Dynamic trigger -> Triggers that created and destroyed in game.
Static trigger -> Basically it is known as trigger for initialization.
 

Jonnycakes

New Member
Reaction score
6
Thanks for the help-it prompted me to look up dynamic triggers and how to properly destroy them. I think I got it right, but I'm not sure. Anyway, I rewrote the trigger to solve the problem (and make it multi-player instanceable):

New, properly working trigger:
JASS:
scope wards initializer init

private struct data
    player owner
    destructable array tree[2]
    trigger array trig[2]
    unit array wisp[2]
    integer x=0
    
    method make takes destructable tree returns nothing
        call SetDestructableMaxLife(tree, 51+GetPlayerId(.owner))
        set .wisp[.x]=CreateUnit(.owner, 'h008', GetDestructableX(tree), GetDestructableY(tree), 0)
        set .tree[.x]=tree
        set .trig[.x]=CreateTrigger()
        call TriggerRegisterDeathEvent(.trig[.x], tree)
        set .x=.x+1
        call SetSoundPosition(gg_snd_WispReady1, GetDestructableX(tree), GetDestructableY(tree), 200)
        call StartSound(gg_snd_WispReady1)
    endmethod
    
    method kill takes integer x returns nothing
        local integer a=x
        call SetDestructableMaxLife(.tree[x], 50)
        call KillUnit(.wisp[x])
        call DisableTrigger(.trig[x])
        call DestroyTrigger(.trig[x])
        set .wisp[x]=null
        set .tree[x]=null
        set .trig[x]=null
        set .x=.x-1
    endmethod
    
endstruct

globals
    private hashtable h=InitHashtable()
    private data array d
endglobals

private function conditionsspell takes nothing returns boolean
    return GetSpellAbilityId()=='A00N'
endfunction

private function conditions takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit())=='H001'
endfunction

private function destroy takes nothing returns boolean
    local destructable tree=GetTriggerDestructable()
    local integer i=LoadInteger(h, GetHandleId(tree), 0)
    local integer pid=R2I(GetDestructableMaxLife(tree))-51
    local integer a
    call d[pid].kill(i)
    call FlushChildHashtable(h, GetHandleId(tree))
    set a=i
    loop
        exitwhen a==d[pid].x
        set d[pid].wisp[a]=d[pid].wisp[a+1]
        set d[pid].trig[a]=d[pid].trig[a+1]
        set d[pid].tree[a]=d[pid].tree[a+1]
        call SaveInteger(h, GetHandleId(d[pid].tree[a]), 0, a)
        set a=a+1
    endloop
    set tree=null
    return false
endfunction

private function actionsagain takes nothing returns nothing
    local destructable tree=GetSpellTargetDestructable()
    local integer maxlife=R2I(GetDestructableMaxLife(tree))
    local unit u=GetTriggerUnit()
    local integer pid=GetPlayerId(GetOwningPlayer(u))
    local integer a
    
    call IssueImmediateOrder(u, "stop")
    
    if maxlife==51+pid then
        call StartSound(gg_snd_Error)
    else
        if maxlife!=50 then
            call d[maxlife-51].kill(LoadInteger(h, GetHandleId(tree), 0))
            set a=LoadInteger(h, GetHandleId(tree), 0)
            loop
                exitwhen a==d[maxlife-51].x
                set d[maxlife-51].wisp[a]=d[maxlife-51].wisp[a+1]
                set d[maxlife-51].trig[a]=d[maxlife-51].trig[a+1]
                set d[maxlife-51].tree[a]=d[maxlife-51].tree[a+1]
                call SaveInteger(h, GetHandleId(d[maxlife-51].tree[a]), 0, a)
                set a=a+1
            endloop
            call FlushChildHashtable(h, GetHandleId(tree))
        endif
        call d[pid].make(tree)
        call SaveInteger(h, GetHandleId(tree), 0, d[pid].x-1)
        call TriggerAddCondition(d[pid].trig[d[pid].x-1], Condition(function destroy))
        if d[pid].x==4 then
            call FlushChildHashtable(h, GetHandleId(d[pid].tree[0]))
            call d[pid].kill(0)
            set a=0
            loop
                exitwhen a==d[pid].x
                set d[maxlife-51].wisp[a]=d[maxlife-51].wisp[a+1]
                set d[maxlife-51].trig[a]=d[maxlife-51].trig[a+1]
                set d[maxlife-51].tree[a]=d[maxlife-51].tree[a+1]
                call SaveInteger(h, GetHandleId(d[maxlife-51].tree[a]), 0, a)
                set a=a+1
            endloop
        endif
    endif
        
    set u=null
    set tree=null
endfunction

private function actions takes nothing returns nothing
    local trigger t=CreateTrigger()
    local player p=GetOwningPlayer(GetTriggerUnit())
    local integer i=GetPlayerId(p)
    call TriggerAddAction(t, function actionsagain)
    call TriggerAddCondition(t, Condition(function conditionsspell))
    set d<i>=data.create()
    set d<i>.owner=p
    call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
    set t=null
    set p=null
endfunction
//===========================================================================
private function init takes nothing returns nothing
    local trigger t=CreateTrigger()
    local region r=CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerAddAction(t, function actions)
    call TriggerRegisterEnterRegion(t, r, Filter(function conditions))
    set t=null
    set r=null
endfunction

endscope</i></i>
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top