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!
"call TriggerClearConditions(trig[this])" should be moved to the "else" actions in the overhead if-block. If the boolexpr is null then the trigger doesn't have any conditions, so the first registry is going to have a pointless function call.
Now that I think of it you could also move the creation of the trigger into the "register" method, because some events never get registered (like only using UnitEvent for reincarnation start/end, for example).
So it would look more like this:
JASS:
static method create takes nothing returns thistype
set count = count + 1
return count
endmethod
method register takes boolexpr c returns nothing
if (null==bc[this]) then
set bc[this]=c
set trig[this] = CreateTrigger()
else
set bc[this]=Or(bc[this],c)
call TriggerClearConditions(trig[this])
endif
call TriggerAddCondition(trig[this], bc[this])
endmethod
method register takes boolexpr c returns nothing
if (null==bc[this]) then
set bc[this]=c
set trig[count] = CreateTrigger()
else
set bc[this]=Or(bc[this],c)
call TriggerClearConditions(trig[this])
endif
call TriggerAddCondition(trig[this], bc[this])
endmethod
The line set trig[count] = CreateTrigger(), is the array value supposed to be count?
Nes, if your standard and data heavy Event libraries have different API's (IE the data heavy one supports GetEventData()), you should name the libraries differently so that systems using the data heavy one can require EventEx (or something), thus not confusing your client with cryptic error messages if they're using the standard Event library.
I've been lately working on destructable and item indexer and everyone knows, that events do not fire before map init. I went looking at wc3c/the helper for answers and possible solutions - outcome: each library has it's own preload stuff (if it does cover mentioned issue). UnitIndexer isn't exception.
I guess we should talk about preloading events so we can get best possible way to fix the issue. Personaly, I have had custom public struct preloader to do the job for me. Problem was, each time I wanted to implement Register<...>/TriggerRegister<...> functions, it forced me to write up additional things. Thus, such struct can't be a resource since user still has to manualy change some stuff.
So.. I started thinking about kinda extension for Event to cover that part. The key in my approach was to get into the core of event firing.. the fire method.
JASS:
library PreLoader
//! textmacro PRELOADER
private static boolean hasPreloaded=false
static thistype preloader=0
static integer array eval
private boolexpr bexpr
static method executePreload takes nothing returns nothing
local trigger t=CreateTrigger()
local thistype this=1
set hasPreloaded=true
loop
exitwhen integer(this)>w
set preloader=this
if eval[this]>0 and this.bexpr!=null then
call TriggerClearConditions(t)
call TriggerAddCondition(t,this.bexpr)
call TriggerEvaluate(t)
endif
set this=this+1
endloop
call DestroyTimer(GetExpiredTimer())
call DestroyTrigger(t)
set t=null
endmethod
static method addPreloader takes code c, thistype ev returns nothing
set ev.bexpr=Condition(c)
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(),0,false,function thistype.executePreload)
endmethod
//! endtextmacro PRELOADER
module PreLoadData
static method preloadEvent takes nothing returns boolean
local integer this=1
local Event ev=Event.preloader
endmodule
module PreLoadSet
loop
exitwhen this > Event.eval[ev]
endmodule
module PreLoadNull
call ev.fire()
set this=this+1
endloop
endmodule
module PreLoadEnd
return false
endmethod
endmodule
endlibrary
and the fire method changes:
JASS:
method fire takes nothing returns nothing
set q=0
set q=this
call TriggerEvaluate(e[this])
static if LIBRARY_PreLoader then
if not thistype.hasPreloaded then
set eval[this] = eval[this]+1
endif
endif
endmethod
Now, lets bring the fact that indexers start indexing from 1. Above lib with consideration of such fact allows typical indexer to avoid implementation of custom preload member and instead offers:
JASS:
implement PreLoadData
local integer prev = eventIndex
implement PreLoadSet
set eventIndex = this
implement PreLoadNull
set eventIndex = prev
implement PreLoadEnd
Such method ignores the division on trigger/condition part since it calls .fire() method.
Next, there is basicaly no gain, if you use this for just UnitIndexer for example. However, if you'd go for additional one, like ItemIndexer then it happily cuts the code and makes things look cleaner.
Once again, it's just a suggestion and since conversations can bring nothing but profit I'd like to know ur opinions about that issue.
There are few options available:
a) each lib implements it's own stuff to deal with this
b) create a lib which covers this on it's own (but how could you acces the event data then)?
c) interference with Event itself
Edit: Additional variant of API from previous lib:
JASS:
//! textmacro PRELOADER takes DATA
static method preloadEvent takes nothing returns boolean
local integer this=next[0]
local Event ev=Event.preloader
local integer save = $DATA$
loop
exitwhen 0==this
set $DATA$ = this
call ev.fire()
set this=next[this]
endloop
set $DATA$ = save
return false
endmethod
//! endtextmacro
Uses the linked list from library directly. Now, you can just type: //! runtextmacro PRELOADER("o") in $DATA$ place type global event index name.
That variant requires no changes in fire method.
Event
DynamicEvent (not out yet)
PriorityEvent
DynamicPriorityEvent
I've discovered a few interesting things
#1: a way to remove trigger conditions without crashing the trigger and without timers or anything special, just a plain TriggerRemoveCondition
#2: a way to evaluate triggers that's even faster than a plain list of TriggerAddConditoin
Check it out here
JASS:
struct PyramidBuilder extends array
private static boolexpr array o
static method register takes trigger T, integer i, boolexpr base returns nothing
local integer m = i
call populate(i, base)
loop
set m = condense(m)
exitwhen m == 0
endloop
call TriggerAddCondition(T, o[0])
endmethod
private static method populate takes integer i, boolexpr base returns nothing
loop
exitwhen 0 == i
set i = i - 1
set o[i] = base
endloop
endmethod
private static method condense takes integer i returns integer
local integer m = 0
local integer n = i/2
set i = i - 1
loop
exitwhen m >= i
set o[m] = Or(o[m], o[i])
set m = m + 1
set i = i - 1
endloop
if (m == i) then
return m
endif
return n
endmethod
endstruct
Less handles are generated and it evaluates more quickly.
edit
A look at Event, underway. Not working atm, but I'll hopefully finish it over the weekend =)
JASS:
/*
static method create takes nothing returns thistype
method fire takes nothing returns nothing
method register takes boolexpr func returns thistype
method unregister takes nothing returns nothing
method destroy takes nothing returns nothing
*/
library Event /* v3.0.0.0
*************************************************************************************
*
* * uses *
*
* * Alloc * hiveworkshop.com/forums/jass-resources-412/snippet-alloc-alternative-221493/
*
************************************************************************************
*
* struct Event extends array
*
* readonly boolexpr functionList
*
* static method create takes nothing returns thistype
* method register takes boolexpr c returns nothing
* method fire takes nothing returns nothing
*
************************************************************************************/
private keyword FunctionList
private struct EventContainer extends array
implement LinkedListNode
boolexpr main
boolexpr sub
method destroy takes nothing returns nothing
local thistype node = first
loop
exitwhen node == 0
call DestroyBoolExpr(node.sub)
set node.sub = null
set node = node.next
endloop
set main = null
call clear()
endmethod
endstruct
private struct EventContainerBuilder extends array
private static boolexpr array builder
private static integer count = 0
private static EventContainer owner
private static method condense takes nothing returns nothing
local integer m = 0
local integer i = count - 1
local integer n = i/2
loop
exitwhen m >= i
set builder[m] = Or(builder[m], builder[i])
set builder[i] = null
set owner.add().sub = builder[m]
set m = m + 1
set i = i - 1
endloop
if (m == i) then
set count = m
else
set count = n
endif
endmethod
static method build takes EventContainer owner returns nothing
local FunctionList node = FunctionList(owner).first
set thistype.owner = owner
set count = 0
loop
exitwhen node == 0
set builder[count] = node.container
set count = count + 1
set node = node.next
endloop
loop
exitwhen count == 0
call condense()
endloop
set owner.main = builder[0]
set builder[0] = null
endmethod
endstruct
private struct FunctionList extends array
implement LinkedListNode
readonly boolexpr container
method register takes boolexpr func returns nothing
local thistype node = first
loop
exitwhen node.container == null
set func = Or(node.container, func)
set node.container = null
set node = node.next
endloop
if (node == 0) then
set node = add()
endif
set node.container = func
endmethod
method build takes nothing returns nothing
call EventContainerBuilder.build(this)
endmethod
method destroy takes nothing returns nothing
local thistype node = first
if (node == 0) then
return
endif
/*
* The first node always contains a plain function
* Don't destroy it
*/
set node = node.next
loop
exitwhen node == 0
if (node.container != null) then
call DestroyBoolExpr(node.container)
set node.container = null
endif
set node = node.next
endloop
call clear()
endmethod
endstruct
private struct Allocator extends array
implement Alloc
endstruct
struct Event extends array
private trigger container
private triggercondition containerCondition
private boolean update
static method create takes nothing returns thistype
local thistype this = Allocator.allocate()
set container = CreateTrigger()
return this
endmethod
method fire takes nothing returns nothing
if (update) then
if (containerCondition != null) then
call TriggerRemoveCondition(container, containerCondition)
endif
call EventContainer(this).destroy()
call FunctionList(this).build()
if (EventContainer(this).main != null) then
set containerCondition = TriggerAddCondition(container, EventContainer(this).main)
else
set containerCondition = null
endif
set update = false
endif
call TriggerEvaluate(container)
endmethod
method register takes boolexpr func returns thistype
set update = true
call FunctionList(this).register(func)
return 0
endmethod
method unregister takes nothing returns nothing
set update = true
endmethod
method destroy takes nothing returns nothing
set update = false
if (containerCondition != null) then
call TriggerRemoveCondition(container, containerCondition)
set containerCondition = null
endif
call EventContainer(this).destroy()
call FunctionList(this).destroy()
call DestroyTrigger(container)
set container = null
call Allocator(this).deallocate()
endmethod
endstruct
endlibrary
With the new design, I can make all of the libs dynamic and they'll be faster . This means that these libs will be faster than triggers with spammed TriggerAddCondition, plus they'll allow you to do TriggerRemoveCondition. Win win? Yes ;D.
Out of curiosity, will the new Event version simply be changed to use Triggers instead of triggers? I haven't really worked on my map lately, but I've been considering updating it with this, because why not. Everything is based on Event after all, so I pretty much only need to change it.
I'll do it nevertheless even if the new version of Event does not come out before the release, but I'd like to know if you have further plans with it (well, it's not like it was needed or possible to further optimize it, and I don't need more functionality, so yea).
I'm planning to move everything over to Trigger/PriorityTrigger. Event is kind of deprecated, but I'll keep it up so as not to break everything else. Behind the scenes, it will use Trigger, and I'll provide access to the Trigger so that users can use all of the cool new features of Trigger . PriorityEvent will be the same deal.
Explain to me how this doesn't break in the case where you have multiple events. How is the game engine going to know which event you're firing when you use one trigger for the entire Event library?
EDIT: WHAT THE HECK where did the @JASS@ highlighting go???
The @JASS@ highlighting thing disappeared mysteriously when Ralle redid the JASS tags and added [highlight] tags that works for about 100 or more programming languages.
Explain to me how this doesn't break in the case where you have multiple events. How is the game engine going to know which event you're firing when you use one trigger for the entire Event library?
Yup, it actualy breaks the entire system. You just need to remove the "static" keyword and it works fine. I wanted to report it when I moved from Advent to Event, but totally forgot about it.
I'm kinda curious what the new version will look like now that we have Trigger
method register takes boolexpr func returns nothing
if (functionList == null) then
set functionList = func
else
set functionList = Or(functionList, func)
endif
call TriggerAddCondition(eventContainer, func)
endmethod
If you always do the "Or" function with the previous conditions, when you add a second registry to the event, the first registry will fire twice, because you have redundancy now. The current version of Event is still broken.
This is why you should always test your resources and encourage others to test your resources, especially even if you're Nestharus.
Right, so basically your entire jump from v2.0.0.1 to v2.1.0.0 was for show. I just recommend deleting version 2.1.0.0 altogether so no one gets confused.
method register takes boolexpr func returns nothing
if (functionList == null) then
set functionList = func
else
set functionList = Or(functionList, func)
endif
call TriggerAddCondition(eventContainer, func)
endmethod
If you always do the "Or" function with the previous conditions, when you add a second registry to the event, the first registry will fire twice, because you have redundancy now. The current version of Event is still broken.
This is why you should always test your resources and encourage others to test your resources, especially even if you're Nestharus.
Well, it's only for the list (that I got rid of anyways) - it still works fine as only the passed boolexpr gets registered to the trigger. But ehm yea, I don't get how no one else reported these before. I didn't, because I'm not really active on the forums, especially not in the JASS section, but still, there're quite a few Nes fanboys around, I don't get how they didn't report it.
It doesn't surprise me. Nestharus updates his resources so often, everyone was probably using an older version and didn't realize/care that he updated it.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.