Ich hab neulich, im Zuge der Veröffentlichung dieses Blogs, in meinen Archiven herumgewühlt und ein Tutorial aus dem Jahre 2010 gefunden. Das mag lange her sein, aber da die Informationen hier immernoch aktuell sind, habe ich den Orginal-Text von damals nochmal überarbeitet, ein paar Screenshots hinzugefügt, und für euch hier verfügbar gemacht.

Eine (aktualisierte) Demo-Mod, welche die umgesetzten Inhalte dieses Tutorials demonstriert, findet in meinem Projekt-Portfolio: Klick mich

Viel Spaß! 🙂 

Motivation

Einer der interessantesten Dinge, die in einem Videospiel passieren können, sind große, sichtbare Veränderungen, die sich direkt auf die Landschaft,  eine Stadt oder sogar die gesamte Spielwelt auswirken. Egal, ob Gegenstände von einem Ort an einen anderen transportiert werden, Hütten und Häuser dort entstehen, wo vorher nur Brachland war oder ein ganzes Dorf von einem wütendenden Drachen dem Erdboden gleichgemacht wurde:  Eine Änderung der Spielwelt wird vom Spieler immer mit Erstaunen festgestellt und erzeugt das unverfälschte Gefühl: „Ich kann Einfluss auf die Spielwelt nehmen!“

Da ich dies einmal, vor langer Zeit, für eine eigene Modifikation für das legendäre Videospiel Gothic 2 brauchte,  habe ich mich auf die Suche nach Möglichkeiten gemacht, so etwas mit dem Gothic 2 Modkit zu realisieren. Mir wurde allerdings schnell klar, dass es, so wie ich es mir vorstellt hatte, keine direkte und vor allem keine einfache Lösungen dafür gab und ich daher mal wieder tief in die Trickkiste greifen musste um letzendlich doch noch eine Lösung zu finden. Eine gehörige Portion Hilfe von einigen besonders fähigen Modding-Kollegen, inklusive!

Dieses Tutorial soll daher nun, das Erstellen von dynamisch veränderbaren Levelmeshes, anhand eines konkreten Beispiels,
erklären. So lernt ihr, wie ihr z.B. eurem Levelmesh Hütten hinzufügt, wie ihr ganze Dörfer aufbauen oder zerstört und andere tolle Dinge mit eurer Spielwelt machen könnt, die sich direkt auf die Topologie der Spielumgebung auswirkt. Dabei werde ich nicht auf alle Aspekte umfassend eingehen, die für
die Umsetzung meiner Lösung nötig sind. Die Bedingung des Spacers, Hinzufügen und Skripten von Gegenständen, NPCs, etc. sowie generelles Arbeiten mit dem Gothic 2 Modkit, soll hier daher keine Rolle spielen. Dafür gibt es bereits eine Vielzahl ausgezeichneter Tutorials, etwa auf der Seite World of Gothic, auf der es eine große Zahl guter Tutorials gibt und auf der ihr auch Hilfe und Unterstützung finden könnte, sollte ihr einmal nicht mehr weiter wissen.

Nun, genug der Vorrede, fangen wir an!

Die Probleme

Nehmen wir an, wir wollen im „Alten Lager“ von Gothic 1 einen Baumeister hinzufügen, der dem Spieler eine Hütte bauen kann,
sofern dieser ihm Holz und Erz bringt. Wie bereits gesagt, werde ich hier nicht darauf eingehen wie man Quests und NPC´s erstellt. Ich nehme mal an, wenn ihr euch an dieses Tutorial ranwagt, könnt ihr das bereits 😉 (Wenn nicht, schaut euch die tollen Tutorials im Internet an. Es gibt glücklicherweise eine Menge gutes Material zum Thema „Gothic 2 Modding„!)

Zurück zu unserem eigentlichen Problem: Hütten sind standardmäßig Teil des sog. „statischen Levelmeshes„. Ein Mesh ist, in diesem Zusammenhang, ein 3D-Objekt, das mit Hilfe eines 3D-Modellierprogramms erstellt worden ist. Beispielsweise Blender, 3dsMax oder Maya. In Gothic 1 und Gothic 2 ist die Grundlage jedes Levels, dieses „Levelmesh„. Andere Spiele nutzen oft viele kleinere 3D-Modelle, aus denen sie dann in ihren (oft selbtentwickelten) Editoren, größere Level zusammensetzen. In Gothic wird dieser „statische“ Teil, der nicht verändert/bewegt/animiert/etc. werden soll, direkt in einem 3D-Modellierungsprogramm erstellt und dann als Grundlage für das darauf aufbauende Level verwendet. Darauf, wie man so ein Mesh erstellt, werde ich hier ebenfalls nicht eingehen(Auch dafür gibt es Tutorials!). Nachdem wir das Levelmesh in einem 3D-Modellierungsprogramm erstellt haben, exportiert man das 3D-Modell und bindet es dann in den, „Spacer“ genannten, Editor
des Gothic 2 Modkits ein, damit das Level dort mit dynamischen Inhalt befüllen kann. Da wird schnell klar, dass wir nicht ohne weiteres, eine neue Hütte zum „Alten Lager“ hinzufügen können. Schaut man sich die Orginal-Datei der Entwickler einmal genauer an, sieht man, dass die Hütten ein fester Teil der Level-Geometrie sind und diese nur aus einem(oder mehreren) große Level-Meshes besteht.  Wir können natürlich bereits im Vorfeld eine neue Hütte zu einem existierenden Level-Mesh hinzufügen(in dem wir z.B. das Levelmesh von Gothic 1 laden und im „Alten Lager“ irgendwo eine Hütte hinzufügen), aber leider ist das nicht sonderlich dynamisch, wie ihr euch sicher denken könnt. Viel toller wäre doch, wenn die Hütte zu Beginn noch gar nicht existiert und man während des Spiels selbst dafür arbeiten müsste, das uns jemand eine Hütte zusammenzimmert, die uns dann gehört.

Eine Möglichkeit wäre, das Haus als 3D-Objekt separat zu modellieren(also nicht als Teil des Levelmeshes) und dieses Objekt dann im Spacer über einen sog. Vob(visual object) zu realisieren. Das ist an sich schon eine ganz gute Lösung, allerdings eröffnen sich da leider 2 Probleme, wie ich bei anfänglichen Recherchen und Experimenten herausfand:

  1. Vobs werden nicht wie der statische Levelmesh behandelt, darum kann es ggf. Probleme mit Kollisionen geben oder es kann Probleme mit Objekten geben, die man vllt. später noch ergänzen möcht(z.B. eine Tür für die Hütte). Außerdem lassen sich für Vobs keine sog. Portale realisieren, was schlecht wäre, wenn man z.B. besonders große Gebäude realisieren will.
  2. Durch ALLE Vobs regnet es durch. Leider. Wenn ihr euch an die kaputten Hütten im Gothic 1 erinnert, welche sich südlich vom neuen Lager, in dem kleinen See, befinden, wisst ihr was ich meine: Bei Regen könnt ihr IM Haus stehen, doch es regnet durch. Das zerstört natürlich die ansonsten tolle Atmosphäre des Spiels und wirkt natürlich auch wie ein technischer Fehler, was wir generell gerne vermeiden würden.

Eine wirklich befriedigende Lösung, ist das also leider auch nicht. Natürlich könnte das, für den einen oder anderen, bereits die richtige Wahl sein. Durch verschiedene Tricks lassen sich oben genannte Probleme, sicher auch noch ausbessern, oder durch ein wenig umsichtigen Tricksen, verstecken. Etwa, wenn man eine neue Hütte zum neuen Lager hinzufügen will. Dort sind die meisten Hütten bekanntlich in einer großen Höhle, folglich kommt der Regen erst gar nicht bis zu den Hütten und wir könnten, ohne Probleme, eine neue Hütte als Vob hinzufügen. Eine andere Möglichkeit für freistehende Häuser wäre, dass man im Modellierungsprogramm eine „unsichtbare“ Plane über der Stelle anbringt, wo die Hütte dann später auftauchen soll. Das hätte allerdings den Nachteil, dass man an dieser Plane hängenbleiben könnte oder quaqsi „in der Luft“, auf der Plane, herumlaufen könnte. Außerdem sähe es merkwürdig aus, wenn
der Regen den rechteckigen Teil aussparen würde, solange das Haus noch nicht dort steht. Insgesamt also auch eine nicht ganz so befriedigende Lösung. Also müssen wir uns noch etwas
anderes einfallen lassen, damit wir unser Problem umsetzen können.

Im Editing-Unterforum, auf der Website World of Gothic, las ich, in einem Tread, dass ein User nach „Veränderbaren Levelmesh-Teilen“ gefragt hat und prompt die Antwort bekam, das man den statischen Teil zur Laufzeit nicht ändern kann. Dieser kann somit nur einmal festgelegt werden. Das erneute Laden der selben Level-Datei, die nur weniger veränderte Elemente enthält, würde dazu führen, dass all unsere Änderungen(Items aufgenommen, Quest gelöst, etc.) verworfen werden, wir also z.B. Items erneut aufnehmen können, die wir aber eigentlich schon aufgehoben haben. Das wäre natürlich ein krasserer Einschnitt in die Spielglaubwürdigkeit und würde zudem noch weitere Probleme mit sich ziehen(etwa Speicherverschwendung). Einer der findigstenen User dort, mit dem Namen Sektenspinner, war aber, wie immer, so freundlich und berichtete von einer Möglichkeit, wie man dies dennoch  bewerkstelligen kann, ohne die Änderungen zu verlieren oder fehlerhaftes Verhalten des Levels hinnehmen zu müssen. Dies funktioniert, in dem man sich die internen Eigenheiten der Gothic Engine zu Nutze macht. Wir werden also einen Trick anwenden, um die Beschränkung des statischen Levelmeshes zu umgehen.

Erstmal zur Theorie:

Angenommen wir haben 2 ZEN-Dateien(Das sind die Level-Dateien der Gothic-Engine, welche die dynamischen und skriptgesteuerten Objekte beinhalten, wie etwa Items, Wegpunkte, Bäume, etc.). Dabei kommt es nun auf den genauen Aufbau der Dateien an. Die eine Datei enthält das gewünschte Level OHNE und die andere MIT den gewünschten
Änderungen(z.B. „Altes Lager“ ohne unsere neue Hütte und einmal mit unseren neuen Hütte). Selbstverständlich müsst ihr zunächst die ZEN-Datei, die wir verwenden wollen, erstellen und mit Inhalt befüllen, Wegpunkte setzen, Objekte platzieren, etc. Also alle Schritte durchführen um die Level-Datei entsprechend vorzubereiten.Dann brauchen wir natürlich noch eine zweite Level-Datei(bzw. auch mehrere, je nach dem wieviele „Stufen“ der Veränderung man darstellen möchte). Wichtig ist dabei vor allem, dass die richtigen Levelmeshes-Dateien zugewiesen werden. Alles andere ist dann wieder davon abhängig, was ihr konkret mit dem Level machen wollt. Die ZEN-Dateien selbst müssen sich dann ZWINGEND an 2 verschiedenen (Unter-)Ordnern befinden(wenn ihr mehr Dateien habt, braucht ihr natürlich auch mehr Ordner):

<Gothic 2 Pfad>\_work\Data\Worlds\KAP1\WORLD.ZEN

<Gothic 2 Pfad>\_work\Data\Worlds\KAP2\WORLD.ZEN

Wenn man zuvor die WORLD.ZEN ohne Änderungen geladen hat und dort mit Vobs interagiert hat(z.B. Items aufgenommen),
erstellt das Spiel eine Savegame-Datei von diesem „Level“ und speichert alle Änderungen, die ihr hier bereits
vorgenommen habt, sobald ihr das erste Mal speichert. Läd man nun(per Level-Change) die 2. WORLD.ZEN, so bleibt alles beim alten, nur der statische Teil wird ausgetauscht, sofern wir in der 2. ZEN-Datei ein anderes statisches Levelmesh ausgewählt haben. Der Trick dabei ist, dass die Level-Dateien den gleichen Namen hat und somit keine „neue“ Savegame-Datei angelegt wird. Dem Spiel wird vorgegaukelt, es würde die selbe Level-Datei laden und bekommt daher nicht mit, dass es sich eigentlich um eine andere Datei handelt und läd die gespeicherten Änderungen,  in der Welt, in das „neue“ Level hinein.

Das ist schonmal eine tolle Möglichkeit um neue statische Objekte zur Laufzeit des Spiels(und somit eurer Mod 😉
hinzuzufügen. Nehmen wir mal an, man möchte irgendwann eine Statue, für den Namenlosen Helden, in Khorinis aufstellen. Beispielsweise als Belohnung oder als Erinnerung an seine Taten, dann wären wir, aus technischer Sicht, an diesem Punkt prinzipiell schon fertig. Wir würden das Level-Mesh austauschen, die Statue würde in Khorinis erscheinen und wir wären fertig. Die Statue hat keinerlei Funktionen, sondern würde eben „nur“ das Level-Mesh entsprechend ändern/austauschen. Jetzt stellen wir uns aber einmal vor, wir sind wieder bei  unserem Hütten-Beispiel. Diese wäre zwar nun, durch unsere gefundene Lösung, vorhanden, nachdem sie durch den Level-Change-Befehl realisiert worden ist und für den Spieler würde auch die Illusion entstehen, dass sie „gebaut“ worden ist, aber sie wäre völlig leer: Truhen, Betten, Türen, Alchemietisch und auch Items, können wir aber eigentlich nur im Spacer oder notfalls über die Cheatkonsole einfügen. Schade wäre es also, wenn wir zwar Hütten bauen könnten, diese aber nicht mir interagierbaren Objekten, Items, etc. befüllen könnten. Der Spieler hätte
dort nichts zu tun und der ganze Aufwand hätte sich nicht wirklich gelohnt. Schließlich braucht der Spieler zumindest ein Bett, das ihm gehört und in dem er schlafen kann, sowie
eine Truhe, in der er Gegenstände verstauen kann. Ein paar Dekorationen wären zudem schön, damit der Spieler sich in seinem virtuellen Heim auch wohlfüllt. Es wird also notwendig,
auch diesen Aspekt anzugehen.

Wie ihr nun diese Dinge genau realisieren können, zeige ich euch nun!

Die Lösung

Wichtig zu erwähnen wäre zunächst: Auch die hier vorgestellte Lösung ist keinesfalls optimal! Aber wie ihr im Abschnitt Die Probleme ja mitbekommen habt, hat jede andere Lösung immer irgendeinen Haken. Hätten die Entwickler  Vobs nicht regendurchlässig implementiert(oder zumindest eine
Option dafür bereitgestellt), wäre unser Leben als Modder erheblich einfacher. Aber sei es drum. Ich werd euch nun zeigen wie genau ihr vorgehen müsst, um Levelmeshes zu ändern und mit dynamischen Objekten zu befüllen.

Übrigens wurde durch meine anfängliche Unkenntnis einiges komplizierter als es notwendig gewesen wäre. Ich hab das natürlich für euch sofort angepasst und verbessert. Scheut euch also nicht, mir Verbesserungsvorschläge zukommen zu lassen 😉

1.) Die Planung

Es mag zunächst unwichtig oder zumindest offensichtlich erscheinen, das man, große Vorhaben, die man umsetzen möchte, planen muss, ABER: Ich empfehle euch immer zu planen, was genau ihr machen wollt, auch wenn das Vorhaben realtiv überschaubar ist(wie in diesem Fall) So wisst ihr schon im Vorfeld, wie genau ihr euer veränderbares Level aufbauen wollt. Natürlich könnt ihr hinterher immer noch Änderungen vornehmen und neue Features hinzufügen, aber besser gut geplant, als hinterher schlecht gefixt, nicht wahr?

Um das Ganze nicht zu komplziert zu machen, nehmen wir für unsere Umsetzung nicht das „Alte Lager“ von Gothic 1. Um das „Alte Lager“ für so ein Vorhaben zu nutzen, müssten einige zusätzliche Arbeiten gemacht werden, damit man das Lager wie gewünscht verwenden kann. Hier reicht es nicht, einfach nur die Levelmesh-Geometrie zu bearbeiten, das das „Alte Lager“ Teil der größeren, zusammenhängenden Oberwelt von Gothic 1 ist. Wir wollen uns diesen zusätzlichen Aufwand nicht antun, weshalb ich eine eigene, kleine Landschaft
modelliert habe, die ich für diese Demonstration genutzt habe. Die 3DS-Datei findet ihr, wie eingangs erwähnt, im Projekt-Portfolio. Nun legen wir fest, dass wir in diese Landschaft eine Hütte bauen lassen wollen, welche uns der Baumeister „baut“. Damit wissen wir praktisch schon grob alles, was wir umsetzen wollen(soll hier möglichst einfach gehalten sein). Wir haben also 2 Versionen der selbsterstellten Landschaft: eine „ursprüngliche Version“ und eine „veränderte Version“. Wie bereits erwähnt könnt ihr eine beliebige Anzahl an Versionen haben. Das ist dann sinnvoll, wenn ihr mit 2 Versionen nicht auskommt. Größere Änderungen z.B., die den Aufbau eines Lagers darstellen oder größere Veränderungen einer Landschaft, sollten besser mit mehreren Versionen realisiert werden, da dies die Glaubwürdigkeit erhöht. Außerdem hat der Spieler es so einfache sich in dem veränderten Level zurechtzufinden. Ich möchte in meinem Beispiel nur eine kleine Hütte bauen, daher begnüge ich mich mit 2 Versionen.

Abschließend überlegen wir uns noch, welche Objekte, Items und Möbel in der Hütte genau enthalten sein sollen. Ich füge der Hütte ein Bett, einen Schrank, ein Bücherregal und ein Bild hinzu. Das sollte zur Demonstration reichen. Man kann natürlich noch viel mehr hinzufügen, wie etwa aufhebare Items oder besagte Truhe, einen Alchemietisch, etc. etc.  Eurer Kreativität sind da nur wenige Grenzen gesetzt, aber ich möchte hier alles möglichst simpel halten, weswegen ich auf interagierbare Objekte verzichte.

Da wir jetzt wissen, was wir genau vorhaben, können wir uns an die Realisierung setzen.

2.) Erstellen der Levelmeshes

Zunächst müssen die Levelmeshes natürlich erstellt werden. Als erstes brauchen wir unsere erste Version(die ich mit V1 bezeichnen werde) und dann die selbe Mesh-Datei nochmal, nut mit dem Unterschied, dass wir dort unsere neue Hütte einfügen.(Diese Datei werde ich mit V2 bezeichnen)

Hier die von mir erstellte Landschaft, ohne Hütte:

In dieser Version(ich habe sie unkreativ levelchangemodV1.3DS genannt) ist das „Orginal„-Levelmesh. Als nächstes habe ich die V1-Datei kopiert und der Landschaft in V2  eine Hütte hinzugefügt:

Diese „veränderte Version“ habe ich „levelchangemodV2.3DS“ genannt. Gemacht habe ich das Ganze in Blender. Das Programm hat den Vorteil, dass es   kostenlos ist(im vergleich zu 3dsMax und Co.) und zudem gibt es ein Plugin, mit dem man Gothic-Meshes korrekt importieren und exportieren kann. Ihr könnt aber natürlich alles nutzen, was funktioniert, bzw. für das es ein solches Plugin gibt.

Nachdem wir nun die beiden Levelvarianten erstellt und erfolgreich exportiert haben, kann es weitergehen.

3.) Bearbeitung im Spacer

Nun da wir unsere 3D-Rohdaten haben, geht es ans Befüllen. Wir wollen die Landschaft mit einem einzigen NPC bevölkern. Diesen stelle ich vor ein Lagerfeuer, damit er nicht so wahlos in der Gegend herumsteht. Wichtig ist, dass ihr nicht den V1-Levelmesh nehmt, um eure ZEN-Datei zu befüllen, sondern V2! Das macht es einfacher, alle Objekte dort zu platzieren, wo ihr sie genau hinhaben wollt. Das erspart später lästiges Nachjustieren.
Außerdem erleichtert es uns nachfolgende Schritte. Nachdem ihr mit dem Befüllen fertig seid, könnt ihr einfach wieder die V1-Version auswählen und das Level erneut kompilieren. Aber eins nach dem anderen.

Die gute Nachricht ist: Wir müssen nur EINE ZEN-Datei mit den gewünschten Objekten befüllen. In allen anderen Versionen werden diese Dinge ja durch den Ladeprozess übernommen, also müssen wir, zum Glück, nicht mehrfache Arbeit machen.

Um den NPC einzubinden, brauchen wir einen sog. „Waypoint„, den ich direkt neben dem Lagerfeuer platziert habe. Außerdem habe ich noch 2 gebratene Schinkenkeulen(Items) platziert, einfach um ein wenig Atmosphäre zum Level hinzuzufügen. Das Ergebnis sieht in etwa so aus:

Da wir nun wissen, wo der NPC stehen wird, der das Haus bauen wird, können wir uns um die restlichen Dinge kümmern. Ich hab noch ein paar Bäume in der Landschaft und ein paar Pflanzen platziert. Der Vorteil daran ist, dass man so überprüfen kann, ob die Übertragung der Vobs und der Items, in das neue Level, funktioniert hat. Ebenso wichtig ist es, einen „zCVobStartpoint“ anzulegen, damit der Spieler irgendwo starten kann. Ich hab meinen Startpunkt in der Nähe des Lagerfeuers gemacht, damit man nicht zu lange laufen muss um mit dem NPC zu sprechen.

Der nächste Schritt wäre dann, das Haus mit Gegenständen zu befüllen. Um das zu tun, müssen wir allerdings etwas anders vorgehen, als bisher, da diese Einrichtungsgegenstände ja erst vorhanden sein sollen, wenn das Haus tatsächlich auch gebaut wurde. Daher müssen wir dafür sorgen, dass diese  Gegenstände initial noch nicht dort vorhanden sind und wir in der Lage sind, diese Gegenstände „erscheinen“ zu lassen, sobald wir sie brauchen. Dies muss skriptseitig möglich sein, da wir das Bauen der Hütte skriptseitig auslösen werden. Um das zu bewerkstelligen, benutzen wir ein Objekt mit dem Namen „zCMover„, diesen findet man im „Create„-Tab des Spacer, unter „TriggerBase(abstract) -> zCTrigger -> zCMover„.

Erstellt also im Spacer einen „zCMover“ und gebt ihm einen Namen(irgendwas passendes, denkt aber daran, dass ihr den Namen später fürs Skripten braucht!). z.B. „OBJECTS_NEW_HOUSE„. Danach könnt ihr ihn irgendwo positionieren, am besten in der Nähe eurer neuen Einrichtungsgegenstände(etwa im Dachgiebel der Hütte oder direkt über dem Haus). Es ist, an sich, eigentlich nicht wichtig, wo sich der „zCMover“ exakt befindet, es ist aber sehr zu empfehlen, ihn direkt in der Nähe eurer Objekte zu platzieren.
So habt ihr alles im Blick und könnt das Objekt bequem jederzeit anwählen und bewegen. Alle Vobs die ihr nun hinzufügen wollt, könnt ihr nicht einfach so platzieren, wir wir das mit dem Lagerfeuer und dem Waypoint gemacht haben. Stattdessen MÜSSEN alle Objekte, als sog. Child-Objekte, dem Mover untergeordnet werden. Das heißt, die Objekte „hängen“ an dem Mover, der hier als Parent-Objekt bezeichnet wird. Wie der Name des zCMovers schon andeutet, ist dies ein Objekt, dass eine Bewegung ausführen kann. Objekte die an diesem Mover „hängen“ führen diese Bewegung ebenfalls aus. So kann man z.B. ein Fallgitter realisieren, in dem man das Gitter an den Mover hängt und dann den Mover bewegt. Für uns ist das besonders wichtig, da wir nicht nur ein Objekt bewegen wollen, sondern mehrere. Ein Gebilde das aus einem Parent-Objekt und einem oder mehreren Child-Objekten besteht wird Vobtree genannt. Ihr könnt so viele verschiedene Vobtrees für unterschiedliche dynamische Spielobjekte anlegen wie ihr wollt. Ihr könnt auch mehrere Objekte an Child-Objekten anhängen, wenn ihr dies braucht.  Denkt immer nur daran, sie als Child des zCMovers anzuhängen!

Alle Einrichtungsgegenstände, die erst später in unserer neuen Hütte verfügbar sein sollen, müssen also als Child-Objekte dem zCMover-Objekt untergeordnet werden. Der Parent wird auch oft als „root“ bezeichnet. Der Mover wird später skriptseitig angesprochen, damit er dafür sorgt, dass wir unsere Vob-Objekte bequem „erscheinen“ lassen können.

Beim Erstellen unseres Vobtrees gehen wir nun wie folgt vor:

Wir wollen, das unserer neuen Hütte später sofort über Bett, Schrank, Bücherregal und ein paar Dekorationen verfügt, also gehen wir zu unserer neuen Hütte und erstellen, für jeden Einrichtungsgegenstand, ein „zCVob„-Objekt, in dem wir auf den zCMover mit der RECHTEN MAUSTASTE klicken. Im Popupmenü wählen wir den Menüpunkt „“, sodass das Vob-Objekt als Child an den Mover angehängt wird. Wenn dieser Menüpunkt nicht erscheint, habt ihr wahrscheinlich entweder aus Versehen das Parent-Objekt(unser zCMover) deselektiert oder an die falsche Stelle geklickt.Beachtet das es normalerweise nicht wichtig ist, wohin man im Spacer-Fenster klickt, wenn man ein Objekt anlegt. Wenn man Child-Objekte zu einem root-Objekt hinzufügt, muss man hingegen darauf achten, dass man das richtige Objekt anklickt. Das kann beim Spacer oft ein wenig hakelig sein. Seid also vorsichtig!

Haben wir alle zCVob-Objekte zum Mover hinzugefügt, weisen wir diesen Objekten noch ihre „visuals“ zu(also die 3D-Objekte, die das Aussehen der Objekte bestimmt).  Ich nehme z.B. „DT_BED_V1.3DS„(Bett), „NW_CITY_CUPBOARD_RICH_01.3DS„(Schrank) und „NW_CITY_BOOKSHELF_01.3DS„(Bücherregal). Ihr könnt
gerne soviele Gegenstände hinzufügen wie ihr wollt und euch richtig austoben, ich belass es der Einfachheit halber dabei. Nun bewegt ihr die neuen Objekte noch dort hin, wo sie später hin sollen(Bett in die Ecke, Schrank und Bücherregal an die Wand, etc.). Das Ergebnis sollte bei euch,in etwa, so aussehen:

Sobald ihr damit fertig seid, ändert ihr die Eigenschaften des Movers im „Modify…„-Tab folgendermaßen:

  • vobname: Beliebiger eindeutiger Name, z.B. „OBJECTS_NEW_HOUSE
  • visual: Beliebige 3DS-Datei, z.B. INVISIBLE_KEYFRAME.3DS (der Mover sollte späteren Spiel nicht zu sehen sein! Aber solche Hilfs-Objekte eignen sich gut dazu, damit man diese im Spacer zumindest sehen kann! Das erleichtern einem die Arbeit.)
  • reactToOnTrigger: TRUE
  • reactToOnTouch: FALSE
  • reactToOnDamage: FALSE
  • respondToObject: TRUE
  • moverBehaviour: 2STATE_TOGGLE

Habt ihr die Änderungen vorgenommen, vergesst nichr Apply zu drücken, um die Änderungen zu übernehmen!

Nun nochmal kurz zur Theorie, wie das Ganze funktionieren soll:

Ihr ja bereits, dass Mover „normalerweise“ dazu gedacht sind, Objekte zu bewegen, um z.B. Fallgitter herunterzulassen,
oder um fiese Stacheln aus dem Boden kommen zu lassen, etc.. Wir „missbrauchen“ die Funktionalität des Movers dafür, dass er uns ermöglicht die Objekte erst anzeigen zu lassen, wenn die neue Hütte gebaut wurde. Dazu verstecken wir den gesamten Vobtree mit Mover und allen Einrichtungsgegenständen einfach irgendwo, weit unter dem eigentlichen Level, an einer Stelle an dem der Spieler (normalerweise!) niemals hinkommen sollte, sofern er sich dort nicht mit Hilfe dem Marvin-Mode hincheatet oder durch einen Bug dort hingelangt. Dann, wenn wir die
Einrichtungsgegenstände brauchen, bewegen wir sie einfach an die richtige Stelle, sodass sie dann in der Spielwelt zugänglich sind.

Gut, nachdem wir nun auch den Mover richtig eingestellt haben, müssen wir dafür sorgen, dass die „Bewegung“, bzw. das Auftauchen korrekt funktioniert. Das geht ganz einfach: markiert den Mover(„OBJECTS_NEW_HOUSE„), drückt „M“ oder den Bewegen-Button in der vertikalen Toolbar des Spacers und bewegt den Mover nach unten, in den Boden.(Standardmäßig Taste „Y“) Da die Einrichtungsgegenstände alle Child-Objekte des Movers sind, bewegen sich diese mit. Das sollte zumindest so sein! Ist das bei euch nicht so, geht nochmal ein Schritt zurück und überprüft, ob ihr alle Objekte korrekt als Child
an den Mover angehängt habt. Sofern alles stimmt, bewegt den Mover + Objekte so tief, dass sie nicht mehr sichtbar sind. Sofern ihr in eurem Level unterirdische Tunnel oder dergleichen habt, achtet darauf, das die Objekte nicht aus den Wänden oder den Levelbegrenzungen herausragen oder derartiges.
Ansonsten könnten die Spieler auf diese Objekte stoßen, die sichtbarerweise nicht dort hingehören und würden es (zu Recht) für einen Bug oder einen  Design-Fehler halten. Und sowas wollen wir ja stehts vermeiden 🙂 

Zurück zu unserem Mover: Nun drückt ihr bei „Objectpages“ auf den Button „new keyframe“ dadurch wird der „0„-te Keyframe erzeugt. Da wir bei 0 anfangen zu zählen, ist das der erste Keyframe, also der Zustand wie er zu Beginn des Spiels, bzw. initial, beim erstmaligen Laden des Levels, vorhanden ist. Da unsere Hütte am Anfang noch nicht gebaut worden ist, wollen wir das genauso haben. Als nächstes bewegen wir den Mover+Objekte wieder nach oben, sodass die Objekte sich an der richtigen Stelle, in der Hütte, befinden und drücken dann erneut „new keyframe„. Der erste Keyframe ist nun so eingestellt das die Objekte auf dem richtigen Platz stehen. Nun ändert ihr am Mover unter „Modify…“ noch folgendes:

  • moveSpeed: 100
  • posLerpType: LINEAR
  • speedType: CONST

Das bewirkt, dass die „Bewegung“ des Movers innerhalb einer 100stel Sekunde ausgeführt wird. Er ist also sofort „da“. Normalerweise würde ein Mover sich mit einer „sichtbaren“ Geschwindigkeit bewegen, etwa wenn der Mover ein Fallgitter bewegen soll. Aber in unserem Fall sähe es seltsam aus, wenn die Objekte „aus dem Boden gefahren“ kämen. Es sei denn natürlich, das es für euch aus irgendeinem Grund zu eurem gewünschten Konzept passt, dann könnt ihr das natürlich anpassen und einen geringen Wert für moveSpeed wählen. Ich möchte das hingegen nicht, weshalb ich mich hier für diesen Weg entschieden habe.

In den Skripten von Gothic können wir den Mover nun „aktivieren“, sobald wir die Einrichtungsgegenstände benötigen. Das machen wir genauso wie alle anderen Trigger, in dem wir folgenden Befehl verwenden:

Wld_SendTrigger(„OBJECTS_NEWHOUSE„);

Diese Funktion sendet ein „Signal“ an den Mover, der dadurch aktiviert wird.Standardmäßig ist er so eingestellt, dass er dann beim 0-ten Keyframe beginnt und alle vorhandenen Keyframes durchläuft, bis der letzte Keyframe erreicht wurde. In unserem Fall gibt es nur 2 Keyframes(0 und 1). Diese werden also ausgeführt, sobald wird oben genannten Befehl ausführen. Wir können somit jederzeit dafür sorgen, dass unsere Objekte „auftauchen“. Praktisch, oder?

So, nachdem wir nun für ALLE veränderbaren Objekte Vobtrees gemacht haben(wir hatten hier nur einen, aber es kann durchaus
mehr geben, je nach dem was ihr machen wollt, z.B. mehr Häuser einbauen etc.) können wir fortfahren. Am Besten speichert ihr eure ZEN-Datei erstmal. Achtet dabei darauf, das ALLE Movern auf den Keyframe „0“ gestellt sind. Schaut dazu in dem  „Objectpages„-Fenster nach! Ansonsten werden diese nicht korrekt gespeichert(Danke an Sektenspinner für den Hinweis! Dieses Detail hat mir eine Menge Kopfschmerzen bereitet!)

Als nächstes bereiten wir unsere beiden ZEN-Dateien auf den Level-Change vor. Wir haben unsere aktuelle ZEN-Datei bearbeitet, haben aber unsere V2-Levelmesh-Datei gewählt. Das müssen wir jetzt wieder korrigieren. Dazu müssen wir lediglich, in unserer aktuellen ZEN-Datei, das Levelmesh austauschen. Klickt im Objekt-Browser auf den Eintrag „Level“, der sich ganz oben befindet. Sollte sich dieser nicht anwählen lassen, klickt zunächst irgendein anderes Objekt an, bevor ihr das Level-Objekt amnwählt. Der Spacer hat so seine Eigenheiten und diese ist eine davon. Im Object-Fenster im „Modify…„-Tab ändern wir den Eintrag „visual„, auf unsere V1-Version. Bei mir wäre das: „levelchangemodv1.3DS“. Wählt dazu die richtige Datei aus dem Ordner aus, in dem ihr die 3DS-Dateien gespeichert habt. Bei mir wäre das: „<Gothic2Verzeichnis>\_work\Data\Meshes\Level\levelchangemod\LEVELCHANGEMODV1.3DS“. Apply drücken nicht vergessen! Nun habt ihr das neue Levelmesh zugewiesen, aber es erscheint noch nicht. Ihr müsst zunächst aus der Menü-Leiste „World -> Compile World…“ anwählen und ausführen. Danach führt ihr noch „World -> Compile Light…“ aus, damit das Levelmesh aktualisiert wird und die LightMaps kompiliert werden. Ist das geschafft, speichert ihr die ZEN-Datei erneut ab. Ich nenne meine Datei ganz unkreativ „WORLD.ZEN„, denkt aber weiterhin daran, dass ALLE ZEN-Datei, die den Versionen entsprechen, den SELBEN Namen haben. Ich speichere die Datei im Unterordner „Kap1“ ab, damit klar ist, dass das die erste Version der WORLD.ZEN ist.

Nun benötigen wir noch die andere Level-Version(mehrere falls ihr mehr als 2 Varianten habt). Die Version der ZEN-Datei, die wir vorher bearbeitet haben,  habt ihr hoffentlich alle gespeichert(das wäre in meinem Fall die „WORLD.ZEN“ im Unterordner „Kap2„(analog zu dem was ich weiter oben beschrieben habe)). Diese öffnen wir jetzt. Da hier bereits das richtige Levelmesh existiert, brauchen wir hier nichts ändern. Stattdessen machen wir nun etwas drastisches:

Wir löschen alle Vobs, aus dieser Datei.

Dies erfordert eine Erklärung: Wir brauchen tatsächlich nur einmal alle Vobs in einer ZEN-Datei plazieren, da wie oben beschrieben, bei Wechsel des statischen  Teils des Levels alle Vobs übertragen werden, so als würden sie zur ZEN-Datei der ersten Version(V1) gehören. Da die „letze“ Version aber nicht bei Spielstart geladen werden soll(logisch!)  brauchen wir die Vobs darin nicht plazieren. Das sollte in der ERSTEN Version geschehen. Warum haben wir dann die letzte Version benutzt um all unsere Vobs zu plazieren? Ganz einfach: Wir wissen bei der ersten Version ja nicht WO genau unser Haus steht, wir können es zwar abschätzen, oder nachmessen, aber beim genauen
Plazieren der Objekte wird es dann schon schwieriger. Wo muss das Bett genau stehen? Ist das Bücherregal korrekt an die Wand gestellt? Steht der Schrank wirklich an der richtigen Stelle?etc. Würden wir die Positionen nur ungefähr schätzen, müssten wir ständig Nachbesserungen vornehmen, wenn etwas nicht am richtigen Platz steht  und das wäre mühseelig und unnötig fummelige Arbeit.

Darüber müssen wir uns aber zum Glück keine Gedanken machen: Dafür haben wir die letze Version benutzt. Wir haben diese auch benutzt um all unsere Mover und die daran hängenden Objekte, so zu programmieren, dass wir sie jederzeit zeigen/verstecken können.

Da die Erklärungen doch etwas unübersichtlich waren, hier nochmal was wir bis hierhin haben sollten:

  • eine ZEN-Datei mit allen Vobs, Movern, etc. (inklusive allem was erst in den anderen Versionen benötigt wird!), das Levelmesh ist die erste Version eures statischen Level-Anteils(also V1)
  • alle ZEN-Dateien, die aber NUR den statischen Teil enthalten(keine Vobs, NICHTS!), im Beispiel wäre das nur eine Datei(V2), aber es könnte eben auch 3, 4, 5 oder mehr sein!
  • Alle ZEN-Dateien MÜSSEN den selben Namen haben, also z.B. „WORLD.ZEN„, egal ob ihr 2 oder 5 Versionen habt! Sonst funktioniert es später nicht! Sie müssen sich aber in versch. Ordnern befinden.
  • Achtet auch darauf, nichts aus versehen zu überschreiben, da dies schnell passieren kann, wenn man die Dateien gleich benennt. Prüft alles am besten nochmal nach, bevor ihr weiter macht!

Als Alternative sei angemerkt, dass ihr nicht zwangsläufig die befüllte ZEN-Datei duplizieren müsst. Es würde reichen, eine neue ZEN-Datei anzulegen, dort das richtige Levelmesh auszuwählen, das Level zu kompilieren(World und Light!) und dann als „WORLD.ZEN“ in den richtigen Unterordner zu speichern. Ich habe das hier anders gemacht, da ich bereits 2 Versionen hatte und daher keine neue Datei angelegen wollte. Beide Wege sind aber absolut legitim.

So, damit wäre der Spacer-Abschnitt abgeschlossen, zumindest was die benötigte Funktionalität für unseren Hausbau angeht. Tatsächlich müssen noch einige Dinge hinzugefügt werden, wie z.B. Levelchange-Trigger und dergleichen. Da das aber stark von eurer Vorgehensweise abhängt und ich dieses Tutorial nicht unnötig aufblähen wollte, verzichte ich hier darauf, auch noch diese Dinge im Detail zu beschreiben. Wenn ihr ein funktionierendes Beispiel sehen wollt oder nicht weiterkommt, dann schaut euch gerne meine Demo-Mod an, die ich für dieses Tutorial gemacht habe! Dort könnt ihr euch im Detail ansehen, wie ich den Levelchange spacerseitig umgesetzt habe, wie die Objekte platziert wurden, wie der Vobtree aussieht, etc.

Nun kümmern wir uns abschließend um die skriptseitige Implementierung, um die letzten Funktionalitäten zu realisieren und unser Vorhaben abzuschließen.

4.) Skripten

Also machen wir uns ans Skripten. Wir müssen noch dafür sorgen, dass alles korrekt zusammengeführt wird. Wie genau diese Umsetzung aussieht, hängt davon ab, wann und wie und wo ihr den Levelwechsel auslösen wollt. In meinem Beispiel ist die Landschaft, die ich erstellt habe, eine eigene, abgeschlossene Umgebung. Wir sprechen dort einfach mit dem NPC „Gunther„(den manche vielleicht aus diversen Gothic-Tutorials kennen) der uns, nach einem kurzen Gespräch bittet, ihm beim Bau seiner Hütte zu helfen. Dies erfolgt, indem man einen Levelwechsel vollzieht.  Leider wirkt es in diesem Fall etwas komisch, wenn nach dem Dialog plötzlich ein Ladebalken erscheint, aber wir machen das der Einfachheit halber so. In einem „richtigen“ Einsatz, in einer Mod, empfiehlt es sich, ein wenig tricksen, denn es ist nicht möglich, die Änderung einfach so, von jetzt auf gleich, zu bewirken. Es ist mindestens ein
Level-Wechsel nötig. Möglich wäre es z.B. soetwas beim Wechsel von einer Höhle oder einem anderen Ort aus zu erledigen. Beispielsweise, wenn man z.B. im Orginal-Spiel Gothic 1 die „Alte Mine“ verlässt oder den „Orkfriedhof„.
Oder eben analog dazu, Level-Wechsel in Gothic 2: Wechsel zum Minental oder zum Addon-Abschnitt „Jharkendar„. Auch hier ist die Lösung wieder nicht 100% optimal, aber man kann mit etwas Umsicht und Kreativität, die Probleme relativ gut umgehen un diese Mechaniken vor dem Spieler verstecken. Eine gute Lösung wäre es z.B. diesen Level-Wechsel an die Hauptquest eurer Mod zu koppeln, sofern das inhaltlich passt. Wenn man z.B. etwas in einer Höhle erledigen muss, für die ein Levelwechsel erforderlich ist, und man die Aufgaben dort
erledigt hat und die Höhle wieder verlässt, könnte dann beim Levelwechsel zurück in die „Oberwelt“, die entsprechende
Änderung ausgeführt werden, wie z.B. das eine Hütte gebaut wird. Man muss sich der Beschränkungen immer im Klaren sein,
dann findet man auch oft genug kreative Lösungen, um diese Beschränkungen zu umgehen.

Kommen wir aber zurück zu den skriptseitigen Anpassungen, die wir benötigen um den Hüttenbau zu realisieren. Wie ich es im Spacer-Abschnitt schon beschrieben habe, muss man einen Trigger auslösen, um die Änderungen skriptseitig hervorzurufen. Dafür gibt es eine Funktion, die für diesen Zweck geschaffen worden ist:

Wld_SendTrigger(„<Name des Triggers>“);

Wenn ihr also nun wollt, dass eure Hütte gebaut wird, dann müsst ihr, wie gesagt, zunächst erstmal den Levelchange vollführen. Anschließend müsst ihr dann euren „OBJECTS_NEW_HOUSE„-Mover über diese Funktion aktivieren, damit in eurer Hütte auch schon alles vorhanden ist 😉

Das geht am besten, indem ihr einen sog. „Flag“ deklariert, der anzeigt, ob das Haus gebaut wurde oder nicht. Ich habe die Variable ganz zweckmäßig „hausGebaut“ genannt. Damit diese Variable in Dialogen und anderen Skripten verfügbar ist, müsst ihr diese zunächst deklarieren, dass passiert am besten in der Skript-Datei „Story_Globals.d“, welche ihr unter folgendem Pfad findet:

<Gothic2Verzeichnis>\_work\Data\Scripts\Content\Story

Dort macht ihr nun irgendwo einen Eintrag, um eure Variable zu deklarieren. Ich habe ganz unten, in der Datei, folgende Zeile hinzugefügt:

var int hausGebaut;

Beachtet bitte, dass man Flags normalerweise über ein Boolean realisiert. Diese gibt es in Daedalus-Skript aber nicht, weshalb wir uns mit einem Integer begnügen.

Als nächstes müssen wir diese Variable abfragen und vor allem müssen wir uns überlegen, WO diese Abfrage stattfindet. Ich fand es am sinnvollsten, dies in der „Startup.d“ zu tun, die sich im selben Ordner wie die „Story_Globals.d“ befindet. In dieser Datei sind die Startup-Funktionen untergebracht, die beim starten/laden eines Levels ausgeführt werden. Somit sind auch alle Funktionen des Hauptspiels dort vertreten. Es gibt 2 Funktionen, die automatisch aufgerufen werden. Diese sind:

FUNC VOID STARTUP_<LEVELNAME> ()

FUNC VOID INIT_<LEVELNAME> ()

Wobei „<LEVELNAME>“ nur ein Platzhalter ist. Dort muss der Name der ZEN-Datei stehen! Ohne die Dateiendung natürlich. In meinem Fall heißt meine ZEN-Datei „WORLD„, meine Startup- und Init-Funktionen sehen also so aus:

FUNC VOID STARTUP_WORLD()

FUNC VOID INIT_WORLD()

Diese beide Funktionen, sofern sie in der „Startup.d“ definiert sind, werden automatisch aufgerufen. die Startup-Funktion wird nur EINMAL beim ersten betreten des Levels aufgerufen(z.B. bei NewGame), während die Init-Funktion jedesmal aufgerufen wird. Das ist also wie geschaffen für unsere Zwecke. Wir wollen sicherstellen, dass beim Laden eines Levels, der Mover aktiv ist(unsere Einrichtungsgegenstände also vorhanden sind), sobald das Haus gebaut wurde, also fügen wir eine Init-Funktion für unser neues Level hinzu und fragen ab, ob das Haus schon gebaut wurde. Wenn ja, dann soll der Mover aktiv sein. Das Ganze sähe etwa so aus:

FUNC VOID INIT_WORLD()
{
      B_InitMonsterAttitudes ();
      B_InitGuildAttitudes();
      B_InitNpcGlobals ();

      if(hausGebaut == TRUE)
      {   
            //Einrichtungsgegenstände werden hinzugefügt
           Wld_SendTrigger(„OBJECTS_NEW_HOUSE“);
       };
};

Die Funktione, die mit einem „B_“ sind Standard-Funktionen, wie sie auch in allen anderen Init-Funktionen aufgerufen werden, weshalb wir sie übernehmen. Dann folgt unsere IF-Abfrage, sofern „hausGebaut“ gleich „TRUE“ ist, wird der Trigger aktiviert. Damit haben wir diesen Teil bereits umgesetzt.

Als letztes bleibt uns eigentlich nur noch, den Flag zu setzen, sowie den Levelchange auszulösen. Das wollen wir, in unserem Beispiel genau dann tun, wenn das Haus gebaut wird. Wie bereits gesagt, passiert das in diesem Fall, durch den Dialog mit dem NPCGunther„. Das heißt: Skriptseitig müssen wir also noch den Flag setzen. Ich habe das in der Dialog-Funktion von „Gunther“, so gelöst:

//Levelchange-Dialog
func void DIA_Gunther_Levelchange_info ()
{

    //…   

   AI_StopProcessInfos (self);

   //Flag setzen
   hausGebaut = TRUE;
};

Ich habe den eigentlichen Dialog hier rausgenommen, damit die Funktion nicht unnötig groß erscheint. Die Dialogzeilen haben keinen Einfluss auf die Funktionalität. Danach wird, standardmäßig mit „AI_StopProcessInfos(self)„, der Dialog mit Gunther beendet. Tun wir dies nicht, oder an der falschen Stelle, kann es zu diversen Bugs kommen. z.B. das sich der Dialog nicht korrekt beendet und wir die Kontrolle über die Spielfigur nicht zurückerlangen.  Daher müssen wir den Dialog erstmal sauber beenden. Am Schluss setzen wir dann unseren Flag. Damit wären wir hier auch schon fertig.

Nun zu der Frage, wie der Levelchange ausgelöst wird. Das war bei der Umsetzung der Demo-Mod etwas kompliziert, weshalb ich diesen Teil aus dem Tutorial rausgenommen habe. Tatsächlich hat er nichts mit dem Thema „dynamische Levelmeshes“ zu tun. Tatsächlich ist es so, dass man skriptseitig keinen Levelchange auslösen kann. Das erfordert dann einen Umweg. Levelchanges werden mit einem Objekt im Spacer ausgelöst. Dieser wird z.B. vor einem Höhleneingang platziert und sobald der Spieler diesen Trigger berührt, wird ein Levelchange ausgelöst. Aufgrund dieser Beschränkung, lässt sich der Levelchange nicht ganz so einfach, nach einem Dialog, auslösen. Ich habe daher wieder eine relativ bastelintensive Lösung gefunden(auch hier wieder der Dank an das Editing-Forum!) um dies dennoch so zu realisieren, wie ich mir das vorgestellt habe. Wenn es euch interessiert, schaut euch die Lösung in der Demo-Mod an.

Generell funktioniert das Ganze so, dass der Levelchange-Trigger mit einem eigenen Mover nach unten bewegt wird, sobald der Dialog fertig ist. Das führt dazu, dass der Levelchange durch die Bewegung des Movers ausgeführt wird, sodass der Spieler nichts tun muss. Zusätzlich musste ich diese Mover-Bewegung korrekt timen, sodass ich 2 Dialoge mit Gunther geskriptet habe, der 2. hat allerdings keine Dialogzeilen, sondern ist lediglich dazu da um den Mover auszulösen und den Levelchange durchzuführen.

 

5.) Abschluss

Mit unseren dynamischen Levelmeshes sind wir nun endlich fertig! Wir haben es geschafft! Hier ein Screenshot aus der Demo-Mod nachdem die Hütte gebaut wurde:

Abschließend bleibt anzumerken, dass die hier gezeigte Technik, sehr bastelintensiv ist. Aber dafür haben wir nun endlich was wir wollen: Eine Hütte, durch die es nicht durchregnet und Einrichtungsgegenstände, die erst erscheinen, wenn der Spieler bestimmte Aktionen vollführt hat.

Ein paar Denkanstöße möchte ich euch aber noch mit auf den Weg geben:

Überlegt euch gut, ob ihr für die Lösung Speicherplatz verschwenden wollt und vor allem „wie viel“. Mit einem Mover und einem Vob lassen sich Häuser viel eleganter hinzufügen, allerdings regnet es dann durch die Häuser und die Hütten wirken u.U. nicht so als wären sie wirklich Teil der Level-Geometrie. Letzteres lässt sich ggf. aber durch diverse Anpassungen ausbessern.

Auf der anderen Seite kann meine Lösung sehr schnell unverhältnismäßig speicherintensiv werden!

Für das „Alte Lager“ z.B. ist die 3DS-Datei mit 611 KB sehr klein, allerdings verbraucht die ZEN-Datei im Orginalzustand ganze 6,13 MB.
Dazu kommen dann nochmal alle neuen Levelmesh-Varianten mit rund 611 KB pro Variante + ZEN-Datei für jede Variante, die dann aber zum Glück leer sind. Trotzdem kann dort schnell einiges dazukommen. Das ist natürlich in Zeiten von Terrabyte-Festplatten und schnellen Internetverbindungen jenseits der „5 MB/s„-Marke, kein wirkliches Thema mehr, aber ihr solltet euch trotzdem dessen bewusst sein. Wir verschwenden hier einiges Speicher einfach weil wir die selbe Datei 2 mal haben + ein paar kleinen Änderungen. Überlegt euch also trotzdem immer, ob sich das wirklich lohnt!

Wovon ich abraten würde, ist diese Lösung für sehr kleine Dinge oder minimale Änderungen einzusetzen. Zum einen, weil
der Aufwand ziemlich groß ist und zum anderen, weil sie sehr fehleranfällig sein kann. Es erfordert eine Menge Umsicht und
Vorausplanung, damit nicht später Bugs auftreten oder bestimmte Areale nicht korrekt befüllt werden. Auch Beleuchtung ist hier ein Thema, auch wenn diese ja durch die neue ZEN übernommen wird. Dennoch muss man hier aufpassen, dass man keine optisch sichtbaren Beleuchtungsfehler erzeugt. Ich denke nicht, dass das ein sonderlich großes Problem ist, solange man das Ganze in Maßen einsetzt. Wenn man aber für jede kleine Veränderungen 10-20 ZENs erzeugt, kann der
Speicherverbrauch schnell anwachsen, eure Download-Dateien unnötig groß machen und obendrein wird eurer „Modding-Alltag“ deutlich erschwert.

Dieses Thema führt auch zum letzen Punkt: Auch wenn die Möglichkeiten nahezu grenzenlos sind, versucht
euch auf das wesentliche zu konzentrieren! Wenn ihr z.B. den Eingang zur alten Mine einstürzen lassen wollt, sieht das bestimmt eindrucksvoll aus, wenn beim nächsten Besuch, ein großer Haufen Geröll davor liegt, oder der Eingang eingestürzt ist, oder dergleichen, aber ein Mover der einfach ein Gitter vor den Eingang schiebt, hat für die Entwickler des Orginal-Spiels ja auch ausgereicht und uns als Spieler doch auch, oder nicht? 😉
Also wenn, dann versucht nur wirklich große Änderungen zu machen. Lasst Dörfer zerstören, lasst Lager wiederauferstehen, oder zeigt die Entwicklung eines kleinen Fischerdörfchens zu einer Metropole, aber kopiert nicht für einen kleinen Steinhaufen, der neu hinzukommt, die ganze Surface.ZEN!
Ich und alle die euren Mod runterladen wollen, werden euch dafür dankbar sein ;D

So kommen wir zum Ende:

Ich bedanke mich bei der Seite World of Gothic, dem Editing-Forum für ihre schnelle und kompetente Hilfe und speziell bei User Sektenspinner,  der den Anstoss für dieses Tutorial gab.

Falls euch die Erklärungen in meinem Tutorial etwas zu allgemein waren oder ihr bestimmte Schritte nicht nachvollziehen könnt,  dann schaut euch, wie schon erwähnt, meine Demo-Mod im Projekt-Portfolio an: Klick mich. Dort findet ihr die fertige Demo-Mod, die alle Punkte beinhalten, die wir hier besprochen haben und die ihr gerne als Grundlage für eure eigenen Mods nutzen könnt.

Wenn ihr Lob, Kritik oder Verbesserungsvorschläge habt, könnt ihr mir gerne per Mail oder über das Kontakt-Formular schicken! Kommentare könnt ihr zudem unter dem Artikel hinterlassen.

Ich antworte auch gern auf andere Probleme, sofern ich euch weiterhelfen kann.

So, dann bleibt mir nicht mehr viel zu sagen, außer: Viel Spaß beim Modden! 🙂

Orginal-Tutorial von 2010

Überarbeitete Fassung: 23.02.2018