• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Registering Events

Status
Not open for further replies.
I've experienced it, yes. I still have the map in which a script of mine first encountered it but I'm a bit lazy to test it again now.

http://filesmelt.com/dl/4AvalancheWithDDKB006.w3x

good damage detection systems don't let the event cap be reached by means of a few different methods.
-unit recycling
-individual triggering
-stack based with event counts and isAlive checks
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Your triggering EVERY UNIT INTO A DAMAGE DETECTION SYSTEM? *cough*soinefficientandtimewasting*cough*
 
I'll post the results in this post :p

I was going to find out the number, but then I got distracted and coded a new resource instead :)D)

I'm getting back to finding the cap now =p

edit

So far:
Simple registeration: >10000

edit

1 trigger + 1300 event registrations + firing the event = NO lag.
I'm going to try this while registering boolexprs to the trigger ;D

edit

Wow, even with an empty boolexpr, nothing.
With a boolexpr that prints text, nothing.

With a CreateUnit call, *testing* it froze and crashed T_T (with 7820 registerations)
With 1300: 2 second lag spike.

We have nothing to worry about :)
The number is too high for anyone to test for ;D

edit
Did another to test to get the event cap.
With a 0.001 timer, I was able to register 38000 events with 0 lag (very minor FPS drop that I couldn't notice)
Then, at 40000, it began to lag a bit.
At 50000, it lagged even more.
I gave up at 70000 because it was way too laggy :/
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
I'm wondering if the result wouldn't be the same or maybe even worse with X triggers which have one event.

Btw Mag, i don't how how you did the tests but if you had the very same event X times to a trigger it will fire the trigger X times when this event fire.
You should probably know that but i find a bit weird your sentences :

Mag said:
The final test involved no unit creation :p
Only 2 of my tests involved unit creation :>
 
Ok, my tests were flawed, so I did them again.

What I did:

JASS:
struct Test extends array
    
    private static trigger onDamageTrig = CreateTrigger()
    private static trigger damageUnitsTrig = CreateTrigger()
    
    private static integer requiredOperations = 8200
    
    private static Table u
    
    private static integer count = 0
    private static integer index = 0
    
    private static method causeDamage takes nothing returns boolean
        local integer op = 200
        loop
            call UnitDamageTarget(u.unit[requiredOperations], u.unit[requiredOperations], 60, false, false, null, null, null)
            set op = op - 1
            set requiredOperations = requiredOperations - 1
            exitwhen op == 0 or requiredOperations <= 0
        endloop
        return requiredOperations <= 0
    endmethod
    
    private static method onDamage takes nothing returns boolean
        set count = count + 1
        return false
    endmethod
    
    private static method createUnits takes nothing returns nothing
        call CreateUnit(Player(0), 'hpea', 0, 0, 0)
        if index == 8200 then
        
            call BJDebugMsg("dealing damage")
            call PauseTimer(GetExpiredTimer())
            call DestroyTimer(GetExpiredTimer())
            
            loop
                exitwhen TriggerEvaluate(damageUnitsTrig)
            endloop
            
            call BJDebugMsg("dealt damage")
        endif
    endmethod
    
    private static method display takes nothing returns boolean
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, I2S(count))
        return false
    endmethod
    
    private static method onEnter takes nothing returns boolean
        set index = index + 1
        set u.unit[index] = GetTriggerUnit()
        call TriggerRegisterUnitEvent(onDamageTrig, u.unit[index], EVENT_UNIT_DAMAGED)
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        local region r = CreateRegion()
        set u = Table.create()
        call RegionAddRect(r, GetWorldBounds())
        
        call TriggerRegisterEnterRegion(t, r, null)
        call TriggerAddCondition(t, Condition(function thistype.onEnter))
        
        call TriggerAddCondition(onDamageTrig, Condition(function thistype.onDamage))
        call TriggerAddCondition(damageUnitsTrig, Condition(function thistype.causeDamage))
        
        set t = CreateTrigger()
        
        call TriggerRegisterPlayerChatEvent(t, Player(0), "-", true)
        call TriggerAddCondition(t, Condition(function thistype.display))
        
        call TimerStart(CreateTimer(), 0.001, true, function thistype.createUnits)
        
        set r = null
        set t = null
    endmethod
    
endstruct

This didn't bug.
It displayed 8200, meaning that all the events were correctly registered.

(I chose 8200 because it's just above 8192)

This event cap must be pretty high :l
(Maybe 65536)
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Honestly i think the only limit is the limit of the ram.
Also i have never tested it but many people say that more handles id leak you have, more the jass vm is slow.
And i suppose an event make one, even if the unit is removed later (i have not tested it)
 
An event should be nothing but an integer that points to a stack of triggers :D
And a trigger should be nothing but an integer that points to a queue of triggeractions and triggerconditions

triggeractions should point to code which should point to a string
triggerconditions should point to a code which should point to a string
(Actually, code could point to an integer representing an index in some string array)

Events shouldn't occupy a lot of memory :p (These are all assumptions, but they're logical ones :O)
 
Well, I still realize the importance of destroying the trigger and re-registering the events.
If events point to a trigger stack (They don't check if the same trigger is registered twice or more before adding it to the stack), then with a lot of events, this stack is going to be very large, and thus, if an event fires, it's going to loop through a very large number of triggers and evaluate/execute them (if any triggeractions or triggerconditions are enqueued)

Triggers aren't even touched by the event if there are no triggeractions or triggerconditions (I know because I registered 30000 events to the same trigger, fired the event and no lag spike or tiny FPS drop occured (not even 1 FPS)
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
This is just pure guess, no facts at all.

Triggers aren't even touched by the event if there are no triggeractions or triggerconditions (I know because I registered 30000 events to the same trigger, fired the event and no lag spike or tiny FPS drop occured (not even 1 FPS)

I think it's just because you don't open a new thread (no condition/action), but create an empty trigger with an event, fire the event, then check GetTriggerEvalCount.
I expect that it still increases when a registred event fire.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
It's me, you can test it by yourself with bigs loops + debug message after the loop (close to op limit) in several trigger conditions, and then evaluate or fire the trigger event, all messages will be displayed.

Btw, each time code or boolexpr is involved in a native "function", the op limit is reset.
Like ForForce, GroupEnum...
 
I didn't test it with op limits, I tested it by crashing the thread in a boolexpr.

Quick example which will crash the thread -
JASS:
scope crashThread initializer i
	private function c takes nothing returns boolean
		call TriggerSleepAction(0.)
		call DisplayTextToPlayer(GetLocalPlayer(),0,0,"This won't display because TSA crashed the thread!")
		return false
	endfunction
	
	private function i takes nothing returns nothing
		local trigger t=CreateTrigger()
		call TriggerRegisterTimerEvent(t,1.,false)
		call TriggerAddCondition(t,Condition(function c))
		set t=null
	endfunction
endscope
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
I'm just saying that trigger conditions resets the limit op.

I shoudn't have said that it opens a new thread.

Now, you are unable to use sync natives, TSA (this one seems obvious, it is not called TriggerSleepCondition), PauseGame and probably some other functions inside them.

EDIT : Nothing is multi-threaded in wc3, when a new thread fire, the previous one is halt, but we still can say than triggerconditions open a new thread.
I got confused by your answers, but if you say that triggerconditions don't open a new thread, then we can say the same for all other jass operations.

JASS:
library ConditionsTest initializer init

    globals
        private constant integer ITERATIONS = 23000 // limit op reached with 24000 ( "ok" not displayed )
    endglobals

    private function Cond0 takes nothing returns boolean
        call BJDebugMsg("the thread will crash")
        loop
        exitwhen false
        endloop
        call BJDebugMsg("this message will never be displayed")
        return false
    endfunction
    
    private function Cond1 takes nothing returns boolean
        local integer i = 0
        call BJDebugMsg("1")
        loop
        exitwhen i == ITERATIONS
        set i = i+1
        endloop
        call BJDebugMsg("end 1")
        return false
    endfunction
    
    private function Cond2 takes nothing returns boolean
        local integer i = 0
        call BJDebugMsg("2")
        loop
        exitwhen i == ITERATIONS
        set i = i+1
        endloop
        call BJDebugMsg("end 2")
        return false
    endfunction

    private function init takes nothing returns nothing
        local integer i = 0
        local trigger trig = CreateTrigger()
        call TriggerAddCondition(trig,function Cond0)
        call TriggerAddCondition(trig,function Cond1)
        call TriggerAddCondition(trig,function Cond2)
        call TriggerSleepAction(0) 
        loop
        exitwhen i == ITERATIONS
        set i = i+1
        endloop
        call BJDebugMsg("ok")
        call TriggerEvaluate(trig)
    endfunction
    
endlibrary

I also confirm this :

myself said:
Btw, each time code or boolexpr is involved in a native "function", the op limit is reset.
Like ForForce, GroupEnum...
 
Last edited:
Status
Not open for further replies.
Top