Jump to content
emrak

Difference between functions and scripts

Recommended Posts

The wiki article for scripts states:

 

Scripts are mainly used for any game processes where timing is important. They are unlike functions where the result or calculation is important.

 

Can someone provide a couple real-world usage examples of what they are referring to here? I'm a little confused by the distinction they're trying to make. Thanks

Share this post


Link to post
Share on other sites

Scripts are good for something like adding magazines to a player's inventory:

player addMagazines ["someMagazineClass",5];

A function is good for returning a result, after some calculation on an input value, so let's say I want a function to return the distance of the player from some object:

fnc_returnDistanceBetween =
{
    _unit = (_this select 0);
    _object = (_this select 1);

    _distanceBetween = _unit distance _object;

    _distanceBetween;//return value line
};

//Example call of the function would be:

_returnedDistance = [player,object1] call fnc_returnDistanceBetween;
  • Like 1

Share this post


Link to post
Share on other sites

Another use for an inline function is the prevention of code repetition.

 

If you use the same code multiple times in a script, then it can be useful to define local/global inline function.

  • Like 1

Share this post


Link to post
Share on other sites

A script, execVM, exec, is processed and then run every time it is called for use.

A function is preprocessed and stored in ram waiting for it to be called. When it is called it simply just runs, no processing required. (This is far more efficient)

  • If a script is likely to be run any more than once, such as  Killed eventhandler code, then it should be preprocessed as a function
  • If a script is only going to be run once, then in most cases just execVM it

 

ExecVM allows the use of sleep and waituntil commands

calling a preprocessed function doesnt allow the use of such sleeper commands

However this can be worked around by spawning a function that has sleeper commands in it.

 

So Golden rules.

  • If its only going to be run once, use Execvm
  • If its going to be used more than once, store it as a function and then
    • if there are no sleeper commands, call it
    • If there are sleeper commands spawn it

 

examples

 

MyTag_fMyFunction = (compilefinal preprocessfilelinenumbers "Functions\fMyFunction.sqf");

[] call MyTag_fMyFunction;

or

[] spawn MyTag_fMyFunction;

 

[] ExecVM "MyRunOnceOnlyscript.sqf";

 

The best way to initialise all of your functions is to create a preinit function, defined in the cfgfunctions class of your description.ext

and in that function, define all of your functions, using the example i used above.

This way any functions you require for the init field of units and vehicles as defined in the mission editor (mission.sqm) are already defined prior to needing them, 

  • Like 4

Share this post


Link to post
Share on other sites

Also if its cpu-intensive code its generally better to spawn it instead of call it, to prevent stuttering. Calling forces the code into the processor, while spawning schedules it for orderly processing.

 

edit: Of course in some cases, such as when expecting and requiring a return, you don't have much choice.

  • Like 1

Share this post


Link to post
Share on other sites

Could be that article is way old and "script" refers to SQS (Status Quo Script) script while "function" to SQF (Status Quo Function) script. In fact I'm pretty sure that is all there is.

Share this post


Link to post
Share on other sites

Thanks for the terrific input everyone (especially jshock and terox!).

 

Killzone_kid, are you saying that "scripts" and "functions" are both loaded into memory now as they are both SQF files?

Share this post


Link to post
Share on other sites

This thread is very helpful as I am trying to learn this whole deal about how to initiate and call functions in a proper way! Thanks

 

 

The best way to initialise all of your functions is to create a preinit function, defined in the cfgfunctions class of your description.ext

and in that function, define all of your functions, using the example i used above.

 

I wouldn't even know how to do this part... Could you (or anyone) provide an example of how this is done?

Share this post


Link to post
Share on other sites

 

Ok, i think I understand that part now, thanks.  So functions initialized this way are compileFinal'd? So the following:

MyTag_fMyFunction = (compilefinal preprocessfilelinenumbers "Functions\fMyFunction.sqf");

Is only needed if I did not initialize the functions in description.ext?? 

Share this post


Link to post
Share on other sites

Yes Altsor.

 

I too have a question though. I only play SP and I am currently designing a large scale random mission generator mission so obviously I will save and load the game and enjoy it over a course of days  :)

So does loading a game save even after restarting PC and Steam will run that SP mission's init.sqf and everything else over again? Or will I have to execute a special code to make the scripts run again like they start the first time.

 

 

btw, interesting topic. I too got to learn a lot. :)

Share this post


Link to post
Share on other sites

Yes Altsor.

 

I too have a question though. I only play SP and I am currently designing a large scale random mission generator mission so obviously I will save and load the game and enjoy it over a course of days   :)

So does loading a game save even after restarting PC and Steam will run that SP mission's init.sqf and everything else over again? Or will I have to execute a special code to make the scripts run again like they start the first time.

 

 

btw, interesting topic. I too got to learn a lot. :)

 

By default, the state of the code execution is saved when you save and is loaded when you load the mission back up. So for example if you have a piece of code that loops and hints something every second, it will continue after the load.

 

I say by default because you can choose to disable this by using disableSerialization. This is necessary to work with UI stuff, but can be useful if for some reason you do not want to save the state. So if you used disableSerialization in the example above, the code would need to be executed again if you want to keep the hints going after the load.

Share this post


Link to post
Share on other sites

By default, the state of the code execution is saved when you save and is loaded when you load the mission back up. So for example if you have a piece of code that loops and hints something every second, it will continue after the load.

 

I say by default because you can choose to disable this by using disableSerialization. This is necessary to work with UI stuff, but can be useful if for some reason you do not want to save the state. So if you used disableSerialization in the example above, the code would need to be executed again if you want to keep the hints going after the load.

Thank you Sniperwolf !! :D

Share this post


Link to post
Share on other sites

Also if its cpu-intensive code its generally better to spawn it instead of call it, to prevent stuttering. Calling forces the code into the processor, while spawning schedules it for orderly processing.

 

This is not true. 

Call merely "pastes" the code as if it was written where it was called from. Calling is in the same thread as and inherits everything from the caller block (even variables!) So in a sense it behaves as spaghetti code, every command waits for the prior to be finished. 

Spawn creates a parallel thread, so the next command after spawn doesn't wait for the spawned commands. You need to pass every variable you need to use to a spawned thread, since it is a new thread, totally separate from the spawner (this is why it can't return anything)

 

So since call inherits, a call in a spawned, or execVMed thread is the same thread, and is scheduled. Most scripts are scheduled, since you start off from the init by execVMing something (which puts you and all further calls to the scheduler)

 

Most important non-scheduled threads are: FSM conditions (run on each frame), waituntil conditions (run on each frame). Calling in these threads are non-scheduled (this is why I said that what you'd written was not true: calling does not force anything to anywhere, it only inherits)

  • Like 1

Share this post


Link to post
Share on other sites

Most important non-scheduled threads are: FSM conditions (run on each frame), waituntil conditions (run on each frame). Calling in these threads are non-scheduled (this is why I said that what you'd written was not true: calling does not force anything to anywhere, it only inherits)

Perhaps even more important are event handlers, in my opinion. And they're more often the cause of stuttering.

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

×