[Modding] Verständnisproblem beim D-Dialogformat

Shai Hulud

Senior Member
Registriert
18.01.2015
Beiträge
194
Ich schreibe gerade einen (minimalistischen) Parser für Dateien im D-Dialogformat. Dabei stolpere ich über ein Konstrukt, an dem ich mir bisher die Zähne ausbeiße und bei dem ich Hilfe bräuchte:

Die Mod „Balduran's Seatower“ verwendet in der Datei bs-baldurans-seatower-veaob.6/bst/dialog/YSMCOOK1.d in den Zeilen 3-12 folgenden Code:
Code:
CHAIN
IF ~Global("bsCookSawDwarf","GLOBAL",0)
OR(6)
Race(Player1,DWARF)
Race(Player2,DWARF)
Race(Player3,DWARF)
Race(Player4,DWARF)
Race(Player5,DWARF)
Race(Player6,DWARF)~ THEN ~YSMCOOK1~ dwarffun
@1227 /* ~Hey you! Dwarf! The alestore's locked so you can get your dirty carcass out of my kitchen NOW!!!~ */ DO ~SetGlobal("bsCookSawDwarf","GLOBAL",1)~
Nach meinem Verständnis der WeiDU-Dokumentation zum D-Format sollte dieses Konstrukt aber gar nicht möglich sein und in der letzten Zeile beim DO gegen die CFG des D-Formats verstoßen, denn:

Eine CHAIN wird nach WeiDU wie folgt definiert:
Code:
CHAIN [ IF [ WEIGHT #weight ] stateTriggerString THEN ] entryFilename entryLabel chainText list chainEpilogue
Das bedeutet also für den obigen Code, dass entryLabel mit dem Wert dwarffun belegt ist. Danach greift die Regel zur chainText list:
Code:
[ IF transTriggerString THEN ] sayText = sayText ...
Das heißt, das erste sayText ist mit Umwegen über die Definitionen von text und reference mit dem Wert @1227 belegt, optionale weitere = sayText sind nicht vorhanden.

Der nachfolgende Kommentar im Seeturm-Code wird nach WeiDU ignoriert und wir landen beim DO ~SetGlobal("bsCookSawDwarf","GLOBAL",1)~, wo ich jetzt das Problem sehe. Wenn ich es richtig verstehe, erlaubt weder die Definition von chainText list noch von chainEpilogue das Vorhandensein eines DO an dieser Stelle. Ein DO wird nach WeiDU lediglich durch die Regel eines transFeature erlaubt, welche hier aber keine Anwendung findet.

Allerdings lässt sich die Mod installieren, ohne einen Fehler zu werfen, daher gehe ich davon aus, dass der Seeturm-Code korrekt ist und ich die Doku nicht richtig verstanden habe. (Eine andere Möglichkeit wäre, dass die Doku falsch ist, aber ich gehe zunächst mal von einem Verständnisproblem meinerseits aus.)

Kann einer von euch erkennen, wo mein Denkfehler liegt?
 

Maus

Senior Member
Registriert
07.08.2002
Beiträge
9.399
Ich glaube, dass die Doku da ähm unvollständig ist. Ein DO kann man glaube ich sehr häufig verwenden... aber ich bin mir nicht sicher. Im Code kommt sicherlich auch noch ein END oder?
 

Shai Hulud

Senior Member
Registriert
18.01.2015
Beiträge
194
Danke für deine Einschätzung. Hm, eine unvollständige Dokumentation wäre natürlich das ärgerlichste Szenario für mich.
Ja, ein END kommt wie von der Regel chainEpilogue definiert am Ende vor:
Code:
CHAIN
IF ~Global("bsCookSawDwarf","GLOBAL",0)
OR(6)
Race(Player1,DWARF)
Race(Player2,DWARF)
Race(Player3,DWARF)
Race(Player4,DWARF)
Race(Player5,DWARF)
Race(Player6,DWARF)~ THEN ~YSMCOOK1~ dwarffun
@1227 /* ~Hey you! Dwarf! The alestore's locked so you can get your dirty carcass out of my kitchen NOW!!!~ */ DO ~SetGlobal("bsCookSawDwarf","GLOBAL",1)~
== %KAGAIN_JOINED% IF ~InParty("Kagain") See("Kagain") !StateCheck("Kagain",CD_STATE_NOTVALID)~ THEN @1243 /* ~Shut yer yap woman. Yer making me ears hurt and me axe twitchy.~ */
= @1242 /* ~I wouldn't want yer dirty ale if it was the last drop in Baldur's Gate and <HESHE> wouldn't either. Yer storeroom's probably got more rats in it than fleas on a mangy cur.~ */
== ~YSMCOOK1~ IF ~InParty("Kagain") See("Kagain") !StateCheck("Kagain",CD_STATE_NOTVALID)~ THEN @1220 /* ~Right, you hairy little runt!~ */
== %YESLICK_JOINED% IF ~InParty("Kagain") See("Kagain") !StateCheck("Kagain",CD_STATE_NOTVALID)
InParty("Yeslick") See("Yeslick") !StateCheck("Yeslick",CD_STATE_NOTVALID)~ THEN @1240 /* ~One day, Kagain, I swear by Clangeddin's Beard that mouth of yours is going to stop my axe.~ */
== %KAGAIN_JOINED% IF ~InParty("Kagain") See("Kagain") !StateCheck("Kagain",CD_STATE_NOTVALID)
InParty("Yeslick") See("Yeslick") !StateCheck("Yeslick",CD_STATE_NOTVALID)~ THEN @1241 /* ~Heh! An' that'll be the day the sun shines out of yer arse too. Bend over and we'll take a look, shall we?~ */
== %YESLICK_JOINED% IF ~InParty("Yeslick") See("Yeslick") !StateCheck("Yeslick",CD_STATE_NOTVALID)~ THEN @1247 /* ~Yeslick Orothiar at your service ma'am. May Clangeddin Silverbeard give his blessing upon you.~ */ == ~YSMCOOK1~ IF ~InParty("Yeslick") See("Yeslick") !StateCheck("Yeslick",CD_STATE_NOTVALID)~ THEN @1223 /* ~Well now, isn't that a surprise? A dwarf with manners!~ */
== ~YSMCOOK1~ IF ~InParty("Yeslick") See("Yeslick") !StateCheck("Yeslick",CD_STATE_NOTVALID)
!RACE(Player1,DWARF)~ THEN @1228 /* ~Yes, well. Be welcome then Yeslick Orothiar - but ye can still keep yer hands off my alestore!~ */
== %YESLICK_JOINED% IF ~InParty("Yeslick") See("Yeslick") !StateCheck("Yeslick",CD_STATE_NOTVALID) !RACE(Player1,DWARF)~ THEN @1246 /* ~Dwarf - yes, but a thief - no. I am sorry if other members of dwarfkind have given you a bad impression of all of us.~ */
END
Für mein Vorhaben reicht es allerdings nicht aus, Anfang und Ende des CHAIN-Blocks ermitteln zu können, sondern auch die String-Beziehungen innerhalb des Blocks erfassen zu können.

Angenommen, die Doku ist tatsächlich falsch, wäre das Pocket-Plane-Forum der richtige Ort für eine Meldung?
 

Taimon

Infinity Engineer
Registriert
25.11.2001
Beiträge
1.501
Die Doku ist an dieser Stelle tatsächlich unvollständig, aber ich weiß auch gar nicht, ob sie überhaupt den Anspruch darauf hat.
Im CHAIN-Tutorial der Readme sieht man, dass diese Syntax gültig ist.

Wenn man sich den D-Parser von WeiDU anschaut, dann findet man dort folgende Regeln:
Code:
| chain3_prologue chain3_list compound_chain3_list chain3_epilogue
[...]

chain3_list : optional_condition lse optional_action     { [($1,$2,$3)] }
| optional_condition lse optional_action EQUALS chain3_list
[...]

  optional_action :       { None }
| DO STRING             { let verified_action = verify_action_list $2 in
  Some(verified_action) }
    ;

Wenn du selbst einen Parser schreiben möchtest, vermute ich, dass du mit der Grammatik schon ein bisschen was anfangen kannst.
Falls nicht, dann hier noch mal nachfragen.
Es gibt auch noch einen Lexer, aber die meisten Sachen sollten selbsterklärend sein. (CHAIN wird durch den Lexer zu CHAIN3)

/Edit:
Mir ist gerade noch aufgefallen, dass dein Link zu einer älteren WeiDU-Dokumentation führt.
Für den konkreten Fall spielt das keine Rolle, aber vielleicht trotzdem besser die neueste Version nutzen.
 
Zuletzt bearbeitet:

Shai Hulud

Senior Member
Registriert
18.01.2015
Beiträge
194
Ich wollte es eigentlich vermeiden, mich durch den ML-Code arbeiten zu müssen, daher meine Hoffnung auf die Dokumentation. Hm, wird mir wohl nichts anderes übrig bleiben.
 
Oben