PDA

View Full Version : [vJASS] TriggerRegisterEnterRegion not firing


Hartog
07-01-2012, 08:14 PM
Hi there, first post, anyway I have a slightly annoying problem. I got this trigger that won't fire and I have no idea why.


function Entering_Conditions takes nothing returns boolean
return true // GetTriggeringRegion() == LoadRegionHandle(udg_PH_HT, GetHandleId(GetTriggerUnit()), 7)
endfunction


function Trig_Enters_Region_Actions takes nothing returns nothing
call BJDebugMsg("success")
endfunction

//===========================================================================
function InitTrig_Enters_Region takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterEnterRegion(t, AREGION1, null)
call TriggerRegisterEnterRegion(t, AREGION2, null)
call TriggerRegisterEnterRegion(t, AREGION3, null)
call TriggerRegisterEnterRegion(t, AREGION4, null)
call TriggerRegisterEnterRegion(t, AREGION5, null)
call TriggerRegisterEnterRegion(t, AREGION6, null)
call TriggerRegisterEnterRegion(t, AREGIONX1, null)
call TriggerRegisterEnterRegion(t, AREGIONX2, null)
//call TriggerAddCondition( t, Condition(function Entering_Conditions ))
call TriggerAddAction( t, function Trig_Enters_Region_Actions )
set t = null
endfunction

That's the trigger and it will never show the "success" message.
The condition currently always return true for testing purposes.
I declare the globals in the global decleration like this.

globals
region AREGION1 = null
region AREGION2 = null
region AREGION3 = null
region AREGION4 = null
region AREGION5 = null
region AREGION6 = null
region AREGIONX1 = null
region AREGIONX2 = null
endglobals

While googling my problem i noticed that other people don't seem to need to set the regions to null, if I don't however the initz crashes. Here is a part of the Initz.

local unit u
local integer int
local integer int2
local region rgn
set udg_TownID_HT = InitHashtable()
set udg_Wall_HT = InitHashtable()
set udg_PH_HT = InitHashtable()
set AREGION1 = CreateRegion()
set AREGION2 = CreateRegion()
set AREGION3 = CreateRegion()
set AREGION4 = CreateRegion()
set AREGION5 = CreateRegion()
set AREGION6 = CreateRegion()
set AREGIONX1 = CreateRegion()
set AREGIONX2 = CreateRegion()
set u = gg_unit_h003_0000
call RegionAddRect(AREGION1, gg_rct_ARegion1)
set rgn = AREGION1
set int = GetHandleId(u)
set int2 = GetHandleId(rgn)
//Link town to its Region
call SaveRegionHandle(udg_TownID_HT, int, 10, rgn)
call SaveUnitHandle(udg_TownID_HT, int2, 10, u)

I first Create the region then i add a pre-placed rect to it.

set u = gg_unit_h003_0000
call RegionAddRect(AREGION1, gg_rct_ARegion1)
set rgn = AREGION1
set int = GetHandleId(u)
set int2 = GetHandleId(rgn)
//Link town to its Region
call SaveRegionHandle(udg_TownID_HT, int, 10, rgn)
call SaveUnitHandle(udg_TownID_HT, int2, 10, u)

That part is done for all the regions with different rects and units ofc.

So anyone see any problem?

PurgeandFire
07-01-2012, 10:07 PM
You have to make sure the rects and regions are created before you register the events. Try putting those actions in the initialization function before you register all the events.

Hartog
07-01-2012, 10:35 PM
All actions but the trigger that does not fire are in the initialization :/ or did i misunderstand you?

PurgeandFire
07-01-2012, 11:01 PM
Oh the rects might not be defined yet since you are using preplaced rects. Try putting a 0 second timer in the init trig function:
call TimerStart(CreateTimer(), 0, false, function <your function w/ init stuff>)

And then move the initialization stuff into the function that the timer is calling. It should work.

Hartog
07-02-2012, 12:15 AM
When debugging i tried to check if a point in the pre-placed rects was also in its respective region and it was. So it does get set correctly. I tried delayin the whole initz by a 0 timer anyways and nothing changed :/

Halo7568
07-02-2012, 04:58 AM
The fact that the map was crashing when you did not set the regions to null was a hint, but here is an explanation.

Compare the two triggers:
function Trig_region_Actions takes nothing returns nothing
call BJDebugMsg("entered region")
endfunction

//===========================================================================
function InitTrig_region takes nothing returns nothing
local region r = CreateRegion()
call RegionAddRect(r, gg_rct_fail)
set gg_trg_region = CreateTrigger( )
call TriggerRegisterEnterRegion(gg_trg_region, r, null)
call TriggerAddAction( gg_trg_region, function Trig_region_Actions )
endfunction


globals
region enter2 = null
endglobals

function enter_region takes nothing returns nothing
call BJDebugMsg("entered region 2")
endfunction

// runs on map initialization via the check box
// http://puu.sh/Fd0W
function region_init takes nothing returns nothing
set enter2 = CreateRegion()
call RegionAddRect(enter2, gg_rct_fail)
endfunction

//===========================================================================
function InitTrig_region2 takes nothing returns nothing
local trigger t
set gg_trg_region2 = CreateTrigger( )
call TriggerAddAction( gg_trg_region2, function region_init )

set t = CreateTrigger()
call TriggerRegisterEnterRegion(t, enter2, null)

call BJDebugMsg("Region handle was: " + I2S(GetHandleId(enter2)))
endfunction


The first creates and sets up the region right before registering the region event, both in the same function.

The second initializes the region to null and registers the region event in the trigger's initialization function, then leaves initializing the region to the trigger's "run on map initialization" option. As the BJDebugMsg will note if you try copying this trigger, the handle of the registered region is 0 (ie, it was null). Simply, the trigger's initialization function runs before a trigger's action "run on map initialization". Which makes sense, you should initialize triggers before running their actions.

Setting the region to null stopped the crash because triggers allow registering null things apparently. If you simply left the region declaration with no initial value, the trigger registration on the region variable would attempt to register whatever value the region variable starts with when declared but not initialized. Not sure if the value is completely arbitrary or not, but it causes a crash if you use it as a region.

(edit: well the thread is supposed to crash as mentioned below, but Wc3 itself is not supposed to)

I do believe PurgeandFire111 has been giving you working advice. If you put your trigger initialization function on a timer like he said, it probably would have worked. Whatever your "initz" function is, you are probably referring to the registered trigger action for "run on map initialization" or something, instead of the trigger initialization function, which is this: "InitTrig_Enters_Region". Delaying your other function is pointless because it already runs after the InitTrig function.

Alternatively, you can just move the trigger region event registrations to the end of your "initz" function.

WaterKnight
07-02-2012, 08:23 AM
Setting the region to null stopped the crash because triggers allow registering null things apparently. If you simply left the region declaration with no initial value, the trigger registration on the region variable would attempt to register whatever value the region variable starts with when declared but not initialized. Not sure if the value is completely arbitrary or not, but it causes a crash if you use it as a region.

The declaration value is not arbitrary but simply empty and the current thread will halt when reading such an unset variable.

Halo7568
07-02-2012, 09:01 AM
Decided to open up Wc3 in a debugger and see if variables with no set value had anything in the value spot, looks like it is set to 0 by default. Which is what null's integer value is as well, as far as I remember. So yeah, I suppose the only thing stopping it from being treated as null is that Wc3 tries to skip over it.

WaterKnight
07-02-2012, 09:08 AM
Array members are set to the standard null value.

Halo7568
07-02-2012, 09:29 AM
Not really sure what that was in response to. Guess I will clarify what I meant, though. What I was verifying was that when this sort of thing is done:
globals
region r
endglobals

The value r has is 0, though Wc3 simply skips over it in the code because it has a variable type check in place that fails, or something to that effect.

Likewise, in this:
globals
region r = null
endglobals

The value r has is again 0, though this time the type check that failed before with a value of 0 has a value of 7 (handle type).

In other words, if you patched one spot in Wc3 memory, variables with no value would be treated as 0 / null. Although in the first case I am not actually sure if the value is always 0, particularly in the case of local variables. The idea interested me and I wanted to know if it was similar to C++, in which uninitialized variables would simply have the last value put there. Despite Wc3 keeping track of whether a variable is initialized or not, it seems to zero that space anyway, which might just be a side effect of how Wc3 initializes space for variables.

Also, as far as Wc3 is concerned, null == 0, similarly to how in C++ NULL is effectively 0.

On a different note, I was able to crash Wc3 once while forming the test code I first posted, though I have not been able to reproduce it. Not sure what that was about.

Hartog
07-02-2012, 02:26 PM
Thanks all and you're right i did just delay the Main Initialization trigger which ofc proved pointless.