[Scripts] Explications pour débutants

Vous trouverez ici les conseils indispensables pour bien modder et maîtriser les outils de modding des jeux.
Répondre
Avatar du membre
Gerauld
Confrère
Messages : 2439

Explications pour débutants

Message par Gerauld »

Vous voulez vous lancer dans les scripts, ce topic est fait pour vous.
Il n'abordera pas les différents éditeurs existants pour les scripts ainsi que leurs spécificités ainsi que les fragments de scripts, spécifiques aux dialogues, packages, perks, et STAGES de quêtes.

0. Au préalable
Avant toute chose, depuis une certaine MAJ, on trouve dans le dossier Data du jeu un fichier scripts.rar. Si on veut pouvoir compiler des scripts il faut d'abord décompresser ce qu'il y a dedans. Il suffit avec Winrar/winzip/7Zip de faire "Extraire ici".


1. Un script, c'est quoi ?
Un script est un ensemble d'instructions, de fonctions, de propriétés et de variables destiné à ajouter, modifier certaines fonctionnalités du jeu.
Ils sont attachés à un "objet" au sens large, ce peut être un ReferenceAlias, un Actor, ou tout autre élément les acceptant.

Pour attacher un script à un objet, dans le Creation Kit, localisez la section "Scripts" de l'objet en question, et cliquez sur Add.
Image
Une fenêtre s'ouvre, vous permettant d'associer un script déjà existant en le sélectionnant dans la liste, ou d'en créer un nouveau pour l'occasion en sélectionnant [New Script]

Pour réaliser un script, nous éditons un fichier appelé source. Ce fichier source est celui que nous modifions à l'aide de nos petites mains à l'aide de l'éditeur de notre choix.
Il est par défaut stocké dans Data\Scripts\Source et possède l'extension *.psc.

Ce fichier source n'est pas utilisé tel quel par le jeu. Il a besoin d'un script compilé.
Quand nous sauvegardons un script, l'éditeur le compile et génère un fichier compilé. C'est ce fichier qui sera chargé par le jeu.
Il a une extension en *.pex et sera stocké dans Data\Scripts.
C'est le seul fichier nécessaire pour faire fonctionner un mod.
Par contre le fichier source est nécessaire pour l'éditer.


2. Créer un nouveau script

Si vous décidez de créer un nouveau script pour l'occasion en sélectionnant [New Script] au moment de l'assignation d'un script à un objet,
vous serez présenté à ce cadre :
Image
Name est le nom de votre script. Il est conseillé de lui donner un préfixe spécifique à votre mod, à la fois pour vous y retrouver plus facilement, et pour éviter les conflits avec d'autres mods où le moddeur aurait eu la même idée de nom pour son script.

Extends est la "base" de votre script. Il doit généralement correspondre à l'objet auquel vous assignez un script (exemple : Quest pour une quête).

Les cases Hidden et Conditional sont des fonctionnalités plus avancées qui ne seront pas abordées ici.

Le champ Documentation String est utile comme son nom l'indique pour documenter votre script, très utile si vous voulez créez des ressources ré-utilisables par d'autres moddeurs.

Pour ensuite pouvoir écrire le script, clique-droit -> Edit Source


3. Déclarer et assigner des properties

Par défaut, votre script ne peut interagir qu'avec l'objet auquel il est associé. Pour qu'il puisse accéder aux autres éléments du jeu, la méthode conventionnelle est d'utiliser des "properties". :

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty1 auto
Ici, notre script pourra donc travailler avec deux properties nommée alphaproperty et alphaproperty1, de type MiscObject. Il faut cependant faire le lien entre ces properties et de véritables objets. Pour ça : sélectionnez votre script dans la zone Papyrus de l'objet auquel il est assigné dans le CK, et cliquez sur Properties.
Image
Dans cette fenêtre, vous pouvez assigner chacune des properties à un objet en cliquant dessus puis en cliquant sur "Edit Value". Le petit menu disponible dépend du type de property en question. Dans le cas de nos "MiscObject", il s'agit d'un menu déroulant vous permettant de sélectionner n'importe quel MiscObject disponible dans les plugins chargés dans le CK.

Cette fenêtre vous permet également de rajouter de nouvelles properties à votre script avec le bouton Add Property.


4. Les instructions IMPORT
Celles-ci permettent d'aérer un peu le code source de votre script en vous évitant des saisies supplémentaires.
Par exemple :

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty1 auto

event oninit()
        int toto = game.getplayer().getitemcount(alphaproperty)
        int toto1 = game.getplayer().getitemcount(alphaproperty1)
endevent
deviendra :

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty1 auto

Import game

event oninit()
        int toto = getplayer().getitemcount(alphaproperty)
        int toto1 = getplayer().getitemcount(alphaproperty1)
 endevent
Le fait d'utiliser la fonction import dans la source n'agit en rien sur le fichier compilé.
En effet, le compilateur sera celui qui importera l'ensemble de fonction game pour réalisé le fichier compilé.
En clair, la fonction import n'a aucune influence sur le fichier compilé. Elle sert juste à améliorer la lisibilité du script et diminuer la saisie.

5. Optimisation - remplacement des getplayer()
Les fonctions getplayer() sont des fonctions assez lentes si on les compare à l'utilisation de propriétés ou de variables.
Nous allons optimiser un peu notre exemple précédent, nous obtenons :

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty1 auto

actor property playerref auto

Import game

event oninit()
        int toto = playerref.getitemcount(alphaproperty)
        int toto1 = playerref.getitemcount(alphaproperty1)
endevent
Le script réalise exactement la même fonction mais de manière plus rapide.
Il ne faut cependant pas oublier de "remplir" la propriété.

A savoir que le fait d'utiliser une propriété au lieu de directement passer par Game.GetPlayer() "alourdi" légèrement le script, en particulier son poids dans la sauvegarde. Si la portion de script faisant appel à au joueur ne tourne que très occasionnellement, Game.GetPlayer() reste préférable.

6. Nommage des propriétés
Dans l'exemple précédent, nous avons nommé notre propriété de type actor playerref.
Le choix n'a pas été anodin car il permet de remplir de manière automatique la propriété du script.
Il suffit d'ouvrir la fenêtre des propriétés et de cliquer sur "auto-fill all". Une fenêtre apparaîtra précisant le nombre de propriétés remplies.
Il suffit donc de nommer la propriété de la même manière que l'objet du même type que l'on veut y mettre dedans pour qu le CK remplisse les champs tout seul après.
Pratique quand on travaille avec beaucoup de propriétés.

Si le nom de la propriété de correspond pas exactement à l'EditorID d'un objet déjà présent dans le plugin, il faudra l'assigner manuellement. (voir partie précédente)

7. Les définitions de variables

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty1 auto

actor property playerref auto

Import game

event oninit()
        int toto = playerref.getitemcount(alphaproperty)
        int toto1 = playerref.getitemcount(alphaproperty1)
endevent
Le code précédant définit deux variables de type int appelées toto et toto1.
Cependant, on remarquera avec ce type de déclaration que la variable n'est pas partagée par toutes les instances du même script. Pour pouvoir utiliser ces variables en dehors de l'event oninit(), il faut les déclarer avant.

Le code devient donc :

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty1 auto

actor property playerref auto

int toto
int toto1

Import game

event oninit()
        toto = playerref.getitemcount(alphaproperty)
        toto1 = playerref.getitemcount(alphaproperty1)
endevent
Les variables toto et toto1 peuvent donc être utilisées par tous les event de ce script mais toujours pas pas les autres.

8. Variables globales
Pour le besoin de l'exemple, nous avons besoin de partager une variable avec plusieurs scripts, toto2.
Il faut d'abord créer la variable globale dans le CK (dans la catégorie miscellaneous).
Ensuite il faudra la déclarer en tant que propriété.

Code : Tout sélectionner

miscobject property alphaproperty auto
miscobject property alphaproperty auto

actor property playerref auto

globalvariable property toto2 auto

int toto
int toto1

Import game

event oninit()
    if toto2 == 1
        toto = playerref.getitemcount(alphaproperty)
        toto1 = playerref.getitemcount(alphaproperty1)
    endif
endevent
Ce script refusera de compiler car toto2 n'est pas une variable à proprement parler mais un objet nommé contenant une valeur avec une ID.
Il existe des fonctions pour lire ou écrire des valeurs dans ces variables globales.
Le script devient :

Code : Tout sélectionner

actor property playerref auto

miscobject property alphaproperty auto
miscobject property alphaproperty auto

globalvariable property toto2 auto

int toto
int toto1

Import game

event oninit()
    if toto2.getvalueint() == 1
        toto = playerref.getitemcount(alphaproperty)
        toto1 = playerref.getitemcount(alphaproperty1)
    endif
endevent
En clair, si la valeur de la variable toto2 est égale à 1 au moment de l'initialisation du script, les variables de ce script toto et toto1 seront remplies avec le nombre d'objets alphaproperty et alphaproperty1 détenus par le joueur.


Si vous avez des trucs, astuces et explications simples, postez les dans ce topic...
Modifié en dernier par Kesta le 19 déc. 2015, 05:49, modifié 3 fois.
Avatar du membre
Gerauld
Confrère
Messages : 2439

Re: LES SCRIPTS : TRUCS ET ASTUCES

Message par Gerauld »

6. Les events

Les events sont des évènement qui déclencheront la partie de script comprise entre le mot "event" et le "endevent".
Par exemple, un event onitemadded() se déclenchera dès que l'objet sur lequel est attaché le script reçoit un objet.
Cependant, si on tape ceci dans un script ça ne marchera pas :

Code : Tout sélectionner

Event onitemadded(gold001)
        debug.notification("Chouette de l'or!!!")
endevent
Il faut mettre :

Code : Tout sélectionner

miscobject property gold001 auto ;propriété pour faire comprendre au script ce qu'est gold001

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
          if akbaseitem == gold001
                  debug.notification("Chouette " + aiitemcount + " pièces d'or!!!")
           endif
endevent
akbaseitem est le form de l'objet ajouté,
aiitemcount est le nombre d'objets ajouté
akitemreference est la référence de l'objet s'il en possède une
akSourcecontainer est la provenance de l'objet. None si ramassé par terre.

Donc ce bout de script se déclenche à l'ajout d'un objet et se termine à endevent.
On peut placer plusieurs events dans un même script.

La liste des events et leur syntaxe est donnée ICI

Une variable définie dans un event ne sera valable que pour cet event.

Il faut veiller à la compatibilité entre l'event utilisé et ce qui suit le extends de la première ligne du script. En cas d'incompatibilité, l'event sera ignoré et le script ne fonctionnera pas.

Un même event peut être lancé plusieurs fois en même temps si l'évènement se reproduit alors que le script n'est pas terminé. Ce sont les joies du multithreading. Il faut donc prévoir cette éventualité pour certains scripts (comme ceux qui lancent des animations par exemple).

Il est aussi possible d'utiliser les STATES pour palier ce problème et permettre plusieurs modes de fonctionnement d'un même script. Nous verrons cela lors d'un prochain post.
Avatar du membre
Gerauld
Confrère
Messages : 2439

Re: LES SCRIPTS : TRUCS ET ASTUCES

Message par Gerauld »

7. Les states ou l'art de proposer plusieurs modes de fonctionnement pour un script.

Qu'est ce qu'un state? C'est tout simplement un état.

Une explication :
Prenons l'exemple d'un script ayant un état "attente" et un état "occupé". Il y aura dans l'état attente un event correspondant au fait que l'on active l'objet. Cet event déclenchera une série d'instructions.
Si on active une deuxième fois l'objet, la série d'instruction sera lancée une nouvelle fois même si la première n'est pas finie. Pour éviter cela, on va basculer vers l'état "occupé" qui ne contiendra pas l'event d'activation donc ne lancera pas d'instructions.
A la fin de la série d'instruction, il est nécessaire de revenir à l'état "attente" pour permettre une nouvelle activation.

En gros, l'architecture de ce script d'activateur ressemblerait à ça :
► Afficher le texte
On peut aussi utiliser les états pour compter un nombre d'activations dans un temps donné et ainsi permettre plusieurs fonctions différentes à l'activation d'un même objet.

Exemple :
► Afficher le texte

Attention, ne pas confondre un gotostate() (changement d'état) avec un goto style language basic.
Dans le cas d'un gotostate(), les instructions qui sont présentes dans l'event après cette instruction sont exécutées jusqu'à la fin de l'event.
Dans l'exemple ci-dessus, on change d'état mais on continue de dérouler le bout de script de l'event onactivate de l'état "dep".


EDIT : donc pour résumer, jusqu'à présent, nous avons vu :
-ce qu'est un script physiquement sur un disque dur
- le nommage des propriétés (et l'utilité d'utiliser une propriété playerref plutôt que game.getplayer())
- la fonction import et le fait qu'elle n'a aucune incidence sur la compilation
- les déclarations de variables et leur champ d'existence.
- les events (des déclencheurs de bouts de scripts)
- les states (des ensemble d'events)
Tout ceci combiné avec la page scripting reference du site web du CK devrait vous permettre de comprendre les scripts déjà présents et vous aider à créer les votres en évitant certaines petites erreurs.

Si vous avez des questions, suggestions ou des demandes pour la suite de ce topic, il suffit de poster.
Le prochain post concernera les propriétés, les sauvegardes et les difficultés liées aux scripts lors des tests ou lors de mises à jour de certains mods.
Avatar du membre
Tezkal
Moddeur aspirant
Moddeur aspirant
Messages : 137

Re: [TUTO] LES SCRIPTS : EXPLICATIONS POUR DEBUTANTS

Message par Tezkal »

Tuto très instructif, bravo. Je me demandais pourquoi certains de mes scripts sont lents et je vais donc arrêter d'utiliser la fonction getplayer(). Merci beaucoup pour l'info ! :)
Frôler la perfection n'est pas bien compliqué. Il suffit simplement de passer à côté de moi.
Wolfsilver
Traducteur en herbe
Traducteur en herbe
Messages : 508

Re: [TUTO] LES SCRIPTS : EXPLICATIONS POUR DEBUTANTS

Message par Wolfsilver »

Si on a jamais fait de script et ni de langage informatique, y a des tuto pour réussir à en faire dans Skyrim?^^'
Traduction

Fini
► Afficher le texte
En cours

Sur la Confrérie :
► Afficher le texte
Personnel :
► Afficher le texte
Avatar du membre
Kesta
Maître de Forge
Maître de Forge
Messages : 1077

Re: [Scripts] EXPLICATIONS POUR DEBUTANTS

Message par Kesta »

Mise à jour du premier post, rajout de quelques éléments plus "basiques", correction de quelques erreurs & oublis dus à l'âge du tuto original, et ajout de quelques images sexy et aération des exemples de code.
Faites un feu à un homme, il aura chaud un jour.
Mettez le feu à un homme, il aura chaud jusqu'à la fin de sa vie.

Terry Pratchett
Répondre

Retourner vers « Tutoriels et conseils de réalisation »