LE MANUEL DE L'EDITEUR

Découvrir l’édition de mission avancée

Introduction

ArmA 3 propose déjà depuis de nombreuses années de puissants outils d’édition à la volée, en temps réel comme le module Zeus*. Si autrefois concevoir un scénario était l’apanage d’une petite minorité déterminée, c’est désormais à la porté d’un grand nombre, ce qui est à l’évidence une excellente nouvelle pour la vitalité du jeu et des groupes de joueurs. Mais nécessairement ce plus grand volume, sauf à rompre avec toutes les lois naturelles, ne pouvait signifier une explosion de la qualité des scénarios. Ce genre d’outils, de manière inhérente à leur fonctionnement même, ne font qu’effleurer les possibilités du moteur, et comptent surtout sur l’attitude des joueurs, le roleplay, pour créer l’identité du scénario ou ses morceaux les plus avancés.

Le moteur portant ArmA 3, le RV Engine, vous propose un langage SQF puissant et solide, 2 300 commandes, des milliers de fonctions intégrées et de gigantesques cartes pour modeler le scénario de vos rêves. Vous pouvez allez bien au-delà de la simple équation, certes fondamentale, équipement – terrain – méchants. Vous pouvez créer des éléments de gameplay inédits et des ambiances incroyables. Vous pouvez créer des scénarios entièrement automatisés qui vous permettront à vous aussi, créateur, d’y participer et d’y découvrir directement l’expérience joueur si nécessaire à la progression de l’éditeur. Ce qui vous est proposé ici est simple et en même temps assez long : aller beaucoup plus loin. 

On y va ?

* Dans l’édition scriptée, cet outil est particulièrement utile pour debugger facilement.

Accès rapide

Pour ne pas rendre l’écriture de ce manuel trop dense (il l’est déjà suffisamment), je partirai du principe que le lecteur maîtrise les premiers aspects de l’éditeur d’EDEN. Je n’expliquerai pas les grandes bases comme comment placer une unité, mettre un point de passage etc..

Aussi, si vous ne comprenez pas tout particulièrement dans les premières parties du manuel, ne vous bloquez pas et acceptez cela. Certaines choses qui vous paraissent obscures seront détaillées plus tardivement. Il est parfois impossible de faire un focus sur un point sans avoir à recourir à d’autres notions. 

Ce manuel est disponible dés sa phase de rédaction. N’hésitez pas à revenir de temps en temps pour y découvrir les nouveautés !

Ouvrir sommaire (+ feuille de route)

A/ Une édition sans limites ?

B/ Donner du caractère à sa création

C/ Les outils nécessaires

A/ Le langage SQF

B/ Focus : les commandes

C/ Focus : les variables

D/ Focus : les conditions

E/ Focus : les boucles

F/ Focus : les listes

A/ Les instances d’exécution

B/ Scripter en multijoueur : la problématique des localités

C/ Les remoteExec

D/ Les fonctions

E/ Les scripts événementiels

F/ Les eventhandlers

G/ L’ordre d’initialisation

A/ Le recours à la pré-compilation

B/ Le spawn dynamique

C/ La simulation

D/ Tester efficacement la mission

A/ Animer les unités

B/ Jouer musiques et sons

C/ Ambiance aérienne

E/ Prendre une image d’illustration

F/ Réaliser une cinématique

A/ Organiser les objectifs

B/ Créer un système puissant de classes

C/ Faire un convoi

D/ Système de téléportation

E/ Créer des interactions : les addActions

F/ Un char, un joueur

PARTIE I : INTRODUCTION ET CONCEPTION

Retour au sommaire

A. Une édition sans limites ?

Quand vous débutez sur l’éditeur, partout où vous regardez vous trouvez des obstacles à la création de votre mission. D’ici quelques temps, quand vous maîtriserez le langage SQF et le comportement du moteur, ces obstacles seront progressivement levés. Il en demeurera cependant que vous rencontrerez plus ou moins vite : 

 

  • Les performances – C’est de loin le facteur le plus limitant dans l’édition. Par exemple, ici, l’esprit de nos créations a toujours été de réaliser des « batailles » importantes avec pourquoi pas des unités IA se battant entre elles. Il s’avère qu’il faut atteindre un bon niveau d’édition et maîtriser vraiment l’optimisation (que nous détaillerons plus tard) pour y arriver dans des conditions honorables ! Et bien sur cela n’évite pas tous les ratés ! Outre les combats, un grand nombre d’objets, de nombreux scripts exécutés au même moment, des échanges sur le réseau trop importants, bref tout ce qui peut foirer, rendra votre mission moins agréable. Vous serez alors surpris par les grandes différences entre vos tests et la sessions réelle. Nous tâcherons de vous éviter ces déconvenues au mieux.

 

  • Les limites du jeu – Vous les apercevrez clairement s’agissant des IAs. Vous les trouverez dans la physique. Et celles-ci ne sont pas sans liens avec les performances puisque le moteur utilise assez mal les ressources des machines. Les limites du jeu existent. Elles se rencontrent avec parcimonie ici ou là, souvent dans des secteurs spécifiques. Quelques exemples : le nombre de lumières dynamiques est assez fortement limité, le combat IA contre IA est un gouffre de performance, les IAs ne sont pas capables de se déplacer sur des structures construites, le JoinInProgress des joueurs peut poser un certain nombre de problèmes, etc.. Malgré tout, cela reste largement gérable. Il ne faut rien exagérer. 

B. Donner du caractère à sa mission

Qu’est ce qui démarque votre mission des autres ? En quelque mots, comment définiriez vous votre scénario ? Donner du caractère à une mission est précisément lui conférer une identité forte pour s’éloigner des contenus génériques, des poncifs et lieux communs, et faire vivre une expérience solide à vos joueurs qui leur laissera un souvenir spécifique. Y arriver nécessite deux habilités importantes à part égale.

 

  • Des compétences techniques : évidemment il faut avoir les moyens de ses ambitions. Autant dire que tout concept un peu spécifique, toute idée qui n’est pas une simple destruction ou un mouvement, nécessitera toujours l’usage de quelques commandes, nécessitera souvent de programmer du code. Cela ne devrait pas vous faire peur, vous allez voir qu’en réalité, ça n’est pas bien compliqué.

 

  • Des compétences conceptuelles : l’autre moitié réside dans votre capacité à imaginer. Une fois que vous vous sentirez libre et capable de faire ce que vous souhaitez, vous découvrirez le sentiment grisant de pouvoir modeler un scénario d’abord dans l’esprit puis de le réaliser concrètement sur le jeu. Aussi, plus vous réalisez des scénarios que vous jouerez, plus vous obtiendrez une expérience qui vous indiquera les bonnes pratiques et les mauvaises, ce qui marche pour les joueurs et ce qui ne fonctionne pas. 

Conseils de conception

  • Prendre du recul, se libérer l'esprit

    Préférez commencer à réfléchir hors éditeur. Libérez vous l’esprit ! A contrario, la vision du terrain risque de borner vos possibilités et de vous amener à une édition somme toute basique à base de simples mouvements et de combats non recherchés. Le terrain doit cadrer avec vos ambitions, pas l’inverse ! C’est la raison d’être même de cartes de plusieurs centaines de km².

  • L'Histoire vous fournit de beaux scénarios !

    Découvrir sur internet le récit d’opérations militaires est un excellent moyen de s’inspirer pour concevoir des scénarios complets et crédibles. Ces lectures vous permettront aussi de penser à des pans souvent peu exploités dans les missions. Par analogie, il en va de même avec les films.

  • Dessinez votre mission !

    Une fois que vous tenez une sorte de concept et des « macro » idées intéressantes, rendez-vous sur la carte puis poser des marqueurs sur vos différents objectifs. En quelque sorte, réalisez un croquis de votre mission entière sur carte. De cela en découlera deux choses : des « micro » idées nâitront et alimenteront les premières; enfin vous serez en mesure d’apprécier le rythme et la durée. 

  • Sortir du combat d'infanterie, densifier le gameplay

    On rentre ici sur le terrain des goûts mais tout de même ! Le combat d’infanterie pur, en plus d’être non réaliste, est éculé sur ArmA. Le fantassin n’est pas seul. Rajoutez des véhicules, des tourelles fixes à emporter, des drones, bref, utilisez les possibilités d’ArmA3 pour densifier les possibilités de gameplay ! Les joueurs vous remercieront !

  • Apportez un soin à l'ambiance !

    Des sons, des musiques, des combats ambiants, un briefing soigné, tout doit être réquisitionné pour immerger le joueur. C’est un des facteurs les plus importants pour l’amusement. Combien de fois ais-je pu voir des combats simples et similaires être vécu complètement différemment en raison des 20 précédentes minutes. 

  • PRO-GRE-SSEZ

    Il est courant de voir des éditeurs aux ambitions démesurées pour la réalisation de leurs premiers scénarios ! Faire un nombre trop grand de choses nouvelles a toute les chances d’aboutir à de grandes déceptions et de vous décourager, en plus de vous avoir grandement retarder. Comme tout, l’édition nécessite une maîtrise qui doit être progressive. Visez l’apprentissage d’un ou deux éléments nouveaux à chacune de vos missions. Pas d’avantage !

Erreurs de conception

  • Négliger l'existence d'un rythme

    La conception d’une mission doit inclure 3 sortes de moments : du relâchement, de la tension, du combat. Rendre les combats omniprésents fatiguera très vite le joueur. Les espacer par de trop longs moments d’attentes le sortira de son immersion d’autant plus si les combats n’ont pas d’envergure suffisante. Attention au rythme ! C’est une donnée à ne pas laisser au hasard ! 

  • Des introductions interminables...

    L’éditeur veut bien faire. Il s’imagine qu’une longue progression dans une zone déserte (avec peu ou pas d’ambiance) pendant 30 / 40 minutes intéressera le joueur. Erreur ! A durée égale de combats / moments calmes, mieux vaut-t-il les répartir en commençant assez vite la mission par une séquence d’action (qui n’est pas forcément du combat pur) et ensuite enchaîner des séquences plus tranquilles. On en revient au point précédent, faire attention au rythme. Initier une mission par une séquence lourde ou intense a le mérite d’immerger le joueur immédiatement, ce qui le rendra plus attentif à la suite, y compris à vos moments sans actions. J’ai par exemple pour ma part pu faire démarrer une attaque ennemie alors même que les joueurs qui se croyaient attaquants sortaient de leur base.. La surprise a été fortement appréciée !

  • Des objectifs trop espacés

    Sans même parler du rythme, marcher des heures en simple fantassin durant des périodes de pur transition présente assez peu d’intérêt pour le joueur selon les avis en général. Prévoyez soit des moyens de transports qui auront le mérite de diversifier la mission, ou alors des phases de transition réduites grâce à une plus grande proximité des lieux d’intérêts. 

  • Surestimer la vitesse de progression des joueurs

    Il semblerait qu’il soit bien plus courant de surestimer l’avancée des combattants que l’inverse ! L’éditeur se lance alors à corps perdu dans la réalisation de 4 / 5 objectifs enchaînés, parfois plus, qui ne seront jamais vus. Préférez réaliser 2 à 3 objectifs principaux, qui plus est d’une manière plus attentionnée, ceux-ci occuperont généralement vos joueurs pour 2 à 3 h tout compris. Votre mission en sera aussi beaucoup plus claire ! Evidemment, tout dépendra aussi beaucoup du groupe de joueurs en question. Vous seul savez. 

  • Trop de surprises sans surprise

    L’idée paraissait géniale ! Mais elle ressemblait aux 50 précédentes. Si l’éditeur se sert de tous les prétextes pour surprendre, les joueurs se méfieront toujours et ne seront plus surpris le moment voulu. La surprise est parfois qu’il n’y a pas de surprise !  

C. Les outils nécessaires

Wiki des fonctions

Cela ne vous servira pas tout de suite mais peut être utile pour la suite : toutes les fonctions utilisées en jeu. 

Wiki des commandes

Il y a plus de 2 000 commandes que vous trouverez toutes répertoriées là. 

Tous les assets

Le plus simple est bien sur de récupérer la classname d’un objet en jeu, mais parfois il peut être utile de consulter ce lien pour trouver une référence particulière comme celle d’un obus pour faire une explosion. 

Extracteur PBO

Pour compiler un PBO (format de mission une fois compressé) ou le décompiler, j’utilise PBO View. La encore il y a une myriade d’alternatives que vous pouvez trouver ici. Vous pouvez par exemple utiliser le très bon PBO Manager

Notepad++

Il est indispensable d’utiliser un outil comme celui là à la place de bloc note pour scripter. Il en existe des plus puissants (ex: Poseidon), mais Notepad++ est mon préféré grâce à sa simplicité et par habitude (surtout). 

Wiki des EventHandlers

Ce sont des outils puissants listés sur ce lien. 

PARTIE II : APPROCHE DU SQF

Retour au sommaire

A. Le langage SQF

ArmA incorpore deux langages : le SQS apparu dés le début de la série sur Opération Flashpoint et le SQF venu avec l’addon Resistance du même jeu. Le premier est aujourd’hui désuet et c’est donc l’autre qui est utilisé, le SQF, pour le nom très funky de Status Quo Function, nom de code d’opération flashpoint lors de son développement. 

Basiquement, le SQF a une structure très simple à base de commandes comprises dans des lignes. Ces dernières sont terminées par un point virgule (;). 

Hint "Ceci est ma première ligne";

Hint "Ceci est ma seconde ligne";

Dans cet exemple, le Hint est une commande qui affiche du texte signifié par "" lors de son exécution, le tout dans une ligne terminée par ;.

Avançons, pour structurer la programmation de ces commandes, celles-ci peuvent être incluses dans des conditions if (ma condition) then { j'exécute du code};, ou encore des boucles while {condition} do {j'exécute du code};. Il existe plusieurs variantes des conditions et des boucles que nous verrons dans leurs parties respectives. Notez qu’à proprement parlé, la structure est uniquement constituée de commandes et de points virgule. Les conditions et boucles sont des commandes en soit.

Bref, voici un exemple général.

Hint "Ceci est ma première ligne";

if (Alive player) then {Hint "Ceci est ma seconde ligne, avec une condition."};

while {Alive player} do {Hint "Ceci est ma troisiéme ligne, avec une boucle"};

Vous remarquerez que les bases de la structuration du SQF n’ont rien d’incompréhensible. Quant aux commandes comme Alive, vous les trouverez sur la page wiki et nous découvrirons exactement comment s’en servir dans le grand B.

Outre ces structures de bases, vous devez dés maintenant identifier dans la syntaxe, c’est à dire la manière d’utiliser le langage, les éléments courants :

Composants utilisés par les commandes

Les STRINGS " " (textes)

Il s’agit bêtement de textes toujours compris entre deux guillemets " ". A l’intérieur il peut être écrit n’importe quoi. Mais attention, vous devez prendre garde à ne pas casser la syntaxe. Admettons que vous souhaitez utiliser des guillemets de texte (comme pour un dialogue) à l’intérieur de ces guillemets de programmation. Vous devrez alors doubler les premières pour signifier au moteur qu’il s’agit d’un élément écrit. Ou bien à l’inverse, vous pourrez remplacer les guillemets de programmation par de simples apostrophes '

Hint "Je crois que pierre a dit ""Quel pignouf !"" ";

Ici, les guillemets de texte sont doublées.

Hint 'Je crois que pierre a dit "Quel pignouf !" ';

Ici, les guillemets de programmation sont remplacées par '.

Peu importe la manière, le résultat est le même en jeu si nous exécutons ces lignes dans la console de debugage en jeu :

Dans des cas particuliers, il peut y avoir 3 niveaux de guillemets à employer. Dans " ", vous utiliserez ' ', dans lequel vous utiliserez "" ""; 

Des blocks de code { }

Le code, dans une ligne, peut être contenu dans un ensemble formé par des { } (une sorte de guillemet incurvé). Il s’agit alors d’un ensemble de code qui peut être plus ou moins long et qui surtout forme un block indépendant du reste du script ou de la ligne. Par exemple voici un script complet (un seul fichier texte dont l’extension est en sqf) : 

Hint "Ceci est ma première ligne de code";

if (alive player) then

{

Hint "Ceci est ma première ligne de code dans ce second block indépendant";

Hint "Ceci est ma seconde ligne de code dans ce second block indépendant";

};

Hint "Ceci est une troisième ligne de code, la deuxième étant formée par le if then";

De manière imagée, vous êtes ici en présence d’un script dans le script, qui est indépendant mais qui peut évidemment interagir avec le script principal. Dans cet exemple, il y a deux blocks de code. Le premier formé par le tout. Le second compris dans les { }. Résultat, si le joueur est vivant, l’ensemble du script sera exécuté, mais si le joueur est mort, le deuxième block sera purement et simplement ignoré. La commande alive check en effet si l’objet testé est en vie. A l’intérieur de ces { } vous pouvez y mettre le code que vous souhaitez, sans restrictions. 

Des commentaires (// ou /* */)

Ces derniers servent à … commenter votre script. Il s’agit d’indications écrites à destination du lecteur qui n’ont aucune influence sur son exécution. Le moteur ignore ces lignes. Cela est très utile pour des raisons évidentes comme pouvoir se repérer dans un code assez long ou expliquer un fonctionnement un peu obtus pour quelqu’un d’autre ou soit même dans l’hypothèse d’une relecture ultérieure. 

Hint "Je crois que pierre a dit ""Quel pignouf !"" ";

// Cela est une première forme de commentaire. Le double // étant nécessaire à chaque ligne.

// Deuxième ligne de commentaires.

Hint "Je crois que pierre a dit ""Quel pignouf !"" ";

/* Cela est une seconde forme de commentaire généralement utilisée pour écrire plus longuement.*/

Des listes [ ]

Les listes (ou array en anglais) [ ] sont des conteneurs qui contiennent plusieurs informations séparées par des ,. Par exemple :

[unit1,unit2,unit3,unit4]

Vous les rencontrez le plus souvent sous forme d’arguments. Ces derniers sont le paramétrage d’une commande ou d’une fonction. Dans cet exemple, le joueur est téléporté à une coordonnée (toujours sous forme de liste) :

player setPos [1456,1464,0];

L’argument peut se trouver avant ou après la commande. Autre exemple avec un argument avant, ici une liste contient deux informations transmises pour l’exécution (execVM) d’un script particulier :

[element1,element2] execvm "monScript.sqf"; 

Une liste peut contenir n’importe quoi : du texte, des variables, du code, des chiffres ou même d’autres listes ! Ex : maListe = [element1,"element2",{element3},[element4],5]; 

Des variables

Les variables sont des conteneurs qui peuvent tout stocker. De part cette fonction, vous vous en servirez toujours pour programmer. Avec les commandes, il s’agit d’un des éléments les plus fondamentaux. Elles se trouvent partout. Enfaîte, vous vous en êtes même servis à de nombreuses reprises en utilisant par exemple this dans l’initialisation d’un objet. Le this est appelé variable magique car il fait toujours référence au « propriétaire » du lieu dans lequel il est mis.

La variable a donc un nom (qui a été déclaré) qui est ensuite repris ailleurs dans un script. Nous n’irons pas plus loin ici car nous allons justement les détailler dans le B de la partie suivante. Mais pour l’exemple, voici la déclaration d’une variable suivi de son usage. 

maVariable = "Un peu de texte contenu dans ma variable.";

hint maVariable;

Exécuté dans la console de debugage, le résultat (la commande hint sert à afficher du texte) sera affiché en haut à droite de l’écran « Un peu de texte contenu dans ma variable. ».

Le reste (divers)

  • Vous pourrez avoir besoin de classnames. Ce sont des noms techniques pour tous les objets du jeu y compris ceux des mods. S’agissant de l’équipement individuel, vous pouvez aisément les récupérer en allant dans l’arsenal (dans le menu ou directement dans EDEN), pour finalement faire un ctrl + c dans l’arsenal suivi d’un ctrl + v dans un fichier texte. Vous aurez alors la transcription scriptée de l’équipement que vous avez configuré. Vous pourrez récupérer toutes les classnames des armes, items etc… Ces dernières ressemblent par exemple à : "tf_anprc152" . Vous pouvez aussi récupérer la classname de n’importe quel objet ou véhicule dans EDEN avec le menu ouvert par le clic droit. 

 

  • Régulièrement vous aurez à spécifier un nom d’objet que vous aurez configuré avant. Pour à peu prés tous les éléments que vous posez dans EDEN, il vous est offert la possibilité de mettre un nom. Ce nom est tout simplement une variable. Pour y référer, vous devez écrire la variable tel quel, sans guillemets. Exemple, je place un soldat que je nomme sol1. Si je veux le tuer : sol1 setDamage 1. 

B. Focus : Les commandes

Les commandes sont des instructions que vous donnez au moteur de jeu. Vous les trouverez toutes ici. Elles sont les briques avec lesquelles vous allez organiser votre script. Pour connaître comment procéder vous devrez vous familiariser avec leur syntaxe que vous trouverez sur chaque page du wiki correspondante. On trouve 3 grands types de commandes. Non pas que le savoir soit utile, mais cela permet d’apprécier un peu divers exemples pour dresser un panorama de leur usage. 

Ne vous laissez pas impressionner par les noms des catégories et la longueur de cette sous partie. Tout ceci est plutôt un prétexte pour voir ensemble un panel varié de commandes et découvrir divers cas. 

');">

Les commandes nulaires (pas d'argument)

Ce sont les plus simples dans la mesure où elles n’attendent aucun argument et retourne quelque chose, un résultat, selon le même principe qu’une variable. Parmi elles on trouve la commande allUnits dont la page à consulter est ici

La description vous renseigne sur l’effet de la commande, ici « return a list of all units ». Cette commande créée donc basiquement une liste (indiquée sur le wiki à return value) comprenant toutes les unités de la mission. Sa syntaxe est très simple puisque vous apercevez qu’il n’y a que la commande en elle même (principe de la commande nulaire).

Vous devez dés maintenant être sensibilisé à l’optimisation. Cette commande, dans la mesure où elle retourne potentiellement beaucoup d’éléments, devrait être utilisée avec parcimonie et stockée dans une variable. En effet allUnits n’est jamais figée, chaque fois que la commande sera appelée le calcul sera réalisé. Ainsi dans votre script vous pourriez écrire : _maListe = allUnits; la variable _maListe contiendra alors toutes les unités qui existaient au moment de l’appel. Pour illustrer, voici deux exemples. A gauche, une méthode non optimisée, à droite une autre qui l’est.

On réalise ici une série d’opérations avec à chaque fois allUnits, ce qui contient beaucoup de calculs. 

{_x setPos (getPos player)} forEach allUnits;

if (count allUnits > 0) then {hint "La partie commence"};

{_x setDamage 1} forEach allUnits;

On stocke allUnits dans une variable (_mesUnits) au début du script, cela permet ensuite de réutiliser de manière beaucoup plus optimisée la liste générée. 

_mesUnits = allUnits;

{_x setPos (getPos player)} forEach _mesUnits ;

if (count _mesUnits > 0) then {hint "La partie commence"};

{_x setDamage 1} forEach _mesUnits ;

Remarquez que _mesUnits = allUnits;  contient une liste qui n’est pas actualisée. Si vous mettez cette commande en début de partie puis que vous utilisez 15 minutes plus tard _mesUnits, la liste sera toujours figée telle qu’elle était il y a 15 min. Il faudra alors remettre la ligne au début de votre block de code pour actualiser. 

Pour revenir proprement à ces commandes nulaires, vous en trouverez d’autres similaires comme allPlayers, allGroups, allDeads, allMines, date… Toutes n’ont aucun argument et retourne le statut de quelque chose à l’instant où elles sont exécutées. 

');">

Les commandes non nulaires (1 argument)

Encore une fois, le nom importe peu. En revanche, cela nous simplifie la vie pour catégoriser et maintenant s’intéresser à une catégorie plus complexe, les commandes à un argument. Un argument est une information complémentaire que vous joignez à une commande pour qu’elle se comporte en interaction avec.

Ces commandes non nulaires sont beaucoup plus courantes que les nulaires. Vous en avez déjà aperçu une avec hint qui a un seul argument, le texte compris dans des guillemets. Mais pour varier, intéressons nous à forceRespawn

Cette commande n’a pas été choisie au hasard : elle permet d’aborder un problème majeur de l’édition multijoueur. Vous apercevez en haut à gauche deux nouveaux symboles ( ). Ces informations sont essentielles pour connaître le comportement des commandes sur un réseau. Ce problème sera abordé au tout début de la troisième partie et représente l’un des fondamentaux. Néanmoins, commençons ici. AL signifie argument local. EG signifie effet global. Ainsi la commande doit être exécutée sur la machine de l’objet à faire réapparaître (argument local) et son effet (ici le respawn) sera connu de toutes les machines du réseau (car l’effet est global). Exemple simple, un forceRespawn player; mis dans un déclencheur serveur uniquement n’aura aucun effet sur le joueur puisque le déclencheur n’est connu que du serveur, la commande ne sera donc pas exécutée sur la machine du joueur. Bien sur, l’argument peut être lui aussi global et inversement, l’effet peut être local.

La syntaxe de la commande nous dit : forceRespawn UNIT. L’argument (UNIT) ne pourra être qu’une unité joueur ou IA mais pas un véhicule sinon le unit aurait été « OBJECT », beaucoup plus englobant. Return value nous dit « NOTHING », il n’y a donc rien à attendre ensuite de la commande que de produire son propre effet, là où allUnits nous envoyait une liste contenant toutes les unités. 

Deuxième et dernier exemple, la commande alive. Celle ci check si une unité est en vie ou non et retourne une variable booléenne (une variable soit TRUE soit FALSE). La syntaxe nous dit « alive OBJECT« , ce qui peut être n’importe quoi : une IA, un joueur, un véhicule vide, une maison placée, etc.. Pour illustrer un petit exemple dans lequel on check la vie d’une unité et on envoi un message en fonction du résultat. 

if (alive uniteTestee) then {hint "L'unité est en vie !"} else {hint "L'unité est DCD !"}; 

');">

Les commandes binaires (2 arguments)

Troisième et dernier niveau de difficulté, les commandes binaires. Pour faire court, elles ressemblent aux précédentes en plus compliquées. Ici nous allons prendre un exemple, la commande setPos. Cette commande va être un prétexte, à l’instar de la précédente, pour aborder un problème connexe : l’ordre d’exécution sur une même ligne. Comme des opérations mathématiques, le SQF connaît un ordre d’exécution qui peut être modifier grâce aux parenthèses. 

La syntaxe nous dit « object setpos pos ». Nous avons déjà vu « object », ce peut être n’importe quoi. Quant à « pos », c’est donc une position qui est toujours, comme nous l’avons précédemment écrit, sous forme de listes [ ]. Premier exemple d’utilisation très classique qui ne requiert aucune modification quant à l’ordre d’exécution.

player setPos [1566,15685,0];

Admettons maintenant que nous voulions modifier le positionnement du joueur en reprenant sa position mais en la modifiant légèrement, par exemple en hauteur. Il faudrait alors récupérer la position initiale et lui ajouter en axe Z (soit la hauteur) quelques mètres. 

player setPos [getPos player select 0, getPos player select 1, (getPos player select 2) + 10];

La commande select (dont la syntaxe est LISTE select INDEX) permet de prendre un élément dont la position dans la liste est précisée. La première position est 0 et non 1 (qui est donc la deuxième). 

Sans les parenthèses, le code ne pourrait tout simplement pas fonctionner. Cela donnerait : select 2 + 10. Le moteur ne le calculerait même pas pour obtenir un select 12. Pour cela il aurait fallu écrire select (2 + 10) et donc encore utiliser les parenthèses. Tout ceci parce que la commande prends la première information disponible. Les parenthèses sert donc à signifier que plusieurs éléments ne forment en réalité qu’une information qu’il faut d’abord traiter !

Si vous n’avez pas tout compris avec la commande select, ne vous triturez pas l’esprit. Revenez plus tard après avoir lu la sous partie focus sur les listes. 

C. Focus : Les variables

Les variables sont des boites dans lesquelles on peut y insérer à peu prés tout : code, autres variables, texte, liste etc.. On fait ensuite référence aux données contenues en utilisant l’identifiant de la variable initialisée.

Il existe plusieurs types de variables dont la portée sur le réseau ou dans le script même varie. J’entends par portée la capacité des autres (scripts ou même machines) à connaître l’existence de cette variable. 

');">

Créer une variable

Pour procéder vous la déclarez en mettant : identifiant = données; L’identifiant doit être un mot court (pour optimiser sa lecture), qui fait sens au regard de la donnée. Par exemple : 

monTexte1 = "Ceci est du texte que contient ma variable";

hint monTexte1;

Le résultat sera l’affichage du texte.

Devant l’identifiant de la variable, il est recommandé de mettre un tiret bas (_) pour préciser que cette variable est totalement locale à votre script. Elle ne sera connue d’aucun autre. Si vous souhaitez faire référence à cette variable ailleurs, vous ne devez donc pas mettre de tiret bas. En revanche si vous le faîtes, cela évite les conflits éventuels entre les noms. 

_monTexte1 = "Ceci est du texte que contient ma variable";

Si vous initialiser une variable locale directement dans un block de code, et comme nous l’avons vu un block de code est indépendant, alors celle-ci n’existera que dans celui-ci. Deux exemples pour comprendre cette subtilité : 

if (alive player) then {_monTexte1 = "Le joueur est en vie"; hint _monTexte1};

Dans cette configuration, le hint affichera bien le texte. 

if (alive player) then {_monTexte1 = "Le joueur est en vie"}; hint _monTexte1;

Dans cette configuration, le hint n’affichera pas le texte. Pour modifier une variable locale dans un block, il faut donc l’initialiser avant.

 

_monTexte1 = ""; if (alive player) then {_monTexte1 = "Le joueur est en vie"}; hint _monTexte1;

La variable étant initialisée au début, sa valeur sera bien mise à jour, le texte s’affichera. 

Dans certains cas, la commande private peut être utile. Si votre script qui utilise des variables locales utilise la commande call pour exécuter un block de code (nous verrons ca un peu plus tard), il se peut que vos variables locales soient identiques et se réécrivent. Pour empêcher ça voici un exemple : 

_monTexte = "1";

call { private _monTexte = "2"; };

hint _monTexte;

Résultat du hint : « 1 ».

_monTexte = "1";

call { _monTexte = "2"; };

hint _monTexte;

Résultat du hint : « 2 ».

Une variable non locale peut être rendue publique et connue à travers le réseau grâce à la commande publicVariable et ses dérivées. Cela peut être utile par exemple à l’intérieur d’une addAction qui est purement locale à celui qui l’exécute. On y reviendra dans la sous partie des localités. 

');">

Supprimer ou mettre à jour

Pour mettre à jour une variable vous n’avez qu’à la redéclarer avec la nouvelle donnée. Cela peut donner : _lesJoueurs = allPlayers; ici la variable reprendra la liste des joueurs actualisée au moment de son appel. Pour supprimer une variable, ce qui en pratique est très rarement nécessaire, vous pouvez mettre : _maVariable = nil.

D. Focus : Les conditions

A

E. Focus : Les boucles

A

F. Focus : Les listes

A

PARTIE III : APPROFONDISSEMENT DU SQF

Retour au sommaire

A. Les instances d'exécution

PARTIE IV : OPTIMISATION

Retour au sommaire

A. Le recours à la pré-compilation

PARTIE V : LA PRATIQUE 1 - AMBIANCE ET APPARENCES

Retour au sommaire

A. Animer les unités

PARTIE VI : LA PRATIQUE 2 - GAMEPLAY

Retour au sommaire

A. Organiser les objectifs