NWScript - pour niveau 1

Afin de dialoguer correctement avec notre ami l'éditeur de script, il vaut mieux comprendre quelle est la base de son langage. Ce n'est certes pas un dialecte aux sons harmonieux, mais vous pourrez ressentir la subtilité de chacun des mots prononcés lorsque vous vous familiariserez avec lui.

Nous apprendrons ce qu'est une variable, ce à quoi elle correspond, ainsi que les fonctions et la façon dont elles agissent. Nous verrons également les différents événements susceptibles d'exécuter un script. Enfin vous pourrez profiter de quelques petites conventions d'écriture tout au long de cette "leçon pour niveau 1".

Sachez que le temps n'est pas votre ennemi, et qu'une machine sera votre serviteur dévolu tant que vous parlerez son langage.



NWScript - Page générale

NWScript - pour niveau 1
- Bases et notions de programmation -

NWScript - pour niveau 2
- Conditions if/else et opérateurs ET / OU -

NWScript - pour niveau 3
- Boucles while/for et sélection switch/case -

NWScript - pour niveau 4
- Constantes, fonctions, et bibliothèques -

NWScript - pour niveau 5
- Variables persistantes et exécution de scripts -

Les commentaires :

Avant tout et parce qu'il est très fortement conseillé d'en user et d'en abuser, voyons les commentaires.

Un commentaire est une portion de texte qui n'est pas exécutée par l'ordinateur. Il y a deux façons de commenter :
// qui permet de commenter tout se qui se trouve derrière lui, et dans la même ligne.
/* et */, qui permettent de commenter tout ce qui se trouve entre eux, peu importe la taille du texte à commenter et l'endroit de début/fin sur une ligne.

Exemple:

Ligne non-commentée

// Ligne commentée

Partie de ligne non-commentée // Partie commentée

/* Ligne commentée
Ligne commentée */

Partie de texte non-commentée /* Partie
commentée */ Partie non-commentée

Partie de texte non-commentée /* Partie commentée */ Partie non-commentée.

Les variables :

Dans le langage de script de NwN, les variables sont typées. C'est à dire qu'une fois déclarées, elles ne contiennent qu'un seul type d'information. L'information contenue dans une variable peut être modifiée tant qu'elle reste du même type.

Voici les principaux types de variables :

Type de variable Valeur
int Nombre entier
float Nombre a virgule flottante
string Chaîne de caractères

D'autres types de variables existent, mais leur usage est néanmoins plus complexe que les précédentes :

Type de variable Valeur
object Objet du jeu (zone, créature, élément de décor, ...)
effect Effet spécial (magique, visuel, ...)
vector Position dans l'espace
location Localisation dans le module
itemproperty Particularité spécifique à un objet

Pour qu'on puisse l'utiliser, une variable doit au moins être déclarée. Il suffit d'annoncer son type, suivi de son nom. Le nom d'une variable peut comporter des lettres, des chiffres, ou encore certains caractères spéciaux, mais il ne doit pas comporter d'espaces. NWScript fait la distinction entre les majuscules et les minuscules. Ainsi, nVariable et NvARIABLE seront deux noms différents :

// Ma variable nVariable sera de type int (nombre entier) :
int nVariable;

Notez que j'ai ponctué la ligne par un point-virgule. Les lignes de commandes à exécuter sont toujours ponctuées de cette manière, quelque soit la complexité de ces lignes.

A partir du moment où la variable est déclarée, une valeur peut lui être attribuée à n'importe-quel endroit du script (pendant ou après sa déclaration). Pour lui donner une valeur, il suffit d'écrire le nom de la variable = sa valeur, le tout ponctué par un point-virgule. Pour attribuer une valeur au moment de la déclaration, il suffit d'annoncer le type au début :

// Pour une variable déjà déclarée :
nVariable = 1;

// Pour déclarer une variable en lui
// attribuant directement une valeur :
int nVariable1 = 1;

int nVariable2 = 2;

// etc. etc. etc.

On peut également modifier une valeur déjà existante :

// Je déclare ma variable
// et lui attribue une valeur :
int nVariable = 1;

// puis je la modifie :
nVariable = 2;

Il s'agit également de savoir comment écrire la valeur d'une variable. On pourra remarquer que seules les valeurs de type "int", "float", et "string", pourront être directement inscrites. Pour les autres types de valeur, il faudra passer par une fonction.

Pour les trois types de valeurs mentionnés, on aura donc :

- Les valeurs de type "int", représentant un nombre entier (sans virgule) compris entre - ∞ et + ∞.

- Les valeurs de type "float", représentant un nombre à virgule compris entre - ∞ et + ∞. Une valeur de type float devra incorporer obligatoirement une virgule, même s'il n'y a rien derrière cette virgule (1 s'écrira donc 1.0). Notez qu'on utilisera un point pour séparer les unités des décimales, et non une virgule.

- Les valeurs de type "string", représentant une chaîne de caractères. Cette chaîne sera entre guillemets, et n'importe quel caractère pourra y être inséré à l'exception de quelques exceptions. Une chaîne de caractère peut comporter des espaces. Notez qu'il ne faut surtout pas incorporer d'autres guillemets dans la chaîne de caractères, mais il est toujours possible d'y insérer deux apostrophes à la suite afin de tromper l'oeil.

// Variable de type "int" :
int nVariable = 1;

// Variable de type "float" :
float fVariable = 1.0;

// Variable de type "string" :
string sVariable = "un";

Remarquez également la manière dont j'ai nommé mes variables. Le choix de mettre un "n" pour les variables "int", un "f" pour les variables "float", et un "s" pour les variables "string", vous appartient entièrement. Il s'agit là d'une convention d'écriture totalement arbitraire. Vous pouvez aussi bien nommer une variable "Platabrouf", "Brubidule" ou "Alfred". La lettre que j'ai rajoutée devant son nom me permet simplement de me rappeler son type, dès que je la regarderai.

Les préfixes suivant sont les plus fréquemment utilisés :

- "n" pour une variable de type "int"
- "f" pour une variable de type "float"
- "s" pour une variable de type "string"
- "o" pour une variable de type "object"
- "e" pour une variable de type "effect"
- "v" pour une variable de type "vector"
- "l" pour une variable de type "location"
- "i" pour une variable de type "itemproperty"

Les fonctions

Une fonction est une commande particulière, effectuant un travail bien précis. En général, NWScript offre un immense choix de fonctions nous permettant de faire un nombre incalculable de choses.

Les fonctions ont un type, au même titre que les variables, et renvoient un type de valeur qui leur est propre. La plupart du temps, les fonctions ont entre parenthèses des paramètres qu'il faut remplir. Ces paramètres doivent avoir un type de valeur précis. Chaque paramètre peut être rempli par une variable, ou même par une autre fonction renvoyant le type de valeur approprié. Notez que dans le cas de plusieurs paramètres, ceux-ci seront séparés par une virgule.


Exemples :

object GetFirstPC()

- Il s'agit d'une fonction de type "object", et renverra donc une valeur de type "object".
- Elle nous permet de retrouver le premier joueur dans la liste des joueurs connectés au module.


int GetIntelligence(object oTarget)

- Il s'agit d'une fonction de type "int", et renverra donc une valeur de type "int".
- Elle permet de retrouver quelle est la valeur d'intelligence d'un objet. Le paramètre oTarget devra donc être une variable de type "object". Pour que la fonction renvoie une valeur correcte, il vaudra mieux que l'objet ait une valeur d'intelligence, et soit donc une créature (logique).


On constatera donc que la valeur d'une fonction peut ainsi être rattachée à une variable du même type :

// Je désire mettre en variable le premier
// joueur de la liste des joueurs du module :
object oJoueur = GetFirstPC();

// ayant récupéré une variable de type objet, et sachant
// qu'il s'agit d'une créature, je l'utilise pour savoir
// quelle est la valeur d'intelligence de cet objet.
int nIntelligence = GetIntelligence(oJoueur);

Une fonction déjà présente dans la liste des fonctions de NWScript n'a pas besoin d'être déclarée, ni initialisée. Il est également possible de créer ses propres fonctions, mais c'est un sujet qui sera abordé plus tard.

Notez que toutes les fonctions ne renvoient pas forcément une valeur. En effet, les fonctions de type "void" se contentent juste d'exécuter leurs instructions.


void DoSinglePlayerAutoSave()

- Il s'agit d'une fonction de type "void", ne renvoyant donc pas de valeur.
- Elle nous permet d'effectuer une sauvegarde lors d'une partie mono-joueur.

Les événements

Un événement est un moment susceptible de déclencher l'exécution d'un script. Il existe une multitude d'événements étant rattachés à plusieurs sortes d'objet. Bien entendu si l'événement d'un objet est activé, il le sera uniquement cet objet. On peut consulter la liste des événements disponibles dans la page des propriétés de chaque objet. Il faut considérer les événements avec attention, car ils représentent le coeur du jeu. Sans événement, pas de script.

Voici la liste des objets susceptibles de lancer un script, et les événements qui s'y rattachent. J'énumèrerai l'ordre des événement tel qu'il est affiché dans l'éditeur.

En plus de ces événements, tous les objets ont un événement appelé "Script récurrent" qui se lance toutes les 6 secondes.


Evénements pour le module, déclenchés par :

  • le chargement du module
  • le lancement du module (événement inactif)
  • la connexion d'un joueur
  • la fin du chargement d'un joueur
  • la déconnexion d'un joueur
  • le repos d'un joueur
  • le moment où un joueur passe un niveau
  • la mort d'un joueur (lorsque ses points de vie sont en dessous de -10)
  • l'agonie d'un joueur (au moment où ses points de vie sont en dessous de 1)
  • le moment où le joueur appuie sur le bouton "Respawn" (événement devenu inactif)
  • l'acquisition d'un objet par un joueur
  • le moment où un joueur équipe un objet
  • le moment où un joueur retire un objet équipé
  • l'activation d'un objet par un joueur
  • la perte d'un objet par un joueur
  • l'annulation d'une cinématique par un joueur

Evénements pour plaçables et portes, déclenchés par :

  • un clic
  • l'utilisation
  • l'ouverture
  • la fermeture
  • le déverrouillage
  • le verrouillage
  • une attaque physique
  • un sort
  • des dégâts subis
  • la "mort"
  • le désarmement d'un piège
  • l'activation d'un piège
  • une conversation
  • l'échec d'ouverture (portes)
  • la modification de l'inventaire (plaçables)

Evénements pour zones, déclencheurs, et rencontres* déclenchés par :

  • un objet entrant
  • un objet sortant
  • la fin du chargement d'un joueur entrant (zones)
  • un clic (déclencheurs)
  • le désarmement d'un piège (déclencheurs)
  • l'activation d'un piège (déclencheurs)
  • l'élimination de toutes les créatures (rencontres)

* Une rencontre est semblable à un déclencheur, à ceci près qu'elle sert à gérer des créatures.


Evénements pour échoppes, déclenchés par :

  • l'ouverture
  • la fermeture

Evénements pour créatures, déclenchés par :

  • l'apparition en jeu (spawn)
  • la perception
  • une attaque physique
  • un sort
  • des dégâts subis
  • la fin du tour de combat
  • la fin du repos
  • la mort
  • une conversation
  • la modification de l'inventaire
  • un blocage dans les déplacement

Il existe un événement supplémentaire, appelé "défini par l'utilisateur". Il ne peut-être déclenché que par un autre script, et par une fonction bien précise. Cette fonction envoie un signal particulier, qui déclenche alors l'événement "défini par l'utilisateur".

Pour la totalité de ces événements, il est possible de savoir l'objet qui l'a provoqué. Les deux exceptions sont le "script récurrent", et l'événement "défini par l'utilisateur".


Débuter un script

Un script n'est pas une chose si compliquée en soi. A partir du moment où on respecte le langage utilisé et que l'on place ses repères, on peut faire des scripts simples sans trop se casser la tête. Il est donc fortement conseillé d'utiliser les commentaires pour se repérer. Planifier un script est également conseillé, afin d'avoir une idée globale de ce qu'on veut qu'il effectue.

Pour débuter, il faudra sélectionner sur l'onglet des scripts du module, et choisir l'option "ajouter" en faisant un clic-droit dans la fenêtre des scripts. Un nouveau script vierge fera son apparition, et s'ouvrira automatiquement :

image

Pour que le script soit valide, je l'écrirai après avoir déclaré la fonction principale, void main(). Grossièrement, cette fonction signifie : "voici ce qu'il faut exécuter". Cette fonction principale est délimitée par des accolades, comme ceci :

void main()
{
    // voici où je mettrai mon code à exécuter
}

Ceci signifie que le script est lui-aussi une fonction.

Pour simplifier les choses, et permettre des tests aisés, l'événement déclenché par "l'utilisation" d'un plaçable sera notre terrain de test. Cet événement se déclenche lorsqu'un joueur a cliqué sur un plaçable utilisable, et qu'il a terminé de s'en rapprocher.

Il faut aussi comprendre quel est l'objet exécutant le script, et quel est l'objet ayant provoqué l'événement. Nous avons donc la fonction OBJECT_SELF, qui représentera toujours l'objet exécutant le script. Ensuite, si besoin est, des fonctions particulières à chaque événement nous permettent de savoir qui l'a provoqué.

Dans cet exemple, je veux :
- savoir qui a utilisé le plaçable
- lui envoyer un message texte

void main()
{
    // La fonction "GetLastUsedBy()" nous permet de
    // connaître l'objet qui a provoqué l'événement
    // déclenché lors d'une utilisation.
    // C'est une fonction de type "object".
    object oJoueur = GetLastUsedBy();

    // Je définis une chaîne de caractères
    string sTexte = "Test réussi";

    // "SendMessageToPC(...)" est une fonction de type
    // "void", permettant d'envoyer une chaîne de caractères
    // dans la boîte de dialogue de l'objet précisé.
    SendMessageToPC(oJoueur, sTexte);
}

... que j'aurais très bien pu écrire de cette manière :

void main()
{
    SendMessageToPC(GetLastUsedBy(), "Test réussi");
}

Notez que si la mise en page n'est pas nécessaire pour un script, elle est fortement recommandée. Il vaut mieux qu'un script soit le plus lisible possible. J'aurais très bien pu l'écrire de la manière suivante :

void main(){SendMessageToPC(GetLastUsedBy(), "Test réussi");}

... Mais pensez bien que pour des scripts de grande taille, cela deviendrait particulièrement difficile à lire. Dans NWScript, vous pouvez utiliser la touche -Tab- de votre clavier pour faire avancer la marge pour une même ligne. Vous pourrez donc poser des repères visuels, vous permettant facilement de voir le début et la fin d'une instruction.


Une fois le script rédigé, il n'y a plus qu'à le compiler pour qu'il soit utilisable en jeu, puis le placer dans l'événement déclenché "lors de l'utilisation" du plaçable.

Il faut bien prendre en compte que chaque parenthèse, chaque accolade, chaque guillemet, doit être fermé(e). Un oubli provoquera irrémédiablement une erreur de compilation.


Profitons-en pour analyser la fonction suivante, qui m'a permis d'envoyer un message à un joueur donné.

void SendMessageToPC(object oPlayer, string sMessage)

- Etant une fonction de type "void", elle ne renverra aucune valeur
- oPlayer* devra être un objet à qui on enverra le message
- sMessage* est le message à envoyer à oPlayer


* object oPlayer et string sMessage représentent le type de paramètre à entrer. Peu importe le nom des variables que l'on mettra pendant l'utilisation de cette fonction, c'est leur type et l'ordre dans lequel elles sont placées qui importent. Veillez à ce que la séparation entre chaque paramètre soit bien réspecté, et représenté par une virgule.

Vous avez gagné un niveau !

A ce stade, et en travaillant uniquement sur ces points, il est possible de faire des scripts simples agissant lors d'un événement donné. Il s'agit surtout de s'entraîner à comprendre des fonctions basiques, de jouer avec les variables, et de repérer le moment où les événements sont déclenchés en y plaçant des scripts de test.



NWScript - Page générale

NWScript - pour niveau 1
- Bases et notions de programmation -

NWScript - pour niveau 2
- Conditions if/else et opérateurs ET / OU -

NWScript - pour niveau 3
- Boucles while/for et sélection switch/case -

NWScript - pour niveau 4
- Constantes, fonctions, et bibliothèques -

NWScript - pour niveau 5
- Variables persistantes et exécution de scripts -

Réactions


Personne n'a encore réagi. Soyez le premier.

Que pensez-vous de Neverwinter Nights 2 ?

127 aiment, 20 pas.
Note moyenne : (155 évaluations | 5 critiques)
8,4 / 10 - Très bien

315 joliens y jouent, 840 y ont joué.