- Joined
- Jul 10, 2007
- Messages
- 6,306
This tutorial is meant to discuss recursion with event data assigned using your own custom event triggers. Without proper recursion, the wrong data may be accessed.
When events are run, data is normally associated with that event.
When creating custom events, it is easy enough to do this
But this can result in a problem.
In events, event data should always be the same data as it was when the event first fired. In the above scenario, the data was first 1 but then becomes corrupted at 2. While this doesn't seem to be an issue, it can be a serious issue.
And thus the major recursion error.
Fire (1)
----run test1 (1->2)
--------Fire (2)
------------run test1 (2)
------------run test2 (2)
----run test2 (2)
There are two methods for solving this recursion error. The first poor way is to create an array type stack.
If I were to fire the second example, it would run in this order-
Test1- data 1
Test1- data 2
Test2- data 2
Test2- data 1
For a clearer understanding-
Fire (1)
----run test1 (1)
--------Fire (2)
------------run test1 (2)
------------run test2 (2)
----run test2 (1)
As can be seen, the data is maintained ; D.
The other and better way is by using locals to store the data to save on an array and a global declaration.
This essentially does the same thing as the stack method but faster. Array reads are also quite a bit slower than var reads, so it's a better design.
When events are run, data is normally associated with that event.
GetTriggerUnit
GetAttacker
GetTriggerPlayer
When creating custom events, it is easy enough to do this
JASS:
globals
private trigger myEvent = CreateTrigger()
private integer data = 0
endglobals
function OnMyEvent takes boolexpr c returns nothing
call TriggerAddCondition(myEvent, c)
endfunction
function FireMyEvent takes integer d returns nothing
set data = d
call TriggerEvaluate(myEvent)
endfunction
function GetEventData takes nothing returns nothing
return data
endfunction
But this can result in a problem.
JASS:
function Test takes nothing returns boolean
local integer d = GetEventData() //d is now 1
if (d == 1) then
call FireMyEvent(2) //set d to 2
endif
if (d != GetEventData()) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "RECURSION ERROR!")
endif
return false //to prevent trigger actions from being run for no reason
endfunction
function Init takes nothing returns nothing
call OnMyEvent(Condition(function test))
call FireMyEvent(1) //data is now 1
endfunction
In events, event data should always be the same data as it was when the event first fired. In the above scenario, the data was first 1 but then becomes corrupted at 2. While this doesn't seem to be an issue, it can be a serious issue.
JASS:
//this will fire second
function Test2 takes nothing returns boolean
//remember that the event data become corrupt on the first fire?
local integer d = GetEventData() //2 on first and second fires
return false
endfunction
//this will fire first
function Test takes nothing returns boolean
local integer d = GetEventData() //d is now 1
if (d == 1) then
call FireMyEvent(2) //set d to 2
endif
if (d != GetEventData()) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "RECURSION ERROR!")
endif
return false //to prevent trigger actions from being run for no reason
endfunction
function Init takes nothing returns nothing
call OnMyEvent(Condition(function Test))
call OnMyEvent(Condition(function Test2))
call FireMyEvent(1) //data is now 1
endfunction
And thus the major recursion error.
Fire (1)
----run test1 (1->2)
--------Fire (2)
------------run test1 (2)
------------run test2 (2)
----run test2 (2)
There are two methods for solving this recursion error. The first poor way is to create an array type stack.
JASS:
globals
private trigger myEvent = CreateTrigger()
private integer stack = 0
private integer array data
endglobals
function OnMyEvent takes boolexpr c returns nothing
call TriggerAddCondition(myEvent, c)
endfunction
function FireMyEvent takes integer d returns nothing
set stack = stack + 1 //increase the stack, thus making a new spot for event data
set data[stack] = d //event the new spot to our current data
call TriggerEvaluate(myEvent) //fire
set stack = stack - 1 //revert to previous data
endfunction
function GetEventData takes nothing returns nothing
return data[stack]
endfunction
If I were to fire the second example, it would run in this order-
Test1- data 1
Test1- data 2
Test2- data 2
Test2- data 1
For a clearer understanding-
Fire (1)
----run test1 (1)
--------Fire (2)
------------run test1 (2)
------------run test2 (2)
----run test2 (1)
As can be seen, the data is maintained ; D.
The other and better way is by using locals to store the data to save on an array and a global declaration.
JASS:
globals
private trigger myEvent = CreateTrigger()
private integer data = 0
endglobals
function OnMyEvent takes boolexpr c returns nothing
call TriggerAddCondition(myEvent, c)
endfunction
function FireMyEvent takes integer d returns nothing
local integer prev = data //store the previous data in a local
set data = d
call TriggerEvaluate(myEvent)
set data = prev //set the data back to the previous value
endfunction
function GetEventData takes nothing returns nothing
return data
endfunction
This essentially does the same thing as the stack method but faster. Array reads are also quite a bit slower than var reads, so it's a better design.
Last edited: