Jump to content
The Real Bunc

using a function to spawn scheduled code

Recommended Posts

I'm making an addon of a script which isn't actually a function. ie it doesn't just get called, do something and then return.

 The script contains sleeps, waitUntils and loops which are not allowed within the unscheduled environment of a called function.

Is it possible to spawn code from within a function and to pass to that spawned code the parameters from the function call?

 

 

 

 

 

Share this post


Link to post
Share on other sites

Yes, very easily. In your function you can just use spawned code and using _this you can transfer all arguments from the original call to the spawned code

myFunction = {
	//bunch of code
  _this spawn {
    	//new code that needs scheduled enviornment
  }
}

I don't know the specifics, but an alternative thing you can do is simply spawn the code rather than call

myArgs spawn myFunction;

In SQF the "code" type you can think of it as just a container for the code, and using spawn or call determines the scheduling behavior of the executed code

  • Like 1

Share this post


Link to post
Share on other sites
4 hours ago, The Real Bunc said:

which are not allowed within the unscheduled environment of a called function

Its worth making a distinction here, calling a function does not necessarily make the code unscheduled. It all depends on the scheduled state of the calling code.

If the calling code is unscheduled, then the called code will be unscheduled.

If the calling code is scheduled, then the called code will be scheduled.

 

You can always use canSuspend to see what the state of suspension is within your called code. ie

//initPlayerLocal.sqf

TAG_fnc_someFunc = {
	
	if !( canSuspend ) exitWith {
		systemChat "unscheduled,  spawning code instead";
		_this spawn TAG_fnc_someFunc;
	};
	
	//Must be scheduled to sleep
	sleep 5;
	
	hint "Done!";
	
};


//InitPlayerLocal is scheduled

waitUntil{ time > 5 };

[] call TAG_fnc_someFunc; //scheduled environment will persist to function

findDisplay 46 displayAddEventHandler[ "KeyDown", {
	//Events are unscheduled
	
	//unscheduled environment will persist to function
	//notice systemchat as the function catches !canSuspend
	//and spawns the code for you instead
	[] call TAG_fnc_someFunc;
}];

 

  • Like 2

Share this post


Link to post
Share on other sites

You must have not read the documentation carefully. The BIS Community Functions page clears states that you can use sleep, waitUntil and loops in functions, as long as you use "spawn" command to call it. This way it will run asynchronously. And the only disadvantage is that you can't obtain the returned value.

Share this post


Link to post
Share on other sites

Thanks Imlay. Thanks for pointing that out.

 

I also note on reading the Function Library page of the Wiki

that it says this about the use of the Postinit attribute 

 

"the postInit attribute can be set to 1 to call the function upon mission start, after objects are initialized.
Passed arguments are ["postInit", didJIP]. The function is run in a scheduled environment so suspension is allowed, but any long term suspension will halt the mission loading until suspension is done."

 

Which is interesting. So, I seem to have two options

1) use the postinit that I already have in my code which will call the function at mission start after objects are initialized

or 

2) don't use an attribute - n which case I assume the function is not run at all but simply compiled and is then only run

(either by call or spawn) when explicitly called on by the coder within a script or init etc.

 

I want to give people two options  1) to have the script run Postinit so its running automatically (on player) whenever they go into any mission/ scenario or campaign

and 2) give them the option to only have the function called when they explicitly call it in one of their scripts or a unit ini.

Thinking about this Im beginning to doubt that I can do both these things within the one addon. I suspect Im going to have to do one addon which runs

automatically and then a second one which isnt run automatically but only runs when called in script or init.

 

Assuming Im understanding the Postinit attribute right of course and that if there is not attribute set the function is simply compiled.

 

Does this sound right?

 

My script/function can be run either on player or AI units though for the latter that wouldn't be automatically but would have to be using 

a specific script/or init call/spawn by the coder. 

 

 

Share this post


Link to post
Share on other sites
13 hours ago, The Real Bunc said:

Assuming Im understanding the Postinit attribute right of course and that if there is not attribute set the function is simply compiled.

Correct

 

13 hours ago, The Real Bunc said:

Thinking about this Im beginning to doubt that I can do both these things within the one addon. I suspect Im going to have to do one addon which runs

automatically and then a second one which isnt run automatically but only runs when called in script or init.

Give them an option in the description.ext?

Spoiler

//config.cpp ( mod ) 

class CfgFunctions {
	class ProjectName {
		tag = "BUNC";
		class Category {
			file = "BUNC\ProjectName\functions";
			class someFunc { postInit = 1; };	//Function always runs on postInit
		};
	};
};

class BUNC {
	class someFunc {
		runOnInit = 0; //Default postInit operation is false;
	};
};


//BUNC\ProjectName\functions\fn_someFunc.sqf

if (
	_this select 0 == "postInit" &&
	{ [ [ "BUNC_someFunc_runOnInit" ], configFile >> "BUNC" >> "someFunc" >> "runOnInit" ] call BIS_fnc_loadEntry == 0 }
) exitWith {};



//End user
//description.ext missionConfigFile/campaignConfigFile

BUNC_someFunc_runOnInit = 1; //Run on postInit

 

So the function in your mod is set to postInit as default.

The function when run and param 0 is "postInit" (as default from CfgFunctions setup) checks for the presents of the mission/campaign configfile property "BUNC_someFunc_runOnInit".

If its 1 the function executes, if 0 the function exits, if its missing then the property configFile > "BUNC" > "someFunc" > "runOnInit" is used instead, which is 0 so function exits.

So it is always set to not run on postInit unless specifically flagged to do so by the mission/campaign designer.

  • Like 1

Share this post


Link to post
Share on other sites

That feels really helpful Larrow but its going to take me more than one pass through on that to get my head round it. LOL I think I get the jist though.

 

Actually I want the function to run on player probably always postinit so its there for them ( once they load the mod) for any scenario or campaign they want to play. I think that's what many will likely want - to be able to load the mod and then get extra camo whatever campaign or scenario they are playing rather than relying on scenario maker having designed it in. But I'm still mulling all this over.

I'm really appreciative of your assistance.

Share this post


Link to post
Share on other sites

one problem leads to another... for instance you call a line with no function to run like a function after a compile. But in that function, which gets called, if accidently over and over again will just start creating the same named variables again and again. You can always start adding stuff to the globals list, and post that. 
 

On 9/11/2022 at 6:15 PM, dreadedentity said:

Yes, very easily. In your function you can just use spawned code and using _this you can transfer all arguments from the original call to the spawned code


myFunction = {
	//bunch of code
  _this spawn {
    	//new code that needs scheduled enviornment
  }
}

I don't know the specifics, but an alternative thing you can do is simply spawn the code rather than call


myArgs spawn myFunction;

In SQF the "code" type you can think of it as just a container for the code, and using spawn or call determines the scheduling behavior of the executed code


I seriously gotta try... so what do I do if I were you?
You can't sleep or wait in a handler that's given fact. But you can call a function and sleep right after calling the handler...
because the handler creates its own little thread and just goes off until terminated.

Carefully create your globals to run with the handler anyways. You can't pass anything directly but it can talk to your namespace variables. Cautiously redesign your code to run as many functions calling each other before getting to the block that you want !( returning variables that you change ) but ( modifying variables instead). 
And then posting MP global for each go. Your ext/config should have a lot more functions to define. You should find yourself creating a lot of paths. 

If you just want to mess around with texts or scripts into code use 
https://community.bistudio.com/wiki/compile
https://community.bistudio.com/wiki/preprocessFile
and 
https://community.bistudio.com/wiki/parseSimpleArray
in succession. In general I avoid using the 'call' function, but it can work. 
Avoid actually putting sleep or wait in your script and instead break it up into multiple functions or clusters that wait to sleep. 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×