• 🏆 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!

[vJASS] Trigger Handle ID?

Status
Not open for further replies.
Level 15
Joined
Nov 30, 2007
Messages
1,202
Why does the handle id vary between what it is when you create the trigger and when it is fired:

JASS:
local trigger t = CreateTrigger()
set id1 = GetHandleId(t)

and when you later use it:

JASS:
set id2 = GetHandleId(GetTriggeringTrigger())

Is there any way to save struct reference to triggers if table[GetHandleId(GetTriggeringTrigger())] does not work?
 
It seems to work correctly for me.
JASS:
struct s

private static method DisplayHandleId takes handle h returns nothing
    call BJDebugMsg(I2S(GetHandleId(h)))
endmethod

private static method action takes nothing returns nothing
    call DisplayHandleId(GetTriggeringTrigger())
endmethod

private static method onInit takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerAddAction(t, function thistype.action)
    call DisplayHandleId(t)
    call TriggerExecute(t)
endmethod

endstruct
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
It seems to work correctly for me.
JASS:
struct s

private static method DisplayHandleId takes handle h returns nothing
    call BJDebugMsg(I2S(GetHandleId(h)))
endmethod

private static method action takes nothing returns nothing
    call DisplayHandleId(GetTriggeringTrigger())
endmethod

private static method onInit takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerAddAction(t, function thistype.action)
    call DisplayHandleId(t)
    call TriggerExecute(t)
endmethod

endstruct

I can't get it to work at all and the only difference i can see is the Execute call?

This is what happens when two units are created ontop of eachother and triggering collision detection for both, as you can see same trigger id is found and struct is null.
View attachment 313469

What I was trying to do:

JASS:
scope Test
  
    struct S
  
        private static Table table
        private static IntArrayList list
        private unit u
        private trigger trg
      
        static method create takes nothing returns thistype
            local thistype this = .allocate()
            local real x = GetLocationX(GetRectCenter(gg_rct_StartZone))
            local real y = GetLocationY(GetRectCenter(gg_rct_StartZone))
            set this.trg = CreateTrigger()
            set this.u = CreateUnit(Player(0), 'hpea', x, y, 0)
            call TriggerRegisterUnitInRangeSimple(this.trg, 80., this.u)
            call TriggerAddAction(this.trg, function thistype.onCollision)
            call BJDebugMsg("Created id: " + I2S(GetHandleId(this.trg)))
            set table[GetHandleId(this.trg)] = this
            call thistype.list.add(0, this)
            return this
        endmethod
      
        static method getStruct takes trigger t returns thistype
            local integer i = 0
            local thistype this
            loop
                exitwhen i == thistype.list.size()
                set this = thistype.list[i]
                if (this.trg == t) then
                    return this
                endif
                set i = i + 1
            endloop
            return 0
        endmethod
        private static method onCollision takes nothing returns nothing
            local trigger t = GetTriggeringTrigger()
            local integer id = GetHandleId(t)
            local thistype this  = getStruct(t) //= table[id]
            call BJDebugMsg("trigger id: " + I2S(id))
            if (this == 0) then
                call BJDebugMsg("NULL")
            else
                call KillUnit(this.u)
            endif
            set t = null
        endmethod
      
        static method setup takes nothing returns nothing
            set thistype.table = Table.create()
            set list = IntArrayList.create()
            call thistype.create()
            call thistype.create()
        endmethod
      
        static method onInit takes nothing returns nothing
            local timer t = CreateTimer()
            call TimerStart(t, 0.1, false, function thistype.setup)
        endmethod
  
    endstruct
endscope


I wrote a work around library, feedback?
JASS:
library Collision2D uses Table 
    globals 
        private constant real INTERVAL = 0.03
        private unit tempUnit
        private Collision2D enum
        private Table table
        private unit lastSourceUnitCol
        private unit lastLeavingUnitCol
        private unit lastEnteringUnitCol
    endglobals
   
    private function Distance takes real x1, real y1, real x2, real y2 returns real
        return SquareRoot(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)))
    endfunction
   
    function GetCollisionSource takes nothing returns unit 
        return lastSourceUnitCol
    endfunction
       
    function GetCollisionLeavingUnit takes nothing returns unit 
        return lastLeavingUnitCol
    endfunction
   
    function GetCollisionEnteringUnit takes nothing returns unit 
        return lastEnteringUnitCol
    endfunction
   
    struct Collision2D
        private timer t 
        private group withinGroup
        unit u 
        real range
        trigger trgEnter
        trigger trgLeave
       
        static method create takes unit u, real range returns thistype 
            local thistype this = .allocate()
            set this.u = u
            set this.range = range
            set this.t = CreateTimer()
            set this.withinGroup = CreateGroup()
            call TimerStart(this.t, INTERVAL, true, function thistype.update)
            set table[GetHandleId(this.t)] = this
            return this
        endmethod
       
        method destroy takes nothing returns nothing 
            call table.remove(GetHandleId(.t))
            set .u = null 
            call PauseTimer(.t)
            call DestroyTimer(.t)
            call DestroyGroup(.withinGroup)
            if .trgEnter != null then 
                call TriggerClearConditions(.trgEnter) 
                call DestroyTrigger(.trgEnter)
                set .trgEnter = null 
            endif
            if .trgLeave != null then 
                call TriggerClearConditions(.trgLeave)
                call DestroyTrigger(.trgLeave)
                set .trgLeave = null 
            endif
            call .deallocate()
        endmethod
       
        method disable takes nothing returns nothing 
            call PauseTimer(.t)
        endmethod
        method enable takes nothing returns nothing 
            call ResumeTimer(.t)
        endmethod
       
        method setOnEnterListener takes code callback returns nothing 
            if .trgEnter != null then 
                call TriggerClearConditions(.trgEnter)
            else 
                set .trgEnter = CreateTrigger()
            endif
            if callback != null then 
                call TriggerAddCondition(.trgEnter, Condition(callback))
            endif
        endmethod
       
        method setOnLeaveListener takes code callback returns nothing 
            if .trgLeave != null then 
                call TriggerClearConditions(.trgLeave)
            else 
                set .trgLeave = CreateTrigger()
            endif
            if callback != null then 
                call TriggerAddCondition(.trgLeave, Condition(callback))
            endif
        endmethod 
       
        private static method leaving takes nothing returns nothing 
            set tempUnit = GetEnumUnit()
            if Distance(GetUnitX(tempUnit), GetUnitY(tempUnit), GetUnitX(enum.u), GetUnitY(enum.u)) > enum.range then 
                call GroupRemoveUnit(enum.withinGroup, tempUnit)
                set lastLeavingUnitCol = tempUnit
                set lastSourceUnitCol = enum.u
                if enum.trgLeave != null then
                    call TriggerEvaluate(enum.trgLeave)
                endif
                call BJDebugMsg(GetUnitName(tempUnit) + " has left " + R2S(enum.range) + " of source: " + GetUnitName(enum.u))
            endif
        endmethod 
       
        private static method entering takes nothing returns nothing 
            set tempUnit = GetEnumUnit()
            call GroupAddUnit(enum.withinGroup, tempUnit)
            call BJDebugMsg(GetUnitName(tempUnit) + " is within " + R2S(enum.range) + " of source: " + GetUnitName(enum.u))
            set lastEnteringUnitCol = tempUnit
            set lastSourceUnitCol = enum.u
            if enum.trgEnter != null then
                call TriggerEvaluate(enum.trgEnter)
            endif
        endmethod
       
        private static method filter takes nothing returns boolean 
            set tempUnit = GetFilterUnit()
            return enum.u != tempUnit and not(IsUnitInGroup(tempUnit, enum.withinGroup))
        endmethod
       
        private static method update takes nothing returns nothing 
            local location point 
            set enum = table[GetHandleId(GetExpiredTimer())]
            set point = GetUnitLoc(enum.u)
            set bj_wantDestroyGroup = true
            call ForGroup(GetUnitsInRangeOfLocMatching(enum.range, point, Condition(function thistype.filter)), function thistype.entering)
            call ForGroup(enum.withinGroup, function thistype.leaving)
            call RemoveLocation(point)
            set point = null 
        endmethod 
       
        private static method onInit takes nothing returns nothing
            set table = Table.create()
        endmethod 
    endstruct 
   
endlibrary
 
Last edited:
I suspect this is due to your method declaration order. Because the onCollision method is located below the constructor, JassHelper generates a trigger evaluation/execution for your trigger action. This results in GetTriggeringTrigger() in onCollision returning the handle of the generated trigger and not your struct trigger as you'd expect.
To fix this you just have to move your onCollision method above the create method.
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
I suspect this is due to your method declaration order. Because the onCollision method is located below the constructor, JassHelper generates a trigger evaluation/execution for your trigger action. This results in GetTriggeringTrigger() in onCollision returning the handle of the generated trigger and not your struct trigger as you'd expect.
To fix this you just have to move your onCollision method above the create method.

Bah, it's too late to turn back at this point. Is it true that UnitComesWithinRangeEvent is less reliable than a periodic distance check?
 
The profit with a custom periodic check is that you ..
  • can decide if you make a UnitInRange check, or a pure distance check (without collision)
  • can access both units that are in range. The one who enters, and the one who is checked
  • have control when exactly, or how often to make the checks
edit: it's never to late to place the functions above, so useless code is created. ;p
 
Status
Not open for further replies.
Top