Jump to content
thy_

null = [ ] execVM vs execVM vs remoteExec BIS_fnc_execVM

Recommended Posts

In the last two weeks, I spent A LOT of my days off to understand programming (I'm not a true one) and Arma scripts syntaxes and etc...

 

Of course, lots of questions came over and some of them that are not clear at all is how to call (in each case) an external piece of code (.sqf) through the init files (init.sqf / initServer.sqf / initPlayerLocal.sqf). Yeap, I've read about them also... and init.sqf is the priority when the mission starts, meanwhile initServer and initPlayerLocal has no guarantees of execution order. Got it, but and how and why call some external scripts like these down below?

 

// init.sqf

null=[] execVM "myScript.sqf";

execVM "mySecondScript.sqf";

"andAnotherScript.sqf" remoteExec ["BIS_fnc_execVM"];

 

What I'm trying to get:

https://community.bistudio.com/wiki/Event_Scripts

https://community.bistudio.com/wiki/execVM

  • Like 1

Share this post


Link to post
Share on other sites

These are all essentially the same, just with varying amounts and depth of information:

execVM "myScript.sqf";  // NOTHING FANCY

null = [] execVM "myScript.sqf";  // NULL HANDLE, WILL ALWAYS RETURN "NOTHING"

_handle = [] execVM "myScript.sqf";  // LOCAL HANDLE

THY_Handle = [param1, param2] execVM "myScript.sqf";  // GLOBAL HANDLE, PARAMS PASSED TO SCRIPT

 

If your script/function does not return a value, then you don't need a handle, but it's best practice as some cases require one (E.g. calling from init fields) and the few extra characters don't cost anything. Plus, descriptive handles are always nice to see.

 

If you need to execute the script/function remotely, use BIS_fnc_execVM.

 

As far as event scripts go, it's generally a matter of locality. Where/when does the script/function need to be executed?

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites
1 hour ago, Harzach said:

As far as event scripts go, it's generally a matter of locality. Where/when does the script/function need to be executed?

 

I'm working in that main bases protection script that you have seen me talking about on another topic. Well, last night I ran a few tests into a dedicated server and when I called the script through initServer.sqf or init.sqf everyone were able to kill and destroy things within mainbases ... the total opposite of my goals hehe. But if I remember well, it works(?) after the caller (execM) is transferred to initPlayerLocal.sqf. In your reading, can you see why? No idea here.

 

 

initPlayerLocal.sqf

// MAINBASES PROTECTION
execVM "mainBasesProtection.sqf";

 

 

mainBasesProtection.sqf

private [/* lots of private variables here */];

//if (!hasInterface) exitWith {};     // if is not a player, get out!

0 = [] spawn
{

	while {true} do
	{
		// SOME CODE WHERE I'M CHECKING IF PLAYER IS INTO MAINBASE. IF SO, THEY ARE IMMORTAL AS THE VEHICLES WHEN HERE. 
      		// NOTHING MORE ELSE!
	};
};

 

Share this post


Link to post
Share on other sites
4 hours ago, thy_ said:

but and how and why call some external scripts like these down below?


// init.sqf

null=[] execVM "myScript.sqf";

execVM "mySecondScript.sqf";

"andAnotherScript.sqf" remoteExec ["BIS_fnc_execVM"];

 

 

If a script is run repetitively, over and over again, you want to compile and run it as a function.  Whether done using  CfgFunctions in a Description.ext, or by using:

THY_fnc_mainBasesProtection = Compile PreprocessFileLineNumbers "FolderName\mainBasesProtection.sqf";

. . . the file will only be compiled once, and the function can be called or spawned over and over again without it being recompiled.

 

execVM compiles the script every time it gets used, and that takes away processer time that could be used elsewhere.  So you would use ExecVM for scripts that are only run once, or remain persistent (like looping updates, which the base protection script sounds like), or scripts that are needed, but rarely get run.

 

 

3 hours ago, Harzach said:

If you need to execute the script/function remotely, use BIS_fnc_execVM.

This is good strong advice (IMHO), because your mission might not use a CfgRemoteExec in the Description.ext, but you won't always know whether an addon that will be used has within its config a RemoteExec restriction against clients running the ExecVM command.

 

 

2 hours ago, thy_ said:

I ran a few tests into a dedicated server

 

On dedicated server, Player is objNull.  If it has to be run by server, you may need to cycle through allPlayers array and determine who is inside the base limits.

But on client, Player command will always return the object which is the client player's unit.  It's different on every machine.  So if the script is only applying immortality to a player, and nothing else, it should likely be run from initPlayerLocal.sqf

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
13 hours ago, opusfmspol said:

 

If a script is run repetitively, over and over again, you want to compile and run it as a function.  Whether done using  CfgFunctions in a Description.ext, or by using:


THY_fnc_mainBasesProtection = Compile PreprocessFileLineNumbers "FolderName\mainBasesProtection.sqf";

. . . the file will only be compiled once, and the function can be called or spawned over and over again without it being recompiled.

 

execVM compiles the script every time it gets used, and that takes away processer time that could be used elsewhere.  So you would use ExecVM for scripts that are only run once, or remain persistent (like looping updates, which the base protection script sounds like), or scripts that are needed, but rarely get run.

 

 

This is good strong advice (IMHO), because your mission might not use a CfgRemoteExec in the Description.ext, but you won't always know whether an addon that will be used has within its config a RemoteExec restriction against clients running the ExecVM command.

 

 

 

On dedicated server, Player is objNull.  If it has to be run by server, you may need to cycle through allPlayers array and determine who is inside the base limits.

But on client, Player command will always return the object which is the client player's unit.  It's different on every machine.  So if the script is only applying immortality to a player, and nothing else, it should likely be run from initPlayerLocal.sqf

 

It's gold right above, man. Let me think and run some tests. 
Yesterday we were 9 players in our dedicated server and, running the protection mainbase through initPlayerLocal.sqf (using "player" instead "allPlayers") everything ran right, except for one of us that sometimes we got kill him. Super weird but, based on what you said, that makes sense. Let me try some fixes and later I come back here with details and results. 

Share this post


Link to post
Share on other sites

@Harzach and @opusfmspol, morning (here is 10h55), 

 

After some tests and thoughts regarding what is needed to be called from execVM and what must be part of CfgFunctions, basically, my conclusion is: about performance saving, CfgFunctions are better (compile once even if I want to check something repeatedly), as well as for main base protection from the point of view my mission has 18 slots and 30 vehicles to "protect" in two main bases in-game. Despite (and I don't know why), when I think CfgFunctions, it looks like I won't use while-looping anymore, or at least not so frequently. Make any sense? Briefly, I am in love with CfgFunctions. Some advice?

 

On other hand, execVM I am using (successfully) to change the time-matches, sometimes in the night, some in the morning, although that script is so simple that I'm running it once at mission start by initServer.sqf > execVM.

 

Share this post


Link to post
Share on other sites
On 2/21/2022 at 11:05 AM, thy_ said:

(...) when I think CfgFunctions, it looks like I won't use while-looping anymore, or at least not so frequently. Make any sense? Briefly, I am in love with CfgFunctions. Some advice?


Hey me from the past, you got wrong. That time was your first time set attention over "FUNCTIONS" topic so that was confusing, but today is a bit clearer. When you use CfgFunctions through Description.ext, you will use while-looping as well, but sometimes we create a file like "fn_PAC_globalFunctions.sqf" or something like that where we set ONLY FUNCTIONS, passing a wrong idea that you are not using while-looping or for-looping but in another file (where you are calling FUNCTIONS) you are. hehe.

Cheers. 
You from the future.

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

×