User Tools

Site Tools


arma2:scripting

This is an old revision of the document!


Scripting

ArmA 2 will be largely compatible with Armed Assault. To make porting of content from ArmA as simple as possible, there are few important things:

  • using of undefined variable in scripts (nil value) will be in ArmA 2 strictly reported as an error. All variables used in any scripts must be initialized before first use.
  • in ArmA 2 namespaces will be introduced for user scripts and variables. There are many low level reasons to do this and most of the content will be not be affected by this in any negative way. However, in order to be prepared, it is very important to separate UI related scripts and code as much as possible and not simply share global variables between UI and missions as UI namespace needs to be handled differently.
  • in order to maintain smooth frame rate in real-time content, time limit for all scripts in each frame is enforced by the engine in ArmA 2. Generally speaking, in case of more demanding scripts, be prepared that their result may come way later and also there probably can suffer from significant latency. It is under evaluation if and how possibly allow user scripts to change how much time they may take from the CPU in every frame.
  • SQS script format will be fully supported in ArmA 2.

initJIPcompatible.sqf is automatically started at unknown time, best guess would be when JIP player joins?

Scripting Commands

There's a lot of cool scripts (functions) available in Modules.pbo - especially under “Functions” and even an multiplayer Framework in “MP”.

Since ArmA 2 you must first initialize a variable before you reference it in your scripts. In ArmA, it was not a problem, at least for conditions.

// this will error if myBoolean was not previously defined.
if (myBoolean) then { hint "test" };

Usage of isNil is still valid.

BIS fnc locations

BIS fnc locations

Description: Creates or registers location logics (used in various modules, like Ambient Civilians, Ambient Civilian Vehicles or Warfare 2).

Upon registering, function will set following variables into location logic's variable space:

  • “class” - unique class of location (either BIS_loc_<configname> or BIS_loc_custom_<ID>)
  • “name” - name of location from config or setName command. If none is defined, class is used
  • “type” - config type
  • “neighbors” - config defined neighbor locations

If you're registering currently existing object and some of variables above is already stored in it, it won't be replaced.

Syntax

Syntax: [type(s),area,debug] call BIS_fnc_locations

Parameters: type(s): String or Array of strings
area: Array in format [center,distance]
debug: (Optional): Boolean

Return Value: Array - List of registered locations

Alternative Syntax

Syntax: [objects] call BIS_fnc_locations

Parameters: objects: Array of Objects or Locations - list of specific locations to be registered

Return Value: Array - List of registered locations

Examples

Example 1:

["CityCenter",[position player,1000]] call bis_fnc_locations;

Example 2:

[["acityc_dolina"]] call bis_fnc_locations;

Example 3:

[[myLocation1,myLocation2],[],true] call bis_fnc_locations;

See also:

Functions Library (above hehe)

allowDamage

Description: Allow an object to be damaged (or injured, or killed).

Syntax: object allowDamage allow

Parameters: object: Object - allow: Boolean -

Example 1:

player allowDamage false

setVariable

setVariable now has a 3rd parameter: Global.

If you set the 3rd parameter to true, the variable will broadcast its value to every machine.

_myObject setVariable ["myVariable", 1, true];

setVariable is now usable on any object, like groups for instance. This was not the case in ArmA.

uiNameSpace

Working with UI related scripting commands, is not accepted in global or private variable space, and needs to be done inside uiNameSpace by using setVariable.

example:

// set it
uiNameSpace setVariable ["myVariable", ctrl...];
// use it
ctrl.... (uiNameSpace getVariable "myVariable");

createDiaryRecord

createDiaryRecord

_diary = player createDiaryRecord ["Diary", ["Technische Details", "Keine"]];

createSimpleTask

createSimpleTask

task1 = player createSimpleTask ["obj1"];

setSimpleTaskDescription

setSimpleTaskDescription

task1 setSimpleTaskDescription ["Description <marker name=""Start"">Start</marker> posit.","more text","more text"];

setSimpleTaskDestination

setSimpleTaskDestination

task1 setSimpleTaskDestination markerPos "Start";

setTaskState

setTaskState

task1 setTaskState "Created";

setCurrentTask

setCurrentTask

player setCurrentTask task1;

attachTo

attachTo, see also detach.

// Make player float exactly 2m above center of car, automatically changing vectordir + relative position as car moves.
player attachTo [car, [0,0,2]];
detach player;

diag_log

diag_log writes any variable ([_fish, _frog] or “Hello, I'm starting to initialize myself”) directly to the log, without needing to pass it via format/str and without any extra text.

Changing nameSpace

You can change namespace inside another namespace. Note that 1 misionNamespace refers to the normal global scope and 1 uiNamespace is the one where you are forced to store any control/display handles:

fish = "Frog!";
 
with uiNamespace do
{
	// Do some stuff with dialogs here.
 
	with missionNamespace do
	{
		hint fish; // This sees the "regular" mission namespace.
	};
	// Do some more stuff with dialogs here.
};

I have no idea what the purpose of 1 parsingNamespace is.

Access nameSpace

The command 1 with gives you a much nicer way to access namespaces and is especially cleaner when making multiple accesses:

with uiNameSpace do
{
	// Any globals in this block are taken from uiNameSpace.
	// Any locals are normal locals from current scope.
	(fishDisplay displayCtrl 102) ctrlSetText _frog;
	piesControl ctrlSetText _pies;
	cheeseControl ctrlSetText _cheese;
};

Rather than:

((uiNameSpace getVariable "fishDisplay") displayCtrl 102) ctrlSetText _frog;
(uiNameSpace getVariable "piesControl") ctrlSetText _pies;
(uiNameSpace getVariable "cheeseControl") ctrlSetText _cheese;

fromEditor

Return if given team was inserted directly from mission editor.

Syntax:

fromEditor teamMember

Parameters:

teamMember: Team Member

Return Value:

Boolean

Example:

_fromEditor = fromEditor _member;

addTeamMember

Add given member to given team.

Syntax:

team addTeamMember member

Parameters:

team: Team_Member
member: Team_Member

Return Value:

Nothing

Example 1:

_team addTeamMember _teamMember;

copyWaypoints

Copy the chain of waypoints from source to target group. The target group will start to process waypoints from the first one.

Syntax:

groupTo copyWaypoints groupFrom

Parameters:

groupTo: Group
groupFrom: Group

Return Value:

Nothing

execFSM

Execute the scripted FSM. The FSM file is first searched in the mission folder, then in the campaign scripts folder and finally in the global scripts folder. Returns the FSM handler or 0 when failed.

Syntax:

execFSM filename

Parameters:

filename: -

Return Value:

Number

Example 1:

execFSM "test.fsm";

Example 2:
execFSM:

hndl = [player] execFSM "group_follow.fsm";
</code?
 
execVM:
<code cpp>
hndl = player execVM "group_follow.sqf";

taskHint.sqf

How to make task hints

taskHint is relatively useless itself (because it requires too much effort), but there is a script that makes it easier to use. So instead of executing a hint, do this:

[objNull, objNull, tskExample1, "SUCCEEDED"] execVM "CA\Modules\MP\data\scriptCommands\taskHint.sqf";

The first 2 arguments are useless so i just send objNull, the 3rd is the task that you've created, and the 4th is the status.

Supported task states: “CREATED”, “CURRENT”, “CANCELED”, “SUCCEEDED” and “FAILED”.

  • This command does not set the state of the task, so you still need to do this command, and the setTaskState command in your trigger.
  • It creates the hint in the middle of the screen, not at the right side (this means that taskHint and hint can be used at the same time).
arma2/scripting.1279026790.txt.gz · Last modified: 2010-07-13 13:13 by snakeman