Scriptsystem: Unterschied zwischen den Versionen

Aus OMSIWiki
Wechseln zu:Navigation, Suche
(Verfassen des Artikels)
(Einstiegs- und Ausstiegspunkte)
Zeile 1: Zeile 1:
 
Das Scriptsystem in OMSI ermöglicht es, dass Szenerieobjekte und vor allem Fahrzeuge mit individuellen Systemen ausgestattet werden können, die über Variablen und Funktionsaufrufe mit dem Hauptprogramm und der Grafik- und Soundengine kommunizieren.
 
Das Scriptsystem in OMSI ermöglicht es, dass Szenerieobjekte und vor allem Fahrzeuge mit individuellen Systemen ausgestattet werden können, die über Variablen und Funktionsaufrufe mit dem Hauptprogramm und der Grafik- und Soundengine kommunizieren.
 +
 +
Der hier beschriebene Stand des Scriptsystems entspricht OMSI Version 1.01.
  
 
== Dateien des Scriptsystems ==
 
== Dateien des Scriptsystems ==
Zeile 26: Zeile 28:
 
Der Stack enthält 8 Speicherplätze, welche von 0 bis 7 durchnumeriert sind. Jede Script-Operation kann nun einen oder mehrere neue Werte in den Stack einfügen (push), wobei der neue Wert auf die Position 0 gesetzt wird und alle folgenden Werte "einen Platz aufrücken", oder sie kann einen oder mehrere Werte aus dem Stack herausziehen (pop/pull) oder lediglich auslesen (peek).
 
Der Stack enthält 8 Speicherplätze, welche von 0 bis 7 durchnumeriert sind. Jede Script-Operation kann nun einen oder mehrere neue Werte in den Stack einfügen (push), wobei der neue Wert auf die Position 0 gesetzt wird und alle folgenden Werte "einen Platz aufrücken", oder sie kann einen oder mehrere Werte aus dem Stack herausziehen (pop/pull) oder lediglich auslesen (peek).
  
=== Einfache Operation ===
+
=== Beispiel-Operationen ===
  
 
Beispiel: Die Operation 1 + 4. Der Code hierfür lautet:
 
Beispiel: Die Operation 1 + 4. Der Code hierfür lautet:
Zeile 71: Zeile 73:
  
 
Am Ende befindet sich also das korrekte Ergebnis auf Stackplatz 0!
 
Am Ende befindet sich also das korrekte Ergebnis auf Stackplatz 0!
 +
 +
=== Einstiegs- und Ausstiegspunkte ===
 +
 +
Alle Befehle müssen zwischen einem Einstiegs- und einem Ausstiegspunkt liegen.
 +
 +
Der Einstiegspunkt wird durch eins der folgenden Schlüsselwörter gekennzeichnet:
 +
 +
* {frame} Im Laufe jedes Frames ruft OMSI über diesen Einstiegspunkt die frameweise Scriptverarbeitung auf, sofern er vorhanden ist.
 +
* {init} Bei der Initialisierung ruft OMSI über diesen Einstiegspunkt die Script-Initialisierung auf.
 +
* {frame_ai} Hierbei handelt es sich um eine Variante des {frame}-Einstiegspunktes, welcher bei Fahrzeugen dann aufgerufen wird, wenn diese nicht im Fokus des Benutzers stehen, z.B. wenn sie als KI-Fahrzeug unterwegs sind. Ist dieser Einstiegspunkt jedoch nicht vorhanden sondern nur {frame}, dann wird dieser alternativ aufgerufen. Bei Szenerieobjekten kommt dieser Eintrittspunkt nicht zur Anwendung.
 +
* {macro:''name''} Dieser Einstiegspunkt ruft ein Subsektion (Makro) auf, welche sich '''stets nach dem Aufruf''' definiert wird. Der Aufruf erfolgt über (L.M.''name'')
 +
* {trigger:''name''} Dieser Einstiegspunkt wird vom Hauptprogramm aufgerufen, wenn der Benutzer die Tastenkombination oder das Maus-Event mit der Bezeichnung ''name'' aufruft - es gibt auch bestimmte Trigger, die direkt vom Hauptprogramm aufgerufen werden, z.B. wenn OMSI bei KI-Bussen die Anzeige wechselt u.Ä.
 +
* {end} Dies ist der universelle Ausstiegspunkt. Er muss stets den Block abschließen, der mit einem der obigen Befehle eröffnet wird.
 +
 +
Bei einfachen Scripts (z.B. bei reinen KI-Fahrzeugen oder Szenerieobjekten) reicht es im Allgemeinen eine *.sco-Datei zu erstellen, welche über einen {frame}...{end}- und ggf. einen {init}...{end}-Block verfügt.
 +
 +
Handelt es sich jedoch um ein komplettes Fahrzeugscript, dann empfiehlt es sich für die verschiedenen Subsysteme getrennte Dateien anzulegen. Hierbei sollte folgendermaßen vorgegangen werden:
 +
 +
* Es gibt ein Hauptscript und die nötigen Subsystemdateien. Die Hauptdatei enthält dabei die {frame}- und {init}-Blöcke, die jedoch nur Makros aufrufen, welche in den Subsystemdateien definiert sind.
 +
* Für jedes Subsystem gibt es eine *.sco-Datei und je nach Bedarf eine eigene Varlist und Constfile mit den zum System gehörenden Variablen. Außerdem werden auch hier die Trigger für die Tastenbefehle einsortiert.
 +
* Die Makros sollten sinnvollerweise folgendermaßen benannt werden: {macro:''subsystem''_frame} und {macro:''subsystem''_init}.
 +
* Damit die Makros vom Hauptscript aufgerufen werden, muss dieses in der Liste der Scripts in der Objekt-Konfigurationsdatei als erstes aufgerufen werden. Die Reihenfolge der Scripts untereinander muss ebenfalls so gewählt werden, dass alle dateiübergreifenden Makroaufrufe stets vor der jeweiligen Makrodefinition stehen.
 +
 +
Die Einschränkung, dass Makros immer hinter dem Aufruf definiert werden müssen, kann zwar bisweilen hinderlich sein, ist aber ein sehr wirksamer Schutz gegen Zirkelschlüsse und Endlosschleifen.
 +
 +
 +
=== Stack-Operationen ===
 +
 +
{| class="wikitable" style="font-size:95%;" 
 +
|- class="hintergrundfarbe5"
 +
| align="left" |Pause
 +
| align="left" |P
 +
|-
 +
| align="left" |Geldwechsler obere Reihe
 +
| align="left" |Strg + Umschalt + 5, 6, 7, 8, 9, 0
 +
|}
  
 
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]
 
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]

Version vom 9. September 2011, 20:39 Uhr

Das Scriptsystem in OMSI ermöglicht es, dass Szenerieobjekte und vor allem Fahrzeuge mit individuellen Systemen ausgestattet werden können, die über Variablen und Funktionsaufrufe mit dem Hauptprogramm und der Grafik- und Soundengine kommunizieren.

Der hier beschriebene Stand des Scriptsystems entspricht OMSI Version 1.01.

Dateien des Scriptsystems

Das Scriptsystem umfasst folgende Dateien:

  • Scriptdateien mit ausführbarem Code (*.sco)
  • Varlist- und Stringvarlist-Dateien im OMSI\program-Verzeichnis zur Definition von Systemvariablen
  • Varlist- und Stringvarlist-Dateien zur Definition von Uservariablen
  • Constfile-Dateien zur Definition von Userkonstanten und Funktionstabellen

Abgesehen von den Dateien zur Definition von Systemvariablen müssen alle benötigten Dateien für jedes Fahrzeug/Szenerieobjekt (im folgenden kurz: Objekt) in dessen Konfigurationsdatei angemeldet werden.

Hierfür gibt es die Befehle [script], [varnamelist], [stringvarnamelist] und [constfile]. Der erste Eintrag jedes Befehls ist die Anzahl der Dateien, darauf folgen die entsprechenden Dateinamen (inkl. Pfad relativ zur Konfigurationsdatei. Die Namen der Dateien sind nicht relevant, solange sie korrekt in die Listen eingetragen werden.

Auf die Funktion der jeweiligen Dateien wird im Laufe der Beschreibung der Scriptsprache eingegangen.

Grundlagen der Scriptsprache

Das OMSI-Scriptsystem arbeitet mit der umgekehrten Polnischen Notation, kurz UPN. Ein ausführlicher Artikel hierzu findet sich in der Wikipedia. Hierbei steht der Operator hinter den beiden Operanden; vereinfacht gesagt bedeutet es, dass die Operation " 1 + 2 " stattdessen folgendermaßen notiert wird: " 1 2 + ". Ein komplizierteres Beispiel: " (1 + 2) * (4 + 5) " entspricht " 1 2 + 4 5 + * ".

Stack

Bei der Verarbeitung der Scripts verfügt OMSI über einen String-Stack und einen Stack für Gleitkommazahlen. Der String-Stack ist an dieser Stelle noch nicht interessant und wird erst später erwähnt. Der Stack für Gleitkommazahlen wird im folgenden der Einfachheit halber nur als "Stack" bezeichnet.

Der Stack enthält 8 Speicherplätze, welche von 0 bis 7 durchnumeriert sind. Jede Script-Operation kann nun einen oder mehrere neue Werte in den Stack einfügen (push), wobei der neue Wert auf die Position 0 gesetzt wird und alle folgenden Werte "einen Platz aufrücken", oder sie kann einen oder mehrere Werte aus dem Stack herausziehen (pop/pull) oder lediglich auslesen (peek).

Beispiel-Operationen

Beispiel: Die Operation 1 + 4. Der Code hierfür lautet:

1 4 +

In der folgenden Tabelle wird demonstriert, wie sich hierbei der Stack verhält:

Operation:	Stack:	0	1	2	3	4 ...
-----------------------------------------------------------------------------
vorher:			0	0	0	0	0
"1"			1	0	0	0	0
"4"			4	1	0	0	0
"+"			5	0	0	0	0

Im Ausgangszustand ist der Stack nur mit Nullen (oder unbekannten/zufälligen Werten) gefüllt. Der Befehl "1" schiebt die Eins in den obersten Stackplatz und schiebt alle weiteren Werte (Nullen) nach hinten. Der Befehl "4" schiebt die Vier auf den 0. Platz und alle folgenden Werte, also insbesondere die Eins auf den jeweils nächsten Platz. Im nächsten Schritt "+" werden die obersten beiden Werte aus dem Stack herausgezogen - also 4 und 1 - und summiert. Das Ergebnis (5) wird wiederum in den Stack geschoben. Die beiden ursprünglichen Zahlen sind im Stack nicht mehr vorhanden.

Ein zweites Beispiel:

(1 + 2) * (4 + 5) muss wie bereits erwähnt folgendermaßen notiert werden:

1 2 + 4 5 + *

Der Stack verhält sich somit folgendermaßen:

Operation:	Stack:	0	1	2	3	4 ...
-----------------------------------------------------------------------------
vorher:			0	0	0	0	0
"1"			1	0	0	0	0
"2"			2	1	0	0	0
"+"			3	0	0	0	0
"4"			4	3	0	0	0
"5"			5	4	3	0	0
"+"			9	3	0	0	0
"*"			27	0	0	0	0

Am Ende befindet sich also das korrekte Ergebnis auf Stackplatz 0!

Einstiegs- und Ausstiegspunkte

Alle Befehle müssen zwischen einem Einstiegs- und einem Ausstiegspunkt liegen.

Der Einstiegspunkt wird durch eins der folgenden Schlüsselwörter gekennzeichnet:

  • {frame} Im Laufe jedes Frames ruft OMSI über diesen Einstiegspunkt die frameweise Scriptverarbeitung auf, sofern er vorhanden ist.
  • {init} Bei der Initialisierung ruft OMSI über diesen Einstiegspunkt die Script-Initialisierung auf.
  • {frame_ai} Hierbei handelt es sich um eine Variante des {frame}-Einstiegspunktes, welcher bei Fahrzeugen dann aufgerufen wird, wenn diese nicht im Fokus des Benutzers stehen, z.B. wenn sie als KI-Fahrzeug unterwegs sind. Ist dieser Einstiegspunkt jedoch nicht vorhanden sondern nur {frame}, dann wird dieser alternativ aufgerufen. Bei Szenerieobjekten kommt dieser Eintrittspunkt nicht zur Anwendung.
  • {macro:name} Dieser Einstiegspunkt ruft ein Subsektion (Makro) auf, welche sich stets nach dem Aufruf definiert wird. Der Aufruf erfolgt über (L.M.name)
  • {trigger:name} Dieser Einstiegspunkt wird vom Hauptprogramm aufgerufen, wenn der Benutzer die Tastenkombination oder das Maus-Event mit der Bezeichnung name aufruft - es gibt auch bestimmte Trigger, die direkt vom Hauptprogramm aufgerufen werden, z.B. wenn OMSI bei KI-Bussen die Anzeige wechselt u.Ä.
  • {end} Dies ist der universelle Ausstiegspunkt. Er muss stets den Block abschließen, der mit einem der obigen Befehle eröffnet wird.

Bei einfachen Scripts (z.B. bei reinen KI-Fahrzeugen oder Szenerieobjekten) reicht es im Allgemeinen eine *.sco-Datei zu erstellen, welche über einen {frame}...{end}- und ggf. einen {init}...{end}-Block verfügt.

Handelt es sich jedoch um ein komplettes Fahrzeugscript, dann empfiehlt es sich für die verschiedenen Subsysteme getrennte Dateien anzulegen. Hierbei sollte folgendermaßen vorgegangen werden:

  • Es gibt ein Hauptscript und die nötigen Subsystemdateien. Die Hauptdatei enthält dabei die {frame}- und {init}-Blöcke, die jedoch nur Makros aufrufen, welche in den Subsystemdateien definiert sind.
  • Für jedes Subsystem gibt es eine *.sco-Datei und je nach Bedarf eine eigene Varlist und Constfile mit den zum System gehörenden Variablen. Außerdem werden auch hier die Trigger für die Tastenbefehle einsortiert.
  • Die Makros sollten sinnvollerweise folgendermaßen benannt werden: {macro:subsystem_frame} und {macro:subsystem_init}.
  • Damit die Makros vom Hauptscript aufgerufen werden, muss dieses in der Liste der Scripts in der Objekt-Konfigurationsdatei als erstes aufgerufen werden. Die Reihenfolge der Scripts untereinander muss ebenfalls so gewählt werden, dass alle dateiübergreifenden Makroaufrufe stets vor der jeweiligen Makrodefinition stehen.

Die Einschränkung, dass Makros immer hinter dem Aufruf definiert werden müssen, kann zwar bisweilen hinderlich sein, ist aber ein sehr wirksamer Schutz gegen Zirkelschlüsse und Endlosschleifen.


Stack-Operationen

Pause P
Geldwechsler obere Reihe Strg + Umschalt + 5, 6, 7, 8, 9, 0