Technical Standards for Core Code Contributions
Please note that this part is still heavily work in progress. For more dev related information please go to our Antistasi-Wiki-for-Devs.
Standardised Header
Standardised Header
/*
Maintainer: Maria Martinez, James Johnson
Calculates the logarithmic mean of the arguments.
Places a marker on the map where Petros is not standing.
Finally, concludes whether the player will win the next lottery.
Arguments:
<STRING> The first argument
<OBJECT> The second argument
<SCALAR> Float or number in SQF.
<INTEGER> If the number cannot have fractional values.
<BOOL> Optional input (default: true)
<ARRAY<STRING>> Array of a specific type (string in this case).
<STRING,ANY> A key-pair as compound type, shorthand by omitting ARRAY.
<CODE|STRING> Optional input with synonymous types, string compiles into code. (default: {true})
<STRING> Optional singular String input | <ARRAY> Optional Array input (default: [""])
<CODE<OBJECT,SCALAR,SCALAR,STRING>> Code that takes arguments of an object, a scalar, a scalar, and returns a string.
Return Value:
<BOOL> If the player will win the next lottery.
Scope: Server/Server&HC/Clients/Any, Local Arguments/Global Arguments, Local Effect/Global Effect
Environment: Scheduled/Unscheduled/Any
Public: Yes/No
Dependencies:
<STRING> A3A_guerFactionName
<SCALER> LBX_lvl1Price
Example:
["something", player, 2.718281828, 4, nil, ["Tom","Dick","Harry"], ["UID123Money",0], "hint ""Hello World!"""] call A3A_fnc_standardizedHeader; // false
*/
Maintainer is the person/people who (mostly) knows how the current code works. People who contributed: Localisation; Refactors; Small bug; etcetera; fixes do not go here. The maintainer list is updated when the code has rewritten/overhauled by a new person/people and the previous maintainer(s) will not be able to assist in troubles concerning the current code.
Remove unused fields.
Public: Yes
means this function is not tied to a complex system but can be freely called by other code/debug console.It is not necessary to specify exact code/array structure (just
<CODE>
or<ARRAY>
). However, a specific structure makes it clear what is expected/returned.It is not normal to have 10 arguments. The majority of humans can only subitise ~5 items, use that as a guide.
Standardised Variable Types
Standardised Variable Types
Because SQF is a small dynamically typed scripting language, there is no default design in of structures and variable types. I have created this guideline to clear the confusion about how to express variable types for function. The following syntax design is inspired by C# Func<> delegates(Except that name/description is coming after the type).
Simple Types
<ARRAY> banList
<BOOL> easyMode
<CODE> crateFiller
<CONFIG> uniformParent
<CONTROL> vehicleBuyMenu
<DISPLAY> currentPlayerMenu
<GROUP> AIPatrol
<LOCATION> village1
<OBJECT> Petros
<SCALAR> chanceOfSuccess
<SCRIPT> waitForSleep
<SIDE> invaders
<STRING> plainMessage
<TEXT> fancyText
<NAMESPACE> storageLocation
<DIARY_RECORD> howToGetStartedGuide
<TASK> defendPetros
<HASHMAP> vehicleEnums
<NIL> Usually used when a function provides no meaningful return.
<ANY> Accepts any type, including nil.
<T> Generic Type
<T#> Generic Type if multiple are required, substitute # with an integer.
These names are based on the return of typeName
engine command. Variable names/description go after the the . UPPERCASE capitalisation is not strictly required.
Variables in Arrays
<ARRAY<STRING>> badList
<ARRAY<SCALAR>> weightedSelectionValues
Arrays passed to functions are expected contain certain types. Just <ARRAY>
will not provide enough information.
Anonymous Structs
<SCALAR,SCALAR,SCALAR> A position or vector.
<ARRAY<SCALAR,SCALAR,SCALAR>> A list of positions or vectors
<STRING,ANY> A key-value pair.
<ARRAY<STRING,ANY>> A list of key-value pairs
Arrays can be used to pass around structured data. Such as a position, that has to maintain the same order and only 3 values. In this case <ARRAY<SCALAR>>
will not do.
Named Structs
Some structs are common enough that almost everyone working with SQF will know what they are. This can provide a great simplification. PascalCase capitalisation is not strictly required.
<PosATL> A 3D position of Type 'Position above terrain level'
<PosAGL> A 3D position of Type 'Position above ground level'
<PosASL> A 3D position of Type 'Position above sea level'
<Vec3> A 3D position or vector
<Pos2> A 2D position or vector, such as marker positions.
<Vec2> A 2D position or vector, such as marker positions.
<ARRAY<Pos3>> A list of positions or vectors
<KeyPair> A key-value pair
<ARRAY<KeyPair>> A list of key-value pairs
Details about the different position system can be found in the biki. The required position system should be mentioned in the header.
Feel free to add common and strongly defined types here:
<Pos#>
A collection of scalars where # represents the number of dimensions:[4,2,0]
<Vec#>
A collection of scalars where # represents the number of dimensions:[4,2,0]
<KeyPair>
A key-value pair. Use ingetVariable
, andhashMap getOrDefault x
:["keyName",someValueOfAnyType]
<Map>
An unordered array of key-value pairs. Use increateHashMapFromArray
:[["key1",value1],["key2",value2]]
<KeyPair<T>>
A key-value pair where all values are of the same defined type.<Map<T>>
An unordered array of key-value pairs. Values’ type are specified:[["key1",0.5],["key2",0.9]]
<UnitLoadout>
https://community.bistudio.com/wiki/Unit_Loadout_Array
Code Params and Return
Passing code around as delegates is required event handlers and actions. Specifying the parameters and return of code will be useful in it’s required in SQF function. In order to shorten and simplify, <>
may be omitted if it is not an unnamed struct. The following syntax is inspired by C# Func<> delegates as C++ delegates are a mess.
_fnc_paired_selectRandom = {
(_this apply {_x#0}) selectRandomWeighted (_this apply {_x#1});
}
If we wanted to accept a matching param and return signature, it could be expressed as:
<CODE<ARRAY<STRING,SCALAR>,STRING> A select random weighted function.
Generic Functions
The above function does not care what type the values are, as they are just selected at random out an array. However, the return type is linked to the the input type. The params are first and return value last. The following is inspired by C# generics.
_fnc_map_selectRandom = {
selectRandom _this; // Does not care what type the values are
}
If we wanted to accept a matching param and return signature, it could be expressed as:
<CODE<Map<T>,KeyPair<T>> A select random weighted function that takes any value type.
Sometimes multiple generic types may be required:
_fnc_swap = {
param ["_var1","_var2"];
[_var2,_var1];
}
If we wanted to accept a matching param and return signature, it could be expressed as:
<CODE<T1,T2,<T2,T1>> A select random weighted function that takes any value type.
Languages and Localisation
Languages and Localisation
Getting started
Localisation in ARMA means the game will try to load the correct language for the version of the game it is currently using. By adding translations, or localisations to this project, we can make it easier for for all players to get involved and use this Mission.
A technical overview of Localisation can be found here.
Contributing to Localisation
For this example I will use the Version number of Antistasi, as this changes frequently and requires manual adjustment each release.
<Container>
<Key ID="STR_antistasi_credits_generic_version_text">
<Original>1.4c2.0</Original>
</Key>
</Container>
Key Setup There are two main parts to setting up localisation, the KEY and the Text. From the example we can see the following information.
Key : STR_antistasi_credits_generic_version_text
Original : 1.4c2.0
The Key is used to identify the text you wish to display in game. By default all Keys in Antistasi should follow a standard convention, using following pattern where possible.
Prefix:
STR_antistasi_
Area of code:
credits_generic
Item name:
version
Type:
text
From this you can easily determine that this code belongs to “Antistasi”, is used in the “Generic Credits” module and contains the “Version” “text”.
Text Setup
The second part of localisation, is the text. This is the actual information which is going to be displayed to users, from the Stringtable when the variable is called.
When creating a new, or change an old KEY, it needs to contain <Original></Original>
as a minimum. The Original
tag implies the default value to be displayed for all game clients, if their default language is not found.
Currently our version will display the following to all game clients, regardless of their language settings. Adding additional languages requires the use of a new tag containing the language you wish to use. For this example we will use English.
Our version example is currently:
<Original>1.4c2.0</Original>
Adding an English localisation can be done with:
<Container>
<Key ID="STR_antistasi_credits_generic_version_text">
<Original>1.4c2.0</Original>
<English>1.4c2.0.6</English>
</Key>
</Container>
Note: There are a limited selection of supported languages for localisation.
Note
Whilst we will make an effort to verify the translations provided, it relies on user input and cannot be guaranteed. If you find any problems, please raise an issue!
Reviewing Pull Requests
Reviewing Pull Requests
The style of reviewing code is very different per person. However, here is an example for getting started:
Overview
I take 7 skims (quickly reading and not paying much attention) over the code looking for these things:
* [ ] Indentation & Headers
* [ ] Naming Conventions & Grammar
* [ ] Macros
* [ ] Param & Call
* [ ] Global Variables
* [ ] Local Variables
* [ ] Logic (Will take the longest)
Equipment
I have lined paper or an Excel spreadsheet to take notes.
Coffee or Tea is a good review parter.
Indentation & Headers
This only applies to new or rewritten functions.
Indentation must be in spaces. 4 spaces is normal. However, if there are a lot of indentation (Barbolani’s if-else chaines), then less spaces are acceptable. I use Visual Studio Code to Check-Out the Pull-Request, then I search for the tab character so it will be highlighted.
Headers must attempt the standard header.
Not all of the header information is necessary. The most important lines are:
Author
(original author and people who might of helped him/her)Arguments
&Return
Value (Does not need to be as specific asStandardised-Variable-Types
. For example just<ARRAY>
would be fine. All arguments inparam
must be listed here.)Environment
(This is important, if it usessleep
it cannot be run from the debug console)
Naming Conventions & Grammar
People should not name their variables
_a
,_69
,_someUnrelatedName
,_bbv
,_bbc
. The variable name should describe what it holds.Grammar is not important, and only matters when text is displayed to the player, using
A3A_fnc_customHint
,systemChat
ect.
Macros
Macros are not common. When they are used, just check that they are correct and will not cause problems.
Param & Call
Double check that the arguments for call
match the param
in the function. Check that the function always returns the expected type.
Global Variables
All global variables created must be prefixed.
banList
will not be accepted, it must beA3A_banList
.Check that global variables are always created before they are used.
Tell the author if there are possible race-conditions. Usually when clients modify arrays and then broadcast with
publicVariable
orsetVariable [name,value,true]
Local Variables
All must be declare with
private
.Check that a local variable is not used in a
spawn
as it will not be defined in that scope.
Logic
No syntax errors.
No undefined edge-cases.
Does not need to be 100% optimised. But it cannot be slow when there is a better way to code a function. (Check nested
findIf
,forEach
,forFrom
, multiplenearObject
ect.)Make sure everthing works as expected.