Jump to content
  • 0

Ways To execVM?


NightHâwk

Question

Just wondering if some one could explain to me a little better or point me in the right direction to know when to use execVM and [] execVM to call/execute scripts.

 

currently I use [] execVM for just about everything I have so is there a better way to do this or does it matter?

Link to comment
Share on other sites

7 answers to this question

Recommended Posts

  • 0

To start off there's 3 ways to do this, call, spawn or execVM.

 

ExecVM and Spawn are very similar, they both create threads and run outside of the original thread that called it, therefore if you need to wait for a scrip to be done you must use waitUntul {scriptDone _handle};

Having many spawns/execVms at once will cause performance to degrade, if you do them too quickly you may crash the game.

 

The major difference between spawn and executeVM is that with spawn you can use preprocessFileLineNumbers (use this one) and preprocessFile. This is great for pre-compiling scripts to save a little bit on overhead, you should look into this if you have tons of execVMs running consistently or at once; additionally unlike execVM you do not need a file since you can just spawn some thing like this.

_code = {
hint "hi";
};

[] spawn _code;
[] execVM _code; <--- generic error

Call is by far the most perfromance friendly version of this so use it whenever you can. It will execute the compiled code (yes it must be compiled, if it's a code block like the example above it is already compiled). However, due to the fact that it does not support sleep/waituntil or anyother form of suspending, it is not always possibly to use it. Also keep in mind that loops in called codes are only run 30,000 times before being closed. Call also supports return variables (last line of your file).

 

Note: never write something like spawn spawn/call compile preprocesslinenumbers "file.sqf";

it's not secure and you should assign the compiled code to a local variable or global variable depending on what you need it for, like so.

_compile = compile preprocessfilelinenumbers "file.sqf";

call _compile;

 

Note 2: when using call/spawn remember that it's important to remember a spawned thread that has a call in it will be able to handle sleeps. see example

//imagine this is in your init.sqf
[] spawn {
_code = compile preprocessfilelinenumbers "custom\script.sqf";
_var = call _code;

if (_var) then { /*something*/ }; //return from call
};
//code after here is executed after script.sqf is finished running
//Note: it's not good to suspend (waituntil/sleep) your init since it's meant to be run instantly, hence to original spawn.

imagine this is script.sqf

private "_something";
_player = vehicle player;

if (_player == player) then { true } else { false }; //return value!

TL;DR Use call, if you must use a sleep or need to run a script in a new thread (parallel to the executing script) use Spawn instead of execVM. Keep in mind that you can't preprocesss every file and have it run properly, you will need execVM for some scripts.

Link to comment
Share on other sites

  • 0

They both do the same thing, more or less. The bracket, to my knowledge only indicates that the execVM syntax is executing additional argument or strings.

For example, my towing exec:

if (isServer) then {
	//Towing
	[true] execVM "R3F_ARTY_AND_LOG\init.sqf"
};
if (!isDedicated) then {
	//Towing
	[] execVM "R3F_ARTY_AND_LOG\init.sqf"
};

So it would mean that, anything that's been passed through the brackets also gets passed through to the executed .sqf file.
As the example above, i pass the true statement even if the server is not dedicated. Which means the R3F starts regardeless. 
 

null = [farts,1234] execVM "stuff.sqf"; //or was it nill?

//and in the stuff.sqf you need to place for example:
//to access the different elements

_farts = _this select 0;
_numbers = _this select 1; //

Correct me if I'm wrong.

Link to comment
Share on other sites

  • 0

You are correct. When using Call just be sure to declare everything private since values are passed in between scripts.

 

I.e.

private "_yourvar"; //we declare it private, despite it being a global (local var - meaning not in an if/then statement), because it would be changed by the call if it was to be set to false by the call (even if it wasn't a return value)
_code = {
diag_log format["hi, _yourvar = %1", _yourvar]; //should = true if player (will also work if using external script via compile)
};

_yourvar = if (isPlayer player) then {true} else {false};

call _code;
Link to comment
Share on other sites

  • 0

Also I wouldn't recommend setting Null = [] execVM "blah.sqf"; use another variable. Especially DON'T set it to nil, you will break the game!!!!

 

Yes, you can overwrite vars like this, no you should never do it.

 

If you need a handle make it local, never assign it a global variable.

_handle = [] execVM "script.sqf"; <-- correct if you need to wait for scriptDone
waitUntil {scriptDone _handle};

[] execVM "script.sqf"; //if you don't need to wait for scriptDone this is correct

if you do not need a handle to wait for script completion don't assign execVM to a variable. Note: if you use it in a trigger it will need a variable assign to it.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Discord

×
×
  • Create New...