HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

ExecuteFunc Issues!

10-19-2004, 08:03 PM#1
RodOfNOD
For the last several months I have been coding over 16k lines of jass for a project. I have run into a MAJOR issue and need some suggestions/help.

Basically I use ExecuteFunc ALOT. I have the name of the function stored in the game cache and then when I want to call a particular function I just use ExecuteFunc( "funcname") and it works great.

However I started to add functions that had WAITs in them and ran into major issues with the functions executing in the wrong order. Basically If you have a function a that calls functions b and c and function b contains a wait, then function b will stop temporarily and function c will continue and finish THEN return to function b.

For what i need, ie functions executing in the CORRECT order all the time, this doesnt work.

I have made a test map to show this, anyone that thinks they have solutions PLEASE DL and see if you can find a work around.

Any help would GREATLY be appreciated.

Thanks

Rod
10-19-2004, 09:54 PM#2
Guest
Thank you for the map that shows the differences between call <function> and run <trigger>! I've been too lazy to test for it myself.

Are there really so many functions that you can't use call statements directly? (/me would understand more if you were to elaborate.)

Failing that... you could create a trigger out of each function and store that. (maybe have one cache or category for the string values, and another for the handle reference (H2I) for that trigger.) Then queue those.

(much later... after spending half an hour looking for `append code to trigger actions' function in the trigger queue code!)
Yep, the only reason the trigger queue works is because you HAVE to put that `clear this trigger from the queue' bit at the end of a trigger (apart from a failsafe 3 minute timer). So each trigger causes the next trigger in the queued array to execute. It shouldn't be too hard to duplicate this with "executefunction" instead, just copy the code from blizzard.j.

(oops, I think I deleted part of a previous edit. sth about creating your own "execute function" queue, I don't know if it is required to understand previous paragraph.)
10-20-2004, 12:31 AM#3
weaaddar
Don't use waits? I think it was known that waits were generally a no-no. Since you use a function based system instead of using function names use the function pointer value and then use a timer with whatever time duration to run this peice of code or whatever.
10-20-2004, 03:43 PM#4
Vexorian
Well the weird thing is that I use ExecuteFunc in my Templates system, and overuse waits with no problems, have to research way more on this.

And what was this doing in the trigger haven, moved to siberia err the JASS vault forum
10-20-2004, 07:14 PM#5
RodOfNOD
Hmm yes i have literally a 1000 different functions.

Don't use waits? LOL i have cinematics. Once again 1000 eventually. Not using waits would be not worth the effort.

Vex: test my map it shows very clearly what works and what doesnt. If you THINK your executefuncs are working with waits well your just getting lucky that you dont care what order shit executes in :>
10-20-2004, 09:46 PM#6
RodOfNOD
So far this is what I have come up with:

function WaitEF takes nothing returns nothing
loop
call TriggerSleepAction( 0.25)
exitwhen execfuncdone[ execfuncdonecount]
endloop
set execfuncdonecount = execfuncdonecount - 1
endfunction //

function DoneEF takes integer val returns nothing
loop
call TriggerSleepAction( 0.25)
exitwhen execfuncdonecount == val
endloop
set execfuncdone[ execfuncdonecount] = true
endfunction

function PushEF takes nothing returns integer
set execfuncdonecount = execfuncdonecount + 1
set execfuncdone[ execfuncdonecount] = false
return execfuncdonecount
endfunction //

function SetEF takes nothing returns integer
return execfuncdonecount
endfunction //




OK and THESE are sample functions:

function test takes nothing returns nothing
local integer EF = SetEF()

..... DO SOME SHIT that contains a WAIT

call DoneEF()
endfunction

function doit takes nothing returns nothing
call PushEF()
call ExecuteFunc( "test")
call WaitEF()
endfunction

It appears to work but what a pain. About to test it with a ton of waits in one call.
10-21-2004, 07:40 AM#7
Guest
Store the name of each <function you want to run in order> as a string in an array, with the first to execute at index zero. Use an index to keep track of the highest index actively in use, just like blizzard did with their queue. Add to the end of each function you use `call AttemptRunNextExecFunc()'. Make `AttemptRunNextExecFunc()' check to see if there are any more functions to be run (and if so, run the first one), and if not, call <whatever you want to happen after all the ExecFuncs are finished>, possibly by storing it in a hardcoded string variable and using ExecFunc again. YW >.>
10-21-2004, 07:58 AM#8
RodOfNOD
Well 2 things misaki.. First off i have lots of functions that are not in any particular order so putting them into an array would be very very hard. Second I THINK what i pasted above is very similar to what you are saying.

However you say "just like blizzard did with their queue. " do you have any links explaining what they did exactly?

Thanks
10-21-2004, 10:20 AM#9
Guest
meh.. you're not making sense. Either you want them to run in a particular order, or you don't want them to run in a particular order. (just like the trigger queue, you would add functions to the queue dynamically...)

The trigger queue functions start here.

The difference between what you do and the queue (the way blizzard does it) is for the queue, the next function in line is executed automatically, not after .25 seconds or more (wait is unreliable).

Also, why is it necessary to use ExecuteFunction() instead of calling them directly?

If you're desperate, you could always make up a huge CallFunctionByString() function, that does an if/then search to call the appropriate function.

Is the `code' variable type useful for anything?

Code:
function experiment takes nothing returns nothing
    local code c = function experiment
    local trigger t
    // call ExecuteFunc("c") // I don't think this would work.
    call TriggerAddAction(t, c)
endfunction

Oi, what's the TriggerExecuteWait() function do? o.0
10-21-2004, 07:46 PM#10
RodOfNOD
Thanks for the link. I didnt realize they were BJ functions.

I am using game cache to store my function names. YES i could make a HUGE if then. While I could make it so it never checked more than a small group at a time there would still LITERALLY be over 1000 if then statements. My map needs are THAT huge.

The problem with the queue is that if u call another executefunc inside it will have the same problem.. ie func a calls EF B then does some stuff an inside EF B there is ANOTHER EF - Execute Func call then it causes major havoc. I appear to have solved this now but what a pain.

There is no ExecuteCode( c) which would be great but there is a workaround. http://kattana.users.whitehat.dk/viewfunc.php?id=23 which has the same issue. Its threaded :(

FOLLOWUP:

function WaitEF takes nothing returns nothing
loop
exitwhen execfuncdone[ execfuncdonecount]
call TriggerSleepAction( 0.0)
endloop
set execfuncdonecount = execfuncdonecount - 1
endfunction //

function DoneEF takes integer val returns nothing
loop
exitwhen execfuncdonecount == val
call TriggerSleepAction( 0.0)
endloop
set execfuncdone[ execfuncdonecount] = true
endfunction

swapping the order of the wait and putting it after appears to make it run faster and not cause any other issues! I had tried this before but think I had another unrelated bug so this had FIXED it.

Basically the problem is simple.

If you have a function "a" that call the function "b" with executefunc and "b" calls a wait then it will continue with function "a"s execution before returning to "b". To prevent this i have the waitEF loop. The next problem is what if function "b" calls using executefunc "c" and "c" uses a wait? Thats why I have to have the PushEF / WaitEF combo at EVERY LEVEL otherwise it will restart when I don't want to.

If I used something like the trigger queue then the problem would be this.

Add trigger "a" to queue. it starts to execute and inside of "a" is an Add trigger "b" to queue. Well it CANT start "b" and YET i NEED it to start "b" before finishing with "a". It appears what my functions do is solve this nasty problem.

Thanks for the comments any followup is appreciated.
10-21-2004, 08:07 PM#11
Vexorian
Quote:
Originally Posted by misaki
meh.. you're not making sense. Either you want them to run in a particular order, or you don't want them to run in a particular order. (just like the trigger queue, you would add functions to the queue dynamically...)

The trigger queue functions start here.

The difference between what you do and the queue (the way blizzard does it) is for the queue, the next function in line is executed automatically, not after .25 seconds or more (wait is unreliable).

Also, why is it necessary to use ExecuteFunction() instead of calling them directly?

If you're desperate, you could always make up a huge CallFunctionByString() function, that does an if/then search to call the appropriate function.

Is the `code' variable type useful for anything?

Code:
function experiment takes nothing returns nothing
    local code c = function experiment
    local trigger t
    // call ExecuteFunc("c") // I don't think this would work.
    call TriggerAddAction(t, c)
endfunction

Oi, what's the TriggerExecuteWait() function do? o.0
Misaki, ExecuteFunc is needed because you can call functions that aren't on the top of the function you are writting, also it takes a string argument which is much flexible than the code argument, meaning you can concatenate and that stuff

function DoSomething takes nothing returns nothing
call ExecuteFunc("sss")
endfunction

function sss takes nothing returns nothing
call BJDebugMsg("sss")
endfunction

Won't give errors
10-22-2004, 06:51 AM#12
Guest
I got it. ^ ^ Do the turn-functions-into-triggers-before-storing-them thing, then call TriggerWaitOnSleeps() for all of them. (tested on your example map and it worked.)

Again, does anyone know what TriggerExecuteWait() does? It doesn't make the calling trigger or the called trigger wait on sleeps; I can't find any difference between normal TriggerExecute().