HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

EnterRegion filter

05-25-2009, 12:03 PM#1
grim001
I'm posting this because I haven't seen it mentioned before. It's rather obscure, but I know that a lot of people here like to memorize every strange behavior that WC3 has.

The results of this test are something you should keep in mind if you use TriggerRegisterEnterRegion in your map. When a unit is created, the filter function of the TriggerRegisterEnterRegion runs instantly (interrupting the current function), but the conditions and actions of that trigger run after a 0. second delay. I tested some other triggers with filter functions and no other trigger seems to work this way.

Code:
Collapse JASS:
library EnterRegionTest initializer Init

function UnitEntersFilter takes nothing returns boolean
        call BJDebugMsg("EnterRegion filter detected "+GetUnitName(GetFilterUnit())+" entering the map.")
    return true
endfunction

function UnitEntersCondition takes nothing returns boolean
        call BJDebugMsg("EnterRegion condition detected "+GetUnitName(GetTriggerUnit())+" entering the map.")
    return true
endfunction

function UnitEntersAction takes nothing returns nothing
    call BJDebugMsg("EnterRegion action detected "+GetUnitName(GetTriggerUnit())+" entering the map.")
endfunction

function ZeroSecExpired takes nothing returns nothing
    call BJDebugMsg("Zero second timer expired.")
endfunction

function DoTest takes nothing returns nothing
    call TimerStart(CreateTimer(), 0., false, function ZeroSecExpired)
    call BJDebugMsg("Creating unit...")
    call CreateUnit(Player(0), 'hpea', 0., 0., 0.)
    call BJDebugMsg("Finished creating unit.")
endfunction

function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region re = CreateRegion()
    
        call SetCameraPosition(0., 0.)
        call FogEnable(false)
        call FogMaskEnable(false)
    
        call RegionAddRect(re, bj_mapInitialPlayableArea)
        call TriggerRegisterEnterRegion(t, re, Condition(function UnitEntersFilter))
        call TriggerAddCondition(t, Condition(function UnitEntersCondition))
        call TriggerAddAction(t, function UnitEntersAction)
        
        call TimerStart(CreateTimer(), 3., false, function DoTest)
endfunction

endlibrary

Results:


Why is this important? Well take AutoIndex for example, I am trying to give units an index as soon as they enter the map, but if I don't do that inside the filter function, it won't run the conditions/events until the current thread ends. In other words, using the filter function, the below code would work, and without using the filter function the below code would break.
Collapse JASS:
set u = CreateUnit(...)
set i = GetUnitId(u) //returns correct index when using filterfunc to index, returns 0 when using condition/action to index
05-25-2009, 01:56 PM#2
rain9441
Good find. I've run into behavior like this before when dealing with issuing orders myself. Strange interrupting behavior occured, but I can't recall the details.
05-25-2009, 04:17 PM#3
Anitarf
So I take it that for other events, the order is as such:
  • Killing unit...
  • Unit death filter detected peasant dying.
  • Unit death condition detected peasant dying.
  • Unit death action detected peasant dying.
  • Finished killing unit.
  • Zero second timer expired.

If so, this really is a peculiar exception.
05-25-2009, 04:50 PM#4
Troll-Brain
You may notice that it seems only GetFilterUnit() work in TriggerRegister..., at least that is true for orders.
Anyway it's obvious that Blizzard didn't finish them, the GUI never use them (well ok that's not a good example xD).
Imho, you should never use a such boolexpr, unless you want more silly bugs in your map.
05-25-2009, 05:31 PM#5
grim001
Quote:
Originally Posted by Troll-Brain
Imho, you should never use a such boolexpr, unless you want more silly bugs in your map.

Er, it doesn't cause bugs. It solves them. You need to use the filter to get the expected behavior.
05-25-2009, 05:34 PM#6
Troll-Brain
Quote:
Originally Posted by grim001
Er, it doesn't cause bugs. It solves them. You need to use the filter to get the expected behavior.
You don't get what i wanted to say, it's like giving a gun to a child, you don't know what will happens, maybe nothing, but maybe it will happens a terrible thing.

I mean Blizzard didn't expect we use them at all.
05-25-2009, 05:49 PM#7
grim001
Quote:
Originally Posted by Troll-Brain
You don't get what i wanted to say, it's like giving a gun to a child, you don't know what will happens, maybe nothing, but maybe it will happens a terrible thing.

I mean Blizzard didn't expect we use them at all.

The filter wouldn't exist if you weren't supposed to use it. I don't understand your reasoning at all. What's wrong with it, what's incomplete, what's buggy? There's no point in spreading fear of bugs unless you have proof or at least any kind of evidence. Furthermore, this is the only proper way to detect units entering the map if you need it to work instantly.
05-25-2009, 06:19 PM#8
Troll-Brain
Quote:
The filter wouldn't exist if you weren't supposed to use it. I don't understand your reasoning at all. What's wrong with it, what's incomplete, what's buggy? There's no point in spreading fear of bugs unless you have proof or at least any kind of evidence

Tell me why only GetFilterUnit() is the only Get which works inside so, if Blizzard expect we use them, why blizzard.j never use them ?

Quote:
Furthermore, this is the only proper way to detect units entering the map if you need it to work instantly.
It's sad ...
05-25-2009, 07:49 PM#9
Anitarf
Quote:
Originally Posted by grim001
The filter wouldn't exist if you weren't supposed to use it.
So we are supposed to use I2H?
Quote:
I don't understand your reasoning at all. What's wrong with it, what's incomplete, what's buggy?
We don't know. Maybe nothing. Maybe not.
Quote:
There's no point in spreading fear of bugs unless you have proof or at least any kind of evidence.
There's also no reason to use something new and untested if you can avoid it, however:
Quote:
Furthermore, this is the only proper way to detect units entering the map if you need it to work instantly.
This is true. It's the only way to get proper behaviour, so you have no choice but to use it. It doesn't change the fact that trigger filters are rather untested, but what can we do? Well, we could do some testing to confirm that trigger filters do not cause any memory leaks or any other easily detectable bugs, as for bugs that are difficult to detect, we just have to hope they do not exist.

Edit: It seems to me that this inconsistency in trigger behaviour is likely intentional. It's difficult to imagine a bug causing this, it's more plausible that Blizzard did this because they wanted the bj_lastCreatedUnit global to be reliable in GUI (otherwise a trigger that created a unit when another unit entered a region could break everything).
05-25-2009, 08:00 PM#10
Bobo_The_Kodo
I've always used this way for my unit indexing, and adding crow abilities and all that, never bugged up yet
05-25-2009, 08:01 PM#11
Troll-Brain
@Anitarf:
Thx, that's what i wanted to say.

EDIT : @Bobo_The_Kodo : Fine, so.
But did you track about potential leaks or such things ?
05-25-2009, 08:12 PM#12
grim001
Why does anyone have a reason to suspect that trigger filters work any differently than enum filters?
05-25-2009, 08:22 PM#13
Troll-Brain
Quote:
Originally Posted by grim001
Why does anyone have a reason to suspect that trigger filters work any differently than enum filters?
Because Blizzard had fail many times ?
Because when there is a potential bug they avoid the case ?
I highly suspect they don't null the timer in PolledWait because they know that it could bug, or maybe because they forget it, then they didn't saw that it could bug, meh nevermind really.

We have many reasons to doubt for any new untested method, but like you've said there is not an other method, so test it, we will see ...
05-25-2009, 08:23 PM#14
Anitarf
Quote:
Originally Posted by grim001
Why does anyone have a reason to suspect that trigger filters work any differently than enum filters?
Because Blizzard coded them?

It's ok, though, I don't think that you shouldn't use them, heck, I'll be using them in the new ADamage myself. Just saying that I hope they don't cause any bugs.
05-25-2009, 09:20 PM#15
Opossum
I guess what blizz did here is just what they should have done to the DROP_ITEM event. Maybe the trigger action runs late because the unit hasn't actually entered the region at the moment of event firing. Just like an item is actually still in the hero's inventory when DROP_ITEM fires.
You should try if GetUnitX(GetFilterUnit()) returns the correct value when used in the filter function.
Edit: just tried that myself... both functions return the correct unit position so screw that theory.

And considering these event filters. I've been using them all the time and they've never caused any problems... I don't see why they should leak either as they're probably just the same as enum filters.