[info] Les dialogues dynamiques

Répondre
Partager Rechercher
Bon, ba puisque g trimé dessus pdt qq temps, autant éviter à d'autres d'avoir à trop défricher
Je ne prétend pas être une référence en la matière, et je me trompe surement à certains endroits, y a probablement mieux, c'est juste que ce système est tellement genial que je trouve dommage de pas en parler au moins une bonne fois
C'est toute fois un système assez complexe, qui demande qq base en script, pas la mort, mais bon, faut qd même avoir fais quelques scripts en plus des tutoriaux je pense ^_^

Alors :

Qu'est ce que c'est ?

En gros, un fialogue qui se construit au fur et à mesure qu'il est euh, dialogué ( ).
En moins gros, il s'agit de créer un dialogue à l'aide de scripts, et d'un "dialogue", créé avec le toolset normal, plus que minimaliste.

Pourquoi faire ?

C'est géré par script, à l'aide de string, donc, on peut tout faire ^_^
Faire un perso à la Norbert de BG1 (le taré à Nashkel) dévient un jeu d'enfant, pire, simuler la folie chez un personnage et changeant à chaque fois certain mots et certaine formule devient vraiment possible, c'est à dire que ses délires peuvent êtres complètement aléatoires (je pense éssayer de faire un truc du style )
Sympa aussi, ca permet d'alleger le nombre de script. Et ben oui, pour faire un dialogue tentaculaire avec moult test différent et moult "récompenses" différentes ne demande plus 15 milliards de scripts, en fait, une dizaine permet de faire absolument tout avec le dialogue (met du genre TOUT )
En fait, il n'y a pas vraiment de limite, statistiques pour les DM, Dialogue modifiable in game, éphémérides, personnalisation en tout genre (vous trouviez que les tokens n'était pas assez nombreux ? réjouissez vous )
moi personnleemnt j'ai fais avec ca un truc qui aurait demandé au mnimum un bon millier de scripts d'actions comséquente, et là j'en suis à grosso modo 20

Mais coment ca marche ?

Ca utilise les CUSTOM token
Il s'agit, au moment ou l'on donne la réponse, d'assigner à différents token la valeur que l'onveut, token qui sont utilisé dans les dialogues.
C'est pas clair ? C'est normal.
Bon, alors :

dialogue basique :
[PNJ] Boujour ! Je m'apelle Pé n'Ji !
---[PJ1]salut !
------[PNJ] Comment va ?
---------[PJ][fin du dialogue]
---[PJ2]Va voir ailleurs si j'y suis ![fin du dialogue]
---[PJ3]oyo ?
------[PNJ]Quelle langue parle tu ?
---------[PJ1]Go Men à Saï !
------------[PNJ]Dsl je ne comprend pas.[fin du dialogue]
---------[PJ2]C'est pas tes ognions ![fin du dialogue]
---------[PJ3]Ki té ?[retour début]

basique non ?
Alors un dialogue dynamique ca serait plutot :

[PNJ] <CUSTOM8000>
---[PJ1] <CUSTOM8001>[retour début]
---[PJ2] <CUSTOM8002>[retour début]
---[PJ3] <CUSTOM8003>[retour début]

Alors, maintenant ca va p-e s'éclairer :
Il y a un script que s'éffectue avant le dialogue, c'est le test, la "condition d'éxécution"

si vous mettez un truc du style :
Code PHP:

int StartingConditional()
{
  
int nStarted GetLocalInt(GetLastSpeaker(), "STARTED");
 
string sDia;
   switch(
nStarted)
     {
      case 
0SetLocalInt(GetLastSpeaker(), "STARTED"1);
     
sDia "Boujour ! Je m'apelle Pé n'Ji !"; break;
      case 
1SetLocalInt(GetLastSpeaker(), "STARTED"0);
     
sDia "Comment va ?"; break;
      }

    
SetCustomToken(8000sDia);
    return 
TRUE;

alors, la, si la variable STARTED n'a pas été fixé à TRUE, elle y est mise (le dia commence) et on assigne au CUSTOM8000 la phrase de début, si ca a commencé, sDia prend la valeur de la deuxieme phrase, et on la remet à zéro.
(pas la peine d'essayer, c'est juste pour comprendre hein )
La, ca va afficher un truc du genre :
1 - Bonjour ....
(réponse)
2 - Comment va ?
(réponse)
3 - Bonjour ....
etc.
sans fin.
pas top.
On fait le même genre de chose sur les réponse possibles et disparu les CUSTOMXXXX !
Bon, maintenant, comment obtenir ce qu'on veut ? comment controler ce qui est dit/proposé ?

Pour cela, il faut approfondir un peu plus la "théorie", si vous avez compris jusque là (si je vous ai pas égaré en chein, avec mon légendaire sens de l'orientation).
Le seul moyen pour savoir sur quel phrase le PJ clique, ce sont les "actions conséquente". c'est a ce moment là, quand on choisit sa réponse, qu'il faut "créer la futur dialogue", un ensemble
PNJ
PJ
PJ
PJ

Lors du test qui suit (immédiatment, mais chronologiquement c'est ca) les différents CUSTOM tokens prennent leurs valeurs.
ca va ?
On récapitule :
1:test => assigne les différente répliques aux tokens
2:action conséquente => suivant le choix du PJ, on construit un nouveau dialogue
3:test => assign les nouvelles valeurs aux custom

il faut comprendre que les CUSTOM token sont utilisé par tout le module. Donc il faut leur donner une valeur et l'afficher dans l'instant dans un dialogue, sinon ba ca va plus, après par contre si on change de valeur, tant que le dialogue n'est pas refait (choix d'une réplique qui arrête puis on reprend ou bien choix d'un réplique qui permet de continuer)

Alors, comment on fait ca ?
Avec des
SetLocalString
et des
GetLocalString

un Set dans les actions conséquentes, et un Get dans le test

Mais coment savoir quel valeur donner ? comment savoir où on en est ?

Et bien avec des
SetLocalInt
et des GetLocalInt

en fait, quand on créé un dialogue, en plus d'assigner à chaque "étage" une valeur pour le token (par étage, comprendre réplique, une pour le PNJ et plusieurs pour le PJ, un étage = une réplique), on assigne un entier, qu'on récupere avant de créer un nouveau dialogue, et qui indique lequel créer.

script de test pour une réplique de PJ :
Code PHP:

int StartingConditional()
{
  
string sDia GetLocalString(GetLastSpeaker(), "DIALOGUE_1");

    if(
sDia == "") return FALSE;

    
SetCustomToken(8001sDia);
    return 
TRUE;


script d'acrtion conséquente de cette même réplique :
Code PHP:

void main()
{
DeleteLocalString(oPJ"DIALOGUE_0");
DeleteLocalString(oPJ"DIALOGUE_1");
DeleteLocalString(oPJ"DIALOGUE_2");
DeleteLocalString(oPJ"DIALOGUE_3");
int nNum 1;
int nDia2Built GetLocalString(oPJ"ACTION_CONSEQUENTE_1");
DeleteLocalInt(oPJ"ACTION_CONSEQUENTE_1");
switch(
nDia2Built )
   {
   case 
0://premier fois qu'on a propos le choix, pas de variable assignee
   
SetLocalString(oPJ"DIALOGUE_0""Comment va ?");
   
SetLocalString(oPJ"DIALOGUE_1""*Fin Du Dialogue*");
   break;
   case 
1://mettons que cela corresponde au choix 3 du premier noeud
   
SetLocalString(oPJ"DIALOGUE_0""Quelle langue parle tu ?");
   
SetLocalString(oPJ"DIALOGUE_1""Go Men à Saï !");
   
SetLocalString(oPJ"DIALOGUE_2""C'est pas tes ognions !");
   
SetLocalString(oPJ"DIALOGUE_3""Ki té ?");
   
SetLocalInt(oPJ"ACTION_CONSEQUENTE_1"2);
   break;
   case 
2://on a cliq_ue sur Go Men . . .
   
SetLocalString(oPJ"DIALOGUE_0""Dsl je ne comprend pas.");
   
SetLocalString(oPJ"DIALOGUE_1""*Fin Du Dialogue*");
   break;
   }

Ce script ne marche pas, il permet, je pense, de comprendre u_n peu, c'est tout

alors, a chaque dialogue correspond en fait un nombre, quand le switch tombe sur ce nombre, il créé le dialogue.
Si vous avez suivi, normalement ici cliquer sur "fin de dialogue" arrêteras le dialogue.
En effet si aucune string n'est assigne à DIALOGUE_0, alors le test renvoi FALSE, et le dialogue s'arrête.
Il faut bien penser à tout "néttoyer" avant de sortir
dans les script d'arrêt du dialogue par exemple.

En fait, personnellement l'utilise des fonction pour gerer tout cela.
Une qui "créé" les dialogue, un switch en fait, une qui applique les effet (un autre switch) et une qui rassemble ces deux là.

en gros :
Code PHP:

void DoDia(int nChoice)
{
 
//en fonction do "choix" entre, on recupere les variable qui indique
 //ce qu'il faut construire comme dialogue et ce qu'il faut faire
 
int nConv GetLocalInt(oPJ,"2SAY_"+IntToString(nChoice));
 
int n2Do GetLocalInt(oPJ,"2DO_"+IntToString(nChoice));



 
int i 0;
 for(; 
i<=8i++)
 {
 
DeleteLocalInt(oPJ"2SAY_"+IntToString(i));
 
DeleteLocalInt(oPJ"2DO_"+IntToString(i));
 
DeleteLocalString(oPJ"DIALOGUE_"+IntToString(i));
 
//supression des variable de dialogues et de "fonction" quand elles sont utilisees, source de bug
 
}

 if(
nConv != 0)
 
BuildDia(nConvnChoice); //construction de la discut
 
if(n2Do != 0)
 
DoDiaRec(n2DonChoice);//execution de l'action consequente (sauf creation dialogue)

 
return;

le script d'action conséquente devient :
Code PHP:

void main()
{
int nNum 1;
DoDia(nNum);

et les autres sont construits pareils, en changeant juste la valeur de l'entier entrée
2 pour la deuxieme réplique, etc.
moi j'ai mis 8 réplique pour le PJ, c'est correct tout en restant lisible

Les deux fonctions utilisée :
Code PHP:

void BuildDia(int nConversationint nChoice)
{
  switch (
nConversation)
     {
     case 
DiaStart(); break;
     case 
Dia2(); break;
     case 
Dia3(); break;
     case 
Dia4(); break;
     case 
Dia5(); break;
     case 
Dia6(); break;
//etc.
     
}
return;

Code PHP:

void DoDiaRec(int nRecint nChoice)
{
   switch(
nRec)
      {
     case 
//faire un truc
     
break;
     case 
//faire un truc
     
break;
     case 
//faire un truc
     
break;
     case 
//faire un truc
     
break;
     case 
//faire un truc
     
break;
     case 
//faire un truc
     
break;
       }
return;

tt con quoi, en fait là les fonctions ne servent à rien, mais il est possible de rajouté moult truc, et c'est parfois pratique de séparer tout cela pour s'y retrouver (en fait g fais le BuiltDia();, puis j'ai eu besoin d'un DoDiaRec, alors j'ai fais une fonction qui mélange les deux )

Oui, il y a quelque chose qui cloche. Je sais Où sont les dialogue ? Et bien dans les fonctions
Dia();
dont la forme est :
Code PHP:

void Dia()
{
  
//w, x, y et z sont des entiers ^_^
    
SetLocalString(oPJ,"DIALOGUE_0""Bla bla bla ?");

    
SetLocalString(oPJ,"DIALOGUE_1""bla bla 1.");
    
SetLocalInt(oPJ,"2SAY_1"x);
    
SetLocalInt(oPJ,"2DO_1"y);

    
SetLocalString(oPJ,"DIALOGUE_2""bla bla 2.");
    
SetLocalInt(oPJ,"2SAY_2"w);

    
SetLocalString(oPJ,"DIALOGUE_3""bla bla 3.");

return;

ici
choisir 1 entrainera un nouveau dialogue et une action
choisir 2 entrainera un nouveau dialogue
choisir 3 arrêteras le dialogue


la structure du tout peut paraitre lourde et inutile, mais elle prend sont interêt quand on arive à un grand nombre de noeuds différents dans le dialogue

normalement, maintenant vous devriez pouvoir créer un dialogue dynamique, je pense . . . peut être . . . (c pas vous qui seriez bête hein, mais moi )

Bon, un truc sympa avec ce système, c'est le "revenir en arrière"

Le revenir en arrière

Bon, avec ce systeme il est assez facil de faire des "précédent" "suivant"
ce que moi j'ai fais :
J'enregistre le numero du dialogue que je viens de construire à la fin du BuildDia, avec :
Code PHP:

DelayCommand(0.1SetLocalInt(oPJ"DIA_CURRENT"nConversation)); 

et au début du BuildDia, je sauvegarde les unes à la suite des autres les références des différents dialogue passés.
Code PHP:

int nPrevT GetLocalInt(oSpeak2"PREC_1");
//premiere référence enregistrée
 
int i=1;
 while(
nPrevT != 0)
    {
    
i++;
    
nPrevT GetLocalInt(oSpeak2"PREC_"+IntToString(i));
    
//on recupere le nb de la dernière valide et on fait +1
    
}
 
SetLocalInt(oSpeak2"PREC_"+IntToString(i), GetLocalInt(oSpeak2"DIA_CURRENT"));
//a ce dernier+1 on assigne la référence actuelle 
Je crée dans le dialogue, une réplique du style
[PJ] *revenir en arrière*

avec en action conséquente un DoDia, avec en entrée 9, le numéro de la réplique (qui ne change pas cependant, c'est toujours la même, donc pas de CUSTOM8009 )
et un test qui vérifie qu'on a au moins une référence de dialogue entrée, sinon ca n'est pas la peine d'afficher la réplique

dans le DoDia on insere :
Code PHP:

if(nChoice == 9)   //si on a clique sur precedent
 
{
 
int nPrevT GetLocalInt(oPJ"PREC_1");
 
int i=1;
 while(
nPrevT != 0)
    {
    
i++;
    
nPrevT GetLocalInt(oPJ"PREC_"+IntToString(i));
    }

 
i--;  //on recupere la derniere, pas la derniere+1 ^_^
 
nConv GetLocalInt(oPJ"PREC_"+IntToString(i));
 
//nConv est entree dans le BuiltDia
 
DeleteLocalInt(oPJ"PREC_"+IntToString(i));
 
//on dit de cosntruire le dernier dia stok, puis on supprime cette reference
 
}
 else 
//si on clique pas sur precdent, on stocke la derniere reference
 
{
 
int nPrevT GetLocalInt(oPJ"PREC_1");
 
int i=1;
 while(
nPrevT != 0)
    {
    
i++;
    
nPrevT GetLocalInt(oPJ"PREC_"+IntToString(i));
    }
 
SetLocalInt(oPJ"PREC_"+IntToString(i), GetLocalInt(oPJ"DIA_CURRENT"));

 
SetLocalInt(oPJ"PREV"1);
 } 

Je n'est pas fais de module demo par faute de temps, mais le DMWand utilise ce système, enfin, ce genre de systeme lol, ainsi que le crieur de rue de RAT (c'est lui qui m'a conseillé ces deux trucs ), et mon machin dès que je le finis


Bon, si j'ai oublié un truc, ba je completerais si personne le vois avant moi
dsl pour l'ortographe désastreuse . . . mais c lisible il me semble

Tout cela n'est absolument pas utilisable comme ca
Il faut comprendre le machin et réemployer les bases donnée ici


edit tardif : il paraitrait que ce topic aide à comprendre (il y est qu'estion d'un dialogue no dynamique, mais qui utilise un pitit bout du principe
Je ne fais pas du tout la tête

il a bien fait de faire ce post .

Mais je suis en train de me demander si je vous ai donné ma fonction de dialogue dynamique, plus simple à comprendre que le DMHelper mais il possède un tout petit bug visuel face au DMHelper quand tu arrives au dernier dialogue.
En tout cas c'est tres interressant tout ça...
Je m'etais un peu penché sur les custom token dans les dialogues mais sans plus, et je ne me serais pas douté des possibilités que cela offrait...
Et dans le cadre d'un monde persistant cela ouvre vraiment des horizons tres interressants
en effet, surtout que couplé avec une bonne gestion de Patternes, on peut faire un nombre de trucs proprement hallucinant
Ainsi un DM peut modifier les dialogues en plein jeu, un joueur peut personnaliser le dialogue d'un objet (m'a permis de faire une zone "préférences" à un tem ), enfin bref, ca permet un tas de trucs qui peuvent être impossible avec un dialogue fait normalement par le toulsèt ^_^
couplez ça avec les tokens de jedai et permettez vous de verser une petite larme de joie
Je ne l'ai pas mis, mais personnelement j'ai défini l'objet

oPJ

utilisé partout en haut de la bibliothèque où se trouvent toutes le fonctions, plus besoin alors de le passer en argument pour chaque fonction
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés