Oblivion:Scripting allgemein
Inhaltsverzeichnis
Scripting-Basiswissen
Du hast wahrscheinlich schon bemerkt, dass alle Objekte ein Feld für Scripts haben. Scripts sind kleine Programme, die innerhalb von Objekten platziert werden können, um eine spezielle Aktion auszuführen.
Scripts können in zwei Grund-Kategorien unterteilt werden: Referenz-Scripts und Nicht-Referenz-Scripts. Wie du sicherlich schon erraten kannst, sind Referenz-Scripts Scripts, die in Referenz-Scripts laufen, aber auch in Dialog-Ergebnissen. Referenz-Scripts können Referenz-Funktionen benutzen ohne die Referenz, auf welcher die Funktion läuft, zu spezifizieren. Es ist dann so, dass die Funktion an der Referenz läuft, der das Script angehängt ist. Nicht-Referenz-Scripts (Quest-Scripts, Quest-Stage-Ergebnisse) müssen dagegen die Referenz spezifizieren, wenn sie eine Referenz-Funktion benutzen.
Eine andere Art Scripts zu kategorisieren wäre, sie in benannte Scripts und in Ergebnis-Scripts zu unterteilen (Named Scripts und Results Scripts). Benannte Scripts sind volle Scripts, die an Objekte, Quests oder Magischen Effekte gehängt werden und Variablen und "BEGIN/END"-Blöcke enthalten können. Ergebnis-Scripts sind Script-Fragmente, die an Dialoge und Quest-Stages gehängt werden.
Wann und wie oft Scripts ausgeführt werden, hängt davon ab, an was das Script gehängt wurde: Scripts, die an Objekte gehängt werden, werden nur ausgeführt, wenn der Spieler in der Nähe ist. Quest-Scripts werden fortlaufend ausgeführt, sobald die Quest gestartet wurde.
Referenz-Scripts
Referenz-Scripts sind Scripts, die den Referenz-Schriftsatz mit Referenz-Funktionen benutzen können, weil sie an Objekt-Referenzen angehängt sind oder auf Objekte-Referenzen angewendet werden:
- Scripts, die an Objekte angehängt sind
- Dialog-Ergebnis-Scripts
Referenz-Funktionen
Viele Script-Funktionen sind Referenz-Funktionen. Das bedeutet auch, dass sie auf eine Objekt-Referenz Referenz-Fenster ausgeführt werden müssen. Referenz-Scripts (Objekt Scripts und Dialog-Ergebnis-Scripts) können auch eine Referenz-Syntax beinhalten.
Als Beispiel:
<tesscript>GetDisposition player</tesscript>
GetDisposition ist eine Referenz-Funktion - Doch wessen Disposition? In diesem Fall, wenn wir eine Referenz noch nicht spezifiziert haben, sollten wir lieber schreiben:
<tesscript>thisReference.GetDisposition player</tesscript>
Du kannst immer eine ausdrückliche Referenz-Syntax benutzen, also immer ausdrücklich die Referenz angeben, auf der die Funktion läuft. Nicht-Referenze-Scripts müssen dagegen die Referenz-Syntax immer mit angeben, wenn sie nicht an eine Objekt-Referenz gebunden sind. Als Beispiel:
<tesscript>JauffreRef.GetDisposition player</tesscript>
Hier fragen wir nach Jauffreys Disposition zu dem Spieler. Diese Syntax kann in jedem Script genutzt werden, weil wir die Funktions-Referenz mit angegeben haben.
HINWEIS: Du kannst auch Referenz-Funktionen auf Referenz-Variablen ausführen, so als wären sie das Objekt selber.
Referenz-Variablen
Genau wie alle anderen Variablen, müssen auch Referenz-Variablen zunächst deklariert werden, bevor sie genutzt werden können:
<tesscript>ref refVarName</tesscript>
Du kannst eine Referenz-Variable überall benutzen, wo du auch eine Objekt-Referenz benutzen kannst. Uninitialisierte Referenz-Variablen werden dabei an das gescriptete Objekt selbst zurückgeführt. Ansonsten agieren Referenz-Variablen genauso wie jede andere Referenz.
Eine Referenz-Variable, deren Objekt nicht im Speicher ist (wie ein Static-Objekt, dessen Zelle vom Spieler verlassen wurde), wird als uninitialisiert behandelt.
Man setzt Referenz-Variablen, indem man der SET-Befehl benutzt, genau wie bei anderen Variablen. In dem meisten Fällen benutzt man die Referenz-Variable, die den Wert der FormID zurückgibt. Als Beispiel:
<tesscript>set myRef to GetContainer</tesscript>
Genau wie andere Variablen kannst du auch eine Referenz-Variable auf ein anderes gesriptetes Objekt setzen:
<tesscript>set BobRef.myRef to GetSelf</tesscript>
Um zu prüfen ob eine Referenz-Variable ungesetzt ist:
<tesscript>if myReferenceVariable == 0</tesscript>
Um zu prüfen ob eine Referenz-Variable gesetzt ist:
<tesscript>if myReferenceVariable != 0</tesscript>
Um zu prüfen, ob die Referenz-Variable eine andere Referenz ist (in diesem Fall der Spieler):
<tesscript>if myReferenceVariable == player</tesscript>
Oder eben keine andere Referenz:
<tesscript>if myReferenceVariable != player</tesscript>
Als Beispiel:
<tesscript>scn TheMastersSword ; Whoever equips it gets +50 to blade
ref UserRef
begin OnEquip
set UserRef to GetContainer
UserRef.Modactorvalue blade 50
end
begin OnUnEquip
set UserRef to GetContainer
UserRef.Modactorvalue blade -50
end</tesscript>
Nicht-Referenz-Scripts
Nicht Referenz-Scripts sind Scripts, die eine ausdrückliche Referenz-Syntax mit Referenz-Funktionen benutzen müssen, weil sie nicht an Objekt-Referenzen angehängt sind oder an Objekt-Referenzen angewendet werden:
- Quest Scripts - Diese werden im Editor-Fenster mit der Dropdown-Liste spezifiziert.
- "Quest Stage Ergebnis"-Scripts
Benannte Scripts
Benannte Scripts werden mit dem Script-Editor-Fenster erstellt. Es muss ihnen ein Name mit dem ScriptName-Befehl gegeben werden (z.B. indem in der ersten Reihe des Scripts "ScriptName AlawenScript" steht) und können alle Möglichkeiten der TES-Script-Sprache benutzen.
Benannten Scripts können an Objekte, Quests oder Magischen Effekt angehängt werden. Wenn ein gescriptetes Objekt in der Welt platziert wird (also eine neue Objekt-Referenz erstellt wurde), bekommt dieses Objekt seine eigene Kopie der Variablen des angehängten Scripts. Auf diese Weise kann ein einzelnes Script den Zustand mehrerer Objekt-Referenzen steuern.
Es gibt drei Arten von benannten Scripts:
Objekt Scripts
Object Scripts sind Scripts, die zu einem Object gehören. Es sind immer Reference Scripts. Sie können jede Funktion bis auf die besonderen Magic_Effect_Script-Kommandos nutzen.
Quest Scripts
Quest-Scripts können erstellt werden, indem im Script-Editor als Script-Type 'Quest' ausgewählt wird. Scripts müssen als Quest-Scripts bezeichnet werden, um an Quests angefügt werden zu können. Quest-Scripts sind Non-Reference-Scripts und deswegen in ihrer Syntax etwas beschränkt.
Grundlegende Fakten
- Quest Scripts werden nur ausgeführt, wenn die auch die Quest läuft (das lässt sich im Spiel mit "sqv QUEST_NAME" herausfinden). Quests können mit den Befehlen StartQuest und StopQuest gestartet und angehalten werden. Beachte dabei, dass dies unabhängig davon ist, ob eine Quest grade läuft oder nicht. Eine Quest fertigzustellen bedeutet, dass sie im Tagebuch des Spielers in den 'Abgeschlossene Aufgaben'-Reiter verschoben wird - aber sie wird immer noch ausgeführt, bis sie mit 'StopQuest' beendet wird.
- Quests werden automatisch aktiviert, wenn der Spieler einen entsprechenden Eintrag in sein Tagebuch erhält. Mit "SetStage QUESTNAME 10" wird das automatisch die Quest starten, vorausgesetzt Eintrag 10 hat einen Journal-Text.
- Normalerweise sollte eine Quest angehalten werden, wenn sie abgeschlossen ist, damit das Quest-Script nicht weiter ausgeführt wird. Wenn es einen Grund gibt, das Script weiterhin laufen zu lassen (aufgrund von Dialogen oder Scripts nach der Quest), solltest du darüber nachdenken, eine zweite Quest zu erstellen (z.B. MS38 und MS38FIN).
- Quest-Variablen können auch dann eingesehen und verändert werden, wenn die Quest nicht ausgeführt wird. Wenn eine Quest angehalten wird, wird zwar auch das Script gestoppt, aber es bleibt ebenso wie seine Variablen erhalten
Ändern, wie oft ein Quest Script ausgeführt wird
- Deklariere die Variable fQuestDelayTime als Float-Variable in deinem Quest-Script.
- Weise fQuestDelayTime zu, in welchem Intervall dein Script ausgeführt werden soll (in Sekunden). Wenn du es auf etwas sehr Kleines setzt (0.01), wird es dann tatsächlich in jedem Frame ausgeführt. Wenn du es auf 0 setzt, wird das Quest-Script zur Standard-Einstellung (alle 5 Sekunden) zurückkehren. Benutze dieses Feature mit Bedacht - Im Allgemeinen sollte fQuestDelayTime nur in sehr kontrollierten und limitierten Prozessen unter 5 Sekunden gesetzt werden, um das Hauptspiel nicht zu sehr zu belasten.
- fQuestDelayTime kann auch von anderen Scripts aus gesetzt werden, indem du dein Script mit angibst, z.B. set MyQuest.fQuestDelayTime to 0.01.
- Quest-Scripts sind die einzigen Scripts, die MenuMode-Blöcke ausführen, während der Spieler schläft oder die Schnellreise-Funktion verwendet.
- Da Quest-Scripts immer basierend auf bestimmten Zeitabständen ausgeführt werden, müssen sie nicht zwangsläufig Frame-synchron sein - auch wenn fQuestDelayTime auf einen sehr kleinen Wert gesetzt wird. Für manche Effekte (z.B. welche, die SetPos verwenden) kann dies ungewünschte Ergebnisse haben. In dem Fall können Objekt- und Magie-Scripts die bessere Wahl sein.
- Deklariere die "Magie-Variable" als "Float fQuestDelayTime" in deinem Quest Script.
Magie Effekt Scripts
Magie Effekt Scripts sind spezielle Scripts, die dazu verwendet werden, um gescriptete Magie-Effekte zu erstellen (klingt logisch, oder?). Sie werden ganz normal im Script-Editor-Fenster erstellt, aber sie müssen als Magie-Effekt gekennzeichnet werden, um auch als solche benutzt werden zu können (das tut man im Script-Editor beim DropDown-Menü oben Rechts unter "Script Type").
Diese Scripts benutzen keine normalen BEGIN/END-Blöcke, weil sie nur dann ausgeführt werden, wenn der Zauber-Effekt auf ein Ziel einwirkt. Sie benutzen drei spezielle Block-Typen und eine spezielle Funktion.
Magie-Effekt Block Typen
- ScriptEffectStart
Verwendung:
<tesscript>begin ScriptEffectStart</tesscript>
Spezieller Block-Typ, der nur für Magie-Effekt-Scripts genutzt wird. Dieser Block startet beim ersten Auftreffen eines gescripteten Zauber-Effekts.
Hinweis: jeder gescriptete Zauber-Effekt wird auf den Ziel-Actor ausgeführt, wenn dieser damit getroffen wird. Das bedeutet, dass die Standard-Referenz für das Script ist, dass der Actor getroffen wurde, nicht der Spieler (wenn auch der Actor, der getroffen wurde, der Spieler sein kann). Das heißt außerdem, dass wenn der Block startet, der Zauber gerade den Actor getroffen hat und so ein "ScriptEffectStart" immer den OnHitWith-<Spellname>-Block auswerten kann.
Die Tatsache, dass Effekt-Zauber-Scripts auf jeden ausgeführt werden können, die von einen Zauber getroffen werden, gibt dem Programmierer die Möglichkeit, das Script an jeden Actor im Spiel für eine bestimmte Zeit anzuhängen und kann dazu benutzt werden, um die Actor-Referenz zu bekommen und viele andere Effekte.
Verwendung:
<tesscript>begin ScriptEffectFinish</tesscript>
Spezieller Block-Typ, der nur bei magischen Effekten benutzt wird. Dieser Block wird nur einmal ausgeführt, wenn der Zauber-Effekt endet. Es sollte auch beachtet werden, dass ScriptEffectUpdate vorher ausgeführt wird. Wenn dort eine Return-Anweisung innerhalb ScriptEffectUpdate ist, die im allerletzen Moment des Zauberwirkens eingreift, wird dieser Teil des Scripts nicht laufen.
Verwendung:
<tesscript>begin ScriptEffectUpdate</tesscript>
Spezieller Block-Typ, der nur bei Magie-Effekt-Scripts genutzt wird. Dieser Block startet beim ersten Auftreffen eines gescripteten Zauber-Effekts und startet jedes mal, wenn der Zauber aktualisiert wird, bis der Zaubereffekt endet.
Andere Block-Typen sind ungültig (sie werden zwar kompiliert, doch der Code innerhalb wird niemals laufen).
Magie Effekt Funktion
Verwendung:
<tesscript>ScriptEffectElapsedSeconds</tesscript>
Nur in Magie-Effect-Scripts verfügbar. Gibt die Sekunden zurück, die seit der letzten Magie-Effekt-Aktualisierung vergangen sind. Dieses gibt innerhalb eines ScriptEffectUpdate-Blocks einen Wert größer als 0 zurück.
Diese Funktion gibt einen Bruch-Wert zurück (das heißt Werte zwischen 0 und 1 Sekunde).
In allen anderen Punkten funktionieren die Magie-Effekt-Scripts genauso wie Referenz-Scripts und können innerhalb des Magie-Effekt-Blocks alle normalen Script-Funktionen benutzen.
Ergebnis Scripts
Ergebnis-Scripts (Original: "Result Scripts") sind Script-Fragmente, die ein einziges Mal ablaufen, sobald ein festgelegtes Ereignis eingetreten ist. Es gibt zwei Arten von Ergebnis-Scripts:
- Dialog-Ergebnisse laufen, wenn ein NPC eine verknüpfte Info ausspricht. Dialog-Ergebnisse werden gewertet wie Referenz-Scripts.
- Quest-Stage-Ergebnisse laufen, wenn eine Quest-Stage gesetzt wurde UND das Stage-Item die angegebenen Konditionen erfüllt hat. Quest-Stage-Ergebnisse werden gewertet wie Nicht-Referenz-Scripts.
Ergebnis-Scripts haben einige Beschränkungen verglichen mit benannten Scripts:
- sie können keine Variablen deklarieren
- sie können keine BEGIN/END-Blöcke verwenden
Darüber hinaus können Ergebnis-Scripts alle normalen Script-Befehle und -Funktionen benutzen.
Dialoge
Ein Dialog ist jeder Text, der im Spiel gesprochen wird. Alle Dialoge werden im Quest-Fenster angelegt. Du findest die Dialoge in den Reitern Topics, Conversation, Combat, Persuasion, Detection und Service.
Quest Stages
Eine Quest Stage zu setzen (siehe auch SetStage), fügt beim Spieler einen Journal-Eintrag hinzu und startet das Result-Script (Ergebnis-Script). Wenn es mehrere Stage-Items für eine einzelne Quest gibt, wird jede ausgewertet, um zu sehen, ob und welche schon erfüllt sind. Folglich ist es möglich, dass eine einzelne Stage mehrere Einträge ins Spieler-Journal hinzufügt und/oder mehrere Ergebnis-Scripts startet.
- SetStage
Syntax:
<tesscript>SetStage QuestID StageIndex</tesscript>
Beispiel:
<tesscript>SetStage MS27 30</tesscript>
Setzt die angegeben Quest-Stage auf "done" (fertig) und startet eines der angehängten Stage-Items, dessen Bedingung erfüllt ist (startet Ergebnis, fügt Questlog hinzu, komplettiert die Quest, wenn es soll).
Wenn dies die erste Stage der Quest ist, die dem Spieler-Journal zugefügt wird, bekommt der Spieler eine "Quest hinzugefügt" auf dem Bildschirm angezeigt. Außerdem wird SetStage die Quest automatisch starten, wenn diese noch nicht gestartet wurde. Bedenke immer, dass SetStage nur Stages akzeptiert, die im Quest-Fenster im Reiter "Quest Stages" definiert wurden. Wenn du eine falsche Stage ansprichst, wird der Stageindex sich nicht ändern.