Page 1 sur 1

[TUTORIEL] LE KIT DE SURVIE - CHAPITRE 4 : Savoir écrire et jongler dans un fichier d

Posté : lun. 01 oct. 2012, 14:41
par Armand
LE KIT DE SURVIE DU MODDER DEBUTANT
Ou comment survivre dans la jungle quand on est un puceau du tp2



Chapitre 4 : Savoir écrire et jongler dans un fichier d



Avant propos


Lors du tutorial précédent nous avons pu découvrir le fonctionnement d'un fichier .d avec tous ses mécanismes de bases. Beaucoup de théorie, trop peut être et en guise d'excuse voici la deuxième partie de ce tutoriel avec une manière optimale de coder vos fichiers sans vous prendre la tête !


Préparation


Comme à chaque fois que vous manipulez du code vous devez avoir un éditeur de texte avec éventuellement les higlighters dédiés. Dans mon précédent tuto je parle de pspad et d'autres, je vous invite à y jeter un œil si vous voulez plus d'info.
De même et en particulier pour ce tuto je vous recommande d'ouvrir également IESDP (trouvable dans la boite à outils ça change pas), l'onglet actions et conditions qu'on a vu vaguement la dernière fois va être beaucoup plus utilisé surtout parce que juste après ce tuto on attaque les scripts et que quelques notions ne vous feront pas de mal. J'ai également construit un autre mini mod qui pourra vous guider dans votre progression, je vous invite à le consulter en même temps que vous faites vos manipulations.


Étape 1 : Répliques à plusieurs

En termes d’écriture de dialogue, on connaît un format principal qui est d'ailleurs le plus courant :


  • On génère un fichier dlg pour faire parler un perso.
  • On fait parler ce perso.
  • Charname répond.
  • Éventuellement on rajoute des actions.
Le schéma classique mais qu'en est-il si je veux faire intervenir d'autres personnages dans l'intervalle ? Comme toujours prenons un exemple pour illustrer notre cas. A l'intérieur du mini mod que vous avez pu télécharger vous trouverez le fichier monks.d comme d'habitude je vous invite à suivre en direct dans le fichier en même temps vous suivez le tuto :


Génération des dlg nécessaires au dialogue


Image
Image
Begin ~nomdudlg~
Je le rappelle, la commande BEGIN permet de générer un dlg (c'est la référence que vous avez pu mettre dans le fichier cre). Mais là problème : on a plusieurs BEGIN en début de fichier. Du coup dans quel dlg écrit-on ? Et bien dans tous en même temps en fait. C'est la magie du CHAIN on a aucune restriction si ce n'est que les fichiers qui font parler les personnages existent bel et bien au moment ou le programme lit les instructions.


BEGIN ~nomdudlg~
BEGIN ~nomdudlg~
BEGIN ~nomdudlg~
BEGIN ~nomdudlg~
Voilà donc l'idée. Je travaille sur une scène avec quatre personnages (4 monk...) par conséquent avant d’écrire tout dialogue les impliquant, il va falloir générer chaque dlg de ces personnages. C'est un peu comme si je munissait chaque personnage de cordes vocales pour leur permettre de s'exprimer.


Phase d'écriture


Image
Image

Encore le format CHAIN car si on a pu voir d'autres méthodes pour vous aider à lire les fichier du jeu, c'est vraiment le format universel qui va vous simplifier la vie. On a déjà plus ou moins vu ce format donc on va revenir rapidement sur les différents éléments et voir un peu plus en détail les spécificités du dialogue à plusieurs.


CHAIN IF ~Global("#VDebatEnrichissant","GLOBAL",1)~ THEN

On annonce qu'on utilise un bloc de format CHAIN. J'en profite pour reparler de cette histoire de variable ; pour chaque dialogue étant initié soit automatiquement soit par le joueur, il faudra une variable dédiée. Par exemple ma variable #Vdebatenrichissant sera à 1 quand je parle d'un débat sur le modding, à 2 quand je parlerai bière irlandaise et à 3 quand il n'aura rien à me dire. C'est vraiment une chose à retenir pour la suite : pour chaque évènement situation il faudra une variable associée. On raccorde toujours un élément scénaristique quel qu'il soit à des valeurs chiffrées, c'est une règle simple qui évite bien des problèmes croyez moi

« #VMonk83 »
Le personnage (dlg) qui initie le dialogue, ça détermine à qui « appartient » le bloc.

@1
Le personnage parle en utilisant le texte contenu dans le @1 du tra dédié.

==
Ce double égal signifie qu'un autre personnage va intervenir

"#VMonk84"
La technique habituelle : on indique la référence du dlg pour savoir qui parle.

@2
La réplique de #Vmonk84

END
La série de réplique suivant la réplique de #Vmonk83 a pris fin, on place le END.

IF ~~ THEN REPLY @9
C'est au tour de Charname de parler avant de conclure.

IF ~~ THEN REPLY @9 EXTERN ~nomdudlg~ nomdubloc (on pourrait aussi envisager IF ~~ THEN EXTERN... Charname n'est pas obligé de répondre)
Charname parle, c'est une chose mais il faut également renvoyer vers le prochain bloc. Ici je vous fais utiliser un EXTERN. C'est le plus simple et qui plus est ça fonctionnera à chaque fois. Avec cet EXTERN je vais renvoyer vers le fichier dlg qui va démarrer le bloc dont j'indique le nom.


Image
Image

On retrouve les blocs indiqués en référence à la fin du dernier screen? Notez bien la différence :


"#VMonk85" MESSIEURS
C'est mon dlg #Vmonk85 qui démarre donc dans mon EXTERN. Je me dois de bien préciser ce dlg là ainsi que le nom de bloc MESSIEURS

"#VMonk84" PROBLEME
C'est mon dlg #Vmonk84 qui démarre donc dans mon EXTERN, je me dois de bien préciser ce dlg là ainsi que le nom de bloc PROBLEM

DO ~SetGlobal("#VDebatEnrichissant","GLOBAL",2)~
Avec le mot clef DO, j'initialise la variable à 2, ça évite que le dialogue ne tourne en boucle : la valeur de la variable a changé le IF du premier CHAIN IF ~variable~ n'est plus vérifié.


L'avis de Brigitte : Je l'ai déjà dit pour les noms de blocs de dialogue rien ne vaut des noms explicites, il faut que les noms de variables vous parlent à vous et même éventuellement aux autres qui pourraient passer derrière vous en cas de test debug. Alors n'oubliez pas mon vieux credo : RANGEMENT ! RANGEMENT ! RANG...


Je crois qu'ils ont compris, Brigitte ça va allez. Au passage vous avez sous la main deux mini mods opérationnels n’hésitez pas à tester/retester, bidouillez/farfouillez. C'est fait pour !



Étape 2 : Le PNJ


La plupart d'entre vous seront amenés à travailler sur un mod PNJ d'une manière ou d'une autre. J'ai donc jugé utile de vous montrer deux concepts rapides d'un dlg dédié au PNJ.


Les différents fichiers d'ordre particulier


Jusqu'à présent nous avons vu le cas universel par excellence : un cre possède un dlg qui lui permet de parler. Dans le cas du PNJ c'est différent : le cre va avoir plusieurs dlg, prenons un exemple avec un cre nommé #VAto par exemple :


#VAto (« nomducre ») : Le dialogue de base du personnage.
#VBAto (« Bnomducre ») : Le dialogue pour les banters.
#VAtoP (« nomducreP ») : Le dialogue de kick out (lorsque le PNJ est éjecté du groupe).
#VAtoJ (« nomducreJ ») : Le dialogue pour quand le personnage se trouve dans le groupe.


Après techniquement parlant on peut faire autant de fichiers qu'on veut (pour la romance, la quête, que sais-je encore...). Mais là, vous avez les basiques, le minimum nécessaire si on peut dire.



Phase d'écriture


Image
Image

Begin ~#VAto~
Génération du dlg de base de la créature comme on l'a déjà vu plein de fois.

Global("#VAtoDia","GLOBAL",1)
Une variable pour vérifier que le dialogue se déclenchera bien et celui là en particulier et pas un autre. Du déjà vu également.

THEN REPLY @10 DO ~
Si Charname (le joueur en fait) opte pour la réplique @10 alors cette suite d'action se déclenche :

JoinParty()
Le dernier perso (autre que Charname bien sur) qui a parlé va se joindre au groupe. Ici c'est celui à qui appartient le dlg « #VAto ».

AddJournalEntry(@71010,QUEST)
Crée un entrée journal de type « QUÊTE » dans le journal du joueur.

SetGlobal("#VAtoJoin","GLOBAL",1)~ EXIT
On implante une variable pour pouvoir vérifier que le perso s'est bien joint au groupe. Comme j'ai déjà pu le dire à chaque événement on y relie une variable, cela permet de vérifier ou vous en êtes dans la trame de votre mod. Puis on sort de la boite de dialogue avec la commande EXIT. Du déjà vu également.

THEN REPLY @11 DO ~
Si Charname (le joueur en fait) opte pour la réplique @11 alors cette suite d'action se déclenche :

SetGlobal("#VAtoLeave","GLOBAL",1)
Encore une variable pour vérifier cette fois un autre événement, une sortie de zone en l’occurrence.

EscapeArea()~ EXIT
La commande qui génère une sortie de zone (s'applique comme toujours au dernier perso qui a parlé autre que Charname) suivi du mot clef

EXIT pour sortir à la boite de dialogue.

SetGlobal("#VAtoJoin","GLOBAL",1)~ EXIT


Image
Image

Begin ~#VAto~
Génération du dlg lorsque le perso est dans le groupe.

Global("#VAtoDia","GLOBAL",2)
Il s'agit d'un autre dialogue pour qu'on puisse le déclencher on a changé la valeur de la variable « dialogue ».

THEN REPLY @11 DO ~
Si Charname (le joueur en fait) opte pour la réplique @11 alors cette suite d'action se déclenche :

EraseJournalEntry(@71010,QUEST)
On a vu l'action pour créer une entrée journal voilà le truc pour l'effacer.

AddJournalEntry(@71011,QUEST_DONE)
Cette deuxième action qui va nous permettre de reproduire le mécanisme du jeu (l’entrée journal apparaît et une autre apparaît). Ici l'action génère une entrée journal dans la partie « QUÊTE ACCOMPLIE».
SetGlobal("#VAtoparledenous","GLOBAL",1)~ EXIT
Idem on implante une variable pour chaque événement, suite aux entrées journal implantées. Notre quête est terminé on le fait savoir par cette variable.




Question du noob : mais comment je fais pour savoir quelles actions/conditions utiliser ?


Vous trouverez tout dans IESDP, ce n'est vraiment pas une façon de parler quand je dis que IESDP est la bible du modder. C'est vraiment la référence et chaque fois que vous coderez je vous conseil de l'avoir ouvert en permanence ça sert vraiment à tout. Pour rappel vous avez la liste des actions ici et la liste des conditions (triggers) ici.
Les descriptions ne sont pas forcement toujours claires mais je vous invite à utiliser la fonction « search » pour trouver des exemples ou bien encore à farfouiller dans les autres mods existants pour voir comment ça fonctionne. Ici je vous donne une base, un certain nombre de manipulations qui fonctionnent et on en verra d'autres par la suite. Mais l'idée c'est vraiment d'explorer par vous même car c'est à force de fouiller dans le fonctionnement du jeu et des mods que vous apprendrez des nouveaux trucs et que vous finirez par trouver extrêmement simple ce qui vous semblait compliqué autrefois.



Conclusion


J'ai essayé de pousser au maximum les infos sur les dialogues. On pourrait en parler encore longtemps mais je pense avoir fait le tour de ce dont vous aurez besoin. La suite logique de ce tutoriel sera le tuto sur les scripts.

Posté : sam. 10 nov. 2012, 13:55
par Armand
Comme sur le précédent tutorial, le mini mod a été mis à jour.

Suppression de reférences de journal inexistantes

Posté : jeu. 25 avr. 2013, 12:11
par Freddy_Gwendo
Je profite de ce tuto pour poser une question en rapport avec une action que l'on peut retrouver dans les dialogues.
Sa place me semble plus appropriée ici que dans un nouveau topic.
Si ce n'est pas le cas, qu'un modo la transfère.


Donc, je me demandais si l'inexistence d'une valeur dans la commande EraseJournalEntry() plantait la compilation, puis l'exécution d'un dialogue ou pas.


Je m'explique.

Lors d'une première rencontre, selon les options choisies, le dialogue inscrit une valeur dans le journal :

- Choix 1 : AddJournalEntry(@3500900,INFO)
- Choix 2 : AddJournalEntry(@3500901,INFO)
- Choix 3 : AddJournalEntry(@3500902,INFO)


Lors d'une seconde rencontre, soit le journal n'est pas modifié, soit on opère un choix modifiant le journal.

- Choix 4 : AddJournalEntry(@3500903,INFO)
- Choix 5 : AddJournalEntry(@3500904,INFO)


Dans ces deux derniers cas de figure, je me demandais si je pouvais utiliser sans risque les commandes suivantes :

Code : Tout sélectionner

DO ~SetGlobal("GWGwendoNO","GLOBAL",0) SetGlobal("GWGwendoOK","GLOBAL",1)   SetGlobal("GWGwendoCurse","GLOBAL",1)
EraseJournalEntry(@3500900) EraseJournalEntry(@3500901) EraseJournalEntry(@3500902) AddJournalEntry(@3500903,INFO)~ 

DO ~SetGlobal("GWGwendoNO","GLOBAL",1) SetGlobal("GWGwendoOK","GLOBAL",0)   SetGlobal("GWGwendoCurse","GLOBAL",0)
EraseJournalEntry(@3500900) EraseJournalEntry(@3500901) EraseJournalEntry(@3500902) AddJournalEntry(@3500904,INFO)~ 
plutôt que de rédiger trois lignes de commande pour effacer uniquement les entrées du journal définies lors de la première rencontre.

Le tout me faisant gagner pas mal de lignes de code, d'autant plus que je ne n'ai cité que 3 valeurs possibles, et qu'il y en a bien plus... ;)

Posté : jeu. 25 avr. 2013, 21:16
par Isaya
BGT utilise du EraseJournalEntry en masse dans son script de passage aux geôles d'Irenicus, avec a priori toutes les entrées possibles de journal de BG. Je ne vois pas pourquoi cela poserait de problème dans le cadre d'un dialogue.

Posté : ven. 26 avr. 2013, 08:23
par Armand
Oui de ce que je sais le mod severian utilise ce type de commande en masse et vu que les 3/4 des trucs sont codé dans les d...

Posté : dim. 18 août 2013, 22:15
par Cocrane
La structure du CHAIN me pose problème au niveau de sa logique

En classique on a:

IF ~condition~Then BEGIN // début de bloc
Code du bloc
END // fin de bloc

=> On peut identifier le début et la fin du bloc


Avec un CHAIN on a:
CHAIN IF ~condition~ THEN "fichier cible" nom du bloc // Début du bloc
Code du bloc
END // fin de bloc
IF ~condition~ THEN instruction1
IF ~condition~ THEN instruction2
etc...

On a des lignes en dehors du bloc. Visiblement c'est à relier au CHAIN du dessus mais ca plus l'effet de lignes en dehors d'un bloc comme si elles étaient orphelines.

Si elles font parties du CHAIN pourquoi ne pas avoir le code suivant:
CHAIN IF ~condition~ THEN "fichier cible" nom du bloc // Début du bloc
Code du bloc
IF ~condition~ THEN instruction1
IF ~condition~ THEN instruction2
END // fin de bloc


Cocrane

Posté : sam. 14 sept. 2013, 10:44
par Cocrane
Qui peut répondre à la question du message précédent?

Posté : mar. 29 mars 2016, 07:29
par Freddy_Gwendo
Pour les ceusses qui se désolaient, j'ai actualisé les liens des images. ^^

Bonne lecture. ;)

@coco = la réponse se trouve dans le tuto précédent. En gros, parce que WeiDU est codé comme ça ! ;)

Posté : sam. 14 nov. 2020, 20:55
par Hayabusa
Bonjour les deux liens suivant sont morts
Vous trouverez tout dans IESDP, ce n'est vraiment pas une façon de parler quand je dis que IESDP est la bible du modder. C'est vraiment la référence et chaque fois que vous coderez je vous conseil de l'avoir ouvert en permanence ça sert vraiment à tout. Pour rappel vous avez la liste des actions ici et la liste des conditions (triggers) ici.

Posté : sam. 14 nov. 2020, 21:13
par Hayabusa
Petite question sur la partie du PNJ je ne comprend pas trop quelle partie de code correspond à quel fichier ?

ça serait dans le fichier ryu.d

Code : Tout sélectionner

BEGIN ~ryu~

CHAIN IF ~Global("ryuDia","GLOBAL",1)~ THEN "" RencontreRyu
	@1
END
	IF ~~ THEN REPLY @10 DO ~JoinParty()AddJournalEntry(@71010, QUEST)SetGlobal("ryuJoin","GLOBAL",1)~ EXIT
	IF ~~ THEN REPLY @11 DO ~SetGlobal("ryuLeave","GLOBAL",1)EscapeArea()~ EXIT
Et ça dans le fichier ryuJ.d

Code : Tout sélectionner

BEGIN ~ryuJ~

CHAIN IF ~Global("ryuDia","GLOBAL",2)~ THEN "ryu" ryuParleDeNous
	@4
END
	IF ~~ THEN REPLY @11 DO ~EraseJournalEntry(@71011,QUEST)AddJournalEntry(@71010,QUEST_DONE)SetGlobal("ryuParleDeNous","GLOBAL",1)~ EXIT
Si j'ai bien tout suivi ^^

Posté : dim. 15 nov. 2020, 16:03
par Isaya
Bonjour,

Le nom du fichier d n'est pas significatif. Le nom qui compte est celui indiqué dans l'instruction BEGIN à l'intérieur du fichier. A moins que tu n'aimes la difficulté, donner au fichier d un nom identique au contenu du BEGIN est sans doute aussi bien. ;)

Pour trouver des liens à jour pour les outils mentionnés dans les différents tutoriels, le plus simple est de consulter les sujets épinglés de la section Modding et Outils de développement.