Projekt Questmod: Shadows of Indoril

Rung

Abenteurer
Shadows of Indoril Pitch GER.jpg


"Shadows of Indoril" ist eine Gilden-Questmod für Morrowind,
in der ihr Ordinator werden könnt.

Ihr braucht zum Spielen Tribunal, Bloodmoon und OAAB.
Die Mod läuft in Vanilla und in OpenMW (beides wurde getestet).

Sie wird auf Deutsch und Englisch erscheinen und zum Teil vertont sein.

Ziel ist es, eine Questlinie für die Ordinatoren zu bieten, die sich nahtlos in das Hauptspiel einfügt.
Das bedeutet Queststruktur, Spieldauer und Konsequenzen orientieren sich an den Gilden des Hauptspiels.

Shadows of Indoril 02.png

Ich habe versucht, so kompatibel wie möglich zu sein,
allerdings gibt es an einigen Stellen sicher die eine oder andere Mod,
mit der es Überschneidungen geben könnte.

Die Arbeiten an der Mod sind weit fortgeschritten.
Es fehlen noch die Testung, Übersetzung ins Englische und Teile der Vertonung.

Der Thread hier ist ein kleines Experiment.
Ich wollte mal schauen, ob es in Germany überhaupt noch Interesse an Content für Morrowind gibt.

Liebe Grüße, Euer Rung​
 
  • Like
Reaktionen: Licht
Spannend! Das schaue ich mir sicher mal an, sobald es fertig ist. Allerdings spiele ich Morrowind eigentlich gar nicht mehr und mache selbst auch nur noch eine Mod dafür.

Ist die Vertonung so geplant wie im Grundspiel, also Voice:Hello/Fight/Idle/... und im aktiven Gameplay über den Say-Befehl oder sollen Dialoge in der Textbox vertont sein? Da würde mich die konkrete Umsetzung ohne lua sehr interessieren. Alles, was ich mir dafür bislang überlegt habe, läuft nämlich auf großen Aufwand mit vielen Skripten hinaus. Die einzige elegante Lösung, die ich kenne, braucht ein MWSE-lua-Framework.
 
Ich hätte nie gedacht, dass noch eine größere deutsche Questmod und dazu noch mit OAAB von einem altbekannten Modder erscheint. Da werde ich wieder Morrowind installieren.
 
Huhu ihr beiden. 🙂

@Krschkr

Also, zur Vertonung. Die wird nicht vollständig sein, sondern nur teilweise.
Momentan ist die Vertonung zu einem Event drin, die ist über den erwähnten Say-Befehl realisiert und läuft sehr kontrolliert ab. Ich wollte erstmal schauen, ob da überhaupt etwas geht. Wie der Rest der Vertonung aussieht, entscheide ich noch. Ich dachte, das kann man vielleicht über Globals und Say im Menü regeln? Habe ich noch nicht probiert, war nur eine Idee.

@Licht

Das freut mich aber sehr. OAAB ist wohl gar nicht so verbeitet, wie ich angenommen habe? Ich finde das Konzept großartig und würde es mir so auch für Oblivion wünschen.
 
Ah, es ist schon eine Weile her, seit ich mit Vertonung experimentiert habe. Aus der Erinnerung:
  • Say funktioniert nur außerhalb von MenuMode überhaupt. SayDone müsste man prüfen. Wahrscheinlich liegt das daran, weil der Befehl dem Animationssystem interagiert. Für Szenen nutzbar, in der Dialogbox nicht.
  • Für die Dialogbox bräuchtest du einen der PlaySound-Befehle und müsstest die Voicelines statt wie üblich in Vo/ als mp3 in einem anderen Ordner als wav ablegen. Das dann als Sound registrieren und per Skriptbefehl ansteuern.
  • Problem: PlaySound macht sein Ding. Einmal gestartet läuft die Datei durch. Du beendest den Dialog? Der Ton geht weiter. Du gehst zur nächsten Antwort? Jetzt spielen zwei Dialoge gleichzeitig. Du entfernst dich vom NPC? Er spricht direkt in deinen Schädel. Du kommst dem NPC zu nahe? Er wird dich begrüßen, während sein Dialog noch durchläuft. Spontaner Herzinfarkt? Das hält diesen NPC nicht auf, seinen letzten Dialog in deinem Kopf ausklingen zu lassen.
Ich habe mir für dieses Problem einen Workaround überlegt, aber mich lieber gegen Vertonung entschieden, als das durchzuziehen. (Ich habe extrem viele Dialoge, das war einfach nicht umsetzbar.) Die Idee sieht wie folgt aus:
  • Zunächst mal jeden vertonten Dialog wie oben beschrieben als Sound registrieren.
  • Statt PlaySound nutzen wir den Befehl PlayLoopSound. (Für direktionalen Ton kannst du stattdessen PlayLoopSound3D auf den sprechenden NPC anwenden, aber dann wird der Ton entsprechend leiser und ist mit Pech nur auf einem Ohr. Ton ist in Morrowind ziemlich grob umgesetzt.)
  • Im Skript arbeitest du mit states und lässt einen Timer laufen. Wenn der Timer die Länge des vertonten Dialogs erreicht hat, schickst du den StopSound-Befehl (der nur mit PlayLoopSound und nicht mit PlaySound funktioniert!) und beendest das Skript.
  • Für MenuMode == 0 implementieren, dass StopSound sofort ausgelöst wird. Gespräch ist beendet, NPC soll aufhören, zu reden.
Jetzt wird es aber komplizierter. Die meisten Dialoge bestehen nicht nur aus einer Antwort, sondern gehen über mehrere. Schlimmstenfalls über verschiedene Topics hinweg. Wir brauchen also eine lokale Variable auf NPCs, deren Skript wir kontrollieren, oder eine globale Variable für NPCs, die wir aus Kompatibilitätsgründen nicht mit einem (neuen) Skript versehen.
  • Weitere Ausnahme hinzufügen: Wenn "NPC-ID".LocalVariable oder die gesetzte globale Variable einen bestimmten Wert erreicht wird StopSound ausgelöst und das Skript beendet.
  • Diese Variable können wir in der Resultbox vor dem Start des nächsten Vertonungsskripts setzen.
  • Der Einfachheit halber würde ich für jeden NPC genau eine Variable nutzen, die ALLE Vertonungsskripte killt und für jede vertonte Antwort ein eigenes Skript nutzen. Das werden viele Skripte, aber dafür hat man kein Megaskript, das sofort unübersichtlich und zum Debug-Albtraum wird.
  • [EDIT: Nachtrag. Ich denke, die eleganteste Lösung ist tatsächlich, eine globale Variable zu nutzen, die dann in absolut jedem Skript genutzt wird und für jeden NPC gleich ist. Warum mehrere Variablen, wenn man dank Dialogbox eh immer nur eine gleichzeitig abfragen muss? Dann müssen wir auch keine lokalen Skripte anrühren.]
  • Sicherheitshalber sollten die Vertonungsskripte erst mal drei Frames hochzählen, bevor sie zu tönen anfangen, damit das vorige Skript sauber ausläuft. Dann können wir das Frame-Zählen auch direkt zum pauschalen Zurücksetzen dieser Variable nutzen.
  • Das sollte alle Standard-Probleme einfangen. Außer, der NPC hat noch eine offene Voiceline, weil er gegrüßt hat, bevor man ihn angesprochen hat. Da müsste man prüfen, ob wenigstens SayDone im MenuMode funktioniert. Dann könnte man unten im Skript noch ein If ( SayDone == 0 ) return vor den Framecounter setzen. Dann würde erst die Begrüßung durchlaufen und dann der Dialog abspielen. Aber wie gesagt: Erst testen, ob SayDone im MenuMode feuert.

Die Implementierung dieses Ansatzes sähe dann in etwa so aus. (Und wie gesagt, ich habe das nicht wirklich getestet. Das ist ein Theorycraft!)

Auf Dialog-Ebene:
Code:
(ID = kr_tn_NPC_MG1_nimar
Choice = 44
PCRace = 3)
*Ihr lasst die Welt um Euch herum verstummen und lauscht in Euch hinein, um Eure Ahnen um Beistand zu bitten. Zwar habt Ihr Euch nie besonders darin hervorgetan, den Fersenknochen Eurer Großtante zu pflegen und zu ehren, doch in diesem Moment sind Eure Familienbande stark genug, dass sie Nimar Tyravels Hieb an Euch vorbeigleiten lässt. Dankbar umarmt Ihr die Seele Eurer Großtante und kehrt aus der Meditation zurück in die physische Welt. Euch eröffnet sich eine Gelegenheit, zum Gegenangriff anzusetzen.*
[Set "kr_tn_NPC_MG1_nimar".RemoteShutUp to 1
StartScript kr_tn_sc_MG1_VA_G5_44_a
Choice, "*Gebt Nimar eine Kopfnuss.*", 28,
Choice, "*Zielt auf die Magengrube.*", 29,
Choice, "*Tretet nach dem Schienbein.*", 30]

Auf Skript-Ebene:
Code:
begin kr_tn_sc_MG1_VA_G5_44_a

short state
float timer

;kr_tn_so_MG1_VA_G5_44_a ist die ID, unter der wir die Vertonung dieses Dialogs registriert haben.
;kr_tn_NPC_MG1_nimar ist ein NPC aus unserer Mod, dessen Skript wir kontrollieren. In seinem lokalen Skript weisen wir ein 'short RemoteShutUp' aus. Das Remote hilft, später zu erinnern, dass diese Variable von einem externen Skript benötigt wird und wir sie nicht löschen dürfen, obwohl sie im Skript selbst gar nicht genutzt wird.
;EDIT Nachtrag: Besser eine globale Variable nutzen, die dann für absolut jeden NPC und jeden Dialog exakt gleich genutzt wird. Ich belasse die Lösung mit der lokalen Variable jetzt aber im Beispielskript.
;Da es viele dieser Skripte und Tondateien geben muss ist es wahrscheinlich sinnvoll, sich ein klares Schema zu überlegen, nach dem die Dialoge und Antworten mit einer ID versehen werden. Im Beispiel nutze ich zunächst mein Standard-Präfix von Autor_Modifikation_Entitätskürzel_Quest-Kontext_IDENTIFIER. Indem wir den Identifier für Skript und registrierten Sound gleich halten, können keine Verwechslungen auftreten, welcher Sound in welchem Skript abzuspielen ist. Interessant ist eher, wie der Identifier aufgebaut werden soll. Ich habe hier G5 für Greeting in Hierarchie-Ebene 5 genommen, 44 für die Choice und das Suffix _a, um die Variante von Choice 44 zu bezeichnen. Je nach zutreffenden Filtern wäre die Antwort auf Choice 44 nämlich eine andere.

if ( state == -1 )
    StopSound "kr_tn_so_MG1_VA_G5_44_a"
    StopScript kr_tn_sc_MG1_VA_G5_44_a
    return
endif

if ( MenuMode == 0 )
    set state to -1
    return
endif

if ( state == 4 )
    if ( "kr_tn_NPC_MG1_nimar".RemoteShutUp == 1 )
        set state to -1
        return
    endif

;Timer an die Länge der Datei anpassen. Eine Sekunde Stille am Dateiende macht es einfacher, einen versehentlichen hörbaren Loop zu vermeiden.
    set timer to ( timer + GetSecondsPassed )
    if ( timer >= 27.8 )
        set state to -1
        return
    endif
    return    

elseif ( state == 3 )
    Set "kr_tn_NPC_MG1_nimar".RemoteShutUp to 0
    PlayLoopSound "kr_tn_so_MG1_VA_G5_44_a"
    set state to 4
    return

else
;drei Frames Puffer, damit das vorherige Skript den vorangegangenen Dialog sauber abbrechen kann.
    Set state to ( state + 1 )
endif

end kr_tn_sc_MG1_VA_G5_44_a

Das ist alles sehr friemelig. Deshalb habe ich nachgefragt, hätte ja sein können, dass du eine bessere Idee hast. MWSE-Mods können das Framework von Voices of Vvardenfell nutzen. Dann muss man nur die Dateien im richtigen Ordner mit dem richtigen Namen ablegen und der Rest läuft von selbst. OpenMW hat inzwischen vielleicht ein ähnliches Tool. Aber ich als hartgesottener MWScript-Nutzer kenne nur Workarounds wie den da oben. 😀

@Licht Kann nicht versprechen, dass ich damit allzu bald fertig werde, aber von mir kommt auch noch eine unkleine deutschsprachige Questmod. Die ist dann allerdings nicht von einem namhaften Modder, sondern nur von mir.