<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>http://wiki.omnibussimulator.de/omsiwikineu.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Faaabiii</id>
	<title>OMSIWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.omnibussimulator.de/omsiwikineu.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Faaabiii"/>
	<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Spezial:Beitr%C3%A4ge/Faaabiii"/>
	<updated>2026-05-05T12:51:35Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Leitfaden_performancefreundlicher_Fahrzeugbau&amp;diff=1293</id>
		<title>Leitfaden performancefreundlicher Fahrzeugbau</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Leitfaden_performancefreundlicher_Fahrzeugbau&amp;diff=1293"/>
		<updated>2014-10-17T18:54:54Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: 1. Zeile entfernt -&amp;gt; Artikel wurde übersetzt! Link zur englischen Seite ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Wie der Name schon sagt, soll dieser Leitfaden Möglichkeiten und Denkanstöße bieten, OMSI-Fahrzeuge möglichst performance-freundlich zu gestalten.&lt;br /&gt;
&lt;br /&gt;
Ein OMSI-Fahrzeug besteht aus 3D-Modellen, Texturen, Sound und Script – und in allen vier Bereichen sollte man mehr oder weniger intensiv auf eine Optimierung hinsichtlich der Performance achten!&lt;br /&gt;
&lt;br /&gt;
Aber eines gilt immer: '''Auch wenn man nicht mehr so geizen muss wie früher: Verschwenden sollte man keinesfalls!''' - Also sollte man bei jedem Teil, welches man modelliert, bei jedem Sound und bei jeder Textur ein wenig im Hinterkopf haben, was sinnvoll und nötig ist oder was eventuell mehr ist, als man braucht. Dass das Geschmacks- und Ansichtssache ist, versteht sich natürlich von selbst.&lt;br /&gt;
&lt;br /&gt;
== 3D-Modelle ==&lt;br /&gt;
&lt;br /&gt;
=== Theorie ===&lt;br /&gt;
&lt;br /&gt;
Zunächst muss der Begriff 'Drawcall' definiert werden:&lt;br /&gt;
&lt;br /&gt;
Zwar wird der Bus (wie alles andere) aus einzelnen Dreiecken gezeichnet, die Dreiecke ihrerseits sind aber zusammengefasst zu Meshs mit gleichen Materialeigenschaften, Texturen und so weiter. Einen solchen zusammengefassten Zeichenvorgang bezeichnet man als Drawcall. Intern wird dieser zunächst von OMSI vorbereitet, dann werden alle Parameter der Grafikkarte übergeben und schließlich arbeitet die Grafikkarte &amp;quot;eigenständig&amp;quot; den Drawcall mit allen zugehörigen Dreiecken ab.&lt;br /&gt;
&lt;br /&gt;
Dieser Zusammenhang erklärt auch, warum ein Drawcall mit 100.000 Vertices wesentlich schneller abgearbeitet wird, als 1000 Drawcalls mit jeweils 100 Vertices.&lt;br /&gt;
&lt;br /&gt;
=== Nicht zuviele o3d-Dateien und nicht zuviele einzelne Texturen ===&lt;br /&gt;
&lt;br /&gt;
Jede o3d-Datei verursacht mindestens einen Drawcall pro Textur, die die o3d-Datei verwendet. In bestimmten Fällen und insbesondere auch bei x-Dateien können es sogar mehrere Drawcalls pro Textur und o3d-Datei sein.&lt;br /&gt;
&lt;br /&gt;
Hieraus ergeben sich folgende Regeln:&lt;br /&gt;
&lt;br /&gt;
'''Verwende so wenig o3d-Dateien wie möglich pro Bus.'''&lt;br /&gt;
&lt;br /&gt;
Unumgänglich ist eine Separierung bei Animationen und oft bei transparenten Dingen, bei denen über die Separierung die Renderreihenfolge festgelegt wird. Daran kann man nicht rütteln.&lt;br /&gt;
&lt;br /&gt;
Es ist aber ohne weiteres möglich, das Fahrzeug nur aus sehr wenigen nicht-animierten o3d-Dateien zusammen zu setzen, z.B. (Reihenfolge = Renderreihenfolge):&lt;br /&gt;
&lt;br /&gt;
# Innenmesh inkl. Fahrerarbeitsplatz ohne Leuchtmelder, Schalter usw.&lt;br /&gt;
# Transparenzen im Innenraum&lt;br /&gt;
# Außenmesh&lt;br /&gt;
# Fensterscheiben von innen&lt;br /&gt;
# Fensterscheiben von außen&lt;br /&gt;
&lt;br /&gt;
'''Innerhalb einer o3d-Datei so wenig unterschiedliche Texturen wie möglich.'''&lt;br /&gt;
&lt;br /&gt;
Mit der obigen Erklärung wohl einfach zu verstehen: Wenn mein komplettes Außenmesh nur eine Textur hat, dann ist es auch nur ein Drawcall. Das ist besser als wenn mein Außenmesh zwei Texturen benötigt, sodass das Außenmesh in zwei Drawcalls gerendert werden muss.&lt;br /&gt;
&lt;br /&gt;
Wird ein Bauteil ohnehin immer animiert (typisches Beispiel: Räder), dann ist es weniger tragisch, wenn deren Textur separat ist. Allerdings sollten auch die [[LOD]]s berücksichtigt werden: Da unsere Fahrzeuge in größerer Entfernung keine animierten Räder haben, haben wir die Radtextur auch in die Haupttextur integriert.&lt;br /&gt;
&lt;br /&gt;
=== Verwendung von reduzierter Darstellung für die Entfernung und für KI-Fahrzeuge ===&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe von [[LOD]]s ist es möglich, dass das Fahrzeug auf größerer Entfernung einfacher gezeichnet wird. Und auch, wenn der User es nicht selbst verwendet, sollte es einfacher werden.&lt;br /&gt;
&lt;br /&gt;
'''Jedes Fahrzeug sollte mindestens über zwei [[LOD]]-Stufen verfügen, sodass es ab unter etwa 10% Bildschirmgröße zu einer starken Vereinfachung kommt.'''&lt;br /&gt;
&lt;br /&gt;
[[Datei:2012 0716 05 Performance.jpg|600px|thumb|right|Das sehr einfache LOD-Mesh für die größere Entfernung des SD77. Zwar sehr einfach, aber für größere Entfernungen völlig ausreichend und sehr sparsam. Einziges Manko: Aufgrund der Repaint-Möglichkeiten muss trotzdem die große 1024er-Textur für die Außenhaut geladen werden, aber abgesehen von der Reflexionstextur ist das alles!]]&lt;br /&gt;
In dieser Größenordnung kann bereits auf den Innenraum komplett verzichtet werden, die äußere Hülle sollte nur noch ein sehr einfaches Mesh sein (20-50 Vertices). Wir haben außerdem auf Nachttexturen und Lichteffekte in dieser Entfernung komplett verzichtet. Man muss ja nur noch sehen, &amp;quot;dass da ein Bus fährt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Jedes Fahrzeug sollte als KI-Fahrzeug wesentlich vereinfacht werden.''' (Obgleich unpräzise, ist mit &amp;quot;KI-Fahrzeug&amp;quot; auch ein &amp;quot;verlassenes&amp;quot; Userfahrzeug gemeint. Sämtliche Flags, wie die folgende, die sich auf diese Nomenklatur beziehen, stufen verlassene Userfahrzeuge als KI-Fahrzeuge ein.)&lt;br /&gt;
&lt;br /&gt;
Hierzu dient der Viewpoint-Befehl. Die darunterstehende Zahl kann folgende Werte annehmen:&lt;br /&gt;
&lt;br /&gt;
* 0 = immer sichtbar&lt;br /&gt;
* 1 = am aktuellen Userfahrzeug nur von außen sichtbar&lt;br /&gt;
* 2 = am aktuellen Userfahrzeug nur von innen sichtbar&lt;br /&gt;
* 3 = 1 + 2, also am aktuellen Userfahrzeug von innen und außen sichtbar&lt;br /&gt;
* 4 = nur an KI-Fahrzeugen sichtbar.&lt;br /&gt;
* 5 = 4 + 1, also an KI-Fahrzeugen sichtbar oder am Userfahrzeug nur von außen&lt;br /&gt;
* 6 = 2 + 4, also an KI-Fahrzeugen sichtbar oder am Userfahrzeug nur von innen&lt;br /&gt;
* 7 = 1 + 2 + 4, also immer sichtbar, dann kann man auch die 0 nehmen! :)&lt;br /&gt;
&lt;br /&gt;
Zu beachten ist: Ein KI-Fahrzeug sieht man sich nur von außen an, aber meist nicht so genau. Es kann aber sehr dicht stehen und man guckt oft auch mal von hinten rein (an der Ampel oder Haltestelle).&lt;br /&gt;
&lt;br /&gt;
* KI-Fahrzeuge sollten daher das komplette, detaillierte Außenmesh haben und die groben Dinge des Innenmeshs, wie Verkleidungen, Sitze usw. Hierbei sind vor allem die Dinge wichtig, die man von hinten sieht.&lt;br /&gt;
* KI-Fahrzeuge brauchen nicht über ein animiertes Cockpit verfügen (animierter Sitz, Lenkrad) und Haltestangen kann man auch wesentlich vereinfachen. Theoretisch gilt das auch für den ''eigenen'' Bus in der Außenansicht, aber hier muss man nicht so sparsam sein, da der eigene Bus ja nur einmal sichtbar ist - KI-Fahrzeuge dagegen oft in großer Zahl.&lt;br /&gt;
* Sehr viel Potenzial bieten wieder Drawcalls: Typischerweise gibt es bei aller Optimierung mehrere Texturen für den Innenraum, oft aber nur eine für das Außenmesh. Sinnvollerweise also sollte man soviele Texturen des Innenraums wie möglich einsparen. Das statische Dashboard, das Lenkrad, die übriggebliebenen Haltestangen usw. benutzen oft separate Texturen; dies alles sollte im KI-Mesh über einen kleinen Bereich einer weiterhin notwendigen Textur gemappt werden, z.B. eine simple dunkelgraue, leicht &amp;quot;angerauhte&amp;quot; Fläche. Aber Achtung: Es bringt erst dann was, wenn eine oder mehrere komplette Texturen eingespart werden.&lt;br /&gt;
&lt;br /&gt;
==== Das KI-Modell des SD77 als Beispiel ====&lt;br /&gt;
&lt;br /&gt;
Das KI-Innenmesh des SD77 benötigt lediglich die Texturen SD77_02.bmp, _03.bmp und _04.bmp. Eingespart werden die Texturen Fahrersitz, Panel, Thermometer und Zahltisch gegenüber dem User-Innenraum:&lt;br /&gt;
&lt;br /&gt;
[[Datei:2012 0716 03 Performance.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
Unterschiede KI- und User-Mesh beim SD77. In der Ansicht von Hinten erkennt man die nur geringen Unterschiede, die vor allem Mesh-Vereinfachungen mit größerem Poly-Reduktionspotential besitzen: Haltestangen, Haltewunschknöpfe, Griffe an den Sitzen. Wichtige Details wie die Sitze, Treppenwangen oder auch Leuchten müssen beibehalten werden:&lt;br /&gt;
&lt;br /&gt;
[[Datei:2012 0716 04 Performance.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
=== Nicht übermäßig viele Vertices verwenden - Texturen können auch sinnvolle Dienste leisten ===&lt;br /&gt;
&lt;br /&gt;
Damals™, als wir im Flusi mit dem Modellbau angefangen haben, mussten wir noch das Mesh per Hand auf Millimeterpapier zeichnen und die Koordinaten selbst ausmessen und maßstäblich umrechnen. Dann haben wir uns an die Lochkarten-Stanzmaschine gesetzt und wehe, wenn wir einen Fehler gemacht haben... ok, genug der angestaubten Geschichten von früher™! :-D (Wobei der Anfang noch stimmt, die Design-Programme für den Flusi kamen erst mit den Versionen 2000/2002 mit FSDS und Gmax so richtig in Schwung...)&lt;br /&gt;
&lt;br /&gt;
Was ich mit der kleinen Geschichte von &amp;quot;damals als wir nix hatten&amp;quot; sagen will: Schon aus Egoismus heraus war man mit Polys und Vertices sparsam. Das bleibt so drinn - während wir heute uns den Freeware-NL202 ansehen und den 3D-Löwen sowie den 3D-Schriftzug bestaunen - und ebenso erstaunt sind, dass das OMSI frisst...&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich ist der NL202 ein gelungenes und natürlich sehr beliebtes OMSI-Addon. Trotzdem bin ich mal so frech und stelle ihn neben unseren in Entwicklung befindlichen NG272:&lt;br /&gt;
&lt;br /&gt;
[[Datei:2012 0716 07 Performance.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
Was fällt auf? Der NL202 verfügt über wesentlich mehr Polygone als der NG272. Selbstverständlich lassen sich bestimmte Dinge nur darstellen mit entsprechend detaillierten Modellierungen, z.B. die Schrägstellung der Lüftungsschlitze oder das Profil des Fenstergummileisten. Aber man muss sich beim Fahrzeugbau ständig fragen: Brauch ich das wirklich? Lohnt sich einerseits der Aufwand und andererseits der Preis der höheren Polygonzahl? Natürlich sieht es sehr schick aus, aber wann ist man schonmal da hinten am Motorraum?&lt;br /&gt;
&lt;br /&gt;
Denn wenn man von weitem schaut, dann reicht eine passende fotoreale Textur im Allgemeinen aus. Natürlich glänzen unsere Lüftungsschlitze dafür nicht so schön in der Sonne! :)&lt;br /&gt;
&lt;br /&gt;
=== Vertices nur da einbauen, wo es auch sinnvoll ist ===&lt;br /&gt;
&lt;br /&gt;
Noch ein Beispiel zum Thema Vertex-Einsparung:&lt;br /&gt;
&lt;br /&gt;
[[Datei:2012 0716 06 Performance.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
Natürlich ist das mittlere Rohr das schönste! :) Aber dieses hat auch die meisten Polygone. Die Frage ist nun - wie genau spart man Polygone ein und wieviel optische Einbuße bringt es?&lt;br /&gt;
&lt;br /&gt;
In diesem Fall kann man entweder in Längsrichtung oder in Umfangrichtung sparen. Was bringt mehr? Wenn man ungefähr gleiche Vertex- und Face-Zahlen erhalten möchte, dann sehen die Rohre wie gezeigt aus. Links wird in Längsrichtung kein einziges Mal mehr gebrochen, dafür hat der Umfang immer noch 32 Kanten. Rechts dagegen hat das Rohr nur 8 Kanten, dafür konnten alle sieben Brüche (entspricht ebenfalls 32 Ecken entlang des Vollkreises!) beibehalten werden. Offensichtlich die bessere Lösung: Denn den Querschnitt nimmt man nur wahr, wo das Profil endet (Auspuff) oder auf eine andersfarbige Fläche trifft bzw. selbst eine andere Farbe annimmt, während man die Längsrichtung oft sehr direkt sieht, wie auch in diesem Beispiel.&lt;br /&gt;
&lt;br /&gt;
Typische Ähnlichkeit hierzu haben Haltestangen, die bei heutigen Bussen oft schwungvoll gestaltet sind: Auch dort sollte der &amp;quot;Schwung&amp;quot; ausreichend rund sein - dafür kann das Profil ruhig etwas eckiger sein (Acht- oder nur Sechseck).&lt;br /&gt;
&lt;br /&gt;
Um also zum Anfang zurück zu kommen: 1995 hatte der FlightShop-Jumbo-Jet für den Flight Simulator 95 einen achteckigen (!!!) Rumpfquerschnitt! Das sollte man immer bedenken, wenn man 32-eckige Haltestangenprofile konstruiert! :D&lt;br /&gt;
&lt;br /&gt;
== Texturen ==&lt;br /&gt;
&lt;br /&gt;
Ein wichtiger Punkt wurde schon genannt:&lt;br /&gt;
&lt;br /&gt;
=== Wenige große Texturen sind im Allgemeinen besser als viele kleine ===&lt;br /&gt;
&lt;br /&gt;
..., insbesondere dann, wenn sie zusammen auf einer o3d-Datei zur Anwendung kommen. Natürlich gibt es Grenzen: Einerseits werden die Texturen ab einer bestimmten Auflösung irgendwann etwas &amp;quot;unhandlich&amp;quot;, weshalb wir meistens nur bis 1024x1024 gehen, obgleich diese Grenze sicherlich auch nicht mehr ganz zeitgemäß ist.&lt;br /&gt;
&lt;br /&gt;
=== Regelmäßige Auflösungen verwenden! ===&lt;br /&gt;
&lt;br /&gt;
Was früher jeder Objektbauer im Flugsimulator wusste, ist heute nicht mehr allgemein bekannt: Texturen sollten Pixel-Maße haben, die der Zwei-Hoch-Reihe folgen:&lt;br /&gt;
&lt;br /&gt;
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, (2048, 4096, ...)&lt;br /&gt;
&lt;br /&gt;
Die eingeklammerten Werte sind jenseits dessen, was wir üblicherweise nutzen und ehrlich gesagt weiß ich nicht, welche Einschränkungen da eventuell auch heute noch warten. Bis 1024 ist aber keinesfalls ein Problem.&lt;br /&gt;
&lt;br /&gt;
Rechtecke sind auch ok, solange die obige Reihe eingehalten wird. 256x256 war früher im Flusi der ultimative Standard für alle Texturen, deshalb findet man bei &amp;quot;alten Hasen&amp;quot; oft heute noch dieses Maß. Aber 1024x128 ist ebenso ok wie 512x512 oder 4x128. Aber man sollte alle krummen Maße vermeiden (200x300 oder aber auch 256x77), weil die Verarbeitung tendentiell schlechter wird. Inwieweit das auf aktuellen Grafikkarten noch der Fall ist, weiß ich nicht - aber hinsichtlich der Kompatibilität zu älteren Karten kann es nicht schaden, sich an die Regel zu halten.&lt;br /&gt;
&lt;br /&gt;
Insbesondere wird in solchen &amp;quot;krummen&amp;quot; Fällen ohnehin aufgerundet zum nächsten &amp;quot;zulässigen&amp;quot; Maß. Dann kann man auch gleich selbst aufrunden und die übrigen Bereiche noch sinnvoll nutzen anstatt verfallen zu lassen.&lt;br /&gt;
&lt;br /&gt;
=== Dateiformate ===&lt;br /&gt;
&lt;br /&gt;
DirectX lädt relativ viele Formate. Das traditionelle Format ist Bitmap (*.bmp). Da dieses Format nicht komprimiert ist, ist mancher geneigt, JPG zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ob die Ladezeit schneller wird oder langsamer, vermag ich nicht zu sagen und das hängt sicherlich auch vom Aussehen der Textur und von einer Vielzahl anderer Faktoren ab. Allerdings sollte klar sein, dass (soweit ich weiß) es aber nichts bringt, um Grafikspeicher zu sparen, da das JPEG-Format nicht im Grafikkartenspeicher zur Anwendung kommen kann.&lt;br /&gt;
&lt;br /&gt;
Möchte man also Grafikkartenspeicher sparen, dann sollte man eher auf das DDS-Format zurückgreifen, welches eine Komprimierung anbietet, die sich - soweit ich richtig informiert bin - auch in den Grafikkartenspeicher überträgt.&lt;br /&gt;
&lt;br /&gt;
== Sound ==&lt;br /&gt;
&lt;br /&gt;
Beim Sound kann man eigentlich gar nicht so viel falsch machen. Grundsätzlich ist OMSI da recht genügsam und auch dafür ausgelegt, dass Fahrzeuge viiiele Sounds haben, damit man richtig viel Spaß hat und normalerweise sind auch etwas längere Sample von 48kHz kein Thema.&lt;br /&gt;
&lt;br /&gt;
Allerdings hat OMSI aus Performance-Gründen einen Soundzähler und eine Sortierfunktion, welche dafür sorgen, dass eine gewisse Höchstanzahl an Sounds nicht überschritten werden. Dies betrifft aber nicht nur aktuell hörbare sondern auch &amp;quot;theoretisch hörbare&amp;quot; Sounds, die also ständig geprüft werden müssen, ob sie demnächst hörbar werden müssen. Damit nun keine unnötigen freien &amp;quot;Soundplätze&amp;quot; verschwendet werden, gibt es die Möglichkeit, dass KI-Fahrzeuge (und wiederum User-Fahrzeuge, die verlassen wurden) mit einem einfacheren Sound-Set ausgerüstet werden.&lt;br /&gt;
&lt;br /&gt;
Dies ist relativ einfach zu realisieren:&lt;br /&gt;
&lt;br /&gt;
1. Zuerst erstellt man die normale Sound.cfg wie gewohnt und stellt sie komplett fertig.&lt;br /&gt;
&lt;br /&gt;
2. Nun kopiert man sie und benennt sie um, praktischerweise z.B. in Sound_AI.cfg.&lt;br /&gt;
&lt;br /&gt;
3. Nun löscht man alle Sound-Einträge in dieser Datei, die bei Fahrzeugen, die nicht der User selbt in der Hand hat, unnötig sind - als da wären:&lt;br /&gt;
:* Anlasser und Abschaltsound&lt;br /&gt;
:* Soundeffekte, die vor allem innen hörbar sind, wie z.B. der Luftpresser oder das Klappern im Stand beim SD&lt;br /&gt;
:* Cockpit- und ähnliche Systemsounds wie Schalter, Warnungen, IBIS, Rollband, Scheibenwischer usw. usw.&lt;br /&gt;
:* Beibehalten haben wir aber Motor, Achsplaneten, Getriebesounds, die man von außen hört, Retarder, Türen, Standheizung und Bremsenquietschen.&lt;br /&gt;
&lt;br /&gt;
4. Zuletzt muss man noch die *.bus/*.ovh-Datei um folgenden Eintrag ergänzen: [sound_ai] | sound\Sound_AI.cfg, sodass OMSI nun weiß, dass hier ein KI-Soundset vorliegt.&lt;br /&gt;
&lt;br /&gt;
Man stellt schnell fest, wieviel man hier einsparen kann und wieviel mehr Fahrzeuge dann noch in der Umgebung &amp;quot;klingen&amp;quot; im Gegensatz zu vorher.&lt;br /&gt;
&lt;br /&gt;
== Script ==&lt;br /&gt;
&lt;br /&gt;
=== Allgemein ===&lt;br /&gt;
&lt;br /&gt;
Ähnlich wie beim Sound gibt es die Möglichkeit, ein vereinfachtes Script ablaufen zu lassen. Wie das geht, wird im Artikel [[Scriptsystem]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Damit man allerdings jederzeit die Möglichkeit hat, das Fahrzeug zu übernehmen, werden stets alle normalen Variablen vorgehalten. Dies ist allerdings normalerweise kein größeres Problem.&lt;br /&gt;
&lt;br /&gt;
Abgesehen davon ist OMSI auch hinsichtlich des Scripts genügsam bzw. gibt es kein größeres Optimierungspotential. Ganz allgemein kann man dem Script-Entwickler nur ganz allgemein auf den Weg geben: Sie wenig wie möglich, so viel wie nötig. Geizen muss man nicht, Verschwenden sollte man nicht und wenn man sich zwischen zwei Varianten entscheiden kann, sollte man versuchen, die mit besserer Leistung zu nehmen.&lt;br /&gt;
&lt;br /&gt;
Wenn übrigens mehrfach genutzte Script-Sequenzen in ein gemeinsames Macro ausgelagert werden, dann spart das Ladezeit und Speicher. Zwar vermutlich nur mikroskopisch wenig, aber immerhin! ;-)&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Performance-Probleme ===&lt;br /&gt;
&lt;br /&gt;
Was man beim Script aber beachten sollte, sind eventuelle Engpässe. Das Script selbst ist relativ unkritisch. Die [[System-Makros]] allerdings erfordern bisweilen einige Verarbeitung durch OMSI, z.B. wenn irgendwelche Hofdateien durchsucht werden. Es ist hier also sinnvoll, möglichst sparsam mit System-Makros umzugehen.&lt;br /&gt;
&lt;br /&gt;
Außerdem erlaubt die Variable [[Refresh Strings|System- und vordefinierte lokalen Variablen]] ein gezieltes Aktualisieren von OMSI-Fonts am Fahrzeug (oder Szenerieobjekt): Dies sollte auch nur dann geschehen, wenn sich auch wirklich etwas geändert hat. Beim eigenen Fahrzeug ist das noch unkritisch, aber KI-Fahrzeuge sollten ihre Strings nur dann aktualisieren, wenn sich wirklich etwas ändert - z.B. die Matrix-Anzeige.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;br /&gt;
[[en:Guide to Performance-Friendly Vehicle Construction]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Boundingbox&amp;diff=929</id>
		<title>Boundingbox</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Boundingbox&amp;diff=929"/>
		<updated>2014-05-16T14:21:48Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Boundingbox wird in den geometrischen Grunddaten für die Konfigurierung eines Fahrzeugs benötigt.&lt;br /&gt;
&lt;br /&gt;
=Anwendung=&lt;br /&gt;
&lt;br /&gt;
Die Boundingbox wird unter dem Punkt &amp;quot;[boundingbox]&amp;quot; in der jeweiligen .bus oder .ovh-Datei eines Fahrzeugs eingetragen. Sie erstellt ein kubisches Kollisionsmodell um das Fahrzeug herum, das dafür sorgt, dass es mit der Szenerie und anderen Objekten zusammenstoßen kann.&lt;br /&gt;
&lt;br /&gt;
=Definition=&lt;br /&gt;
&lt;br /&gt;
Die Boundingbox setzt sich wie folgt zusammen:&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
&lt;br /&gt;
*Breite ohne Außenspiegel des zu simulierenden Fahrzeugs in m&lt;br /&gt;
*Länge des zu simulierenden Fahrzeugs in m&lt;br /&gt;
*Höhe des zu simulierenden Fahrzeugs in m&lt;br /&gt;
&lt;br /&gt;
==Vorgehensweise==&lt;br /&gt;
&lt;br /&gt;
Die Boundingbox besteht aus sechs Werten, die in je eine Zeile eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
#Breite&lt;br /&gt;
#Länge&lt;br /&gt;
#Höhe&lt;br /&gt;
#Abstand des Mittelpunkts der Boundingbox vom Nullpunkt des lokalen Koordinatensystems auf Breitenachse in m (x)&lt;br /&gt;
#Abstand des Mittelpunkts der Boundingbox vom Nullpunkt des lokalen Koordinatensystems auf Längsachse in m (y)&lt;br /&gt;
#Abstand des Mittelpunkts der Boundingbox vom Nullpunkt des lokalen Koordinatensystems auf Hochachse in m (z)&lt;br /&gt;
&lt;br /&gt;
=Hinweis!=&lt;br /&gt;
&lt;br /&gt;
Viele Maps weisen an Objektübergängen &amp;quot;unsichtbare Wände&amp;quot; auf, an denen vorwiegend tief liegende Fahrzeuge hängen bleiben. Um dies zu vermeiden, kann die Höhe von betroffenen Fahrzeugen um einen Meter reduziert und der Abstand der Box zum Nullpunkt um einen Meter auf der z-Achse erhöht werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;br /&gt;
[[en:Bounding Box]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=DISABLED-Befehl&amp;diff=928</id>
		<title>DISABLED-Befehl</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=DISABLED-Befehl&amp;diff=928"/>
		<updated>2014-05-16T14:19:44Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''OMSI-Version: 2.0''&lt;br /&gt;
&lt;br /&gt;
Die Befehle &amp;quot;-&amp;lt;DISABLED&amp;gt;-&amp;quot; und &amp;quot;-&amp;lt;ENABLED&amp;gt;-&amp;quot; sind in einigen Konfigurationsdateien erlaubt und dienen dem Auskommentieren mehrerer Zeilen, ohne dass die jeweiligen Schlüsselworte einzeln auskommentiert werden müssen.&lt;br /&gt;
&lt;br /&gt;
Die Anwendung erfolgt schlicht:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
{gültige Zeilen}&lt;br /&gt;
...&lt;br /&gt;
-&amp;lt;DISABLED&amp;gt;-&lt;br /&gt;
...&lt;br /&gt;
{auskommentierte Zeilen}&lt;br /&gt;
...&lt;br /&gt;
-&amp;lt;ENABLED&amp;gt;-&lt;br /&gt;
...&lt;br /&gt;
{gültige Zeilen}&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In folgenden Konfigurationsdateien kann dieser Befehl benutzt werden:&lt;br /&gt;
&lt;br /&gt;
*.bus, *.ovh, *.sco, *.hum, model.cfg, envir.cfg, passengercabin.cfg, path.cfg&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;br /&gt;
[[en:DISABLED-Command]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Kehrwert_des_minimalen_Lenkradius&amp;diff=927</id>
		<title>Kehrwert des minimalen Lenkradius</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Kehrwert_des_minimalen_Lenkradius&amp;diff=927"/>
		<updated>2014-05-16T14:17:51Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der Kehrwert des minimalen Lenkradius wird in den physikalischen Grunddaten für die Konfigurierung eines Fahrzeugs benötigt.&lt;br /&gt;
&lt;br /&gt;
=Anwendung=&lt;br /&gt;
&lt;br /&gt;
Der Kehrwert des minimalen Lenkradius wird unter dem Punkt &amp;quot;[inv_min_turnradius]&amp;quot; in der jeweiligen .bus oder .ovh-Datei eines Fahrzeugs eingetragen.&lt;br /&gt;
&lt;br /&gt;
=Berechnung=&lt;br /&gt;
&lt;br /&gt;
Der Kehrwert des minimalen Lenkradius ergibt sich wie folgt:&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
&lt;br /&gt;
*Radstand des zu simulierenden Fahrzeugs in m&lt;br /&gt;
*Wendekreis vom kurvenäußeren zum kurvenäußeren Rad des zu simulierenden Fahrzeugs in m&lt;br /&gt;
*Optional: Windows-Taschenrechner in der wissenschaftlichen Ansicht&lt;br /&gt;
&lt;br /&gt;
==Vorgehensweise==&lt;br /&gt;
&lt;br /&gt;
# (2 * Radstand) / Wendekreis = sin(maximaler Einschlagwinkel der Räder auf Lenkachse in °)&lt;br /&gt;
# tan(maximaler Einschlagwinkel der Räder auf Lenkachse in °) / Radstand&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;br /&gt;
[[en:Inverse of the Minimum Turning Radius]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Fahrzeugmasse&amp;diff=926</id>
		<title>Fahrzeugmasse</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Fahrzeugmasse&amp;diff=926"/>
		<updated>2014-05-16T14:13:36Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Masse eines Fahrzeugs wird für dessen korrekte Simulation benötigt. Dabei berechnet OMSI immer das aktuelle Gewicht aus dem in den physikalischen Grunddaten unter [mass] eingegebenen Leergewichts, sowie aller momentan beförderten Fahrgäste.&lt;br /&gt;
&lt;br /&gt;
Daher ist es wichtig beim Eintragen eines Wertes für [mass] nach Möglichkeit das &amp;quot;trockene&amp;quot; Leergewicht zu verwenden, also das Gewicht ohne Tankinhalt, Gepäck, Fahrgäste und natürlich den Fahrer selbst.&lt;br /&gt;
&lt;br /&gt;
Die Masse des Fahrzeugs wird in t angegeben.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;br /&gt;
[[en:Vehicle Mass]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Scriptsystem&amp;diff=925</id>
		<title>Scriptsystem</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Scriptsystem&amp;diff=925"/>
		<updated>2014-05-16T14:09:46Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''OMSI-Version: 1.0 - 2.0''&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Der hier beschriebene Stand des Scriptsystems entspricht OMSI Version 1.01.&lt;br /&gt;
&lt;br /&gt;
== Dateien des Scriptsystems ==&lt;br /&gt;
&lt;br /&gt;
Das Scriptsystem umfasst folgende Dateien:&lt;br /&gt;
&lt;br /&gt;
* Scriptdateien mit ausführbarem Code (*.osc)&lt;br /&gt;
* Varlist- und Stringvarlist-Dateien im OMSI\program-Verzeichnis zur Definition von Systemdateien und vordefinierten Dateien&lt;br /&gt;
* Varlist- und Stringvarlist-Dateien zur Definition von Uservariablen&lt;br /&gt;
* Constfile-Dateien zur Definition von Userkonstanten und Funktionstabellen&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Auf die Funktion der jeweiligen Dateien wird im Laufe der Beschreibung der Scriptsprache eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Grundlagen der Scriptsprache ==&lt;br /&gt;
&lt;br /&gt;
Das OMSI-Scriptsystem arbeitet mit der [http://de.wikipedia.org/wiki/Umgekehrte_Polnische_Notation umgekehrten Polnischen Notation]. Hierbei steht der Operator hinter den beiden Operanden; vereinfacht gesagt bedeutet es, dass die Operation &amp;quot; 1 + 2 &amp;quot; stattdessen folgendermaßen notiert wird: &amp;quot; 1 2 + &amp;quot;. Ein komplizierteres Beispiel: &amp;quot; (1 + 2) * (4 + 5) &amp;quot; entspricht &amp;quot; 1 2 + 4 5 + * &amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Ganz wichtig ist die Tatsache, dass die OMSI-Textdateien und insbesondere die Scriptsprache [http://de.wikipedia.org/wiki/Case_sensitivity Case-Sensitive] ist! D.h. es ist immer auf die Groß- und Kleinschreibung zu achten!&lt;br /&gt;
&lt;br /&gt;
=== Stack und Register ===&lt;br /&gt;
&lt;br /&gt;
Bei der Verarbeitung der Scripts verfügt OMSI über einen String-Stack und einen [http://de.wikipedia.org/wiki/Stapelspeicher Stack] für [http://de.wikipedia.org/wiki/Gleitkommazahl Gleitkommazahlen]. Im folgenden ist mit &amp;quot;Stack&amp;quot; immer der Stack für Gleitkommazahlen gemeint, andernfalls wird von &amp;quot;String-Stack&amp;quot; gesprochen.&lt;br /&gt;
&lt;br /&gt;
Beide Stacks enthält 8 Speicherplätze, welche von 0 bis 7 durchnumeriert sind. Jede Script-Operation kann nun einen oder mehrere neue Werte in einen der Stacks einfügen (push), wobei der neue Wert auf die Position 0 gesetzt wird und alle folgenden Werte &amp;quot;einen Platz aufrücken&amp;quot;, oder sie kann einen oder mehrere Werte aus dem Stack herausziehen (pop/pull) oder lediglich auslesen (peek).&lt;br /&gt;
&lt;br /&gt;
Fürs temporäre Ablegen von Zahlen gibt es zusätzlich acht indizierte Speicherplätze, welche direkt geschrieben oder gelesen werden können, die sich im sogenannten Register befinden - hier gibt es jedoch nur einen Register für die Gleitkommazahlen.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel-Operationen ===&lt;br /&gt;
&lt;br /&gt;
Beispiel: Die Operation 1 + 4. Der Code hierfür lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 4 +&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der folgenden Tabelle wird demonstriert, wie sich hierbei der Stack verhält:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Operation:	Stack:	0	1	2	3	4 ...&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
vorher:			0	0	0	0	0&lt;br /&gt;
&amp;quot;1&amp;quot;			1	0	0	0	0&lt;br /&gt;
&amp;quot;4&amp;quot;			4	1	0	0	0&lt;br /&gt;
&amp;quot;+&amp;quot;			5	0	0	0	0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Ausgangszustand ist der Stack nur mit Nullen (oder unbekannten/zufälligen Werten) gefüllt. Der Befehl &amp;quot;1&amp;quot; schiebt die Eins in den obersten Stackplatz und schiebt alle weiteren Werte (Nullen) nach hinten. Der Befehl &amp;quot;4&amp;quot; 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 &amp;quot;+&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
Ein zweites Beispiel:&lt;br /&gt;
&lt;br /&gt;
(1 + 2) * (4 + 5) muss wie bereits erwähnt folgendermaßen notiert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 2 + 4 5 + *&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Stack verhält sich somit folgendermaßen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Operation:	Stack:	0	1	2	3	4 ...&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
vorher:			0	0	0	0	0&lt;br /&gt;
&amp;quot;1&amp;quot;			1	0	0	0	0&lt;br /&gt;
&amp;quot;2&amp;quot;			2	1	0	0	0&lt;br /&gt;
&amp;quot;+&amp;quot;			3	0	0	0	0&lt;br /&gt;
&amp;quot;4&amp;quot;			4	3	0	0	0&lt;br /&gt;
&amp;quot;5&amp;quot;			5	4	3	0	0&lt;br /&gt;
&amp;quot;+&amp;quot;			9	3	0	0	0&lt;br /&gt;
&amp;quot;*&amp;quot;			27	0	0	0	0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am Ende befindet sich also das korrekte Ergebnis auf Stackplatz 0!&lt;br /&gt;
&lt;br /&gt;
=== Gleitkommazahlen und Strings ===&lt;br /&gt;
&lt;br /&gt;
Das OMSI-Skriptsystem arbeitet ausschließlich mit den Datentypen Gleitkommazahl (einfache Präzision mit Vorzeichen) und String. Beide Datentypen haben getrennte Stacks. Deshalb laufen die Verarbeitung von Gleitkommazahlen und Strings im Allgemeinen unabhängig nebeneinander. Jedoch kann es natürlich vorkommen, dass bestimmte Funktionen z.B. Zahlen in Strings umwandeln und somit gleichzeitig auf beide Teilbereiche zugreifen.&lt;br /&gt;
&lt;br /&gt;
Auf boolische Variablen wurde verzichtet. Für boolische Werte werden im Allgemeinen die Zahlenwerte 0 und 1 verwendet.&lt;br /&gt;
&lt;br /&gt;
== Script-Schlüsselwörter ==&lt;br /&gt;
&lt;br /&gt;
=== Kommentare ===&lt;br /&gt;
&lt;br /&gt;
Kommentierungen sind nur möglich, indem in der auszukommentierenden Zeile ganz vorne ein Apostroph ['] gesetzt wird:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'Ich bin eine Kommentarzeile&lt;br /&gt;
   'Ich bin KEINE Kommentarzeile!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einstiegs- und Ausstiegspunkte, Makros und Trigger ===&lt;br /&gt;
&lt;br /&gt;
Alle Befehle müssen zwischen einem Einstiegs- und einem Ausstiegspunkt liegen.&lt;br /&gt;
&lt;br /&gt;
Der Einstiegspunkt wird durch eins der folgenden Schlüsselwörter gekennzeichnet:&lt;br /&gt;
&lt;br /&gt;
* {frame} Im Laufe jedes Frames ruft OMSI über diesen Einstiegspunkt die frameweise Scriptverarbeitung auf, sofern er vorhanden ist.&lt;br /&gt;
* {init} Bei der Initialisierung ruft OMSI über diesen Einstiegspunkt die Script-Initialisierung auf.&lt;br /&gt;
* {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.&lt;br /&gt;
* {macro:''name''} Dieser Einstiegspunkt ruft ein Subsektion (Makro) auf, welche '''stets nach dem Aufruf''' definiert werden muss.&lt;br /&gt;
* {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.Ä.&lt;br /&gt;
&lt;br /&gt;
{end} ist der universelle Ausstiegspunkt. Er muss stets den Block abschließen, der mit einem der obigen Befehle eröffnet wird.&lt;br /&gt;
&lt;br /&gt;
==== Makroaufruf ====&lt;br /&gt;
&lt;br /&gt;
Der Aufruf eines Makros erfolgt über (M.L.''name''). Der Aufruf des Makros muss ''immer'' vor dessen Definition erfolgen. Andernfalls meldet OMSI, dass das Makro nicht gefunden wurde.&lt;br /&gt;
&lt;br /&gt;
==== Aufteilung des Scripts in mehrere Dateien ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&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:&lt;br /&gt;
&lt;br /&gt;
* 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.&lt;br /&gt;
* 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.&lt;br /&gt;
* Die Makros sollten sinnvollerweise folgendermaßen benannt werden: {macro:''subsystem''_frame} und {macro:''subsystem''_init}.&lt;br /&gt;
* 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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== Trigger ====&lt;br /&gt;
&lt;br /&gt;
Wie schon geschrieben wurde, kann ein {trigger:''name''}...{end}-Abschnitt durch verschiedene Möglichkeiten aus dem Hauptprogramm heraus aufgerufen werden. Hierzu zählen:&lt;br /&gt;
&lt;br /&gt;
* Auslösung per Tastatur. Wurde die Tastenkombination mit dem Namen ''tastkomb'' bezeichnet, wird {trigger:tastkomb} aufgerufen, wenn die Taste gedrückt wird und {trigger:tastkomb_off}, wenn die Taste losgelassen wird.&lt;br /&gt;
* Auslösung per Maus. Wurde ein Mesh angeklickt mit der [mouseevent]-Bezeichnung ''mouse_ev'', so wird {trigger:mouse_ev} aufgerufen, wenn die Maustaste gedrückt wird, {trigger:mouse_ev_drag}, während die Maustaste gehalten wird und {trigger:mouse_ev_off}, wenn die Maustaste losgelassen wird.&lt;br /&gt;
* Außerdem gibt es noch eine Reihe von [[System-Trigger|System-Triggern]].&lt;br /&gt;
&lt;br /&gt;
=== Operationen ===&lt;br /&gt;
&lt;br /&gt;
==== Stack-Operationen ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |%stackdump%&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Gibt eine Dialogbox mit dem Gleitkomma-Stackinhalt aus. Sollte deshalb natürlich nur zu Debug-Zwecken eingesetzt werden.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |s0, s1, ..., s7&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Speichern des aktuellen Stackwertes im durch die Ziffer angegebenen Register. Der Wert verbleibt hierbei im Stack&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |l0, l1, ..., l7&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Laden des entsprechenden Registerwertes und Verschiebung in den Stack. Registerwert bleibt erhalten.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |d&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Dubliziert den obersten Stackwert; alle weiteren Stackwerte rücken nach hinten.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$msg&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Schreibt den obersten String-Stack-Wert in die Debug-Zeile von OMSI - egal, ob es sich um ein User-, KI-Fahrzeug oder Szenerieobjekt handelt.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$d&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Dubliziert den Stringstack-Wert analog zu &amp;quot;d&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logische Operationen ====&lt;br /&gt;
&lt;br /&gt;
Die logischen Operationen arbeiten nach dem Prinzip 0 = FALSE, alles andere ist TRUE.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;amp;&amp;amp;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |UND, d.h. wenn einer der beiden obersten Stackwerte gleich 0 ist, ist das Ergbnis 0, sonst 1.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |ODER&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Verneinung&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Vergleichsoperationen ====&lt;br /&gt;
&lt;br /&gt;
Die Vergleichsoperationen vergleichen die Werte in den beiden jeweils obersten Stackplätzen und fügen dann je nach Ergebnis eine &amp;quot;1&amp;quot; oder &amp;quot;0&amp;quot; im obersten Stackplatz ein. Die Größer-/Kleinerzeichen stehen dabei entsprechend für der Reihenfolge, in der die Werte zuvor angegeben wurden. Das bedeutet:&lt;br /&gt;
&lt;br /&gt;
4 2 &amp;gt; ist wahr, weil die intern durchgeführte Operation in diesem Fall &amp;quot;4 &amp;gt; 2&amp;quot; ist.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;quot;1&amp;quot;, falls die obersten Stackwerte identisch sind, sonst &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;quot;1&amp;quot;, falls Stackwert 1 kleiner ist als Stackwert 0, sonst &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |... größer ist ...&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |... kleiner als oder gleich ist ...&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;gt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |... größer als oder gleich ist ...&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wie &amp;quot;=&amp;quot; nur für die obersten beiden Stringstack-Plätze.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;lt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Kleiner als (String). Die Ungleich-Operationen bei Strings prüfen auf alphabetische Reihenfolge. &amp;quot;A&amp;quot; ist also kleiner als &amp;quot;B&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Größer als (String).&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;lt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Kleiner oder gleich (String).&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;gt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Größer oder gleich (String).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Mathematische Operationen ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |+&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Plus&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Minus (Stackplatz 1 - Stackplatz 0, also vom Prinzip her wie bei den Größer/Kleiner-Operationen)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |*&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Mal&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |/&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |geteilt (Stackplatz 1 / Stackplatz 0)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |%&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rest der Division (folgendermaßen erweitert für Gleitkommazahlen: Stack0 - trunc(Stack1 / Stack0) * Stack1 )&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |/-/&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Vorzeichenwechsel&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sin&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Sinus&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |arcsin&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Umkehrfunktion zum Sinus ''(ab OMSI2)''&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |arctan&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Umkehrfunktion zum Tangens ''(ab OMSI2)''&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |min&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wahl des kleineren der beiden obersten Stackwerte&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |max&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wahl des größeren der beiden obersten Stackwerte&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |exp&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Exponentialfunktion zur Basis e (e^Stack0)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sqrt&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Quadratwurzel&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sqr&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Quadrat&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sgn&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rückgabe des Vorzeichens; je nachdem entweder -1, 0 oder 1&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |pi&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Kreiszahl pi&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |random&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |ganzzahlige Zufallszahl 0 &amp;lt;= x &amp;lt; Stack0&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |abs&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rückgabe des Absolutwertes&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |trunc&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Abrunden auf nächste ganze Zahl&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== String-Operationen ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;quot;''bla''&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Einfügen des Strings ''bla'' auf dem obersten String-Stack-Platz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$+&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Zusammenfügen zweier Strings. &amp;quot;Omnibus&amp;quot; &amp;quot;simulator&amp;quot; $+ ergibt &amp;quot;Omnibussimulator&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$*&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Der oberste Stack-String wird sooft wiederholt, bis die resultierende Zeichenlänger gerade noch kleiner oder gleich des obersten Stackwertes ist. Beispiel: &amp;quot;nu&amp;quot; 6 $* ergibt &amp;quot;nununu&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$length&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Gibt die Anzahl der Zeichen des obersten Stack-String zurück in den Stack. &lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$cutBegin&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Schneidet ''stack0'' Zeichen vorne vom obersten Stack-String ab.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$cutEnd&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Schneidet ''stack0'' Zeichen hinten vom obersten Stack-String ab.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$SetLengthR&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Passt die Länge des obersten Stack-Strings auf ''stack0'' rechtsbündig an, indem am Anfang Zeichen entfernt oder Leerzeichen ergänzt werden.&lt;br /&gt;
Achtung: Der Befehl entfernt den Float-Operator nicht vom Stack. Der Wert, auf dessen Länge der String gekürzt wurde, verbleibt also auf Stack0.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$SetLengthC&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Passt die Länge des obersten Stack-Strings auf ''stack0'' zentriert an, indem am Anfang und am Ende Zeichen entfernt oder Leerzeichen ergänzt werden ''(ab OMSI2)''.&lt;br /&gt;
Achtung: Der Befehl entfernt den Float-Operator nicht vom Stack. Der Wert, auf dessen Länge der String gekürzt wurde, verbleibt also auf Stack0.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$SetLengthL&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Passt die Länge des obersten Stack-Strings auf ''stack0'' linksbündig an, indem am Ende Zeichen entfernt oder Leerzeichen ergänzt werden.&lt;br /&gt;
Achtung: Der Befehl entfernt den Float-Operator nicht vom Stack. Der Wert, auf dessen Länge der String gekürzt wurde, verbleibt also auf Stack0.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$IntToStr&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rundet ''stack0'' ab und wandelt die resultierende Ganzzahl um in einen String.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$IntToStrEnh&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Die erweiterte Version von IntToStr. Hierbei wird der oberste Stack-String verwendet, um das Format der String-Umwandlung zu bestimmen: Das erste Zeichen im String wird zum Auffüllen der fehlenden Zeichen verwendet, die folgenden Zeichen müssen eine Zahl ergeben, die die Stellen angibt. Beispiel: 35 &amp;quot; 5&amp;quot; $IntToStrEnh führt zu &amp;quot;   35&amp;quot; und 123456789 &amp;quot;011&amp;quot; $IntToStrEnh führt zu &amp;quot;00123456789&amp;quot;. Falls ein Fehler vorliegt, wird &amp;quot;ERROR&amp;quot; ausgegeben.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$StrToFloat&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wandelt den obersten Stack-String in eine Gleitkommazahl um, falls möglich. Andernfalls wird eine -1 geschrieben.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$RemoveSpaces&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Entfernt sämtliche Leerzeichen vor und nach dem eigentlichen String. Aus &amp;quot;   Spandau Freudstr    &amp;quot; wird &amp;quot;Spandau Freudstr&amp;quot; ''(ab OMSI2)''.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Variablenzugriff ===&lt;br /&gt;
&lt;br /&gt;
Es wird unterschieden in Systemvariablen und in lokale Variablen. Die Systemvariablen gelten OMSI-weit, die lokalen Variablen werden zum Fahrzeug/Objekt zugehörig gespeichert.&lt;br /&gt;
&lt;br /&gt;
Bei den lokalen Variablen gibt es stets einen Grundstamm an Variablen, welcher von OMSI vordefiniert werden. Darüber hinaus können beliebig viele Variablen mit Hilfe der Varlist-Dateien ergänzt werden. Außerdem gibt es seit OMSI2 die Variante, dass man die Variable zwar selbst definieren muss, sie dann aber trotzdem mit einem OMSI-Internen Zustand verbunden wird (&amp;quot;on-demand-vordefinierte Variablen&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(L.S.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Lädt die Systemvariable ''varname'' in den obersten Stackplatz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(L.L.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Lädt die lokale Variable ''varname'' in den obersten Stackplatz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(L.$.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Lädt die lokale String-Variable ''varname'' in den obersten String-Stackplatz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(S.L.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Speichert den obersten Stackplatz in die lokale Variable ''varname''&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(S.$.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Speichert den obersten String-Stackplatz in die lokale String-Variable ''varname''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Eine detaillierte Beschreibung der einzelnen Systemvariablen und der vordefinierten lokalen Variablen finden Sie hier: [[System- und vordefinierte lokalen Variablen]]&lt;br /&gt;
&lt;br /&gt;
=== Konstanten und Funktionen ===&lt;br /&gt;
&lt;br /&gt;
Lokale Konstanten und [http://de.wikipedia.org/w/index.php?title=Datei:Linear_interpolation.svg&amp;amp;filetimestamp=20080226155013 stückweise definierte lineare Funktionen] können in den Konstantendateien (''constfiles'', ''~_constfile.txt'') definiert werden. Der Aufbau jeder Konstantendatei entspricht der der [[Konfigurationsdateien|Konfigurationsdatei]]. Es gibt lediglich drei Schlüsselwörter. Zu beachten ist: Bisher können keine Strings, sondern nur Fließkommazahlen als Konstanten definiert werden.&lt;br /&gt;
&lt;br /&gt;
[const] definiert eine neue Konstante und gibt ihren Wert an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[const]&lt;br /&gt;
name&lt;br /&gt;
wert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[const]&lt;br /&gt;
leistung&lt;br /&gt;
200&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[newcurve] leitet die Definition einer neuen (stückweise linearen) Funktion ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[newcurve]&lt;br /&gt;
name&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[pnt] fügt der zuvor mit [newcurve] definierten Funktion ein neues x-y-Paar hinzu. Jede Funktion sollte normalerweise über mindestens zwei Paare verfügen. Die Reihenfolge der Paare ''muss'' in x-Richtung aufsteigend sein!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[pnt]&lt;br /&gt;
x&lt;br /&gt;
y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[newcurve]&lt;br /&gt;
Drehzahl_Drehmoment_Kennlinie&lt;br /&gt;
&lt;br /&gt;
[pnt]&lt;br /&gt;
50&lt;br /&gt;
0&lt;br /&gt;
&lt;br /&gt;
[pnt]&lt;br /&gt;
300&lt;br /&gt;
400&lt;br /&gt;
&lt;br /&gt;
[pnt]&lt;br /&gt;
1000&lt;br /&gt;
600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Konstanten werden über den Befehl (C.L.''konstantenname'') in den Stack geladen.&lt;br /&gt;
&lt;br /&gt;
Funktionen werden über den Befehl (F.L.''funktionsname'') aufgerufen. Dabei wird stets der zuvor auf oberster Stackposition befindliche Wert als x-Parameter übergaben und der resultierende y-Wert der Funktion stattdessen auf dem obersten Stackplatz gespeichert. Bewegt sich der x-Wert außerhalb der Grenzen der durch die [pnt]-Einträge definierten Eckpunkte, wird stets der y-Wert des nächstliegenden Eckpunktes verwendet. Die Funktion wird also vor dem ersten und hinter dem letzten Eckpunkt ins Unendliche waagerecht verlängert.&lt;br /&gt;
&lt;br /&gt;
=== Sound-Trigger ===&lt;br /&gt;
&lt;br /&gt;
Soundtrigger sind nicht mit den weiter oben erwähnten Triggern zu verwechseln!&lt;br /&gt;
&lt;br /&gt;
Sie stellen vielmehr eine Möglichkeit dar, direkt einen gewünschten Sound abzuspielen. Hierbei gibt es zwei Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
(T.L.''soundtriggername'') ist ein einfacher Soundtrigger. Der so markierte Sound wird (einmalig) abgespielt.&lt;br /&gt;
&lt;br /&gt;
(T.F.''soundtriggername'') ist ein Soundtrigger mit Dateiwechselfunktion. Hierbei wird der oberste Stackstring ausgelesen und als Dateiname verwendet, wobei der Dateipfad relativ zum Sound-Ordner des Objektes interpretiert wird.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
Angenommen, die Sounddatei lautet &amp;quot;diese.wav&amp;quot; und ist mit dem Trigger ''MeinTrigger'' verknüpft, dann spielt&lt;br /&gt;
&lt;br /&gt;
 (T.L.MeinTrigger)&lt;br /&gt;
&lt;br /&gt;
die Datei &amp;quot;diese.wav&amp;quot; ab und&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;andere.wav&amp;quot; (T.F.MeinTrigger)&lt;br /&gt;
&lt;br /&gt;
die Datei &amp;quot;andere.wav&amp;quot;. Alternativ zu (T.L.''soundtriggername'') kann beim Befehl (T.F.''soundtriggername'') auch ein &amp;quot;Nullstring&amp;quot; im Stack liegen (also der String: &amp;quot;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== System-Makros ===&lt;br /&gt;
&lt;br /&gt;
Die bisherigen Methoden erlauben dem Script folgende Kommunikationsmöglichkeiten mit OMSI:&lt;br /&gt;
&lt;br /&gt;
* Lesen von Werten über System- und vordefinierte lokale Variablen&lt;br /&gt;
* Schreiben von Werten über ebendiese&lt;br /&gt;
* Empfangen von Tastatur-, Maus- oder Systemtriggern&lt;br /&gt;
&lt;br /&gt;
Schließlich gibt es noch eine weitere Methode, um mit dem Hauptprogramm zu kommunizieren, die sogenannten System-Makros, gelegentlich auch unpräzise als &amp;quot;Callback-Funktionen&amp;quot; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
In bestimmten Situationen ist es nötig, dass das Script Werte von OMSI bekommt, die in größeren Datenbanken vorliegen und daher nicht über vordefinierte Variablen übermittelt werden können, z.B. die Inhalte der Hofdatei. Hier kommen nun die System-Makros ins Spiel.&lt;br /&gt;
&lt;br /&gt;
Diese arbeiten scriptseitig sehr ähnlich wie die lokalen, selbstdefinierten Makros: Der Aufruf (M.V.''macroname'') ruft das System-Makro auf (&amp;quot;V&amp;quot; stand ursprünglich für &amp;quot;Vehicle-Macro&amp;quot;, gilt aber genauso auch in Szenerieobjekten), das sich während der Ausführung Werte aus den beiden Stacks holt und/oder in diese schreibt. Eine Aufstellung aller System-Makros findet sich hier: [[System-Makros]]&lt;br /&gt;
&lt;br /&gt;
=== Bedingungen und Schleifen ===&lt;br /&gt;
&lt;br /&gt;
Die einzige Steuerung des Programmablaufs ist zur Zeit nur mit der IF-Bedingung möglich.&lt;br /&gt;
&lt;br /&gt;
==== IF-Bedingung ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'Hier muss eine Bedingung stehen, z.B.:&lt;br /&gt;
    (L.L.bla) 1 =&lt;br /&gt;
    {if}&lt;br /&gt;
'Dieser Abschnitt wird ausgeführt, wenn bla = 1 ist:&lt;br /&gt;
        2 3 +&lt;br /&gt;
    {else}&lt;br /&gt;
'Dieser Abschnitt wird andernfalls ausgeführt:&lt;br /&gt;
        3 4 +&lt;br /&gt;
    {endif}&lt;br /&gt;
    (S.L.blub)&lt;br /&gt;
{end}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dass erst die Bedingung formuliert wird und dann erst das Schlüsselwort {if} folgt, sollte einleuchten: Zunächst muss an oberster Stelle des Stacks der Wert abgelegt werden und erst dann folgt das Schlüsselwort {if}, welches diesen Wert prüft. Hierbei bedeutet ähnlich wie bei &amp;amp;&amp;amp; und || Gleichheit mit Null gleichbedeutend mit ''False'', alle anderen Werte bedeuten ''True''.&lt;br /&gt;
&lt;br /&gt;
Wenn also im obigen Beispiel ''bla'' den Wert 1 hat, wird ''blub'' auf den Wert 5 gesetzt, andernfalls auf den Wert 7.&lt;br /&gt;
&lt;br /&gt;
Verschachtelungen der IF-Bedingung dienen als Ersatz für die (nicht vorhandenen) &amp;quot;Else-If&amp;quot;-Konstruktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'Hier muss eine Bedingung stehen, z.B.:&lt;br /&gt;
    (L.L.bla) 1 =&lt;br /&gt;
    {if}&lt;br /&gt;
'Dieser Abschnitt wird ausgeführt, wenn bla = 1 ist:&lt;br /&gt;
        2 3 +&lt;br /&gt;
    {else}&lt;br /&gt;
    (L.L.bla) 5 =&lt;br /&gt;
    {if}&lt;br /&gt;
'Dieser Abschnitt wird ausgeführt, wenn bla = 5 ist:&lt;br /&gt;
        3 4 +&lt;br /&gt;
    {else}&lt;br /&gt;
'Dieser Abschnitt wird andernfalls ausgeführt:&lt;br /&gt;
        13&lt;br /&gt;
    {endif}&lt;br /&gt;
    {endif}&lt;br /&gt;
    (S.L.blub)&lt;br /&gt;
{end}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei ist insbesondere auf das doppelte {endif} zu achten! Hier gilt:&lt;br /&gt;
&lt;br /&gt;
* bla = 1 ==&amp;gt; blub = 5&lt;br /&gt;
* bla = 5 ==&amp;gt; blub = 7&lt;br /&gt;
* sonst   ==&amp;gt; blub = 13&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;br /&gt;
[[en:Scripting System]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Scriptsystem&amp;diff=924</id>
		<title>Scriptsystem</title>
		<link rel="alternate" type="text/html" href="http://wiki.omnibussimulator.de/omsiwikineu.de/index.php?title=Scriptsystem&amp;diff=924"/>
		<updated>2014-05-16T14:08:43Z</updated>

		<summary type="html">&lt;p&gt;Faaabiii: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''OMSI-Version: 1.0 - 2.0''&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Der hier beschriebene Stand des Scriptsystems entspricht OMSI Version 1.01.&lt;br /&gt;
&lt;br /&gt;
== Dateien des Scriptsystems ==&lt;br /&gt;
&lt;br /&gt;
Das Scriptsystem umfasst folgende Dateien:&lt;br /&gt;
&lt;br /&gt;
* Scriptdateien mit ausführbarem Code (*.osc)&lt;br /&gt;
* Varlist- und Stringvarlist-Dateien im OMSI\program-Verzeichnis zur Definition von Systemdateien und vordefinierten Dateien&lt;br /&gt;
* Varlist- und Stringvarlist-Dateien zur Definition von Uservariablen&lt;br /&gt;
* Constfile-Dateien zur Definition von Userkonstanten und Funktionstabellen&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Auf die Funktion der jeweiligen Dateien wird im Laufe der Beschreibung der Scriptsprache eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Grundlagen der Scriptsprache ==&lt;br /&gt;
&lt;br /&gt;
Das OMSI-Scriptsystem arbeitet mit der [http://de.wikipedia.org/wiki/Umgekehrte_Polnische_Notation umgekehrten Polnischen Notation]. Hierbei steht der Operator hinter den beiden Operanden; vereinfacht gesagt bedeutet es, dass die Operation &amp;quot; 1 + 2 &amp;quot; stattdessen folgendermaßen notiert wird: &amp;quot; 1 2 + &amp;quot;. Ein komplizierteres Beispiel: &amp;quot; (1 + 2) * (4 + 5) &amp;quot; entspricht &amp;quot; 1 2 + 4 5 + * &amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Ganz wichtig ist die Tatsache, dass die OMSI-Textdateien und insbesondere die Scriptsprache [http://de.wikipedia.org/wiki/Case_sensitivity Case-Sensitive] ist! D.h. es ist immer auf die Groß- und Kleinschreibung zu achten!&lt;br /&gt;
&lt;br /&gt;
=== Stack und Register ===&lt;br /&gt;
&lt;br /&gt;
Bei der Verarbeitung der Scripts verfügt OMSI über einen String-Stack und einen [http://de.wikipedia.org/wiki/Stapelspeicher Stack] für [http://de.wikipedia.org/wiki/Gleitkommazahl Gleitkommazahlen]. Im folgenden ist mit &amp;quot;Stack&amp;quot; immer der Stack für Gleitkommazahlen gemeint, andernfalls wird von &amp;quot;String-Stack&amp;quot; gesprochen.&lt;br /&gt;
&lt;br /&gt;
Beide Stacks enthält 8 Speicherplätze, welche von 0 bis 7 durchnumeriert sind. Jede Script-Operation kann nun einen oder mehrere neue Werte in einen der Stacks einfügen (push), wobei der neue Wert auf die Position 0 gesetzt wird und alle folgenden Werte &amp;quot;einen Platz aufrücken&amp;quot;, oder sie kann einen oder mehrere Werte aus dem Stack herausziehen (pop/pull) oder lediglich auslesen (peek).&lt;br /&gt;
&lt;br /&gt;
Fürs temporäre Ablegen von Zahlen gibt es zusätzlich acht indizierte Speicherplätze, welche direkt geschrieben oder gelesen werden können, die sich im sogenannten Register befinden - hier gibt es jedoch nur einen Register für die Gleitkommazahlen.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel-Operationen ===&lt;br /&gt;
&lt;br /&gt;
Beispiel: Die Operation 1 + 4. Der Code hierfür lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 4 +&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der folgenden Tabelle wird demonstriert, wie sich hierbei der Stack verhält:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Operation:	Stack:	0	1	2	3	4 ...&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
vorher:			0	0	0	0	0&lt;br /&gt;
&amp;quot;1&amp;quot;			1	0	0	0	0&lt;br /&gt;
&amp;quot;4&amp;quot;			4	1	0	0	0&lt;br /&gt;
&amp;quot;+&amp;quot;			5	0	0	0	0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Ausgangszustand ist der Stack nur mit Nullen (oder unbekannten/zufälligen Werten) gefüllt. Der Befehl &amp;quot;1&amp;quot; schiebt die Eins in den obersten Stackplatz und schiebt alle weiteren Werte (Nullen) nach hinten. Der Befehl &amp;quot;4&amp;quot; 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 &amp;quot;+&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
Ein zweites Beispiel:&lt;br /&gt;
&lt;br /&gt;
(1 + 2) * (4 + 5) muss wie bereits erwähnt folgendermaßen notiert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 2 + 4 5 + *&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Stack verhält sich somit folgendermaßen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Operation:	Stack:	0	1	2	3	4 ...&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
vorher:			0	0	0	0	0&lt;br /&gt;
&amp;quot;1&amp;quot;			1	0	0	0	0&lt;br /&gt;
&amp;quot;2&amp;quot;			2	1	0	0	0&lt;br /&gt;
&amp;quot;+&amp;quot;			3	0	0	0	0&lt;br /&gt;
&amp;quot;4&amp;quot;			4	3	0	0	0&lt;br /&gt;
&amp;quot;5&amp;quot;			5	4	3	0	0&lt;br /&gt;
&amp;quot;+&amp;quot;			9	3	0	0	0&lt;br /&gt;
&amp;quot;*&amp;quot;			27	0	0	0	0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am Ende befindet sich also das korrekte Ergebnis auf Stackplatz 0!&lt;br /&gt;
&lt;br /&gt;
=== Gleitkommazahlen und Strings ===&lt;br /&gt;
&lt;br /&gt;
Das OMSI-Skriptsystem arbeitet ausschließlich mit den Datentypen Gleitkommazahl (einfache Präzision mit Vorzeichen) und String. Beide Datentypen haben getrennte Stacks. Deshalb laufen die Verarbeitung von Gleitkommazahlen und Strings im Allgemeinen unabhängig nebeneinander. Jedoch kann es natürlich vorkommen, dass bestimmte Funktionen z.B. Zahlen in Strings umwandeln und somit gleichzeitig auf beide Teilbereiche zugreifen.&lt;br /&gt;
&lt;br /&gt;
Auf boolische Variablen wurde verzichtet. Für boolische Werte werden im Allgemeinen die Zahlenwerte 0 und 1 verwendet.&lt;br /&gt;
&lt;br /&gt;
== Script-Schlüsselwörter ==&lt;br /&gt;
&lt;br /&gt;
=== Kommentare ===&lt;br /&gt;
&lt;br /&gt;
Kommentierungen sind nur möglich, indem in der auszukommentierenden Zeile ganz vorne ein Apostroph ['] gesetzt wird:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'Ich bin eine Kommentarzeile&lt;br /&gt;
   'Ich bin KEINE Kommentarzeile!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einstiegs- und Ausstiegspunkte, Makros und Trigger ===&lt;br /&gt;
&lt;br /&gt;
Alle Befehle müssen zwischen einem Einstiegs- und einem Ausstiegspunkt liegen.&lt;br /&gt;
&lt;br /&gt;
Der Einstiegspunkt wird durch eins der folgenden Schlüsselwörter gekennzeichnet:&lt;br /&gt;
&lt;br /&gt;
* {frame} Im Laufe jedes Frames ruft OMSI über diesen Einstiegspunkt die frameweise Scriptverarbeitung auf, sofern er vorhanden ist.&lt;br /&gt;
* {init} Bei der Initialisierung ruft OMSI über diesen Einstiegspunkt die Script-Initialisierung auf.&lt;br /&gt;
* {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.&lt;br /&gt;
* {macro:''name''} Dieser Einstiegspunkt ruft ein Subsektion (Makro) auf, welche '''stets nach dem Aufruf''' definiert werden muss.&lt;br /&gt;
* {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.Ä.&lt;br /&gt;
&lt;br /&gt;
{end} ist der universelle Ausstiegspunkt. Er muss stets den Block abschließen, der mit einem der obigen Befehle eröffnet wird.&lt;br /&gt;
&lt;br /&gt;
==== Makroaufruf ====&lt;br /&gt;
&lt;br /&gt;
Der Aufruf eines Makros erfolgt über (M.L.''name''). Der Aufruf des Makros muss ''immer'' vor dessen Definition erfolgen. Andernfalls meldet OMSI, dass das Makro nicht gefunden wurde.&lt;br /&gt;
&lt;br /&gt;
==== Aufteilung des Scripts in mehrere Dateien ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&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:&lt;br /&gt;
&lt;br /&gt;
* 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.&lt;br /&gt;
* 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.&lt;br /&gt;
* Die Makros sollten sinnvollerweise folgendermaßen benannt werden: {macro:''subsystem''_frame} und {macro:''subsystem''_init}.&lt;br /&gt;
* 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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== Trigger ====&lt;br /&gt;
&lt;br /&gt;
Wie schon geschrieben wurde, kann ein {trigger:''name''}...{end}-Abschnitt durch verschiedene Möglichkeiten aus dem Hauptprogramm heraus aufgerufen werden. Hierzu zählen:&lt;br /&gt;
&lt;br /&gt;
* Auslösung per Tastatur. Wurde die Tastenkombination mit dem Namen ''tastkomb'' bezeichnet, wird {trigger:tastkomb} aufgerufen, wenn die Taste gedrückt wird und {trigger:tastkomb_off}, wenn die Taste losgelassen wird.&lt;br /&gt;
* Auslösung per Maus. Wurde ein Mesh angeklickt mit der [mouseevent]-Bezeichnung ''mouse_ev'', so wird {trigger:mouse_ev} aufgerufen, wenn die Maustaste gedrückt wird, {trigger:mouse_ev_drag}, während die Maustaste gehalten wird und {trigger:mouse_ev_off}, wenn die Maustaste losgelassen wird.&lt;br /&gt;
* Außerdem gibt es noch eine Reihe von [[System-Trigger|System-Triggern]].&lt;br /&gt;
&lt;br /&gt;
=== Operationen ===&lt;br /&gt;
&lt;br /&gt;
==== Stack-Operationen ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |%stackdump%&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Gibt eine Dialogbox mit dem Gleitkomma-Stackinhalt aus. Sollte deshalb natürlich nur zu Debug-Zwecken eingesetzt werden.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |s0, s1, ..., s7&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Speichern des aktuellen Stackwertes im durch die Ziffer angegebenen Register. Der Wert verbleibt hierbei im Stack&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |l0, l1, ..., l7&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Laden des entsprechenden Registerwertes und Verschiebung in den Stack. Registerwert bleibt erhalten.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |d&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Dubliziert den obersten Stackwert; alle weiteren Stackwerte rücken nach hinten.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$msg&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Schreibt den obersten String-Stack-Wert in die Debug-Zeile von OMSI - egal, ob es sich um ein User-, KI-Fahrzeug oder Szenerieobjekt handelt.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$d&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Dubliziert den Stringstack-Wert analog zu &amp;quot;d&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logische Operationen ====&lt;br /&gt;
&lt;br /&gt;
Die logischen Operationen arbeiten nach dem Prinzip 0 = FALSE, alles andere ist TRUE.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;amp;&amp;amp;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |UND, d.h. wenn einer der beiden obersten Stackwerte gleich 0 ist, ist das Ergbnis 0, sonst 1.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |ODER&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Verneinung&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Vergleichsoperationen ====&lt;br /&gt;
&lt;br /&gt;
Die Vergleichsoperationen vergleichen die Werte in den beiden jeweils obersten Stackplätzen und fügen dann je nach Ergebnis eine &amp;quot;1&amp;quot; oder &amp;quot;0&amp;quot; im obersten Stackplatz ein. Die Größer-/Kleinerzeichen stehen dabei entsprechend für der Reihenfolge, in der die Werte zuvor angegeben wurden. Das bedeutet:&lt;br /&gt;
&lt;br /&gt;
4 2 &amp;gt; ist wahr, weil die intern durchgeführte Operation in diesem Fall &amp;quot;4 &amp;gt; 2&amp;quot; ist.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;quot;1&amp;quot;, falls die obersten Stackwerte identisch sind, sonst &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;quot;1&amp;quot;, falls Stackwert 1 kleiner ist als Stackwert 0, sonst &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |... größer ist ...&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;lt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |... kleiner als oder gleich ist ...&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;gt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |... größer als oder gleich ist ...&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wie &amp;quot;=&amp;quot; nur für die obersten beiden Stringstack-Plätze.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;lt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Kleiner als (String). Die Ungleich-Operationen bei Strings prüfen auf alphabetische Reihenfolge. &amp;quot;A&amp;quot; ist also kleiner als &amp;quot;B&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;gt;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Größer als (String).&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;lt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Kleiner oder gleich (String).&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$&amp;gt;=&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Größer oder gleich (String).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Mathematische Operationen ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |+&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Plus&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Minus (Stackplatz 1 - Stackplatz 0, also vom Prinzip her wie bei den Größer/Kleiner-Operationen)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |*&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Mal&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |/&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |geteilt (Stackplatz 1 / Stackplatz 0)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |%&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rest der Division (folgendermaßen erweitert für Gleitkommazahlen: Stack0 - trunc(Stack1 / Stack0) * Stack1 )&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |/-/&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Vorzeichenwechsel&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sin&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Sinus&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |arcsin&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Umkehrfunktion zum Sinus ''(ab OMSI2)''&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |arctan&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Umkehrfunktion zum Tangens ''(ab OMSI2)''&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |min&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wahl des kleineren der beiden obersten Stackwerte&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |max&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wahl des größeren der beiden obersten Stackwerte&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |exp&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Exponentialfunktion zur Basis e (e^Stack0)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sqrt&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Quadratwurzel&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sqr&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Quadrat&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |sgn&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rückgabe des Vorzeichens; je nachdem entweder -1, 0 oder 1&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |pi&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Kreiszahl pi&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |random&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |ganzzahlige Zufallszahl 0 &amp;lt;= x &amp;lt; Stack0&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |abs&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rückgabe des Absolutwertes&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |trunc&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Abrunden auf nächste ganze Zahl&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== String-Operationen ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&amp;quot;''bla''&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Einfügen des Strings ''bla'' auf dem obersten String-Stack-Platz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$+&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Zusammenfügen zweier Strings. &amp;quot;Omnibus&amp;quot; &amp;quot;simulator&amp;quot; $+ ergibt &amp;quot;Omnibussimulator&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$*&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Der oberste Stack-String wird sooft wiederholt, bis die resultierende Zeichenlänger gerade noch kleiner oder gleich des obersten Stackwertes ist. Beispiel: &amp;quot;nu&amp;quot; 6 $* ergibt &amp;quot;nununu&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$length&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Gibt die Anzahl der Zeichen des obersten Stack-String zurück in den Stack. &lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$cutBegin&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Schneidet ''stack0'' Zeichen vorne vom obersten Stack-String ab.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$cutEnd&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Schneidet ''stack0'' Zeichen hinten vom obersten Stack-String ab.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$SetLengthR&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Passt die Länge des obersten Stack-Strings auf ''stack0'' rechtsbündig an, indem am Anfang Zeichen entfernt oder Leerzeichen ergänzt werden.&lt;br /&gt;
Achtung: Der Befehl entfernt den Float-Operator nicht vom Stack. Der Wert, auf dessen Länge der String gekürzt wurde, verbleibt also auf Stack0.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$SetLengthC&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Passt die Länge des obersten Stack-Strings auf ''stack0'' zentriert an, indem am Anfang und am Ende Zeichen entfernt oder Leerzeichen ergänzt werden ''(ab OMSI2)''.&lt;br /&gt;
Achtung: Der Befehl entfernt den Float-Operator nicht vom Stack. Der Wert, auf dessen Länge der String gekürzt wurde, verbleibt also auf Stack0.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$SetLengthL&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Passt die Länge des obersten Stack-Strings auf ''stack0'' linksbündig an, indem am Ende Zeichen entfernt oder Leerzeichen ergänzt werden.&lt;br /&gt;
Achtung: Der Befehl entfernt den Float-Operator nicht vom Stack. Der Wert, auf dessen Länge der String gekürzt wurde, verbleibt also auf Stack0.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$IntToStr&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Rundet ''stack0'' ab und wandelt die resultierende Ganzzahl um in einen String.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$IntToStrEnh&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Die erweiterte Version von IntToStr. Hierbei wird der oberste Stack-String verwendet, um das Format der String-Umwandlung zu bestimmen: Das erste Zeichen im String wird zum Auffüllen der fehlenden Zeichen verwendet, die folgenden Zeichen müssen eine Zahl ergeben, die die Stellen angibt. Beispiel: 35 &amp;quot; 5&amp;quot; $IntToStrEnh führt zu &amp;quot;   35&amp;quot; und 123456789 &amp;quot;011&amp;quot; $IntToStrEnh führt zu &amp;quot;00123456789&amp;quot;. Falls ein Fehler vorliegt, wird &amp;quot;ERROR&amp;quot; ausgegeben.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$StrToFloat&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Wandelt den obersten Stack-String in eine Gleitkommazahl um, falls möglich. Andernfalls wird eine -1 geschrieben.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |$RemoveSpaces&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Entfernt sämtliche Leerzeichen vor und nach dem eigentlichen String. Aus &amp;quot;   Spandau Freudstr    &amp;quot; wird &amp;quot;Spandau Freudstr&amp;quot; ''(ab OMSI2)''.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Variablenzugriff ===&lt;br /&gt;
&lt;br /&gt;
Es wird unterschieden in Systemvariablen und in lokale Variablen. Die Systemvariablen gelten OMSI-weit, die lokalen Variablen werden zum Fahrzeug/Objekt zugehörig gespeichert.&lt;br /&gt;
&lt;br /&gt;
Bei den lokalen Variablen gibt es stets einen Grundstamm an Variablen, welcher von OMSI vordefiniert werden. Darüber hinaus können beliebig viele Variablen mit Hilfe der Varlist-Dateien ergänzt werden. Außerdem gibt es seit OMSI2 die Variante, dass man die Variable zwar selbst definieren muss, sie dann aber trotzdem mit einem OMSI-Internen Zustand verbunden wird (&amp;quot;on-demand-vordefinierte Variablen&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;font-size:95%;&amp;quot;  &lt;br /&gt;
|- class=&amp;quot;hintergrundfarbe5&amp;quot;&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(L.S.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Lädt die Systemvariable ''varname'' in den obersten Stackplatz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(L.L.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Lädt die lokale Variable ''varname'' in den obersten Stackplatz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(L.$.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Lädt die lokale String-Variable ''varname'' in den obersten String-Stackplatz&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(S.L.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Speichert den obersten Stackplatz in die lokale Variable ''varname''&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |(S.$.''varname'')&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |Speichert den obersten String-Stackplatz in die lokale String-Variable ''varname''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Eine detaillierte Beschreibung der einzelnen Systemvariablen und der vordefinierten lokalen Variablen finden Sie hier: [[System- und vordefinierte lokalen Variablen]]&lt;br /&gt;
&lt;br /&gt;
=== Konstanten und Funktionen ===&lt;br /&gt;
&lt;br /&gt;
Lokale Konstanten und [http://de.wikipedia.org/w/index.php?title=Datei:Linear_interpolation.svg&amp;amp;filetimestamp=20080226155013 stückweise definierte lineare Funktionen] können in den Konstantendateien (''constfiles'', ''~_constfile.txt'') definiert werden. Der Aufbau jeder Konstantendatei entspricht der der [[Konfigurationsdateien|Konfigurationsdatei]]. Es gibt lediglich drei Schlüsselwörter. Zu beachten ist: Bisher können keine Strings, sondern nur Fließkommazahlen als Konstanten definiert werden.&lt;br /&gt;
&lt;br /&gt;
[const] definiert eine neue Konstante und gibt ihren Wert an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[const]&lt;br /&gt;
name&lt;br /&gt;
wert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[const]&lt;br /&gt;
leistung&lt;br /&gt;
200&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[newcurve] leitet die Definition einer neuen (stückweise linearen) Funktion ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[newcurve]&lt;br /&gt;
name&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[pnt] fügt der zuvor mit [newcurve] definierten Funktion ein neues x-y-Paar hinzu. Jede Funktion sollte normalerweise über mindestens zwei Paare verfügen. Die Reihenfolge der Paare ''muss'' in x-Richtung aufsteigend sein!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[pnt]&lt;br /&gt;
x&lt;br /&gt;
y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[newcurve]&lt;br /&gt;
Drehzahl_Drehmoment_Kennlinie&lt;br /&gt;
&lt;br /&gt;
[pnt]&lt;br /&gt;
50&lt;br /&gt;
0&lt;br /&gt;
&lt;br /&gt;
[pnt]&lt;br /&gt;
300&lt;br /&gt;
400&lt;br /&gt;
&lt;br /&gt;
[pnt]&lt;br /&gt;
1000&lt;br /&gt;
600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Konstanten werden über den Befehl (C.L.''konstantenname'') in den Stack geladen.&lt;br /&gt;
&lt;br /&gt;
Funktionen werden über den Befehl (F.L.''funktionsname'') aufgerufen. Dabei wird stets der zuvor auf oberster Stackposition befindliche Wert als x-Parameter übergaben und der resultierende y-Wert der Funktion stattdessen auf dem obersten Stackplatz gespeichert. Bewegt sich der x-Wert außerhalb der Grenzen der durch die [pnt]-Einträge definierten Eckpunkte, wird stets der y-Wert des nächstliegenden Eckpunktes verwendet. Die Funktion wird also vor dem ersten und hinter dem letzten Eckpunkt ins Unendliche waagerecht verlängert.&lt;br /&gt;
&lt;br /&gt;
=== Sound-Trigger ===&lt;br /&gt;
&lt;br /&gt;
Soundtrigger sind nicht mit den weiter oben erwähnten Triggern zu verwechseln!&lt;br /&gt;
&lt;br /&gt;
Sie stellen vielmehr eine Möglichkeit dar, direkt einen gewünschten Sound abzuspielen. Hierbei gibt es zwei Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
(T.L.''soundtriggername'') ist ein einfacher Soundtrigger. Der so markierte Sound wird (einmalig) abgespielt.&lt;br /&gt;
&lt;br /&gt;
(T.F.''soundtriggername'') ist ein Soundtrigger mit Dateiwechselfunktion. Hierbei wird der oberste Stackstring ausgelesen und als Dateiname verwendet, wobei der Dateipfad relativ zum Sound-Ordner des Objektes interpretiert wird.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
Angenommen, die Sounddatei lautet &amp;quot;diese.wav&amp;quot; und ist mit dem Trigger ''MeinTrigger'' verknüpft, dann spielt&lt;br /&gt;
&lt;br /&gt;
 (T.L.MeinTrigger)&lt;br /&gt;
&lt;br /&gt;
die Datei &amp;quot;diese.wav&amp;quot; ab und&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;andere.wav&amp;quot; (T.F.MeinTrigger)&lt;br /&gt;
&lt;br /&gt;
die Datei &amp;quot;andere.wav&amp;quot;. Alternativ zu (T.L.''soundtriggername'') kann beim Befehl (T.F.''soundtriggername'') auch ein &amp;quot;Nullstring&amp;quot; im Stack liegen (also der String: &amp;quot;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== System-Makros ===&lt;br /&gt;
&lt;br /&gt;
Die bisherigen Methoden erlauben dem Script folgende Kommunikationsmöglichkeiten mit OMSI:&lt;br /&gt;
&lt;br /&gt;
* Lesen von Werten über System- und vordefinierte lokale Variablen&lt;br /&gt;
* Schreiben von Werten über ebendiese&lt;br /&gt;
* Empfangen von Tastatur-, Maus- oder Systemtriggern&lt;br /&gt;
&lt;br /&gt;
Schließlich gibt es noch eine weitere Methode, um mit dem Hauptprogramm zu kommunizieren, die sogenannten System-Makros, gelegentlich auch unpräzise als &amp;quot;Callback-Funktionen&amp;quot; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
In bestimmten Situationen ist es nötig, dass das Script Werte von OMSI bekommt, die in größeren Datenbanken vorliegen und daher nicht über vordefinierte Variablen übermittelt werden können, z.B. die Inhalte der Hofdatei. Hier kommen nun die System-Makros ins Spiel.&lt;br /&gt;
&lt;br /&gt;
Diese arbeiten scriptseitig sehr ähnlich wie die lokalen, selbstdefinierten Makros: Der Aufruf (M.V.''macroname'') ruft das System-Makro auf (&amp;quot;V&amp;quot; stand ursprünglich für &amp;quot;Vehicle-Macro&amp;quot;, gilt aber genauso auch in Szenerieobjekten), das sich während der Ausführung Werte aus den beiden Stacks holt und/oder in diese schreibt. Eine Aufstellung aller System-Makros findet sich hier: [[System-Makros]]&lt;br /&gt;
&lt;br /&gt;
=== Bedingungen und Schleifen ===&lt;br /&gt;
&lt;br /&gt;
Die einzige Steuerung des Programmablaufs ist zur Zeit nur mit der IF-Bedingung möglich.&lt;br /&gt;
&lt;br /&gt;
==== IF-Bedingung ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'Hier muss eine Bedingung stehen, z.B.:&lt;br /&gt;
    (L.L.bla) 1 =&lt;br /&gt;
    {if}&lt;br /&gt;
'Dieser Abschnitt wird ausgeführt, wenn bla = 1 ist:&lt;br /&gt;
        2 3 +&lt;br /&gt;
    {else}&lt;br /&gt;
'Dieser Abschnitt wird andernfalls ausgeführt:&lt;br /&gt;
        3 4 +&lt;br /&gt;
    {endif}&lt;br /&gt;
    (S.L.blub)&lt;br /&gt;
{end}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dass erst die Bedingung formuliert wird und dann erst das Schlüsselwort {if} folgt, sollte einleuchten: Zunächst muss an oberster Stelle des Stacks der Wert abgelegt werden und erst dann folgt das Schlüsselwort {if}, welches diesen Wert prüft. Hierbei bedeutet ähnlich wie bei &amp;amp;&amp;amp; und || Gleichheit mit Null gleichbedeutend mit ''False'', alle anderen Werte bedeuten ''True''.&lt;br /&gt;
&lt;br /&gt;
Wenn also im obigen Beispiel ''bla'' den Wert 1 hat, wird ''blub'' auf den Wert 5 gesetzt, andernfalls auf den Wert 7.&lt;br /&gt;
&lt;br /&gt;
Verschachtelungen der IF-Bedingung dienen als Ersatz für die (nicht vorhandenen) &amp;quot;Else-If&amp;quot;-Konstruktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'Hier muss eine Bedingung stehen, z.B.:&lt;br /&gt;
    (L.L.bla) 1 =&lt;br /&gt;
    {if}&lt;br /&gt;
'Dieser Abschnitt wird ausgeführt, wenn bla = 1 ist:&lt;br /&gt;
        2 3 +&lt;br /&gt;
    {else}&lt;br /&gt;
    (L.L.bla) 5 =&lt;br /&gt;
    {if}&lt;br /&gt;
'Dieser Abschnitt wird ausgeführt, wenn bla = 5 ist:&lt;br /&gt;
        3 4 +&lt;br /&gt;
    {else}&lt;br /&gt;
'Dieser Abschnitt wird andernfalls ausgeführt:&lt;br /&gt;
        13&lt;br /&gt;
    {endif}&lt;br /&gt;
    {endif}&lt;br /&gt;
    (S.L.blub)&lt;br /&gt;
{end}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei ist insbesondere auf das doppelte {endif} zu achten! Hier gilt:&lt;br /&gt;
&lt;br /&gt;
* bla = 1 ==&amp;gt; blub = 5&lt;br /&gt;
* bla = 5 ==&amp;gt; blub = 7&lt;br /&gt;
* sonst   ==&amp;gt; blub = 13&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Nachschlagewerk für Addon-Entwickler]]&lt;/div&gt;</summary>
		<author><name>Faaabiii</name></author>
		
	</entry>
</feed>