HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Really weird trigger handle bug?!

01-17-2011, 03:04 AM#1
rogueteddybear
I've attached the example map with the small amount of code.


Situation:

I have a single struct, with two triggers. Both triggers register in TriggerRegisterUnitInRange() and go to different boolexpr.

In one of the boolexpr, the handle of GetTriggeringTrigger() matches the trigger that was registered.

In the other boolexpr, the handles don't match (wtf?). The weirder part is that if I get rid of some of the code in the second one (the if statement and the unit = null) then it seems to work.

code:
Code

Collapse JASS:
library AdvancedProjectile initializer initShowBug


module Projectile

    trigger collisionTrg1
    trigger collisionTrg2
    
    static thistype ref

    
    static method createNormal takes nothing returns thistype
        local thistype this = thistype.allocate()
        local unit u1 = CreateUnit(Player(0), 'hpea', 0,0,0)
        local unit u2 = CreateUnit(Player(0), 'hpea', 0,0,0)

        set ref = this

        set collisionTrg1 = CreateTrigger()
        call TriggerRegisterUnitInRange(collisionTrg1, u1, 200.0, null)
        call TriggerAddCondition(collisionTrg1, function thistype.inRangeEnum)

        set collisionTrg2 = CreateTrigger()
        call TriggerRegisterUnitInRange(collisionTrg2, u2, 200.0, null)
        call TriggerAddCondition(collisionTrg2, function thistype.inRangeEnum2)
        
        return this
    endmethod
   
   //This one doesn't bug out, handle id's match
    static method inRangeEnum2 takes nothing returns boolean
        call BJDebugMsg("This: "+I2S(GetHandleId(ref.collisionTrg2))+" should match "+I2S(GetHandleId(GetTriggeringTrigger())) + " <-- And it does. wtf..")
        return false
    endmethod
   
   
    //this one shows different handle id's
    static method inRangeEnum takes nothing returns boolean
        call BJDebugMsg("This: "+I2S(GetHandleId(ref.collisionTrg1))+" should match "+I2S(GetHandleId(GetTriggeringTrigger())) + " <-- But it doesn't!?")
//this line (the comment) causes the bad handle id --- lol?
        return false
    endmethod

endmodule

struct ProjectileStruct
    implement Projectile
endstruct

function ShowBug takes nothing returns nothing
    call ProjectileStruct.createNormal()
endfunction

function initShowBug takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 1.0, false)
    call TriggerAddAction(t, function ShowBug)
endfunction

endlibrary



Does anyone know what might cause this behavior?

edit: I have updated the code to be easier to read with less stuff. The bug still happens and goes away if you remove a line of comment! (wtf!?)
Attached Images
File type: jpgBugPic.jpg (39.2 KB)
Attached Files
File type: w3xShowTriggerBug.w3x (17.7 KB)
01-17-2011, 07:29 AM#2
jrhetf4xb
Ok, this is totally bugged... The comment indeed causes the strange behavior. O_O It seems to also appear if you put a comment in inRangeEnum2.
Your usage of GetTriggeringTrigger() there bugs me, as if that's what causes the problem
01-17-2011, 09:20 AM#3
rain.mon
This happens because your trigger condition function is located below the function that you register them to the triggers. Move both the functions above the creation method and your problems should be gone. You might also want to read the vJass manuall and you'll see why that happens
01-17-2011, 11:37 AM#4
Anitarf
rain.mon is correct. You can not place functions below any code that calls them in regular JASS. The same is apparently true for placing functions below any code that uses them as trigger conditions. vJass works around this problem by creating a dummy function at the top of the map script which then in turn uses TriggerEvaluate to execute the original function. However, by doing this, the original function is no longer a trigger condition of your original trigger, but of an autogenerated trigger instead and GetTriggeringTrigger returns incorrectly as a result.

Newer versions of JassHelper can rearrange the order of struct methods automatically to avoid needlessly using trigger evaluates instead of regular function calls, however apparently this only works for function calls and not for using functions as trigger conditions since in your case the order of the methods does not change, but the workaround mentioned above is used instead.

The reason one of your functions works anyway and the other one works too if you remove the comment is that JassHelper is also capable of inlining some simple functions. It seems your method inRangeEnum2 matches the criteria for inlining while inRangeEnum doesn't because of that extra line (even if it is just a comment; the inliner is by no means perfect). As a result, the contents of the method get inlined into the autogenerated dummy function at the top of the map script, removing the trigger evaluate in the process.

You can see this for yourself if you place the code you posted in an empty map, save it, open the outputwar3map.j file in the NewGen logs folder with a text editor, then fix the order of the methods in the trigger editor, save the map again and open the same file again. Now you can compare the two outputwar3map.j files.


Edit: I recall it being said before that in-range triggers are no more efficient than doing periodic group in-range enums, since that is what the triggers do internally anyway. You might find it simpler to use group enums instead of dynamic triggers.
01-17-2011, 09:54 PM#5
rogueteddybear
Ah this all makes sense now. I knew there was a reason for why I was going insane.

Quote:
Edit: I recall it being said before that in-range triggers are no more efficient than doing periodic group in-range enums, since that is what the triggers do internally anyway. You might find it simpler to use group enums instead of dynamic triggers.

I was directed to the trigger technique over the group enum after posting that group enums that do nothing still lower my fps by 30 with 300 projectiles on the field (doing nothing, again).
01-19-2011, 11:50 AM#6
Bribe
Projectiles shouldn't be checking for collision every single period especially if the collision range is >= 100. Just do it every 3-5 frames and you'll notice your FPS will spike.

FYI, the trigger-inRange check happens every 0.1 seconds. So your check should happen around the same interval if you want to keep the same FPS.