Page 1 sur 1

[DLG] Dialogue P qui ne s'enclenche pas

Posté : dim. 30 mai 2021, 10:20
par Bataff
Contexte : BGT en commençant à Château-Suif (BG1).

Bonjour,
Je poste ce sujet car depuis deux bons jours je ne suis pas arrivé à faire déclencher normalement le dialogue P prévu pour la gestion d'entrée et sortie du groupe d'un PNJ par l'intermédiaire du fichier PDIALOG.2DA, bien qu'en ayant trouvé une alternative.

Descriptif du problème : Le dialogue J prend normalement le relai une fois que le PNJ a été recruté mais, lorsqu'on vire ce dernier du groupe, le P ne prend pas le relai et c'est toujours le J qui est actif lorsque le pnj exclu retourne voir Player1 après avoir été éjecté. Puis c'est un script par défaut du jeu (par exemple, du type : "Bonne nuit mesdames et messieurs ...") lorsque Player1 lui parle à nouveau.

J'ai pu contourné le problème en forçant le dialogue P par l'action dynamique SetDialog là où il faut dans le dialogue J (cf code à la fin du message avec le PNJ-test entp1).
Mais la question que je me pose est si c'est bien normal d'avoir à faire ainsi. Le problème est quand même que le jeu ignore purement et simplement le fichier P mentionné dans PDIALOG.2DA . A quoi cela pourrait-être dû? Un bug ou aurais-je fait une erreur quelque-part? Quelque-chose m'aurait-il échappé ?
Par des sauvegardes aux différentes étapes dans les entrées et sorties du groupe, j'ai pu aussi constater avec NI que le dialogue J est toujours dans la case dialogue après la sortie du PNJ.
Sinon, j'ai aussi testé au cas-où le script Dream et les banters et ces derniers s'enclenchent sans soucis (par la touche repos pour le premier et en utilisant le cheat code CTRL+I pour les seconds).

J'ai fait un mod test basique avec le moins de fioritures possibles avec deux PNJ à Château-Suif (ar0015) : entp1 et entp2. Le PNJ où le dialogue P n'a pas été forcé s'appelle entp2 et celui où le dialogue P a été forcé par SetDialog s'appelle entp1. Leurs variables death sont respectivement entp2 et entp1, scripts entp2 et entp1 dans leur case override et dialogues entp2 et entp1 dans la case dialogue dans leurs fichiers .cre.

Voilà les différents fichiers pour le PNJ entp2 :

entp2.baf :

Code : Tout sélectionner

IF
  See([PC])
  NumTimesTalkedTo(0)
THEN
  RESPONSE #100
//    Dialogue([PC])
END
Dialogues :

Code : Tout sélectionner

BEGIN ~entp2~
IF ~!InParty(Myself)~ THEN BEGIN 10
  SAY ~(dialogue entp2) Bonjour, je suis entp2~
  IF ~~ THEN DO ~~ REPLY ~oui~ EXIT
  IF ~~ THEN DO ~JoinParty()~ REPLY ~Viens~ EXIT  //test
END

Code : Tout sélectionner

BEGIN ~entp2P~
IF ~True()~ THEN BEGIN 0
  SAY ~(dialogue entp2P) Snif, adieu ...~
  IF ~~ THEN REPLY ~Mouaip~ EXIT
  IF ~~ THEN DO ~JoinParty()~ REPLY ~Meuh non, reviens~ EXIT
END

Code : Tout sélectionner

BEGIN ~entp2J~
IF ~True()~ THEN BEGIN 0
  SAY ~(dialogue entp2J) je suis avec vous~
  IF ~~ THEN REPLY ~Mouaip~ EXIT
  IF ~Global("entp2bav","LOCALS",1)~ THEN REPLY ~le script entp2D fonctionne~ EXIT //Pour tester le script Dream
END

Code : Tout sélectionner

BEGIN ~entp2B~
IF ~True()~ THEN BEGIN 0
  SAY ~(dialogue entp2B) Pas le temps de bavarder~
  IF ~~ THEN REPLY ~Mouaip~ EXIT
END
(oui... le B doit être normalement avant le nom par convention :rtfm: )

entp2D.baf :

Code : Tout sélectionner

IF
  Global("entp2bav","LOCALS",0)
THEN
  RESPONSE #100
    SetGlobal("entp2bav","LOCALS",1)
END
ar0015.baf :

Code : Tout sélectionner

IF
  Global("enttestcreations","ar0015",0)
THEN
  RESPONSE #100
    SetGlobal("enttestcreations","ar0015",1)
    CreateCreature("entp1",[1000.800],3)
    CreateCreature("entp2",[950.800],3)
END
Fichiers test.tp2 et log weidu (version 246):

Code : Tout sélectionner

BACKUP ~test/Backup~
AUTHOR ~Bataff~

BEGIN ~test~

EXTEND_BOTTOM ~ar0015.bcs~ ~test/ar0015.baf~

COMPILE ~test/p1/entp1.d~
COMPILE ~test/p1/entp1P.d~
COMPILE ~test/p1/entp1J.d~
COMPILE ~test/p1/entp1B.d~
COMPILE ~test/p1/entp1D.baf~
COMPILE ~test/p1/entp1.baf~
COMPILE ~test/p2/entp2.d~
COMPILE ~test/p2/entp2P.d~
COMPILE ~test/p2/entp2J.d~
COMPILE ~test/p2/entp2B.d~
COMPILE ~test/p2/entp2.baf~
COMPILE ~test/p2/entp2D.baf~

COPY ~test/p1/entp1.cre~ ~Override~
  SAY NAME1 ~Perso1~
  SAY NAME2 ~Perso1~
BUT_ONLY

COPY ~test/p2/entp2.cre~ ~Override~
  SAY NAME1 ~Perso2~
  SAY NAME2 ~Perso2~
BUT_ONLY

APPEND ~pdialog.2da~
~entp1 entp1P entp1J entp1D entp1P entp1J *** ***~
UNLESS ~entp1~

APPEND ~interdia.2da~
~entp1 entp1B entp1B~
UNLESS ~entp1~

APPEND ~pdialog.2da~
~entp2 entp2P entp2J entp2D entp2P entp2J *** ***~
UNLESS ~entp2~

APPEND ~interdia.2da~
~entp2 entp2B entp2B~
UNLESS ~entp2~
► Afficher le texte
Et voilà pour finir le dialogue P et le dialogue J qui contourne le problème pour le PNJ entp1 (si le PNJ est sorti, le dialogue J est toujours actif mais il passe dans ce cas la main au dialogue P) :

Code : Tout sélectionner

BEGIN ~entp1P~
IF ~True()~ THEN BEGIN 11
  SAY ~(script entp1P) Je suis toujours exclu ?~
  IF ~~ THEN DO ~~ REPLY ~Mouaip~ EXIT
  IF ~~ THEN DO ~JoinParty()~ REPLY ~Meuh non, reviens~ EXIT
END

Code : Tout sélectionner

BEGIN ~entp1J~
IF ~InParty(myself)~ THEN BEGIN 10
  SAY ~(dialogue entp1J) Je suis avec vous~
  IF ~~ THEN REPLY ~Ben oui~ EXIT
  IF ~Global("entp1bav","LOCALS",1)~ THEN REPLY ~le script entp1D fonctionne~ EXIT //Pour tester le script Dream
END

IF ~!InParty(myself)~ THEN BEGIN 12
  SAY ~(dialogue entp1J) On y va ?~
  IF ~~ THEN DO ~SetDialog("entp1p")~ REPLY ~Non, tu restes ici~ EXIT
  IF ~~ THEN DO ~JoinParty()~ REPLY ~Mouaip~ EXIT
END

Posté : dim. 30 mai 2021, 23:10
par Bataff
Bon, après avoir jeté un coup d'oeil sur quelques fichiers J de perso de BG1 ( trouvés dans ../BGII-Soa/bgt/base/d_bg1/), il semblerait que ce soit la même méthode utilisée ou presque (mais peut-être pas partout, à voir). Voilà ce qu'il y a par exemple dans safanj.d :

Code : Tout sélectionner

IF WEIGHT #3 ~False()~ THEN BEGIN 1
  SAY @16653
  IF ~~ THEN DO ~LeaveParty()
SetDialog("SafanP")~ EXIT
END
(avec le False() qui ne devrait logiquement jamais faire fonctionner cette partie mais qui le ferait quand même si aucun trigger n'a déclenché quelque-chose ailleurs, si j'ai bien compris)

Posté : lun. 31 mai 2021, 08:53
par Bataff
(suite) Pour le False(), c'est l'explication que j'avais trouvé par Isaya dans ce fil : https://www.baldursgateworld.fr/lacouronne/dialogues/31030-dlg-dialogue-de-depart-personnalise.html :
[quote=""Isaya" (message #4)"]Remarque : je ne suis certain à 100 % que la combinaison de False() et d'une autre condition fonctionne puisque le but de False() est d'attraper le cas où aucune condition prévue ailleurs dans le dialogue n'a déclenché. Néanmoins, au pire, il faudrait simplement remplacer False() par le test de ta variable.[/quote]
C'est la seule que j'ai sous la main jusqu'à maintenant (et du mal à comprendre ce type de programmation).

Sinon, j'ai vu une combinaison de False() et d'une autre condition dans le dialogue khalij.d :

Code : Tout sélectionner

IF WEIGHT #4 ~False()
!InParty("Jaheira")~ THEN BEGIN 0
  SAY @16683
  IF ~~ THEN DO ~LeaveParty()
SetDialog("KhaliP")~ EXIT
END
Pour d'autres PNJ comme Kagain, il n'y a pas de dialogue P, le départ du PNJ semble être géré dans le J.
Edit : Ah si, il y a un KagaiP mais pas dans /bgt/base/d_bg1/ Il est dans /bgt/compat/bgt/ et intégré dans le jeu.

Bon, déçu que le P ne soit pas géré automatiquement par pdialog.2da mais d'un autre côté, je suis rassuré que ce fait ait été reconnu par les développeurs de BGT (et donc mon cas n'est pas isolé :$ )

Posté : dim. 04 juil. 2021, 09:07
par Bataff
Je viens de trouver autre chose. Après avoir créé un autre PNJ à Brasamical avec deux dialogues P et J, le P s'est enclenché automatiquement après sa sortie du groupe (et c'était la première fois qu'un de mes PNJs le faisait).
Je me suis demandé d'abord si cela ne viendrait du fait qu'il n'ait pas été créé à Château-Suif. Mais cela me semblait improbable.

J'ai examiné ensuite les fichiers CRE de ce nouveau PNJ et de l'un des anciens (où le P ne s'enclenchait pas) et j'ai remarqué une différence :
L'ancien avait le flag activé (dans NI) 'Export allowed (11)' et pas le nouveau.

J'ai désactivé ce flag à l'ancien PNJ créé dans Château-Suif, recommencé une partie pour le recruter puis le virer. Et ... le P s'est enclenché automatiquement. Il me restait à rectifier les dialogues P et J en conséquence et c'était tout bon ;) .

Edit : Reste le mystère du False(). Hormis un cas particulier trouvé dans un forum anglo-saxon (mais perdu le lien) et qui ne correspondait pas à cette situation, je n'ai rien trouvé qui étayerait qu'il pourrait exécuter un bloc malgré tout.
Je me demande si False() ne serait pas tout simplement ce que son nom indique et que les concepteurs en ont simplement rajouter dans les conditions pour empêcher que les blocs en question s'exécutent afin de pouvoir suivre une autre piste, sans les supprimer dans le cas où il aurait fallu y revenir. Mais ce n'est qu'une hypothèse.
En attendant, je pense que je peux mettre mon fil en résolu.