Functions Library – Arma 3

From Bohemia Interactive Community
Jump to navigation Jump to search
No edit summary
mNo edit summary
Line 157: Line 157:
Compile function '''<big><span style="color:green;">myTag</span>_fnc_<span style="color:teal;">myFunction</span></big>''' from the following file:
Compile function '''<big><span style="color:green;">myTag</span>_fnc_<span style="color:teal;">myFunction</span></big>''' from the following file:
  ''%ROOT%''\<span style="color:DarkOrange;">myPath</span>\fn_<span style="color:teal;">myFunction</span>.sqf
  ''%ROOT%''\<span style="color:DarkOrange;">myPath</span>\fn_<span style="color:teal;">myFunction</span>.sqf
<span style="color:DarkOrange;">myFolder</span> can be a folder or multiple folders, e.g., <span style="color:DarkOrange;">myFolder\mySubfolder</span>
<span style="color:DarkOrange;">myPath</span> can be a folder or multiple folders, e.g., <span style="color:DarkOrange;">myFolder\mySubfolder</span>


==== Default Path (Mission Only) ====
==== Default Path (Mission Only) ====
Line 198: Line 198:


== Writing a Function ==
== Writing a Function ==
The most important thing to remember when writing a function is that other people than you are going to use it. Most of them won't understand how does it work, expecting it to does its job without problems.


=== Recompiling ===
Your function must be '''robust'''. It shouldn't allow passing arguments of incorrect [[Data Types]] in. When some values are incorrect, it should throw an error explaining what went wrong and how to fix it. And above all, its header must provide complete explanation of usage.
{{Important|What is not documented, does not exist!}}
 
=== Loading Parameters ===
Arguments are the only way how to interact with your function. Let's now see how to make sure they are loaded properly.
 
We have this very simple function which will let a unit watch a position:
_unit = <span style="color:green;">_this</span> [[select]] <span style="color:darkorange;">0</span>;
_target = <span style="color:green;">_this</span> select <span style="color:darkorange;">1</span>;
_unit [[doWatch]] _target;
 
Expected way how to call the function is by correctly defining all arguments:
[player,[position myCar] call myTag_fnc_myFunction;
 
However, the function will break down when you try to send only one argument in:
[player] call myTag_fnc_myFunction;
 
Furthermore, using wrong data type will also lead to a problem:
[player,0] call myTag_fnc_myFunction;
 
Variabe ''_target'' expects position array in format [x,y,z]. Scripting error will appear when different number of elements is used:
[player,[1,2,3,4]] call myTag_fnc_myFunction;
 
 
As you can see there, the most common problems are:
# '''Param of wrong data type is sent'''
# '''Param is missing'''
# '''Param is an array expecting specific number of elements, but different number is sent'''
 
Rather than check for these exceptions yourself, you can use existing function [[BIS_fnc_param]] which will does it for you:
_unit = [<span style="color:green;">_this</span>, <span style="color:darkorange;">0</span>, <span style="color:teal;">objNull</span>, <span style="color:crimson;">[objNull]</span>] call BIS_fnc_param;
_target = [<span style="color:green;">_this</span>, <span style="color:darkorange;">1</span>, <span style="color:teal;">[0,0,0]</span>, <span style="color:crimson;">[[],objNull]</span>, <span style="color:indigo;">[2,3]</span>] call BIS_fnc_param;
_unit doWatch _target;
* First two arguments are the same as you used when selecting the param manually - <span style="color:green;">source array</span> and <span style="color:darkorange;">index</span> number.
* Third argument is the <span style="color:teal;">default value</span>. It will be used when the argument is incorrect.
* Next is optional <span style="color:crimson;">array of compatible data types</span>. They are defined by an example of the type, e.g. [[objNull]] will mean an object is allowed. When wrong data type is sent into your function, BIS_fnc_param will log an error message explaining what went wrong and use the default value.
* The last, also optional argument is an <span style="color:indigo;">array of required array sizes</span>. [2,3] means only array with 2 or 3 elements are allowed. When incorrectly large array is sent into your function, BIS_fnc_param will log an error message explaining what went wrong and use the default value.
 
 
Let's see what will happen when you try to use the wrong examples now:
[player] call myTag_fnc_myFunction;
: ''_target'' is missing. Default [0,0,0] is used. No error message is logged.
 
[player,0] call myTag_fnc_myFunction;
: ''_target'' has wrong type. Default [0,0,0] is used. Error message is logged.
 
[player,[1,2,3,4]] call myTag_fnc_myFunction;
: ''_target'' has wrong size. Default [0,0,0] is used. Error message is logged.
 
=== Returning Value ===
 
=== Documenting ===
 
=== Debugging ===
==== Recompiling ====
Once compiled, functions remain unchanged and editing their file won't have any effect in the game. To adjust functions on the fly, you can manually triger their recompilation.
Once compiled, functions remain unchanged and editing their file won't have any effect in the game. To adjust functions on the fly, you can manually triger their recompilation.
  1 call [[BIS_fnc_recompile]];
  1 call [[BIS_fnc_recompile]];
Line 209: Line 264:
  allowFunctionsRecompile = 1;
  allowFunctionsRecompile = 1;


=== Loading Parameters ===
==== Showing Error Messages ====
 
=== Debugging ===


=== Adding Header ===


<!--
<!--

Revision as of 17:03, 3 August 2013


Arma 3 Functions Library is pack of routine script functions available from anywhere in game. Main difference from older Functions Library is that it runs automatically and doesn't require Functions manager to be present.

Finding a Function

Functions Viewer

Before you can use a function, you first need to find it. The easiest way is to access the Functions Viewer:

  • In editor, click on icon editor functions.png icon or press Ctrl + F
  • In mission, access the debug console (automatically visible in pause menu of an editor mission) and click on FUNCTIONS button.

Once in the Functions Viewer, you can filter all available functions by location, projects and categories.

When you find the desired function, look at the code preview on the right. Every function has a header where you can find basic description of its functionality including required arguments, returned values and sometimes examples of use.

Template:note


Calling a Function

Functions can be launched in mission, intro and outro using this call or spawn commands:

_returnedValue = arguments call functionName;
arguments spawn functionName;

Arguments

Arguments are data sent into the function, affecting its behavior.

They can be mandatory or optional.

  • Mandatory arguments are required for function to run. When missing, the function usually stops and throws an error.
  • Optional arguments allows more detailed configuration. If you dont send them, the function will use pre-defined default values.

Template:note


For example, let's take a look at BIS_fnc_endMission, a function which ends a mission with animated closing shot. This is what the header says:

/*
	Author: Karel Moricky

	Description:
	Ends mission with specific ending.

	Parameter(s):
		0 (Optional):
			STRING - end name (default: "end1")
			ARRAY in format [endName,ID], will be composed to "endName_ID" string
		1 (Optional): BOOL - true to end mission, false to fail mission (default: true)
		2 (Optional):
			BOOL - true for signature closing shot (default: true)
			NUMBER - duration of a simple fade out to black

	Returns:
	BOOL
*/

As you can see, all arguments are marked optional and you can call the function without them.

[] call BIS_fnc_endMission;
This will result in successfull ending of type "end1", preceeded with the signature closing shot.
["end2"] call BIS_fnc_endMission;
Set the ending type to "end2", while keeping the other arguments intact.
["end2",false,false] call BIS_fnc_endMission;
Fail the mission without any effect, using "end2" type.


However, what should you do if you want to set the only last argument without affecting the previous ones? The solution is simple - put an empty variable nil on their place.

[nil,nil,false] call BIS_fnc_endMission;
Disable the closing effects, but keep the other aguments intact (successful "end1").

Template:note

Returned Value

Functions executed by call command can return back a value. Let's take a look at BIS_fnc_sideName:

/*
	Author: Karel Moricky

	Description:
	Returns side name

	Parameter(s):
	0: SIDE or NUMBER - either side or side ID

	Returns:
	STRING
*/

The function returns a String - localized name of a side.

_westName = west call BIS_fnc_sideName;
Variable _westName will now be "BLUFOR" (or other name, based on selected language)

Multiplayer

Functions executed using call or spawn command will run only on the computer which triggered them. If you'd wish to execute a function remotely on specific clients, use BIS_fnc_MP function.

[arguments,"functionName",target,isPersistent] call BIS_fnc_MP;

User Interface

Anywhere outside of running mission, refer to the functions stored in uiNamespace.

arguments call (uiNamespace getVariable "functionName");

Adding a Function

When writing a script, consider registering it into the Functions Library.

Main benefits uncludes:

  1. Automatic compilation upon mission start into a global variable - no need to remember direct paths to files.
  2. Anti-hack protection using compileFinal
  3. Listing in the Functions Viewer
  4. Advanced debugging options
  5. Optional immediate execution upon mission start, without need for manual call


Mission and campaign specific functions can be configured in Description.ext, while addon functions are defined in Config.cpp. Configuration structure is the same in both cases.

Tag

Functions are configured within CfgFunctions class. To prevent duplicities, every author must create a subclass with unique tag and place functions inside it. The tag name will be used when composing a function name.

class CfgFunctions
{
	class myTag
	{
	};
	class Anything
	{
		tag = "myTag"; // Custom tag name
		requiredAddons[] = {"A3_Data_F"}; // Optional requirements of CfgPatches classes. When some addons are missing, functions won't be compiled.
	};
};

Path

File Path

The easiest and the most transparent way is to set path for each function.

class CfgFunctions
{
	class myTag
	{
		class myCategory
		{
			class myFunction {file = "myFile.sqf";};
		};
	};
};

Compile function myTag_fnc_myFunction from the following file:

%ROOT%\myFile.sqf

Where %ROOT% is either mission root (where mission.sqm file is), or the game root (path to an addon is not included and has to be part of the file path, e.g., myAddon\myFile.sqf).

Folder Path

You can set folder path and leave the function paths undefined. The functions will then be loaded from the folder.

class CfgFunctions
{
	class myTag
	{
		class myCategory
		{
			file = "myPath";
			class myFunction {};
		};
	};
};

Compile function myTag_fnc_myFunction from the following file:

%ROOT%\myPath\fn_myFunction.sqf

myPath can be a folder or multiple folders, e.g., myFolder\mySubfolder

Default Path (Mission Only)

In a mission, you can leave also the folder path undefine and let functions be loaded from the default directory.

class CfgFunctions
{
	class myTag
	{
		class myCategory
		{
			class myFunction {};
		};
	};
};

This will try to compile function myTag_fnc_myFunction from the following file:

%ROOT%\functions\myCategory\fn_myFunction.sqf

Attributes

Apart from already mentioned file, function class can have additional attributes:

class CfgFunctions
{
	class myTag
	{
		class myCategory
		{
			class myFunction
			{
				preInit = 1; // 1 to call the function upon mission start, before objects are initialized
				postInit = 1; // 1 to call the function upon mission start, after objects are initialized
				recompile = 1; // 1 to recompile the function upon mission start
				ext = ".fsm"; // Set file type, can be ".sqf" or ".fsm" (meaning scripted FSM). Default is ".sqf".
			};
		};
	};
};

preInit and postInit atrributes are truly powerful ones, as they let you execute your function at the beginning of every mission. Use them with caution!

  • Any scripting error will prevent the mission from being loaded correctly
  • Server admins might blacklist your addon if they find out you're using the function for hacking.


Writing a Function

The most important thing to remember when writing a function is that other people than you are going to use it. Most of them won't understand how does it work, expecting it to does its job without problems.

Your function must be robust. It shouldn't allow passing arguments of incorrect Data Types in. When some values are incorrect, it should throw an error explaining what went wrong and how to fix it. And above all, its header must provide complete explanation of usage.

What is not documented, does not exist!

Loading Parameters

Arguments are the only way how to interact with your function. Let's now see how to make sure they are loaded properly.

We have this very simple function which will let a unit watch a position:

_unit = _this select 0;
_target = _this select 1;
_unit doWatch _target;

Expected way how to call the function is by correctly defining all arguments:

[player,[position myCar] call myTag_fnc_myFunction;

However, the function will break down when you try to send only one argument in:

[player] call myTag_fnc_myFunction;

Furthermore, using wrong data type will also lead to a problem:

[player,0] call myTag_fnc_myFunction;

Variabe _target expects position array in format [x,y,z]. Scripting error will appear when different number of elements is used:

[player,[1,2,3,4]] call myTag_fnc_myFunction;


As you can see there, the most common problems are:

  1. Param of wrong data type is sent
  2. Param is missing
  3. Param is an array expecting specific number of elements, but different number is sent

Rather than check for these exceptions yourself, you can use existing function BIS_fnc_param which will does it for you:

_unit = [_this, 0, objNull, [objNull]] call BIS_fnc_param;
_target = [_this, 1, [0,0,0], [[],objNull], [2,3]] call BIS_fnc_param;
_unit doWatch _target;
  • First two arguments are the same as you used when selecting the param manually - source array and index number.
  • Third argument is the default value. It will be used when the argument is incorrect.
  • Next is optional array of compatible data types. They are defined by an example of the type, e.g. objNull will mean an object is allowed. When wrong data type is sent into your function, BIS_fnc_param will log an error message explaining what went wrong and use the default value.
  • The last, also optional argument is an array of required array sizes. [2,3] means only array with 2 or 3 elements are allowed. When incorrectly large array is sent into your function, BIS_fnc_param will log an error message explaining what went wrong and use the default value.


Let's see what will happen when you try to use the wrong examples now:

[player] call myTag_fnc_myFunction;
_target is missing. Default [0,0,0] is used. No error message is logged.
[player,0] call myTag_fnc_myFunction;
_target has wrong type. Default [0,0,0] is used. Error message is logged.
[player,[1,2,3,4]] call myTag_fnc_myFunction;
_target has wrong size. Default [0,0,0] is used. Error message is logged.

Returning Value

Documenting

Debugging

Recompiling

Once compiled, functions remain unchanged and editing their file won't have any effect in the game. To adjust functions on the fly, you can manually triger their recompilation.

1 call BIS_fnc_recompile;
Recompiles all functions. Can be also achieved by clicking on RECOMPILE button in the Functions Viewer
"functionName" call BIS_fnc_recompile;
Recompile the given function

As a security measure, functions are by default protected against rewriting during the mission. This restriction does not apply in missions previewed from the editor and in missions with the following attribute in Description.ext:

allowFunctionsRecompile = 1;

Showing Error Messages