Eine Quest besteht aus vielen Teilen. Aus Dialogen, Erfahrungsvergabe usw., aber ohne die Tagebucheinträge gibt es eigentlich gar keine Quests. Darum habe ich dieses Tutorial geschrieben.
Die Tagebucheinträge bestehen eigentlich aus zwei Teilen. Einmal setzt man den Status des Auftrags (Aktuell, Erfüllt…) und einmal schreibt man die Tagebucheinträge dazu.
Bevor wir mit den Tagebucheinträgen wirklich beginnen können, müssen wir ein bisschen Vorarbeit leisten. Dazu gehört natürlich, die ganzen Dialoge schon zu schreiben. Dazu müssen einige (konstante) Variablen definiert werden.
Am besten macht ihr dazu zwei ganz neue Skripts. Das erste Skript heißt LOG_Constants_TESTNAME.d und das zweite B_CloseTopics_TESTNAME.d
. Beide Skripts solltet ihr in [Gothic II-Verzeichnis]\_work\Data\Scripts\Content\Story\Log_Entries
speichern. TESTNAME könnt ihr durch euren Namen ersetzen, dort schreibt ihr dann im Laufe eurer Skripter-Karriere alle Tagebuchvariablen rein.
Zuerst machen wir die LOG_Constants_TESTNAME.d
:
// *************************** // LOG_Constants für Missionen // // (LOG_MISSION) // *************************** const string TOPIC_TESTTAGEBUCHNAME = "AUFTRAGSNAME"; var int MIS_TESTTAGEBUCHNAME;
const string TOPIC_TESTTAGEBUCHNAME = "AUFTRAGSNAME";
Das const string
muss dorthin, die Gründe zu erklären wäre erstmal zu schwer… TOPIC_TESTTAGEBUCHNAME
ist der interne Name, der nur im Inneren von Gothic existiert. Er könnte also auch TOPIC_BLOEDER_AUFTRAG
heißen und es wäre sogut wie egal (aber ihr solltet natürlich Namen verwenden, die ihr im Code erkennt und die für euch eine sinnvolle Bedeutung haben!). Nur das TOPIC_
muss so bleiben und es dürfen auf keinen Fall Leerzeichen auftauchen!
Das was in den Anführungszeichen steht, ist dafür umso interessanter. Das ist nämlich der Name, der nachher im Tagebuch erscheint - diesen kann der Spieler also sehen und sollte darum ein aussagekräftiger Questname sein.
var int MIS_TESTTAGEBUCHNAME;
Das var int
ist prinzipiell wie das const string - es zeigt, dass das folgende der Name für eine Variable ist. Allerdings handelt es sich hier nicht um einen kostanten, nicht-änderbaren Text (const string
) sondern um eine variable, änderbare Zahl (var int
) TESTTAGEBUCHNAME ist der Name für die Variable und dieser Name ist intern (siehe TOPIC_TESTTAGEBUCHNAME). Diese Variable muss änderbar sein, weil sich der Status einer Mission ändern kann (von „nicht angenommen“ bis „erledigt“).
Das war an sich schon vorerst das ganze Skript, nachher kommen natürlich mehr Quests zusammen.
Nun schauen wir uns mal die B_CloseTopics_TESTNAME.d an:
// *************************************************** // B_CloseTopics_TESTNAME () (verschiebt Topics in den zugehörigen Log-Ordner bei FAILED oder SUCCESS) // *************************************************** func void B_CloseTopics_TESTNAME () { B_CloseTopic (TOPIC_TESTTAGEBUCHNAME,MIS_TESTTAGEBUCHNAME,0,6); };
func void B_CloseTopics_TESTNAME ()
Das func void
und das ()
kennt ihr ja nun schon zur Genüge und ihr könnt euch auch sicher denken, dass das B_CloseTopics_TESTNAME
der Name der Funktion ist. Der sollte übrigens mit dem Skriptnamen übereinstimmen und darf nur einmal in allen Gothic-Skripten vorhanden sein. Ihr könnt TESTNAMEN darum durch euren Namen ersetzen und dieses Skript für all eure Tagebucheinträge nutzen.
B_CloseTopic (TOPIC_TESTTAGEBUCHNAME,MIS_TESTTAGEBUCHNAME,0,6);
Das sieht vielleicht kompliziert aus - aber das ist es (mal wieder) kaum. Ein gutes Auge hat bemerkt, dass TOPIC_TESTTAGEBUCHNAME
und MIS_TESTTAGEBUCHNAME
bereits in der LOG_Constants_TESTNAME.d
vorkam - und es müssen auch genau die gleichen Namen sein. B_CloseTopic ist nachher der Befehl, um den Auftrag zu beenden - ansonsten wäre der Auftrag immer bei den aktuellen Tagebucheinträgen…
Nun bleibt nur noch zu erklären, was du 0 und die 6 am Ende sollen. Wer Gothic schon öfter gespielt hat, weiß, dass Gothic 6 Kapitel hat. Also ist die erste Zahl das Kapitel, in dem man den Auftrag anfangen kann und die zweite Zahl ist das Kapitel, wo man den Auftrag spätestens beendet haben muss. Würde dort also ,4,3); stehen, könnte man den Auftrag nie korrekt erfüllen, weil man ihn erst im vierten Kapitel anfangen könnte, der Auftrag allerdings schon im dritten Kapitel beendet sein müsste.
Das war an sich schon vorerst das ganze Skript, nachher kommen natürlich mehr Quests zusammen.
Jetzt haben wir schon die ganze Vorarbeit geleistet und müssen diese nur noch in unseren Dialogen einbauen. Dazu nutzen wir mal einen Beispieldialog:
instance PAL_555_Reiner_Testdialog01 (C_INFO) { npc = PAL_555_Reiner; condition = PAL_555_Reiner_Testdialog01_Condition; information = PAL_555_Reiner_Testdialog01_Info; important = FALSE; permanent = FALSE; nr = 1; description = "Ich will einen Auftrag!"; }; func int PAL_555_Reiner_Testdialog01_Condition() { return TRUE; }; func void PAL_555_Reiner_Testdialog01_Info() { AI_Output (other, self, "PAL_555_Reiner_Testdialog01_15_01");//Ich will einen Auftrag! AI_Output (self, other, "PAL_555_Reiner_Testdialog01_04_02");//Toll... Hier hast du einen! Log_CreateTopic (TOPIC_TESTTAGEBUCHNAME, LOG_MISSION); Log_SetTopicStatus(TOPIC_TESTTAGEBUCHNAME, LOG_RUNNING); B_LogEntry (TOPIC_TESTTAGEBUCHNAME,"Ich habe einen Auftrag bekommen..."); }; // ************************************************** instance PAL_555_Reiner_Testdialog02 (C_INFO) { npc = PAL_555_Reiner; condition = PAL_555_Reiner_Testdialog02_Condition; information = PAL_555_Reiner_Testdialog02_Info; important = FALSE; permanent = FALSE; nr = 2; description = "Habe ich den Auftrag geschafft?"; }; func int PAL_555_Reiner_Testdialog02_Condition() { if (Npc_KnowsInfo (hero, PAL_555_Reiner_Testdialog01)) { return TRUE; }; }; func void PAL_555_Reiner_Testdialog02_Info() { AI_Output (other, self, "PAL_555_Reiner_Testdialog02_15_01");//Habe ich den Auftrag geschafft? AI_Output (self, other, "PAL_555_Reiner_Testdialog02_04_02");//Ja! MIS_TESTTAGEBUCHNAME = LOG_SUCCESS; Log_SetTopicStatus(TOPIC_TESTTAGEBUCHNAME, LOG_SUCCESS); B_CheckLog(); };
Das meiste solltet ihr schon wissen, sonst solltet ihr das Dialog-Tutorial wiederholen. Ich gehe jetzt nur auf die Stellen ein, die ihr wahrscheinlich noch nicht versteht.
Log_CreateTopic (TOPIC_TESTTAGEBUCHNAME, LOG_MISSION); Log_SetTopicStatus(TOPIC_TESTTAGEBUCHNAME, LOG_RUNNING); B_LogEntry (TOPIC_TESTTAGEBUCHNAME,"Ich habe einen Auftrag bekommen...");
Das sieht sehr kompliziert aus - aber ihr wisst schon…
Die ersten zwei Befehle sind eigentlich recht simpel und dort müsst ihr nur TESTTAGEBUCHNAME durch euren internen Tagebuchnamen ersetzen. Diese drei Befehle sagen Gothic, dass dieser Auftrag nun aktuell ist und gelöst werden kann.
B_LogEntry (TOPIC_TESTTAGEBUCHNAME,„Ich habe einen Auftrag bekommen…“);
ist eigentlich auch ganz einfach, hier müsst ihr wieder TESTTAGEBUCHNAME
ersetzen und das, was in den Anführungszeichen steht, wird dann nachher ins Tagebuch reingeschrieben.
if (Npc_KnowsInfo (hero, PAL_555_Reiner_Testdialog01)) { return TRUE; };
Das könntet ihr schon verstehen. Der erste Dialog heißt ja PAL_555_Reiner_Testdialog01, und um den zweiten Dialog beginnen zu dürfen, muss der Held den ersten Testdialog kennen. Dann sind alle Bedingungen wahr und ihr könnt den Dialog ausführen. Es wäre ja blöd, wenn man direkt den zweiten Dialog auswählen könnte und die Mission erfüllt wäre, bevor man sie angefangen hat…
MIS_TESTTAGEBUCHNAME = LOG_SUCCESS; Log_SetTopicStatus(TOPIC_TESTTAGEBUCHNAME, LOG_SUCCESS); B_CheckLog();
TESTTAGEBUCHNAME
müsst ihr wieder ersetzen. Der Befehl MIS_TESTTAGEBUCHNAME = LOG_SUCCESS;
sagt Gothic, dass der Auftrag erfüllt ist. So könnte es aber auch MIS_TESTTAGEBUCHNAME = LOG_FAILED;
heißen, dann wäre der Auftrag z.B. nicht erfüllt.
Das gleiche gilt eigentlich auch für Log_SetTopicStatus(TOPIC_TESTTAGEBUCHNAME, LOG_SUCCESS);
, es könnte auch Log_SetTopicStatus(TOPIC_TESTTAGEBUCHNAME, LOG_FAILED);
heißen - es sollte einfach dort stehen, das gewährleistet, dass der Auftrag wirklich erfolgreich geschaltet wird.
B_CheckLog();
muss noch dahinter, damit Gothic das auch wirklich übernimmt.
Und das war schon das vierte Kapitel. Ich hoffe ihr habt möglichst viel verstanden und habt nun Laune, an euren eigenen Dialogen und Tagebucheinträgen zu arbeiten.
In dem Sinne, an die Arbeit. ;)