Inhaltsverzeichnis

Dialoge

Sie sind das Hauptelement, um eure Geschichte zu erzählen.
Dialoge zu erstellen und ins Spiel zu bringen sollte deswegen keine Probleme bereiten.
Ihr wisst bereits was Klassen, Instanzen und Funktionen sind? Dann weiter!

Dialogoptionen

Wenn der Spieler einen NPC anspricht werden ihm einige Dialogoptionen zur Auswahl gegeben, aber längst nicht alle. Das merkt ihr allein schon daran, dass Aufträge mit einer bestimmten Dialogoption beendet werden, welche jedoch zu Beginn des Auftrags noch nicht zur Auswahl stand.

Man kann sagen das Tun und Lassen des Spielers ist darauf ausgerichtet Dialogoptionen verfügbar zu machen.
Beim Anzeigen der Auswahlliste entscheidet die Engine, welche der vielen möglichen Dialogoptionen in die Auswahlliste kommen. Sie bedient sich dazu eurer Angaben in den Instanzen von Klasse C_INFO.

Beispiel

///////////////////////////////////////////////////////////////////////
// Info EXIT 
///////////////////////////////////////////////////////////////////////
instance DIA_Ignaz_EXIT ( C_INFO )
{
   npc         = VLK_498_Ignaz;
   nr          = 999;
   condition   = DIA_Ignaz_EXIT_Condition;
   information = DIA_Ignaz_EXIT_Info;
   permanent   = TRUE;
   description = "ENDE";
};
 
func int DIA_Ignaz_EXIT_Condition() {
   return TRUE;
};
 
func void DIA_Ignaz_EXIT_Info() {
   AI_StopProcessInfos(self);
};
 
///////////////////////////////////////////////////////////////////////
// Info Hallo 
///////////////////////////////////////////////////////////////////////
instance DIA_Ignaz_Hallo (C_INFO) {
   npc         = VLK_498_Ignaz;
   nr          = 2;
   condition   = DIA_Ignaz_Hallo_Condition;
   information = DIA_Ignaz_Hallo_Info;
   permanent   = FALSE;
   important   = TRUE;
};
 
func int DIA_Ignaz_Hallo_Condition() {
   if Npc_IsInState(self, ZS_Talk) {
       return TRUE;
   };
};
 
func void DIA_Ignaz_Hallo_Info() {
   AI_Output(self, other, "DIA_Ignaz_Hallo_14_00");//Ah - du kommst mir gerade recht. Ich suche noch einen Assistenten für ein magisches Experiment.
   AI_Output(self, other, "DIA_Ignaz_Hallo_14_01");//Du willst doch bestimmt der Wissenschaft einen Dienst erweisen.
   AI_Output(other, self, "DIA_Ignaz_Hallo_15_02");//Immer langsam. Sag mir erst mal, worum es geht.
   AI_Output(self, other, "DIA_Ignaz_Hallo_14_03");//Ich habe einen neuen Zauber entwickelt. Einen Zauber des Vergessens.
   AI_Output(self, other, "DIA_Ignaz_Hallo_14_04");//Ich konnte bereits einige praktische Anwendungen durchführen, aber mir fehlt die Zeit für einen abschließenden Test.
};

Wie ihr an dem Beispiel erkennen könnt, beginnt das Einfügen einer neuen Dialogoption mit dem Aufschreiben ihrer Instanz. DIA_Ignaz_EXIT, der Bezeichner ist im gesamten Spiel eindeutig und darf nicht ein zweites Mal vergeben werden. Mit der Instanz werden die Eigenschaften der Dialogoption festgelegt.

Darauf folgt die Bedingungsfunktion DIA_Ignaz_EXIT_Condition. Nebenan sind die Bedingungen immer erfüllt.

Zuletzt kommt noch der Dialog als Callbackfunktion DIA_Ignaz_EXIT_Info.
Es ist offenbar, dass durch Auswahl dieser Dialogoption kein Dialog gestartet wird. Im Gegenteil die Dialogoptionenauswahlliste wird durch den Befehl AI_StopProcessInfos(self); versteckt und der Spieler kann sich wieder frei bewegen. Es handelte sich um die ENDE Auswahl in den Dialogoptionen von Ignaz.

Detailerklärung

DIA_Ignaz_EXIT_Condition
func int DIA_Ignaz_EXIT_Condition() {
   return true;
}; 

DIA_Ignaz_EXIT_Condition ist der Name für die Auflistung der Bedingungen, die alle wahr sein müssen, damit man den Dialog ausführen kann. Dieser Name muss auch oben bei condition = stehen.
Über das func int und die leere Klammer dahinter macht euch mal keine Gedanken - wenn ihr später richtig programmieren wollt, werdet ihr erfahren, warum das gebraucht wird. Erstmal braucht ihr es nicht wirklich verstehen, es muss nur dort stehen.
Nun kommen die Bedingungen. Für den ENDE-Dialog gibt es aber keine Bedingungen, die erfüllt werden müssen. Also schreibt man ein einfaches return true; hin, welches direkt sagt, dass alle Bedingungen wahr sind.

DIA_Ignaz_EXIT_Info
func void DIA_Ignaz_EXIT_Info () {
   AI_StopProcessInfos (self);
};

Hinter das func void kommt der Name des eigentlichen Dialogs.
Das AI_StopProcessInfos(self); befiehlt, dass nun der Dialog beendet wird. Dies ist also der Befehl für ein Beenden des Dialoges. Es gibt noch sehr viele andere Befehle - zum Beispiel das Ziehen einer Waffe, das Saufen von Bier etc. Das kann man alles selbst herausfinden, in Scripten wo ein NPC so etwas tut.

Hier ist der erste Dialog eigentlich schon beendet. Jeder NPC sollte einen Ende-Dialog haben oder zumindest etwas ähnliches, weil man unter Umständen sonst den Dialog nicht beendet kann und eventuell den PC neustarten muss.

DIA_Ignaz_Hallo
instance DIA_Ignaz_Hallo (C_INFO) {
	npc         = VLK_498_Ignaz;
	nr          = 2;
	condition   = DIA_Ignaz_Hallo_Condition;
	information = DIA_Ignaz_Hallo_Info;
	permanent   = false;
	important   = true;
};

Hier kommt noch etwas dazu. Das important = TRUE; sagt dem NPC, dass dieser Dialog wichtig ist, was bedeutet, dass der NPC den Held von selbst anspricht, sobald dieser in den Radius des NPC gerät. Wenn ein Dialog nicht wichtig ist, also FALSE, müsst ihr das nicht von selbst dazuschreiben, sobald important = nicht aufgeführt ist, wird angenommen, dass der Dialog nicht wichtig ist (das gilt übrigens auch für permanent = …).

DIA_Ignaz_Hallo_Condition
func int DIA_Ignaz_Hallo_Condition () {
  if Npc_IsInState (self, ZS_Talk) {
    return true;
  };
};

Hier ist nun die Bedingung, dass der NPC sich im Zustand „Reden“ befindet, damit dieser Dialog zustande kommt.
Das (self) wird immer aus der Sicht des NPC betrachtet.
Der NPC ist nicht im Zustand „Reden“, wenn der Spieler den NPC nicht angesprochen hat. Sobald man also nachher den NPC anspricht, wird er den eigentlichen Dialog ausführen, weil dann alle Bedingungen wahr sind.
Weil es im Forum nun zu oft zu Verwechslungen kam: Diese Condition sorgt nicht dafür, dass der NPC einen direkt anspricht! Wenn ihr möchtet, dass ihr angesprochen werdet, sobald ihr in der Nähe seid, schreibt einfach nur return true; in die Funktion!

DIA_Ignaz_Hallo_Info
func void DIA_Ignaz_Hallo_Info () {
  AI_Output(self, other, "DIA_Ignaz_Hallo_14_00");//Ah - du kommst mir gerade recht. Ich suche noch einen Assistenten für ein magisches Experiment.
  AI_Output(self, other, "DIA_Ignaz_Hallo_14_01");//Du willst doch bestimmt der Wissenschaft einen Dienst erweisen.
  AI_Output(other, self, "DIA_Ignaz_Hallo_15_02");//Immer langsam. Sag mir erst mal, worum es geht.// __
  AI_Output(self, other, "DIA_Ignaz_Hallo_14_03");//Ich habe einen neuen Zauber entwickelt. Einen Zauber des Vergessens.
  AI_Output(self, other, "DIA_Ignaz_Hallo_14_04");//Ich konnte bereits einige praktische Anwendungen durchführen, aber mir fehlt die Zeit für einen abschließenden Test.
};

Sieht das kompliziert aus? Ja. Aber mit ein wenig Nachdenken und Verstehen kommt man schnell hinter dieses System.
AI_Output ist die wohl am häufigsten verwendete Funktion. Sie lässt den NPC oder den Held etwas sagen. Und auch hier wird wieder alles aus der Sicht des NPC betrachtet.
AI_Output(self, other, ) bedeutet also, dass self, der NPC etwas zu other, der Held sagt. Umgekehrt sagt also der Held etwas zu dem NPC, hier also zu Ignaz.
:Was nun in den Anführungzeichen steht, ist im Prinzip der Name der folgenden Aussage. Er darf nur ein einziges Mal (!) in allen Scripten auftauchen. Im Prinzip kann man hier auch „Ignaz_ist_nicht_intelligent_26_74“ stehen haben. Das einzige was zwingend ist, ist eine Doppelzahl, also 14_06 oder 25_95 und so weiter.
:Die Piranhas haben eine gewisse Ordnung in diese Namen gebracht, sodass man alles wiederfindet und dass alles überschaubar ist. Das was hinter // steht, wird in diesem Fall in die Untertitel geschrieben, die dann angezeigt werden.

Ihr seht, es gibt viele Befehle, 3 habt ihr bereits kennen gelernt. Stöbert in den Scripten und ihr werdet noch auf weit mehr stoßen. Und falls ihr tätsächlich komplett alles bisher gelesen und auch das meiste verstanden habt, besteht Aussicht darauf, dass euch das Scripten Spaß macht und dass ihr es zu etwas bringt.

Tja, falls du es noch nicht gemacht hast, solltest du diesen Dialog in einen Texteditor wie deinen NPC eingeben und eventuell noch auf deinen eigenen NPC umstellen.

Du weißt nicht, wo du deinen Dialog hinspeichern sollst? Das ist normalerweise in:
Gothic 2:

[Gothic II-Verzeichnis]\\_work\\data\\Scripts\\Content\\Story\\Dialoge

Gothic 1:

[GothicI-Verzeichnis]\\_work\\data\\Scripts\\Content\\Story\\Missions

Dann kannst du den Dialog genauso wie den NPC testen (du musst dann natürlich auch zum NPC hingehen, dem der Dialog gehört).

Eins sei noch gesagt: Wenn du keine Untertitel bei deinem Dialog siehst, ist das kein Fehler, sondern ganz normal, die müssen leider immer seperat erstellt werden. Das kannst du in diesem Kapitel durchnehmen.

Somit ist das zweite Kapitel abgeschlossen.
Ich hoffe ihr seit mit dem Tutorial zurecht gekommen.
Ich gebe euch noch mit auf den Weg - Fragen kostet nichts. Außer Zeit. Und die braucht ihr für erfolgreiches Modding.

Falls ihr es trotz der wunderbaren Beschreibung in diesem Tutorial nicht schaffen solltet, einen Dialog zu skripten, ladet euch den Gothic Text Editor runter. Es eignet sich hervorragend für Anfänger auf diesem Gebiet.

Außerdem empfielt sich der Miranda Dialog Creator, allerdings nur für Skripter, die die Materie begriffen haben. ;).