Lou Montana/Sandbox – User

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Almost release?)
m (Page cleanup)
Tag: Replaced
Line 1: Line 1:
[[Category: Sandbox]]
[[Category: Sandbox]]
{{Informative | Future [[Code Best Practices]] page}}
{{wip}}
----
{{SideTOC}}
{{Stub}}
[[:Category: Scripting Topics]]
== Getting started ==
In the domain of development, any rule is a rule of thumb.
If a rule states for example that it is better that a line of code doesn't go over 80 characters, it doesn't mean that any line '''''must not''''' go over 80 characters; sometimes, the situation needs it.
If you have a good structure, '''do not''' change your code to enforce a single arbitrary rule.
If you break many of them, you may have to change something; again, this is according to your judgement.
With that being said, let's go!
=== Prerequisites ===
* An advanced text editor such as Visual Studio Code or Notepad++ (see [[Debugging Techniques#Code Edition|Debugging Techniques' Code Edition chapter]] for useful plugins)
* Some English knowledge, helped if needed by a translator tool such as [https://www.google.com/translate Google Translate] or [https://www.deepl.com/ DeepL]
* Access to this wiki is a plus (the Swiss flag is, too)
* Tutorials/examples (YouTube tutorials, community tutorials, [[:Category:Example_Code|Example Code]])
* Google-Fu (a.k.a search engine skills)
* {{arma3}} Discord channel: [https://discord.gg/arma ARMA], channel <tt>#scripting</tt>
== Best practices ==
=== Code format ===
* Whatever you do about your code's format, '''be consistent'''.
* Choose an indentation format '''and stick to it'''. There is not especially one indent better than another (''but there sure are terrible ones''), again the important point here being ''consistency''.
** Common indentation styles are:
*** [https://en.wikipedia.org/wiki/Indentation_style#K&R_style K&R style] indenting
*** [https://en.wikipedia.org/wiki/Indentation_style#Allman_style Allman style] indenting
** Use empty space. Line return, spaces before and after brackets, if this improves readability, use it: space is free.
** indent with two/four spaces '''or''' one tab. Do not mix these.
** ''One-lining'' (putting everything in one statement) memory improvement is most of the time not worth the headache it gives when trying to read it. Don't overuse it.
* {{Inline code|<span style{{=}}"background-color: #FCC">'''0 {{=}}''' </span>''myCommand''}} is "useful" only for editor fields that for no apparent reason refuse commands returning a value. You do '''not''' need it in script files.
=== Variable format ===
* Name your variables and functions properly:<!--
--> While [[SQF syntax|SQF]] ''is'' (non-noticeably) impacted by variable name length, this should not take precedence on the fact that code must be readable by a human being.
** Your variable names must have a meaning: variables like '''_u''' instead of '''_uniform''' should not exist. '''_i''' is an accepted iteration variable name (e.g in [[for]] loops).
** It is recommended to use [https://en.wikipedia.org/wiki/Camel_case camel-case] your variables;<!--
--> camel-casing (namingLikeThis) your variables and functions make the code naturally more readable, especially for long names.
* Prefix your public variables and [[setVariable]] with your tag in order to avoid any conflict about other mods, scripts or mission variables.
* Make your variables '''private''' thanks to the [[private]] or [[params]] keyword in order to avoid accidental upper-scope overwriting of variables of the same name.
* Defined constants must be UPPERCASE_WITH_UNDERSCORES (e.g {{Inline code|#define SOME_CONST}}).
=== Code structuration ===
* '''DRY:''' '''D'''on't '''R'''epeat '''Y'''ourself. If you write the same code block or the same logic many times, export this code as a function and use parameters with it.
** If your code has too many levels, it is time to split and rethink it<!--
--> (e.g {{Inline code|[[if]] (a) [[then]] { [[if]] (b) [[then]] { [[if]] (c) [[then]] { {{codecomment|/* etc */ }} }; }; };}}...)
** Do NOT use [[PreProcessor Commands#Macros|macros]] as functions - these hinder readability. Use functions instead.
* {{codecomment|Comments}} in your code must not explain ''what'' the code does, but ''why'' it is done this way (if needed).<!--
--> Your code organisation combined to your variable names must be enough to be read by a human.
=== Code/Files organisation ===
* Use [[Arma 3 Functions Library#Adding a Function|CfgFunctions]] to declare the functions that will be called frequently.
** One Functions directory, with sub-directories if needed.
* Use [[Event Scripts]] as needed.
* Don't put '''any code''' in a unit's init box ''but eventually'' [[local]] commands for this specific unit - '''all''' unit's init boxes are run client-side on client connection.
== Examples ==
<!--
EDITOR'S NOTE: Formatting Code examples are not linking commands on purpose! This allows for a fair comparison of both syntaxes' readability.
-->
{| class="bikitable"
! <big>Bad Example</big>
! <big>Good Example</big>
|-
! colspan="2" |
<small>
=== Good Practice examples ===
</small>
|-
| <code>_unit = player;</code>
| <code>'''private''' _unit = player;</code>
|-
| <code>private _uB = allUnits select { side _x == blufor };</code>
| <code>private '''_bluforUnits''' = allUnits select { side _x == blufor };</code>
|-
| <code>private _plead = leader player;</code>
| <code>private '''_playersLeader''' = leader player;</code>
|-
| <code>finalAssault = true; publicVariable "finalAssault";</code>
| <code>'''PREFIX_'''finalAssault = true; publicVariable "'''PREFIX_'''finalAssault";</code>
|-
| <code>player setVariable ["MoneyInPocket", 250, true];</code>
| <code>player setVariable ["'''PREFIX_'''MoneyInPocket", 250, true];</code>
|-
|
<code>#define KILL(UNIT) UNIT setDamage 1<br>
(...)<br>
{
KILL(_x);
} forEach (units group player - [player]);</code>
|
<code>private _killFnc = { _this setDamage 1; };<br>
(...)<br>
{
_x call _killFnc;
} forEach (units group player - [player]);</code>
|- style="vertical-align: top"
|
<code>{{cc|if player has less than 3/4 health}}
if (damage player > 0.25) then
{
{{cc|if the player has no first aid kit}}
if (not ("FirstAidKit" in items player))
{
{{cc|if player has room for first aid kit}}
if (player canAdd "FirstAidKit") then
{
{{cc|add first aid kit to the player}}
player addItem "FirstAidKit";
}
else
{
{{cc|set player's damage to 1/4}}
player setDamage 0.25;
};
};
};</code>
|
<code>{{cc|player will need health at this stage of the mission}}
if (
damage player > 0.25 &&
not ("FirstAidKit" in items player)) then
{
if (player canAdd "FirstAidKit") then
{
player addItem "FirstAidKit";
}
else {{cc|let's help him anyway}}
{
player setDamage 0.25;
};
};</code>
|-
! colspan="2" |
<small>
=== Flow Logic examples ===
</small>
|- style="vertical-align: top"
|
<code>if (alive player && damage player >= 0.9) then {
hint "very damaged";
};
if (alive player && damage player >= 0.5 && damage player < 0.9) then {
hint "quite damaged";
};
if (alive player && damage player > 0 && damage player < 0.5) then {
hint "slightly damaged";
};
if (alive player && damage player == 0) then {
hint "pristine state";
};
if (not alive player) then {
hint "dead";
};</code>
|
<code>if (not alive player) exitWith { hint "dead"; };<br>
private _playerDamage = damage player;
switch (true) do {
case (_playerDamage >= 0.9): { hint "very damaged"; };
case (_playerDamage >= 0.5): { hint "quite damaged"; };
case (_playerDamage > 0)  : { hint "slightly damaged"; };
default { hint "pristine"; };
};</code>
|-
! colspan="2" |
<small>
=== Format examples ===
</small>
|- style="vertical-align: top"
|
<code>if (not alive player) exitWith
{ hint "dead"; };<br>
private _playerDamage = damage player;
switch (true) do {
case (_playerDamage >= 0.9): {hint "very damaged";};
case (_playerDamage >= 0.5): {
hint  "quite damaged";};<br>
case (_playerDamage > 0): { hint "slightly damaged"; };
<nowiki>  </nowiki>default
{<br>
<nowiki>    </nowiki>hint "pristine";
<nowiki>  </nowiki>};
};</code>
|
<code>if (not alive player) exitWith { hint "dead"; };<br>
private _playerDamage = damage player;
switch (true) do {
case (_playerDamage >= 0.9): { hint "very damaged"; };
case (_playerDamage >= 0.5): { hint "quite damaged"; };
case (_playerDamage > 0)  : { hint "slightly damaged"; };
default { hint "pristine"; };
};</code>
|}
== Final words ==
* Remember: '''consistency''' is the most important thing!
* The {{arma3}} Discord channel and its community can help: [https://discord.gg/arma ARMA]
* Learn from others' scripts but don't steal code and pretend it's yours — be a decent human being. Stealing code and its consequences:
** It soils your reputation and devaluates your actions once it is found out — and it ''always'' get found out. DMCA's are filled on Steam every day.
** It makes people in the community get less helpful and more reluctant in giving advices. It can also prevent them to ''release'' an interesting feature!
* Don't try to obfuscate your code: it is considered rude, especially since you learnt from others.
** Obfuscated code only makes it ''harder'' to get, but does not make it ''copy-protected''. If the engine can read it, it can be obtained.
** Obfuscated code is also slower on compilation (and, depending on the quality of code and obfuscation, on execution too).
* Most of all, have fun!

Revision as of 19:57, 12 September 2019