Darkstar One Modding

Zuletzt aktualisiert am: 24.09.2019


ModdingGuide

Darkstar One Modding Guide v2.7

Inhalt

  1. Voraussetzung für das Modden von Darkstar One
  2. Darkstar One Modding-Möglichkeiten
  3. Vorbereitungen und Beispiel-Mod
    1. Die Tutorial-Mod
    2. Die Datei "darkstarmod.ini"
    3. Das Mod-Verzeichnis
  4. Inifiles
    1. Sternensysteme
    2. Planeten
    3. Cluster
    4. Frachter und Frachterdefinitionen
    5. Die restlichen Dateien
  5. Eigene Texte
  6. Eigene Sounds
    1. Abspielen von Soundeffekten
    2. Erzeugen der Datenbankdatei
  7. Skriptsystem
    1. Allgemeines über Skriptfunktionen
    2. Logische Untergruppen der Skriptfunktionen
    3. Aufbau eines Skriptes
    4. Die Transitionstabelle
    5. Die Funktionsparameter V und Data
    6. Ablauf eines Skriptes
    7. Skriptevents
    8. Skripttypen
    9. Beispielskript
    10. Weitere Beispiele
    11. Nützliche Erweiterungen
    12. Skripttools
    13. Der Skript-Debugger
    14. Breakpoints
    15. Variablen, Stack und Co.
    16. Skriptcompiler
  8. Ändern der 3D-Objekte
    1. Verzeichnisstrukturen
    2. Allgemeine Vorgehensweise
    3. Aufbau der XML-Szenendateien
    4. Objekttypen
    5. AVCMesh
    6. Level of Detail und AVCLODSelector
    7. Der X File Converter
    8. Blendercompiler
    9. Blender Beispiel (simple_blender)
  9. Weitere Tools
  10. Wie man das Containermodell ersetzt (Beispiel)
  11. Weitergabe von Mods
  12. Nützliche Links

Ein allgemeiner Hinweis zu diesem Modding Guide:
Im Hauptmenü kann durch Anklicken des Ordnersymbols oder des zugehörigen Textes ebenfalls eine Hilfeseite mit vielen Infos geöffnet werden.

1 - Voraussetzung für das Modden von Darkstar One

Modden wird erst ab der Darkstar One Version 1.2 unterstützt, ein entsprechender Patch ist frei u.a. im Supernature-Forum : Gameplay FAQ unter "Wo finde ich das Modding Tool?" in der aktuellsten und letzten Version 1.3 erhältlich. Dieser Patch wird aber mittlerweile nur noch für alte und ungepatchte DVDs benötigt. Neuere Ausgaben wie die vom Publisher Kalypso Media (Purple Hills), enthalten ihn bereits. Bei diesen DVD-Ausgaben darf der Patch keinesfalls mehr nachinstalliert werden, damit würde auch der inzwischen entfernte Kopierschutz wieder mit installiert und das Spiel startet dadurch nicht mehr. Die Versionsnummer wird im Hauptmenü unten links angezeigt.

Aufzug

2 - Darkstar One Modding-Möglichkeiten

Da sind sie also – die Modding-Tools für eurer Lieblingsspiel. Trotz aller Freude gibt es einige Dinge zu beachten: Modding ist kein Kinderspiel, man braucht so einiges an Kenntnissen, seien es programmiertechnische oder künstlerische.

Leider war Darkstar One nicht darauf ausgelegt, Veränderungen von außen zu unterstützen. Alle Möglichkeiten des Moddens wurden nachträglich eingepflegt und sind auf Grund dessen teilweise nicht ganz einfach zu verwenden.

Trotzdem ist es mit den hier vorgestellten Tools und Kurzanleitungen möglich, Darkstar One ganz nach seinen Wünschen anzupassen. Eigene Missionen, mehr Sternensysteme oder eigene Schiffsmodelle sind mit etwas Aufwand und Engagement kein Problem.

Es stehen folgende Möglichkeiten zur Verfügung, um DSO zu modden:

  • Missionen
    Es können eigene Missionen geschrieben werden, die entweder am Terminal angeboten werden oder nach bestimmten Bedingungen automatisch im All starten, sobald man ein bestimmtes Sonnensystem betritt. Sogar neue Sidequests lassen sich mit den entsprechenden Kenntnissen programmieren. Dafür sind möglichst fortgeschrittene Kenntnisse in der Skriptsprache Lua erforderlich, die sich jedoch relativ leicht erlernen lässt. Eigene Missionen können auch eigene Texte, neue Sprachdateien und Sounds enthalten.

  • Ini-Dateien
    Alle verfügbaren Konfigurations-Dateien (*.ini) können geändert werden. Dies beeinflusst unter anderem:

    • Aufbau der Sonnensysteme
    • Handelssystem
    • Parameter für Schiffe, Waffen, Ausrüstung usw.
    • Sound und Textzuweisungen im GUI
    • Upgradesystem

  • Grafik
    Vorhandene 3D-Modelle (Objekte) und Texturen können ausgetauscht bzw. geändert werden. Achtung: Neue Objekte können nicht eingefügt werden. Als Objektformat werden im Moment nur Dateien im X-Format unterstützt; hierfür gibt es einen Konverter in das Darkstar-eigene Format. Mehr dazu im Kapitel Ändern der 3D-Objekte.

Aufzug

3 - Vorbereitungen und Beispiel-Mod

Alle Modifikationen müssen sich an ein festes Verzeichnisschema halten, das hier näher erläutert wird.
Version 1.3 von Darkstar One legt im Ordner "Eigene Dateien\Ascaron Entertainment\Darkstar One\" einen "Customization"-Unterordner an. Dort muss jede Mod in ein eigenes Verzeichnis gespeichert werden, wobei der Verzeichnisname frei wählbar ist. Nach korrekter Installation der Mod kann sie im Hauptmenü von DSO unter "Mods" ausgewählt werden. Der Name der Mod wird in der Datei "darkstarmod.ini" festgelegt, die zu jeder Mod gehört (siehe unten). Der Mod-Name hat nichts mit dem Verzeichnisnamen zu tun und kann unabhängig von ihm frei gewählt werden.

Aufzug

3.1 - Die Tutorial-Mod

Die Mod-Tools installieren eine Beispielmodifikation in den Ordner "Tutorial" unter "Eigene Dateien\Ascaron Entertainment\Darkstar One\Customization".
"Tutorial" enthält eine vollständige Modifikation inklusive aller Dateien, die verwendet wurden. Alle Beispiele und Erklärungen in diesem Modding-Guide beziehen sich auf Inhalte des Modding-Tutorials. Auf diese Weise eignet sich die Mod "Tutorial" sehr gut als Referenz für eigene Mods.

Aufzug

3.2 - Die Datei "darkstarmod.ini"

Jede Mod hat eine "darkstarmod.ini"-Datei, die wie folgt aufgebaut ist:

[darkstarmod]
mod_name = <Name der Modifikation>
mod_desc = <Kurze, einzeilige Beschreibung> (ca. 350 Zeichen max.)

Der Name und die Beschreibung werden innerhalb des Auswahlmenüs für Modifikationen angezeigt.

Aufzug

3.3 - Das Mod-Verzeichnis

Ein Modverzeichnis hat folgenden Aufbau:
  • Eigene Dateien\Ascaron Entertainment\Darkstar One\Customization\<Ordnername der Mod>
    • \3DView - Falls dieser Ordner existiert, befinden sich darin die selbst erstellten 3D-Modelle.
    • \inifiles - Wenn dieser Ordner existiert, dann müssen alle .ini-Dateien vorhanden sein.
      (Bei Neuerstellung einer Mod einfach aus dem "ds_3dadd.cpr" extrahieren, falls man daran etwas ändern möchte.)
    • \save - Alle gespeicherten Spielstände dieser Mod.
    • \scripts - Hier finden sich alle selbst erstellten .lua-Dateien bzw. kompilierten Dateien.
    • \sound - Alle Sounddateien (vorzugsweise mp3) kommen hier rein.
    • \staticImages - Falls dieser Ordner existiert, befinden sich darin die geänderten .dds-Grafiken aus dem "ds_interface.cpr".
    • \strings - Die Ressourcendatei "user_strings.res" und die Quelldatei "user_strings.xml" für neue Texte befinden sich in diesem Verzeichnis.

Für 3-D-Daten gibt es weiterhin eine Zipdatei mit dem Namen "user_data.zip". Wie diese Datei dann genau aufgebaut ist, wird im Kapitel "3D" erläutert. Das Fehlen von Verzeichnissen oder Dateien beeinflusst das Spiel nur insofern, dass die Originaldateien verwendet werden. Bestes Beispiel hierfür sind die .ini-Dateien; fehlen diese in der Mod, so werden die ursprünglichen Darkstar One-Dateien geladen. Die Beispielmodifikation verwendet mehrere Möglichkeiten, das Spiel zu verändern.

Wichtiger Hinweis: Um die Kompatibilität der Savegames zu gewährleisten, speichert jede Modifikation ihre eigenen Spielstände. Speichert man, während Mod "A" geladen ist, so ist dieser Speicherstand ausschließlich für diese Modifikation "A" verfügbar. Es werden auch nur zu dieser Mod passende Spielstände angezeigt. Es sollten auch keine Spielstände aus dem Originalspiel oder einer anderen Mod in den Save-Ordner kopiert und gestartet werden. Das kann zu undefinierbaren Zuständen bis hin zum Absturz führen.

Aufzug

4 - Inifiles

Die komplette Spiellogik (Sternensysteme, Handelslogik) erhält ihre Startwerte aus Textdateien. Bei Programmstart werden diese eingelesen und bei Bedarf eine neue Binärdatei erstellt. Viele Dateien haben Abhängigkeiten untereinander (Anzahl der Sternensysteme in Clustern usw.). Diese Abhängigkeiten werden gesondert erwähnt, sofern vorhanden.
Soll nun für eine Modifikation diese Logik angepasst werden, müssen zunächst alle notwendigen Dateien in das "inifiles"-Verzeichnis der Mod kopiert werden. Die Quellen hierzu befinden sich in dem Archiv "ds_3dadd.cpr". Einfach in "ds_3dadd.zip" umbenennen, entpacken und die Dateien kopieren.

Im Folgenden ein kurzer Abriss, welche Teile der Logik sich in welchen Dateien befinden.

Erstellen einer BIN Datei
Alle INI-Dateien werden bei Spielstart geladen und in einer Binärdatei namens "ini_file.bin" gespeichert. Ändert man nun Einstellungen an den Konfigurationsdateien, so muss diese Binärdatei gelöscht werden, sie wird dann beim nächsten Programmstart wieder automatisch neu erzeugt. Danach wird aus Geschwindigkeitsgründen nur noch diese Binärdatei geladen.

Achtung: Es müssen wirklich alle Dateien kopiert werden.
Fehlen ein oder mehrere davon, kann keine funktionierende BIN-Datei erstellt werden.

Aufzug

4.1 - Sternsysteme

Es darf maximal 403 Sternsysteme in Darkstar One geben. Definiert sind sie in der Datei "StarSystem.ini", durchnummeriert von 0 bis 402. Jedes System besteht aus folgenden Attributen:
  • Artefakt: >0, wenn in diesem System ein Artefakt vorhanden ist
  • Bedroht: >0, wenn das System von Piraten besetzt ist
  • Bürger: Anzahl der Einwohner in Milliarden
  • Cluster: Nummer des Clusters, in dem sich das System befindet
  • EnergyLevel: Je höher der Level, desto mehr "Schwebteilchen" befinden sich im Raum
  • Faction: Zu welcher Fraktion das System gehört (0=Galaktische Union, 1=Rebellen, 2=Neutral)
  • Function_X1/2/3 und Function_Y: Definieren die Parameter für die Handelssimulation
  • NachbarRegel: Bereich von Systemen, die betreten werden müssen, um dieses System sichtbar zu machen
  • Piratengang: Index der Piratengang (0-46; 65535 wenn keine Piratengang vorhanden ist)
  • Planeten: Anzahl der Planeten im System ("Planets.ini")
  • PosX, PosY: Position auf der Sternenkarte in Lichtjahren, 0/0 liegt links oben
  • Produktion1-5: Welche Waren werden in diesem System produziert (Exportwaren)
  • Produktionsfaktor: wie der Name schon sagt, Faktor von 0.0 bis 1.0
  • Regierung: Regierungsform (0=Demokratie, 1=Diktatur, 2=Staatenbund, 3=Anarchie, 4=Konzern, 5=Monarchie)
  • Sichtbarkeitstyp: Auf welche Weise das System freigeschaltet wird (0=Spielstart, 2=Nachbarsystem betreten, 4=von der Story, 6=niemals, 7=System ist versteckt)
  • StarLightId: Die Systembelichtung spiegelt die Systemsicherheit wider, die sich aus der Regierungsform ergibt (Anarchien sind unsicher und haben ein bedrohlicheres, rötlicheres Lichtsetting; Demokratien hingegen sind sicherer und haben ein freundlicheres, helleres Setting) und verweist auf die Einträge in der "StarLight.ini" (dort werden die Lichtsettings für die Systeme beschrieben)
  • UniqueItem: >0, wenn ein Unique Item versteckt ist

Aufzug

4.2 - Planeten

Jedes System besteht aus einer festgelegten Anzahl an Objekten, die aus ein bis drei Sonnen, ein oder mehreren Planeten, Monden, Asteroiden, Meteoritenfeldern, Dekorationen (z. B. Schiffswracks) und Stationen bestehen, plus ein Sprungtor.
Die Parameter in der "Planets.ini":
  • [Globals]
    Planetenanzahl = 5970 ; Die Anzahl der Objektdaten in dieser Ini-Datei (alle Sektionen, nicht nur Planeten!)
    Sternenanzahl = 403 ; Die Anzahl der Sternensysteme, für die in dieser Ini-Datei Planeten gespeichert sind

  • [Planet000_000]
    Model = 3 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
    Orbitart = Sonne ; Name der Art dieses Orbiters
    Position = 464831.531250 / 1936431.875000 / 499874.875000 ; die X-, Y- und Z-Koordinaten in Metern
    Radius = 20000.000000 ; Radius in Metern ( 1m = 1 tausendstel Unit )
    RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
    SystemId = 0 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
    UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

  • ...

  • [Planet402_009]
    ...

Aufzug

4.3 - Cluster

Jeder Cluster im Spiel hat eine entsprechende Konfigurationsdatei (clusternnn.ini) und besteht aus drei Punkten:
  • Anzahl der Frachter
  • Definition der Frachter
  • Produktionsangaben der im Cluster "enthaltenen" Waren

Aufzug

4.4 - Frachter und Frachterdefinitionen

Eine Frachterdefinition ist folgendermaßen aufgebaut:
  • ein Startsystem
  • ein Zielsystem
  • der Frachtertyp
  • Anzahl der mitgeführten Waren
  • Warentypen und deren Menge
Auf diese Weise werden alle Frachter in einem Cluster definiert. Es ist nicht unbedingt zu empfehlen, diese Dateien von Hand zu ändern. Für Darkstar One geschah die Startverteilung automatisch.
Zusätzlich zu den Frachtern wird für jedes im Cluster befindliche System die Warenmenge definiert. Für jede der 24 im Spiel enthaltenen Warenarten wird die Menge angegeben.

Aufzug

4.5 - Die restlichen Dateien

Die Dateien sind alle kommentiert und teilen sich grob in folgende Bereiche auf:
  • Spielerschiff: Afterburners.ini, Engines.ini, Equipment.ini, Thrusters.ini, Upgrades.ini, StarFlight.ini
  • Handel: Goods.ini, Prices.ini
  • Objekte: Meteorids.ini, TradeStation.ini, StarShip.ini
  • Bewegung (allgemein): StarFlight.ini
  • Simulation: Time.ini, HitPoint.ini
  • Effekte: Projectiles.ini, Explosion.ini, ExplosionDef.ini

Aufzug

5 - Eigene Texte

Um eigene Skripte und Missionen zu erstellen, wird man nicht daran vorbeikommen, eigene Texte zu verfassen. Darkstar One verwendet hierfür ein eigenes Ressourcenformat, um Lokalisierungen zu vereinfachen. Intern verwendet Darkstar sogenannte StringIDs, es ist daher unumgänglich, selbst solche IDs zu erstellen. Hierfür kann Microsoft Excel (ab Office 2003) oder der kostenlose XML Notepad 2007 verwendet werden. In der ersten Spalte der Excel-Tabelle wird die StringID eingetragen, rechts davon der eigentliche Text. Über diese ID ist der Text dann später im Spiel verfügbar. Die Exceldatei muss als XML-Arbeitsblatt gespeichert werden (kann Excel bis 2002 nicht). Im Tutorialmod ist diese Datei als Beispiel noch vorhanden.

Um die Texte nun endgültig im Spiel zu verwenden, muss diese XML-Datei noch konvertiert werden. Hierfür findet sich im "Tools"-Ordner ein Programm namens "Xml2ResConverter.exe". Dort müssen nun drei Dateien angegeben werden: Die originale global.res-Datei von Darkstar One (um Konflikte mit StringIDs zu vermeiden, dennoch können in der global.res vorhandene StringIDs in der XML-Datei neu definiert werden), die XML-Datei sowie die Zieldatei "user_strings.res". Die Zieldatei muss dann in das entsprechende Verzeichnis der Mod kopiert werden. Aus Geschwindigkeitsgründen wird nur diese Ressoucendatei vom Spiel beim Programmstart eingelesen. Während des Konvertiervorgangs muss die Datei in Excel geschlossen sein, sonst schlägt die Konvertierung fehl. In anderen Bearbeitungsprogrammen (Notepad++, XML Notepad, usw.) kann sie ggf. geöffnet bleiben, einfach ausprobieren.

Zur schnellen und bequemen Konvertierung empfiehlt es sich, eine Verknüpfung auf dem Desktop mit folgendem Inhalt anzulegen:
(mit Anführungszeichen, Pfad dem eigenen Dateisystem entsprechend anpassen)
  • Ziel:
    "C:\Darkstar One\Modding\Tools\Xml2ResConverter.exe" "C:\Benutzer\Name\Eigene Dokumente\Ascaron Entertainment\Darkstar One\Customization\global.res" user_strings.xml user_strings.res
  • Ausführen in:
    "C:\Benutzer\Name\Eigene Dokumente\Ascaron Entertainment\Darkstar One\Customization\Mod-Name\strings"

    Die originale global.res-Datei sollte dafür aus dem Archiv "ds_interface.cpr", Ordner "\strings\DEU" oder für die englische Version "\strings\ENG", einmalig in den Customization-Ordner extrahiert werden.

    Das war es dann auch schon, die Texte stehen über ihre StringIDs allen Missionen zur Verfügung. Soll nun ein Text an einer bestimmten Stelle im Skript verwendet werden, wird er einfach über die StringID angegeben.
    Beispiel: NGUI.ShowInfoText( { Text = "IDM_MEINE_ERSTE_STRING_ID" } )

    Aufzug

    6 - Eigene Sounds

    Für die Verwendung in Missionsskripten können auch eigene Sounddateien in die Modifikationen eingebunden werden. Ähnlich wie bei den Texten werden Dateien nicht direkt mit dem Dateinamen angesprochen, sondern über eine ID. Diese IDs werden jedoch nicht von Hand vergeben, sondern aus der Struktur der Verzeichnisse und Dateinamen erzeugt. Im "Sound" Ordner der Modifikation sollten zunächst einmal Unterordner für die drei Hauptgruppen "(stream)", "(sfx2d)" und "(sfx3d)" erstellt werden. Die Namen der Unterordner sind inklusive der Klammerung zu übernehmen.

    Stream - Dateien in dieser Hauptgruppe werden als Stream abgespielt. Hier sollten Musikstücke abgelegt werden.
    2d - In diesem Ordner liegen einfache Stereoeffekte.
    3d - Ordner für dreidimensionale Effekte.

    In jeder dieser Hauptgruppen können neue Untergruppen erstellt werden, indem man neue Verzeichnisse erstellt, die jeweils mit "grp_<Gruppenname>" benannt werden.

    Aufzug

    6.1 - Abspielen von Soundeffekten

    Wurde mit Hilfe des "KlangKollektor" Tools die entsprechende Datenbankdatei erstellt, so stehen alle Effekte und Musikstücke zur Verwendung in Skripten bereit. Über die erstellten Gruppen hat der Skriptprogrammierer Zugriff auf die IDs der Effekte. Abspielen lassen sie sich über den Befehl "NSound.PlayUserSound". Als Parameter dienen die Gruppen (nicht die Hauptgruppen) ohne den Präfix "grp_". Liegt der Soundeffekt in "(sfx2d)\grp_Gruppe\grp_Untergruppe\sound.mp3", so lautet der Aufruf wie folgt:
      NSound.PlayUserSound( { File = "Gruppe.Untergruppe.sound" } )
    für den speziellen Sound, oder
      NSound.PlayUserSound( { File = "Gruppe.Untergruppe" } )
    für einen Sound aus der Gruppe. Wird kein spezieller Effekt angegeben, so wird ein Element der Gruppe zufällig ausgewählt.

    Aufzug

    6.2 - Erzeugen der Datenbankdatei

    Mit Hilfe des "KlangKollektor" Tools läßt sich nun aus der Verzeichnisstruktur zusammen mit den .asset Dateien eine "user_sounds.xml" erzeugen. Diese Datei wird dann bei Spielstart eingelesen, registriert alle Dateien mit ihren eindeutigen Namen und stellt diese dem Skriptprogrammierer zur Verfügung. Aufruf:
      KlangKollektor.exe -o user_sounds.xml sound

    Aufzug

    7 - Skriptsystem

    Darkstar One verwendet für Missionen ein LUA-basiertes Skriptsystem (Lua Version 4.1.0) mit geringfügigen Anpassungen.
    ( Siehe Lua 5.1 Reference Manual von der Webseite http://www.lua.org )

    Alle Skripte (Missionen, auch Storymissionen) setzen auf ein zustandsbasiertes System auf. Statt für jedes auftretende Event eine entsprechende Funktion zu implementieren, werden so genannte Transitions definiert, die entsprechend dem aktuellen 'Step' der Mission aktiv sind. Somit können Skripte in chronologischem Missionsablauf geschrieben werden, was das Verständnis eines Skriptes wesentlich erleichtert.

    Grundvoraussetzung für das Schreiben von Skripten ist ein solides Maß an LUA-Kenntnissen, insbesondere der Tabellen. Allgemeine Programmierkenntnisse sind sicherlich auch von Vorteil.

    Hier im ModdingGuide wird nur auf die Grundlagen des Systems eingegangen, ausführliche Beschreibungen der verfügbaren Skriptbefehle befinden sich unter dem Menüpunkt Commands dieser Dokumentation.

    Aufzug

    7.1 - Allgemeines über Skriptfunktionen

    WICHTIG: In den Skripts wird bei der Syntax zwischen Groß- und Kleinschreibung unterschieden! Das wird oftmals leicht übersehen und man sucht sich dumm und dämlich, um den Fehler zu finden. Beachtet man das nicht, liefern die Funktionen keine oder falsche Ergebnisse oder produzieren einen Laufzeitfehler. In vielen Fällen stürzt dadurch Darkstar oder sogar der Rechner ab. Beispiel:

    -- FALSCH
NGUI.ShowInfotext( { Text = "ID_STRINGID", replace = { "ID_1", "ID_2" } } )
         ^-Absturz			   ^-unbekannter Parameter, wird einfach nicht ausgeführt
-- RICHTIG
NGUI.ShowInfoText( { Text = "ID_STRINGID", Replace = { "ID_1", "ID_2" } } )
    Dies hier sind trotz scheinbar gleichen Namen zwei ganz unterschiedliche Funktionen:
    MissionLib.der_Gefangene_floh = function()
    return "Knastbruder macht die Fliege"
end

MissionLib.der_gefangene_Floh = function()
    return "Das arme Tierchen"
end
    Selbstgeschriebene Funktionen und Skriptbibliotheken (MissionLib.lua, usw.): Den Funktionen übergebene Parameter werden innerhalb der Funktion als lokale Variablen behandelt. Siehe auch im Lua 5.1 Reference Manual unter Variables, Function Definitions und Visibility Rules. Ändert man also den Wert einer übergebenen Variablen in der Funktion, so wird nicht die ursprüngliche Variable verändert, sondern behält ihren Wert. Dies gilt selbst dann, wenn bereits eine gleichnamige globale Variable definiert wurde. Das hat den Vorteil, dass man einem übergebenen Parameter in der Funktion einen neuen Wert zuweisen darf, ohne ihn vorher einer lokal definierten Variablen zuweisen zu müssen (im Gegensatz z.B. zu VB-Script). Beispiel:
    VarTest = function( Value )
    Value = Value * 2
    return Value
end

local var1 = 15
local var2 = VarTest( var1 )
    Hier behält die Variable "var1" ihren Wert von 15 während "var2" den berechneten Wert von 30 enthält (bei VB-Script enthielte "var1" jetzt ebenfalls den Wert 30).
    Etwas anders ist das bei übergebenen Tabellen. Einfaches Beispiel:
    TableTest = function( Table )
    -- Table = { 30 }  -- Das darf man nicht machen, da "Table" ein Zeiger und kein Wert ist!
    Table[2] = 45
    Table[3] = 60
end

local Tabelle = { 15, 20 }
TableTest( Tabelle )

-- Ergebnis: Tabelle = { 15, 45, 60 }
    "Table" (ohne Index) ist ein Zeiger und kein Wert und darf daher nicht in der Funktion verändert werden, sonst schlagen weitere Wertzuweisungen fehl! Fragt man nun den Inhalt der Tabelle ab, dann liefert "Tabelle[1]" weiterhin den Wert 15. "Tabelle[2]" hingegen enthält nun den zugewiesenen Wert von 45 anstatt dem vorherigen Wert 20 und Tabelle[3] den neu hinzugefügten Wert 60. Siehe hierzu als praktisches Beispiel auch den Quellcode der Funktion "MissionLib.AppendToTable".
    Wie man sieht, wurde hier die übergebene Tabelle direkt geändert. Möchte man das nicht, so muss in diesem Fall die Tabellenvariable zunächst einer lokalen Variablen zugewiesen werden, die dann nach Belieben geändert werden kann. Zum Schluss wird sie dann mit dem "return"-Befehl als Ergebnis zurückgegeben. Beispiel:
    TableTest = function( Table )
    local result = Table
    result[2] = 45
    result[3] = 60
    return result
end

local Tabelle = { 15, 20 }
local newTable = TableTest( Tabelle )

-- Ergebnis: "Tabelle" hat sich nicht verändert, newTable = { 15, 45, 60 }

    Globale Variablen können an jeder beliebigen Stelle definiert werden, also auch innerhalb von Funktionen, Blöcken und Kontrollstrukturen, was aber möglichst vermieden werden sollte. Besser ist es, sie in der skriptglobalen Tabelle V (siehe 7.5) einzubinden. Sie gelten ab dem Zeitpunkt des ersten Aufrufs für das gesamte Skript.
    Achtung: Globale Variablen, die innerhalb einer Funktion gesetzt und initialisiert werden und sich weder in der GLOBALS-Tabelle noch an übergeordneter Stelle befinden (wie z. B. in Funktionsbibliotheken, der Options.lua oder in Skripts vor dem Aufruf von NScript.Register), sind nach dem Neuladen eines Spielstands wieder weg, da sie nicht erneut initialisiert werden! Wenn es also notwendig ist, dass eine dynamisch erzeugte Variable auch später von allen Skripts gelesen und geändert werden soll, dann muss man sie in die GLOBALS-Tabelle eintragen!
    Die Tabelle GLOBALS: Hier werden alle dynamischen Variablen eingetragen, die auch später noch von allen Skripts und zu jeder Zeit gelesen und/oder bearbeitet werden sollen. Die Tabelle wird sehr häufig für die Datenübergabe an nachfolgende Missionen genutzt.
    Konstanten: Echte Konstanten, die nur gelesen werden können, gibt es in Lua leider nicht. Alles, was hier als Konstante bezeichnet wird, ist tatsächlich eine globale Variable, die natürlich wieder mit einem anderen Wert überschrieben werden kann. Um das weithehend zu vermeiden, sind diese Variablen durch generelle Großschreibung besonders hervorgehoben. Was aber nicht heißt, dass alle großgeschriebene Variablen nur zum Lesen da sind. Es gibt ein paar vom System festgelegte Tabellen, bei denen lediglich eine besonders große Vorsicht beim Ändern notwendig ist.
    Vorsicht mit globalen Variablen, die in den Missions-Skripts vor dem Aufruf von "NScript.Register" definiert werden: Es ist dabei vollkommen unerheblich, in welchem Skript sie enthalten sind, sie lassen sich immer auch von allen anderen Skripts im selben Verzeichnis lesen und verändern! Die Skripts mit diesen globalen Variablen müssen dazu nicht per source-Anweisung importiert worden sein, wenn sie sich im selben Verzeichnis befinden. Außerdem sind vom Skript geänderte Wertzuweisungen dieser Variablen nach dem Neuladen eines Spielstands wieder weg und wurden mit ihrem ursprünglichen Wert frisch initialisiert! Sollen solche Variablen nur für das eine Skript global gültig sein, in welchem sie definiert wurden, müssen sie mit local definiert werden. Aber auch hier greift die Zurücksetzung auf den Ursprungswert beim Laden eines Spielstands! Um diese local-Variablen innerhalb von Funktionen lesen und verändern zu können (ändern geht nur in Tabellen), muss ihnen ein Prozentzeichen vorangestellt werden. Dasselbe gilt analog auch für Funktionen. Beispiel:

    Meine_Var = "Das ist eine globale Variable, die überall gilt."

-- Lokale Funktion, gilt nur für dieses Skript global:
local KayronMessage = function( V, Message )
    return NComm.AddMessage( {
        Text = Message,
        Actor = "kayron",
        Sender = V.Player
    } ).Message
end

-- Lokale Variable, gilt auch nur für dieses Skript global:
local kayron = { spoken = false }

NScript.Register( {
    Name  = "BAR_XYZ",
    Group = 0,
    Type  = MTYPE_BAR,
    Transitions = {

{   -- Kayron sagt was
    1, 1, "Timer", function( V, Data )
    if Data.Timer == V.Timer then
        if not %kayron.spoken then
            V.Comm = %KayronMessage( V, "IDM_BAR_XYZ_RADIO_KAYRON" )
            %kayron.spoken = true
        end
    end
end },

    Sollten dennoch echte globale Variablen benötigt werden (in der MissionLibEx.lua z. B. gibt es jede Menge davon), müssen sie vor der endgültigen Definition unbedingt daraufhin geprüft werden, ob sie schon vorhanden sind. Es existieren nämlich einige undokumentierte Variablen im System, die für eine korrekte Funktion des Spiels extrem wichtig sind!

    Hinweis: In den ursprüngliche Skriptbibliotheken wurden diese Punkte teilweise nicht bedacht. In den hier vorliegenden und überarbeiteten Fassungen wurden u.a. alle überflüssigen globalen und lokalen Variablen entfernt.

    Aufzug

    7.2 - Logische Untergruppen der Skriptfunktionen

    Alle Funktionen des Skriptsystems sind in logische Untergruppen gegliedert, die jeweils in ihren eigenen Namespaces leben.
    Konkret sind das folgende Gruppen:
    NCamera | Kameras für Ingame-Cutscenes
    NCanyon | Kabro-Canyon, Waffenfabrik und S'kaa-Mutterschiff
    NComm | Dialogsystem, Funksprüche etc.
    NContainer | Funktionen, die Container und ihre Fracht betreffen
    NDebug | Funktionen für den Skript-Debugger. Wegen Abschaltung des Online-Frontends sinnlos geworden.
    NGame | Spielsteuerung
    NGroupAi | KI-Gruppen
    NGUI | Grafische Benutzerschnittstelle (Texte anzeigen usw.)
    NMission | Missionsspezifische Funktionen
    NNPC | Non-Player Character (Bar Missionen)
    NObject | Objekte allgemein
    NPlayer | Alles, was den Spieler und sein Schiff betrifft
    NScript | Allgemeine Skriptfunktionen
    NShip | Raumschiffe allgemein
    NSound | Musikalische Funktionen, Soundeffekte
    NStarSystem | Funktionen zur Arbeit mit den Sternsystemen
    NStory | Spielfortschritt
    NTerminal | Nachrichten im Terminal
    NTutorial | Buttons und Popups (Namespace existiert in Darkstar One 1.3 nicht)
    NVector | Vektor-Berechnungen
    NWaypoint | Wegpunktsystem
    NWing | Funktionen, die Wings (Raumschiffgruppen) betreffen

    Alle Gruppen enthalten Erzeugungsfunktionen für die jeweilige Gruppe und eine Vielzahl von Zusatzfunktionen. Jeder Namespace, der im Skript verwendet wird, muss vorher importiert werden (siehe Beispielskript). Alle Funktionen folgen einem einheitlichen Schema: Jeder Funktion wird genau ein Parameter übergeben, die Parametertabelle. Als Rückgabewert erhält man auch genau eine Tabelle, die Rückgabetabelle. Beide Tabellen enthalten benannte Felder, die ausgefüllt und übergeben werden. Funktionen, die keine Parameter haben, wird eine leere Tabelle übergeben. Es gibt also keine argumentlosen Funktionen.* Auch die Rückgabetabelle muss über die benannten Felder ausgewertet werden, anders kommt man nicht an die Werte:

    local ships = NWing.List( { Wing = V.Pirate } ).ShipList
              --  ^- Parametertabelle  ^- Rückgabetabelle
    oder auch so, was aber nur Sinn macht, wenn die Rückgabetabelle mehr als nur einen Wert enthält:
    local align = NShip.GetAlignment( { V.Player } )
local myPos = align.Pos
local dir_z = align.Front
local dir_y = align.UpDir

    * Hinweis: Auch das wird manchmal leicht übersehen und man wundert sich, dass man keine oder falsche Rückgabewerte bekommt. Ein Beispiel mit einer einfachen Funktion aus der "MissionLibEx.lua":

    -- Liefert einen boolschen Zufallswert
MissionLib.RandomBool = function()
    return( math.random() > 0.5 )
end
---------------------------------------
if MissionLib.RandomBool() == true then
    machwas
end
    Vergisst man hier das abschließende argumentlose Klammernpaar, dann wird diese Funktion nicht etwa ausgeführt, sondern es wird nur auf das Vorhandensein der Funktion, die in dem Fall als normale Variable angesehen wird, geprüft. Man bekommt also immer true zurückgeliefert!

    Das ist nun ein guter Zeitpunkt, um sich mit der Dokumentation der einzelnen Befehle in den Gruppen vertraut zu machen. Also auf zur Dokumentation.

    Aufzug

    7.3 - Aufbau eines Skriptes

    Im Grunde besteht ein Skript aus einem einzigen Aufruf der Funktion "NScript.Register". Das komplette Skript ist dann quasi als Parameter enthalten.
    NScript.Register( {
    Name  = <Missionsname>,
    Group = <GroupId>,
    Type  = <Missionstyp>,
    Transistions = <Transitionstabelle> } )

    Aufzug

    7.4 - Die Transitionstabelle

    Die Transitionstabelle ist eine normale LUA-Tabelle mit einer beliebigen Anzahl von Transitions. Jede Transition selbst ist eine Tabelle mit vier Elementen:
    { <MinStep>, <MaxStep>, <Event>, <Funktion> }
    Dabei sind MinStep und MaxStep die float-Werte, zwischen denen (einschließlich) sich der Zustand der Mission befinden muss, damit die Funktion ausgeführt werden kann. Event ist ein String mit dem Namen des Events. Sollte ein falscher Eventname benutzt werden, wird eine Assertion ausgelöst. Sind alle drei Bedingungen wahr, wird der Code in Funktion aufgerufen, wobei weiterhin die Parameter V und Data benutzt werden. Eine vollständige Transition sieht dann beispielsweise so aus:
    {   -- Starte Mission
    nil, nil, "MissionStart", function( V, Data )
    NGUI.ShowInfoText( { Text = "IDM_NEW_LOGENTRY" } )
    NStarSystem.SetAsMissionTarget( { System = 2, Set = 1 } )
    V.Step = 1
    end
},
    Hierbei fällt auf, dass anstatt der float-Werte für MinStep und MaxStep jeweils "nil" eingetragen ist. Das steht für einen undefinierten Wert, womit diese Transition immer ausgeführt wird, wenn das Event "MissionStart" ausgelöst wird. Außerdem wird abschließend V.Step auf 1 gesetzt. Dabei handelt es sich um den Zustand der Mission. Wenn eine Transition also den Folgezustand ändert, muss das über Zuweisung von V.Step passieren. V.Step sollte mit einem float-Wert > 0 gestartet werden, da C++ keinen Unterschied zwischen nil und 0 macht. Um nahe am Konzept zu bleiben, bietet es sich an mit V.Step = 1 zu starten. Da <MinStep> und <MaxStep> verschieden sein können, kann man Transitions schreiben, die während einer Reihe von Zuständen greifen können. Das ist besonders interessant für Abkürzungen in der Mission. Wenn also in den Zuständen 3 bis 14 Dinge passieren, die man umgehen kann, indem man das Sternensystem verlässt, könnte man folgende Transition schreiben:
    {   -- Raus hier
    3.0, 14.0, "System", function( V, Data )
    if Data.State == LEAVE_SYSTEM then
        V.Step = 15
    end
    end
},
    Bei jedem Event werden alle definierten Transitions ausgewertet, die greifen können. Die Reihenfolge ist hierbei undefiniert. Das sollte stets bedacht werden.

    Aufzug

    7.5 - Die Funktionsparameter V und Data

    Jedes Skript bzw. jede Mission hat eine skriptglobale Tabelle V, die an jede Funktion als Parameter übergeben wird. Hiermit besteht die Möglichkeit, Zustände, Variablen usw. zwischen den einzelnen Transitions weiterzugeben.
    Ganz besonders wichtig ist in dieser Hinsicht "V.Step", die Variable hält den aktuell gültigen Fortschritt der Mission (anhand derer die entsprechenden Transitions aktiviert werden). Diese Tabelle hält beliebig viele Variablen, je nachdem wie der Autor des Skriptes sie eben verwenden muss oder möchte.

    Die Data-Tabelle wiederum ist abhängig vom jeweiligen Event, das ausgelöst wird. Sie enthält all die Variablen, die das Event mit sich bringt. Die einzelnen Parameter sind in der Dokumentation der Events ersichtlich.

    Aufzug

    7.6 - Ablauf eines Skriptes

    Alle Skripte laufen nach einem festen Schema ab:

    1. Laden
      Vor dem Starten eines Skriptes wird es einmal komplett ausgeführt, d.h. der "NScript.Register" Aufruf wird ausgeführt, nicht aber die Funktionen innerhalb der definierten Transitions.

    2. Initialisierung
      Um festzustellen, ob ein Skript gestartet werden darf, wird ein "Init"-Event ausgelöst, auf das mit 0 oder 1 bzw. false oder true geantwortet werden muss. 1 oder true ist gleichbedeutend mit "ja, Skript bitte starten".

    3. Start
      Wird das Skript gestartet, wird zuerst noch einmal "Init" ausgeführt. Sollte der Rückgabewert hier nicht 1 sein, kommt es zu einem Fehler. Danach wird das Event "Create" ausgelöst. Der Zustand ist zu diesem Zeitpunkt undefiniert, weshalb "Create" eine {nil, nil}-Transition sein muss. Hier kann erstmals in die V-Tabelle geschrieben* und damit auch erstmals der Step gesetzt werden (und das sollte man auch unbedingt machen, spätestens jedoch im Event "MissionStart", z.B. mit V.Step = 1). Das nächste Event ist "MissionStart", das direkt nach "Create" abgefeuert wird. In Terminal-Missionen und Sidequests muss dazu allerdings zunächst der Auftrag angenommen worden sein, im Falle eines geöffneten Popup-Fensters eines NPCs anderer Missionen muss das Popup zuerst geschlossen werden. Danach können beliebige Events von der Anwendung kommen.
      * Man darf allerdings auch schon im "Init"-Event in die V-Tabelle schreiben, sofern der Start des Skripts sicher ist. Also wenn der Befehl return { Ready = true } ganz bestimmt ausgeführt wird.

    4. Ende
      Das Skript wird beendet, sobald der Zustand der Mission auf MSTATE_ACHIEVED, MSTATE_FAILED oder MSTATE_ENDED gesetzt wird. Dieser Zustand hat nichts mit dem Eintrag in V.Step zu tun und wird über die Funktion "NMission.SetState" gesetzt. Nachdem diese Zustände gesetzt sind, wird entsprechend das Event "Achieved" oder "Failed" ausgelöst, bei MSTATE_ENDED wird das Skript einfach beendet.

    Aufzug

    7.7 - Skriptevents

    Eine ausführliche Aufstellung aller verwendeten Ereignisse finden Sie hier im Menüpunkt Events. Also los, gleich mal reinschauen.

    Aufzug

    7.8 - Skripttypen

    Es gibt unterschiedliche Arten von Missionstypen. Für selbstgeschriebene Skripte stehen zwei besondere Missionstypen zur Verfügung, die vom Spiel bevorzugt behandelt werden: MTYPE_USER_TERMINAL sowie MTYPE_USER_SPACE. Terminalmissionen tauchen, wie der Bezeichner schon sagt, an den Terminals der Stationen auf. Kann eine solche Mission erzeugt werden, d.h. "Init" liefert eine 1, so wird diese bevorzugt dargestellt. Das Gleiche gilt für Space-Missionen, die nach dem Hyperraumsprung beim Betreten eines neuen Systems erzeugt werden. Sollten mehrere gleichwertige Missionen vorhanden sein, werden die vom Typ MTYPE_USER_* bevorzugt.

    Aufzug

    7.9 - Beispielskript

    Anhand eines kleines Beispielskriptes (Terminalmission) soll das Erstellen einer Mission veranschaulicht werden. Vorteilhaft für die Herangehensweise an die Skriptprogrammierung ist es, sich vorher darüber im Klaren zu sein, was die Mission tun soll. Hat man dieses "Konzept", kann man dieses Skript Schritt für Schritt abarbeiten und in LUA-Code umwandeln.
    Die Idee

    Für das erste Skript basteln wir eine einfache Rescue-Mission, bei der ein Container eingesammelt und zur Station zurückgebracht werden muss.

    Hinweis

    Das hier behandelte Skript befindet sich im Tutorial unter "\scripts\skript_tut001.lua".
    Der Ablauf des Skripts soll wie folgt sein:

    • Die Mission darf nur im Startsystem angeboten werden.
    • Nach Annahme der Mission am Terminal und dem Verlassen der Station soll ein Container in der Nähe der Handelsstation erzeugt werden. Als Inhalt soll ein String ausreichen ("Darkstar One Dokumentation").
    • Nach Aufnahme des Containers soll die Aufgabe angepasst werden; dem Spieler wird mitgeteilt, den Container zurück zur Station zu bringen.
    • Bringt er den Container zurück, gilt die Mission als erfolgreich. In dem Fall soll sie nicht wieder angeboten werden.
    • Landet er auf der Station, ohne den Container bei sich zu haben, passiert nichts.
    • Verlässt der Spieler das System, gilt die Mission als fehlgeschlagen.
    • Zerstört der Spieler den Container, gilt die Mission ebenfalls als fehlgeschlagen.
    Schon hier ist zu erkennen, dass es wichtig ist, alle möglichen Aktionen des Spielers abzudecken, um eine konsistente und glaubwürdige Mission zu erstellen. Gerade die Aktionen, die nicht zum erfolgreichen Abschließen einer Mission führen, sollten sorgfältig ausgearbeitet werden.

    Das Skript

    Als Basis für das einfache Beispiel dient die LUA-Vorlage aus dem TutorialMod ("template.luatemplate"). Einfach mal kopieren, und in <name>.lua umbennen. Alle vom Skriptautoren unbedingt auszufüllenden Stellen in der Vorlage sind mit "<$ ... $>" markiert.
    Der "Import"-Abschnitt der Vorlage importiert alle wichtigen Namespaces und Zusatzfunktionen. Um auf der sicheren Seite zu stehen, sollte man diese Zeile immer beibehalten.

    Nun folgt der eigentliche Missionskopf, der "NScript.Register" Aufruf:
    NScript.Register( {
    -- name
    Name = <$ HIER DEN SKRIPTNAMEN EINFÜGEN $>,
    -- group
    Group = 0,
    -- type
    Type = <$ HIER DEN SKRIPTTYP EINFÜGEN $>,
    -- transition table
    Transitions = {

    Hier fügen wir nur den Namen des Skriptes (ein String) sowie den Typ ein. Eine Aufstellung aller möglichen Typen findet sich in der HTML-Dokumentation.

        Name = "SKRIPT_TUT_001",
    -- group
    Group = 0,
    -- type
    Type = MTYPE_TERMINAL,

    Direkt darauf folgen schon die Transitions. Für alle Missionen unabdingbare Transitions sind in der Vorlage bereits eingetragen, und müssen nach Bedarf nur noch mit missions-spezifischen Details ausgefüllt werden. Jede Mission sollte natürlich eine Belohnung für den Spieler bereithalten. Deshalb tragen wir in die "MissionStart"-Transition eine Variable in die "V"-Tabelle ein.

    {   -- Mission startet
    nil, nil, "MissionStart", function( V, Data )
    -- hier sollten notwendige Initialisierungen vorgenommen werden
    V.Reward = 9876;  -- ein paar Credits für den Spieler
    -- hier startet nun die eigentliche Mission
    V.Step = 1
    end
},

    Hier ist auch zu sehen, dass der Step der Mission auf eins gesetzt wird. Die Mission startet jetzt also. Weiterhin sollte für die Belohnung V.Reward benutzt werden, da diese Variable bereits in der Vorlage verwendet wird.

    Die Vorarbeiten sind nun erledigt, die eigenen Missionssteps können nun eingefügt werden. Hierbei arbeiten wir unser "Minimalkonzept" Schritt für Schritt ab.

    Der erste Punkt ("Die Mission darf nur im Startsystem angeboten werden") muss in der "Init"-Transition behandelt werden. Diese Funktion wird jedes Mal aufgerufen, wenn Missionen angeboten oder erzeugt werden sollen. "Init" muss true oder false zurückgeben, je nachdem ob die Mission gestartet werden kann oder nicht. Da Lua nicht zwischen false und nil unterscheidet, darf anstelle von { Ready = false } hier auch eine leere Tabelle {} zurückgeliefert werden.

    {   -- Mission prüfen
    nil, nil, "Init", function( V, Data )
    if MissionLib.GetStarSystemId() == 8 then
        return { Ready = true }
    end
    return { Ready = false }
    end
},

    Über die MissionLib-Funktion GetStarSystemId() wird die ID des Sternsystems geliefert, in der sich der Spieler gerade aufhält. Ist er im System 8 ("Pencah", dem Startsystem des Spiels), so darf die Mission starten, andernfalls nicht. Wird true zurückgegeben, wird auch gleich die "Create"-Transition aufgerufen. Je nach Missionstyp wird nun "MissionStart" aufgerufen, in diesem Fall dann, wenn der Spieler die Mission am Terminal annimmt. In dieser "MissionStart"-Transition passen wir auch gleich die notwendigen Schritte an.

    {   -- Starte die Mission
    nil, nil, "MissionStart", function( V, Data )
    NStarSystem.SetAsMissionTarget( { System = MissionLib.GetStarSystemId(), Set = true } )
    MissionLib.LogUpdateStory()
    V.Step = 1
    end
},

    Das aktuelle Sternsystem wird als aktives Missionssystem auf der Karte gekennzeichnet. Weiterhin sagen wir dem Spieler, dass sich das Logbuch geändert hat (diese MissionLib.lua ist in der Installation frei zugänglich und beinhaltet eine Vielzahl von hilfreichen Zusatzfunktionen). Zudem wird der Step auf 1 gesetzt. Damit startet dann auch die "eigentliche" Mission. Es ist nun nützlich, den Sourcecode für die Tutorialmission zur Hand zu haben.

    Den ersten Event, den wir behandeln wollen, ist "Station". Wird eine Station betreten oder verlassen, so wird dieses Event getriggert. In diesem Fall erzeugen wir mit NContainer.Create einen Container, den wir mit missionsspezifischen Waren beladen, in diesem Fall ein String. Zum Abschluss speichern wir das Handle des Containers in der missionsglobalen Tabelle V und setzen den Step der Mission um einen Schritt weiter (V.Step=2).
    Damit werden weitere Transitions aktiv, mit denen wir die Aktivitäten des Spielers "überwachen". Drei dieser Events werden nun überwacht: "System", falls der Spieler das System verlässt, "Container", für den Fall, dass er den Container zerstört, und "Grab" für das Einsammeln des Containers. Wird der Container zerstört oder verlässt der Spieler das System vorzeitig, so wird der Status der Mission auf MSTATE_FAILED gesetzt. Die Mission ist somit beendet (natürlich nicht, ohne vorher das entsprechende "Failed"-Event auszulösen). Sammelt der Spieler hingegen den Container ein (Transition "Grab"), dann wird der Step auf drei hochgesetzt und eine weitere Transition wird aktiv ("Station"). Mit dieser neuen Transition wird auf das Betreten der Raumstation reagiert und, wenn der Spieler den Container dabei hat, mit dem Setzen des Status auf MSTATE_ACHIEVED reagiert.
    Zudem existieren weitere Transitions "Text": Diese werden aufgerufen, falls der Spieler das Logbuch oder das Terminal öffnet. Durch Transitions verschiedener Stufen kann man die Missionstexte anpassen und somit den Missionsverlauf für den Spieler deutlicher werden lassen.

    Aufzug

    7.10 - Weitere Beispiele

    Im Beispiel-Mod finden sich drei Missionsskripte, die das Erzeugen von Gegnern sowie das Dialogsystem erklären. Einfach mal reingucken.
    • skript_tut001.lua
    • script_tut002.lua
    • script_tut003.lua

    Aufzug

    7.11 - Nützliche Erweiterungen

    Diese sechs Skriptbibliotheken zum Importieren in eigene Skripts beinhalten eine Vielzahl von hilfreichen Zusatzfunktionen allgemeiner Art, zur Erzeugung großer Schlachten sowie zum Erstellen von Video-Sequenzen im Spiel.
    Die "MissionLib.lua" sollte man immer importieren, da deren Funktionen sehr häufig benötigt werden. Mit ihrem Import wird auch die "MissionLibEx.lua" (erstellt von [SNF]Norbert, nicht im Lieferumfang enthalten) automatisch mit eingebunden. Dasselbe gilt für die "BattleLibEx.lua" beim Import der "BattleLib.lua" und die "CameraLibEx.lua" beim Import der "CameraLib.lua".
    • MissionLib.lua: Viele allgemeine Zusatzfunktionen
    • MissionLibEx.lua: Erweiterung der MissionLib.lua
    • BattleLib.lua: Erzeugung großer Schlachtfelder
    • BattleLibEx.lua: Erweiterung der BattleLib.lua
    • CameraLib.lua: Erstellung von Videos im Spiel
    • CameraLibEx.lua: Erweiterung der CameraLib.lua

    Aufzug

    7.12 - Skripttools

    Skripte schreiben ist schön und gut, aber debuggen muss man die Sachen früher oder später ja doch. Hierfür gibt es einen leistungsfähigen LUA-Debugger, der über HTML erreichbar ist. Solange das Spiel läuft, ist dieses Frontend per Webbrowser über "localhost:54321" erreichbar.*

    * Seit der Insolvenz Ascarons ist der Debugger nicht mehr verfügbar, da der Server abgeschaltet wurde. Die folgenden Kapitel 7.13 bis 7.15 dienen daher nur noch zur Veranschaulichung. Eventuell lässt sich ja einer der frei verfügbaren Lua-Debugger einsetzen: Debugging Lua Code. Es muss jedoch beachtet werden, dass diese zumeist erst für Lua-Versionen ab 5.0 gedacht sind, während Darkstar One noch eine leicht modifizierte Version 4.0 verwendet. Zwischen diesen Versionen gibt es einige Syntaxunterschiede.

    Aufzug

    7.13 - Der Skript-Debugger

    Hat man die Seite geladen und folgt man dem "Missions"-Link, findet man eine Tabelle vor, die erst alle zu diesem Zeitpunkt laufenden Missionen auflistet, und weiter unten folgt eine Aufstellung aller anderen Missionen, die geladen wurden.

    Bild 1: Tabelle der aktuell laufenden Missionen.
    Zu sehen sind der Skriptname, sein gegenwärtiger Status und und ein Link zur Quelle des Skripts.

    Aufzug

    7.14 - Breakpoints

    Zum Setzen von Breakpoints (Unterbrechungspunkte) muss man zunächst einmal den Quellcode anzeigen. Entweder über einen Klick auf den Link "view script source" oder über die Seite "localhost:54321/Framework/ViewScript"

    Bild 2: Ansicht des Skript-Codes im LUA-Debugger.
    Ein Klick auf eine Zeilennummer setzt oder entfernt einen Breakpoint auf der nächsten ausführbaren Zeile. Unterbrechungspunkte werden mit dem Prefix '@' markiert.

    Aufzug

    7.15 - Variablen, Stack und Co.

    Wird ein Breakpoint erreicht und hält das Spiel an, so ändert sich auch die Ansicht. Oben erscheinen ein paar Debug-Ausgaben, links unten der Source und rechts die aktuellen Variablen (lokal, global, Stack, usw.). Gegebenenfalls muss die Seite neu geladen werden, um die Ansicht zu aktualisieren.
    Wer schon mal einen Debugger bedient hat, sollte sich auch hier recht schnell zurechtfinden. Das Fenster links oben ist für Befehle und Eingaben gedacht, die über den "Eval"-Button ausgeführt werden. "Step" springt in die aktuell angezeigte Funktion ("next" nicht vergessen, damit er auch den Source umschaltet, sofern möglich).

    Bild 3: Ansicht des Scripts nach Unterbrechung durch einen Breakpoint.

    Aufzug

    7.16 - Skriptcompiler

    Sind alle Skripte fertig und getestet, kann man mit Hilfe des Skriptcompilers (aus dem "Tools"-Verzeichnis) eine Datei erstellen, die alle Skripte im Bytecode enthält. Der Aufruf gestaltet sich recht einfach:
    scriptcompiler.exe -o user_scripts.bin *.lua
    Folgendes muss unbedingt beachtet werden: Um die LUA-Dateien kompilieren zu können, müssen folgende Dateien aus dem Darkstar Verzeichnis vorhanden sein:
    • BattleLib.lua
    • BattleLibEx.lua
    • CameraLib.lua
    • CameraLibEx.lua (falls vorhanden und eingebunden)
    • MissionLib.lua
    • MissionLibEx.lua (falls vorhanden und eingebunden)
    Danach können diese aus dem Mod-Verzeichnis gelöscht werden. Will man seine LUA-Dateien nicht kompilieren, dann ist dieser Kopierschritt überflüssig. Die entstandene "user_scripts.bin"-Datei muss im "scripts"-Ordner liegen um von Darkstar One gefunden werden zu können.

    Hinweis: Durch das Kompilieren sind die Skripte nicht mehr von außen zugänglich. Breakpoints lassen sich dann auch nicht mehr setzen.

    Aufzug

    8 - Ändern der 3D-Objekte

    Wenn das Schreiben neuer Missionen und das Anpassen der Galaxie langweilig geworden ist, kann man immer noch die 3D-Objekte austauschen oder neue Texturen einbauen. Die komplette Toolchain können wir aus rechtlichen Gründen leider nicht freigeben, das Erstellen und Einbauen veränderter Objekte ist deshalb "etwas" aufwendiger, aber keineswegs unmöglich.

    Aufzug

    8.1 - Verzeichnisstrukturen

    Alle für die dreidimensionale Darstellung verwendeten Dateien befinden sich in drei Archiven.
    • ds_3dgen.cpr
    • ds_3dobj.cpr
    • ds_3dtex.cpr

    Will man nun 3D-Dateien ändern, sollte man zuerst diese Archive entpacken.

    Hinweis:
    • CPR-Archive können mit jedem Zip-Programm gepackt bzw. entpackt werden, wenn man zuvor die Endung .cpr durch .zip ersetzt. Viele Zip-Programme lassen sich aber auch mit der Endung .cpr verknüpfen, sodass ein Umbenennen nicht mehr nötig ist.
    • Die Archive nicht in den Darkstar One Ordner entpacken!
    Nach dem Entpacken sieht man ein "3DView"-Verzeichnis, in dem sich die wichtigsten Daten befinden.

    Aufzug

    8.2 - Allgemeine Vorgehensweise

    Um nun ein Modell oder eine Textur auszutauschen, sollte man zunächst einmal die Originaldaten "isolieren" und in das zukünftige Modverzeichnis kopieren, unter Beibehalten der Verzeichnisstruktur (ausgehend von "3DView"). Da die Modelle teilweise festgelegte Objekte besitzen, die vom Programm aus angesprochen werden müssen, ist es sinnvoll, nur die ".3do"-Referenzen und evtl. die Shader innerhalb der XML Dateien auszutauschen. Ein komplettes Ersetzen durch eine neue XML-Datei ist sehr, sehr aufwendig und zeitraubend.
    Der nächste Schritt ist dann das Erstellen einer ".3do"-Datei mit Hilfe des Konverters sowie das Schreiben der passenden Blender.

    Aufzug

    8.3 - Aufbau der XML-Szenendateien

    Ein Spielmodell besteht aus einer XML-Szene, die auf alle verwendeten Resourcen verweist. Das sind im Einzelnen das eigentliche Modell (im ".3do"-Format), die verwendeten Shader (Blender) sowie die verwendeten Texturen. Ausgehend vom Wurzelknoten sind alle Objekte hierarchisch angeordnet (Szenengraph). Ein Objekt setzt sich normalerweise aus mehreren einzelnen Objekten zusammen, die bestimmten "Aufgaben" zugeordnet sind. Am besten lädt man sich mal ein Objekt (z.B. "Freighter_A_0.xml") in das "TakeALookXP"-Tool (vergleiche Abschnitt 7.7). Dort kann man auch die Hierarchie der Szene durchgehen, und sich einzelne Unterobjekte ansehen. Das sollte einiges zum Verständnis beitragen.

    Aufzug

    8.4 - Objekttypen

    • AVCWorldRoot: Basisknoten
    • AVCTransformationNode: einfacher Transformationsknoten
    • AVCMesh: einfaches Mesh im ".3do"-Format
    • AVCShieldMesh: Mesh für den Schutzschild eines Objektes
    • AVCGlowObject: Mesh für die "leuchtenden" Bereiche eines Objektes
    • AVCDistortionObject: Mesh für den Distortioneffekt (z.B. Hitzeflimmern) eines Objektes
    • AVCLODSelector: Level-of-Detail-Stufendefinition

    Aufzug

    8.5 - AVCMesh

    Der wichtigste Objekttyp; er definiert das "eigentliche" darzustellende Objekt. Er beinhaltet "EffectContainer", die Anzahl dieser Container entspricht der Anzahl an Materialien im verwendeten ".3do"-Objekt. Darauf ist unbedingt zu achten, wenn man ein neues Objekt einträgt. Jedem Effectcontainer ist ein Blender (Shader) zugeordnet (Path="..."). Materialeigenschaften sowie weitere Parameter für den Blender werden als Kindknoten des Containers eingetragen. Ein "EffectContainer" sieht also folgendermaßen aus:
    <EffectContainer path="test/test.bsd9">
<Material>
+0.000000 +0.261784 +0.344000 +0.000000
+0.471080 +0.471080 +0.471080 +0.000000
+0.000000 +0.761000 +1.000000 +0.000000
+0.025000 +0.050000 +0.100000 +0.000000
+100.000000
</Material>
<Parameters>
<Float semantic="..." value="+1.00000" />
...
</Parameters>
</EffectContainer>

    Das Material setzt sich aus Diffuse, Ambient, Specular und Emissive Color sowie Shininess zusammen. Alle Farben werden als RGBA angegeben. Die Materialeigenschaften sowie die Parameter stehen dem angegebenen Blender über Semantiken zur Verfügung. Eingehendere Details finden sich im Abschnitt " Blendercompiler". Besonders zu beachten ist folgender Sachverhalt: Befinden sich im ".3do"-Objekt mehrere LOD-Stufen, so entspricht die Anzahl der Effektcontainer der Summer aller Materialien der LOD-Stufen.

    Aufzug

    8.6 - Level of Detail und AVCLODSelector

    Darkstar One unterstützt mit seinem ".3do"-Format mehrere LOD-Stufen pro Objekt. Unabhängig von der Anzahl der LOD-Stufen in der Objektdatei wird in der XML-Szene ein Objekt des Typs "AVCLODSelector" benötigt, welches angibt, bei welcher Entfernung Stufen umgeschaltet werden und welche Teilobjekte der Szene gegebenenfalls abgeschaltet werden sollen.
    <Object Type=".?AVCLODSelector@@" ... LODNumber="2">

    LODNumber gibt in diesem Fall nicht die Anzahl der Stufen innerhalb des Meshes an, sondern die Anzahl der "LODDesc" (LOD Descriptions), die folgen. Eine solche Beschreibung gibt an, welche Teilobjekte der Szene sich im Vergleich zur Vorherigen ändern. Die einzelnen Teilobjekte werden jeweils über ihre Namen angesprochen, entsprechend der Hierarchie in der Szene.

    <LODDesc Clients="2">
lod_0|object_a 1 +0.00000
lod_0|object_b 1 +0.00000
</LODDesc>
<LODDesc Distance="+25.000000" Clients="2">
lod_0|object_a 0 +0.000000
lod_0|object_b 1 +0.750000
</LODDesc>

    "Clients" gibt die Anzahl der zu ändernden Objekte an, "Distance" die Entfernung zum Betrachter, die erreicht sein muss, um die LOD-Stufe zu aktivieren. Ein Client definiert sich durch den Pfad in der Szene zum betroffenen Objekt. Dann folgt 0=Objekt ausschalten, 1=Objekt anschalten. Der letzte Wert gibt einen Wert zwischen Null und Eins an; an Hand dieses Wertes wird die LOD-Stufe innerhalb der ".3do"-Datei ausgewählt. Null bedeutet erste Stufe, Eins die letzte. Hier kann ein Wert größer Eins angegeben werden, aber nur, wenn das Objekt ausgeschaltet ist.

    Aufzug

    8.7 - Der X File Converter

    Zum Umwandeln von Modellen im ".x"-Format nach .3do gibt es ein rudimentäres Tool. Der Aufruf gestaltet sich recht einfach:
      3do_convert <lod1.x> <lod2.x> ... <Ausgabe.3do>

    Man übergibt einfach die gewünschten Eingabedateien sowie als letzten Parameter die gewünschte Ausgabedatei. Das war es dann auch schon. Zu beachten ist das die übergebenen ".x"-Dateien den verschiedenen Level-of-Detail Meshes entsprechen sollten (es sei denn, man will aus einem Raumschiff einen Container machen, wenn sich das Objekt im Spiel weit entfernt). Zum ersten Test reicht dann aber eine einzige Stufe, womit sich der Aufruf auf folgenden Befehl reduziert.

      3do_convert <Eingabe.x> <Ausgabe.3do>

    Für ein einfaches Preview erstellt der Konverter eine Datei "output.xml". Mit "TakeALookXP" kann man nun sein Objekt mit einem einfachen Blender betrachten. Alle LOD-Stufen sind enthalten.

    Aufzug

    8.8 - Blendercompiler

    Mit Hilfe des Blendercompilers lassen sich eigene Shader für die selbst erstellten Modelle erzeugen. Solide Kenntnisse in der Programmierung von Shadern sind allerdings zwingend erforderlich, andernfalls wird man hiermit sicherlich keinen Spaß haben. Als einfaches Beispiel ein Blender, der nur die Vertices transformiert und eine feste Farbe zuweist. (Diese Farbe kann in der XML Szenendatei festgelegt werden)

    Aufzug

    8.9 - Blender Beispiel (simple_blender)

    Um einen Blender zu erstellen, braucht man zwei Dateien, einmal den Shader (".fx"-Format) und eine dazu passende XML-Datei. In der XML ist erstmal nur die Angabe der verwendeten Techniques von Bedeutung. Es können mehrere angegeben werden, die erste Funktionierende wird dann angewendet (von links nach rechts).
    <?xml version="1.0" encoding="utf-8" ?>
<Blender>
    <Effect include="simple_blender.fx">
    </Effect>
    <Variables/>
    <EffectAnimators totaltime="2.0">
    <EffectAnimator name="DOIT" duration="2.0" techniques="simple">
    <Trigger animator="DOIT" time="2.0" />
    <Init />
    <Main />
    </EffectAnimator>
    </EffectAnimators>
</Blender>

    Dieses Template kann so übernommen werden, die ".fx"-Datei sollte aber angepasst werden.
    Für die Verwendung in einem Effekt gibt es eine Vielzahl von Werten, die bereits von der Engine bereitgestellt werden. Dazu gehören z.B. bestimmte Matrizen. Das zugehörige Beispiel befindet sich im Tutorialmod unter "3DView/my_objects/simple_blender.fx" sowie "3DView/my_objects/simple_blender.xml".

    Bereitgestellte Werte
    Die von der Engine bereitgestellten Werte werden mit ihrer Semantik aufgelistet:
    • World: Worldmatrix
    • WorldView: Worldmatrix*Viewmatrix
    • WorldViewProjection: World*View*Projection
    • WorldInverseTransposed: Wordmatrix invertiert und transponiert
    • View: ViewMatrix
    • ViewInverse: Inverses der Viewmatrix
    • ViewProjection: View*Projection
    • Projection: Projectionmatrix
    Die oben genannten Matrizen können direkt so im Shader verwendet werden. Aus der Szenenbeschreibung heraus können auch noch weitere Werte an den Shader gegeben werden – entweder direkt über "<Material>" oder über "<Parameters>".
    Material
    Eine Materialbeschreibung setzt sich aus ambient, diffuse, specular und emissive Color zusammen. Im Shader sind diese Werte über folgende Semantik zu verwenden:
    • Ambient
    • Diffuse
    • Specular
    • Emission
    Parameters
    Parameter bekommen eine Semantik mitgegeben, mit der sie im Shader ansprechbar sind. Für Parameter gibt es verschiedene Typen:
    • Float: einfacher float-Wert
    • Vector: float4
    Beleuchtung
    Objekte können in Darkstar One von maximal vier Lichtquellen illuminiert werden. Shader, die Beleuchtung verwenden wollen, bekommen die Anzahl der Lichtquellen von der Engine übergeben und geben diese Anzahl an die Shader per "uniform"-Parameter weiter. Als Bespiel sollte man sich unbedingt den Beispielblender ansehen, der mit dem "Blendercompiler" ausgeliefert wird. Dort wird ein Array von Shadern erzeugt, jeweils mit den passenden Parametern für die Anzahl der aktiven Lichtquellen.

    Aufzug

    9 - Weitere Tools

    Hat man nun ein neues Objekt erstellt, kann man es sich mit "TakeALookXP" ansehen. Eine gute Möglichkeit, sich mit diesem Tool vertraut zu machen, ist es, sich mal ein paar Objekte aus den entpackten Archiven anzusehen.
    Links die hierarchische Struktur der XML-Szenendatei, darunter die Kamerasettings. Rechts die 3D-Ansicht sowie die Debug-Ausgaben. Zudem erstellt das Convertertool eine "output.xml" Datei, mit der man sich seine konvertierten Objekte ansehen kann.

    Aufzug

    10 - Wie man das Containermodell ersetzt (Beispiel)

    Als einfaches Beispiel nehmen wir uns den Frachtcontainer und ersetzen ihn durch ein beliebiges anderes Modell. Dafür erzeugen wir zunächste die nötigen Ordnerstrukturen im Modverzeichnis. Wir erstellen ein "3DView"-Verzeichnis und kopieren uns die "Container.xml" sowie die "Container_low.xml" aus dem Archiv "ds_3dgen.cpr". Für unsere eigenen Dateien erzeugen wir in diesem Ordner einen Unterordner "my_objects". Als Nächstes müssen wir unser Objekt konvertieren und einen passenden Blender basteln. Diese Dateien kopieren wir in den "my_objects"-Ordner. Haben wir das gemacht, so suchen wir in den Dateien "Container.xml" sowie "Container_low.xml" den passenden Node, den wir ersetzen wollen. Normalerweise ist dieser vom Typ ".?AVCMesh@@". Unbedingt darauf achten, dass man die Effectcontainer passend zum eigenen Blender und Mesh ersetzt. Auch die Pfadangaben müssen richtig sein (in diesen Fall "my_objects/<object>.3do" usw). Das war es dann auch schon. Der von uns im Mod-Verzeichnis erstellte "3DView"-Ordner muss nun noch in ein Zipfile mit dem Namen "user_data.zip" gepackt werden und sich im Root des Mod-Verzeichnisses befinden.
    Dateien mit Endung *_low.xml
    Alle 3d-Objekte existieren sowohl als XML-Datei sowie als "*_low.xml" Datei. Solche mit Endung "_low" sind speziell für Shader-1.1-Karten und verwenden angepasste Blender. Soll die Erweiterung auch auf älteren Grafikkarten laufen, so muss dieses hier auch beachtet und angepasst werden.

    Aufzug

    11 - Weitergabe von Mods

    Ist eine Mod fertiggestellt und getestet, dann kann sie auch weitergegeben werden. Es brauchen jedoch nicht alle Dateien ausgeliefert zu werden (es sei denn, die User sollen daran weiterentwickeln können). Folgende Dateien können für ein Weitergeben weggelassen werden:
    • .lua-Dateien, nachdem eine .bin-Datei kompiliert wurde
    • Alle Grafikdaten, nachdem eine user_data.zip erzeugt wurde
    • Alle .ini-Dateien, nachdem die ini_files.bin erstellt wurde

    Aufzug

    12 - Nützliche Links

    Ein paar Weblinks für Downloads und weitere Informationen:
    • Google.de : Suche nach „Darkstar One“
    • Google.de : Screenshots
    • Google.de : Videos
    • Dr. Windows : Darkstar One Downloads und Video Review
    • Supernature-Forum : Darkstar One - Modding (PC-Version)
    • Supernature-Forum : Darkstar One - Grafik-Mods (PC-Version)
    • Supernature-Forum : Darkstar One - Flakmissions-Patch
    • Supernature-Forum : Gameplay FAQ
    • Steam Users' Forums : Darkstar One
    • GameStar : Darkstar One - Patch 1.3 (nicht für DVDs der Version 1.3 installieren!)
    • 4Players : Darkstar One - Modding-Tools (Deutsch)
    • Lua 5.1 Referenzhandbuch (Deutsch)
    • Lua-users Wiki : Sample Code (Code-Beispiele in Lua 5.x)
    • Debugging Lua Code (Downloads - Debugger und Syntaxeditoren)

    Aufzug
    Zuletzt aktualisiert am: 24.09.2019


Glossar

Funktionen im Skriptsystem
Funktion Namespace Index
  1. ActivateRing
  2. ActivateScanner
  3. Add
  4. AddAction
  5. AddAmmo
  6. AddAmmoType
  7. AddContainer
  8. AddCredits
  9. AddDialog
  10. AddDialog
  11. AddEnemy
  12. AddFilter
  13. AddMessage
  14. AddNews
  15. AddWings
  16. AmmoInfo
  17. Blink
  18. ChangeToCanyon
  19. ChangeToSpace
  20. ChangeToWeaponFactory
  21. ClearMissionObjects
  22. ClearSubtitle
  23. CloseHyper
  24. Create
  25. Create
  26. Create
  27. Create
  28. Create
  29. Create
  30. CreateBoundCam
  31. CreateDeath
  32. CreateDialog
  33. CreateDialogObj
  34. CreateExplosion
  35. CreateForceField
  36. CreateFreeCam
  37. CreateGenerator
  38. CreateHyper
  39. CreateLoot
  40. CreateMenace
  41. CreateMine
  42. CreateObject
  43. CreatePosCam
  44. CreateRandomCargo
  45. CreateRing
  46. CreateSatellite
  47. CreateShip
  48. CreateSpeedBoost
  49. CreateSplineCam
  50. CreateTimer
  51. CreateWreck
  52. DeactivateScanner
  53. DeactivateSkaaShield
  54. Define
  55. Destroy
  56. Destroy
  57. Destroy
  58. Destroy
  59. Destroy
  60. DestroyForceField
  61. DestroyMine
  62. DestroyPlayerShip
  63. DestroyRing
  64. DistanceFromPlayer
  65. DropContainer
  66. DumpCargo
  67. EnableContainerHits
  68. End
  69. EndDialog
  70. EndEscort
  71. EndSiege
  72. EnterActionTurret
  73. Equip
  74. EquipContainer
  75. EquipmentInfo
  76. EscortNPC
  77. EscortPlayer
  78. ExecuteAi
  79. ExitActionTurret
  80. Explode
  81. Explode
  82. FirePlasma
  83. Freeze
  84. GameOver
  85. GangDetected
  86. GetActionTurret
  87. GetAlignment
  88. GetAlignment
  89. GetAmmoDamage
  90. GetAnomalie
  91. GetArtefact
  92. GetAsteroidPos
  93. GetAsteroidPosCont
  94. GetCombineName
  95. GetContainer
  96. GetCriminalRecord
  97. GetFrontDir
  98. GetHandleFromId
  99. GetHangarPos
  100. GetHideOut
  101. GetIdFromHandle
  102. GetMissionGood
  103. GetMissionHandle
  104. GetName
  105. GetNameArray
  106. GetNumCargoBays
  107. GetOrbiter
  108. GetPirateField
  109. GetPos
  110. GetPosition
  111. GetSkaaShieldEnterPos
  112. GetState
  113. GetTime
  114. GetTradeStation
  115. GetType
  116. GetUpDir
  117. GetWingRelPos
  118. HelpDialog
  119. IsEona
  120. IsHostileShip
  121. IsInSpace
  122. IsInSpace
  123. IsObjectInView
  124. IsPlayerShip
  125. IsQueueEmpty
  126. IsWing
  127. JoinWing
  128. LandOnBase
  129. LeaveSpaceStation
  130. List
  131. List
  132. ListOrbiters
  133. LockHyperJump
  134. LockSystemEntry
  135. MakeHostile
  136. Message
  137. MoveAhead
  138. NoEnemy
  139. OrbiterTurretLock
  140. Pause
  141. Place
  142. Place
  143. PlayerLanding
  144. PlayMovie
  145. PlaySound
  146. PlayUserSound
  147. Progress
  148. Protect
  149. ProtectCargo
  150. RadarMapColor
  151. Register
  152. RemoveDialog
  153. RemoveDialog
  154. RemoveHostilePlayer
  155. RemoveStoryLock
  156. RemoveWeapons
  157. ResetActor
  158. Save
  159. ScanObject
  160. SelectNearestEnemy
  161. SelectTarget
  162. SendMail
  163. SetActor
  164. SetActor
  165. SetAlignment
  166. SetAlignment
  167. SetAsMissionTarget
  168. SetAsStoryTarget
  169. SetBoss
  170. SetCloaked
  171. SetCloakScanner
  172. SetCrime
  173. SetCrime
  174. SetCustomMusic
  175. SetDefaultMusic
  176. SetDurability
  177. SetFormation
  178. SetHidden
  179. SetIllegal
  180. SetInvalidEnemy
  181. SetInvulnerable
  182. SetMag
  183. SetMaxY
  184. SetMinY
  185. SetMissionFlag
  186. SetMultipliers
  187. SetName
  188. SetOrbiterEvasion
  189. SetPlanetCollision
  190. SetPlasmaEffect
  191. SetPlayerEntryPos
  192. SetPlayerFriend
  193. SetPlayerHostile
  194. SetRecharge
  195. SetRoomType
  196. SetScanningFlag
  197. SetShipHostile
  198. SetShipLiftOff
  199. SetShipSpeed
  200. SetSpecialName
  201. SetState
  202. SetTurn
  203. SetUniqueItems
  204. SetVisible
  205. Show
  206. ShowInfoText
  207. ShowMovie
  208. ShowSubtitle
  209. StandardReward
  210. StartFollow
  211. StopFollow
  212. Sub
  213. SubWings
  214. ToggleSplineMode
  215. TraderLogicOn
  216. TriggerDialog
  217. TriggerDialog
  218. Unlock
  219. UseMissiles
NObject
NPlayer
NVector
NWing
NPlayer
NPlayer
NShip
NPlayer
NObject
NShip
NWing
NCamera
NComm
NTerminal
NGroupAi
NPlayer
NGUI
NCanyon
NCanyon
NCanyon
NObject
NGUI
NObject
NContainer
NGroupAi
NMission
NNPC
NWaypoint
NWing
NCamera
NCamera
NCamera
NCamera
NObject
NCanyon
NCamera
NCanyon
NObject
NContainer
NCamera
NObject
NCamera
NCamera
NShip
NObject
NObject
NCanyon
NCanyon
NCamera
NMission
NShip
NPlayer
NShip
NWing
NCamera
NContainer
NGroupAi
NNPC
NWing
NCanyon
NObject
NPlayer
NObject
NObject
NShip
NShip
NObject
NCamera
NObject
NPlayer
NStarSystem
NObject
NContainer
NShip
NPlayer
NPlayer
NShip
NWing
NObject
NContainer
NShip
NPlayer
NObject
NGame
NGUI
NObject
NContainer
NShip
NObject
NObject
NObject
NObject
NObject
NStarSystem
NPlayer
NPlayer
NObject
NStarSystem
NObject
NShip
NStarSystem
NContainer
NMission
NObject
NObject
NShip
NStarSystem
NStarSystem
NVector
NObject
NShip
NMission
NGame
NStarSystem
NContainer
NObject
NCamera
NGUI
NPlayer
NWing
NContainer
NShip
NPlayer
NShip
NComm
NWing
NShip
NPlayer
NPlayer
NStarSystem
NWing
NStarSystem
NPlayer
NPlayer
NWing
NDebug
NPlayer
NWing
NObject
NGame
NObject
NWing
NObject
NGame
NSound
NSound
NStory
NShip
NShip
NObject
NScript
NObject
NShip
NGroupAi
NStarSystem
NShip
NObject
NGame
NObject
NPlayer
NPlayer
NPlayer
NObject
NShip
NContainer
NShip
NStarSystem
NStarSystem
NShip
NShip
NPlayer
NObject
NShip
NSound
NSound
NShip
NWing
NShip
NContainer
NWing
NShip
NVector
NCanyon
NCanyon
NObject
NPlayer
NMission
NShip
NShip
NDebug
NWing
NShip
NGroupAi
NShip
NSound
NObject
NCanyon
NCanyon
NCanyon
NObject
NMission
NCanyon
NContainer
NStarSystem
NWaypoint
NGUI
NGUI
NGUI
NPlayer
NPlayer
NPlayer
NVector
NGroupAi
NCanyon
NShip
NObject
NShip
NStarSystem
NShip 		31
6
1
15
16
15
21
9
32
26
11
9
2
1
6
24
5
2
13
1
41
2
23
2
2
1
2
2
2
13
7
2
5
30
7
8
14
9
8
11
7
1
3
28
33
24
15
5
10
6
36
4
25
13
6
6
1
1
8
12
38
25
34
35
10
11
19
12
6
7
14
8
10
29
8
28
30
5
5
4
16
11
10
1
4
2
11
17
39
21
13
16
29
5
19
26
17
9
18
22
3
12
5
4
12
24
2
11
3
42
7
3
3
7
1
22
4
3
22
6
5
19
13
18
1
9
32
21
14
13
14
6
23
20
12
1
2
10
28
2
20
7
15
4
5
3
1
34
31
11
1
1
3
3
8
27
37
5
36
1
3
18
26
20
3
8
10
12
2
35
17
3
4
4
2
12
1
15
7
4
1
2
10
8
25
5
2
23
5
2
3
9
4
33
1
14
4
6
11
27
4
3
9
4
1
7
6
1
27
12
10
4
5
9
6
40
14
1
13

=== lua Funktionen === === math Funktionen === === string Funktionen ===
Funktion Index
  1. call
  2. gc
  3. getglobals
  4. getn
  5. getregistry
  6. max
  7. min
  8. pack
  9. rawget
  10. rawset
  11. setglobals
  12. sizeof
  13. tag
  14. tofloat
  15. tonumber
  16. tostring
  17. type
  18. unpack
12
7
16
3
14
4
1
13
6
11
18
15
9
8
5
17
2
10
Funktion Index
  1. abs
  2. acos
  3. asin
  4. atan
  5. atan2
  6. ceil
  7. cos
  8. deg
  9. exp
  10. floor
  11. frexp
  12. ldexp
  13. length
  14. log
  15. log10
  16. mod
  17. normalize
  18. pi
  19. rad
  20. random
  21. randomseed
  22. sin
  23. sqrt
  24. tan
22
23
9
10
5
13
14
1
19
17
8
20
11
21
15
12
2
4
18
24
7
6
3
16
Funktion Index
  1. at
  2. erase
  3. find
  4. find_first_of
  5. find_last_of
  6. format
  7. is_valid
  8. length
  9. replace
  10. substr
  11. tokenize
  12. tolower
  13. toupper
13
12
11
5
8
6
4
3
9
10
2
1
7


Commands

ScriptingCommands : Allgemeines

Packages

Alle Funktionen sind in Packages organisiert, welche als Namespace fungieren. Ein Package fasst dabei alle Funktionen zusammen, die eine logische Gruppe bilden oder auf den gleichen logischen Objekten arbeiten. NWing enthält beispielsweise alle Funktionen, die auf der Logik-Klasse CWing operieren, NPlayer beinhaltet alle Funktionen, die den Spieler oder das Spielerschiff betreffen.

Um die Funktionen eines Packages nutzen zu können, muss das Package zu Beginn des Skriptes per import-Anweisung importiert werden:

-- Packages importieren
import "NPlayer"
import "NSound"
...
...
NPlayer.AddReward( { Reward = NPlayer.StandardReward({}).Credits } )
NSound.SetCustomMusic( { Title = "victory" } )
...
...

Funktionen

Das Interface aller Funktionen folgt einem einheitlichen Schema. Jeder Funktion wird genau ein Parameter übergeben, die Parametertabelle und liefert genau einen Wert zurück, die Rückgabetabelle.

Beide Tabellen enthalten benannte Felder, in denen die einzelnen Parameter bzw. Rückgabewerte übergeben werden. Funktionen, die keine Parameter haben, wird eine leere Parametertabelle übergeben - es gibt keine argumentlosen Funktionen. Besonders zu beachten ist, daß die Rückgabe der Ergebnisse einer Funktion immer über eine Tabelle erfolgt, d.h. es müssen - auch bei einfachen Funktionen, die nur einen Wert liefern - Felder der Rückgabetabelle angesprochen werden. Beispiel:

-- FALSCH
if NPlayer.IsEona({}) then ...

-- RICHTIG
if NPlayer.IsEona({}).Eona then ...

Hinweis: Dieses Schema mit den Tabellen betrifft die im Skriptsystem fest implementierten Funktionen. Für die Funktionen in den externen Bibliotheken (MissionLib.lua usw.) erfolgt die Parameterübergabe und Rückgabe der Werte dagegen in vielen Fällen und wie allgemein üblich als direkte Argumente, ohne dafür Tabellen zu verwenden. Dasselbe gilt auch für alle lua- und get-"Logic"-Funktionen.

Die Dokumentation der Funktionen folgt dem folgenden Schema:

  • < Name der Funktion >( < Parametertabelle > ) : < Rückgabetabelle >
  • Kurze Beschreibung der Funktion
  • Parametertabelle
  • Rückgabetabelle
  • Beispiele
Kursive Feldbezeicher kennzeichnen optionale Parameter. In diesem Falle ist hinter der Angabe des Wertebereichs der Default-Wert zu finden. Sind im Wertebereich keine Angaben zu finden, so sind alle Werte erlaubt, die der Datentyp annehmen kann. In einigen Fällen bedingen die Werte einiger Parameter andere Parameter. In diesem Fall sind die abhängigen Parameter mit '|' getrennt. Zwei Beispiele:
  • NContainer.Create( { Type, Size, Ship|PosDesc|Position } ) : { Container }
    Hier wird in Abhängigkeit vom Wert von 'Type' entweder der Parameter 'Ship' oder 'PosDesc' oder 'Position' erwartet.
  • NContainer.Equip( { Container, Goods, Amount } ) : {}
    In diesem Fall kann der Parameter 'Amount' weggelassen werden. Der Container wird dann komplett gefüllt.

Datentypen

Folgende Datentypen für Parameter werden in der Dokumentation unterschieden:
  • float : Fließkommazahl
  • int : vorzeichenbehaftete Ganzahl
  • unsigned int : positive Ganzahl
  • bool : Boolscher Wert ( true | false )
  • enum : Aufzählungstyp der vordefinierte benannte Konstanten verwendet
  • string : Nullterminierte Zeichenkette
  • table[n]:<Typ> : Tabelle mit n Einträgen des Typs <Typ>
Der Datentyp bool ist in der verwendeten LUA-Version nicht vorhanden und wird daher emuliert. true entspricht dabei einem Wert von 1 (int), es werden auch alle anderen Zahlen, Strings oder sonstige gültige Werte - einschließlich der 0 - bei einem booleschen Vergleich als true interpretiert. false ist nil, also eine nicht-existierende Variable. Prinzipiell ist daher das Weglassen eines bool-Parameters identisch mit der Zuweisung von false. Aus Gründen der Lesbarkeit sollte jedoch in den meisten Fällen besser false zugewiesen werden. Beispiel:
NStarSystem.SetAsMissionTarget( { System = V.System, Set = false } )
-- ist identisch zu
NStarSystem.SetAsMissionTarget( { System = V.System } )
Letzteres ist semantisch allerdings irreführend, da ja die Missionsmarkierung vom Zielsystem entfernt und nicht gesetzt wird.

Beim Datentyp table beginnt die Nummerierung immer bei 1, d.h. table[3] bezeichnet eine Tabelle mit den Einträgen table[1], table[2] und table[3]. Die Angabe table[n] bezeichnet eine Tabelle mit beliebig vielen Einträgen (1 bis n).

Anmerkung: Diese Datentypen sind nur für den Zweck der Dokumentation vorhanden und haben nichts mit den Datentypen in LUA zu tun.

Aufzählungtypen

Einige Aufzählungstypen werden von mehreren Funktionen verwendet. Um die wiederholte Angabe aller möglichen Werte zu vermeiden, findet sich im Folgenden eine Übersicht über einige Aufzählungstypen, die über Querverweise bei den entsprechenden Funktionen angesprochen werden. Sind die Bezeichner von Aufzählungstypen nicht selbsterklärend, so wird bei der Beschreibung einer Funktion eine oder mehrere Tabellen mit Erläuterungen der einzelnen Werte angefügt.

Hinweis: Diese Übersicht ist nicht vollständig und wird auch nicht mehr weiter aktualisiert. Dafür existiert jetzt der neue Menüeintrag Tabellen, der weiterhin auf einem möglichst aktuellen Stand gehalten wird. Die Aufzählungstypen sind dort leicht auffindbar in den dafür passenden Untermenüs enthalten. Dort sind auch alle im System gefundene und bisher undokumentierte Typen mit aufgeführt, ebenso wie auch alle neu hinzugefügten Aufzählungstypen.

Containertypen

Eine Aufzählung der vorhandenen Containertypen
Konstante | Kommentar | Wert
CONTAINER_SMALL | Container mit 50t | 0
CONTAINER_MEDIUM | Container mit 100t | 1
CONTAINER_LARGE | Container mit 200t | 2
CONTAINER_SPECIAL | Geheimdienstwaffen-Container (Unique Items) | 3
CONTAINER_PASSENGER | Passagiercontainer an Shuttles | 4
CONTAINER_ROCK | Container, der beim Sprengen eines Meteoriten erzeugt wurde | 5
CONTAINER_ARTEFACT | Artefakt-Container | 6

Erzeugungsbereiche

Die Erzeugungsbereiche, in denen Wings erzeugt werden können
Konstante | Parameter | Kommentar
POSDESCR_PLAYERSHIP | -/- | Kugelschale um das Spielerschiff im Abstand von 2-4 Units (u).
POSDESCR_INTERCEPTION | -/- | Kugelschale im Abstand von 2-4 Units vom Mittelpunkt. Der Mittelpunkt liegt auf der Verbindungsachse Absprungtor - Handelsstation im Abstand von 4 Units vom Ring.
POSDESCR_OFFSET | -/- | Kugel mit einem Radius von 3 Units. Der Mittelpunkt liegt 3 Units von der 3-Unit-Marke der Verbindungsachse Absprungtor - Handelsstation entfernt.
POSDESCR_ASTEROID | -/- | Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Mittelpunkt des Asteroiden entfernt, auf der zur Handelsstation abgewandten Seite. Hat ein System mehrere Asteroiden, so wird zufällig ein Asteroid gewählt.
POSDESCR_TRADESTATION1 | -/- | Kugel mit einem Radius 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Mittelpunkt der Handelsstation entfernt, auf der zum Absprungtor abgewandten Seite.
POSDESCR_TRADESTATION2 | -/- | Kugelschale um die Handelsstation im Abstand von 1-3 Units.
POSDESCR_RESEARCHSTATION | -/- | Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Mittelpunkt der Forschungsstation entfernt, auf der zur Handelsstation abgewandten Seite. Hat ein System mehrere Forschungsstationen, so wird zufällig eine ausgewählt.
POSDESCR_WELCOME | -/- | Ein Ring mit einem Durchmesser von 0,1 Units, dessen Mittelpunkt 0,1 Units vor dem Tor der Handelsstation liegt.
POSDESCR_METEROIDS | -/- | Der Mittelpunkt eines Meteoritenfeldes (jedes System kann nur ein Feld haben).
POSDESCR_ESCORT | -/- | Ein Torus, dessen Mittelpunkt genau zwischen Handelsstation und Hyperraumtor liegt.
POSDESCR_HANGAR | Object | Start aus einem Objekt mit Hangar.
POSDESCR_WINGDISTANCE | Object und Distance | In einem gegebenen Abstand neben einem Wing im Weltraum.
POSDESCR_EXPLICIT | Position, FrontDir, UpDir | Eine absolute Position mit Ausrichtung.
POSDESCR_HYPERSPACE | -/- | Das System wird durch das Hyperraumtor betreten.
POSDESCR_HYPERSPACE_CRUISER | -/- | Kreuzer betreten das System ohne das Tor an einer freien Position.
POSDESCR_FIRST_PLANET | -/- | Position über dem ersten Planeten hinter der Handelsstation.
POSDESCR_ACTIONTURRET | Position | Position ist eine Position relativ zu dem ActionTurret.
POSDESCR_CRUISER_ENTRY | Position, FrontDir, UpDir | Kann mit Skaa- und Kreuzerwings wie POSDESCR_EXPLICIT verwendet werden. Die Schiffe werden nur nicht einfach erzeugt, sondern betreten das System mit einem Hyperraumfenster und bremsen dann ab.
Bei mehreren Forschungsstationen oder Asteroiden wird zufällig ausgewählt, wo erzeugt wird. Das sollte sich steuern lassen. Wenn man sonst drei Wellen Jäger vom Asteroiden losschicken möchte, geht das nicht zuverlässig. Einfach einen Parameter Explicit einfügen bei dem die Nummer/ID des Objekts übergeben werden kann.

Handelswaren

Alle von der Wirtschaftssimulation verwendeten Handelswaren
Konstante | Kommentar | Wert
GOODS_COALHYDRATES | Kohlenhydrate | 0
GOODS_PROTEINS | Proteine | 1
GOODS_LIFEFORMS | Lebensformen | 2
GOODS_VEGFIBERS | Pflanzefasern | 3
GOODS_METALS | Metalle | 4
GOODS_PRECMETALS | Edelmetalle | 5
GOODS_CRYSTALS | Kristalle | 6
GOODS_ALLOYS | Legierungen | 7
GOODS_MACHINERY | Maschinen | 8
GOODS_ELECTRONICS | Elekronik | 9
GOODS_COMPUTERS | Computer | 10
GOODS_SHIPTECHS | Schiffstechnik | 11
GOODS_MEDICINE | Medizin | 12
GOODS_CHEMICALS | Chemikalien | 13
GOODS_LIQUOR | Likör | 14
GOODS_FERTILIZER | Dünger | 15
GOODS_ENERGYCELLS | Energiezellen | 16
GOODS_FUELRODS | Brennstäbe | 17
GOODS_ISOTOPES | Isotope | 18
GOODS_SUPERCONDUCTORS | Supraleiter | 19
GOODS_VIDEOGAMES | Videospiele | 20
GOODS_LUXURIES | Luxusgüter | 21
GOODS_ANDROIDS | Androiden | 22
GOODS_DRUGS | Drogen | 23
GOODS_NONE * | Keine Waren | 24
GOODS_MISSIONOBJECT | Missionswaren | 25
* Konstante in der MissionLibEx.lua definiert.

Munitionssorten

Die im Spiel verwendeten Munitionsarten
Konstante | Kommentar | Wert
AMMO_TYPE_LASER | Standardwaffe der Menschen | 0
AMMO_TYPE_RAILGUN | Standardwaffe der Mortok | 1
AMMO_TYPE_PHASER | Standardwaffe der Raptor | 2
AMMO_TYPE_SONIC | Standardwaffe der Oc'to | 3
AMMO_TYPE_ENERGY | Standardwaffe der Arrack | 4
AMMO_TYPE_PHOTON | Standardwaffe der Thul | 5
AMMO_TYPE_SKAADRILL | Standardwaffe der S'kaa | 6
AMMO_TYPE_SWARM | Schwarm-Rakete | 7
AMMO_TYPE_HELLFIRE | Hellfire-Rakete | 8
AMMO_TYPE_BIGBANG | Raumtorpedo | 9

RadarMapColors

Die auf der Radarmap verwendeten Farben. Die Farben haben keinen Einfluss auf das Verhalten.
Konstante | Kommentar | Wert
RADARMAP_INVISIBLE | Objekt wird nicht angezeigt | 0
RADARMAP_SHIP_FRIEND | freundliches Objekt (grün) | 1
RADARMAP_SHIP_HOSTILE | feindliches Objekt (rot) | 3
RADARMAP_SHIP_OFFICIAL_WING | Patrouillenschiffe (blaue Dreiecke) | 6
RADARMAP_SHIP_CRUISER | Kreuzer (blau) | -/-
RADARMAP_SHIP_THREAT | Bedrohung (orange) | 9
RADARMAP_SHIP_NEUTRAL | neutrales Schiff (weiß) | 9
RADARMAP_INVALID | ungültige Farbe | 18

StarShip-Typen

Eine Aufzählung aller Schiffsklassen in DSO
Konstante | Kommentar | Wert
ST_PLAYERSHIP | Das Schiff des Spielers | 0
ST_TRADERSHIP | Handelsfrachter | 1
ST_SHUTTLE | Shuttle, bewegt Container zwischen Frachtern und der Handelsstation | 2
ST_CONSUMPTION_SHUTTLE | Shuttle, bringt Waren von der Handelsstation zu anderen Orbitern | 3
ST_PRODUCTION_SHUTTLE | Shuttle, bringt die Produktion von den Orbitern zu der Handelsstation | 4
ST_POLICE | Polizeijäger | 5
ST_PIRATESHIP | Piratenjäger | 6
ST_WINGMAN | Begleitjäger oder Schiff der Kopfgeldjäger | 7
ST_CRUISER | Großer oder kleiner Kreuzer | 8
ST_SKAADRONE | Kampfdrohne der S'kaa, die immer in einer Formation bleibt | 9
ST_MILITARYFIGHTER | Militärjäger | 10
ST_CARGODRONE | Frachtdrohne, die für Jäger die Container trägt | 11
ST_WEAPONBASE | Unbewegliche Waffenplattform | 12
ST_PIRATEFREIGHTER | Frachter der Piraten | 13
ST_SKAASWARM | Kein Schiff, sondern das Zentrum der S'kaadrohnen-Formation | 14
ST_CANYONSHIP | Schiff, welches in Canyons auf festen Bahnen fliegt | 15
ST_COMMSAT | Kommunikations-Satellit als Waffenplattform wie ST_WEAPONBASE | 16
ST_TRADERDRONE | Frachtdrohne, mit der Frachter Container einsammeln können | 17
ST_COLLECTOR_SHUTTLE | Shuttle, kann frei im Weltraum schwebende Container einsammeln | 18
ST_SHIELDGEN | Missionsobjekt, das im Canyon zerstört werden soll | 19
ST_... ? | Frei? | 20
ST_PASSENGER_SHUTTLE | Transportshuttle mit Passagiermodul (Taxi) | 21
ST_BASESHIP | Piratenbasis | 22
ST_SUPERFREIGHTER * | Superfrachter 9000t, trägt 45 Container á 200t | 23
* Konstante in der MissionLibEx.lua definiert.

Volk

Eine Aufzählung aller vorhandenen Völker in DSO
Konstante | Kommentar | Wert
RACE_HUMAN | Menschen | 0
RACE_MORLOK | Mortok | 1
RACE_RAPTOR | Raptor | 2
RACE_OCTO | Oc'to | 3
RACE_WASP | Arrack | 4
RACE_THUL | Thul | 5
RACE_SKAA | S'kaa | 6
RACE_1704 * | 1704 (nicht vorhanden) | 7
RACE_RANDOM | Automatische Rassenverteilung des Clusters wird verwendet | 8
* Konstante in der MissionLibEx.lua definiert.

Wingtypen

Die Wingtypen, die erzeugt werden können
Konstante | Kommentar | Wert
WINGTYPE_HUNTER | ein Kopfgeldjäger-Wing | 0
WINGTYPE_FREIGHTER50T | ein Wing mit einem Frachter (200/400t), der 4 oder 8 Container á 50t tragen kann. Die Anzahl der Containerplätze wird zufällig erzeugt. | 1
WINGTYPE_FREIGHTER100T | ein Wing mit einem Frachter (200/400/600t), der 2, 4 oder 6 Container á 100t tragen kann. Die Anzahl der Containerplätze wird zufällig erzeugt. | 2
WINGTYPE_FREIGHTER200T | ein Wing mit einem Frachter (600t), der 3 Container á 200t tragen kann. | 3
WINGTYPE_POLICE | ein Polizei-Wing | 4
WINGTYPE_MILITARY | ein Wing mit Militärjägern | 5
WINGTYPE_CRUISER1 | ein großer Kreuzer mit Hangar | 6
WINGTYPE_CRUISER2 | ein kleiner Kreuzer ohne Hangar | 7
WINGTYPE_WEAPONBASE | ein Wing aus Waffenplattformen mit je einer Kanone | 8
WINGTYPE_PIRATES | ein normaler Piratenwing für den Angriff auf Schiffe | 9
WINGTYPE_RAIDERS | ein Piratenwing mit besonderer Logik für den Raub von Containern | 10
WINGTYPE_PIRATEFREIGHTER | Es wird ein Wing aus Piratenfrachtern erzeugt. Geleitschiffe werden nicht erzeugt. Die Tonnage ist zufällig, es läßt sich auch keine Fracht andocken. | 11
WINGTYPE_SKAA | der Wing ist ein S'kaa-Schwarm. | 12
WINGTYPE_PIRATEFREIGHTER50T | ein Wing mit einem Piratenfrachter, der 50t-Container tragen kann. Alle weiteren Schiffe des Wings sind Hunter. | 13
WINGTYPE_PIRATEFREIGHTER100T | ein Wing mit einem Piratenfrachter, der 100t-Container tragen kann. Alle weiteren Schiffe des Wings sind Hunter. | 14
WINGTYPE_PIRATEFREIGHTER200T | ein Wing mit einem Piratenfrachter, der 200t-Container tragen kann. Alle weiteren Schiffe des Wings sind Hunter. | 15
WINGTYPE_FREIGHTER200CAP | ein Wing mit einem Frachter, der Kapazität für 200t Ladung hat. Es können 2 Container á 100t oder 4 Container á 50t angedockt werden. | 16
WINGTYPE_FREIGHTER400CAP | ein Wing mit einem Frachter, der Kapazität für 400t Ladung hat. Es können 4 Container á 100t oder 8 Container á 50t angedockt werden. | 17
WINGTYPE_FREIGHTER600CAP | ein Wing mit einem Frachter, der Kapazität für 600t Ladung hat. Es können 3 Container á 200t oder 6 Container á 100t angedockt werden. | 18
WINGTYPE_BASESHIP | eine einzelne Piratenbasis | 19
WINGTYPE_WEAPONBASE2 | ein Wing aus Waffenplattformen mit je 2 Kanonen | 20


AddFilter

AddFilter( { Camera, Filter, Value1, Value2 } ) : {}

Trägt besondere Effekte in die Kamera ein.
Effekte, die nur am Start wirken, sollten sofort nach dem Erzeugen eingetragen werden, damit es nicht zu unerwünschten Verzögerungen kommt.
Ungültige Werte für den Filter haben keine Auswirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der Kamera
Filter | unsigned int | TCameraFilter | Effekt, den die Kamera ausführen soll
Value1 | float | n/a | Sinn ist abhängig von dem Filter
Value2 | float | n/a | Sinn ist abhängig von dem Filter

Rückgabetabelle
leer

TCameraFilter-Tabelle
Filter | Zeitbereich | Effekt | Parameter 1 | Parameter 2
CAMERA_FILTER_BLACK | Kamerastart | Bild bleibt eine halbe Sekunde schwarz | - | -
CAMERA_FILTER_BLACK_IN | Kamerastart | Einblenden aus schwarz | - | -
CAMERA_FILTER_BLACK_OUT | Kameraende | Ausblenden nach schwarz | - | -
CAMERA_FILTER_BLUR | immer | Weichzeichner | - | -
CAMERA_FILTER_SHAKE | immer | Kamera wackelt | - | -
CAMERA_FILTER_WHITE_IN | Kamerastart | Einblenden aus weiß | - | -
CAMERA_FILTER_WHITE_OUT | Kameraende | Ausblenden nach weiß | - | -
CAMERA_FILTER_FLASH | Kamerastart | Blendet zuerst nach weiß ein und geht dann wieder auf die normalen Werte zurück | Dauer der Blende nach weiss in Sekunden | Dauer der Blende von weiss auf die normalen Werte in Sekunden
CAMERA_FILTER_FOV | immer | Field Of View: Ändert kontinuierlich den Kamerawinkel | Dauer bis zur maximalen Winkeländerung in Sekunden | Faktor für den Kamerawinkel. Positive Werte zoomen weg, negative zoomen heran

Beispiel

-- Kamera an einer Position erzeugen
V.Cam = NCamera.CreatePosCam( {
    Object = V.Ship,
    Position = { 2000, 400, 200 },
    Time = 4.5
} ).Camera

-- Kamera soll aus dem Dunkel einblenden
NCamera.AddFilter( { Camera = V.Cam, Filter = CAMERA_FILTER_BLACK_IN } )

-- am Ende soll nach schwarz ausgeblendet werden
NCamera.AddFilter( { Camera = V.Cam, Filter = CAMERA_FILTER_BLACK_OUT } )


CreateBoundCam

CreateBoundCam( { TargetObject, BindObject, Distance, Time, Immediate } ) : { Camera }

Erzeugt eine Kamera, die von einem gegebenen BindObject auf das TargetObject schaut.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
TargetObject | unsigned int | CObjectHandle oder CWingHandle | CWing oder CSpaceObject, das beobachtet wird
BindObject | unsigned int | CObjectHandle, default=PlayerShip | das CSpaceObject, das die Blickrichtung auf TargetObject festlegt
Distance | float | n/a | Kameraabstand von BindObject in Richtung TargetObject. Ist Distance negativ, ist das BindObject zu sehen.
Time | float | 0.0f < Time | Lebensdauer der Kamera in Sekunden
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Beispiel

-- Die Kamera schaut für 8.5 Sekunden vom Spielerschiff aus auf ein Hunter-Schiff.
-- Sie ist 50m von dem Hunter-Schiff entfernt und wird sofort gestartet.
V.Cam = NCamera.CreateBoundCam( { TargetObject = V.Hunter, Time = 8.5, Immediate = true } ).Camera


CreateDeath

CreateDeath( { Object, Time } ) : { Camera }

Erzeugt eine Kamera, die das gegebene Objekt filmt und auch über dessen Vernichtung die letzte Position weiterfilmt. Diese Dauer kann im 'Time' Parameter angegeben werden. Die Kamera wird immer sofort angezeigt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | CSpaceObject, das beobachtet wird
Time | float | 0.0f < Time, default=unendlich | Lebensdauer der Kamera in Sekunden nach dem Ableben des Objekts

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Beispiel

-- Todeskamera starten
V.Cam = NCamera.CreateDeath( { Object = V.Hunter, Time = 3 } ).Camera


CreateDialog

CreateDialog( { Wing, Type, Time, Immediate } ) : { Camera }

Erzeugt eine vorgefertigte Kamera für einen Wing, die für Dialoge verwendet werden kann. Die Kamera wird nach Ablauf von 'Time' zerstört und erzeugt ein 'Camera'-Event.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handle des zu beobachtenden Wings
Type | enum | DIALOG_TYPE_1, DIALOG_TYPE_EIGHT, DIALOG_TYPE_TURN | Typ der Kamera
Time | float | 0.0f < Time, default=2000.0f | Lebensdauer der Kamera in Sekunden
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Parametertabelle für Type
Konstante | Kommentar | Wert
DIALOG_TYPE_1 | Kamera fährt von schräg oben auf den Leader des Wings zu und verfolgt ihn dann aus einer Perspektive oberhalb des Spielerschiffs. | 0
DIALOG_TYPE_EIGHT | Kamera fährt zunächst vor dem Wingleader hin und her und fliegt dann in Achterschleifen um ihn herum. | 1
DIALOG_TYPE_TURN | Kamera fährt langsam vom Spieler aus schräg nach links oben auf den Wing zu und dreht sich dann langsam um den Leader. | 2

Beispiel

-- Dialogkamera für den Frachter erzeugen
V.Camera = NCamera.CreateDialog( {
    Wing = V.Trader,
    Type = DIALOG_TYPE_EIGHT,
    Immediate = true
} ).Camera


CreateDialogObj

CreateDialogObj( { Object, Type, Time, Immediate } ) : { Camera }

Erzeugt eine vorgefertigte Kamera für ein CSpaceObject, das im Weltraum ist. Die Kamera wird nach Ablauf von 'Time' zerstört und erzeugt ein 'Camera'-Event.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des zu beobachtenden CSpaceObjects (Schiff, Orbiter oder sonstige, aber kein Wing!)
Type | enum | DIALOG_TYPE_1, DIALOG_TYPE_EIGHT, DIALOG_TYPE_TURN | Typ der Kamera
Time | float | 0.0f < Time, default=2000.0f | Lebensdauer der Kamera in Sekunden
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Parametertabelle für Type
Konstante | Kommentar | Wert
DIALOG_TYPE_1 | Kamera fährt von schräg oben auf das Objekt zu und verfolgt es dann aus einer Perspektive oberhalb des Spielerschiffs. | 0
DIALOG_TYPE_EIGHT | Kamera fährt zunächst vor dem Objekt hin und her und fliegt dann in Achterschleifen um es herum. | 1
DIALOG_TYPE_TURN | Kamera fährt langsam vom Spieler aus schräg nach links oben auf das Objekt zu und dreht sich dann langsam um es herum. | 2

Beispiel

-- Dialogkamera für den Frachter erzeugen
V.Camera1 = NCamera.CreateDialogObj( {
    Object = V.Freighter,
    Type = DIALOG_TYPE_EIGHT,
    Immediate = true
} ).Camera

-- Dialogkamera für einen Container erzeugen
-- (was immer man auch mit einem Container bereden will)
V.Camera2 = NCamera.CreateDialogObj( {
    Object = V.Container,
    Type = DIALOG_TYPE_1
} ).Camera


CreateFreeCam

CreateFreeCam( { TabTargetPosition, TabCamPosition, Time, BaseObj, Immediate } ) : { Camera }

Erzeugt eine Kamera, die sich durch die gegebenen CamPositionen bewegt und dabei auf die gegebenen TargetPositionen schaut. Wird 'BaseObj' angegeben, so sind alle Koordinaten relativ zu diesem Objekt und die Kamera wird zusammen mit dem Objekt bewegt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
TabTargetPosition | table:table[3] : float | n/a | Tabelle mit absoluten Zielkoordinaten
TabCamPosition | table:table[3] : float | n/a | Tabelle mit absoluten Kamerakoordinaten
Time | float | 0.0 < Time | Laufzeit der Kamera in Sekunden
BaseObj | unsigned int | CObjectHandle | Objekt, zu der die Kamera relativ positioniert werden soll
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Beispiel

-- Freie Kamera erzeugen, die eine Wegpunktfolge abfliegt.
V.Camera = NCamera.CreateFreeCam( {
    TabTargetPosition = {
        { 0, 0, 100 },
        { 100, 0, 100 },
        { 100, 0, 0 },
        { 0, 0, 0 }
    },
    TabCamPosition = {
        { 1000, 0, 1000 },
        { 2000, 0, 1000 },
        { -1000, 0, 1000 }
    },
    Time = 10.0,
    Immediate = true
} ).Camera


CreateMenace

CreateMenace( { Wing, Type, Immediate } ) : { Camera }

Erzeugt eine Bedrohungskamera für den übergebenen Wing. 'Type' wählt eine von 4 vordefinierten Kameras mit verschiedenen Bewegungsabläufen aus. Die Kamera läuft genau 5 Sekunden, zerstört sich am Ende ihrer Bewegung selbst und erzeugt ein 'Camera'-Event.
Fehler: Die Funktion erzeugt kein "ActionCamStart"-Event!

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handle des Wings, der beobachtet werden soll
Type | enum | MENACE_TYPE_1, MENACE_TYPE_2, MENACE_TYPE_3, MENACE_TYPE_4, MENACE_INVALID | Typ der Kamera
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Parametertabelle für Type
Konstante | Kommentar | Wert
MENACE_TYPE_1 | Kamera zeigt den Wing kurz von der Seite und fliegt dann von ihm weg. | 0
MENACE_TYPE_2 | Kamera fliegt auf den Leader des Wings von oben zu und entfernt sich dann wieder. | 1
MENACE_TYPE_3 | Kamera dreht sich von rechts neben dem Wing hinter ihn und fliegt dann über den Leader hinweg weiter geradeaus. | 2
MENACE_TYPE_4 | Kamera fliegt von schräg oben langsam auf den Leader des Wings zu und bleibt dann stehen. | 3
MENACE_INVALID | Wählt eine der 4 Bedrohungskameras zufällig aus. | 4

Beispiel

-- Bedrohungskamera für die Piraten erzeugen
V.Camera = NCamera.CreateMenace( {
    Wing = V.PirateWing,
    Type = MENACE_TYPE_1,
    Immediate = true
} ).Camera


CreateObject

CreateObject( { Object, TurnSteps, PostSteps, AngleX1, AngleX2, AngleY1, AngleY2, Distance1, Distance2, Immediate } ) : { Camera }

Erzeugt eine Kamera die auf ein Objekt ausgerichtet ist und sich den Parametern entsprechend bewegt. Die Kamera kann dabei um die X- und die Y-Achse des Objekts rotiert und die Distanz zum Objekt variiert werden. Diese Bewegungen finden innerhalb der durch 'TurnSteps' vorgegebenen Zeit statt. Nach Ablauf von TurnSteps+PostSteps zerstört sich die Kamera selber und es wird ein 'Camera'-Event ausgelöst. Anders als sonst üblich werden hier die Winkel nicht im Bogenmaß, sondern in Grad angegeben.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Das Objekt, auf das die Kamera ausgerichtet ist.
TurnSteps | unsigned int | >= 0 | Bewegungsdauer in Zeitschritten, 1 Zeitschritt = 1/25 Sekunde
PostSteps | unsigned int | n/a | Haltedauer nach der Bewegung in Zeitschritten
AngleX1 | float | n/a | Startwinkel in Grad bzgl. der X-Achse des Objekts
AngleX2 | float | n/a | Endwinkel in Grad bzgl. der X-Achse des Objekts
AngleY1 | float | n/a | Startwinkel in Grad bzgl. der Y-Achse des Objekts
AngleY2 | float | n/a | Endwinkel in Grad bzgl. der Y-Achse des Objekts
Distance1 | float | > 0.0f | Startdistanz zum Objekt
Distance2 | float | > 0.0f | Enddistanz zum Objekt
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Camera

Beispiel

-- Diese Kamera blickt von vorne oben auf ein Schiff, dreht sich innerhalb von 5 Sekunden
-- hinter das Schiff und entfernt sich dabei vom Schiff. Die Kamera bleibt anschließend
-- 1 Sekunde in dieser Position, bevor sie automatisch zerstört wird.
V.Camera = NCamera.CreateObject( {
    Object = V.Ship,
    TurnSteps = 125,
    PostSteps = 25,
    AngleX1 = 45.0,
    AngleX2 = 45.0,
    AngleY1 = 180.0,
    AngleY2 = 0.0,
    Distance1 = 50.0,
    Distance2 = 150.0,
    Immediate = true
} ).Camera


CreatePosCam

CreatePosCam( { Object, Position, Time, Immediate } ) : { Camera }

Erzeugt eine vorgefertigte Kamera für einen Wing oder ein CSpaceObject, das im Weltraum ist. Die Kamera wird auf die angegebene Position gesetzt und schaut auf ihr Target. Die Kamera wird nach Ablauf von 'Time' zerstört und erzeugt ein 'Camera'-Event.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CWingHandle oder CObjectHandle | Handle des zu beobachtenden CWings oder CSpaceObjects
Position | table[3] : float | n/a | Absolute Position der Kamera
Time | float | 0.0f < Time | Lebensdauer der Kamera in Sekunden
Immediate | bool | default=false | Kamera sofort anzeigen (true), oder in die Warteschlange hängen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der erzeugten Kamera

Beispiel

-- 4.5 Sekunden dauernde Positionkamera für den Frachter erzeugen
V.Camera1 = NCamera.CreatePosCam( {
    Object = V.Ship,
    Position = { 2000.0, 400.0, 200.0 },
    Time = 4.5
    Immediate = true
} ).Camera

-- Zweite Positionkamera für 6 Sekunden dem selben Frachter folgen lassen
V.Camera2 = NCamera.CreatePosCam( {
    Object = V.Ship,
    Position = { 2000.0, -400.0, 300.0 },
    Time = 6.0,
    Immediate = false
} ).Camera


ChangeToCanyon

ChangeToCanyon( { Canyon, Segment } ) : {}

Lässt das Spielerschiff in den Canyon oder das S'kaa-Mutterschiff wechseln und platziert es in 'Segment'. Befindet sich der Spieler bereits im Canyon oder Mutterschiff, so hat die Funktion keine Auswirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Canyon | unsigned int | 0..1 | Nummer des Canyonmodells: 0 = KabroTunnel, 1 = S'kaaTunnel
Segment | unsigned int | n/a | Nummer des Segments. Die Anzahl der Segmente ist vom Modell anhängig: Kabros Versteck = 0 bis 63 S'kaa-Mutterschiff = 0 bis 137

Rückgabetabelle
leer

Beispiel

-- Den Spieler in den Canyon setzen und am Anfang platzieren
NCanyon.ChangeToCanyon( { Canyon = 0, Segment = 0 } )


ChangeToSpace( {} ) : {}

Wechselt zurück in den Weltraum. Befindet sich der Spieler bereits im Weltraum, so hat die Funktion keine Auswirkung.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Spieler kehrt in den Weltraum zurück
NCanyon.ChangeToSpace({})


ChangeToWeaponFactory( {} ) : {}

Lässt das Spielerschiff in die Waffenfabrik wechseln und platziert es an der Startposition. Befindet sich der Spieler bereits im Canyon oder der Waffenfabrik, so hat die Funktion keine Auswirkung. Im Gegensatz zum Kabro-Canyon und dem S'kaa-Mutterschiff gibt es hier keine Segmente, es müssen kartesische Koordinaten für die Positionen verwendet werden. Die Startposition befindet sich an { -6397, 141, -3455 }.

Achtung: Die Erzeugung von Wings und Schiffen in der Waffenfabrik ist absolut sinnlos!
Normale Wings und CStarShips werden zwar erzeugt und können auch platziert und abgefragt werden, sie sind also tatsächlich vorhanden, jedoch absolut unsichtbar und gegenstandslos, man kann durch sie hindurch fliegen, ohne sie zu bemerken oder zu kollidieren. Sie lassen sich auch durch keinerlei speziellen Befehle wie NShip.SetCloaked sichtbar machen. Bringt man sie mit NShip.Explode zur Explosion, ist der dem Schiff zugehörige Explosionseffekt allerdings zu sehen, ohne dabei das Schiff selbst zu zeigen. Lässt man von beladenen Frachtern die Container abwerfen, werden auch diese plötzlich aus dem Nichts sichtbar und schweben ganz normal ein Stück davon.
Dies betrifft alle normalen Wings, Satelliten und Waffenplattformen. Canyon-Schiffe lassen sich wegen den fehlenden Segmenten überhaupt nicht erzeugen.
Minen und Container lassen sich dagegegen ganz normal erzeugen, wobei Container nicht aufgenommen werden können. Es wird keine Frachtdrohne ausgeschickt, obwohl die entsprechende Meldung kommt.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Den Spieler in die Waffenfabrik packen und am Anfang platzieren
NCanyon.ChangeToWeaponFactory({})


CreateForceField

CreateForceField( { Type, Locator, Notify } ) : { Handle }

Erzeugt ein Kraftfeld im Canyon (Kabro oder S'kaa) oder in der Waffenfabrik. Das Kraftfeld kann nur erzeugt werden, wenn das Canyon- oder Waffenfabrikmodell den Spawnpunkt (Lokator) zur Verfügung stellt. Ist 'Notify' true, kann das Kraftfeld durchflogen werden und es wird ein CANYON_TRIGGER Event mit dem Handle des Kraftfeldes ausgelöst.
Hinweis: Es wird nicht verhindert, mehrere Kraftfelder am gleichen Lokator zu erzeugen. In diesem Falle ist das Verhalten undefiniert.
Achtung: Ist der Parameter 'Notify' false oder fehlt und die Energiesperre damit eigentlich undurchdringlich, kann der Spieler sie mit aktiviertem Plasmaschild und brutaler Gewalt trotzdem durchbrechen. Allerdings kommt danach das Kollisionsmodell von Waffenfabrik oder Mutterschiff völlig aus dem Ruder und alle Wände und Objekte können durchflogen werden, als wären sie gar nicht vorhanden. Das macht dann aber keinen Spaß mehr und sollte besser vermieden werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | unsigned int | n/a | Typ des Kraftfelds: 0 = Große Energiebarriere 1 = Energiesperre mit 4 Strahlen 2 = Energiesperre mit 5 Strahlen 3 = Unsichtbare Energiesperre, ist daher sehr gefährlich
Locator | unsigned int | n/a | Index des Lokators ( fortlaufende Nummer, beginnend bei 0 )
Notify | bool | default = false | false = Spieler kollidiert mit dem Feld und kann es nicht durchdringen true = Spieler kann das Feld durchfliegen und löst damit ein Event aus

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | CStarShipHandle | Handle des Kraftfelds

Beispiel


CreateGenerator

CreateGenerator( { Type, Locator } ) : { Handle }

Erzeugt einen Schutzschildgenerator im Canyon (Kabro oder S'kaa) oder in der Waffenfabrik. Der Generator zählt als StarShip, die Zerstörung kann also über das 'StarshipDestroyed'-Event abgefragt werden. Der Generator kann nur erzeugt werden, wenn das Canyonmodell den Spawnpunkt (Lokator) zur Verfügung stellt. Hinweis: Es wird nicht verhindert, mehrere Generatoren am gleichen Lokator zu erzeugen. In diesem Falle ist das Verhalten undefiniert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | unsigned int | Generatortyp | Typ des Generators
Locator | unsigned int | n/a | Index des Lokators ( fortlaufende Nummer, beginnend bei 0 )

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | CStarShipHandle | Handle des Generators

Generatortypen
Name | Kommentar | Wert
GENERATOR_KABRO | Der Generator in der ersten Tunnelmission | 0
GENERATOR_BRONIS_0 | Ein blauer Generator in der Waffenfabrik | 1
GENERATOR_BRONIS_1 | Ein roter Generator in der Waffenfabrik | 2
GENERATOR_BRONIS_2 | Ein grüner Generator in der Waffenfabrik | 3
GENERATOR_SKAA | Ein Generator im Skaatunnel | 4
GENERATOR_SKAA_CORE | Der Hauptreaktor des Skaamutterschiffs | 5

Beispiel


CreateShip

CreateShip( { Type, Look, Race, Level, Segment, StartSpline, EndSpline } ) : { Ship }

Erzeugt ein Canyon-Schiff anhand der übergebenen Parameter. 'StartSpline' und 'EndSpline' werden nicht immer beide für alle Typen verwendet, sind aber trotzdem anzugeben (siehe Typtabelle unten). Die Schiffe haben standardmäßig keine Geschwindigkeit außer beim Typ CST_ENTER. Die Frachter können nicht mit Containern beladen werden, beim Versuch wird eine Fehlermeldung ausgelöst. Mit Taxis funktioniert es hingegen.
Achtung: In der Waffenfabrik lassen sich keine Schiffe erzeugen!
Hinweis: Für den Feldbezeichner 'Look' in der Parametertabelle funktionieren SPACE_SKAADRONE und SPACE_SKAASWARM nicht, die Drohnen müssen mit SPACE_HUNTER definiert werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | CST_ON_SPLINE, CST_ON_SPLINE_REVERSE, CST_ENTER, CST_ENTER_REVERSE, CST_HOVER, CST_HOVER_REVERSE, CST_LANDING | Bewegungstyp des Schiffs (siehe Typtabelle unten)
Look | enum | SPACE_CRUISER, SPACE_HUNTER, SPACE_MILITARY, SPACE_PIRATE, SPACE_PIRATE_FREIGHTER, SPACE_POLICE, SPACE_TAXI, SPACE_TRANSPORTER, SPACE_WEAPONBASE | Modelltyp (die Erzeugung ist abhängig vom verwendeten Canyon-Typ, z.B. lassen sich keine Skaadrohnen im Kabro-Canyon erzeugen)
Race | enum | Rassen | Volk
Level | unsigned int | n/a | Level des Schiffs
Segment | unsigned int | Abhängig vom Canyon-Modell, aber nicht in der Waffenfabrik | Nummer des Segments, in dem das Schiff platziert wird
StartSpline | enum | SPLINE_PLAYER, SPLINE_AI_0, SPLINE_AI_1, SPLINE_AI_2, SPLINE_AI_3, SPLINE_OVERTURN, SPLINE_ENTER | Spline auf dem das Schiff bei Erzeugen platziert wird
EndSpline | enum | SPLINE_PLAYER, SPLINE_AI_0, SPLINE_AI_1, SPLINE_AI_2, SPLINE_AI_3, SPLINE_OVERTURN, SPLINE_ENTER | Spline auf den das Schiff wechselt (bei bestimmten Werten für 'Type', siehe Typtabelle)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des erzeugten Schiffs

Typtabelle für den Parameter 'Type'
Type | StartSpline | EndSpline | Beschreibung
CST_ON_SPLINE | ja | nein | Schiff wird direkt auf dem ersten Punkt des Splines im Segment gesetzt und folgt diesem Spline.
CST_ON_SPLINE_REVERSE | ja | nein | Schiff wird in Gegenrichtung direkt auf dem letzten Punkt des Splines im Segment gesetzt und folgt diesem Spline in Gegenrichtung.
CST_ENTER | nein | ja | Schiff wird auf den Spline SPLINE_ENTER des Segments gesetzt und folgt diesem bis zum Ende. Danach wechselt es auf 'EndSpline' und folgt diesem.
CST_ENTER_REVERSE | nein | ja | Schiff wird auf den Spline SPLINE_ENTER des Segments gesetzt und folgt diesem bis zum Ende. Danach wechselt es auf 'EndSpline' und folgt diesem in Gegenrichtung. Funktioniert nur, wenn SPLINE_ENTER in Gegenrichtung angelegt ist.
CST_HOVER | ja | ja | Schiff wird auf den ersten Punkt des Spline 'StartSpline' gesetzt und hovert auf der Stelle. Wird für dieses Schiff ein SetShipLiftOff() aufgerufen, hebt es ab und folgt dem Spline 'EndSpline'.
CST_HOVER_REVERSE | ja | ja | Schiff wird auf den ersten Punkt des Spline 'StartSpline' gesetzt und hovert auf der Stelle. Wird für dieses Schiff ein SetShipLiftOff() aufgerufen, hebt es ab und folgt dem Spline 'EndSpline' in Gegenrichtung.
CST_LANDING | ja | ja | Schiff wird auf den ersten Punkt des Spline 'StartSpline' gesetzt und folgt diesem bis zum Ende. Dann wird ein Approach-Maneuver eingeleitet, welches das Schiff auf den ersten Punkt des Splines 'EndSpline' steuert. Die Ausrichtung wird durch die ersten beiden Punkte von 'EndSpline' bestimmt.

Beispiel

-- Mortok-Piraten erzeugen, der in Durchflugrichtung in den Canyon eintaucht

V.Ship = NCanyon.CreateCanyonShip( {
    Type = CST_ENTER,
    Look = SPACE_HUNTER,
    Race = RACE_MORLOK,
    Level = V.AIStufe,
    Segment = V.Einsetzsegment,
    StartSpline = SPLINE_ENTER,
    EndSpline = SPLINE_AI_0 + Splinewahl
) }.Ship


CreateSpeedBoost

CreateSpeedBoost( { Locator } ) : { Handle }

Erzeugt ein grünes Kraftfeld im S'kaa-Mutterschiff (nicht im Canyon oder Waffenfabrik), welches das Schiff stark beschleunigt, wenn es hineinfliegt. Das Kraftfeld kann nur erzeugt werden, wenn das Mutterschiffmodell den Spawnpunkt (Lokator) zur Verfügung stellt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Locator | unsigned int | n/a | Index des Lokators ( fortlaufende Nummer, beginnend bei 0 )

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | n/a | Handle des Beschleunigungsfeldes

Beispiel


DestroyForceField

DestroyForceField( { Handle } ) : {}

Zerstört ein Kraftfeld.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | CStarShipHandle | Handle des Kraftfelds

Rückgabetabelle
leer

Beispiel


SetMaxY

SetMaxY( { Value } ) : {}

Setzt den Y-Wert über Canyonniveau, ab dem die Höhenkontrolle ein weiteres Steigen des Spielers verhindert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Value | float | 0.0 < Value | Höhenwert

Rückgabetabelle
leer

Beispiel


SetMinY

SetMinY( { Value } ) : {}

Setzt den Y-Wert über Canyonniveau, ab dem die Höhenkontrolle beginnt abzuriegeln. Sollte etwa 50m unter dem Max-Wert liegen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Value | float | 0.0 < Value | Höhenwert

Rückgabetabelle
leer

Beispiel


SetShipHostile

SetShipHostile( { Ship, Hostile } ) : {}

Setzt den Feindstatus eines Schiffs im Canyon.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs. Muss ein CanyonShip sein
Hostile | bool | n/a | Schiff soll feindlich sein (true) oder freundlich (false)

Rückgabetabelle
leer

Beispiel


SetShipLiftOff

SetShipLiftOff( { Ship, Spline } ) : {}

Ein Schiff soll abheben und auf einen Spline wechseln. Funktioniert nur bei Schiffen, die mit CST_HOVER oder CST_HOVER_REVERSE erzeugt wurden, ansonsten hat der Aufruf keine Wirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs. Muss ein CanyonShip sein
Spline | enum | SPLINE_PLAYER, SPLINE_AI_0, SPLINE_AI_1, SPLINE_AI_2, SPLINE_AI_3, SPLINE_OVERTURN, SPLINE_ENTER | Spline, auf den eingeschwenkt werden soll

Rückgabetabelle
leer

Beispiel


SetShipSpeed

SetShipSpeed( { Ship, Speed, Value } ) : {}

Gibt einem Canyon-Schiff eine Geschwindigkeitsvorgabe. Referenziert 'Ship' kein Schiff vom Typ STARSHIP_TYPE_CANYONSHIP, schlägt die Funktion mit einer Fehlermeldung fehl.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs. Muss ein CanyonShip sein
Speed | enum | SPEED_DYNAMIC, SPEED_FIXED | Typ für Geschwindigkeitswahl (siehe Typtabelle)
Value | float | 0.0f <= Value, default=1.0f | Geschwindigkeit für SPEED_FIXED

Rückgabetabelle
leer

Typtabelle für Parameter 'Speed'
Wert | Beschreibung
SPEED_DYNAMIC | Das Schiff passt sich der Geschwindigkeit des Spielerschiffs an und versucht immer in seiner Nähe zu bleiben. Ist das Schiff hinter dem Spieler, so wird es aber immer überholen und sich vor den Spieler setzen. Eine Minimalgeschwindigkeit wird jedoch niemals unterschritten, das Schiff bleibt also niemals stehen.
SPEED_FIXED | Das Schiff bekommt über den Parameter 'Value' einen Geschwindigkeitswert zugewiesen, den es konstant beibehält.

Beispiel


SetTurn

SetTurn( { Turn } ) : {}

Standardmäßig kann der Spieler im Kabro-Canyon nicht gegen die vorgegebene Durchflugrichtung steuern. Möchte man Freiflugzonen definieren, kann dies mit SetTurn abgeschaltet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Turn | bool | n/a | Spielerschiff darf wenden (true) oder nicht (false).

Rückgabetabelle
leer

Beispiel


ToggleSplineMode( {} ) : {}

Schaltet die Steuerung des Spielerschiffs zwischen Freiflugmodus und Splinemodus um. Der Splinemodus kann für geführte Sequenzen mit ActionCams verwendet werden (z. B. Talkessel im Canyon, Fluchttunnel in Waffenfabrik und Mutterschiff).

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel


AddMessage

AddMessage( { Text, Voice, Video, Sender, CommInOut, Actor } ) : { Message }

Sendet eine Funkmeldung mit hoher Priorität, d.h. alle Standard-Funkmeldungen der Simulation werden augenblicklich unterbrochen. Werden mehrere Nachrichten per 'AddMessage' gesendet, so werden sie in dieser Reihenfolge nacheinander abgespielt. Endet eine Funkmeldung, wird ein 'CommEnd' Event erzeugt. Wird statt des Parameters 'Video' der Parameter 'Sender' verwendet, so wird ein zum Schiffstyp und dem Volk passendes Video gewählt. Wird der 'Actor'-Parameter verwendet und handelt es sich um einen NPC-Actor (Ramirez, Eona, etc.), so wird für diese Nachricht der entsprechende Actor verwendet. Dieser Actor hat bei der Anzeige Vorrang vor dem eigentlichen Actor des Senders, falls der 'Sender'-Parameter angegeben ist. D.h. eine Forschungsstation kann mit dem Actor 'jiju' senden, ohne das ein SetActor(…) für die Station aufgerufen werden müsste.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Text | string | StringId aus dem LokaTool | Anzuzeigender Text der Meldung. Ist 'Text' gleich dem Prefix eines gültigen Streambezeichners und wurde ein Sender oder Akteur angegeben, kann 'Voice' weg gelassen werden und wird für die Sprachausgabe in gleicher Art wie bei 'Voice' um das Suffix ergänzt.
Voice | string | Prefix eines Bezeichners einer Stream-Resource bzw. absoluter Bezeichner einer Stream-Resource aus der KlangErzeugerDefault.xml. | Abzuspielender Stream. Ist ein Sender oder Akteur angegeben und 'Voice' kein absoluter Bezeichner eines Streams, dann ist 'Voice' das Prefix eines Bezeichners einer Stream-Resource aus der KlangErzeugerDefault.xml. Der Bezeichner wird um das Suffix "_SPOKEN_<race><actor>" erweitert, wobei Volk und Akteur dem Sender entnommen werden (z.B. "humsta00"). Falls kein Sender angegeben ist, ist 'Voice' der absolute Bezeichner einer Stream-Resource aus der KlangErzeugerDefault.xml.
Video | string | Pfad zu einem .bik Video (vollständiger Pfad + Endung .bik). | Abzuspielendes Video. Wird kein Video angegeben, so wird ein Video basierend auf dem Parameter 'Sender' gewählt, ist dieser nicht vorhanden, wird ein leeres Funkvideo verwendet.
Sender | unsigned int | CObjectHandle | Sender der Funkmeldung. Wird verwendet, um Video und Soundfile zu bestimmen.
CommInOut | bool | default=false | CommIn und CommOut Videoschnipsel für das Ein- und Ausschalten des Funkgeräts abspielen (true) oder weglassen (false)
Actor | string | Name eines Akteurs | Akteur, der für diese Nachricht gilt. Muss ein NPC sein (kein Standardakteur). Siehe auch NShip.SetActor.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Message | unsigned int | n/a | Id der Messsage (wird für die Bearbeitung des 'CommEnd'-Events benötigt) -1, wenn die Nachricht nicht abgespielt werden konnte (z.B. auf Stationen)

Beispiel

-- Funkmeldungen senden

-- Ist das übergebene Schiff ein Menschen-Jäger und hat den Akteur 0
-- so wird das Video "HUNTER_HUMAN_00.bik"
-- und das Soundfile "IDM_GLOBAL_5000_MSG_TXT_SPOKEN_HUMAN_00.mp3" ausgewählt
V.MsgId = NComm.AddMessage( {
    Text = "IDM_GLOBAL_5000_MSG_TXT",
    Voice = "IDM_GLOBAL_5000_MSG_TXT_SPOKEN",
    Sender = V.Ship,
    CommInOut = true
} ).MessageId

-- Hier soll Kayron was sagen
NShip.SetActor( { Ship = MissionLib.GetPlayerHandle(), Actor = "kayron" } )
NComm.AddMessage( {
    Sender = MissionLib.GetPlayerHandle(),
    Text = "IDM_LABENICHT_RUM",
    CommInOut = false
} )

-- Hier sagt Eona etwas, der Actor des Spielerschiffs bleibt unverändert
NComm.AddMessage( {
    Sender = MissionLib.GetPlayerHandle(),
    Text = "IDM_EONA_BLUBB",
    Actor = "eona",
    CommInOut = false
} )

-- Hier soll Ramirez etwas sagen, obwohl er eigentlich gar nicht da ist
NComm.AddMessage( { Text = "IDM_GHOST", Actor = "ramirez", CommInOut = true } )


IsQueueEmpty

IsQueueEmpty( {} ) : { Empty }

Fragt ab, ob die Nachrichtenqueue leer ist.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Empty | bool | n/a | Keine Nachrichten in der Queue (true) oder noch Nachrichten vorhanden (false)

Beispiel

-- Nächste Nachricht nur, wenn die Queue leer ist
if NComm.IsQueueEmpty({}).Empty then
    NComm.AddMessage( ParamTable )
end


Create

Create( { Type, Size, Ship|PosDesc|Position } ) : { Container }

Erzeugt einen Container des angegebenen Typs (siehe Typtabelle). Je nach Typ wird einer der Parameter 'Ship', 'PosDesc' oder 'Position' benötigt. Ist das Schiff das Spielerschiff und auf der Station gelandet, so kann mit CONTAINER_SHIP ein Missionscontainer angehängt werden. Der Platz durch diesen Container ist belegt.
Container der Größe CONTAINER_SPECIAL können nicht nur mit Geheimdienstwaffen bestückt werden, sondern auch mit Missions- oder Handelswaren. Die Kapazität für Handelswaren beträgt in diesem Fall allerdings nur 1 Tonne. Sie sind für den Beschuss mit Schiffswaffen unzerstörbar, können aber mit der Funktion "NContainer.Explode" zur Explosion gebracht werden. Ebenso können sie von Kreuzern zerstört werden, falls einer diese Container rammt.

Parametertabelle

Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | CONTAINER_POSITION, CONTAINER_SHIP, CONTAINER_SPACE, CONTAINER_ASTEROID | Typ des Containers
Size | enum | CONTAINER_SMALL, CONTAINER_MEDIUM, CONTAINER_LARGE, CONTAINER_ARTEFACT, CONTAINER_SPECIAL, CONTAINER_PASSENGER, CONTAINER_ROCK | Größenklasse des Containers
Ship | unsigned int | CStarShipHandle | Schiff, an den der Container angehängt werden soll (muss ein Frachter sein, ein Canyon-Taxi oder die Darkstar One, jedoch nur, wenn sie gelandet ist)
PosDesc | enum | Erzeugungsbereich | Positionsbeschreibung
Position | table[3] : float | n/a | Absolute Raumkoordinaten

Rückgabetabelle

Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des erzeugten Containers

Typtabelle für den Parameter 'Type'

Type | Erforderlicher Parameter | Beschreibung
CONTAINER_POSITION | Position | Container wird an der übergebenen Raumkoordinate frei im Weltall erzeugt
CONTAINER_SPACE | PosDesc | Container wird im angebenen Raumbereich erzeugt (nicht POSDESCR_EXPLICIT)
CONTAINER_SHIP | Ship | Container wird erzeugt und an das angegebene Schiff angedockt. Muss ein Frachter sein oder die Darkstar One, jedoch nur, wenn sie gelandet ist. Funktioniert nicht mit Artefaken und nur eingeschränkt mit Passagiermodulen.
CONTAINER_ASTEROID | ? (evtl. Handle des Asteroiden und Index der Position?) | Container für Minenwaren in einem Asteroiden oder Meteoritencontainer? (Testen, ob und wie der erzeugt werden kann)

Beispiel

-- Einen Container für einen Frachter erzeugen, die Größe muss zum Frachter passen.
V.ContainerShip = NContainer.Create( {
    Type = CONTAINER_SHIP,
    Size = CONTAINER_SMALL,
    Ship = V.Trader
} ).Container

-- Einen Fracht-Container hinter der Raumstation erzeugen.
V.ContainerSpace = NContainer.Create( {
    Type = CONTAINER_SPACE,
    Size = CONTAINER_MEDIUM,
    PosDesc = POSDESCR_TRADESTATION1
} ).Container

-- Einen Fracht-Container 1 Unit über der Raumstation erzeugen.
V.ContainerPos = NContainer.Create( {
    Type = CONTAINER_POSITION,
    Size = CONTAINER_LARGE,
    Position = { 0, 1000, 0 }
} ).Container

-- Einen Artefakt-Container an der Position eines explodierten Schiffs erstellen.
-- Number in 'SetUniqueItems' ist egal, es wird immer genau 1 Artefakt erzeugt.
V.Artefact = NContainer.Create( {
    Type = CONTAINER_POSITION,
    Size = CONTAINER_ARTEFACT,
    Position = V.PiratePos
} ).Container
NContainer.SetUniqueItems( { Container = V.Artefact, Number = 1 } )

-- Einen Spezial-Container erstellen...
V.Weapon = NContainer.Create( {
    Type = CONTAINER_POSITION,
    Size = CONTAINER_SPECIAL,
    Position = { V.PiratePos[1], V.PiratePos[2] - 50, V.PiratePos[3] }
} ).Container

-- ...und mit 2 Geheimdienstwaffen,
-- (Number=0 erzeugt nur einen leeren Spezialcontainer)
NContainer.SetUniqueItems( { Container = V.Weapon, Number = 2 } )

-- ...oder Missionsware,
NContainer.Equip( { Container = container, Goods = "ID_BOMB" } )

-- ...oder normaler Handelsware bestücken (1t max.)
NContainer.Equip( { Container = container, Goods = GOODS_FUELRODS } )

-- Ein Passagiermodul erzeugen. Kann mit maximal 1t Handelsware beladen werden.
V.ContainerPassenger = NContainer.Create( {
    Type = CONTAINER_POSITION,
    Size = CONTAINER_PASSENGER,
    Position = { 0, 0, 1000 }
} ).Container

-- Einen Meteoriten-Container erzeugen. Kann mit maximal 50t Handelsware beladen werden.
V.ContainerRock = NContainer.Create( {
    Type = CONTAINER_POSITION,
    Size = CONTAINER_ROCK,
    Position = { 0, 0, 1000 }
} ).Container

Die Container der Größen CONTAINER_PASSENGER und CONTAINER_ROCK sind nicht für Frachter geeignet. Beim Andocken mit der Frachtdrohne verschwinden sie und falls man sie mit dem Typ CONTAINER_SHIP erzeugt, wird das Design in normale Fracht-Container geändert.


CreateLoot

CreateLoot( { Ship, UniqueItems, Artefact } ) : { Container }

Erzeugt an der Position eines Schiffs einen Geheimdienstwaffen- oder Artefaktcontainer mit den angegebenen Inhalten. Falls weder UniqueItems noch Artefact angeben ist, wird ein Artefakt in den Container gelegt. Der Loot-Container kann nur für ein Schiff erzeugt werden, das gerade explodiert, also im 'StarshipDestroyed'-Event. Der Container wird an die Position des Schiffs gesetzt und bewegt sich zunächst mit dem letzten Geschwindigkeitsvektor des Schiffs weiter. Gleichzeitig rotiert er ein wenig.
Hinweis: Die Funktion ist nicht für Kreuzer geeignet, da diese nach der Explosion als bewegungslose Wracks zurückbleiben. Kreuzer haben während der Explosion auch keinen Geschwindigkeitsvektor mehr, da sie beim Abschuss sofort stoppen und während den Explosionen nur noch etwas rotieren. Dadurch befindet sich der Artefakt- bzw. Geheimdienstwaffen-Container dann im Inneren des Wracks und ist somit unzugänglich.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle eines Schiffs, das Schiff muss gerade zerstört werden
UniqueItems | unsigned int | 0..100 | Anzahl der Geheimdienstwaffen im Container
Artefact | unsigned int | 0 | 1 | Falls > 0 wird ein einzelnes Artefakt im Container platziert

Rückgabetabelle

Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des erzeugten Containers

Beispiel

{   -- Loot mit 2 Geheimdienstwaffen erzeugen
    1, 1, "StarshipDestroyed", function( V, Data )
    if Data.Ship == V.BossShip then
        NContainer.CreateLoot( { Ship = V.BossShip, UniqueItems = 2 } )
    end
end },

{   -- Loot mit 1 Geheimdienstwaffe erzeugen und Inhalt beim Scannen anzeigen
    1, 1, "StarshipDestroyed", function( V, Data )
    if Data.Ship == V.BossShip then
        local weapon = NContainer.CreateLoot( { Ship = V.BossShip, UniqueItems = 1 } ).Container
        NContainer.Equip( { Container = weapon, Goods = "IDL_WEAPON_04" } )
    end
end },

{   -- Loot mit einem Artefakt erzeugen, entweder so:
    1, 1, "StarshipDestroyed", function( V, Data )
    if Data.Ship == V.BossShip then
        NContainer.CreateLoot( { Ship = V.BossShip, Artefact = 1 } )
    end
end },

{   -- Loot mit einem Artefakt erzeugen, oder auch so:
    1, 1, "StarshipDestroyed", function( V, Data )
    if Data.Ship == V.BossShip then
        NContainer.CreateLoot( { Ship = V.BossShip } )
    end
end },


Destroy

Destroy( { Container } ) : {}

Zerstört den angegebenen Container. Der Container verschwindet einfach. Es wird kein CONTAINER_DESTROYED Event ausgelöst.
Hinweis: Darf nicht im Event "Container" aufgerufen werden, sonst stürzt das Programm ohne Fehlermeldung ab!

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers

Rückgabetabelle
leer

Beispiel

{   -- Spieler erreicht die Station
    -- (das Event "EnterStation" ist nicht dokumentiert, prüfen!)
    2.1, 2.1, "EnterStation", function( V, Data )
    if V.DestSystem == Data.System then
    if V.Container then
        NContainer.Destroy( { Container = V.Container } )
        V.Container = nil
    end
    end
end },

{   -- Landung auf einer Station
    3, nil, "Station", function( V, Data )
    if Data.Enter then
    if V.PlayerHasContainer then
        NContainer.Destroy( { Container = V.Container } )
        V.Container = nil
        NMission.SetState( { State = MSTATE_ACHIEVED } )
        V.Step = 0
    end
    end
end },


Equip

Equip( { Container, Goods, Amount } ) : {}

Füllt einen existierenden Container mit der angegebenen Ware. Wenn 'Amount' nicht angegeben ist, wird der Container komplett gefüllt. Übersteigt 'Amount' die verbleibende Kapazität des Containers, wird der restliche Raum gefüllt. Bei Missionswaren (StringId) hat 'Amount' keine Auswirkung.
Wurde der Container mit Missionsware beladen, kann man diese mit einem erneuten Equip jederzeit ändern. Er lässt sich jedoch nicht mehr mit Handelswaren beladen. Füllt man umgekehrt einen mit Handelsware beladenen Container nachträglich mit Missionsware, dann gehen die Handelswaren dabei verloren. Es kann immer nur eine Missionsware in den Container geladen werden.
Container vom Typ CONTAINER_SPECIAL für Geheimdienstwaffen und CONTAINER_PASSENGER für Reisende können ebenfalls mit Handelswaren beladen werden, haben in dem Fall aber nur eine Kapazität von einer Tonne.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers
Goods | enum oder string | Handelsware oder StringId aus dem LokaTool | Handelsware oder Missionsware
Amount | unsigned int | n/a | Menge der Ware

Rückgabetabelle
leer

Beispiel

-- Einen Container komplett mit Maschinenteilen füllen
NContainer.Equip( { Container = V.Container, Goods = GOODS_MACHINERY } )

-- Einen Container mit Missionswaren füllen
NContainer.Equip( { Container = V.Container, Goods = "IDM_GLOBAL_031_GOODS" } )

-- Einen Container mit unterschiedlichen Waren füllen.
-- Bei 50t-Containern hat der dritte Befehl keine Auswirkung mehr
-- und von den Kristallen werden natürlich auch nur 30t geladen.
NContainer.Equip( { Container = V.Container, Goods = GOODS_ANDROIDS, Amount = 20 } )
NContainer.Equip( { Container = V.Container, Goods = GOODS_CRYSTALS, Amount = 50 } )
NContainer.Equip( { Container = V.Container, Goods = GOODS_PROTEINS, Amount = 30 } )

-- Einen Container komplett mit zufälliger Ware füllen
local RandomGoods = MissionLib.RandomInteger( GOODS_COALHYDRATES, GOODS_DRUGS )
NContainer.Equip( { Container = V.Container, Goods = RandomGoods } )

-- Entleert einen beladenen Container wieder
NContainer.Equip( { Container = V.Container, Goods = "" } )


Explode

Explode( { Container } ) : {}

Der Container explodiert und wird zerstört. Es wird ein CONTAINER_DESTROYED Event ausgelöst.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers

Rückgabetabelle
leer

Beispiel

NContainer.Explode( { Container = V.Container } )
V.Container = nil


GetAlignment

GetAlignment( { Container } ) : { Position, Front, UpDir }

Liest die Ausrichtung eines Containers aus.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | absolute Koordinate des Containers
Front | table[3] : float | n/a | z-Achse, Richtungsvektor der Containerachse (Ebenenwinkel)
UpDir | table[3] : float | n/a | y-Achse, parallel zum Vektor durch die Containerdrohnen (Höhenwinkel)

Beispiel

-- Einen Artefakt-Container erstellen
V.Container = NContainer.Create( {
    Type = CONTAINER_SPACE,
    Size = CONTAINER_ARTEFACT,
    PosDesc = POSDESCR_INTERCEPTION
} ).Container

-- die Position des Containers auslesen
V.Position = NContainer.GetAlignment( { Container = V.Container } ).Position
V.Front = NContainer.GetAlignment( { Container = V.Container } ).Front
V.UpDir = NContainer.GetAlignment( { Container = V.Container } ).UpDir

-- oder besser so, die Funktion wird hier nur einmal aufgerufen:
local Alignment = NContainer.GetAlignment( { Container = V.Container } )
V.Position = Alignment.Positon
V.Front = Alignment.Front
V.UpDir = Alignment.UpDir


GetMissionGood

GetMissionGood( { Container } ) : { SpecialGood, SpecialName }

Prüft, ob der Container Missionswaren enthält. Enthält er keine, wird in 'SpecialName' ein leerer String zurückgeliefert. Somit darf bei der Prüfung auf eine bestimmte Missionsware die Abfrage mittels 'SpecialGood' auch weggelassen und direkt auf 'SpecialName' geprüft werden.
Handelswaren können damit nicht ausgelesen werden. Leider existiert dafür auch keine andere Funktion.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle eines Containers, der geprüft wird

Rückgabetabelle

Feldbezeichner | Datentyp | Wertebereich | Kommentar
SpecialGood | bool | n/a | ist gesetzt, wenn der Container Missionswaren enthält
SpecialName | String | n/a | Die StringId des Namens der Missionsware

Beispiel

-- Die Missionswaren des Containers auslesen
local goods = NContainer.GetMissionGood( { Container = V.Container } )

-- Name anzeigen, falls Missionsware drin ist
if goods.SpecialGood then
    -- Name der Missionsware
    NGUI.ShowInfoText( { Text = goods.SpecialName } )
end

-- Anzeigen, ob eine bestimmte, keine oder irgendeine Missionsware drin ist
if goods.SpecialName == "IDM_STORY_025_ISOTOPE" then
    -- "Missionswaren"
    NGUI.ShowInfoText( { Text = "ID_GOODS_25" } )
elseif goods.SpecialName == "" then
    -- "Keine Waren"
    NGUI.ShowInfoText( { Text = "ID_GOODS_24" } )
else
    -- "Unbekannt"
    NGUI.ShowInfoText( { Text = "ID_UNKNOWN" } )
end


GetType

GetType( { Container } ) : { Type }

Liefert zu dem gegebenen Container den Größentyp des Containers.
Existiert der Container nicht, wird der Typ -1 (CONTAINER_NONE*) zurückgegeben.

* Konstante in der MissionLibEx.lua definiert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle eines Containers, der geprüft wird.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | int | Containertyp | der Größentyp des Containers

Beispiel

-- Nur Container mit Artefakten betrachten
if NContainer.GetType( { Container = V.Container } ).Type == CONTAINER_ARTEFACT then
    eiguggeda
end


IsInSpace

IsInSpace( { Container } ) : { InSpace }

Prüft, ob sich der angegebene Container im All befindet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
InSpace | unsigned int | 0..1 | Der Container ist im Weltraum (1) oder nicht (0)

Beispiel

if NContainer.IsInSpace( { Container = V.Container } ).InSpace == 1 then
    V.Info = "Da ist ein Container"
else
    V.Info = "Da ist nix"
end


SetAlignment

SetAlignment( { Container, Position, Front, UpDir } ) : {}

Setzt einen Container auf die gegebene Position. Die Vorderseite zeigt in Richtung Front. Wird UpDir nicht angegeben, wird der Container an der Y-Achse des Systems aufgerichtet. Hatte sich der Container vor der Positionsänderung bewegt, so ist er danach regungslos. Die Position sollte frei sein, damit die Logik nicht im nächsten Zeitschritt eine Kollision feststellt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers
Position | table[3] : float | n/a | Absolute Koordinate (default ist die aktuelle Position)
Front | table[3] : float | n/a | Richtungsvektor für Containerachse, default ist die aktuelle Richtung (Ebenenwinkel)
UpDir | table[3] : float | n/a | Richtungsvektor, an dem der Container aufgerichtet wird, default ist die Y-Achse des Systems (Höhenwinkel)

Rückgabetabelle
leer

Beispiel

-- Einen Artefakt-Container erstellen
V.Container = NContainer.Create( {
    Type = CONTAINER_SPACE,
    Size = CONTAINER_ARTEFACT,
    PosDesc = POSDESCR_INTERCEPTION
} ).Container

-- den Container auf eine bestimmte Position setzen
NContainer.SetAlignment( {
    Container = V.Container,
    Position = { 0.0, 3000.0, 0.0 },
    Front = { 0.0, -3000.0, 10000.0 }
} )

-- richtet einen Container so aus, das er in der X-Z-Achse liegt
NContainer.SetAlignment( { Container = V.Container } )


SetArtefact

SetArtefact( { Container } ) : {}

Diese Funktion gibt es nicht!

Die Beschreibung bleibt aber mal vorläufig noch hier drin.

Funktioniert nur mit Containern, die mit der Größe CONTAINER_ARTEFACT erzeugt wurden. Das Artefact-Flag wird gesetzt, so dass der Spieler einen Artefakt-Punkt erhält, wenn er den Container aufnimmt.

Hinweis: Funktioniert nicht mit Containern vom Typ CONTAINER_SHIP. Darkstar stürzt in dem Fall ab!

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers

Rückgabetabelle
leer

Beispiel

-- Einen Artefakt-Container erstellen
V.Container = NContainer.Create( {
    Type = CONTAINER_SPACE,
    Size = CONTAINER_ARTEFACT,
    PosDesc = POSDESCR_INTERCEPTION
} ).Container

NContainer.SetArtefact( { Container = V.Container } )


SetIllegal

SetIllegal( { Container, Illegal } ) : {}

Markiert bzw. demarkiert einen Container als illegal, d.h. die Polizei wird beim Scannen fündig werden.
Hinweis: Hat für KI-Schiffe keine Auswirkung, wenn sie illegale Fracht geladen haben. Sie werden von der Polizei nicht angegriffen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers
Illegal | bool | n/a | Container enthält illegale Ware (true) oder nicht (false)

Rückgabetabelle
leer

Beispiel

-- Einen Container mit heißer Ware erstellen
V.Container = NContainer.Create( {
    Type = CONTAINER_SPACE,
    Size = CONTAINER_LARGE,
    PosDesc = POSDESCR_INTERCEPTION
} ).Container
NContainer.Equip( { Container = V.Container, Goods = GOODS_LIQUOR } )

NContainer.SetIllegal( { Container = V.Container, Illegal = true } )


SetUniqueItems

SetUniqueItems( { Container, Number } ) : {}

Funktioniert nur mit Containern, die mit den Größen CONTAINER_ARTEFACT oder CONTAINER_SPECIAL erzeugt wurden. Die Anzahl der enthaltenen Unique Items wird gesetzt (wirkt nur für Geheimdienstwaffen). Die Unique Items werden in das Lager des Spielerschiffes übertragen, wenn der Spieler den Container aufnimmt. Es können 0-100 Geheimdienstwaffen in einem Spezialcontainer erzeugt werden. Ist der Parameter 'Number' = 0, wird ein leerer Geheimdienstwaffen-Container erzeugt. Bei Artefakt-Containern hat er keine Auswirkung, es wird immer nur ein Artefakt erzeugt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers
Number | int | 0..100 | Anzahl der Unique Items im Container

Rückgabetabelle
leer

Beispiel

-- Einen Artefakt-Container erstellen.
V.Artefact = NContainer.Create( {
    Type = CONTAINER_SPACE,
    Size = CONTAINER_ARTEFACT,
    PosDesc = POSDESCR_INTERCEPTION
} ).Container

-- 'Number' ist egal, es wird immer nur 1 Artefakt erzeugt.
NContainer.SetUniqueItems( { Container = V.Artefact, Number = 1 } )

-- Geheimdienstwaffen: Number = 0 erzeugt nur einen leeren Spezialcontainer.
V.Weapon = NContainer.Create( {
    Type = CONTAINER_POSITION,
    Size = CONTAINER_SPECIAL,
    Position = { V.PiratePos[1], V.PiratePos[2] - 50, V.PiratePos[3] }
} ).Container

NContainer.SetUniqueItems( { Container = V.Weapon, Number = 2 } )


Message

Message( { Message } ) : {}

Gibt eine Meldung im Script-Channel aus. Nach dem Text folgt in Klammern der Name des verwendeten Skripts. Diese Funktion ist im Releasemodus ohne Wirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Message | string | n/a | Auszugebende Nachricht

Rückgabetabelle
leer

Beispiel

 -- Debug Meldung ausgeben
 NDebug.Message( { Message = "Variante 2 wird verwendet" } )


SetPlasmaEffect( {} ) : {}

Funktion unbekannt.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel


GameOver( {} ) : {}

Eine wichtige Mission wurde nicht erfüllt und daher ist das Spiel zu Ende. Popup mit "Hauptmenü", "Laden" wird angezeigt.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- Mission fehlgeschlagen, Spiel vorbei
    1.0, nil, "Failed", function( V, Data )
    MissionLib.UnregisterMission( "IDM_BAR_007" )
    NGame.GameOver({})
    return { Timeout = 0 }
end },


GetTime

GetTime( {} ) : { Time }

Ermittelt die Weltzeit seit Spielstart in Sekunden. Der Spielstart ist der Zeitpunkt, an dem ein neues Spiel begonnen wurde. Während Pausen und der Erzeugung von Objekten läuft diese Zeit nicht weiter. GetTime ist daher nur sehr eingeschränkt für Laufzeitmessungen von Skriptfunktionen geeignet. Außerdem rast die Zeit bei Hyperraumsprüngen mit ungefähr 300 Sekunden pro Lichtjahr Entfernung durch, was die Verwendung noch weiter drastisch einschränkt oder extrem erschwert. Der Einsatz von GetTime ist also im Prinzip nur im aktuellen System sinnvoll und wenn die Erzeugung und Abfrage eines Timer-Events mit NMission.CreateTimer zu umständlich wäre.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Time | float | n/a | Weltzeit seit Spielstart in Sekunden

Beispiel

{   -- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    V.SecondsSinceStart = NGame.GetTime({}).Time
    V.NextMessageTime = 0.0
    V.Step = 1
end },

{   -- Nächste Abschussmeldung frühestens 30 Sekunden nach der Zerstörung des letzten Wings
    1, 1, "Wing", function( V, Data )
    if Data.Event == WING_DESTROYED then
        local currentTime = NGame.GetTime({}).Time
        if currentTime > V.NextMessageTime then
            NGUI.ShowInfoText( { Text = "IDM_WING_DESTROYED" } )
            V.NextMessageTime = currentTime + 30.0
        end
    end
end },


Pause

Pause( { Pause } ) : {}

Pausiert oder startet das Spiel.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Pause | bool | default=false | Spiel pausieren (true) oder weiterlaufen lassen (false)

Rückgabetabelle
leer

Beispiel

-- Spiel anhalten
NGame.Pause( { Pause = true } )

-- Weiter gehts
NGame.Pause( { Pause = false } )


PlayMovie

PlayMovie( { Name } ) : {}

Zeigt ein Fullscreen Video an und pausiert die Simulation bis das Video vorbei ist. Am Ende des Videos wird ein 'Movie'-Event an die Mission gesendet. Die Filmsequenz kann jederzeit mit der ESC-Taste abgebrochen werden. Standardmäßig befinden sich die Filme mit der Dateiendung .bik im Verzeichnis "video\Movies\" des Installationsordners. Funktionsgleich mit NGUI.ShowMovie.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | n/a | Name des Videos. Pfadangabe und Dateiendung werden vom Programm konstruiert und dürfen nicht mit angegeben werden. (z.B. "indoor01" --> "videos/movies/indoor01.bik")

Rückgabetabelle
leer

Beispiel

-- Film abspielen
NGame.PlayMovie( { Name = "outdoor05" } )


Save

Save( { Name | Chapter, Subchapter } ) : {}

Legt einen Spielstand des mit einer StringId angegebenen Namens aus der Datei global.res oder user_strings.res an. Pfad und Dateiendung werden vom Programm konstruiert. Ein bereits existierender Spielstand gleichen Namens wird überschrieben. Wird stattdessen der Parameter 'Chapter' verwendet, wird der Name des Spielstands aus dem Namen der Mission und der Kapitelnummer erzeugt. Zusammen mit dem Parameter 'Chapter' kann der Parameter 'Subchapter' verwendet werden, um Unterkapitel anzulegen. Falls nicht der Skriptname verwendet werden soll, muss der Name zuvor mit NMission.SetName gesetzt werden. Der Aufruf der Save-Funktion erzeugt automatisch die Infomeldung "Spielstand gespeichert".

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | StringId aus dem LokaTool | Name des Spielstands
Chapter | int | n/a | Kapitelnummer, negative Zahlen sind erlaubt
Subchapter | unsigned int | >= 0 | Unterkapitelnummer, nur positive Zahlen, negative Werte werden ignoriert

Rückgabetabelle
leer

Beispiel

-- Spielstand sichern
NGame.Save( { Name = "ID_TEST" } )

-- Spielstand unter dem Missionstitel sichern
NGame.Save( { Name = "ID_MODTUT_HEADER" } )


AddWings

AddWings( { Group, WingList } ) : {}

Alle Wings in 'WingList' werden in die gegebene GruppenKI eingetragen und gehören ab dann zu der KI-Gruppe.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Group | unsigned int | CEventHandle | Handle der GruppenKI
WingList | table[n] : [<unsigned int>] | Liste von CWingHandle | Handles der Wings, die zu der Gruppe gehören

Rückgabetabelle
leer

Beispiel

-- Gruppen erzeugen
local groups = NGroupAi.Create({})

-- Wings in erste Gruppe eintragen
NGroupAi.AddWings( { Group = groups.GroupA, WingList = { wing1, wing2 } } )

-- Wings in zweite Gruppe eintragen
NGroupAi.AddWings( { Group = groups.GroupB, WingList = { wing3, wing4, wing5 } } )


Create

Create( {} ) : { GroupA, GroupB }

Erzeugt zwei gegnerische KI-Gruppen und liefert die Handles der beiden zurück. Die Gruppen exisiteren so lange, bis für eine der Gruppen Destroy aufgerufen wird.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
GroupA | unsigned int | CEventHandle | Handle der ersten GruppenKI
GroupB | unsigned int | CEventHandle | Handle der zweiten GruppenKI

Beispiel

-- Gruppen erzeugen
local groups = NGroupAi.Create({})

-- Wings in erste Gruppe eintragen
NGroupAi.AddWings( { Group = groups.GroupA, WingList = { wing1, wing2 } } )

-- Wings in zweite Gruppe eintragen
NGroupAi.AddWings( { Group = groups.GroupB, WingList = { wing3, wing4, wing5 } } )


Destroy

Destroy( { Group } ) : {}

Speichert in der Gruppe, dass sie bei der nächsten Berechnung gelöscht werden soll.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Group | unsigned int | CEventHandle | Handle der zu löschenden GruppenKI

Rückgabetabelle
leer

Beispiel

-- Gruppen erzeugen
local groups = NGroupAi.Create({})

-- erste Gruppe wieder löschen
NGroupAi.Destroy( { Group = groups.GroupA } )

-- zweite Gruppe löscht sich selbst, wenn die erste gelöscht ist!


RemoveHostilePlayer

RemoveHostilePlayer( { Group } ) : {}

Der Spieler wird als Gegner aus der GruppenKi entfernt. Die GruppenKi entfernt den Spieler bei allen Wings der Gruppe als Gegner.
Hinweis: Im Gegensatz zu "NWing.NoEnemy" hört die Kampfmusik nicht auf zu dudeln, wenn keine Gegner mehr da sind und solange man sich noch im System aufhält.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Group | unsigned int | CEventHandle | Handle der GruppenKi

Rückgabetabelle
leer

Beispiel


SetPlayerHostile

SetPlayerHostile( { Group } ) : {}

Der Spieler wird als Gegner in die GruppenKi eingetragen. Die GruppenKi trägt den Spieler bei allen Wings der Gruppe als Gegner ein.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Group | unsigned int | CEventHandle | Handle der GruppenKi

Rückgabetabelle
leer

Beispiel


SubWings

SubWings( { Group, WingList } ) : {}

Alle Wings in 'WingList' werden aus der gegebenen GruppenKi entfernt, falls sie dort eingetragen sind. Die GruppenKi bleibt auch erhalten, wenn sie keine Wings mehr enthält.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Group | unsigned int | CEventHandle | Handle der GruppenKi
WingList | table[n] : [<unsigned int>] | Liste von CWingHandle | Handles der Wings, die aus der Gruppe entfernt werden sollen.

Rückgabetabelle
leer

Beispiel

-- Gruppen erzeugen
local groups = NGroupAi.Create({})

-- Wings in erste Gruppe eintragen
NGroupAi.AddWings( { Group = groups.GroupA, WingList = { wing1, wing2, wing3 } } )

-- Wings wieder aus der Gruppe entfernen, falls sie enthalten sind
NGroupAi.SubWings( { Group = groups.GroupA, WingList = { wing1, wing2 } } )


Blink

Blink( { Button } ) : {}

Lässt einen bestimmten Button blinken, bis der User ihn anklickt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Wert | Kommentar
Button | enum | GUI_BTN_COMMUNICATION | 0 | Ziel kontaktieren
 |  | GUI_BTN_PLASMA | 1 | Plasmawaffe auswählen
 |  | GUI_BTN_ROCKET | 2 | Raketensorte auswählen
 |  | GUI_BTN_TARGETMAP | 3 | Targetliste öffnen
 |  | GUI_BTN_LOGBOOK | 11 | Logbuch öffnen
 |  | GUI_BTN_LOGBOOK_UPGRADE | 12 | Upgradelog öffnen
 |  | GUI_BTN_NAVMAP | 13 | Navigationskarte öffnen
 |  | GUI_BTN_MENU | 14 | Optionsmenü öffnen
 |  | GUI_BTN_HYPERJUMP | 21 | Hyperraumsprung ausführen
 |  | GUI_BTN_CONTAINER_GET | 22 | Container aufnehmen
 |  | GUI_BTN_TIME | 23 | Zeitbeschleunigung aktivieren
 |  | GUI_BTN_UPGRADE | 24 | Upgrade durchführen
 |  | GUI_BTN_CONTAINER_DROP | 25 | Container abwerfen

Rückgabetabelle
leer

Beispiel

-- Wichtige Mitteilung im Logbuch
NGUI.Blink( { Button = GUI_BTN_LOGBOOK } )


ClearSubtitle( {} ) : {}

Löscht einen bestehenden Untertitel.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Untertitel löschen
NGUI.ClearSubtitle({})


Disable

Disable( { Feature } ) : {}

Diese Funktion gibt es nicht!

Die Beschreibung bleibt aber mal vorläufig noch hier drin.

Deaktiviert ein bestimmtes GUI Feature ( z.B. Shortcut, Button etc. )

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Feature | enum | GUI_HYPERJUMP, GUI_NAVMAP, GUI_TARGETVIEW | Zu deaktivierendes Feature

Rückgabetabelle
leer

Beispiel

-- Navigationskarte deaktivieren
NGUI.Disable( { Feature = GUI_NAVMAP } )


Enable

Enable( { Feature } ) : {}

Diese Funktion gibt es nicht!

Die Beschreibung bleibt aber mal vorläufig noch hier drin.

Aktiviert ein bestimmtes GUI Feature ( z.B. Shortcut, Button etc. )

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Feature | enum | GUI_HYPERJUMP, GUI_NAVMAP, GUI_TARGETVIEW | Zu aktivierendes Feature

Rückgabetabelle
leer

Beispiel

-- Navigationskarte aktivieren
NGUI.Enable( { Feature = GUI_NAVMAP } )


GangDetected

GangDetected( { GangId, Respawn } ) : {}

Zeigt die Meldung "<Gangname>-Gang entdeckt" an

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
GangId | unsigned int | 0..46 | Id der Gang, die angezeigt werden soll
Respawn | unsigned int | n/a | Leveloffset der Gang, die angezeigt werden soll

Rückgabetabelle
leer

Beispiel

-- Zeigt die Meldung "Akim-Gang entdeckt" an
NGUI.GangDetected( { GangId = 1 } )


HelpDialog

HelpDialog( { Screen } ) : {}

Aktiviert verschiedene Hilfe-Popups für die Belegungen von Tastatur, Maus und Joystick.
Beim Schließen des Dialogs wird das "Tutorial"-Event TUTORIAL_ONCLOSE_HELPDIALOG ausgelöst. Während der Anzeige des Popups pausiert das Spiel und alle Objekte werden eingefroren, auch Timer werden angehalten und laufen erst nach dem Schließen der Hilfe weiter. Da außer Objektanwahl, Soundausgaben und noch ein paar wenigen Befehlen kaum noch welche ausgeführt oder sogar übergangen werden, sollte man erst nach dem Event TUTORIAL_ONCLOSE_HELPDIALOG weitere Aktionen starten.
Bitte beachten: Ist der Wert für 'Screen' größer 5 oder kleiner -33, stürzt das Programm mit einer EXCEPTION_ACCESS_VIOLATION ab!

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Screen | unsigned int | 0..5 | Zu aktivierendes Hilfefenster

Der Screen-Wert aktiviert die Hilfe für:
Wert | Kommentar
Funktionstaste
0 | die Schiffssteuerung | keine
1 | das Ziel und die Targetliste
2 | Container aufnehmen und abwerfen
3 | Containeraufnahme und Zeitbeschleunigung
4 | die Waffenbedienung
5 | die komplette Übersicht der Belegungen | F1
-1 | nichts, kein Popup | keine
-2 .. -33 | keine Hilfe, sondern nur ein leeres Fenster

Rückgabetabelle
leer

Beispiel

-- Die komplette Übersicht aktivieren
NGUI.HelpDialog( { Screen = 5 } )


ShowInfoText

ShowInfoText( { Text, Replace } ) : {}

Blendet eine Info-Meldung im oberen Bildschirmbereich ein, die etwa 3-4 Sekunden zu sehen ist. Es werden maximal 9 Zeilen angezeigt. Längere Texte werden abgeschnitten. Im Parameter 'Replace' kann eine Liste von StringIds übergeben werden, die Lücken in 'Text' ersetzen sollen. Die Ersetzungen werden in der Reihenfolge der StringIds in 'Replace' vorgenommen, d.h. 'Replace[1]' ersetzt %1, 'Replace[2]' %2 usw. in 'Text'. Überzählige Platzhalter in 'Text' müssen mit einem Leerstring ( "" ) besetzt werden, damit nicht die Prozentwerte angezeigt werden. Es können bis zu 99 Ersetzungen vorgenommen werden. Ungültige bzw. nicht existente StringIds in 'Text' und 'Replace' werden ignoriert, es wird halt einfach nichts angezeigt und lediglich der Jingle abgespielt.

Achtung, Fehler: Sind in 'Replace' mehr als 9 Ersetzungen vorhanden, dann muss jede 10. Stelle (%10, %20,...) DOPPELT besetzt werden, sonst wird der Text dieser Stelle nicht angezeigt! Man kann einen beliebigen String vor jeder 10. Stelle einsetzen, auch ein Leerstring (nicht nil) genügt. Besonders in for-, repeat- und while-Schleifen muss man darauf achten, da ab der 10. Stelle der Tabellenindex von der Zählvariablen abzuweichen beginnt. Siehe unten im Beispiel 3.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Text | string | n/a | StringId aus der user_strings.res oder global.res
Replace | table[n] : string | n/a | Liste mit StringIds aus dem LokaTool

Rückgabetabelle
leer

Beispiel

-- 1.) Einfache Meldung
NGUI.ShowInfoText( { Text = "IDM_GLOBAL_5000_INFO_0" } )

-- 2.) Meldung mit Ersetzungen
NGUI.ShowInfoText( {
    Text = "IDM_GLOBAL_5000_INFO_1",
    Replace = { "IDM_SYSTEMNAME_00", "IDM_NPCNAME_05", "" }
} )

-- 3.) Mehr als 9 Ersetzungen
-- 3.1)
local ReplaceText = {
     "ID_1", "ID_2", "ID_3", "ID_4", "ID_5", "ID_6", "ID_7", "ID_8", "ID_9","","ID_10",
    "ID_11","ID_12","ID_13","ID_14","ID_15","ID_16","ID_17","ID_18","ID_19","","ID_20"
}
NGUI.ShowInfoText( { Text = "ID_TEXT_20", Replace = ReplaceText } )

-- 3.2)
local texte = {}
local index = 0
for i = 1, 99 do
    index = index + 1
    if lua.tonumber( math.mod( i, 10 ) ) == 0 then  -- WICHTIG: lua.tonumber() !!!
    texte[index] = ""
    index = index + 1
    end
    texte[index] = "ID_"..i  -- der normale Text
end
NGUI.ShowInfoText( { Text = "ID_TEXT_99", Replace = texte } )


ShowMovie

ShowMovie( { Video } ) : {}

Zeigt ein Fullscreen Video an und pausiert die Simulation bis das Video vorbei ist. Am Ende des Videos wird ein 'Movie'-Event an die Mission gesendet. Funktionsgleich mit NGame.PlayMovie.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Video | string | n/a | Name des Videos. Pfadangabe und Dateiendung werden vom Programm konstruiert und dürfen nicht mit angegeben werden. (z.B. "cutscene0" --> "videos/movies/cutscene0.bik")

Rückgabetabelle
leer

Beispiel

-- Video abspielen
NGUI.ShowMovie( { Video = "cutscene0" } )


ShowSubtitle

ShowSubtitle( { Text } ) : {}

Zeigt einen Untertitel im Kommunikationsfeld (untere Bildschirmhälfte) an, bis ClearSubtitle aufgerufen wird. Ein erneuter Aufruf fügt den neuen Text an den bestehenden an. Eine Funkmeldung oder ein Dialog löscht den Untertitel sofort. Voraussetzung ist, dass die Anzeige der Untertitel in den Einstellungen eingeschaltet ist, sonst hat die Funktion keine Auswirkung. (Funktioniert nicht!)

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Text | string | n/a | StringId aus der user_strings.res oder global.res

Rückgabetabelle
leer

Beispiel

-- Einfacher Untertitel
NGUI.ShowSubtitle( { Text = "IDM_GLOBAL_5000_SUB_00" } )

-- Text anhängen
NGUI.ShowSubtitle( { Text = "IDM_GLOBAL_5000_SUB_01" } )


Create

Create( { Script, Run } ) : { Success }

Erzeugt eine Mission, die das angegebene Skript verwendet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Script | string | n/a | Name des Skripts in NScript.Register. Hat nichts mit dem Dateinamen des Skripts zu tun.
Run | bool | default=false | Mission sofort starten. Zielskripts ohne "MissionStart"-Filter starten immer sofort nach "Create".

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Success | bool | n/a | Mission erfolgreich erzeugt

Beispiel

-- Mission erzeugen und sofort starten
NMission.Create( { Script = "GLOBAL_5000", Run = true } )


CreateTimer

CreateTimer( { Time } ) : { Timer }

Erzeugt ein "Timer"-Event nach n Sekunden Simulationszeit. Öffnet man die Navigationskarte oder das Logbuch während die Zeit läuft, wird der Timer solange angehalten, bis Karte oder Logbuch wieder geschlossen wurde. Dasselbe gilt auch für Pausen (NGame.Pause oder Pause- und Esc-Taste). Die Verwendung von CreateTimer ist nicht geeignet, wenn während der ablaufenden Zeit ein Hyperraumsprung durchgeführt wird, da hier die Simulationszeit sehr stark beschleunigt wird.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Time | float | Time > 0.0f | Zeit in Sekunden

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Timer | unsigned int | CEventHandle | Handle des erzeugten 'Timer'-Events

Beispiel

-- Erzeugt ein Event nach 5 Sekunden
V.Timer = NMission.CreateTimer( { Time = 5 } ).Timer


GetMissionHandle

GetMissionHandle( { Script } ) : { MissionList }

Liefert das Handle der Mission, die das angegebenen Skript verwendet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Script | string | n/a | Name des Scripts

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
MissionList | table[1] : unsigned int | CMissionHandle | Handle der Mission

Beispiel

-- Handle einer Mission holen
local missionlist = NMission.GetMissionHandle( { Script = "GLOBAL_019" } ).MissionList
local mission = missionlist[1]


GetState

GetState( { State, MissionId } ) : { State }

Liefert den Zustand einer Mission ( V.STATE )

Die ursprüngliche Doku war hier total falsch, nichts hatte gestimmt oder funktioniert! Anstelle dem Parameter 'Mission' (den es gar nicht gibt) wurde vom Fehlerbericht 'State' verlangt. Dieser liefert auch einen Wert zurück, der jedoch nur mit dem Zustand der aktuell laufenden Mission übereinstimmt. Andere Missionen lassen sich anscheinend nicht abfragen. Der Parameter 'State' scheint auch nichts zu bewirken.
Hab hier zumindest mal die Parameter korrigiert, auch wenn es nichts bringt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
State | unsigned int | n/a | Für die Füße
MissionId | unsigned int | CMissionHandle | Handle einer Mission

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
State | enum | MSTATE_OFFERING, MSTATE_RUNNING, MSTATE_ACHIEVED, MSTATE_FAILED, MSTATE_ENDED | Zustand der Mission

Beispiel

-- Zustand der aktuellen Mission abfragen (geht so nicht)
if NMission.GetState( { State = egal } ).State == MSTATE_OFFERING then
    DoSomething()
end

-- Zustand einer anderen laufenden Mission abfragen (geht gar nicht, Absturz)
local mission = NMission.GetState( { Mission = V.OtherMission } )
if mission.State == MSTATE_RUNNING then
    DoSometing2()
end

-- Fragt wie im ersten Beispiel ab, ob die Mission im Terminal angeboten wird
if V.STATE == MSTATE_OFFERING then
    return { Text = "IDM_GLOBAL_019_MISSIONTEXT" }
end


SetName

SetName( { Name } ) : {}

Setzt einen Namen für die Mission, der beim Anlegen von Spielständen verwendet wird.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | StringId aus der user_strings.res oder global.res | Name der Mission

Rückgabetabelle
leer

Beispiel

NMission.SetName( { Name = "ID_AUTOSAVE" } )


SetState

SetState( { State, Mission } ) : {}

Setzt den Zustand einer Mission ( V.STATE )

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
State | enum | MSTATE_OFFERING, MSTATE_RUNNING, MSTATE_ACHIEVED, MSTATE_FAILED, MSTATE_ENDED | Zu setzender Zustand
Mission | unsigned int | CMissionHandle | Handle einer Mission

Rückgabetabelle
leer

Beispiel

-- Setzt den Zustand der aktuellen Mission und beendet sie im nächsten Step
if count == 5 then
    NMission.SetState( { State = MSTATE_ACHIEVED } )
end

-- Setzt den Zustand einer anderen laufenden Mission
if count == 5 then
    NMission.SetState( { Mission = V.OtherMission, State = MSTATE_ACHIEVED } )
end

-- Setzt den Zustand der aktuellen Mission auf "Failed", beendet sie aber noch nicht
if Data.Event == WING_DESTROYED then
    NMission.SetState( { State = MSTATE_FAILED } )
    V.STATE = MSTATE_RUNNING
    V.Timer = NMission.CreateTimer( { Time = 4 } ).Timer
end

-- Beendet die aktuelle und zuvor auf "Failed" gesetzte Mission, wenn die Zeit abgelaufen ist
if Data.Timer == V.Timer then
    NMission.SetState( { State = MSTATE_ENDED } )
end

Hinweis: Hat man in der Mission eine USE-Taste (für Gegenstand/Funktion benutzen) eingebaut, dann verschwindet diese, wenn man die Mission mit V.STATE = MSTATE_RUNNING weiterlaufen lässt. Wurde mit der Taste zwischen zwei Zuständen umgeschaltet (Ein/Aus), bleibt der zuletzt geschaltete Zustand erhalten. In dem Fall ist es also besser, die Mission normal zu beenden und davor die gewünschten Meldungen, Aktionen und Zustände (z.B. Belohnung) mit den entsprechenden Skriptfunktionen anstatt in den "Achieved" und "Failed" Events zu erstellen.


Create

Create( { Name, Model, Location, System } ) : { NPC }

Erzeugt einen NPC im aktuellen System des Spielers. Der NPC sitzt in der Bar und kann rechts im Auswahlmenü angewählt werden. Es ist das Symbol mit dem Kopf und der Beschriftung "Sidequest" oder "Kontaktperson". Beim Anklicken des NPCs wird ein "Text"-Event erzeugt und ein Dialog mit "OK" und "Abbrechen" wird geöffnet, der im wesentlichen dieselbe Funktion hat wie das Terminal in der Lobby. Drückt der Spieler "OK", wird die Mission per "MissionStart"-Event gestartet, der Dialog wird geschlossen und der NPC wird inaktiv, kann also nicht erneut angeklickt werden. Drückt der Spieler "Abbrechen", so wird der Dialog lediglich geschlossen, die Mission erhält kein Event und der NPC kann erneut angeklickt werden.
Hinweis: Der NPC muss immer im "Create"-Event erzeugt werden.
Tipp: Anstatt ihn erst beim Verlassen der Station im ersten Step mit NNPC.Destroy zu löschen, kann er bereits im Event "MissionStart" gelöscht werden, da er nach Annahme der Mission sowieso nicht mehr angeklickt werden kann. Somit verschwindet der nunmehr überflüssige Menü-Button, falls er noch da ist, sofort nach der Annahme.
Anmerkung zur Parametertabelle: Die Parameter 'Name', 'Model' und 'Location' zeigen keinerlei Auswirkungen auf das Erscheinungsbild des Buttons oder die Texte, obwohl z. B. für die Charaktermodelle entsprechende XML-Dateien vorhanden sind. Es ist völlig egal, was man übergibt, Leerstrings oder beliebige Werte tun es genauso. Die Parameter müssen lediglich vorhanden sein und gültige Werte enthalten. Auch der optionale Parameter 'System' hat keine Funktion, die Sternsysteme, wo der NPC erzeugt werden soll, hängen ausschließlich von den Bedingungen im "Init"-Event ab.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | StringId aus der user_string.res oder global.res | Name des NPCs
Model | string | Modell-Name | Name eines Charaktermodells
Location | string | "01", "02", "03", "04" | Lokator (Sitzposition)
System | unsigned int | 0-399 (StarSystemId) | System, in dem der NPC erzeugt wird

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
NPC | unsigned int | CNPCHandle | Handle des erzeugten NPCs

NPC Charaktermodelle
Modellname | Kommentar
"ArrackJiju" | Arrack Jiju
"ArrackMathaFu" | Arrack MathaFu
"ArrackRatsmitglied1" | Arrack Ratsmitglied
"ArrackStatist" | Arrack Statist
"barfrau0" | Frau in der Bar
"barfrau1" | Frau in der Bar
"barfrau2" | Frau in der Bar
"bartyp0" | Mann in der Bar
"bartyp1" | Mann in der Bar
"bartyp2" | Mann in der Bar
"Guard0" | Wächter
"Guard1" | Wächter
"Guard2" | Wächter
"kontaktfrau0" | Kontaktfrau
"kontaktfrau1" | Kontaktfrau
"kontaktfrau2" | Kontaktfrau
"kontaktmann0" | Kontaktmann
"kontaktmann1" | Kontaktmann
"kontaktmann2" | Kontaktmann
"MortokDrinker" | Mortok Säufer
"MortokRatsmitglied1" | Mortok Ratsmitglied
"MortokRatsmitglied2" | Mortok Ratsmitglied
"MortokScientist1" | Mortok Wissenschaftler
"MortokSoldier" | Mortok Soldat
"MortokSoldier1" | Mortok Soldat
"OctoJow" | Oc'to Jow
"OctoJowSon" | Oc'to Jow'son
"OctoRatsmitglied1" | Oc'to Ratsmitglied
"OctoSicherheitschef" | Oc'to Sicherheitschef
"OctoStationsleiter" | Oc'to Stationsleiter
"Ramirez" | Ramirez
"RaptorKontaktmann" | Raptor Kontaktmann
"RaptorNicolai" | Raptor Nicolai
"RaptorRatsmitglied1" | Raptor Ratsmitglied
"RaptorSicherheitschef" | Raptor Sicherheitschef
"RaptorZarkov" | Raptor Zarkov
"ThulNaara0" | Thul Naara
"ThulNaara1" | Thul Naara
"ThulNaara2" | Thul Naara
"ThulSoldatin" | Thul Soldatin

Beispiel

-- Einen Mortok in der Bar erzeugen
V.NPCName = NObject.GetName( { Race = RACE_MORTOK } ).Name
V.NPC = NNPC.Create( {
    Name = V.NPCName,
    Model = "MortokRatsmitglied2",
    Location = "01"
} ).NPC


Destroy

Destroy( { NPC } ) : { }

Zerstört einen NPC.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
NPC | unsigned int | CNPCHandle | Handle des NPCs

Rückgabetabelle
leer

Beispiel

{   -- Spieler verlässt die Station nach Annahme --> NPC weg
    1.0, 1.0, "Station", function( V, Data )
    if V.NPC then
        NNPC.Destroy( { NPC = V.NPC } )
        V.NPC = nil
    end
end },

{  -- oder besser schon hier -> Mission startet, wenn angenommen
    nil, nil, "MissionStart", function( V, Data )
    if V.NPC then
        NNPC.Destroy( { NPC = V.NPC } )
        V.NPC = nil
    end
    V.Step = 1
end },


ActivateRing

ActivateRing( { Handle, Activate } ) : {}

Aktiviert oder deaktiviert den gegebenen Ring. Aktive Ringe haben eine blaue, deaktivierte eine graue Farbe.
Hinweis: Nach dem Neuladen eines Spielstands sind deaktivierte Ringe wieder aktiv, das Programm hat den Zustand also nicht gespeichert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | n/a | Handle eines CStaticObject
Activate | int | n/a | > 0: der Ring wird aktiviert. Sonst wird der Ring deaktiviert.

Rückgabetabelle
leer

Beispiel

-- Einen Ring zwischen Handelsstation und Hypergate erzeugen und zum Hypergate ausrichten
V.Ring = NObject.CreateRing( { Position = {0, 0, 5000}, Front = {0, 0, 10000} } ).Handle

-- Ring deaktivieren
NObject.ActivateRing( { Handle = V.Ring, Activate = 0 } )

-- Ring aktivieren
NObject.ActivateRing( { Handle = V.Ring, Activate = 1 } )


AddDialog

AddDialog( { Object, Exclusive } ) : {}

Fügt die aufrufende Mission in den Dialog des Objekts ein. Wird der Dialog des Objekts aufgerufen, so erhält die Mission Dialog-Events und muss die Texte und Eingabemöglichkeiten im Event "Dialog" bereitstellen. Ist 'Exclusive' true, dann wird der vorhandene Standard-Dialog des Objekts komplett überschrieben, das heißt, es stehen keine Standardtexte und -eingaben mehr zur Verfügung (z.B. Frachter-Geleitschutz). Andernfalls werden die Missionseingaben an die bestehenden Dialogdaten angehängt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts (Schiff oder Station)
Exclusive | bool | default=false | Standarddialog überschreiben (true) oder Dialogdaten einfügen (false)

Rückgabetabelle
leer

Beispiel

-- Standard-Dialog des Frachters ersetzen
NObject.AddDialog( { Object = V.Trader, Exclusive = true } )


ClearMissionObjects( {} ) : {}

Entfernt die Missionsmarkierung von allen Objekten im Weltraum.
(Missionssymbol M in Targetliste und Zielerfassung sowie die kleinen Infoboxen links im Cockpit.)
Es werden wirklich alle Markierungen entfernt, nicht nur die vom aufrufenden Skript gesetzten. Das muss man bedenken, falls die Möglichkeit besteht, dass zwei oder mehr Missionen gleichzeitig laufen (z. B. eine Sidequest und ein Terminalauftrag). In dem Fall sollte nicht diese Funktion verwendet werden, sondern besser NObject.SetMissionFlag, auch wenn damit der Aufwand höher sein kann.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Alle Missionsmarkierungen entfernen
NObject.ClearMissionObjects({})


CloseHyper

CloseHyper( { Effect } ) : {}

Schliesst einen Hyperraumtoreffekt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Effect | unsigned int | CHyperSpaceDoorHandle | Handlewert eines Hyperspace-Effekts

Rückgabetabelle
leer

Beispiel

-- ein Hyperraumtor-Effekt wird geschlossen
NObject.CloseHyper( { Effect = V.Hyper } )


CreateExplosion

CreateExplosion( { Position, Type, Damage, Size } ) : {}

Erzeugt eine Explosion an der angegebenen Position vom entsprechenden Typ. Optional kann der Schaden der Explosion angegeben werden. Der Parameter 'Size' gibt den Wirkungsradius der Explosion an, hat aber keinen Einfluss auf die Darstellungsgröße der Explosion. Vorsicht mit diesen beiden Parametern, wie in der Sidequest "Flüssiger Sprengstoff" demonstriert wird, können sogar große Kreuzer auf einen Schlag vernichtet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[1-3] : float | n/a | Raumkoordinate
Type | string | n/a | Bezeichner für einen Explosionstyp aus der Explosion.ini
Damage | float | default=0.0 | Schaden für Objekte in Reichweite
Size | float | default=50.0 | Wirkungsradius der Explosion

Rückgabetabelle
Ist leider leer, obwohl ein Handle für die Explosion erzeugt wird.
Kann daher nicht als Killer im StarshipDestroyed-Event ermittelt werden.

Beispiel

local pos = NObject.GetPosition( { Object = V.Cruiser } ).Position
NObject.CreateExplosion( {
    Position = { pos[1], pos[2], pos[3]-50 },
    Type = "EXPLOSION_MISSILE_BIGBANG",
    Size = 500,
    Damage = 800
} )


CreateHyper

CreateHyper( { Object, Open } ) : { Effect }

Erzeugt einen Hyperraumtoreffekt, der an der Position des Objekts erzeugt wird. Die Größe des Effekts wird automatisch an das Objekt angepasst. Wurde ein Parameter 'Open' übergeben und er ist größer als 0, wird der Effekt in der vollen Größe erzeugt, sonst baut sich der Effekt erst auf.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert eines SpaceObjects
Open | int | default=0 | ist Open > 0, hat der Effekt die volle Größe, sonst baut er sich erst auf

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Effect | unsigned int | CHyperSpaceDoorHandle | Handlewert eines Hyperspace-Effekts

Beispiel

-- Um einen Frachter herum soll ein Hyperraumtor-Effekt angezeigt werden
V.Effect = NObject.CreateHyper( { Object = V.Trader, Open = 1 } ).Effect

-- Um einen Frachter herum soll ein Hyperraumtor-Effekt aufgebaut werden
V.Effect = NObject.CreateHyper( { Object = V.Trader, Open = 0 } ).Effect

-- dto, ohne Parameter und Rückgabewert
NObject.CreateHyper( { Object = V.Trader } )


CreateMine

CreateMine( { Position, AimShip, Shooter } ) : { Mine }

Erzeugt eine Mine an der angegebenen Position. Wird 'Shooter' > 0 oder auf true gesetzt, erzeugt die Funktion eine selbstfeuernde Drohne, ansonsten eine normale Mine. In 'AimShip' kann ein Schiff übergeben werden, das beschossen wird oder bei Annäherung die Drohne zur Explosion bringt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[1-3] : float | n/a | Raumkoordinate
AimShip | unsigned int | CStarShipHandle | Handle des Zielschiffs
Shooter | unsigned int | default=0 | Ist Shooter = 0, wird eine normale Mine erzeugt, sonst eine selbstfeuernde.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Mine | unsigned int | CProjectileHandle | Handle der erzeugten Mine

Beispiel

-- Eine einzelne selbstfeuernde Mine erzeugen
V.Mine = NObject.CreateMine( { Position = { 1000, 2000, 3000 }, Shooter = 1 } ).Mine

-- Funktion, um ein mittelgroßes Minenfeld aus 100 Minen zu erzeugen.
-- Es wird ein quadratisches Feld in der XY-Ebene aufgebaut und etwas
-- in Z-Richtung durcheinander gemischt, sodass ein 3D-Minenfeld entsteht.
MissionLib.CreateMineField = function()
    local mineField = {}
    for x = 1, 10 do
    local x_ = ( x - 1 ) * 10
    for y = 1, 10 do
        mineField[x_ + y] = NObject.CreateMine( {
        Position = {
            -150 + x * 30,
            -150 + y * 30,
            6000 + 100 * math.sin( x * 1.5 ) + 200 * math.sin( y * 1.5 )
        }
        } )
    end
    end
    return mineField
end


CreateRing

CreateRing( { Position, Front } ) : { Handle }

Erzeugt an 'Position' einen Ring, der in Richtung 'Front' ausgerichtet ist. Zurückgegeben wird das Handle eines StaticObjects.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | Position des Objekts
Front | table[3] : float | n/a | Blickrichtung des Objekts

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | n/a | Handle eines CStaticObject

Beispiel

-- Einen Ring zwischen Handelsstation und Hypergate erzeugen und zum Hypergate ausrichten
V.Ring = NObject.CreateRing( { Position = {0, 0, 5000}, Front = {0, 0, 10000} } ).Handle


CreateSatellite

CreateSatellite( { Position, Turrets, LevelOffset, Nation, Center, Distance } ) : { Satellite, Wing }

Erzeugt einen Kommunikationssatelliten an einer definierten Position im Raum und bestückt ihn optional mit Geschütztürmen. Der bewaffnete Satellit verträgt allerdings standardmäßig wesentlich weniger Trefferpunkte als eine Waffenplattform vom Typ ST_WEAPONBASE. Übergibt man in 'Center' das Handle eines Orbiters, dann wird der Satellit in der Nähe des Orbiters im Abstand 'Distance' von dessen Hüllkugel erzeugt. Die Startposition 'Position' wird als Richtungsvektor relativ zum Zentrum interpretiert und so geändert, dass der Abstand eingehalten wird. Liegt die ursprüngliche Startposition im Zentrum des Orbiters, dann wird der Satellit an einer zufälligen Stelle im gegebenen Abstand erzeugt. Ist der Orbiter ein Himmelskörper, dann wird dieses Objekt vom Satelliten umkreist. Andere Objekte, die keine Orbiter sind, wie z.B. Piratenverstecke, werden nicht umkreist. Als Orbiter gelten Sonnen, Planeten, Monde, Anomalien, Asteroiden, Meteoritenfelder, Schiffs- und Stationswracks, Raumstationen und das Hypergate.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[1-3] : float | n/a | Raumkoordinate
Turrets | unsigned int | 0..2, default=0 | Anzahl der Geschütztürme. Die maximale Anzahl von Türmen hängt vom Modell ab. Wird ein einzelner Turm angegeben, ist dieser an der Unterseite montiert.
LevelOffset | int | ± n, default=0 | Levelunterschied zum Level des Spielers. Beeinflußt den Level der verwendeten Geschütztürme. n darf mehr als ±30 sein.
Nation | unsigned int | Rassen | Rasse, zu der der Satellit gehören soll. Wird kein Wert angegeben, wird die Rasse verwendet, zu der das System gehört.
Center | unsigned int | COrbiterHandle | Handle eines Orbiters, der von dem Satelliten umkreist werden soll.
Distance | float | >= 0.0 | Abstand zwischen dem Satelliten und der Hüllkugel des Orbiters.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Satellite | unsigned int | CStarShipHandle | Ship-Handle des erzeugten Satelliten
Wing | unsigned int | CWingHandle | Wing-Handle des erzeugten Satelliten

Beispiel

-- Einfachen Satelliten ohne Bewaffnung erzeugen
V.Sat = NObject.CreateSatellite( { Position = { 1000, 2000, 3000 } } ).Satellite

-- Mit einem Railgun-Turret bewaffneten Satelliten erzeugen
V.Sat = NObject.CreateSatellite( {
    Position = { 1000, 2000, 3000 },
    Turrets  = 1,
    Nation   = RACE_MORLOK
} ).Satellite

-- Mit zwei Railgun-Turrets bewaffneten Satelliten erzeugen
V.Sat = NObject.CreateSatellite( {
    Position = { 1000, 2000, 3000 },
    Turrets  = 2,
    Nation   = RACE_MORTOK,
    LevelOffset = 5
} ).Satellite

-- Kommunikationssatellit umkreist einen Asteroiden mit engstem Abstand
V.Asteroid = MissionLib.GetSystemAsteroid()
V.Sat = NObject.CreateSatellite( {
    Position = { 0, 0, 100 },
    Center   = V.Asteroid,
    Distance = 0
} )

-- Eigene Variablen für Wing und Ship des Kommunikationssatelliten
V.CommSatWing   = V.Sat.Wing       -- Wing
V.CommSatLeader = V.Sat.Satellite  -- Ship


DestroyMine

DestroyMine( { Mine } ) : {}

Bringt eine existierende Mine zur Explosion. Bezeichnet das Handle keine Mine oder ist die Mine nicht mehr vorhanden, hat die Funktion keine Auswirkung. Das Handle darf aber nicht gleich nil sein, sonst wird ein Absturz mit Fehlermeldung ausgelöst.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Mine | unsigned int | CProjectileHandle | Handle der erzeugten Mine

Rückgabetabelle
leer

Beispiel

-- Mine zerstören
NObject.DestroyMine( { Mine = V.Mine } )


DestroyRing

DestroyRing( { Handle } ) : {}

Der gegebene Ring wird gelöscht. Bezeichnet das Handle keinen Ring oder ist der Ring nicht mehr vorhanden, hat die Funktion keine Auswirkung. Das Handle darf aber nicht gleich nil sein, sonst wird ein Absturz mit Fehlermeldung ausgelöst.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | n/a | Handle eines CStaticObject

Rückgabetabelle
leer

Beispiel

-- Einen Ring erzeugen...
V.Ring = NObject.CreateRing( { Position = {0, 0, 5000}, Front = {0, 0, 100} } ).Handle

-- ...und wieder entfernen
NObject.DestroyRing( { Handle = V.Ring } )


DistanceFromPlayer

DistanceFromPlayer( { Object } ) : { Distance }

Liefert die Entfernung eines Objekts zum Spielerschiff. Die Entfernung wird zwischen den beiden Oberflächen der Hüllkugeln der Objekte bestimmt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Objekt, dessen Abstand gemessen werden soll

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Distance | float | 0.0f < Distance | Entfernung in 1/1000 Units

Beispiel

-- Entfernung zu einem Objekt
local dist = NObject.DistanceFromPlayer( { Object = V.Ship } ).Distance


EnableContainerHits

EnableContainerHits( { Container, AiHits } ) : {}

Normalerweise werden Container von der KI nicht getroffen. Wenn KI-Schiffe einen Container abschießen sollen, müssen die Treffer der KI erst beim Container erlaubt werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers, der abgeschossen werden soll
AiHits | unsigned int | >= 0 | ist AiHits = 0 oder nicht vorhanden, werden Treffer der KI verboten, sonst werden Treffer der KI erlaubt.

Rückgabetabelle
leer

Beispiel

-- Container darf von der KI zerstört werden
NObject.EnableContainerHits( { Container = V.Container, AiHits = 1 } )


EndDialog

EndDialog( { Object } ) : {}

Beendet einen laufenden Dialog des Objekts.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts ( Schiff oder Station )

Rückgabetabelle
leer

Beispiel

-- Dialog beenden
NObject.EndDialog( { Object = V.Trader } )


EnterActionTurret

EnterActionTurret( { Orbiter, Position, Front, AngleUp, AngleDown, AngleTurn, FarPlane } ) : {}

Richtet eine Flak in einem CTurretOrbiter ein und setzt den Spieler an die Kontrollen. Handelsstationen, Forschungsstationen und Asteroiden sind CTurretOrbiter. Anders als sonst üblich werden hier die Winkel nicht im Bogenmaß, sondern in Grad angegeben.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Orbiter | unsigned int | CObjectHandle | Handle eines CTurretOrbiters
Position | table[3] : float | n/a | Position relativ zum Zentrum des Orbiters?
Front | table[3] : float | n/a | Richtung x/y/z, eine absolute Koordinate im Raum
AngleUp | float | 0.0 - 90.0 ? | Drehwinkel in Grad vertikal nach oben
AngleDown | float | 0.0 - 90.0 ? | Drehwinkel in Grad vertikal nach unten
AngleTurn | float | 0.0 - 90.0 ? | Drehwinkel in Grad horizontal nach links und rechts
FarPlane | float | > 0.0 | Reichweite der Drohnenwaffen

Rückgabetabelle
leer

Beispiel

-- Die Flak in der ersten Flakmission
NObject.EnterActionTurret( {
    Orbiter   = V.ResearchStation,
    Position  = { 0, 10, 20 },
    Front     = { 0, 0, 1 },
    AngleUp   = 45,
    AngleDown = 45,
    AngleTurn = 85,
    FarPlane  = 600.0
} )


ExitActionTurret( {} ) : {}

Der Spieler verlässt die Flak wieder.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel


Freeze

Freeze( { Object, Freeze } ) : {}

Friert ein Objekt ein bzw. taut es auf. Ein eingefrorenes Objekt erhält keine Zeitschritte und hat keine Kollision (inklusive Projektilen und Explosionen). Sollte in Verbindung mit ActionCams verwendet werden, wenn der Spieler mit anderen Wings ein Ziel anfliegt und eine Kamera auf eine andere Gruppe gezeigt wird, da sich die Schiffe im eingefrorenen Zustand nicht vom Spielerschiff entfernen. Da die Kollision abgeschaltet wird, sollte das Einfrieren von Objekten nur geschehen, wenn Kollisionen mit anderen Objekten unwahrscheinlich sind.
Hinweis: Vom Spielerschiff geschleppte Container lassen sich nicht einfrieren, beim Versuch wird ein Laufzeitfehler erzeugt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts
Freeze | bool | n/a | Objekt einfrieren (true) oder auftauen (false)

Rückgabetabelle
leer

Beispiel

-- Ramirez wird unbeweglich und kann nicht mehr kollidieren
NObject.Freeze( { Object = V.Ramirez, Freeze = true } )


GetActionTurret

GetActionTurret( {} ) : { Handle }

Liefert das Handle des ActionTurrets (Flak).

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsignet int | CObjectHandle, CStarShipHandle | Handle des ActionTurrets

Beispiel


GetAmmoDamage

GetAmmoDamage( { Ammo, Level } ) : { DamageHull, DamageShield }

Berechnet den Schaden einer Munitionssorte eines gegebenen Levels. Wird kein Level vorgegeben, verwendet die Funktion den aktuellen Waffenlevel des Spielers. Ist die angegebene Munitionssorte noch nicht verfügbar, wird der Wert 0.0 zurückgeliefert.
Hinweis: Wird für den Level ein ungültiger Wert angegeben (z.B. 10), liefert die Funktion nicht den maximal möglichen Schaden, sondern den Wert 0.0 zurück. Es muss hierbei beachtet werden, dass die Wertebereiche der Levels intern von 0 bis 9 gehen, während im Spiel ein Bereich von 1 bis 10 angezeigt wird.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ammo | unsigned int | Munitionssorten | Munitionsart
Level | unsigned int | 0..9 | gewünschter Waffenlevel

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
DamageHull | float | >= 0.0 | Rumpfschaden, den ein Treffer erzeugt
DamageShield | float | >= 0.0 | Schildschaden, den ein Treffer erzeugt

Beispiel

-- Schadenswerte einer Photonenwaffe des angezeigten DSO-Waffenlevels 4
local HitPoints = NObject.GetAmmoDamage( { Ammo = AMMO_TYPE_PHOTON, Level = 3 } )
V.HullDamage = HitPoints.DamageHull
V.ShieldDamage = HitPoints.DamageShield


GetAnomalie

GetAnomalie( {} ) : { Handle }

Liefert das Handle der Anomalie, wenn eine im System vorhanden ist.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsignet int | CObjectHandle | Handle der Anomalie, 0 wenn keine existiert

Beispiel

local handle = NObject.GetAnomalie({}).Handle
if handle > 0 then
    V.Anomalie = handle
end


GetArtefact

GetArtefact( {} ) : { Handle }

Sucht den ersten Artefakt-Container im Spiel. Im System sollte nur ein Artefakt-Container vorhanden sein.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | n/a | Handle des Artefakt-Containers. Existiert kein Artefakt, wird 655359 zurückgegeben.

Beispiel

local handle = NObject.GetArtefact({}).Handle
if handle ~= 655359 then
    V.Artefact = handle
end


GetAsteroidPos

GetAsteroidPos( { Asteroid, Index} ) : { Position }

Liefert eine der Positionen in einem Asteroiden, an denen die Container für Minenwaren erzeugt werden. Diese Positionen liegen direkt auf den Plattformen. Kann keine Position gefunden werden, wird {0,0,0} geliefert. Lässt man den Parameter 'Index' weg, liefert die Funktion die erste Position im Asteroid. Je nach Asteroidengröße variiert die Anzahl der Positionen, bei kleinen Asteroiden sind es 8, bei mittleren 10 und bei großen 13 Koordinaten. Werden höhere Werte für den Index angegeben, dann wiederholen sich die Positionswerte. Bei einem mittleren Asteroiden mit 10 Positionen liefert ein Index von 10 also dieselbe Position wie der Index 0 usw.

Hinweis: Die Erzeugung von Schiffen, Wings, Satelliten und Containern direkt im Asteroiden löst oft eine Kollision aus und sie werden daher meistens wieder rausgefeuert. Sie stehen dann irgendwo außerhalb in der Nähe des Asteroiden. Es ist also besser, diese Objekte zunächst außerhalb zu erzeugen und sie dann etwas zeitverzögert mit der Funktion NObject.Place in den Asteroiden zu versetzen. Objekte wie Explosionen, Minen und Ringe lassen sich hingegen direkt im Inneren erzeugen, ohne das sie nach draußen versetzt werden. Die lassen sich sogar in den Felswänden platzieren.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Asteroid | unsigned int | CObjectHandle | Handlewert eines Asteroiden
Index | int | n/a | Index einer bestimmten Asteroidenposition, die abgefragt werden soll.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | Absolute Koordinate

Beispiel

-- Eine Position in einem Asteroiden suchen
V.Position = NObject.GetAsteroidPos( { Asteroid = V.Asteroid, Index = 3 } ).Position

-- Liefert eine Tabelle mit allen Positionen im Asteroiden, wo Minenwaren erzeugt werden.
-- Der Parameter 'Count' der Rückgabetabelle enthält die Anzahl der gefundenen Positionen.
MissionLib.GetAsteroidPosTable = function( Asteroid )
    local idx = 0
    local posTable = { { 0.0, 0.0, 0.0 } }
    while Asteroid do
    local pos = NObject.GetAsteroidPos( { Asteroid = Asteroid, Index = idx } ).Position
    if ( pos[1] ~= posTable[1][1] )
    or ( pos[2] ~= posTable[1][2] )
    or ( pos[3] ~= posTable[1][3] ) then
        idx = idx + 1
        posTable[idx] = pos
    else
        break
    end
    end
    posTable.Count = idx
    return posTable
end


GetAsteroidPosCont

GetAsteroidPosCont( { Asteroid, Index} ) : { Position }

Liefert wie "GetAsteroidPos" eine der Positionen in einem Asteroiden. Die Position liegt in der Nähe der Positionen, an denen die Container für Minenwaren erzeugt werden. Sie liegt frei im Raum oberhalb der Plattformen, sodass dort ein Objekt erzeugt werden kann. Kann keine Position gefunden werden, wird die Position {0,0,0} geliefert. Wird der Parameter 'Index' weggelassen, liefert die Funktion die erste Position im Asteroid.
Je nach Asteroidengröße variiert die Anzahl der Positionen, bei kleinen Asteroiden sind es 8, bei mittleren 10 und bei großen 13 Koordinaten. Werden höhere Werte für den Index angegeben, dann wiederholen sich die Positionswerte. Bei einem mittleren Asteroiden mit 10 Positionen liefert ein Index von 10 also dieselbe Position wie der Index 0 usw.

Hinweis: Die Erzeugung von Schiffen, Wings, Satelliten und Containern direkt im Asteroiden löst oft eine Kollision aus und sie werden daher meistens wieder rausgefeuert. Sie stehen dann irgendwo außerhalb in der Nähe des Asteroiden. Es ist also besser, diese Objekte zunächst außerhalb zu erzeugen und sie dann etwas zeitverzögert mit der Funktion NObject.Place in den Asteroiden zu versetzen. Objekte wie Explosionen, Minen und Ringe lassen sich hingegen direkt im Inneren erzeugen, ohne das sie nach draußen versetzt werden. Die lassen sich sogar in den Felswänden platzieren.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Asteroid | unsigned int | CObjectHandle | Handlewert eines Asteroiden
Index | int | n/a | Index einer bestimmten Asteroidenposition, die abgefragt werden soll.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | Absolute Koordinate

Beispiel

-- Eine Position in einem Asteroiden suchen
V.Pos = NObject.GetAsteroidPosCont( { Asteroid = V.Asteroid, Index = 3 } ).Position
local X = V.Pos[1]
local Y = V.Pos[2]
local Z = V.Pos[3]

-- Liefert eine Tabelle mit allen Positionen im Asteroiden, wo Objekte erzeugt werden können.
-- Der Parameter 'Count' der Rückgabetabelle enthält die Anzahl der gefundenen Positionen.
MissionLib.GetAsteroidPosContTable = function( Asteroid )
    local idx = 0
    local posTable = { { 0.0, 0.0, 0.0 } }
    while Asteroid do
    local pos = NObject.GetAsteroidPosCont( { Asteroid = Asteroid, Index = idx } ).Position
    if ( pos[1] ~= posTable[1][1] )
    or ( pos[2] ~= posTable[1][2] )
    or ( pos[3] ~= posTable[1][3] ) then
        idx = idx + 1
        posTable[idx] = pos
    else
        break
    end
    end
    posTable.Count = idx
    return posTable
end


GetFrontDir

GetFrontDir( { Object } ) : { FrontDir }

Liefert die Z-Achse eines Objekts als Vektor.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Objekt, dessen Front-Richtung bestimmt werden soll

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
FrontDir | table[3] : float | n/a | Ausrichtung der Z-Achse (Ebenenwinkel) des Objekts

Beispiel

-- Ausrichtung eines Objektes bestimmen
V.Sat = NObject.CreateSatellite( { Position = { 1000, 2000, 3000 } } ).Satellite
V.DirZ = NObject.GetFrontDir( { Object = V.Sat } ).FrontDir


GetHangarPos

GetHangarPos( { Object } ) : { Position, Front, UpDir }

Liefert die Position und Ausrichtung eines Hangars. Hat das gewählte Objekt keinen Hangar, wird die Position (0,0,0) zurückgeliefert.
Achtung: Die Funktion enthält einen Fehler, durch den auch von kleinen Kreuzern Hangarposition und Ausrichtung geliefert wird, obwohl sie gar keinen Hangar haben. Allerdings ist die Hangarposition gleich der vom Schiff, sodass man durch Vektorsubtraktion kleine und große Kreuzer dennoch voneinander unterscheiden kann.
Wichtig: Die Ausrichtung 'Front' weist nicht wie sonst üblich nach vorne vom Hangar weg, also aus ihm heraus, sondern vielmehr nach hinten in ihn hinein. Im Vergleich zu den Richtungsvektoren anderer Objekte ist die Z-Achse also praktisch invertiert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle eines Objekts

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | die absolute Koordinate des Hangars
Front | table[3] : float | n/a | Ausrichtung der Z-Achse des Hangars (Ebenenwinkel)
UpDir | table[3] : float | n/a | Ausrichtung der Y-Achse des Hangars (Höhenwinkel)

Beispiel

-- Position und Ausrichtung des Hangars einer Forschungsstation auslesen
local align = NObject.GetHangarPos( { Object = V.ResearchStation } )
V.HangarPos   = align.Position
V.HangarFront = align.Front
V.HangarUpDir = align.UpDir

-- Prüft, ob das Schiff ein großer Kreuzer ist
MissionLib.IsCruiser1 = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CRUISER then
        local diff = MissionLib.SubVector(
            NObject.GetPosition( { Object = Ship } ).Position,
            NObject.GetHangarPos( { Object = Ship } ).Position
        )
        if MissionLib.GetVectorLength( diff ) > 0.0 then
            return 1
        end
    end
end

-- Prüft, ob das Schiff ein kleiner Kreuzer ist
MissionLib.IsCruiser2 = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CRUISER then
        local diff = MissionLib.SubVector(
            NObject.GetPosition( { Object = Ship } ).Position,
            NObject.GetHangarPos( { Object = Ship } ).Position
        )
        if MissionLib.GetVectorLength( diff ) == 0.0 then
            return 1
        end
    end
end

-- Berechnet eine Position 1u vor dem Hangar, in dem der Spieler gelandet ist
local playerHangar = get( "Logic.PlayerShip.hangar" )
local hangarAlign  = NObject.GetHangarPos( { Object = playerHangar } )
local hangarPos    = hangarAlign.Position
local hangarFront  = hangarAlign.Front

V.HangarFrontPos = {
    hangarPos[1] - hangarFront[1] * 1000,
    hangarPos[2] - hangarFront[2] * 1000,
    hangarPos[3] - hangarFront[3] * 1000
}


GetName

GetName( { Race } ) : { Name }

Liefert die StringId eines zufälligen Piratennamens der gegebenen Rasse.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Race | unsigned int | Rassen | Index der Rasse, zu der der Name gehören soll. Ist der Index > 5 (RACE_THUL), wird die Id eines Thulnamens geliefert.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | n/a | StringId des Namens

Beispiel

-- einen Namen berechnen
V.Name = NObject.GetName( { Race = RACE_MORTOK } ).Name

-- Einem Frachter einen speziellen Namen geben
NObject.SetSpecialName( { Object = V.Trader, Name = V.Name } )


GetNameArray

GetNameArray( { Number } ) : { NameArray }

Liefert eine Tabelle mit 'Number' Paaren aus StringIds eines Piratennamens und der Rasse, zu der der Name gehört.
Achtung: Die Funktion arbeitet unvollständig und erzeugt nur für die Rassen Oc'to und Arrack bis zu je 60 unterschiedliche Namen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Number | unsigned int | 1..1025 | Anzahl der Namen, die NameArray enthalten soll. Maximal 1025, sonst kommt es zu einem Stacküberlauf mit Absturz!

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
NameArray | table[Number]:table:{string,int} | n/a | 'Number' Paare aus StringId und Rasse eines Namens. Die Reihenfolge der Namen ist zufällig und die Tabelle kann mehrere gleiche Einträge enthalten.

Beispiel

-- Ein Feld mit Namen berechnen
V.Names = NObject.GetNameArray( { Number = 8 } ).NameArray

-- Einem Objekt einen speziellen Namen geben
NObject.SetSpecialName( { Object = V.Ship1, Name = V.Names[1][1] } )

-- Einem zweiten Objekt einen speziellen Namen geben
NObject.SetSpecialName( { Object = V.Ship2, Name = V.Names[2][1] } )


GetPosition

GetPosition( { Object } ) : { Position }

Liefert die Raumkoordinaten eines Objekts.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Objekt, dessen Position bestimmt werden soll

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | Position des Objekts

Beispiel

-- Position eines Objektes bestimmen
V.Sat = NObject.CreateSatellite( { Position = { 1000, 2000, 3000 } } ).Satellite
V.Pos = NObject.GetPosition( { Object = V.Sat } ).Position


GetUpDir

GetUpDir( { Object } ) : { UpDir }

Liefert die Y-Achse eines Objekts als Vektor.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Objekt, dessen Y-Achsen-Richtung ermittelt werden soll

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
UpDir | table[3] : float | n/a | Ausrichtung der Y-Achse (Höhenwinkel) des Objekts

Beispiel

-- Ausrichtung der Y-Achse eines Objektes ermitteln
V.Sat = NObject.CreateSatellite( { Position = { 1000, 2000, 3000 } } ).Satellite
V.DirY = NObject.GetUpDir( { Object = V.Sat } ).UpDir


OrbiterTurretLock

OrbiterTurretLock( { Object, Lock } ) : {}

'Lock' legt für den gegebenen CTurretOrbiter fest, ob er Turrets haben darf. Handelsstationen, Forschungsstationen und Asteroiden sind CTurretOrbiter.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | n/a | Handle eines CTurretOrbiter
Lock | int | n/a | Lock > 0 verbietet Turrets auf dem Orbiter, sonst werden Turrets erlaubt

Rückgabetabelle
leer

Beispiel

-- Die Handelsstation hat keine Geschütztürme mehr
NObject.OrbiterTurretLock( { Object = V.Tradestation, Lock = 1 } )


Place

Place( { Object, Position, Front, LookAt, BaseObj } ) : {}

Platziert ein Objekt an der angegebenen Position und Ausrichtung. Wird 'BaseObj' angegeben, sind 'LookAt' und 'Position' Koordinaten im Bezugssystem von 'BaseObj'. Hatte sich das Objekt vor der Positionsänderung noch bewegt, so bewegt es sich danach im Gegensatz zu NContainer.SetAlignment oder NShip.SetAlignment in der ursprünglichen Richtung weiter. Ein Drehimpuls bleibt dabei ebenfalls erhalten.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts, auch Schiffe, aber kein Wing
Position | table[3] : float | n/a | Position des Objekts
Front | table[3] : float | n/a | Blickrichtung des Objekts
LookAt | table[3] : float oder unsigned int | Vektor oder CObjectHandle | Position bzw. Objekt, worauf die Kamera blicken soll
BaseObj | unsigned int | CObjectHandle | Objekt, auf das sich 'Position' und 'LookAt' beziehen

Rückgabetabelle
leer

Beispiel


PlayerLanding

PlayerLanding( { Object, Accept, Granted } ) : {}

Erlaubt oder verbietet dem Spieler die Landung auf Forschungsstationen, Asteroiden und großen Kreuzern. Die Erlaubnis gilt nur einmalig, die Funktion muss vor jeder weiteren Landung wieder ausgeführt werden. Sie bleibt jedoch solange bestehen, bis der Spieler tatsächlich gelandet ist. Wurde also die Landeerlaubnis wegen Überschreitung des Zeitfensters entzogen, wird sie bei erneuter Anfrage wieder gewährt, ohne dass "PlayerLanding" nochmals ausgeführt werden muss. Ist der Parameter 'Granted' true, öffnet sich das Hangartor sofort. Bei Objekten ohne Hangar (z.B. kleine Kreuzer) und Handelsstationen hat die Funktion keine Auswirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert eines SpaceObjects
Accept | int | n/a | >0 erlaubt die Landung, sonst wird die Landung verboten
Granted | bool | default=false | true = Das Hangartor öffnet sich sofort ohne Anfrage um Landeerlaubnis

Rückgabetabelle
leer

Beispiel

-- Erlaubt dem Spieler die einmalige Landung in einem Asteroidenhangar
NObject.PlayerLanding( { Object = V.Asteroid, Accept = 1 } )

-- Erlaubt die Landung in der Forschungsstation und öffnet sofort das Hangartor
NObject.PlayerLanding( { Object = V.ResearchStation, Accept = 1, Granted = true } )

-- Verbietet dem Spieler die Landung in der Forschungsstation
NObject.PlayerLanding( { Object = V.ResearchStation, Accept = 0 } )

{   -- Erlaubt dem Spieler bei jedem 'TargetSelect' eines großen Kreuzers die Landung in seinem Hangar
    1, nil, "TargetSelect", function( V, Data )
    local ship = MissionLib.GetObjectType( Data.Target )
    if ship ~= nil then
        if ( ship.Type == "Ship" ) and ( ship.ObjType == ST_CRUISER ) then
        NObject.PlayerLanding( { Object = Data.Target, Accept = 1 } )
        end
    end
    end
},

{   -- dto. etwas einfacher, mit der neuen Funktion 'IsShip' aus der MissionLibEx.lua
    1, nil, "TargetSelect", function( V, Data )
    local ship = MissionLib.IsShip( Data.Target )
    if ship.IsShip then
        if ship.ShipType == ST_CRUISER then
        NObject.PlayerLanding( { Object = Data.Target, Accept = 1 } )
        end
    end
    end
},


RadarMapColor

RadarMapColor( { Object, Color } ) : {}

Trägt eine besondere Farbe in ein CSpaceObject ein. Das CSpaceObject liefert dann unabhängig von seinem Verhalten nur noch diese Farbe für die Radarmap. Das Verhalten wird davon auch nicht beeinflusst. Soll das CSpaceObject wieder seine Farbe selbst berechnen, muss die ungültige Farbe RADARMAP_INVALID übergeben werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Objekt, dessen Farbe gesetzt werden soll
Color | int | RadarMapColors | Radarfarbe, die das Objekt haben soll

Rückgabetabelle
leer

Beispiel

-- Radarfarbe auf freundlich setzen
NObject.RadarMapColor( { Object = V.StarShip, Color = RADARMAP_SHIP_FRIEND } )


RemoveDialog

RemoveDialog( { Object } ) : {}

Entfernt die Mission aus dem Dialog des Objekts. Ein laufender Dialog wird sofort beendet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts ( Schiff oder Station )

Rückgabetabelle
leer

Beispiel

-- Halt's Maul, alte Quasselstrippe:
NObject.RemoveDialog( { Object = V.Researchstation } )


ResetActor

ResetActor( { Object } ) : {}

Setzt den Standardakteur für ein Objekt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts ( Schiff oder Station )

Rückgabetabelle
leer

Beispiel


ScanObject

ScanObject( { Object, Aim, Time, Scanner } ) : {}

Sorgt dafür, dass ein von CSpaceObject abgeleitetes Objekt ein anderes von CSpaceObject abgeleitetes Objekt scannt. Die Dauer des Vorgangs wird in Time übergeben. Es erfolgt keine Kontrolle der Reichweite und es wird kein SCAN Event ausgelöst.
Hinweis: ScanObject kann nur von Huntern, Polizei- und Militärjägern und der Darkstar One angewendet werden. Mit allen anderen Schiffen ist die Funktion wirkungslos. Dazu zählen auch Piratenjäger und Satelliten.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Objekt, das den Scaneffekt aussenden soll. Funktioniert nur mit der Darkstar One, Huntern, Polizei- und Militärjägern.
Aim | unsigned int | CObjectHandle | Objekt, welches der Scaneffekt treffen soll. Fehlt das Ziel, beendet Object alle seine Scaneffekte.
Time | float | n/a | Dauer des Effekts in Sekunden. Fehlt der Parameter, dauert der Effekt 1 Sekunde.
Scanner | int | n/a | Index des Scannerstrahls, den das Schiff aussenden soll. 0 ist der Standardscanner. Scanner=0 ist ein blauer, 1 ein grüner und >=2 ein roter Scannerstrahl.

Rückgabetabelle
leer

Beispiel

-- Das Spielerschiff soll einen Container 10 Sekunden lang scannen
NObject.ScanObject( { Object = V.PlayerShip, Aim = V.Container, Time = 10.0 } )

-- Scan kann vorzeitig abgebrochen werden
NObject.ScanObject( { Object = V.PlayerShip } )


SetActor

SetActor( { Object, Actor } ) : {}

siehe auch NShip.SetActor

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts ( Schiff oder Station )
Actor | unsigned int oder string | 0, 1 oder Bezeichner für einen Actor | Nummer des Akteurs. 0 und 1 sind Standardakteure aller Völker oder explizite Angabe eines Akteurs

Rückgabetabelle
leer

Beispiel


SetCrime

SetCrime( { Object, Set } ) : {}

Das Objekt wird bei Beschuss Strafpunkte geben.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts
Set | bool | n/a | Strafpunkte an (true) oder aus (false)

Rückgabetabelle
leer

Beispiel

-- Asteroid soll bei Beschuss keine Strafpunkte geben
NObject.SetCrime( { Object = V.Asteroid, Set = false } )


SetMissionFlag

SetMissionFlag( { Object, Set } ) : {}

Setzt für ein Objekt, ob es in der Targetliste und an der Zielmarkierung im HUD mit einem Missionssymbol (M) markiert werden soll oder nicht. Wenn gesetzt, werden zusätzlich im Cockpit auf der linken Seite bis zu 6 dieser markierten Objekte in einem kleinen Fenster eingeblendet, in aufsteigender Reihenfolge ihrer Entfernung vom Spieler. Für NObject unüblich kann der Parameter 'Object' auch ein WingHandle sein. Dann werden alle Schiffe des Wings markiert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert eines SpaceObjects, darf ungültig sein, aber nicht nil
Set | unsigned int | 0..1 | Set=1 setzt das Symbol, ist Set=0 oder nicht vorhanden, wird es entfernt

Rückgabetabelle
leer

Beispiel

-- Einen Frachter in der Targetliste als Missionsschiff markieren
NObject.SetMissionFlag( { Object = V.Trader, Set = 1 } )

-- Die Markierung des Frachters wieder entfernen
NObject.SetMissionFlag( { Object = V.Trader } )

-- oder so, ist semantisch verständlicher:
NObject.SetMissionFlag( { Object = V.Trader, Set = 0 } )


SetScanningFlag

SetScanningFlag( { Object, Set } ) : {}

Setzt für ein Objekt, ob es in der Targetliste und an der Zielmarkierung im HUD mit einem Scannersymbol markiert werden soll oder nicht. Das Scanningflag ist das orange Symbol, wie es bei Polizeischiffen zu sehen ist und soll anzeigen, dass das Objekt den Spieler auf illegale Waren scannen kann. Für NObject unüblich kann der Parameter 'Object' auch ein WingHandle sein. Dann werden alle Schiffe des Wings markiert. Funktioniert aber nicht für Tabellen, wie z.B. bei Containerlisten. Diese müssen einzeln markiert werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert eines SpaceObjects
Set | unsigned int | 0..1 | Set=1 setzt das Symbol, ist Set=0 oder nicht vorhanden, wird es entfernt

Rückgabetabelle
leer

Beispiel

-- Ein Militärjäger mit dem Scannersymbol markieren
-- Funktioniert auch mit einem Wing aus mehreren Schiffen
NObject.SetScanningFlag( { Object = V.Military, Set = 1 } )

-- Die Markierung des Jägers wieder entfernen
NObject.SetScanningFlag( { Object = V.Military, Set = 0 } )

-- Eine Liste mit mehreren Containern markieren
for i, container in list do
    NObject.SetScanningFlag( { Object = container, Set = 1 } )
end


SetSpecialName

SetSpecialName( { Object, Name } ) : {}

Setzt einen speziellen Namen für ein Objekt, welcher dann auch in der Targetliste und dem Zielcomputer angezeigt wird.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert eines SpaceObjects
Name | string | StringId aus der user_strings.res oder global.res | Name des Objekts

Rückgabetabelle
leer

Beispiel

-- Einem Frachter einen speziellen Namen geben
NObject.SetSpecialName( { Object = V.Trader, Name = "IDM_GLOBAL_5000_TRADERNAME" } )


TriggerDialog

TriggerDialog( { Object } ) : {}

Aktiviert den Dialog eines Objekts und startet ihn sofort. Eigene Dialoge können im Event "Dialog" angelegt werden. Der Dialog wird vom betreffenden Objekt initiiert und hat keine Reichweitenbeschränkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle des Objekts (Schiff oder Station)

Rückgabetabelle
leer

Beispiel

{   -- Spieler hat sich dem Asteroiden genähert und wird angefunkt
    2, 3, "Waypoint", function( V, Data )
    if Data.Waypoint == V.Waypoint then
    NObject.TriggerDialog( { Object = V.Asteroid } )
    end
},

{   -- Spieler hat sich dem Schiff genähert und wird angefunkt
    2, 3, "Waypoint", function( V, Data )
    if Data.Waypoint == V.Waypoint then
    NObject.TriggerDialog( { Object = V.Trader } )
    end
},


ActivateScanner( {} ) : {}

Der Spieler darf den Scanner des Spielerschiffes wieder verwenden.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- falls der Spieler-Scanner nicht funktioniert hat, ist er wieder in Ordnung
NPlayer.ActivateScanner({})


AddAmmo

AddAmmo( { Ammo, Number } ) : { Stored }

'Number' Raketen vom Typ 'Ammo' werden in das Munitionslager des Spielerschiffes gepackt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ammo | unsigned int | Index in Projectiles.ini | Index der Raketensorte, die geladen werden soll. Wird eine Raketensorte höheren Levels als der aktuelle Waffenlevel angegeben, dann werden die Raketen zwar geladen, können aber erst abgefeuert werden, wenn dieser Level erreicht und der entsprechende Raketenwerfer gekauft wurde. (Siehe auch Munitionssorten)
Number | unsigned int | > 0 | Anzahl der Raketen. Bei höheren Angaben als den vorhandenen freien Plätzen wird der Raketenwerfer voll bestückt.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Stored | unsigned int | <= Number | Anzahl der tatsächlich geladenen Raketen

Beispiel

-- dem Spieler eine Big Bang (Level 3, Stufe 4) geben
NPlayer.AddAmmo( { Ammo = 12, Number = 1 } )


AddAmmoType

AddAmmoType( { AmmoType, Number } ) : { Stored }

Ähnlich wie "NPlayer.AddAmmo", funktioniert jedoch nicht mit dem Index, es wird nichts geladen.
Eventuelle Namen für 'AmmoType' müssen noch getestet werden. Es muss auch geprüft werden, ob der Parameter 'Number' überhaupt existiert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
AmmoType | unsigned int (?) | Index in Projectiles.ini (?) | Index oder Name der Raketensorte, die geladen werden soll? (Siehe auch Munitionssorten)
Number (?) | unsigned int | > 0 | Anzahl der Raketen. Bei höheren Angaben als den vorhandenen freien Plätzen wird der Raketenwerfer voll bestückt.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Stored | unsigned int | 0 .. Number | Anzahl der tatsächlich geladenen Raketen

Beispiel


AddCredits

AddCredits( { Credits, Message } ) : {}

Überweist einen Betrag auf das Spielerkonto.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Credits | unsigned int | n/a | Geldmenge in Credits
Message | bool | n/a | Die Nachricht "nnn Credits erhalten" wird angezeigt

Rückgabetabelle
leer

Beispiel

-- Spieler bezahlen
NPlayer.AddCredits( { Credits = 50000 } )


AmmoInfo

AmmoInfo( { Type } ) : { Count }

Liefert die vorhandene Anzahl an Raketen des übergebenen Typs an Bord des Spielerschiffs.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | AMMO_TYPE_SWARM, AMMO_TYPE_HELLFIRE, AMMO_TYPE_BIGBANG | Raketentyp

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Count | unsigned int | n/a | Anzahl der Raketen

Beispiel

V.Rockets = {}
V.Rockets[1] = NPlayer.AmmoInfo( { Type = AMMO_TYPE_SWARM } ).Count
V.Rockets[2] = NPlayer.AmmoInfo( { Type = AMMO_TYPE_HELLFIRE } ).Count
V.Rockets[3] = NPlayer.AmmoInfo( { Type = AMMO_TYPE_BIGBANG } ).Count


DeactivateScanner( {} ) : {}

Der Scanner des Spielerschiffes wird abgeschaltet.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- der Scanner des Spielers funktioniert nicht mehr
NPlayer.DeactivateScanner({})


DestroyPlayerShip

DestroyPlayerShip( {} ) : { Done }

Wenn das Spielerschiff im Weltraum ist, wird es zerstört und eine Death-Cam gestartet.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Done | bool | n/a | ist true, wenn das Spielerschiff zerstört wurde.

Beispiel

-- das Spielerschiff wird zerstört
NPlayer.DestroyPlayerShip({})


EndEscort( {} ) : {}

Das Spielerschiff verlässt den Wing, in dem es sich momentan befindet.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- Zielsystem erreicht, Eskorte beenden
    1, nil, "Wing", function( V, Data )
    if WING_ENTER_SYSTEM == Data.Event then
    NPlayer.EndEscort({})
    end
end },


EquipmentInfo

EquipmentInfo( { Type } ) : { Level, Count, Size }

Ruft Informationen über einen Ausrüstungsgegenstand ab. Die zurückgelieferten Werte hängen vom Ausrüstungsgegenstand ab.
Hinweis: Derzeit nur für EQUIPMENT_CARGO_COMPUTER und EQUIPMENT_ORE_COLLECTOR implementiert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | EQUIPMENT_ORE_COLLECTOR, EQUIPMENT_CARGO_COMPUTER | Typ des Ausrüstungsgegenstandes

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Level | unsigned int | 0 .. 4 | Level des Ausrüstungsgegenstandes
Count | unsigned int | 1 .. 3 0 .. 1 | EQUIPMENT_CARGO_COMPUTER: Anzahl der Frachtdrohnen, EQUIPMENT_ORE_COLLECTOR: Anzahl der eingebauten Geräte
Size | unsigned int | CONTAINER_SMALL, CONTAINER_MEDIUM, CONTAINER_LARGE | Containergröße für EQUIPMENT_CARGO_COMPUTER

Beispiel

-- Informationen zum Frachtcomputer abfragen
local info = NPlayer.EquipmentInfo( { Type = EQUIPMENT_CARGO_COMPUTER } )

-- Der Spieler muss mindestens zwei 100T-Container transportieren können
if ( info.Count > 1 ) and ( info.Size > CONTAINER_SMALL ) then
    tuwas
end


EscortNPC

EscortNPC( { Ship, Leader } ) : { Wing }

Das Spielerschiff wird in den Wing eines KI-Schiffs eingefügt. Hat das Zielschiff keinen Wing, so wird ein Wing erzeugt. Das Spielerschiff verlässt automatisch den Wing, in dem es sich momentan befindet. Während der Eskorte kann der Spieler selbst keine Hyperraumsprünge mehr ausführen, sondern nur noch zusammen mit dem KI-Wing, wenn dieser einen Sprung durchführt. Ein gesetzter LockHyperJump bleibt in diesem Fall ohne Wirkung, wird aber auch nicht zurückgesetzt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Zielschiffs
Leader | bool | default=false | Spieler wird Leader des Wings, wenn true

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handle des Wings, in den das Spielerschiff eingefügt wurde

Beispiel

-- Spieler soll den Frachter eskortieren
NPlayer.EscortNPC( { Ship = V.Trader } )

-- Spieler eskortiert den Hunter, liefert dessen Winghandle und wird Leader des Wings
V.HunterWing = NPlayer.EscortNPC( { Ship = V.Hunter, Leader = true } ).Wing

-- dito, der Hunter wird aber vorher aus seinem Wing entfernt und gründet einen neuen
V.PlayerWing = NShip.JoinWing( { Ship = V.Hunter, WingType = WINGTYPE_HUNTER } ).Wing
NPlayer.EscortNPC( { Ship = V.Hunter, Leader = true } )


FirePlasma

FirePlasma( { Target, Type } ) : {}

Das Spielerschiff feuert einen Plasmastrahl auf das angegebene Ziel ab. Der Plasmastrahl hat keine Auswirkung auf das Ziel, es ist nur ein optischer Effekt mit z.T. begleitendem Sound. Der Effekt hat keine Reichweitenbeschränkung. Beim Abschuss des Waffenstrahls wackelt auch das ganze Cockpit der Darkstar.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Target | unsigned int | CObjectHandle | Handle des Objekts, welches beschossen werden soll. Kann ein beliebiges Spaceobjekt sein.
Type | enum | Effekte | Konstante eines Plasmastrahl-Effekts

Rückgabetabelle
leer

Beispiel

-- Feuert einen Overload-Plasmastrahl auf ein Schiff ab
NPlayer.FirePlasma( { Target = V.Ship, Type = EFFECT_OVERLOAD } )

-- Auch die Handelsstation kriegt was ab
NPlayer.FirePlasma( { Target = V.TradeStation, Type = EFFECT_EMP } )


GetContainer

GetContainer( {} ) : { Number, Container0, Container1, Container2 }

Die Handles der Container des Spielers werden ausgegeben. 'Number' enthält die Anzahl der gültigen Container. Die gültigen Container werden in den ersten Handles ausgegeben.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Number | unsigned int | 0 .. 3 | Anzahl der Container
Container0 | unsigned int | CContainerHandle | Handle des ersten Containers
Container1 | unsigned int | CContainerHandle | Handle des zweiten Containers
Container2 | unsigned int | CContainerHandle | Handle des dritten Containers

Beispiel

local cargo = NPlayer.GetContainer({})
local goods = {}

-- Die Missionswaren der Container auslesen
for i = 1, cargo.Number do
    local nr = i - 1
    goods[i] = NContainer.GetMissionGood( { Container = cargo["Container"..nr] } )
end


GetCriminalRecord

GetCriminalRecord( { System } ) : { Crime }

Die Strafpunkte für das angegebene System werden ausgegeben. Wird kein gültiges System übergeben, werden die Strafpunkte des aktuellen Systems ausgegeben.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0 .. 402 | Id des Sytems, für das das Strafenregister gelesen wird

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Crime | float | 0.0 .. 5.0 | Strafpunkte in dem System

Beispiel

-- Strafpunkte des Spielers im aktuellen System abfragen
crime = NPlayer.GetCriminalRecord({}).Crime

-- Strafpunkte des Spielers im Sol-System abfragen
earth = NPlayer.GetCriminalRecord( { System = 29 } ).Crime


IsEona

IsEona( {} ) : { Eona }

Prüft, ob Eona an Bord ist (in der Story ist sie ja eine Weile entführt).

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Eona | bool | n/a | Eona ist an Bord (true) oder nicht (false)

Beispiel

V.Eona = NPlayer.IsEona({}).Eona


IsObjectInView

IsObjectInView( { Object } ) : { InView }

Ermittelt, ob sich ein Objekt im Sichtfeld des Spielers befindet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Zu testendes Objekt

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
InView | bool | n/a | true, wenn das Objekt im Sichtfeld des Spielers ist

Beispiel

if NPlayer.IsObjectInView( { Object = V.Sat } ).InView then
    V.Step = 2.0
end


LandOnBase

LandOnBase( { Object } ) : {}

Lässt den Spieler auf der Handelsstation, einer Forschungsstation, einem Asteroiden oder großen Kreuzer landen.
Dabei wird automatisch die Cutscene der Landung abgespielt. Das normalerweise bei Forschungsstationen und Asteroiden bestehende Landeverbot wird hier ignoriert, es muss also nicht erst die Funktion "NObject.PlayerLanding" ausgeführt werden. Auch die Entfernung von der Station spielt hierbei keine Rolle. Hat bei Objekten ohne Hangar keine Auswirkung.
Hinweis: Große Kreuzer sollten stillstehen, sonst schafft es die Darkstar One meistens nicht in den Hangar.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CStationHandle | Handle eines Space-Objekts mit Hangar

Rückgabetabelle
leer

Beispiel

-- Spieler auf einer Forschungsstation landen lassen
NPlayer.LandOnBase( { Object = V.ResearchStation } )

-- Spieler soll auf einem Kreuzer landen
MissionLib.WingAiActionWarten( V.CruiserWing )
NPlayer.LandOnBase( { Object = V.Cruiser } )


LeaveSpaceStation( {} ) : {}

Lässt das Spielerschiff aus dem Hangar starten, in dem es akuell gelandet ist. Hat keine Auswirkungen, wenn das Spielerschiff nicht gelandet ist.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Spieler aus der Station werfen
NPlayer.LeaveSpaceStation({})


LockHyperJump

LockHyperJump( { Lock } ) : {}

Regelt die Verfügbarkeit des Hyperraumsprungs für den Spieler. Ist Lock = true, kann der Spieler kein System mehr auf der Navigationskarte auswählen und daher auch nicht in ein anderes System springen. Ein bereits gewähltes Ziel wird deselektiert. Ist der Spieler einem KI-Wing beigetreten und dieser springt zusammen mit ihm in ein anderes System, hat die Sperre keine Wirkung. Sie bleibt aber gesetzt, wenn der Spieler den KI-Wing wieder verlässt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Lock | bool | n/a | Sprung sperren (true) oder erlauben (false)

Rückgabetabelle
leer

Beispiel

-- Du darfst hier nicht mehr raus
NPlayer.LockHyperJump( { Lock = true } )


LockSystemEntry

LockSystemEntry( { Locked } ) : {}

Der Systemeintritt des Spielerschiffes wird gesperrt oder freigegeben. Ist der Eintritt gesperrt, wartet das Spielerschiff im Hypergate. LockSystemEntry sollte so früh wie möglich und noch vor der Objekterzeugung im System-Event ENTER_PRECAM gesetzt werden. Eignet sich gut, um z.B. Videosequenzen vor dem Systemeintritt abzuspielen. Wenn der Eintritt wieder freigegeben wird, startet eine Entry-Kamera und das Spielerschiff kommt aus dem Hypergate.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Locked | int | n/a | wenn Locked > 0 ist, wird das System gesperrt, sonst freigegeben

Rückgabetabelle
leer

Beispiel

-- Systemeintritt sperren
NPlayer.LockSystemEntry( { Locked = 1 } )

-- z.B. besondere Kameras anzeigen
...

-- Spieler in das System kommen lassen
NPlayer.LockSystemEntry({})


MoveAhead

MoveAhead( { Speed } ) : {}

Solange eine ActionCam läuft, fliegt das Spielerschiff geradeaus. Danach erhält der Spieler wieder die Steuerung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Speed | float | n/a | Optionale Geschwindigkeitsangabe (4.0 = 100%)

Rückgabetabelle
leer

Beispiel

-- Kamera erzeugen, sonst gehts nicht
V.Camera = NCamera.CreateBoundCam( { TargetObject = V.Hunter, Time = 8.5 } ).Camera

-- Spieler geradeaus fliegen lassen
NPlayer.MoveAhead({})

-- Nachbrenner zünden
NPlayer.MoveAhead( { Speed = 20.0 } )


SelectNearestEnemy( {} ) : {}

Selektiert das nächste zum Spieler feindliche Objekt.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Ziel ist außer Schußweite, nächsten Gegner anwählen
if NObject.DistanceFromPlayer( { Object = V.Enemy } ).Distance > 1000 then
    NPlayer.SelectNearestEnemy({})
end


SelectTarget

SelectTarget( { Object } ) : {}

Selektiert das Objekt als Ziel des Spielerschiffs und zeigt es im Zielcomputer an.
Das Objekthandle darf ungültig sein, aber nicht nil. In dem Fall wird das aktuell selektierte Objekt abgewählt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Zu selektierendes Objekt

Rückgabetabelle
leer

Beispiel

-- Den Kommunikationssatelliten auswählen
NPlayer.SelectTarget( { Object = V.Sat } )

-- Aktuell selektiertes Objekt abwählen
NPlayer.SelectTarget( { Object = 0 } )


SendMail

SendMail( { Category, Text } ) : {}

Verschickt eine EMail an den Spieler.
Hinweis: Gültige Kategorien sind im LokaTool unter "MISSION/STORYLINE/EMAIL" zu finden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Category | string | StringId aus dem LokaTool | Titel der Kategorie, in der die Nachricht auftaucht
Text | string | StringId aus dem LokaTool | Text der Nachricht

Rückgabetabelle
leer

String-IDs für Category
StringId | Kategorie
IDM_EMAIL_CAT_A | Hauptstory
IDM_EMAIL_CAT_B | Nützliche Informationen
IDM_EMAIL_CAT_C | Persönliche Nachrichten

Beispiel

-- Spieler einen Eintrag in "Persönliche Nachrichten" schicken
NPlayer.SendMail( { Category = "IDM_EMAIL_CAT_PERSONAL", Text = "IDM_BLUBB" } )


SetCloakScanner

SetCloakScanner( { Set } ) : {}

Schaltet den Tarnfeldscanner ein oder aus.
Im eingeschalteten Zustand werden Objekte, die mit "NShip.SetCloaked" getarnt wurden, zwar nicht (besser) sichtbar, lassen sich nun aber in der Targetliste und im All wieder anwählen. Die Funktion hat keine Auswirkung bei Schiffen, die mit "NShip.SetHidden" für den Zielcomputer versteckt wurden. Etwas anders ist die Auswirkung, wenn das Objekt getarnt und mit "NObject.RadarMapColor( { Object=Objekt, Color=RADARMAP_INVISIBLE } )" im Zielcomputer versteckt und auch im All nicht anwählbar gemacht wurde. Schaltet man in diesem Fall den Tarnfeldscanner ein, wird das Objekt zwar immer noch nicht in der Targetliste angezeigt und bleibt unsichtbar, kann nun aber im All angewählt werden (wenn man es findet, was bei Kreuzern anhand der Triebwerksumrisse von hinten möglich ist) und wird auch in der Targetview des Cockpits angezeigt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Set | bool | default=false | Tarnfeldscanner ein- (true) oder ausschalten (false)

Rückgabetabelle
leer

Beispiel

-- Tarnfeldscanner aktivieren
NPlayer.SetCloakScanner( { Set = true } )

-- Tarnfeldscanner deaktivieren
-- Funktioniert zwar auch ohne Parameter, ist aber semantisch irreführend.
NPlayer.SetCloakScanner({})

-- Es ist daher besser fürs Verständnis, den Parameter Set=false einzusetzen:
NPlayer.SetCloakScanner( { Set = false } )


SetMultipliers

SetMultipliers( { RollFactor, RotFactor, MaxSpeedFactor, AccelFactor, MaxShiftFactor, ShiftAccelFactor, BoostFactor, MinSpeedFactor, MinBrakeSpeed } ) : {}

Verändert die Schiffswerte des Spielers. Wird ein Wert nicht angegeben, wird der programmseitige Defaultwert verwendet. Alle Faktoren beziehen sich auf den jeweiligen Grundwert des Schiffs. BoostFactor = 2.0 bedeutet damit eine doppelte normale Nachbrenner-Geschwindigkeit, insgesamt also dreifache Normalgeschwindigkeit.

Ausnahmen:
'MinSpeedFactor' bezieht sich auf die aktuelle Höchstgeschwindigkeit, also inklusive 'MaxSpeedFactor'.
'MinBrakeSpeed', dies ist ein absoluter (meist negativer) Wert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
RollFactor | float | RollFactor >= 0.0 | Faktor für das Rollen um die Z-Achse (Maximalwert & Beschleunigung)
RotFactor | float | RotFactor >= 0.0 | Faktor für die Rotation um die X- und Y-Achsen (Maximalwert & Beschleunigung)
MaxSpeedFactor | float | MaxSpeedFactor >= 0.0 | Faktor für die Maximalgeschwindigkeit
AccelFactor | float | AccelFactor >= 0.0 | Faktor für die Beschleunigung (Antrieb und Nachbrenner)
MaxShiftFactor | float | MaxShiftFactor >= 0.0 | Faktor für die Maximalgeschwindigkeit mit den Steuerdüsen
ShiftAccelFactor | float | ShiftAccelFactor >= 0.0 | Faktor für die Beschleunigung der Steuerdüsen
BoostFactor | float | BoostFactor >= 0.0 | Faktor für die Endgeschwindigkeit mit dem Nachbrenner
MinSpeedFactor | float | MinSpeedFactor >= 0.0 | Faktor die minimale Geschwindigkeit (nur im Canyon wirksam)
MinBrakeSpeed | float | MinBrakeSpeed <= 0.0 | Minimale Rückwärtsgeschwindigkeit (sollte <= 0.0 sein, -1.0 = -25%)

Rückgabetabelle
leer

Beispiel

-- Nachbrenner um 20% schneller, Rückwärtsgeschwindigkeit = -30%
NPlayer.SetMultipliers( { BoostFactor = 1.2, MinBrakeSpeed = -1.2 } )

-- Nur die Rückwärtsgeschwindigkeit auf -100%, alles andere auf Grundwert
NPlayer.SetMultipliers( { MinBrakeSpeed = -4.0 } )

-- Alles wieder auf den Grundwert zurücksetzen
NPlayer.SetMultipliers({})


StandardReward

StandardReward( { Factor } ) : { Credits }

Liefert die Standardbelohnung für den aktuellen Spielerlevel. Die Belohnung kann durch die Angabe eines Faktors modifiziert werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Factor | float | 0.0f < Factor | Faktor für den Belohnungswert

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Credits | unsigned int | n/a | Belohnungswert in Credits

Beispiel

-- Spieler erhält die doppelte Standardbelohnung
NPlayer.AddCredits( { Credits = NPlayer.StandardReward( { Factor = 2.0 } ).Credits } )


StartFollow

StartFollow( { Wing, Offset } ) : {}

Das Spielerschiff soll einem KI-Wing folgen. Der Spieler verliert die Kontrolle über das Schiff, allerdings wird keine Kamera erzeugt. Ist kein Offset angegeben, nimmt der Spieler eine freie Position im Wing ein. Sind alle Positionen besetzt, wird der Offset (0,100,0) gewählt.
Wichtig: Der Spieler wird nicht in den Wing aufgenommen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handle des Wings, dem das Spielerschiff folgen soll
Offset | table[3] : float | n/a | Offset-Koordinate relativ zum Wing

Rückgabetabelle
leer

Beispiel

-- Den Spieler Ramirez hinterherfliegen lassen
NPlayer.StartFollow( { Wing = V.Ramirez } )


StopFollow( {} ) : {}

Das Spielerschiff hört auf, einem KI-Wing zu folgen und der Spieler erhält die Kontrolle über das Schiff zurück.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Dem Spieler die Steuerung wiedergeben
NPlayer.StopFollow({})


Register

Register( { Name, Type, Group, Transitions } ) : {}

Registriert ein Missionsskript im Missionssystem. Für die allgemeine Syntax eines Missionsskripts und die Verwendung von Transitionen siehe ScriptingCommands : Allgemeines im Menüpunkt Commands und Skriptsystem im Menüpunkt ModdingGuide.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | n/a | Interner Name des Skripts. Muss eindeutig sein. Hat nichts mit dem Dateinamen zu tun.
Type | enum | MTYPE_ALWAYS, MTYPE_SPACE, MTYPE_TERMINAL, MTYPE_BAR, MTYPE_CHAPTER, MTYPE_TUNNEL, MTYPE_STORY, MTYPE_STORY_TERMINAL, MTYPE_STORY_CHAPTER, MTYPE_STORY_BAR, MTYPE_MENU, MTYPE_USER_TERMINAL, MTYPE_USER_SPACE, MTYPE_GLOBAL, MTYPE_VIDEO, MTYPE_NONE | Typ der Mission. Beeinflusst den Zeitpunkt der Erzeugung und die Verfügbarkeit.
Group | unsigned int | n/a | Gruppenindex (derzeit nicht verwendet)
Transitions | table[n] : {float,float,string,function} | n/a | Liste aller Missionszustände

Rückgabetabelle
leer

Beispiel

NScript.Register( {
    Name = "HUMAN_000",
    Group = 0,
    Type = MTYPE_TERMINAL,
    Transitions = {

{   -- Mission prüfen, ob sie erzeugt werden darf
    nil, nil, "Init", function( V, Data )
    if MissionLib.GetStarSystemId() == 8 and MissionLib.GetPlayerLevel() == 0 then
        return { Ready = true }
    end
    return { Ready = false}
end },

{   -- Mission wird erzeugt (wenn "Init" true zurückliefert)
    nil, nil, "Create", function( V, Data )
    V.Reward = 12345
    V.Step = 1
end },
...
...
}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


AddContainer

AddContainer( { Ship, Container } ) : {}

Dockt einen bestehenden Container an einen Frachter an. Referenziert das übergebene Handle keinen Frachter, schlägt die Funktion mit einer Fehlermeldung fehl.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Zielschiffs. Muss ein Frachter sein oder die Darkstar, wenn sie gelandet ist
Container | unsigned int | CContainerHandle | Handle des anzudockenden Containers

Rückgabetabelle
leer

Beispiel

NShip.AddContainer( { Ship = V.Trader, Container = V.Container } )


AddDialog

AddDialog( { Ship, Exclusive } ) : {}

Fügt die aufrufende Mission in den Dialog des Schiffs ein. Wird der Dialog des Schiffs aufgerufen, so erhält die Mission Dialog-Events und muss die Texte und Eingabemöglichkeiten im Event "Dialog" bereitstellen. Ist 'Exclusive' true, dann wird der vorhandene Standard-Dialog des Schiffs komplett überschrieben, das heißt, es stehen keine Standardtexte und -eingaben mehr zur Verfügung (z.B. Frachter-Geleitschutz). Andernfalls werden die Missionseingaben an die bestehenden Dialogdaten angehängt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Exclusive | bool | default=false | Standarddialog überschreiben (true) oder Dialogdaten einfügen (false)

Rückgabetabelle
leer

Beispiel

-- Frachter bekommt neuen Dialog, keine Standardantworten mehr
NShip.AddDialog( { Ship = V.Trader, Exclusive = true } )


CreateRandomCargo

CreateRandomCargo( { Ship } ) : { ContainerList }

Erzeugt für alle freien Containerplätze eines Handelsfrachters Container mit zufälligen Importwaren und dockt sie am Schiff an. Exportwaren werden nicht erzeugt. Jeder Container wird mit genau einer Ware voll beladen. Wurden vorher bereits Container angedockt, werden sie als erste mit in die Containerliste übernommen. Referenziert das übergebene Handle keinen Handelsfrachter, hat die Funktion keine Auswirkung (auch nicht mit dem Spielerschiff in der Handelstation).

ACHTUNG: Funktioniert nicht bei Piraten- und Superfrachtern.
Es werden keine Container erzeugt und angedockt, bei Superfrachtern stürzt das Programm sogar sofort ab mit der Fehlermeldung:
EXCEPTION_ACCESS_VIOLATION: "The thread tried to read from or write to a virtual address for which it does not have the appropriate access".
Für diese Frachter muss entweder die Funktion NContainer.Create() mit anschließendem NContainer.Equip() oder eine der beiden Funktionen NShip.EquipContainer() und MissionLib.LoadCargo() verwendet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs, muss ein Handelsfrachter sein

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
ContainerList | table[n] : unsigned int | CContainerHandle | Liste der Handles aller Container am Schiff

Beispiel

-- Dem Frachter zufällige Waren mitgeben
NShip.CreateRandomCargo( { Ship = V.Trader } )

-- Dem Frachter zufällige Waren mitgeben und die Containerliste speichern
V.ContainerList = NShip.CreateRandomCargo( { Ship = V.Trader } ).ContainerList


CreateWreck

CreateWreck( { Ship } ) : {}

Zerstört den angegebenen Kreuzer und hinterlässt dessen Wrack. Es wird dabei keine Todesanimation angezeigt, d.h. der Kreuzer wird einfach durch sein Wrack ersetzt. Es wird ein WING_DESTROYED Event (jedoch kein "StarshipDestroyed") ausgelöst. Hat auf Frachter, Jäger und sonstige Schiffe keine Auswirkung. Es darf kein COrbiterHandle übergeben werden, sonst stürzt das Programm mit der Fehlermelung "invalid Handle" ab. Leider liefert die Funktion kein Handle des erzeugten Wracks zurück.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Id des Kreuzers

Rückgabetabelle
leer

Beispiel

-- Kreuzer verschrotten
NShip.CreateWreck( { Ship = V.Cruiser } )


DeactivateSkaaShield

DeactivateSkaaShield( { Ship } ) : {}

Deaktiviert den Schild des S'kaa-Mutterschiffs.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des S'kaa-Kreuzers

Rückgabetabelle
leer

Beispiel

-- S'kaaschild abschalten
NShip.DeactivateSkaaShield( { Ship = V.SkaaCruiser } )


DropContainer

DropContainer( { Ship, Container } ) : {}

Veranlasst einen Frachter, den genannten Container fallen zu lassen. Referenziert das übergebene Handle keinen Frachter, schlägt die Funktion mit einer Fehlermeldung fehl. Ist der Container nicht an dem Frachter angedockt, so hat die Funktion keine Auswirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Zielschiffs. Muss ein Frachter sein
Container | unsigned int | CContainerHandle | Handle des abzudockenden Containers

Rückgabetabelle
leer

Beispiel

-- Container fallenlassen
NShip.DropContainer( { Ship = V.Trader, Container = V.Container } )


DumpCargo

DumpCargo( { Ship, Destroy } ) : { ContainerList }

Veranlasst das Schiff, alle angedockten Container abzuwerfen. Ist 'Destroy' = true, werden die Container sofort gelöscht, andernfalls enthält die Rückgabetabelle die Liste aller ContainerHandles. Hat für das Spielerschiff keine Auswirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Destroy | bool | default=false | Fracht zerstören (true) oder abwerfen (false)

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
ContainerList | table[n] : unsigned int | CContainerHandle | Liste aller Handles der abgeworfenen Container

Beispiel

-- Alle Container fallenlassen und löschen
NShip.DumpCargo( { Ship = V.Trader, Destroy = true } )

-- Alle Container fallenlassen und in Containerliste speichern
V.Container = NShip.DumpCargo( { Ship = V.Trader } ).ContainerList


EquipContainer

EquipContainer( { Ship, Goods } ) : { Container }

Erzeugt einen mit der angegebenen Ware komplett gefüllten Container und dockt ihn am Schiff an. Die Containergröße wird automatisch dem Frachter angepasst. Die Ware kann entweder eine Handelsware oder eine Missionsware sein und muss immer angegeben werden. 'Ship' muss ein Frachterschiff sein, andernfalls schlägt die Funktion mit einer Fehlermeldung fehl. Falls der Frachter keine freie Containerposition mehr hat, schlägt die Funktion ebenfalls mit einer Fehlermeldung fehl, ggf. vorher mit "NShip.GetNumCargoBays" abfragen. Mit Canyon-Taxis funktioniert EquipContainer auch nicht, jedoch kann dafür die Funktion "NContainer.Create" verwendet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs, muss ein Frachter sein
Goods | enum oder string | Handelsware oder StringId aus der user_strings.res | Id der Handelsware oder Bezeichner der Missionsware

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des erzeugten Containers

Beispiel

-- Container mit Handelsware erzeugen, andocken und Container speichern
V.Container = NShip.EquipContainer( { Ship = V.Trader, Goods = GOODS_DRUGS } ).Container

-- Container mit Handelsware erzeugen und andocken
NShip.EquipContainer( { Ship = V.Trader, Goods = GOODS_COMPUTERS } )

-- Container mit Missionsware erzeugen und andocken
NShip.EquipContainer( { Ship = V.Trader, Goods = "IDM_GOODS_FURBALLS" } )

-- Leeren Container erzeugen und andocken, 'Goods' muss angegeben werden, sonst Absturz
NShip.EquipContainer( { Ship = V.Trader, Goods = "" } )


EscortPlayer

EscortPlayer( { Ship } ) : { Wing }

Nimmt das KI-Schiff in den Wing des Spielers auf. War es das einzige Schiff im Wing, wird der KI-Wing im Anschluss gelöscht und löst ein WING_DESTROYED Event aus. Hat der Spieler noch keinen Wing, so wird ein neuer Wing erzeugt. Das Schiff erhält durch die Aufnahme in den Wing noch kein neues Verhaltensmuster.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handle des Wings des Spielers

Beispiel

-- Erstes Begleitschiff aufnehmen, Spielerwing wird erzeugt
V.PlayerWing = NShip.EscortPlayer( { Ship = V.Hunter1 } ).Wing

-- Nächstes Schiff dem Wing hinzufügen
NShip.EscortPlayer( { Ship = V.Hunter2 } )


Explode

Explode( { Ship } ) : {}

Das angegebene Schiff explodiert nach kurzem Trudeln und wird zerstört. Es wird kein "StarshipDestroyed" Event ausgelöst.

Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs

Rückgabetabelle
leer

Beispiel
-- Pirat ins Vakuum jagen
NShip.Explode( { Ship = V.Pirate } )


GetAlignment

GetAlignment( { Ship } ) : { Pos, Front, UpDir }

Liefert die Ausrichtung eines Schiffes. Nicht für Schiffswracks, hier müssen die Funktionen von NObject verwendet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Pos | table[3] : float | n/a | die absolute Koordinate des Schiffes
Front | table[3] : float | n/a | Ausrichtung der Z-Achse des Schiffes (Ebenenwinkel)
UpDir | table[3] : float | n/a | Ausrichtung der Y-Achse des Schiffes (Höhenwinkel)

Beispiel

-- liest die Ausrichtung eines Schiffes aus
local align = NShip.GetAlignment( { Ship = V.Player } )

-- ein anderes Schiff genauso wie V.Player ausrichten
NShip.SetAlignment( { Ship = V.Hunter, Front = align.Front, UpDir = align.UpDir } )


GetHideOut

GetHideOut( {} ) : { Ship, Wing }

Sucht nach einem Piratenversteck. Wird ein Piratenversteck gefunden, wird sein Handle in 'Ship' und sein Wing in 'Wing' zurückgegeben. Ein weiteres Piratenversteck wird nicht gesucht. Zur Zeit ist nur ein Piratenversteck pro System vorgesehen, sodass das kein Problem machen sollte.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des gefundenen Piratenverstecks (327679, wenn keins existiert)
Wing | unsigned int | CWingHandle | Handle des Wings, zu dem das Piratenversteck gehört (720895, wenn keins existiert)

Beispiel


GetNumCargoBays

GetNumCargoBays( { Ship, Free } ) : { NumCargoBays }

Liefert die maximale Anzahl der Containerplätze eines Frachters, bzw. die maximale Anzahl der freien Plätze. Liefert für alle anderen Schiffe 0 zurück.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Free | bool | default=false | true, wenn nur die freien Plätze gezählt werden sollen

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
NumCargoBays | unsigned int | n/a | Anzahl der Containerplätze

Beispiel

local freeBays = NShip.GetNumCargoBays( { Ship = V.Trader, Free = true } ).NumCargoBays

-- Einen (weiteren) Container andocken, falls noch Platz ist
if freeBays > 0 then
    V.Container = NShip.EquipContainer( {
    Ship = V.Trader,
    Goods = "IDM_GOODS_FURBALLS"
    } ).Container
end


GetSkaaShieldEnterPos

GetSkaaShieldEnterPos( { Ship } ) : { Position, Front, UpDir }

Liefert Position und Ausrichtung der Eintrittsöffnung im Schild des S'kaa-Mutterschiffs.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des S'kaa-Kreuzers

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | die absolute Koordinate der Eintrittsposition
Front | table[3] : float | n/a | Ausrichtung der Z-Achse der Eintrittsöffnung (Ebenenwinkel)
UpDir | table[3] : float | n/a | Ausrichtung der Y-Achse der Eintrittsöffnung (Höhenwinkel)

Beispiel

-- Ausrichtung der Öffnung im S'kaaschild auslesen
local align = NShip.GetSkaaShieldEnterPos( { Ship = V.SkaaCruiser } )

-- Position in die V-Tabelle
V.Position = align.Position

-- Spielerschiff genauso wie die Schildöffnung ausrichten
NShip.SetAlignment( { Ship = V.Player, Front = align.Front, UpDir = align.UpDir } )


IsInSpace

IsInSpace( { Ship } ) : { InSpace }

Prüft, ob sich das angegebene Schiff im All befindet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Id des Schiffs

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
InSpace | unsigned int | 0..1 | Das Schiff ist im Weltraum (1) oder nicht (0)

Beispiel

if NShip.IsInSpace( { Ship = V.Player } ).InSpace == 1 then
    V.Info = "Du fliegst draußen herum"
else
    V.Info = "Du bist gelandet"
end


IsPlayerShip

IsPlayerShip( { Ship } ) : { IsPlayer }

Prüft, ob das angegebene Schiff das Spielerschiff ist.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Id des Schiffs

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
IsPlayer | unsigned int | 0..1 | Ship ist das Spielerschiff (1) oder nicht (0)

Beispiel

local ships = {}
ships[1] = MissionLib.GetPlayerHandle()
ships[2] = V.HunterLeader
ships[3] = V.PirateLeader
random = MissionLib.RandomInteger( 1, 3 )

if NShip.IsPlayerShip( { Ship = ships[random] } ).IsPlayer == 1 then
    V.Info = "ID_DARKSTAR"
end


JoinWing

JoinWing( { Ship, Wing | WingType } ) : { Success, Wing }

Ein Schiff soll einem Wing beitreten oder ihn verlassen und einen neuen Wing gründen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Wing | unsigned int | CWingHandle | Handle des Wings
WingType | unsigned int | Wingtypen | Art des zu erzeugenden Wings

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Success | bool | n/a | true, wenn dem Wing beigetreten werden konnte (funktioniert nicht, ist immer nil)
Wing | unsigned int | CWingHandle | Handlewert des erzeugten Wings

Beispiel

-- Alle Schiffe des AlphaWings treten dem BravoWing bei.
-- Anschließend wird der AlphaWing automatisch gelöscht und löst ein WING_DESTROYED Event aus.
-- Daher kann und sollte die Variable ebenfalls gelöscht werden.
for i, ship in NWing.List( { Wing = V.AlphaWing } ).ShipList do
    NShip.JoinWing( { Ship = ship, Wing = V.BravoWing } )
end
V.AlphaWing = nil

-- Alle Schiffe außer dem Leader des AlphaWings treten dem BravoWing bei.
local shiplist = NWing.List( { Wing = V.AlphaWing } ).ShipList
for i = 2, lua.sizeof( shiplist ) do
    NShip.JoinWing( { Ship = shiplist[i], Wing = V.BravoWing } )
end

-- Wie oben, jedoch verlässt der Leader erst den Wing und bekommt einen neuen gleichen Namens.
-- Da das alte Handle vom AlphaWing gelöscht wird, muss auch hier WING_DESTROYED beachtet werden.
local leader = MissionLib.GetWingLeaderID( V.AlphaWing )
local alphaWing = NShip.JoinWing( { Ship = leader, WingType = WINGTYPE_MILITARY } ).Wing
for i, ship in NWing.List( { Wing = V.AlphaWing } ).ShipList do
    NShip.JoinWing( { Ship = ship, Wing = V.BravoWing } )
end
V.AlphaWing = alphaWing

-- Ein Hunter verlässt den aktuellen Wing und gründet einen neuen.
V.NewWing = NShip.JoinWing( { Ship = V.HunterShip, WingType = WINGTYPE_HUNTER } ).Wing


Protect

Protect( { Ship, Protect } ) : {}

Ändert den Sterblichkeitsstatus eines Schiffs. Wenn 'Protect' true ist, kann der Rumpfzustand des Schiffs nur knapp unter 10% sinken (das StarShip-Event SHIP_HULL_10 wird gerade noch ausgelöst) und die Geschütztürme von Kreuzern und Piratenbasen können nicht abgeschossen werden.
Hinweis: Funktioniert nicht für die Darkstar und den ActionTurret (Flak).
Beachte: War die Hüllenintegrität bereits vor dem Aufruf der Funktion unter 10% gefallen, wird sie wieder auf den Grenzwert gesetzt. Soll der Wert niedriger bleiben, kann man ihn nach "NShip.Protect" wieder mit der Funktion "MissionLib.SetHull" verringern.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des betreffenden Schiffs
Protect | bool | default=false | Macht das Schiff unsterblich (true|1) oder sterblich (false|0)

Rückgabetabelle
leer

Beispiel

-- Zielschiff kann nicht mehr zerstört werden
NShip.Protect( { Ship = V.Hunter, Protect = true } )


ProtectCargo

ProtectCargo( { Ship, Protect } ) : {}

Verhindert oder erlaubt bei Frachtern den Abwurf der Container, wenn die Schilde ausfallen. Ist bei allen missionserzeugten Frachtern standardmäßig true, bei den vom Hauptprogramm automatisch erzeugten Handelsfrachtern false. Ein Frachter, der seine Fracht abwirft, wird automatisch nicht mehr feindlich sein, bis erneuter absichtlicher Beschuss durch den Spieler festgestellt wird.
Hinweis: Funktioniert nicht bei Piratenfrachtern, die müssen explizit per Skriptbefehl, z.B. mit NShip.DropContainer, zum Abwurf veranlasst werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des betreffenden Schiffs, muss ein Frachter sein
Protect | bool | n/a | Verhindert, dass die Waren abgeworfen werden (true|1) oder nicht (false|0)

Rückgabetabelle
leer

Beispiel

-- Handelsfrachter soll seine Waren normal abwerfen
NShip.ProtectCargo( { Ship = V.Trader, Protect = false } )


RemoveDialog

RemoveDialog( { Ship } ) : {}

Entfernt die Mission aus dem Dialog des Schiffs. Ein laufender Dialog wird sofort beendet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs

Rückgabetabelle
leer

Beispiel

NShip.RemoveDialog( { Ship = V.Trader } )


RemoveWeapons

RemoveWeapons( { Ship } ) : {}

Baut alle Waffen des Schiffes aus.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des betreffenden Schiffs

Rückgabetabelle
leer

Beispiel

-- das Schiff hat keine Waffen mehr
NShip.RemoveWeapons( { Ship = V.Hunter } )


SetActor

SetActor( { Ship, Actor } ) : {}

Setzt einen Akteur für das Schiff, welcher für Funkmeldungen verwendet wird. Akteure können über einen Index ( 0 oder 1 ) angegeben werden. Es wird dann der entsprechende Standardakteur für das Schiff ermittelt. Akteure können aber auch explizit mit einem Bezeichner ( z.B. "arim" oder "hummil00" ) angegeben werden, in diesem Falle wird dieser Akteur direkt verwendet. Bezeichner von Standard-Akteuren setzen sich aus einem Kürzel für die Rasse, einem Kürzel für den Actor-Typ und einem Index zusammen.

Akteure: NPCs
Kürzel | NPC | String-ID
arim | Arim | IDM_NPC_NAME_ARIM
basilius | Basilius | IDM_NPC_NAME_BASILIUS
eona | Eona | IDM_NPC_NAME_EONA
fervath | Fervath | IDM_NPC_NAME_FERVATH
hartok | Hartok | IDM_NPC_NAME_HARTOK
hornblower | Hornblower | IDM_NPC_NAME_HORNBLOWER
hunhan | Hunhan | IDM_NPC_NAME_HUNHAN
jack | Jack | IDM_NPC_NAME_JACK
jiju | Jiju | IDM_NPC_NAME_JIJU
jowhal | Jowhal | IDM_NPC_NAME_JOWHAL
jowson | Jowson | IDM_NPC_NAME_JOWSON
kabro | Kabro | IDM_NPC_NAME_KABRO
kayron | Kayron | IDM_NPC_NAME_KAYRON
kornius | Kornius | IDM_NPC_NAME_KORNIUS
mendo | Mendo | IDM_NPC_NAME_MENDO
mitri | Mitri | IDM_NPC_NAME_MITRI
naara | Naara | IDM_NPC_NAME_NAARA
nicolai | Nicolai | IDM_NPC_NAME_NICOLAI
ramirez | Ramirez | IDM_NPC_NAME_RAMIREZ
robert | Robert | IDM_NPC_NAME_ROBERT
robot | Automat | IDM_NPC_NAME_ROBOT
shurik | Shurik | IDM_NPC_NAME_SHURIK
skaa_boss | Skaaboss | IDM_NPC_NAME_SKAABOSS
tanale | Tanale | IDM_NPC_NAME_TANALE
zarkov | Zarkov | IDM_NPC_NAME_ZARKOV

Akteure: Rassen
Kürzel | Rasse
hum | Menschen
mor | Mortok
rap | Raptor
oct | Oc'to
arr | Arrack
thu | Thul

Akteure: Typen
Kürzel | Typ
mil | Militär, Polizei, Zivil
hun | Kopfgeldjäger
pir | Piraten
sta | Stationen
tra | Frachter (außer Piratenfrachter)

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Actor | unsigned int oder string | 0, 1 oder Bezeichner für einen Actor | Nummer des Akteurs. 0 und 1 sind Standardakteure aller Völker oder Explizite Angabe eines Akteurs

Rückgabetabelle
leer

Beispiel

-- Der Frachter soll immer mit der Stimme des Standardakteurs 1 reden
-- Ist der Frachter ein Mortokfrachter, so wird "mortra01" als Akteur gewählt
NShip.SetActor( { Ship = V.Trader, Actor = 1 } )

-- Der Kopfgeldjäger soll mit Ramirez' Stimme reden
NShip.SetActor( { Ship = V.Ramirez, Actor = "ramirez" } )


SetAlignment

SetAlignment( { Ship, Position, Front, UpDir } ) : {}

Setzt ein Schiff auf die gegebene Position. Die Nase des Schiffs zeigt in Richtung Front. Wird 'UpDir' nicht angegeben, wird das Schiff an der Y-Achse aufgerichtet. Hatte sich das Schiff vor der Positionsänderung noch vorwärts bewegt, dann wird es angehalten. Eine vorhandene Rollbewegung um die Längsachse bleibt aber erhalten.
Vorsicht: Die Funktion darf nicht auf Schiffe angewendet werden, die eine bestimmte Position halten müssen (z.B. Frachter beim Entladen vor der Station oder Schiffe beim Hyperraumsprung). Die Position sollte frei sein, damit die Logik nicht im nächsten Zeitschritt eine Kollision feststellt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Position | table[3] : float | n/a | absolute Koordinate (default ist die aktuelle Position)
Front | table[3] : float | n/a | Richtungsvektor für Schiffsrichtung, default ist die aktuelle Richtung (Ebenenwinkel)
UpDir | table[3] : float | n/a | Richtungsvektor, an dem das Schiff aufgerichtet wird, default ist die Y-Achse des Systems (Höhenwinkel)

Rückgabetabelle
leer

Beispiel

-- Das Schiff soll 3u über die Handelsstation gesetzt werden und zum Sprungtor schauen
NShip.SetAlignment( {
    Ship = V.Player,
    Position = { 0.0, 3000.0, 0.0 },
    Front = { 0.0, -3000.0, 10000.0 }
} )

-- Richtet das Spielerschiff so aus, wie es das automatische Ausrichten tun würde
NShip.SetAlignment( { Ship = V.Player } )


SetBoss

SetBoss( { Ship, BossId } ): {}

Das Schiff erhält eine Boss-Id. Es kann dann besondere Manöver ausführen und erhält mehr Stärkepunkte. Wird der Parameter 'BossId' auf 0 gesetzt, wird die Marke entfernt und das Schiff verwendet wieder die Standardmanöver.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
BossId | unsigned int | n/a | Id, die besondere Maneuver freischaltet

Rückgabetabelle
leer

Beispiel

-- das Schiff soll ein Bossgegner werden
NShip.SetBoss( { Ship = V.Pirate, BossId = 1 } )

-- das Schiff soll kein Bossgegner mehr sein
NShip.SetBoss( { Ship = V.Pirate, BossId = 0 } )


SetCloaked

SetCloaked( { Ship, Set } ) : {}

Tarnt bzw. enttarnt ein Schiff. Ein getarntes Schiff ist unsichtbar und lässt sich nicht anwählen. Es wird jedoch vom Zielcomputer weiterhin in der Targetliste angezeigt. Trotzdem kann es nicht mehr von den automatisch feuernden Geschütztürmen beschossen werden. Befindet sich das Schiff im Flug, kann es anhand seiner Triebwerksstrahlen ausgemacht werden. Getarnte Kreuzer können bei günstigem Blickwinkel sogar noch im Stillstand an ihren Triebwerksumrissen erkannt werden. Bei Satelliten ist noch der innere leuchtende Kern und bei Waffenplattformen der Lichtkranz zu sehen. SetCloaked funktioniert auch für die Darkstar.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Set | bool | default=false | Tarnen (true) oder enttarnen (false)

Rückgabetabelle
leer

Beispiel

-- Spielerschiff unsichtbar machen
NShip.SetCloaked( { Ship = get( "Logic.PlayerShip.id" ), Set = true } )


SetCrime

SetCrime( { Ship, Set } ) : {}

Das Schiff wird bei Beschuss Strafpunkte geben. Piraten und Hunter ohne Wing werden allerdings niemals Strafpunkte geben. Bei Shuttles (Taxis) kann man die Vergabe von Strafpunkten dagegen nicht abschalten (auch nicht mit NObject.SetCrime).

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Set | bool | n/a | Strafpunkte an (true|1) oder aus (false|0)

Rückgabetabelle
leer

Beispiel

-- Frachter soll bei Beschuss keine Strafpunkte geben
NShip.SetCrime( { Ship = V.Trader, Set = false } )


SetDurability

SetDurability( { Ship, Hull, Shield } ) : {}

Setzt einen Multiplikator für die maximalen Rumpf- und Schildpunkte. Der Multiplikator bezieht sich immer auf den Basiswert des jeweiligen Typs inklusive Boss-Status. D.h. 'Hull' = 2.0 bedeutet bei einem normalen Schiff doppelte Standardhitpoints, bei einem Boss doppelte Boss-Hitpoints. Bei jeder Änderung des Multiplikators erhalten Rumpf und Schild wieder die vollen Trefferpunkte, d.h. ein beschädigter Rumpf wurde somit repariert und die Schilde wieder voll aufgeladen.
Hinweis: Bitte nur in Ausnahmefällen verwenden, da sonst das Balancing sehr schwer fällt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des betreffenden Schiffs
Hull | float | 0.0f < Hull, default = 1.0 | Setzt einen Multiplikator für die maximalen Rumpfpunkte
Shield | float | 0.0f < Shield, default = 1.0 | Setzt einen Multiplikator für die maximalen Schildpunkte

Rückgabetabelle
leer

Beispiel

-- Setzt einen Multiplikator für die maximalen Rumpf- und Schildpunkte der DSO
MissionLib.SetPlayerDurability = function( Body, Shields )
    local PlayerShip = get( "Logic.PlayerShip.id" )
    NShip.SetDurability( { Ship = PlayerShip, Hull = Body, Shield = Shields } )
end

-- Setzt die Multiplikatoren wieder auf Standard zurück und repariert ggf. das Schiff
NShip.SetDurability( { Ship = V.Ship } )

Tipp
Möchte man die Stabilität von Rumpf und Schilden ändern, ohne das das Schiff dabei repariert wird, kann die folgende neue Funktion aus der MissionLibEx.lua verwendet werden:

-- Setzt einen Multiplikator für die maximalen Rumpf- und Schildpunkte eines Schiffs.
-- Im Gegensatz zu "NShip.SetDurability" wird das Schiff dabei nicht repariert.
-- Syntax: MissionLib.SetDurability( { Ship, Hull, Shield } )
MissionLib.SetDurability = function( Params )
    if Params.Ship then
        local ship = "Logic.StarShips."..Params.Ship
        local hullCondition        = ship..".hullCondition"
        local shieldConditionBack  = ship..".shieldConditionBack"
        local shieldConditionFront = ship..".shieldConditionFront"
        local hull  = get( hullCondition )
        local back  = get( shieldConditionBack )
        local front = get( shieldConditionFront )
        NShip.SetDurability( Params )
        set( hullCondition, hull )
        set( shieldConditionBack, back )
        set( shieldConditionFront, front )
    end
end


SetHidden

SetHidden( { Ship, Set } ) : {}

Versteckt ein Schiff für die Zielerfassung des Targetcomputers (ECM). Ein verstecktes Schiff wird vom Zielcomputer weder in der Targetliste noch auf der Radarmap angezeigt und lässt sich nicht anwählen. Es kann auch nicht mehr von den automatisch feuernden Geschütztürmen beschossen werden. Das Schiff ist jedoch weiterhin im Raum sichtbar, hat aber keine Zielmarkierung mehr (eckige Klammern) und lässt sich auch hier nicht anwählen. SetHidden funktioniert auch für die Darkstar.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Id des Schiffs
Set | bool | default=false | true = Schiff wird weder im Zielcomputer angezeigt noch ist es anwählbar false = Schiff ist im Zielcomputer sichtbar und lässt sich wieder anwählen

Rückgabetabelle
leer

Beispiel

-- Piratenjäger verstecken
NShip.SetHidden( { Ship = V.PirateLeader, Set = true } )


SetInvulnerable

SetInvulnerable( { Ship, Set } ) : {}

Ändert den Verbundbarkeitsstatus eines Schiffs. Falls 'Set' true ist, ist das Schiff immun gegen sämtliche Schäden. Es können auch Planeten durchflogen werden und Kollisionen mit Monden führen nicht mehr zur Zerstörung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des betreffenden Schiffs
Set | bool | n/a | macht das Schiff unverwundbar (true) oder verwundbar (false)

Rückgabetabelle
leer

Beispiel

-- Die DSO immun gegen sämtliche Schäden machen
NShip.SetInvulnerable( { Ship = get( "Logic.PlayerShip.id" ), Set = true } )


SetOrbiterEvasion

SetOrbiterEvasion( { Ship, Set } ) : {}

Lässt das Schiff den im Kurs liegenden Orbitern automatisch ausweichen, sodass es nicht mehr mit ihnen kollidiert. Es fliegt auch nicht in die Atmosphäre der Planeten hinein. Ist Set=false, kann das Schiff dagegen ohne Schaden die Atmosphäre durchfliegen ohne zu verglühen, zerschellen aber weiterhin auf der Oberfläche des Planeten.
Hinweis: Funktioniert auch für die Darkstar. Allerdings ist hier Vorsicht angesagt. Wird der Spielstand nämlich abgespeichert, während man sich innerhalb einer Planetenatmosphäre befindet und lädt ihn später wieder, hat er diesen Zustand "vergessen". Befand man sich zu diesem Zeitpunkt schon tief unten, wird die DSO sofort zerstört und der Spielstand ist somit unbrauchbar. Auch für KI-Schiffe wird eine abgeschaltete Orbiterumgehung nicht im Spielstand gespeichert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Id des Schiffs
Set | bool | default=true | Orbiter umfliegen (true) oder nicht (false)

Rückgabetabelle
leer

Beispiel

-- Schiff kann ohne Schaden in die Atmosphäre reinfliegen
NShip.SetOrbiterEvasion( { Ship = V.Freighter, Set = false } )


SetPlanetCollision

SetPlanetCollision( { Ship, Set } ) : {}

Die Kollision des Schiffes mit Planeten wird an- oder ausgeschaltet. Schiffe ohne Kollision mit Planeten weichen Planeten nicht aus, sie können aber auch ohne Schaden durch Planeten hindurchfliegen.
Hinweis: Funktioniert nicht für die Darkstar. In diesem Fall muss "NShip.SetInvulnerable" verwendet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Set | bool | n/a | Kollisionen an (true) oder aus (false)

Rückgabetabelle
leer

Beispiel


SetPlayerFriend

SetPlayerFriend( { Ship, Set } ) : {}

Das Schiff reagiert weniger stark auf Spielerbeschuss.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Set | bool | n/a | Weniger stark (true) oder normal (false) reagieren

Rückgabetabelle
leer

Beispiel

NShip.SetPlayerFriend( { Ship = V.Trader, Set = true } )


SetRecharge

SetRecharge( { Ship, EnergySecs, ShieldSecs, PlasmaSecs } ) : {}

Das Schiff erhält einen neuen Powergenerator, der die Energiespeicher für Waffen und Schilde in den angegebenen Zeiten wieder auflädt. Werden keine Zeiten angegeben, wird die Waffenenergie sofort und die Schildenergie in einer Stunde aufgeladen. Direkt nach dem Setzen der Aufladung ist jedoch auch ein entladener Schild erstmal wieder voll aufgeladen. Wird die Plasmawaffe des Spielers auf 0 gesetzt, während sie noch aktiv ist (Plasmaschild, Waffenboost, usw.), bleibt sie zunächst noch weiterhin aktiv, bis die Zeit ihrer Wirkungsdauer abgelaufen ist.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs.
EnergySecs | float | EnergySecs > 0 | Aufladezeit der Waffenenergie in Sekunden. -1 setzt den Standard.
ShieldSecs | float | ShieldSecs > 0 | Aufladezeit der Schilde in Sekunden. -1 setzt den Standard.
PlasmaSecs | float | default = 1.0 | Falls der Wert > 0.0 ist, wird die Plasmawaffe aufgeladen, ansonsten nicht und zuvor entladen.

Rückgabetabelle
leer

Beispiel

-- die Waffenenergie wird sofort, die Schilde sind nach 2 Minuten voll aufgeladen
NShip.SetRecharge( { Ship = V.Pirate, ShieldSecs = 120.0 } )


TraderLogicOn

TraderLogicOn( { Ship } ) : {}

Schaltet die Handelslogik eines Frachters (wieder) ein. 'Ship' muss ein Frachter sein (nicht Piratenfrachter!), andernfalls schlägt die Funktion mit einer Fehlermeldung fehl.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs, muss ein Frachter sein

Rückgabetabelle
leer

Beispiel

-- Frachter an die Handelslogik übergeben
NShip.TraderLogicOn( { Ship = V.Trader } )


TriggerDialog

TriggerDialog( { Ship } ) : {}

Aktiviert den Dialog eines Schiffs und startet ihn sofort. Eigene Dialoge können im Event "Dialog" angelegt werden. Der Dialog wird vom betreffenden Schiff initiiert und hat keine Reichweitenbeschränkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs

Rückgabetabelle
leer

Beispiel

{   -- Spieler hat sich dem Schiff genähert und wird angefunkt
    2, 3, "Waypoint", function( V, Data )
    if Data.Waypoint == V.Waypoint then
    NShip.TriggerDialog( { Ship = V.Trader } )
    end
},


UseMissiles

UseMissiles( { Ship, Ammo } ) : {}

Baut einen Raketenwerfer in das Schiff ein, der den angegebenen Munitionstyp verwendet. Muss ein Schiff mit starren Frontwaffen sein. Hat mit der Raketensorte Swarm bei Raptor-Jägern keine Auswirkung, da sie hier sowieso immer verwendet werden. Bei Mortok-Jägern geht diese Funktion gar nicht, da sie nur über Geschütztürme verfügen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des betreffenden Schiffs
Ammo | enum | 7..18 (Munitionssorten ab AMMO_TYPE_SWARM) | Raketentyp

Rückgabetabelle
leer

Beispiel

-- Das Schiff kann mit Raketen feuern, tut es aber manchmal nur beim ersten Anflug
if get( "Logic.StarShips."..ShipId..".race" ) ~= RACE_MORTOK then
    NShip.UseMissiles( { Ship = V.Hunter, Ammo = AMMO_TYPE_HELLFIRE } )
end


PlaySound

PlaySound( { Sound, Volume, Mode } ) : {}

Spielt einen Soundeffekt ab. Wird der Sound mit Mode 0 oder 1 abgespielt, kann er nachträglich abgebrochen werden, wenn in 'Sound' ein leerer String übergeben wird. Es kann immer nur ein Sound mit Mode 0 oder 1 gespielt werden. Sounds ohne Mode können nicht abgebrochen werden, was auch bedeutet, dass Funkmeldungen unterdrückt werden anstatt den Soundeffekt zu überlagern.
Was noch beachtet werden muss, kann im Modding Guide unter Eigene Sounds nachgelesen werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Sound | string | Name einer Klang-Ressource aus der KlangErzeugerDefault.xml | Name der Sound-Ressource
Volume | float | 0.0 ... 10.0 | Lautstärkefaktor
Mode | unsigned int | default = nil | Sound nur einmal abspielen (0) oder Sound ständig wiederholen (1)

Rückgabetabelle
leer

Beispiel

-- Sound einmal abspielen, Unterbrechung zulassen
NSound.PlaySound( { Sound = "FX.UI.DataTransmission", Mode = 0 } )

-- Sound einmal mit maximaler Lautstärke abspielen, keine Unterbrechung zulassen
NSound.PlaySound( { Sound = "FX.UI.DataTransmission", Volume = 10.0 } )

-- Sound ständig wiederholen (loopen)
NSound.PlaySound( { Sound = "FX.UI.DataTransmission", Mode = 1 } )

-- Looped Sound abrechen
NSound.PlaySound( { Sound = "" } )


PlayUserSound

PlayUserSound( { File } ) : {}

Spielt einen Soundeffekt bis zu seinem Ende ab. Dieser Sound hat keinen Mode und kann daher auch nicht abgebrochen werden.
Was noch beachtet werden muss, kann im Modding Guide unter Eigene Sounds nachgelesen werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
File | string | Name einer Klang-Ressource aus der KlangErzeugerDefault.xml | Name der Sound-Ressource

Rückgabetabelle
leer

Beispiel

-- Benutzer-Sound abspielen
NSound.PlayUserSound( { File = "USER.TangerineDream_Hyperborea" } )


SetCustomMusic

SetCustomMusic( { Title, Once } ) : {}

Spielt den angegebenen Musiktitel im Wiederhol-Modus ab. Die Musik hat die höchste Priorität und wird durch nichts unterbrochen (auch keine Jingles). Die Musik kann nur durch einen Aufruf von 'SetDefaultMusic' beendet werden.
Was noch beachtet werden muss, kann im Modding Guide unter Eigene Sounds nachgelesen werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Title | string | Name einer Stream-Resource aus der KlangErzeugerDefault.xml | Titel des Musikstücks
Once | bool | default=false | Musikstück nur einmal abspielen, wenn true

Rückgabetabelle
leer

Beispiel

-- Musik loopen
NSound.SetCustomMusic( { Title = "MUSIC.SpaceBack.42_plain_wormhole" } )


SetDefaultMusic( {} ) : {}

Beendet das Abspielen einer benutzerdefinierten Musik. Die Musik wird ab nun wieder situationsabhängig vom MusicManager ausgewählt.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

-- Musikstück beenden
NSound.SetDefaultMusic({})


SetRoomType

SetRoomType( { Type } ) : {}

Setzt ein Sound-Environment. Wird der Parameter 'Type' nicht angegeben, wird die Standardeinstellung wiederhergestellt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | siehe Typtabelle | Raumklangtyp

Rückgabetabelle
leer

Typtabelle für Parameter Type
Bezeichner | Kommentar | Wert
ENVIRONMENT_GENERIC | Default setting | 0
ENVIRONMENT_PADDEDCELL | Padded cell reverb | 1
ENVIRONMENT_ROOM | Simple room reverb | 2
ENVIRONMENT_BATHROOM | Bathroom reverb | 3
ENVIRONMENT_LIVINGROOM | Living room reverb | 4
ENVIRONMENT_STONEROOM | Stone room reverb | 5
ENVIRONMENT_AUDITORIUM | Auditorium reverb | 6
ENVIRONMENT_CONCERTHALL | Concert hall reverb | 7
ENVIRONMENT_CAVE | Cave reverb | 8
ENVIRONMENT_ARENA | Arena reverb | 9
ENVIRONMENT_HANGAR | Hanger reverb | 10
ENVIRONMENT_CARPETEDHALLWAY | Carpeted hallway reverb | 11
ENVIRONMENT_HALLWAY | Hallway reverb | 12
ENVIRONMENT_STONECORRIDOR | Stone corridor reverb | 13
ENVIRONMENT_ALLEY | Alley reverb | 14
ENVIRONMENT_FOREST | Forest reverb | 15
ENVIRONMENT_CITY | City reverb | 16
ENVIRONMENT_MOUNTAINS | Mountains reverb | 17
ENVIRONMENT_QUARRY | Quarry reverb | 18
ENVIRONMENT_PLAIN | Open plain reverb | 19
ENVIRONMENT_PARKINGLOT | Parking lot reverb | 20
ENVIRONMENT_SEWERPIPE | Sewer pipe reverb | 21
ENVIRONMENT_UNDERWATER | Underwater reverb | 22
ENVIRONMENT_DRUGGED | Drugged reverb | 23
ENVIRONMENT_DIZZY | Dizzy reverb | 24
ENVIRONMENT_PSYCHOTIC | Psychotic reverb | 25

Beispiel

-- Umgebung eines Hangars setzen
NSound.SetRoomType( { Type = ENVIRONMENT_HANGAR } )
NSound.PlaySound( { Sound = "FXFire" } )
...
-- Standardeinstellung wiederherstellen
NSound.SetRoomType({})


EndSiege

EndSiege( { System } ) : {}

Beendet den Zustand von bedrohten Systemen, das System ist also nicht mehr von Piraten besetzt. Das Artefakt wird sofort ins Schiff aufgenommen und die Navigationskarte wird aktualisiert. Falls das System nicht bedroht ist, hat die Funktion keine Auswirkung.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | Id des Systems

Rückgabetabelle
leer

Beispiel

-- Das Ta-System ist nicht länger bedroht
NStarSystem.EndSiege( { System = 19 } )


GetCombineName

GetCombineName( { System } ) : { Name }

Liefert die StringId eines Konzernnamens, der für dieses System gültig ist.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | Id des Systems

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Name | string | StringId aus dem LokaTool | Name eines ansässigen Konzerns

Beispiel

V.Raffgeier = NStarSystem.GetCombineName( { System = 29 } ).Name


GetHandleFromId

GetHandleFromId( { Id } ) : { Handle }

Ermittelt zu einer SystemId das Handle des Systems.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Id | unsigned int | 0..402 | Id des Systems

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | CStarHandle | Handle des Systems

Beispiel

-- Logik-Handle vom System 12 (Patorwalla im Barnard-Cluster)
V.SystemHandle = NStarSystem.GetHandleFromId( { Id = 12 } ).Handle

-- oder so:
V.SystemId = 12
V.SystemHandle = NStarSystem.GetHandleFromId( { Id = V.SystemId } ).Handle

Beispiel 2

Noch eine andere Möglichkeit, um das Handle zu ermitteln, kurz und schnell:

V.SystemHandle = get( "Logic.StarSystems.12.id" )

-- oder so:
V.SystemHandle = get( "Logic.StarSystems."..V.SystemId..".id" )


GetIdFromHandle

GetIdFromHandle( { Handle } ) : { Id }

Liefert die SystemId eines Systems zu einem Handle.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsigned int | CStarHandle | Handle des Systems

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Id | unsigned int | 0..402 | Id des Systems

Beispiel

-- Die Id eines Systems ermitteln
V.SystemId = NStarSystem.GetIdFromHandle( { Handle = V.SystemHandle } ).Id

-- Liefert die SystemId des aktuellen Systems
MissionLib.GetStarSystemId = function()
    return NStarSystem.GetIdFromHandle( { Handle = get( "Logic.PlayerShip.systemId", nil ) } ).Id
end


GetOrbiter

GetOrbiter( { Type, Index, Mode } ) : { Orbiter, Valid }

Sucht einen bestimmten Orbiter im aktuellen System und liefert dessen Handle. 'Valid' gibt an, ob der Orbiter gültig ist. Die Funktion sucht die Orbiter in der Reihenfolge, wie sie in der Planets.ini eingetragen sind.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | unsigned int | Orbitertypen | Der Typ des gesuchten Orbiters
Index | unsigned int | >= 0 | Laufende Nummer des Orbiters, beginnend bei 0
Mode | unsigned int | 0..? | Keine Auswirkung feststellbar

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Orbiter | unsigned int | OrbiterId | Handle des Orbiters
Valid | bool | n/a | ist gesetzt, wenn der Orbiter existiert

Beispiel

-- Handle der zweiten Forschungsstation holen
local station = NStarSystem.GetOrbiter( { Type = OBJTYPE_STATION, Index = 1, Mode = 0 } )

-- falls die Station existiert, in die V-Tabelle eintragen und anwählen
if station.Valid then
    V.ResearchStation2 = station.Orbiter
    NPlayer.SelectTarget( { Object = V.ResearchStation2 } )
end


GetPirateField

GetPirateField( { Object } ) : { Orbiter, Valid }

Liefert das Handle des Orbiters, in dem die Piratengang beheimatet ist. 'Valid' gibt an, ob der 'Orbiter' gültig ist. GetPirateField funktioniert nur für das aktive System.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | COrbiterHandle | Handle der Piratenbasis von MissionLib.GetSystemOrbiter(OBJTYPE_BASESHIP) Ist nicht das CStarShipHandle der Piratenbasis!

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Orbiter | unsigned int | OrbiterId | Meteoritenfeld, in dem die Piratengang beheimatet ist
Valid | bool | n/a | ist gesetzt, wenn das Meteoritenfeld existiert

Beispiel

-- Die Position kann nicht wie sonst ermittelt werden, liefert nur {0,0,0}.
-- Daher zunächst das Handle des Orbiters holen, in dem die Piraten sind.
V.PirateBase = MissionLib.GetSystemOrbiter( OBJTYPE_BASESHIP )
local PirateField = NStarSystem.GetPirateField( { Object = V.PirateBase } )

-- oder so:
local PirateField = NStarSystem.GetPirateField({})

-- falls der Orbiter gültig ist, kann jetzt die Position ausgelesen werden.
if PirateField.Valid then
    V.MeteoridHandle = PirateField.Orbiter
    V.MeteoridCenter = NObject.GetPosition( { Object = V.MeteoridHandle } ).Position
end


GetTradeStation

GetTradeStation( {} ) : { Handle }

Liefert das Handle der Handelsstation, wenn eine im System vorhanden ist.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Handle | unsignet int | CObjectHandle | Handle der Handelsstation, -1 wenn keine existiert

Beispiel

local handle = NStarSystem.GetTradeStation({}).Handle
if handle > 0 then
    V.TradeStation = handle
end


List

List( { Mode } ) : { SystemList }

Je nach dem Wert von 'Mode' werden entweder alle Sternsysteme oder nur die in Reichweite des Hyperraumantriebs gesucht und eine Liste mit den gefundenen Handles zurückgeliefert. Es spielt dabei keine Rolle, ob die Systeme noch unsichtbar oder versteckt sind.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Mode | unsigned int | >= 0 | =0 - alle Systeme in Reichweite des Hyperraumantriebs werden gesucht. >0 - das genaue Kriterium ist noch unklar, manchmal werden alle Systemhandles geliefert, manchmal nur 396 und manchmal nur die Handles der Systeme des aktuellen Clusters und den umliegenden 3 Clustern der Rasse, wo man gerade ist. Die Anzahl ist aber immer höher als im Mode 0.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
SystemList | table[n] : unsigned int | CStarSystemHandle | Handles aller gefundenen Sternsysteme

Beispiel

-- Liste mit allen Sternsystemen in Reichweite erstellen
local systemhandles = NStarSystem.List( { Mode = 0 } ).SystemList
V.SystemIds = {}
for i, system in systemhandles do
    V.SystemIds[i] = NStarSystem.GetIdFromHandle( { Handle = system } ).Id
end


ListOrbiters

ListOrbiters( {} ) : { OrbiterList }

Listet alle Orbiter (Raumstationen, Asteroiden, Planeten, Monde, usw.) des aktuellen Systems auf.
Die Liste enthält die gefundenen Orbiter in der umgekehrten Reihenfolge, wie sie in der Planets.ini eingetragen sind. Das heißt also, der zuletzt in der Planets.ini definierte Orbiter des Systems steht in dieser Liste an erster Stelle.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
OrbiterList | table[n] : unsigned int | CObjectHandle | Liste der Handlewerte aller Orbiter

Beispiel

local Orbiters = NStarSystem.ListOrbiters({}).OrbiterList


RemoveStoryLock

RemoveStoryLock( { System } ) : {}

Entfernt das Storylock eines Systems.
Hinweis: Nur nach dem erfolgreichen Ende einer Barmission verwenden!

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | Id des Systems

Rückgabetabelle
leer

Beispiel

NStarSystem.RemoveStoryLock( { System = 29 } )


SetAsMissionTarget

SetAsMissionTarget( { System, Set, Hidden } ) : {}

Markiert ein System als Missionssystem oder entfernt die Markierung wieder. Das System muss auf der Navigationskarte sichtbar sein. Es darf sich aber auch um ein noch nicht freigeschaltetes oder verstecktes System handeln, der Spieler muss also keinen Systemschlüssel dafür haben. Markierte Systeme erhalten auf der Navigationskarte ein M für Terminalmissionen oder ein Q für Sidequests (Barmissionen), sofern der Parameter 'Hidden' nicht true ist. In den markierten Systemen werden außerdem keine Zufallspiraten oder Zufallsmissionen vom Typ MTYPE_SPACE mehr erzeugt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | SystemId oder Handle des Systems
Set | bool | n/a | Markierung setzen (true|1) oder entfernen (false|0)
Hidden | bool | n/a | Markierung ist auf der Sternenkarte unsichtbar

Rückgabetabelle
leer

Beispiel

-- Sol-System als Missionsziel markieren
NStarSystem.SetAsMissionTarget( { System = 29, Set = true } )

-- dito mit dem Handle des Systems
V.Sol = get( "Logic.StarSystems.29.id" )
NStarSystem.SetAsMissionTarget( { System = V.Sol, Set = true } )


SetAsStoryTarget

SetAsStoryTarget( { System, Set, Hidden } ) : {}

Markiert ein System als Storysystem oder entfernt die Markierung wieder. Das System muss auf der Navigationskarte sichtbar sein. Es darf sich aber auch um ein noch nicht freigeschaltetes oder verstecktes System handeln, der Spieler muss also keinen Systemschlüssel dafür haben. Markierte Systeme erhalten auf der Navigationskarte ein S, sofern der Parameter 'Hidden' nicht true ist. In den markierten Systemen werden außerdem keine Zufallspiraten oder Zufallsmissionen vom Typ MTYPE_SPACE mehr erzeugt.
Nur Missionen vom Typ MTYPE_STORY und MTYPE_STORY_CHAPTER können diese Funktion benutzen, von denen auch immer nur eine aktiv sein sollte. Jedoch dürfen in der Mission mehrere Storyziele gleichzeitig markiert werden.

Wichtig: Funktioniert nur in Storymissionen und hat sowohl in Sidequests als auch Terminalmissionen keine Auswirkung.
Setzt man die Markierung erst im Zielsystem, kann dies frühestens im Event "MissionStart" geschehen, in "Create" funktioniert es noch nicht.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | SystemId oder Handle des Systems
Set | bool | n/a | Markierung setzen (true|1) oder entfernen (false|0)
Hidden | bool | n/a | Markierung ist auf der Sternenkarte unsichtbar

Rückgabetabelle
leer

Beispiel

-- Sol-System als Storysystem markieren
NStarSystem.SetAsStoryTarget( { System = 29, Set = true } )

-- dito mit dem Handle des Systems
V.Sol = get( "Logic.StarSystems.29.id" )
NStarSystem.SetAsStoryTarget( { System = V.Sol, Set = true } )


SetVisible

SetVisible( { System } ) : {}

Deckt ein Sternsystem auf der Navigationskarte auf. Es wird aber noch nicht freigeschaltet, der Spieler erhält also keinen Systemschlüssel dafür.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | SystemId vom aufzudeckenden System

Rückgabetabelle
leer

Beispiel

-- Das Programm deckt ein neues System auf
NStarSystem.SetVisible( { System = 29 } )


Unlock

Unlock( { System } ) : {}

Der Spieler erhält einen Systemschlüssel und bekommt eine Info-Meldung darüber. Das System wird automatisch aufgedeckt und freigeschaltet.

Tipp: Sollen Systeme als Belohnung freigeschaltet werden, so sollte dies besser im Missionsevent Achieved erfolgen, da beim manuellen Freischalten per Unlock die Freischalt-Nachricht vor "Auftrag erfüllt" kommt. Dort kann dann der Parameter 'Keys' dafür verwendet werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | 0..402 | SystemId vom freizuschaltenden System

Rückgabetabelle
leer

Beispiel

-- Spieler erhält einen Systemschlüssel
NStarSystem.Unlock( { System = 29 } )


Progress

Progress( {} ) : { Chapter, Subchapter }

Liefert den Fortschritt der Story anhand des aktuellen Kapitels und Unterkapitels.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Chapter | unsigned int | n/a | Aktuelles Kapitel
Subchapter | unsigned int | n/a | Aktuelles Unterkapitel

Beispiel

-- Mission nur nach dem Prolog erzeugen
if NStory.Progress({}).Chapter > 0 then
    ...
    return 1
end


AddNews

AddNews( { Header, Body, Lifetime } ) : {}

Fügt eine neue Nachricht in die News-Sektion des Terminals ein.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Header | string | StringId aus dem LokaTool | Überschrift
Body | string | StringId aus dem LokaTool | Text des Textkörpers
Lifetime | unsigned int | n/a | Lebensdauer in Tagen

Rückgabetabelle
leer

Beispiel

-- Neuigkeiten über die Thul-Angriffe
NTerminal.AddNews( {
    Header = "IDM_NEWS_THUL_HDR",
    Body = "IDM_NEW_THUL_TEXT",
    Lifetime = 20
} )


Blink

Blink( { Type } ) : {}

Diese Funktion gibt es nicht, da der Namespace NTutorial gar nicht existiert!

Die Beschreibung bleibt aber mal vorläufig noch hier drin.

Läßt ein Interface-Element blinken.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | BLINK_BTN_NAVMAP, BLINK_BTN_TARGETMAP, BLINK_BTN_COMMUNICATION, BLINK_BTN_LOGBUCH, BLINK_BTN_SHIP, BLINK_BTN_SPELLWEAPON, BLINK_BTN_ROCKETS, BLINK_BTN_OPTIONS | Anzeigeelement, das blinken soll

Rückgabetabelle
leer

Beispiel

-- Den Raketenbutton blinken lassen
NTutorial.Blink( { Type = BLINK_BTN_ROCKETS } )


ShowPopup

ShowPopup( { Text, Width, Height } ) : { Popup }

Diese Funktion gibt es nicht, da der Namespace NTutorial gar nicht existiert!

Die Beschreibung bleibt aber mal vorläufig noch hier drin.

Zeigt ein Popup mit Text an und hält die Simulation an. Das Popup muss vom Spieler bestätigt werden. Das Schließen des Popups erzeugt ein 'TutorialPopup'-Event für die Mission. Falls 'Width' oder 'Height' angegeben wird, muss der jeweils andere Parameter ebenfalls definiert werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Text | string | StringId aus der user_strings.res | Anzuzeigender Text
Width | unsigned int | n/a | Breite des Popups in Pixeln
Height | unsigned int | n/a | Höhe des Popups in Pixeln

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Popup | unsigned int | n/a | Id des Popups (kann im Event 'TutorialPopup' verwendet werden)

Beispiel

V.Popup = NTutorial.ShowPopup( { Text = "IDM_GLOBAL_5000_POPUP" } ).Popup


Add

Add( { Vector1, Vector2 } ) : { Vector }

Addiert die beiden Vektoren.

Diese Funktion ist zwar nicht besonders schnell in der Ausführung, kann aber dennoch für einzelne Aufrufe oder Schleifen mit relativ wenigen Durchläufen verwendet werden. Programmiert man jedoch for-, while- oder repeat-Schleifen mit insgesamt tausenden von Zyklen, sollte man besser den unten beim Hinweis stehenden Code verwenden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Vector1 | table[3] : float | n/a | Erster Vektor
Vector2 | table[3] : float | n/a | Zweiter Vektor

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Vector | table[3] : float | n/a | Vector = Vector1 + Vector2

Beispiel

V.NewPos = NVector.Add( { Vector1 = V.WingPos, Vector2 = V.NextPos } ).Vector

NWing.AddAction( {
    Wing = V.Wing,
    List = LIST_ACTIVE,
    First = true,
    Actions = { { Type = AI_ACTION_POSITION1, Position = V.NewPos } }
} )
NWing.ExecuteAi( { Wing = V.Wing } )

Hinweis:
Einfache Messungen haben ergeben, dass diese Funktion nicht gerade schnell ist. Eine wesentlich bessere Laufzeit mit ca. 5- bis 8-fach höherer Geschwindigkeit kann mit dem folgenden etwas längeren Code direkt im Skript erreicht werden, das Ergebnis ist damit dasselbe:

V.NewPos = {
    VectorA[1] + VectorB[1]
    VectorA[2] + VectorB[2]
    VectorA[3] + VectorB[3]
}
Selbst wenn die Variablen vor der Ausführung auf Fehler überprüft werden, ist die Geschwindigkeit immer noch mehr als doppelt so hoch:
if ( lua.type( V.WingPos ) == "table" ) and ( lua.type( V.NextPos ) == "table" )
and ( lua.sizeof( V.WingPos ) == 3 ) and ( lua.sizeof( V.NextPos ) == 3 ) then
    V.NewPos = {
        VectorA[1] + VectorB[1]
        VectorA[2] + VectorB[2]
        VectorA[3] + VectorB[3]
    }
end
Wer aber nun denkt: "Toll, bau ich mir als Funktion in die MissionLib.lua ein", ist leider auf dem Holzweg. Durch die Parameterübergabe (nicht nur) beim Funktionsaufruf geht noch weitere Zeit verloren, sodass die Version ohne Fehlerüberprüfung weiter oben nur noch doppelt anstatt ca. achtmal so schnell ist, während der Geschwindigkeitszuwachs bei der mit Fehlerprüfung kaum noch eine Rolle spielt.


GetPos

GetPos( { Area } ) : { Pos }

Liefert eine Position in dem angegebenen Erzeugungsbereich. Kann keine Position gefunden werden, da das entsprechende Objekt fehlt, z.B. ein Asteroid, wird {0,0,0} geliefert.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Area | unsigned int | Erzeugungsbereich | nur Erzeugungsbereiche ohne Parameter

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Pos | table[3] : float | n/a | absolute Raumkoordinate in dem angegebenen Erzeugungsbereich

Beispiel

-- eine Position hinter der Handelsstation berechnen
V.Pos = NVector.GetPos( { Area = POSDESCR_TRADESTATION1 } ).Pos


SetMag

SetMag( { Vector, Mag } ) : { Vector }

Setzt die Länge eines Vektors. Ist 'Mag' nicht angegeben oder gleich 1, wird der Vektor normalisiert (Länge 1). In diesem Fall ist der Vektor derselbe, wie er von den Rückgabewerten 'Front' der GetAlignment-Funktionen geliefert wird.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Vector | table[3] : float | n/a | Vektor
Mag | float | 0.0 < Mag | Länge des Vektors in 1/1000 Units

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Vector | table[3] : float | n/a | Skalierte Version von 'Vector'

Beispiel

local area = NVector.GetPos( { Area = POSDESCR_WELCOME } ).Pos
local normalize = NVector.SetMag( { Vector = area } ).Vector
local dist_1000 = NVector.SetMag( { Vector = area, Mag = 1000.0 } ).Vector


Sub

Sub( { Vector1, Vector2 } ) : { Vector }

Zieht Vektor2 von Vektor1 ab.

Diese Funktion ist zwar nicht besonders schnell in der Ausführung, kann aber dennoch für einzelne Aufrufe oder Schleifen mit relativ wenigen Durchläufen verwendet werden. Programmiert man jedoch for-, while- oder repeat-Schleifen mit insgesamt tausenden von Zyklen, sollte man besser den unten beim Hinweis stehenden Code verwenden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Vector1 | table[3] : float | n/a | Erster Vektor
Vector2 | table[3] : float | n/a | Zweiter Vektor

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Vector | table[3] : float | n/a | Vector = Vector1 - Vector2

Beispiel

-- Vektorlänge zwischen zwei Raumkoordinaten berechnen, Vec1|Vec2 = { x, y, z }
MissionLib.GetVectorDistance = function( Vec1, Vec2 )
    if ( Vec1 ~= nil ) and ( Vec2 ~= nil )  -- <- kann man sich sparen, wird durch "lua.type" erledigt
    and ( lua.type( Vec1 ) == "table" ) and ( lua.type( Vec2 ) == "table" )
    and ( lua.sizeof( Vec1 ) == 3 ) and ( lua.sizeof( Vec2 ) == 3 ) then
    local vec = NVector.Sub( { Vector1 = Vec1, Vector2 = Vec2 } ).Vector
    return math.sqrt( vec[1]*vec[1] + vec[2]*vec[2] + vec[3]*vec[3] )
    end
end

-- Entfernung zwischen zwei Raumkoordinaten in Units/1000
V.Distance = MissionLib.GetVectorDistance( Vector1, Vector2 )

Hinweis:
Einfache Messungen haben ergeben, dass diese Funktion nicht gerade schnell ist. Sie ist sogar noch ein wenig langsamer als NVector.Add. Eine wesentlich bessere Laufzeit mit ca. 7- bis 10-fach höherer Geschwindigkeit kann mit dem folgenden etwas längeren Code direkt im Skript erreicht werden, das Ergebnis ist damit dasselbe:

local vec = {
    vec1[1] - vec2[1]
    vec1[2] - vec2[2]
    vec1[3] - vec2[3]
}
Selbst wenn die Variablen vor der Ausführung auf Fehler überprüft werden, ist die Geschwindigkeit immer noch mehr als doppelt so hoch:
local vec = {}
if ( lua.type( vec1 ) == "table" ) and ( lua.type( vec2 ) == "table" )
and ( lua.sizeof( vec1 ) == 3 ) and ( lua.sizeof( vec2 ) == 3 ) then
    vec[1] = vec1[1] - vec2[1]
    vec[2] = vec1[2] - vec2[2]
    vec[3] = vec1[3] - vec2[3]
end
Wer aber nun denkt: "Toll, bau ich mir als Funktion in die MissionLib.lua ein", ist leider auf dem Holzweg. Durch die Parameterübergabe (nicht nur) beim Funktionsaufruf geht noch weitere Zeit verloren, sodass die Version ohne Fehlerüberprüfung weiter oben nur noch doppelt anstatt ca. achtmal so schnell ist, während der Geschwindigkeitszuwachs bei der mit Fehlerprüfung kaum noch eine Rolle spielt.


Create

Create( { Object|Position, Radius, Visible, Wing } ) : { Waypoint }

Erzeugt einen Wegpunkt an der durch 'Position' angegebenen Raumkoordinate oder an dem Objekt 'Object'. Wegpunkte, die mit einem Objekt erzeugt werden, bewegen sich mit diesem Objekt mit. Der Wegpunkt sendet ein 'Waypoint'-Event an die Mission, wenn der Spieler in die Kugel mit dem Radius 'Radius' um den Wegpunkt fliegt. Wurde ein Wing-Handle übergeben, triggert der Wegpunkt nur für diesen Wing, nicht jedoch für den Spieler. Sobald der Wing zerstört wurde, ist auch der Wegpunkt weg. Wegpunkte sind standardmäßig nicht sichtbar.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert eines Objekts, an das der Wegpunkt gebunden werden soll.
Position | table[3] : float | n/a | Position, an der der Wegpunkt erzeugt werden soll.
Radius | float | 0.0f < Radius | Triggerradius für den Wegpunkt.
Visible | bool | default=false | Wegpunkt ist sichtbar (true) oder unsichtbar (false)
Wing | unsigned int | CWingHandle | WingHandle. Für alle Schiffe in diesem Wing wird der Wegpunkt ausgelöst. Wurde kein Wing angegeben, triggert der Wegpunkt nur für den Spieler.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Waypoint | unsigned int | CWaypointHandle | Handle des erzeugten Wegpunkts

Beispiel

-- Wegpunkt an den Frachter binden
V.WP = NWaypoint.Create( { Object = V.Trader, Radius = 300 } ).Waypoint

-- Wegpunkt im Raum erzeugen und anwählbar machen
V.WP = NWaypoint.Create( { Position = {900,0,0}, Radius = 2000, Visible = true } ).Waypoint

-- Wegpunkt wird von allen Schiffen des HunterWings ausgelöst, wenn sie in Spielernähe kommen
V.WP = NWaypoint.Create( { Object = V.Player, Radius = 1200, Wing = V.HunterWing } ).Waypoint


Show

Show( { Waypoint, Show } ) : {}

Zeigt einen Wegpunkt an oder versteckt ihn. Sichtbare Wegpunkte können über den Zielcomputer selektiert werden.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Waypoint | unsigned int | CWaypointHandle | Handle des Wegpunkts
Show | bool | n/a | Zeigen (true) oder verstecken (false)

Rückgabetabelle
leer

Beispiel

-- Waypoint erzeugen und anzeigen
V.WP = NWaypoint.Create( { Position = { 2000, 0, 0 }, Radius = 200 } ).Waypoint
NWaypoint.Show( { Waypoint = V.WP, Show = true } )


AddAction

AddAction( { Wing, List, First, Actions } ) : {}

Diese Funktion trägt eine Aktionsliste in einen Wing ein oder ergänzt eine im Wing vorhandene Aktionsliste mit weiteren Befehlen.
Siehe auch den Menüpunkt \Tabellen\Wings.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Wing, der die Aktionsliste erhält
List | unsigned int | LIST_ACTIVE .. LIST_PLAYER | Bezeichner für die Aktionsliste
First | unsigned int oder bool | n/a | Ist der Parameter true oder >= 1, werden die alten Einträge der Liste gelöscht. Ist er nil, 0 oder false, werden die neuen Einträge angehängt.
Actions | table[n] : Action | n/a | Tabelle mit den Aktionen

Rückgabetabelle
leer

Parametertabelle für List
Die Aktionslisten, die bei besonderen Situationen aktiviert werden
Wert | Kommentar
LIST_ACTIVE | Liste, die zur Zeit abgearbeitet wird
LIST_SHIELD | Wird aktiviert, wenn ein Schiff seinen Schild verloren hat
LIST_FIRST_SHIP | Wird aktiviert, wenn das erste Schiff des Wings zerstört wurde
LIST_HALF | Wird aktiviert, wenn die Hälfte der Schiffe des Wings zerstört wurden
LIST_LAST_SHIP | Wird aktiviert, wenn der Wing nur noch ein Schiff hat
LIST_NO_ENEMY | Wird aktiviert, wenn der Wing keinen Gegner mehr hat
LIST_PLAYER | Wird aktiviert, wenn der Wing ein Gegner des Spielers wird

Parametertabelle für Actions
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | unsigned int | AI_ACTION_INAKTIV .. AI_ACTION_SKAA_ACTIONTURRET | Typbezeichnung der Action
Speed | float | 0.0f .. 5.0f | Geschwindigkeit in Meter pro Zeitschritt, mit der sich der Wing bewegen soll (1.0 = 25%, 4.0 = 100%)
Handle | unsigned int | CHandle | Value eines Handles (abhängig von 'Type')
Position | table[3] : float | n/a | Absolute Koordinate

Liste der möglichen Aktionen des Wings ('Type' der Actions)
Wert | Parameter | Kommentar
AI_ACTION_INAKTIV
AI_ACTION_INACTIVE
 ohne Der Wing ist völlig regungslos und reagiert auch nicht auf Angriffe.
AI_ACTION_STATISCH
AI_ACTION_STATIC
 ohne Der Wing ist regungslos, führt aber eine Gegnerliste und feuert auf Gegner in Schussweite.
AI_ACTION_WARTEN
AI_ACTION_WAIT
 ohne Der Wing ist regungslos, bis seine Gegnerliste einen Eintrag erhält.
AI_ACTION_ANGRIFF
AI_ACTION_ATTACK
 Ist Handle ein Schiff oder Wing, wird es in die Gegnerliste eingetragen. Der Wing greift alle Gegner seiner Gegnerliste an.
AI_ACTION_CONTANGRIFF
AI_ACTION_CONTATTACK
 Ist Handle ein Schiff oder Wing, wird es in die Gegnerliste eingetragen. Wie AI_ACTION_ANGRIFF, jedoch sucht sich der Wing automatisch einen neuen Gegnerwing aus der Gruppen-KI.
AI_ACTION_POSITION1
Speed wird beachtet.
Position enthält die absolute Position.
Der Wing wird zu einer neuen absoluten Position geschickt. Gegner werden mit Türmen beschossen, die Schiffe ändern aber nicht ihren Kurs.
AI_ACTION_POSITION2
Speed wird beachtet.
Position enthält die absolute Position.
Der Wing wird zu einer neuen absoluten Position geschickt. Gegner werden angegriffen, wobei der Anflug auf die Position unterbrochen wird.
AI_ACTION_OBJECT1
Position und Speed werden beachtet. Handle ist ein SpaceObject.
Der Wing wird zu einem SpaceObject geschickt. Gegner werden nicht angegriffen. Position ist ein Richtungsvektor relativ zum Objekt.
AI_ACTION_OBJECT2
Position und Speed werden beachtet. Handle ist ein SpaceObject.
Der Wing wird zu einem SpaceObject geschickt. Gegner werden angegriffen. Position ist ein Richtungsvektor relativ zum Objekt.
AI_ACTION_LANDEN
AI_ACTION_LAND
Speed wird beachtet.
Handle ist ein SpaceObject mit Hangar.
Der Wing landet auf dem angegebenen Objekt, wenn keine Gegner in der Nähe sind. Ist das letzte Schiff gelandet, wird der Wing danach gelöscht und es wird ein WING_DESTROYED Event ausgelöst. Es wird jedoch kein "StarshipDestroyed" für die einzelnen Schiffe getriggert. Sollen KI-Schiffe auf einem Kreuzer landen, muss dieser stillstehen, sonst werden die Jäger wieder vor den Hangar gesetzt.
Frachter fliegen eine Position etwa 0,6u vor dem Hangar der Handelsstation an (~1,24u vor dem Systemzentrum) oder ca. 0.9u vor einer Forschungsstation und parken dort. Begleitende Geleitschutzjäger landen beim Erreichen der Position.
AI_ACTION_SOFORTLANDEN
AI_ACTION_LANDNOW
Speed wird beachtet.
Handle ist ein SpaceObject mit Hangar.
Wie AI_ACTION_LANDEN, Gegner werden jedoch nicht angegriffen.
AI_ACTION_KREISEN
AI_ACTION_CIRCLE
 Position und Speed werden beachtet. Wie AI_ACTION_WARTEN, jedoch kreist der Wing um die aktuelle oder die angegebene Position in einem Standardabstand. Bekommt der Wing Gegner, wird das Kreisen beendet.
AI_ACTION_PATROUILLE
AI_ACTION_PATROL
Speed wird beachtet.
Position enthält die absolute Position.
Hier können bis zu 4 Positionsangaben und mehr folgen. Der Wing fliegt von einer Position zur nächsten und beginnt nach der letzten wieder von vorne.
AI_ACTION_BESCHUETZEN
AI_ACTION_PROTECT
Handle ist ein Wing,
Position wird beachtet.
Der Wing soll einen anderen Wing beschützen. Er folgt diesem in einem Standard-Abstand. Position ist ein Richtungsvektor relativ zum Leader des Wings. Funktioniert mit Militär- und Kreuzer-Wings nur sehr eingeschränkt.
AI_ACTION_BEWACHEN
AI_ACTION_GUARD
 Handle ist ein Container. Der Wing soll einen Container bewachen.
AI_ACTION_BERGEN
AI_ACTION_PICKUP
 Handle ist ein Container. Der Wing soll einen Container bergen.
AI_ACTION_ABWERFEN
AI_ACTION_DROP
 Handle ist ein Container. Bezeichnet das Handle einen Container, wird nur dieser abgeworfen. Sonst werfen alle Schiffe des Wings alle ihre Container ab.
AI_ACTION_HYPERRAUM
AI_ACTION_HYPERJUMP
 Handle muss ein CStarHandle enthalten, wenn der Wing der Spielerwing ist. Der Wing springt in den Hyperraum, wenn keine Gegner in der Nähe sind. Ist der Spieler im Wing, springt dieser zusammen mit dem Wing in das angegebene System (inklusive Kamera). Ein Missions-Wing, der nur aus KI-Schiffen besteht, wird beim Verlassen des Systems gelöscht und es wird ein WING_DESTROYED Event ausgelöst.
AI_ACTION_SOFORTSPRUNG
AI_ACTION_HYPERJUMPNOW
 Handle muss ein CStarHandle enthalten, wenn der Wing der Spielerwing ist. Wie AI_ACTION_HYPERRAUM, Gegner werden jedoch nicht angegriffen.
AI_ACTION_BOSSKREISEN
AI_ACTION_BOSSCIRCLE
 Position und Speed werden beachtet. Der Wing fliegt zur angegebenen Position und umkreist sie dann. Speed wird als Radius interpretiert. Fehlt Speed, kreist der Wing in einem Standardabstand. Ohne Positionsangabe fliegt er in Richtung Systemzentrum und umkreist dann dieses. Die Bahnneigung relativ zur X/Z-Ebene des Systems ist von der Ausgangsposition des Wings abhängig. Der Status endet nicht, wenn Gegner eingetragen werden.
AI_ACTION_EINTRITT
AI_ACTION_ENTRY
 Handle ist ein Schiff oder Wing. Der Wing kämpft gegen Gegner in seiner Nähe. Ist der angegebene Wing bzw. das Schiff im System angekommen, wird eine neue Aktion gestartet.
AI_ACTION_ESKORTE
AI_ACTION_ESCORT
 Position und Speed werden beachtet. Der Wing fliegt zu einer Position. Kleine Schiffe (auch als Leader) dürfen die Formation verlassen, um Gegner anzugreifen.
AI_ACTION_FOLGESCHIFF
AI_ACTION_FOLLOWSHIP
Handle ist ein Schiff,
Position wird beachtet.
Handle bezeichnet ein Schiff eines anderen Wings, dem gefolgt werden soll. Position bestimmt die Richtung vom Wing zum Leader des zu folgenden Wings.
AI_ACTION_POSANGRIFF
AI_ACTION_POSATTACK
 Position wird beachtet. Die gegebene 3D-Position wird angeflogen und beschossen.
AI_ACTION_ACTIONTURRET | Das Handle wird in die Gegnerliste eingetragen. | Der ActionTurret wird angegriffen.
AI_ACTION_DESTROYOBJ | Handle ist ein statisches SpaceObject. | Der Wing stellt sich vor das Objekt und beschießt es mit seinen Frontwaffen.
AI_ACTION_GETLIST | ohne | Eine neue Aktion aus der Aktionsliste soll gestartet werden, funktioniert jedoch nicht für bereits aktive Listen. Kann aber für vorbereitete Listen zum Löschen eines Eintrags verwendet werden, da mit nil die nächste Aktion sonst nicht gestartet wird.
AI_ACTION_STANDARD
Speed wird beachtet.
Das Verhalten ist abhängig vom Wing.
Die Standard-KI des Wings wird gestartet.
AI_ACTION_POLICESCAN | Speed und Zielposition werden beachtet. | Der Wing fliegt zur Position. Das Spielerschiff wird gescannt, wenn es in die Nähe kommt. Bei Position { 0, 0, 0 } probiert der Wing einen Scan an der aktuellen Position, wenn der Spieler nicht in Reichweite ist, ignorieren sie die Aktion. Dieser Befehl funktioniert nur mit Wings, die als WINGTYPE_POLICE erzeugt wurden!
AI_ACTION_SKAA_ATTACK | Handle ist ein Schiff. | Der S'kaa-Wing greift das Schiff an. Dieser Befehl funktioniert nur mit Wings, die als WINGTYPE_SKAA erzeugt wurden!
AI_ACTION_SKAA_ACTIONTURRET | ohne | Ist der CActionTurret aktiv, wird dessen Zielschiff angegriffen. Andere Ziele werden nicht beachtet. Dieser Befehl funktioniert nur mit Wings, die als WINGTYPE_SKAA erzeugt wurden!

Hinweise und Tipps zu den Aktionen
Aktion | Kommentar
AI_ACTION_HYPERRAUM AI_ACTION_SOFORTSPRUNG | Ist der Spieler in einem KI-Wing, kann er zusammen mit dem Wing nicht nur in ein anderes, sondern sogar ins aktuelle System springen. Das kann in Missionen ausgenutzt werden, wo der Spieler besonders weit zu einem Missionsziel innerhalb des aktuellen Systems versetzt wird. Ein Sprung ins eigene System befördert ihn somit wieder zum Hyperraumtor in der Nähe des Zentrums. Ohne KI-Wing geht das nicht, da das gegenwärtige System nicht in der Navigationskarte angewählt werden kann.

Beispiel

-- Wing soll sofort zu der angegebenen Position fliegen und dort langsam kreisen
NWing.AddAction( {
    Wing = V.WingId,
    List = LIST_ACTIVE,
    First = 1,
    Actions = {
    { Type = AI_ACTION_POSITION1, Speed = 1.2, Position = {2039, 5095, -5393} },
    { Type = AI_ACTION_KREISEN, Speed = 1.2 }
    }
} )

-- Wenn der Wing nur noch ein Schiff hat, Container abwerfen und in den Hyperraum springen
NWing.AddAction( {
    Wing = V.WingId,
    List = LIST_LAST_SHIP,
    First = true,
    Actions = {
    { Type = AI_ACTION_ABWERFEN },
    { Type = AI_ACTION_HYPERRAUM, Handle = V.SystemId }
    }
} )


AddEnemy

AddEnemy( { Wing, Target, Priority } ) : {}

In die Gegnerliste vom Wing werden neue Gegner eingetragen. Target kann ein Wing- oder StarShip-Handle sein. Wenn ein Wing angegeben wird, werden alle Schiffe des Wings mit 'Priority' in die Gegnerliste eingetragen. Wird ein Schiff angegeben, wird nur das Schiff mit 'Priority' in die Gegnerliste eingetragen. Ist das Schiff in einem Wing, werden die anderen Schiffe des Wings mit der Standardpriorität 0.2f als Gegner eingetragen. Die Priorität regelt die Zuteilung der Schiffe des Wings zu den Gegnern. Bei dem Start der Gegnerzuweisung wird jedem Schiff in der Gegnerliste die Priorität als aktueller Wert zugewiesen, bei allen Wing-Schiffen werden die Gegner gelöscht. Solange ein Wing-Schiff keinen Gegner hat, wird das Gegnerschiff mit dem kleinsten aktuellen Wert einem der Wing-Schiffe ohne Gegner als Gegner zugewiesen. Der aktuelle Wert des Gegnerschiffes wird dann um die Priorität des Gegnerschiffes erhöht.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Wing, der einen neuen Gegner bekommt
Target | unsigned int | CWingHandle oder CStarShipHandle | der neue Gegner kann ein Wing oder ein StarShip sein
Priority | float | > 0.0f | Gewichtung des neuen Gegners. Je kleiner der Wert, desto höher die Priorität.

Rückgabetabelle
leer

Beispiel

-- Startposition festlegen
V.StartPos = NVector.GetPos( { Area = POSDESCR_OFFSET } ).Pos

-- Piraten-Wing erzeugen
V.PiratenWing = NWing.Create( {
    WingType = WINGTYPE_PIRATES,
    Number = 5,
    LevelOffset = 2,
    PosType = POSDESCR_EXPLICIT,
    Position = { V.StartPos[1], V.StartPos[2], V.StartPos[3] - 1000 }
} ).Wing

-- Frachter-Wing erzeugen
V.FrachterWing = NWing.Create( {
    WingType = WINGTYPE_FREIGHTER50T,
    Number = 3,
    LevelOffset = 1,
    PosType = POSDESCR_EXPLICIT,
    Position = V.StartPos
} ).Wing
V.Frachter = MissionLib.GetWingLeader( V.FrachterWing )

-- Nur den Frachter ohne seine Eskorte in die Gegnerliste der Piraten eintragen
NWing.AddEnemy( { Wing = V.PiratenWing, Target = V.Frachter } )

-- Piraten in die Gegnerliste des Frachterwings eintragen
NWing.AddEnemy( { Wing = V.FrachterWing, Target = V.PiratenWing } )


Create

Create( { WingType, Number, Level | LevelOffset, Names, Race, PosType, Position | Object & Distance, FrontDir, UpDir } ) : { Wing, Position }

Erzeugt einen Wing und liefert dessen Handle.

Besonderheiten einiger Wingtypen:

  • WINGTYPE_FREIGHTERxxx und WINGTYPE_PIRATEFREIGHTERxxx
    • Bei Handelsfrachtern kann je nach 'WingType' lediglich bestimmt werden, ob der Frachter entweder nur Container einer bestimmten Größe transportiert (je nach Rasse wählt das Programm dann den Schiffstyp für die Anzahl der Container zufällig aus), oder ob der Frachter eine feste Gesamtkapazität hat (je nach Rasse sind Schiffstypen für unterschiedliche Containergrößen möglich).
    • Bei Piratenfrachtern kann nur die Containergröße mit dem entsprechenden 'WingType' festgelegt werden. Anzahl der Container und damit die Größe des Frachters wird bei den Terranern und Mortok zufällig bestimmt. Wird ein Wing mit mehr als einem Schiff erzeugt, sind die begleitenden Jäger keine Piraten-, sondern normale Hunterschiffe!
    • Wird in einem Frachterwing der Frachter zerstört und sind noch welche seiner Geleitschutzjäger übrig, dann erhalten diese einen neuen Wing! Diesen Umstand muss man bei der Abfrage des Wing-Handles, z. B. im WING_DESTROYED Event, gegebenenfalls beachten. Die Jäger zählen dann nämlich nicht mehr zum Frachterwing, sondern haben ihren eigenen Wing mit einem anderen gemeinsamen Handle! Dasselbe passiert, wenn der Geleitschutz eines Handlesfrachters diesen beim Containerabwurf oder zur Landung verlässt.
    • Superfrachterwings können mit Create gar nicht gezielt erzeugt werden. Zur gezielten Erzeugung bestimmter Superfrachter muss man NWing.Define verwenden, dann klappt das problemlos.

  • WINGTYPE_PIRATES, WINGTYPE_RAIDERS und WINGTYPE_SKAA
    • Piratenjäger und S'kaaschwärme können zwar auf Kreuzern landen, lassen sich aber nicht in Kreuzerhangars erzeugen und aus ihnen starten.

  • WINGTYPE_POLICE
    • Der Parameter 'Race' hat keine Auswirkung, es werden immer Polizeischiffe der Rasse des aktuellen Systems erzeugt. Sollen Schiffe einer anderen Rasse erzeugt werden, muss man die Funktion NWing.Define verwenden.
    • Polizeiwings können ebenfalls nicht aus Kreuzern starten.

  • WINGTYPE_WEAPONBASE und WINGTYPE_WEAPONBASE2
    • Die Erzeugung von Waffenplattformen ist auch nicht ganz fehlerfrei: Egal, welche Rasse man einsetzt, es werden immer mit Lasern bestückte terranische Plattformen erzeugt. Mit NWing.Define klappt das dagegen auch hier problemlos. Eine Ausnahme sind die runden orangefarbigen Waffenplattformen mit einem Geschützturm, da lassen sich auch mit Define nur die terranischen mit einem Laserturm erzeugen, für alle anderen Rassen wird der schwarze Stern als Waffenträger verwendet.
    • Waffenplattformen wandern nach ihrer Erzeugung sehr langsam von ihrer ursprünglichen Position weg. Falls erforderlich, kann man sie von Zeit zu Zeit mit Hilfe eines Timers und Verwendung einer der Funktionen NShip.SetAlignment, NWing.Place oder NObject.Place wieder auf ihre ursprüngliche Position setzen.
    • Ausrichtung: Die standardmäßige Front-Ausrichtung der Waffenplattformen mit einem Geschützturm liegt bei den sternförmigen auf der vom Geschützturm abgewandten Seite, bei den runden orangefarbigen zeigt die Mündung der Waffe in die Front-Richtung.

NWing.Define ist vielleicht nicht ganz so komfortabel, da die korrekten StarShip-Modelle erst in der Datei "StarShip.ini" gesucht und bei Frachterwings alle eventuell gewünschten Begleitschutzjäger einzeln definiert werden müssen (geht aber auch, indem man einen separaten Wing erzeugt und dessen Schiffe dann mit NShip.JoinWing dem Frachterwing beitreten lässt), aber nur so lassen sich die Einschränkungen von NWing.Create umgehen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
WingType | unsigned int | Wingtypen | Art des zu erzeugenden Wings
Number | unsigned int | 0 .. 11 | Anzahl der Schiffe im Wing, 0 erzeugt einen Standardwing mit 4 Schiffen und negative Werte einen Wing mit der maximalen Größe von 11 Schiffen.
Level | unsigned int | 0 .. 30 | die Gegnerstufe wird direkt vorgegeben.
LevelOffset | int | -30 .. 30 | Gegnerstufe wird berechnet als Spielerstufe + relStufe. Wird nur verwendet, wenn Level nicht eingetragen ist.
Names | table[n] : string | n/a | Ein Feld von String-Ids. Schiff i erhält den Namensindex i+1. Wenn es diesen nicht gibt, erhält es den letzten Namen.
Race | int | Rassen | ohne Angabe oder mit RACE_RANDOM oder -1 wird die automatische Rassenverteilung des Clusters verwendet.
PosType | unsigned int | Erzeugungsbereich | Konstante, die den Erzeugungsbereich festlegt.
Position | table[3] : float | n/a | eine absolute Konstante im Weltraum, die tatsächliche Position kann bei Schiffen je nach deren Größe bis zu 0,15u abweichen.
FrontDir | table[3] : float | n/a | die Ausrichtung der Z-Achse (Ebene), eine absolute Konstante im Weltraum.
UpDir | table[3] : float | n/a | die Ausrichtung der Y-Achse (Höhe), eine absolute Konstante im Weltraum.
Object | unsigned int | CHandle | Handle des Objekts bei POSDESCR_HANGAR und POSDESCR_WINGDISTANCE.
Distance | float | n/a | Abstand zu einem gegebenen Wing.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handlewert des erzeugten Wings
Position | table[3] : float | n/a | die relative Position, an der der Leader erzeugt wurde. Ist meistens 0/0/0.

Beispiel

-- ein Standard-Kopfgeldjägerwing wird im Abfangbereich erzeugt
V.Hunter = NWing.Create( {
    WingType = WINGTYPE_HUNTER,
    Number   = 0,
    Level    = 3,
    Race     = RACE_MORLOK,
    PosType  = POSDESCR_INTERCEPTION
} ).Wing

-- ein Piratenfrachter wird an einer festen Position erzeugt
V.PirateFreighter = NWing.Create( {
    WingType  = WINGTYPE_PIRATEFREIGHTER,
    Number    = 1,
    PosType   = POSDESCR_EXPLICIT,
    Position  = {250.0, -4000.0, 8000.0}
} ).Wing

-- ein Piratenwing wird 1.5 Units neben dem Frachterwing erzeugt
V.Pirate = NWing.Create( {
    WingType = WINGTYPE_RAIDERS,
    Number   = 4,
    PosType  = POSDESCR_WINGDISTANCE,
    Object   = V.FreighterWing,
    Distance = 1500
} ).Wing

-- eine Piratenbasis einer zufälligen Rasse und mit einem großen Piratenfrachter,
-- ebenfalls von einer zufälligen Rasse, auf dem Landefeld. Direkt vor der Haustür!
-- Der Frachter ist hier exakt auf dem Landefeld der Piratenbasis ausgerichtet.
V.PirateBase = NWing.Create( {
    WingType = WINGTYPE_BASESHIP,
    Number   = 1,
    Race     = MissionLib.RandomInteger( RACE_HUMAN, RACE_THUL ),
    PosType  = POSDESCR_EXPLICIT,
    Position = { 0, 100, 2000 },
    FrontDir = { 0, 100, 0 },
    UpDir    = { 0, 100, 0 }
} ).Wing

V.PirateSupply = NWing.Create( {
    WingType = WINGTYPE_PIRATEFREIGHTER200T,
    Number   = 1,
    Race     = MissionLib.RandomInteger( RACE_HUMAN, RACE_THUL ),
    PosType  = POSDESCR_EXPLICIT,
    Position = { -54, 118, 1970 },
    FrontDir = { 0, 100, 0 },
    UpDir    = { 0, 100, 0 }
} ).Wing
V.Leader = MissionLib.GetWingLeader( V.PirateSupply )	    -- ↓ Was denn sonst?! ☺
V.Container = NShip.EquipContainer( { Ship = V.Leader, Goods = GOODS_DRUGS } ).Container

-- ein "kleiner"* S'kaa-Kreuzer betritt das System durch ein Hyperraumfenster und bremst ab.
-- *Standardmäßig ist WINGTYPE_CRUISER1 für S'kaa-Kreuzer in der StarShip.ini nicht definiert.
-- Tipp: S'kaa-Kreuzer sollten immer recht weit weg von anderen Objekten erzeugt werden,
-- diese Schiffsmonster sind mit einer Größe von rund 4000 (4 Units) größer als jeder Mond!
V.Skaa = NWing.Create( {
    WingType = WINGTYPE_CRUISER2,
    Race     = RACE_SKAA,
    Number   = 1,
    PosType  = POSDESCR_CRUISER_ENTRY,
    Position = { -3000, -1000, 10000 }
} ).Wing
MissionLib.SetWingName( V.Skaa, "RANDOM" )


Define

Define( { WingType, Ships, Names, PosType, Position | Object & Distance, FrontDir, UpDir } ) : { Wing, Position }

Erzeugt einen Wing und liefert dessen Handle.
Einige der Besonderheiten, die in NWing.Create beschrieben sind, treffen auch hier zu.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
WingType | unsigned int | Wingtypen | Art des zu erzeugenden Wings. Wenn angegeben, hat der Wing die Standard-KI.
Ships | table[n] : ShipDef | n/a | Beschreibung der einzelnen Schiffe. Das zuerst in der Liste definierte Schiff ist immer Wingleader.
Names | table[n] : string | n/a | Ein Feld von StringIds. Schiff i erhält den Namensindex i+1. Wenn es diesen nicht gibt, erhält es den letzten Namen.
PosType | unsigned int | Erzeugungsbereich | Konstante, die den Erzeugungsbereich festlegt.
Position | table[3] : float | n/a | eine absolute Konstante im Weltraum, die tatsächliche Position kann bei Schiffen je nach deren Größe bis zu 0,15u abweichen.
FrontDir | table[3] : float | n/a | die Ausrichtung der Z-Achse (Ebene), eine absolute Konstante im Weltraum.
UpDir | table[3] : float | n/a | die Ausrichtung der Y-Achse (Höhe), eine absolute Konstante im Weltraum.
Object | unsigned int | CHandle | Handle des Objekts bei POSDESCR_HANGAR und POSDESCR_WINGDISTANCE.
Distance | float | n/a | Abstand zu einem gegebenen Wing.

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handlewert des erzeugten Wings.
Position | table[3] : float | n/a | die relative Position, an der der Leader erzeugt wurde. Ist meistens 0/0/0.

Parametertabelle für ShipDef
Feldbezeichner | Datentyp | Wertebereich | Kommentar
ObjType | unsigned int | StarShip-Typen | Art des zu erzeugenden Schiffes
ObjIndex | unsigned int | StarShip-Modelle | Index des Schiffes aus der StarShip.ini
Level | unsigned int | 0 .. 30 | die Gegnerstufe wird direkt vorgegeben.
LevelOffset | int | -30 .. 30 | Gegnerstufe wird berechnet als Spielerstufe + relStufe. Wird nur verwendet, wenn Level nicht eingetragen ist.

Beispiel

-- Ein Kopfgeldjägerwing der Menschen wird im Abfangbereich erzeugt
V.Wing = NWing.Define( {
    WingType = WINGTYPE_HUNTER,
    Ships = {
    { ObjType = ST_WINGMAN, ObjIndex = 0, LevelOffset = 0 },
    { ObjType = ST_WINGMAN, ObjIndex = 1, Level = 4 }
    },
    PosType = POSDESCR_INTERCEPTION
} ).Wing

-- Ein gemischter Missionswing wird an einer gegebenen Position erzeugt.
-- Hier wurde mit WINGTYPE_MILITARY zwar ein falscher Bezeichner verwendet,
-- ist jedoch ein durchaus gültiger Wert, der dem von ST_POLICE entspricht.
V.Wing = NWing.Define( {
    Ships = {
    { ObjType = ST_WINGMAN, ObjIndex = 0, LevelOffset = 4 },    -- Typ 7  Terraner Jäger
    { ObjType = ST_MILITARYFIGHTER, ObjIndex = 1, Level = 2 },  -- Typ 10 Mortok Militärjäger
    { ObjType = WINGTYPE_MILITARY, ObjIndex = 2, Level = 2 },   -- Typ 5  Raptor Polizeijäger
    { ObjType = ST_POLICE, ObjIndex = 4, LevelOffset = 2 },     -- Typ 5  Arrack Polizeijäger
    },
    PosType = POSDESCR_EXPLICIT,
    Position = { 1000.0, 1000.0, 0.0 },
    FrontDir = { -1.0, -1.0, 0.0 }
} ).Wing

-- Ein Ring aus 8 Waffenplattformen mit je 2 Geschütztürmen und zufälliger Rasse
V.Weaponbase = {}
local index = MissionLib.RandomInteger( RACE_HUMAN, RACE_THUL ) * 2 + 1
for i = 1, 8 do
    local angle = math.rad( i * 360 / 8 )
    V.Weaponbase[i] = NWing.Define( {
    Ships    = { { ObjType = ST_WEAPONBASE, ObjIndex = index } },
    PosType  = POSDESCR_EXPLICIT,
    Position = { 200 * math.sin( angle ), 200 * math.cos( angle ) + 100, 2000 },
    FrontDir = { 0, 0, 0 },
    UpDir    = { 0, 0, 0 }
    } ).Wing
end

-- Hier ist jeder Waffenplattformtyp einmal vertreten
V.Weaponbase2 = {}
for i = 0, 11 do
    local angle = i * math.pi / 6
    V.Weaponbase2[i+1] = NWing.Define( {
    Ships    = { { ObjType = ST_WEAPONBASE, ObjIndex = i } },
    PosType  = POSDESCR_EXPLICIT,
    Position = { 200 * math.sin( angle ), 100 + 200 * math.cos( angle ), 2000 },
    } ).Wing
end

Special: Superfrachterwings☺ (mit und ohne Ladung).

Hinweis: Superfrachter können nur für Terraner, Arrack und Raptoren erzeugt werden.
Eine Abfrage der automatisch vom Programm erzeugten Superfrachter mittels "MissionLib.GetObjectType(Data.Target)" im "TargetSelect"-Event liefert immer den StarShip-Typ "23". Leider lassen sich die Frachter nicht mit diesem ST-Typ von 'Define' erzeugen, es muss der Typ "1" (ST_TRADERSHIP) verwendet werden. Möglicherweise ist das auch der Grund dafür, dass sich mit 'NWing.Create' Superfrachter nicht gezielt erzeugen lassen.

-- Frachter für den Transport von Geheimdienstwaffen.
-- Standardmäßig ist nur dieser Typ in der StarShip.ini definiert.
-- ( Wert ContainerSize = 3 ; das entspricht der Konstanten CONTAINER_SPECIAL )
V.Superfrachter = NWing.Define( {
    Ships = {
    { ObjType = ST_TRADERSHIP, ObjIndex = 24 },	-- Terraner Superfrachter 9000t
    { ObjType = ST_TRADERSHIP, ObjIndex = 25 },	-- Arrack Superfrachter 8400t
    { ObjType = ST_TRADERSHIP, ObjIndex = 26 }	-- Raptor Superfrachter 8000t
    },
    PosType = POSDESCR_EXPLICIT,
    Position = { 0, 1500, 2000 },
} ).Wing

-- Einen Spezialcontainer mit 2 Geheimdienstwaffen an den Arrackfrachter andocken
V.Arrackfrachter = MissionLib.GetWingMember( V.Superfrachter, 1 )
V.Weapon = NContainer.Create( {
    Type = CONTAINER_SHIP,
    Size = CONTAINER_SPECIAL,
    Ship = V.Arrackfrachter
} ).Container
NContainer.SetUniqueItems( { Container = V.Weapon, Number = 2 } )
-- Frachter soll seine Container bei Ausfall der Schilde abwerfen
NShip.ProtectCargo( { Ship = V.Arrackfrachter, Protect = false } )

-- Frachter für den Transport von Handelswaren in 50t-Containern.
-- Hierfür muss die StarShip.ini um die drei Sektionen [StarShip005_0<ObjIndex>]
-- ( hier also [StarShip005_027], [StarShip005_030] und [StarShip005_033] )
-- erweitert und darin der Wert ContainerSize = 0 ( CONTAINER_SMALL ) gesetzt werden.
-- Dabei kann auch noch der Wert BayNum = 45 auf den korrekten Wert von 42 für die Arrack
-- und 40 für die Raptoren geändert werden. Hat aber scheinbar keine negativen Auswirkungen,
-- wenn man es nicht tut. NShip.GetNumCargoBays() z.B. liefert trotzdem den richtigen Wert.
-- Da es ein Frachter für kleine Container ist, kann man auch den Rumpfwert verringern, z.B.
-- auf HitpointFactor = 16.000000, was immerhin noch dem doppelten Faktor eines normalen
-- 600-Tonnen Frachters bzw. dem Wert eines kleinen Kreuzers entspricht.
V.Superfrachter50T = NWing.Define( {
    Ships = {
    { ObjType = ST_TRADERSHIP, ObjIndex = 27 },	-- Terraner Superfrachter 2250t
    { ObjType = ST_TRADERSHIP, ObjIndex = 30 },	-- Arrack Superfrachter 2100t
    { ObjType = ST_TRADERSHIP, ObjIndex = 33 }	-- Raptor Superfrachter 2000t
    },
    PosType = POSDESCR_EXPLICIT,
    Position = { 1500, 0, 2000 },
} ).Wing

-- Frachter für den Transport von Handelswaren in 100t-Containern.
-- Hierfür muss die StarShip.ini um die drei Sektionen [StarShip005_0<ObjIndex>]
-- erweitert und darin der Wert ContainerSize = 1 ( CONTAINER_MEDIUM ) gesetzt werden.
-- Da es ein Frachter für mittlere Container ist, kann man auch den Rumpfwert verringern,
-- z.B. auf HitpointFactor = 20.000000.
V.Superfrachter100T = NWing.Define( {
    Ships = {
    { ObjType = ST_TRADERSHIP, ObjIndex = 28 },	-- Terraner Superfrachter 4500t
    { ObjType = ST_TRADERSHIP, ObjIndex = 31 },	-- Arrack Superfrachter 4200t
    { ObjType = ST_TRADERSHIP, ObjIndex = 34 }	-- Raptor Superfrachter 4000t
    },
    PosType = POSDESCR_EXPLICIT,
    Position = { -1500, 0, 2000 },
} ).Wing

-- Frachter für den Transport von Handelswaren in 200t-Containern.
-- Hierfür muss die StarShip.ini um die drei Sektionen [StarShip005_0<ObjIndex>]
-- erweitert und darin der Wert ContainerSize = 2 ( CONTAINER_LARGE ) gesetzt werden.
-- Der Standardwert HitpointFactor = 24.000000 für den Rumpf kann so bleiben und entspricht
-- dem eines großen Kreuzers.
V.Superfrachter200T = NWing.Define( {
    Ships = {
    { ObjType = ST_TRADERSHIP, ObjIndex = 29 },	-- Terraner Superfrachter 9000t
    { ObjType = ST_TRADERSHIP, ObjIndex = 32 },	-- Arrack Superfrachter 8400t
    { ObjType = ST_TRADERSHIP, ObjIndex = 35 }	-- Raptor Superfrachter 8000t
    },
    PosType = POSDESCR_EXPLICIT,
    Position = { 0, -1500, 2000 },
} ).Wing

-- Den terranischen 9000t-Frachter komplett mit zufälliger Ware beladen:
V.Terranerfrachter200T = MissionLib.GetWingLeader( V.Superfrachter200T )
V.ContainerListe = MissionLib.LoadCargo( V.Terranerfrachter200T )
NShip.ProtectCargo( { Ship = V.Terranerfrachter200T, Protect = false } )

-- Superfrachterwing mit Eskorte (max. 10 Begleitschiffe), fliegt durch das Hyperraumtor ein
V.SuperfrachterWing = NWing.Define( {
    WingType = WINGTYPE_FREIGHTER200T,  --< wenn angegeben, ist die Handelslogik aktiv
    Ships = {
    { ObjType = ST_TRADERSHIP, ObjIndex = 35 }, -- Raptor	Jägerpositionen:
    { ObjType = ST_WINGMAN, ObjIndex = 0 },	-- Terraner	vorne rechts
    { ObjType = ST_WINGMAN, ObjIndex = 0 },	-- Terraner	vorne links
    { ObjType = ST_WINGMAN, ObjIndex = 1 },	-- Mortok	vorne oben
    { ObjType = ST_WINGMAN, ObjIndex = 2 },	-- Raptor	mitte rechts
    { ObjType = ST_WINGMAN, ObjIndex = 2 },	-- Raptor	mitte links
    { ObjType = ST_WINGMAN, ObjIndex = 1 },	-- Mortok	mitte unten
    { ObjType = ST_WINGMAN, ObjIndex = 3 },	-- Oc'to	hinten rechts
    { ObjType = ST_WINGMAN, ObjIndex = 3 },	-- Oc'to	hinten links
    { ObjType = ST_WINGMAN, ObjIndex = 4 },	-- Arrack	hinten unten
    { ObjType = ST_WINGMAN, ObjIndex = 4 },	-- Arrack	hinten oben
    },
    PosType = POSDESCR_HYPERSPACE,
} ).Wing
NWing.SetFormation( { Wing = V.SuperfrachterWing, Formation = 22 } ) -- große Formation
V.Superfrachter = MissionLib.GetWingLeader( V.SuperfrachterWing ) -- Chef
V.Container = MissionLib.LoadCargo( V.Superfrachter )		  -- Beladen
NShip.ProtectCargo( { Ship = V.Superfrachter, Protect = false } ) -- Waren normal abwerfen
NShip.SetCrime( { Ship = V.Superfrachter, Set = true } )	  -- Strafpunkte bei Beschuss

-- Frachter für den Transport von Artefakt-Containern lassen sich nicht erzeugen.

Definiert man in der "StarShip.ini" einen entsprechenden Eintrag mit der Größe ContainerSize = 6 ( CONTAINER_ARTEFACT ), wird ein Superfrachter für normale 50t-Container erzeugt. Der untenstehende Beispielcode wird auch ausgeführt, aber der Artefakt-Container wird dabei zu einem leeren 50t-Container. Dieser wird dann zwar auch angedockt, lässt sich aber nicht mehr abwerfen. Absturz beim Versuch mit "NShip.DropContainer". Ein Versuch mit "NShip.AddContainer", wenn vorher ein Artefakt-Container mit Type = CONTAINR_SPACE im All erzeugt wurde, führt beim Andocken ebenfalls zum Absturz.

V.Superfrachter = NWing.Define( {
    Ships = {
    { ObjType = ST_TRADERSHIP, ObjIndex = SI_SUPERTRADER_ARTEFACT },
    },
    PosType = POSDESCR_EXPLICIT,
    Position = { 0, 0, 2000 },
} ).Wing
V.Freighter = MissionLib.GetWingLeader( V.Superfrachter )

V.Artefact = NContainer.Create( {
    Type = CONTAINER_SHIP,
    Size = CONTAINER_ARTEFACT,
    Ship = V.Superfrachter
} ).Container
NContainer.SetUniqueItems( { Container = V.Artefact, Number = 1 } )

Die hier angesprochenen Ergänzungen der Frachterdefinitionen (ObjIndex) können der Hilfe für die Datei StarShip.ini entnommen werden.


Destroy

Destroy( { Wing } ) : {}

Zerstört den angegebenen Wing. Es wird kein WING_DESTROYED Event ausgelöst.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings

Rückgabetabelle
leer

Beispiel

NWing.Destroy( { Wing = V.Gegner } )


ExecuteAi

ExecuteAi( { Wing } ) : {}

Dieser Befehl lässt den Wing seine aktuelle AI-Action sofort berechnen. So kann eine Mission einen Aktions-Befehl ohne Verzögerung ausführen lassen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings

Rückgabetabelle
leer

Beispiel

-- Dieser Piratenwing berechnet seine Aktion sofort.
NWing.ExecuteAi( { Wing = V.Pirates } )


IsHostileShip

IsHostileShip( { Wing, Ship } ) : { Hostile }

Es wird geprüft, ob das angegebene Schiff ein Feind des angegebenen Wings ist.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings
Ship | unsigned int | CStarShipHandle | Id des StarShips

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Hostile | bool | n/a | ist gesetzt, wenn das Schiff in der Feindliste des Wings ist.

Beispiel

if NWing.IsHostileShip( { Wing = V.FrachterWing, Ship = V.Player } ).Hostile then
    tu_was...
end


IsWing

IsWing( { Wing } ) : { IsWing }

Prüft, ob der angegebene Wing vorhanden ist.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
IsWing | unsigned int | 0..1 | Der Wing existiert (1) oder nicht (0)

Beispiel

if NWing.IsWing( { Wing = V.Hunter } ).IsWing == 1 then
    V.Info = "Der Wing existiert."
end


List

List( { Wing } ) : { ShipList }

Listet die Schiffshandles aller Schiffe des Wings auf. Wurde der Wing mit NWing.Create erzeugt, ist ein einzelnes Schiff, ein Kreuzer oder ein Frachter im Wing immer der Wingleader. Bei NWing.Define ist das erste in der Liste 'Ships' definierte Schiff der Leader.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
ShipList | table[1..11] : unsigned int | CStarShipHandle | Handlewerte aller Schiffe des Wings

Beispiel

local Ships = NWing.List( { Wing = V.FrachterWing } ).ShipList

-- Wingleader ermitteln, alles dasselbe:
V.Frachter = Ships[1]
V.Frachter = MissionLib.GetWingLeader( V.FrachterWing )
V.Frachter = MissionLib.GetWingMember( V.FrachterWing, 0 )


MakeHostile

MakeHostile( { Wing } ) : {}

Der Spieler wird ein Feind dieses Wings.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings

Rückgabetabelle
leer

Beispiel

NWing.MakeHostile( { Wing = V.CruiserWing } )


NoEnemy

NoEnemy( { Wing } ) : {}

Die Feindliste des angegebenen Wings wird gelöscht. Auch der Spieler ist nicht mehr Feind dieses Wings. Wird dieser Befehl mit der Gruppen-KI verwendet, kann es passieren, dass sich der Wing neue Gegner holt. Wenn zwei Wings gegeneinander kämpfen, müssen beide Gegnerlisten gelöscht werden, damit der Kampf endet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings

Rückgabetabelle
leer

Beispiel

NWing.NoEnemy( { Wing = V.Rekruten } )
NWing.NoEnemy( { Wing = V.KompanieSpiess } )


Place

Place( { Wing, Position, Front, LookAt, BaseObj } ) : {}

Platziert den Leader eines Wings an der angegebenen Position und Ausrichtung und platziert alle weiteren Schiffe auf ihre Wingpositionen. Wird 'BaseObj' angegeben, sind 'LookAt' und 'Position' Koordinaten im Bezugssystem von 'BaseObj'.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings
Position | table[3] : float | n/a | Position des Wingleaders
Front | table[3] : float | n/a | Blickrichtung des Wingleaders
LookAt | table[3] : float oder unsigned int | Vektor oder CObjectHandle | Position bzw. Objekt, worauf die Kamera blicken soll
BaseObj | unsigned int | CObjectHandle | Objekt, auf das sich 'Position' und 'LookAt' beziehen

Rückgabetabelle
leer

Beispiel


SetFormation

SetFormation( { Wing, Formation } ) : {}

Gibt eine Formation für den Wing vor.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings
Formation | unsigned int | Index aus WingInfo.ini | Index der Formation

Rückgabetabelle
leer

Beispiel

NWing.SetFormation( { Wing = V.Pirate, Formation = 2 } )


SetInvalidEnemy

SetInvalidEnemy( { Wing, TypeId, Set } ) : {}

Dieser Befehl sperrt oder erlaubt einen Schiffstyp als Gegner eines Wings.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Id des Wings
TypeId | unsigned int | Schiffstyp | Schiffstyp, der als Gegner verboten oder erlaubt werden soll
Set | int | int | wird hier 0 übergeben, wird der Schiffstyp TypeId als Gegner zugelassen. Sonst wird TypeId als Gegner verboten.

Rückgabetabelle
leer

Beispiel

-- Dieser Piratenwing darf auch gegen andere Piratenschiffe kämpfen.
-- Er greift aber weiterhin keine Piratenschiffe seiner KI-Gruppe an.
NWing.SetInvalidEnemy( { Wing = Pirates.Wing, TypeId = ST_PIRATESHIP, Set = 0 } )

-- Dieser Piratenwing darf den Spieler nicht angreifen
NWing.SetInvalidEnemy( { Wing = Pirates.Wing, TypeId = ST_PLAYERSHIP } )


SetPlayerEntryPos

SetPlayerEntryPos( { Position, Front, Updir } ) : {}

Wenn ein Spielerwing das System betritt, aber nicht das Hypergate benutzt, kann eine Eintrittsposition vorgegeben werden. Die Position sollte nur im PREFADE-Event eingetragen werden. Gibt man keine Position oder {0,0,0} an, wird eine Eintrittsposition an einer freien Stelle berechnet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Position | table[3] : float | n/a | Position, an der der Wing das System betreten soll
Front | table[3] : float | n/a | Flugrichtung, mit der der Wing das System betreten soll.
Updir | table[3] : float | n/a | Aufwärtsrichtung, an der sich der Wing ausrichten soll.

Rückgabetabelle
leer

Beispiel


Events

ScriptingEvents : Allgemeines

Missions-Skripte in DSO sind ereignisgesteuert, d.h. ein Skript wird nur dann aufgerufen und ausgeführt, wenn ein Ereignis ausgelöst wird, für das diese Mission einen Event-Filter gesetzt hat. Das Installieren dieser Filter erfolgt automatisch bei der Angabe des Event-Namens in einer Transition und braucht nicht manuell vorgenommen zu werden. Tritt ein Ereignis ein, so werden alle Missionen, die sich für dieses Ereignis registriert haben, aufgerufen und die entsprechenden Behandlungsroutinen in den gültigen Transitionen gestartet. Diese werten die in der Parametertabelle übergebenen Werte aus, führen den benutzerdefinierten Code aus und füllen die Felder der Rückgabetabelle mit Daten. Anschließend kann nach der Rückkehr ins C-Programm noch programmseitiger Code für dieses Ereignis ausgeführt werden.

Die Behandlungsroutine für ein Event erhält genau zwei Parameter, die Datentabelle 'V' der Mission und die Parametertabelle 'Data' des Ereignisses, in der alle wesentlichen Informationen zu diesem Ereignis vom Programm übergeben werden. Bestimmte Ereignisse liefern Werte zurück. Dies geschieht wie bei den Funktionen in einer Rückgabetabelle, in der Rückgabewerte in benannten Feldern abgelegt werden.

Die Dokumentation folgt dabei folgendem Schema:

  • < Name des Events > : < Parametertabelle > : < Rückgabetabelle >
  • Auslöser
  • Parametertabelle
  • Rückgabetabelle
  • Beispiele
Kursive Feldbezeicher kennzeichnen optionale Parameter. In diesem Falle ist hinter der Angabe des Wertebereichs der Default-Wert zu finden. Sind im Wertebereich keine Angaben zu finden, so sind alle Werte erlaubt, die der Datentyp annehmen kann. Erläuterungen zu den Datentypen sind unter Datentypen zu finden.

Ereignisse

Alphabetische Liste der Events
Eventname | Gruppe
Achieved | Missionen
ActionCamEnd | Camera
ActionCamStart | Camera
Artefact | Player
Bar | Player
Canyon | Canyon
CommEnd | Communication
Communication | Communication
Container | Objects
Create | Missionen
CriminalRecord | Player
Destroy | Missionen
Dialog | Communication
Equipment | Player
Failed | Missionen
Grab | Player
Hostile | Player
Init | Missionen
Item | Player
MissionStart | Missionen
Movie | GUI
MovieFinished | GUI
PlayerLevelUpgrade | Player
PlayerScanned | Player
Run | Simulation
Scan | Player
Scanning | Player
Shield | Starships
StarShip | Starships
StarshipCreated | Starships
StarshipDeath | Starships
StarshipDestroyed | Starships
StarSystemSelect | Player
Station | Player
Subtype | Missionen
System | Player
TargetSelect | Player
Text | Missionen
Timer | Missionen
Tutorial | Tutorial
TutorialPopup | Tutorial
Use | Player
Waypoint | Objects
Wing | Wing


ActionCamEnd

ActionCamEnd : { Camera } : {}

Eine Kamera ist im Begriff beendet zu werden, das Kameraobjekt existiert aber noch.

Auslöser
Zerstörung einer Kamera, die programmseitig oder per Skript erzeugt wurde.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der Kamera, die beendet wird

Rückgabetabelle
leer

Beispiel

{
    1.1, 1.7, "ActionCamEnd", function( V, Data )
        if Data.Camera == V.Cam then
            V.Cam = nil
        end
    end
},


ActionCamEnd

ActionCamStart : { Camera } : {}

Das Abspielen einer Kamera beginnt.
Achtung: Das Event wird nur in dem Skript getriggert, wo auch die Kamera erzeugt wurde!

Auslöser
Programmseitig durch das Setzen einer neuen aktiven Kamera per Skript.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Camera | unsigned int | CCameraHandle | Handle der Kamera, die gestartet wird

Rückgabetabelle
leer

Beispiel

{
    1.1, 1.7, "ActionCamStart", function( V, Data )
        if Data.Camera == V.Cam then
            ...
        end
    end
},


Canyon

Canyon : { Event, Segment, Handle } : {}

Ein Ereignis im Canyon ist eingetreten

Auslöser
Spieler betritt oder verlässt den Canyon (CANYON_ENTER, CANYON_LEAVE),
Spieler bewegt sich durch den Canyon und wechselt das Segment (CANYON_SEGMENT),
Spieler fliegt durch ein Kraftfeld (CANYON_TRIGGER).

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Event | enum | CANYON_ENTER CANYON_LEAVE CANYON_SEGMENT CANYON_TRIGGER | Das Ereignis
Segment | unsigned int | n/a | Das Segment, das der Spieler betreten hat (im Event CANYON_SEGMENT). In der Waffenfabrik wird das Event allerdings nicht ausgelöst, da sie keine Segmente hat.
Handle | unsigned int | CStaticObjectHandle | Handle des Objekts, das den Event ausgelöst hat.

Rückgabetabelle
leer

Beispiel

{   -- Spieler wechselt das Segment im Canyon oder im S'kaa-Mutterschiff
    1.1, 1.7, "Canyon", function( V, Data )
        if Data.Event == CANYON_SEGMENT then
            if Data.Segment == 5 then
                -- Schiff erzeugen
                ...
            end
        end
    end
},


CommEnd

CommEnd : { Message } : {}

Eine Funkmeldung ist zu Ende.

Auslöser
Ende einer Funkmeldung, die programmseitig oder per Skript erzeugt wurde.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Message | unsigned int | n/a | ID der Funkmeldung

Rückgabetabelle
leer

Beispiel

{   -- Warten nach CommEnd
    1.1, 1.1, "CommEnd", function( V, Data )
        if Data.Message == V.Comm then
            V.TimerId = NMission.CreateTimer( { Time = 3 } ).Timer
            V.Step = 1.2
        end
    end
},


Communication

Communication : { Type, Object } : { Object, BlockDlg }

Ereignisse im Zusammenhang mit Standarddialogen.

Auslöser
Spieler betätigt die Kommunikationstaste.
Ein Dialog wird per TriggerDialog() gestartet.
Spieler betätigt eine Wahlmöglichkeit in einem Standarddialog.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | COMMTYPE_LANDING_FORBIDDEN, COMMTYPE_LANDING_DENIED, COMMTYPE_LANDING_GRANTED, COMMTYPE_LANDING_CLEARED, COMMTYPE_DLG_START, COMMTYPE_DLG_END | Antworttyp
Object | unsigned int | CObjectHandle | Handlewert des Objekts, zu dem der Dialog gehört

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handlewert des Objekts, zu dem der Dialog gehört
BlockDlg | bool | n/a | War der Antworttyp COMMTYPE_DLG_START, dann verhindert ein 'BlockDlg' = true das Starten des Dialogs

Beispiel

{   -- Kreuzer lässt den Spieler nicht landen
    2, 3, "Communication", function( V, Data )
    if Data.Object == V.Cruiser then
        NObject.PlayerLanding( { Object = V.Cruiser, Accept = 0 } )
        local i = MissionLib.RandomBit()
        NComm.AddMessage( {
            Text = "IDR_STATION_LANDING_DENIED_HUM_00",
            Voice = "VOICE.IDR_STATION_LANDING_DENIED_HUM_00_SPOKEN_humsta0"..i,
            Video = "video/radio/radio_humsta00.bik",
            Sender = V.Cruiser,
            CommInOut = true
        } )
        return { Object = V.Cruiser, BlockDlg = false }
    end
    return {}
end },

{   -- Landung genehmigt
    35, 35, "Communication", function( V, Data )
    if Data.Type == COMMTYPE_LANDING_GRANTED and Data.Object == V.TradeStation then
        V.Comm = %ArimMessage( V, "29" )
        V.Step = 36
        return { Object = V.TradeStation, BlockDlg = true }
    end
    return {}
end },


Dialog

Dialog : { Owner, Input } : { Text, Voice, Video, Inputs }

Ein Dialog zwischen dem Spieler und einem anderen Objekt (Schiff, Station) findet statt. Die Mission muss Texte und Auswahlmöglichkeiten bereitstellen. Die Liste 'Inputs' der Rückgabetabelle enthält Paare aus einer StringId und einer Zahl. Die Zahl wird als Eingabe an die Mission zurückgegeben, wenn diese Auswahl betätigt wird.
Hinweise:
1. Alle Input-Zweige (-1 bis 9) außer dem Dialogende (-2) müssen mindestens mit return { Text = "" } abgeschlossen werden, sonst kommt es zum Absturz mit einem "DoReturn"-Fehler.
2. Wird der Dialog aufgerufen, z. B. wenn der Spieler die Kommunikationstaste betätigt oder eine Antwortoption im Dialog anwählt, liefert der Start der NPC-Nachricht sofort den Wert 0 im "CommEnd"-Event zurück. Ein "CommEnd"-Event für das Ende der Nachricht gibt es jedoch nicht. Das selektierte Objekt (Schiff, Shuttle, Station, usw.) muss mindestens über einen Standarddialog verfügen. So haben beispielsweise nicht alle Shuttles einen und bleiben stumm.
Achtung: In der Rückgabetabelle darf die Liste 'Inputs' maximal 3 Auswahlmöglichkeiten enthalten, die vierte Auswahl ist für das Dialogende reserviert. Zwar stimmen die Auswahlnummern mit denen von Data.Input, dem Index der angezeigten Felder und den zugeordneten Aktionen überein, nicht jedoch die Texte. Manchmal werden auch gar keine Texte angezeigt. Außerdem bleiben alle weiteren angezeigten Felder nach dem vierten immer leer.

Auslöser
Aufruf eines Dialogs, in den sich die Mission eingeklinkt hat.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Owner | unsigned int | CObjectHandle | Handle des Dialogobjekts
Input | int | 0 .. 9, -1, -2 | 0..9 = Inputindex des Spielers, -1 = Dialogstart, -2 = Dialogende

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Text | string | StringId aus dem LokaTool | Anzuzeigender Text. Entspricht die StringId dem Bezeichner einer Stream-Resource, braucht 'Voice' nicht zugewiesen zu werden.
Voice | string | Bezeichner einer Stream-Resource aus der KlangErzeugerDefault.xml oder user_sounds.xml | Abzuspielender Stream. Braucht nicht angegeben zu werden, wenn 'Text' bereits einem Bezeichner entspricht.
Video | string | n/a | Vollständiger Pfad zu einem Video (.bik)
Inputs | table[n] : { string, int } | Paare aus einer StringId aus dem LokaTool und einer Ziffer von 0 bis 9 | Auswahlmöglichkeiten für den Spieler. Maximal 3 Einträge!

Beispiel

{   -- Dialog für Basilius
    10, 12, "Dialog", function( V, Data )
    if Data.Owner == V.BasiliusShip then
        NShip.SetActor( { Ship = V.BasiliusShip, Actor = "basilius" } )
        V.Dialog = true
        -- Dialog Start
        if Data.Input == -1 then
            return {
                Text = "IDM_STORY_011_RADIO_028_BASILIUS_SPOKEN",
                Voice = "IDM_STORY_011_RADIO_028_BASILIUS_SPOKEN_basilius",
                Inputs = {
                    { "IDM_STORY_011_COMDIA_01", 0 },
                    { "IDM_STORY_011_COMDIA_02", 1 }
                }
            }

        elseif Data.Input == 0 or Data.Input == 1 or Data.Input == -2 then
            -- Timer für Angriff
            V.Timer = NMission.CreateTimer( { Time = 0.25 } ).Timer
            V.Step = 13
            return {
                Text = "IDM_STORY_011_RADIO_030_BASILIUS_SPOKEN",
                Voice = "IDM_STORY_011_RADIO_030_BASILIUS_SPOKEN_basilius"
            }
        end
    end
end },

{   -- Dialog mit Mitris Frachter
    2, 2.3, "Dialog", function( V, Data )
    if Data.Owner == V.TraderMitri and Data.Input == -1 then
        -- "Wir sind gerade bei Wartungsarbeiten. Mitri erwartet euch..."
        return { Text = "IDM_STORY_010_RADIO_002_TRADERMITRI" }
    end
end },


Movie : { ? } : { ? }

Undokumentiertes Event.

Auslöser
?

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
? | ? | ? | ?

Rückgabetabelle
unbekannt

Beispiel


MovieFinished : {} : {}

Eine Zwischensquenz wurde abgespielt.

Auslöser
Programmseitig nach dem Beenden des Videos.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel


Achieved

Achieved : {} : { Timeout, Credits, Text, Keys }

Die Mission wurde erfolgreich beendet. Es wird ein Infotext eingeblendet ( default ist "Mission erfolgreich!" ) und der entsprechende Musik-Jingle abgespielt. Die Mission erhält den Zustand MSTATE_IDLE und es werden keine Events mehr an die Mission weitergeleitet.
Sollen als Belohnung Systeme freigeschaltet werden, so sollte der Parameter 'Keys' verwendet werden, da beim manuellen Freischalten per NStarsystem.Unlock die Freischalt-Nachricht vor "Auftrag erfüllt" kommt, was vermieden werden sollte.
Die Markierung des im Skript zuletzt als Missionsziel markierten Sternsystems wird auf der Navigationskarte automatisch gelöscht. Bei mehr als einem markierten Missionsziel bleiben also die anderen Markierungen bestehen und müssen ggf. noch nachträglich mit der Funktion NStarSytem.SetAsMissionTarget entfernt werden.

Auslöser
Aufruf aus dem Skript per NMission.SetState( { State = MSTATE_ACHIEVED } )

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Timeout | int | n/a | Auszeit der Mission in Tagen, 0 - wird sofort, < 0 - wird nie wieder angeboten
Credits | unsigned int | n/a | Geldbetrag, der dem Spieler automatisch überwiesen wird
Text | string | StringId aus dem LokaTool | Anzuzeigender Info-Text, default = StringId für "Mission erfolgreich" bzw. "Auftrag erfolgreich"
Keys | table[n] : unsigned int | Liste mit Systemnummern (0-402) | Liste aller freizuschaltener Systeme. Hat für bereits freigeschaltete Systeme keine Auswirkung, es kommt auch keine Freischalt-Nachricht.

Beispiel

{   -- Mission erfolgreich, Schlüssel vergeben, nicht mehr anbieten
    1, nil, "Achieved", function( V, Data )
    NStarSystem.Unlock( { System = 19 } )
    NPlayer.AddCredits( { Credits = NPlayer.StandardReward().Credits } )
    return { Timeout = -1 }
    end
},

-- Wenn die Credits bereits bei der Missionserzeugung festgelegt wurden:
{   -- Erzeuge Mission
    nil, nil, "Create", function( V, Data )
    V.Reward = NPlayer.StandardReward().Credits
    end
},

{   -- Mission erfolgreich, statt "Unlock" den Parameter 'Keys' verwenden
    1, nil, "Achieved", function( V, Data )
    return { Timeout = -1, Credits = V.Reward, Keys = { 19 } }
    end
},

-- Mission leise beenden, es wird weder ein Text angezeigt noch ein Jingle abgespielt:
{   -- Mission erfolgreich, in 80 Tagen wieder anbieten
    nil, nil, "Achieved", function( V, Data )
    return { Timeout = 80, Text = "" }
    end
},


Create : {} : {}

Die Mission wurde erzeugt und ist ab jetzt aktiv.

Auslöser
Programmseite Missionserzeugung, Aufruf aus Script per NMission.Create()

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- Mission wurde erzeugt
    nil, nil, "Create", function( V, Data )
    -- Hier kann erstmalig ein Step gesetzt werden
    V.Step = 1
    end
},


Destroy : {} : {}

Die Mission wurde zerstört und wird nach diesem Aufruf endgültig entfernt.

Auslöser
Programmseitiges Beenden der Mission,
Als Folge der Behandlung der Events 'Achieved' oder 'Failed' bei Angabe von 'Timeout=0',
Aufruf aus einem Skript per NMission.SetState( { State = MSTATE_ENDED } )

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- Aufräumen
    nil, nil, "Destroy", function( V, Data )
        NStarSystem.SetAsMissionTarget( { System = V.System0, Set = 0 } )
        NStarSystem.SetAsMissionTarget( { System = V.System1, Set = 0 } )
    end
},


Failed

Failed : {} : { Timeout, Text }

Die Mission wurde erfolglos beendet. Es wird ein Infotext eingeblendet ( default ist "Mission gescheitert!" ) und der entsprechende Musik-Jingle abgespielt. Die Mission erhält den Zustand MSTATE_IDLE und es werden keine Events mehr an die Misison weitergeleitet.
Die Markierung des im Skript zuletzt als Missionsziel markierten Sternsystems wird auf der Navigationskarte automatisch gelöscht. Bei mehr als einem markierten Missionsziel bleiben also die anderen Markierungen bestehen und müssen ggf. noch nachträglich mit der Funktion NStarSytem.SetAsMissionTarget entfernt werden.

Auslöser
Aufruf aus dem Skript per NMission.SetState( { State = MSTATE_FAILED } )

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Timeout | unsigned int | n/a | Auszeit der Mission in Tagen, 0=wird sofort wieder angeboten, -1=wird nie wieder angeboten
Text | string | StringId aus dem LokaTool, default=<StringId für Mission/Auftrag fehlgeschlagen> | Anzuzeigender Info-Text

Beispiel

{
    nil, nil, "Failed", function( V, Data )
    if V.Step == 100.0 then
        return { Timeout = -1 }
    else
        return { Timeout = 0 }
    end
    end
},


Init

Init : {} : { Ready }

Die Mission soll erzeugt werden. Die Behandlungsroutine für dieses Ereignis muss prüfen, ob alle Bedingungen für die Erzeugung erfüllt sind und in diesem Falle im Feld 'Ready' der Rückgabetabelle true zurückliefern.

Auslöser
Programmseitige Erzeugung einer Mission.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ready | bool | n/a | true, wenn die Mission erzeugt werden darf

Beispiel

{
    nil, nil, "Init", function( V, Data )
    local system = MissionLib.GetStarSystemId()
    if ( system >= 12 ) and ( system <= 15 ) then
        V.System0 = 16;
        V.System1 = 12;
        V.System2 = 17;
        V.Pirates = {}
        return { Ready = true }
    end
    return { Ready = false }
    end
},


MissionStart : {} : {}

Die Mission wird endgültig gestartet.

Auslöser
Programmseitiger Start der Mission,
Aufruf aus dem Skript per NMission.SetState( { State = MSTATE_RUNNING } )

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- es geht los
    nil, nil, "MissionStart", function( V, Data )
    NStarSystem.SetAsMissionTarget( { System = V.System0, Set = true } )
    V.Step = 1.0
    end
},


Subtype

Subtype : {} : { Subtype }

Das Programm möchte den Subtyp der Mission erfahren. Wird normalerweise nur für Terminal-Missionen benötigt. Es wird dann das dem Subtype entsprechende Bild im Terminal angezeigt.

Auslöser
Programmseitig beim Erzeugen einer Mission.

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Subtype | enum | SUBTYPE_TRANSPORT, SUBTYPE_HEADHUNT, SUBTYPE_PIRATES, SUBTYPE_SABOTAGE, SUBTYPE_PROTECT, SUBTYPE_RESCUE, SUBTYPE_POLITICAL | Subtyp der Mission, für die programmseitige Auswahl und Anzeige

Beispiel

{
    nil, nil, "Subtype", function( V, Data )
    return { Subtype = SUBTYPE_POLITICAL }
    end
},

Grafiken im Terminal
SUBTYPE_HEADHUNT | SUBTYPE_PIRATES | SUBTYPE_POLITICAL
Kopfgeldjagd | Piratenjagd | Politisch
SUBTYPE_PROTECT | SUBTYPE_RESCUE | SUBTYPE_SABOTAGE
Beschützen | Bergung / Rettung | Sabotage
SUBTYPE_TRANSPORT |  |
Lieferdienst |  |


Text

Text : { NPC } : { Header, Client, Text, Replace, Reward, Credits }

Vom Programm wird Text angefordert. Der zurückgelieferte Text kann (und soll) je nach internem Zustand der Mission ein anderer sein. Wird in 'Replace' eine Liste mit StringIds übergeben, so werden diese verwendet, um Lücken in 'Text' zu füllen. Die Ersetzung wird dabei in der Reihenfolge der StringIds in 'Replace' vorgenommen, d.h. 'Replace[1]' esetzt %1 in 'Text' usw.

Auslöser
Der Spieler ruft eine Mission am Terminal ab,
Der Spieler öffnet das Logbuch.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
NPC | unsigned int | CNPCHandle | Handle eines NPCs, falls dieser Text von einem NPC stammen soll

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Header | string | StringId aus dem LokaTool | Überschrift
Client | string | StringId aus dem LokaTool | Auftraggeber
Text | string | StringId aus dem LokaTool | Anzuzeigender Text
Replace | table[n] : string | Tabelle mit StringIds aus dem LokaTool | Optionale Lückenfüller für 'Text'
Reward | string | StringId aus dem LokaTool | Angezeigte Belohnung, z.B. ein Systemschlüssel
Credits | int | default=StandardReward | Angezeigte Bezahlung, darf auch negativ sein

Beispiel

{   -- Logbucheintrag zeigen
    nil, nil, "Text", function( V, Data)
    if V.Step > 0 then
        return {
        Text = "IDM_HUMAN_003_LOG_CH01_0",
        Header = "IDM_HUMAN_003_HEADER",
        Client = "IDL_TRADER_02_0"..V.Combine,
        Replace = { "IDM_HUMAN_003_TRADERNAME", "ID_SYSTEMNAME_"..V.StartSystemId }
        }
    else
        return { Text = "IDM_HUMAN_003_LOG_CH01_1" }
    end
    end
},

{   -- Missionsbeschreibung im NPC-Fenster und erstem Logbucheintrag
    nil, 2, "Text", function( V, Data )
    return {
    Header  = "IDM_BAR_000_BAR_HDR",
    Client  = V.CombineName,
    Text    = "IDM_BAR_000_BAR_TEXT",
    Replace = { "ID_SYSTEMNAME_"..V.TargetSystemId, "ID_CLUSTER_2" },
    Reward  = "IDM_REWARD_HIDDEN_KEY",
    Credits = V.Reward
    }
end },


Timer

Timer : { Timer } : {}

Ein vorher erstellter Timer läuft ab.

Auslöser
Als Folge des Abarbeitens eines CMissionEvents, welches zuvor aus dem Skript heraus per NMission.CreateTimer() erstellt wurde.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Timer | unsigned int | CEventHandle | Handle des eingetretenden Ereignisses

Rückgabetabelle
leer

Beispiel

{   -- Timer beim Verlassen der Station erzeugen
    1, 1, "Station", function( V, Data )
    if Data.Enter == false then
        -- Timer für den Kamera-Start
        V.TimerStart = NMission.CreateTimer( { Time = 15 } ).Timer
    end
    end
},

{   -- Timer ist abgelaufen, die Kamera wird gestartet
    1, 1, "Timer", function( V, Data )
    if Data.Timer == V.TimerStart then
        V.Cam = NCamera.CreateFreeCam( { ... } ).Camera
    end
    end
},


Container

Container : { Container, Ship, Wing, Action } : {}

Ein Container wurde manipuliert. Wurde der Container abgeworfen oder aufgenommen, wird in 'Ship' das Schiff zurückgegeben, das den Container abgeworfen hat. Das kann auch eine Drohne sein, die den Container des Spielers geschleppt hat. Wurde der Container von einer Drohne aufgenommen, so wird in 'Ship' das Schiff zurückgegeben, dem die Drohne gehört.
Achtung: Der Container darf in diesem Event nicht zerstört oder gelöscht werden, sonst stürzt das Programm mit einem Laufzeitfehler ab!

Auslöser
Programmseitig durch die Manipulation eines Containers.

Fehler des Events
CONTAINER_DESTROYED:
Es wird kein Handle von Schiffen oder Wings zurückgeliefert, die den Container zerstört haben.
Schießt der Spieler seine eigenen Container mit Handelsware ab, die er in einer Handelsstation gekauft hat, wird das Event nicht ausgelöst!

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers
Ship | unsigned int | CStarShipHandle | CONTAINER_DROPPED: Schiff, das den Container abgeworfen hat. CONTAINER_TAKEN: Schiff, zu dem der Container gehört. CONTAINER_DESTROYED: nil
Wing | unsigned int | CWingHandle | Handle vom Wing des Schiffs (nil für CONTAINER_DESTROYED)
Action | enum | CONTAINER_TAKEN CONTAINER_DROPPED CONTAINER_DESTROYED CONTAINER_METEROID | Aktion, die mit dem Container ausgeführt wurde. CONTAINER_TAKEN wird ausgelöst, sobald die Frachtdrohne am Container andockt. Im Fall von Geheimdienstwaffen also bereits schon dann, bevor der Container tatsächlich an Bord genommen wurde. Dafür scheint es kein Event zu geben.

Rückgabetabelle
leer

Beispiel

{   -- Container wurde zerstört oder abgeworfen
    2, nil, "Container", function( V, Data )
    if Data.Container == V.Container then
    if Data.Action == CONTAINER_TAKEN then
        -- Container wurde aufgenommen
        V.ContainerRetrieved = V.ContainerRetrieved + 1
        V.Step = 3
    elseif Data.Action == CONTAINER_DROPPED then
        -- Container wurde wieder abgeworfen
        V.ContainerRetrieved = V.ContainerRetrieved - 1
        V.Step = 2
    elseif Data.Action == CONTAINER_DESTROYED then
        -- Container zerstört -> Mission fehlgeschlagen
        NMission.SetState( { State = MSTATE_FAILED } )
    end
    end
end },

{   -- Programmabsturz!!!
    2, nil, "Container", function( V, Data )
    if Data.Action == CONTAINER_DROPPED and Data.Container == V.Container then
        if V.GenerateEvent then
            NContainer.Explode( { Container = V.Container } )
        else
            NContainer.Destroy( { Container = V.Container } )
        end
        V.Container = nil
    end
end },


Waypoint

Waypoint : { Waypoint, Leaving, Ship, Wing } : {}

Ein Wegpunkt wurde erreicht. Das Handle vom Waypoint darf gelöscht werden, wenn er nicht mehr benötigt wird. Sichtbare Wegpunkte sollte man vorher mit der Funktion NWaypoint.Show wieder unsichtbar machen. Der Wegpunkt selbst kann jedoch nicht vom Skript zerstört werden und triggert weiterhin, löst aber durch den fehlenden Handlewert keine Aktion mehr aus. An Schiffe oder Wings gebundene Wegpunkte werden dagegen vom Programm zerstört, sobald das Schiff oder der Wing nicht mehr existiert und der Handlewert wird damit ungültig. In dem Fall verschwindet er von selbst, falls er sichtbar war und muss nicht erst unsichtbar gemacht werden.

Auslöser
Spieler, Schiff oder Wing fliegt in den Trigger-Radius des Wegpunktes oder verlässt diesen.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Waypoint | unsigned int | CWaypointHandle | Handle des Wegpunkts
Leaving | bool | n/a | Ship, Wing oder Spieler verlässt den Bereich (true) oder fliegt hinein (false)
Ship | unsigned int | CStarShipHandle | Das Schiff, welches den Wegpunkt ausgelöst hat
Wing | unsigned int | CWingHandle | Der Wing des auslösenden Schiffs

Rückgabetabelle
leer

Beispiel

{   -- Spieler hat den Wegpunkt erreicht
    2, 3, "Waypoint", function( V, Data )
    if Data.Waypoint == V.Waypoint and not Data.Leaving then
        -- Wegpunkt wird nicht mehr benötigt:
        V.Waypoint = nil
        -- mach was
    end
    end
},

{   -- Ein anderer Wing hat den Wegpunkt erreicht oder verlässt ihn
    2, 3, "Waypoint", function( V, Data )
    if Data.Waypoint == V.Waypoint and Data.Wing == V.HunterWing then
        -- Triggert hier nur auf den Hunterwing und nicht den Spieler
    end
    end
},


Artefact : {} : {}

Der Spieler erhält ein Artefakt.

Auslöser
Der Spieler hat sich einem Artefakt so weit genähert, dass es vom Schiff automatisch aufgenommen wurde.
Der Spieler hat sich in der Handelsstation das im System vorhandene Artefakt gegen Bezahlung besorgen lassen.
Hinweis: Triggert erst, wenn das Artefakt tatsächlich an Bord ist. Bei Aufnahme im Asteroiden oder All also nach der Plasmastrahl-Animation.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- Gesammelte Artefakte zählen
    1, nil, "Artefact", function( V, Data )
    local count = GLOBALS.ArtefactCount + 1
    GLOBALS.ArtefactCount = count
    NGUI.ShowInfoText( { Text = "IDA_002_ARTEFACTS", Replace = { "ID_"..count } } )
    end
},


Bar

Bar : { System, Enter } : {}

Der Spieler betritt oder verlässt die Bar auf einer Raumstation.

Auslöser
Der Spieler klickt auf den 'Bar'-Hotspot in der Ankunftshalle,
Der Spieler klickt auf den 'Verlassen'-Button in der Bar.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | CStarHandle | Handle des Systems in dem sich die Raumstation befindet
Enter | bool | n/a | Spieler betritt die Bar (true), oder verlässt sie (false)

Rückgabetabelle
leer

Beispiel


CriminalRecord

CriminalRecord : { System, Record } : {}

Das Strafenregister des Spielers in einem System hat sich geändert.

Auslöser
Spieler erhält oder verliert Strafpunkte im einem System.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | CStarHandle | Handle des Systems
Record | float | 0.0f < Record | Aktueller Zählerstand

Rückgabetabelle
leer

Beispiel


Equipment

Equipment : { Type, Level } : {}

Der Spieler ändert seine Schiffsausrüstung.

Auslöser
Der Spieler kauft einen neuen Ausrüstungsgegenstand oder aktiviert ihn.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Type | enum | EQUIPMENT_AFTERBURNER, EQUIPMENT_CAPACITOR, EQUIPMENT_CARGO_COMPUTER, EQUIPMENT_GENERATOR, EQUIPMENT_HYPERDRIVE, EQUIPMENT_ORE_COLLECTOR, EQUIPMENT_SCANNER, EQUIPMENT_SCANNER_JAMMER, EQUIPMENT_SHIELD_GENERATOR | Art der Ausrüstung
Level | unsigned int | 0 .. 9 | Level der Ausrüstung

Rückgabetabelle
leer

Beispiel


Grab

Grab : { Container, HasGrabbed } : {}

Eine Frachtdrohne des Spielers wurde zu einem Container herausgeschickt oder der Spieler kann den Container aufnehmen.

Auslöser
Programmseitig durch den Andockbefehl für die Frachtdrohne,
Programmseitig durch die Überprüfung der Dockmöglichkeit.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Container | unsigned int | CContainerHandle | Handle des Containers
HasGrabbed bool n/a
false: Der Container wurde angewählt und ist in Reichweite der Frachtdrohne. Der Spieler kann den Container jetzt aufnehmen.
true: Wird ausgelöst, sobald die Frachtdrohne des Spielers vom Schiff abdockt und zum Container geschickt wird. Es ist also nicht sicher, ob der Container auch tatsächlich aufgenommen wurde, da der Vorgang jederzeit durch Abwurf abgebrochen werden kann.

Rückgabetabelle
leer

Beispiel

{   -- Ein Container wurde aufgenommen
    2, nil, "Grab", function( V, Data )
    -- Ist es unser Container?
    if V.Container == Data.Container and Data.HasGrabbed then
        MissionLib.LogUpdateTask()	-- Neuer Logbuch Eintrag
        V.PlayerHasContainer = true	-- Flag ändern
        V.Step = 3
    end
    end
},


Hostile

Hostile : { Enemy } : {}

Der Spieler wird feindlich zu einem Wing.

Auslöser
Programmseitig durch die Wing-Logik,
Aus dem Skript durch Maniplation der Feindliste des Wings.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Enemy | unsigned int | CWingHandle | Handle des Wings, der feindlich geworden ist

Rückgabetabelle
leer

Beispiel


Item

Item : {} : { Item }

Das Programm fragt die Mission nach dem Namen eines Spezialitems, das der Spieler per Use-Taste verwenden kann. Dieses selbstdefinierte Item wird in der Liste immer an erster Stelle angezeigt.
Es kann pro Skript und Fortschritt (Step) der Mission immer nur ein Spezial-Item angezeigt werden, da es einerseits nur den einen Rückgabewert "Item" gibt und andererseits das zugehörige "Use"-Event parameterlos ist und dadurch keine Abfrage mehrerer Items ermöglicht. Mehrere neue Items zur gleichen Zeit sind im selben Skript also nicht möglich. Allerdings kann man im Skript in unterschiedlichen Step-Bereichen, die sich nicht überschneiden dürfen, auch unterschiedliche Items definieren, die dann im jeweiligen Step aktiviert oder deaktiviert werden. Auch wenn in anderen gleichzeitig laufenden Skripts Items definiert wurden, werden diese angezeigt und können benutzt werden.

Achung: Funktioniert nicht mit dem Missionstyp MTYPE_ALWAYS, es wird kein neues Item angezeigt!
Wichtig: Bitte während Missionen, in denen ein Spezialitem eingebaut ist, auf gar keinen Fall einen Taskwechsel vom Spiel zu Windows durchführen. Nach dem Wechsel zurück zum Spiel kann der neue Eintrag nämlich aus der Benutzen-Liste verschwunden sein und in vielen Missionen geht es dann nicht mehr weiter (Storyblocker)!

Auslöser
Der Spieler öffnet den Use-Dialog mit der Taste "F".

Parametertabelle
leer

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Item | string | StringId aus dem LokaTool | Anzuzeigender Name des Items

Beispiel

{    -- Turbo-Booster des Nachbrenners in der Use-Liste anzeigen
    1, nil, "Item", function( V, Data )
    if V.Turbo then
        -- "Turbo AUS" wird angezeigt
        return { Item = "ID_AFTERBURNER_NORMAL" }
    else
        -- "Turbo EIN" wird angezeigt
        return { Item = "ID_AFTERBURNER_BOOST" }
    end
end },


PlayerLevelUpgrade : { ? } : { ? }

Undokumentiertes Event.

Auslöser
Upgrade wurde durchgeführt oder Upgrade möglich oder Anzahl Artefakte bis zum nächsten Upgrade?

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
? | ? | ? | ?

Rückgabetabelle
unbekannt

Beispiel


PlayerScanned

PlayerScanned : { illegal } : {}

Der Spieler wird von der Polizei gescannt. 'illegal' ist > 0, wenn der Spieler illegale Ware an Bord hat und von der Polizei angegriffen wird.

Auslöser
Ein Polizeischiff hat den Spieler gescannt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
illegal | unsigned int | n/a | > 0, wenn beim Spieler illegale Waren gefunden wurden.

Rückgabetabelle
leer

Beispiel


Scan

Scan : { Target } : {}

Der Spieler scannt ein SpaceObject mit dem Frachtscanner durch Betätigen des blauen Buttons in der TargetView. Der Scanneffekt dauert 5 Sekunden, das Event wird sofort beim Start des Scanns ausgelöst. Funktioniert auch bei Satelliten, normale Orbiter (Raumstationen, Asteroiden, Himmelskörper, Wracks) lassen sich aber nicht scannen, es wird auch kein Scan-Event ausgelöst.

Auslöser
Der Spieler scannt ein CSpaceObject mit dem eingebauten Frachtscanner.
Wird nicht von der Funktion NObject.ScanObject oder beim Scannen von Orbitern ausgelöst.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Target | unsigned int | CObjectHandle | Objekt, das gescannt wird

Rückgabetabelle
leer

Beispiel


Scanning : { ? } : { ? }

Undokumentiertes Event.

Auslöser
Der Spieler scannt was? Oder ist das vielleicht ein "StarShips"-Event, wo ein KI-Schiff am Scannen ist?

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
? | ? | ? | ?

Rückgabetabelle
unbekannt

Beispiel


StarSystemSelect : { ? } : { ? }

Undokumentiertes Event.

Auslöser
Spieler selektiert ein Sternsystem in der Navigationskarte?

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
? | ? | ? | ?

Rückgabetabelle
unbekannt

Beispiel


Station

Station : { System, Enter } : {}

Der Spieler landet auf einer Raumstation oder einem Kreuzer oder startet.

Auslöser
Spieler fliegt mit gültiger Landeerlaubnis in den Hangar und wechselt in die Stationsansicht,
Spieler klickt auf den 'Verlassen'-Button in der Ankunftshalle der Station oder des Kreuzers.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | CStarHandle | Handle des Systems in dem sich die Station befindet
Enter | bool | n/a | Spieler landet (true) oder startet (false)

Rückgabetabelle
leer

Beispiel

{   -- Spieler landet auf einer Station
    4, nil, "Station", function( V, Data )
    if  Data.Enter
        and Data.System == NStarSystem.GetHandleFromId( { Id = 29 } ).Handle
        and MissionLib.GetPlayerHangar() == MissionLib.GetSystemTradeStation() then
        NMission.SetState( { State = MSTATE_ACHIEVED } )
    end
    end
},


System

System : { System, State } : {}

Der Spieler betritt oder verlässt ein System.

Auslöser
Programmseitig:
- mit dem Erreichen eines neuen System durch das Hypergate,
- wenn danach der Spieler die Kontrolle über sein Schiff wiedererlangt hat,
- und durch den Eintritt des Spielerschiffs in den Hyperraum.

ACHTUNG: In Skripts vom Typ MTYPE_ALWAYS wird nur das Event ENTER_POSTCAM getriggert!
Die anderen drei Events werden niemals getriggert, wenn der Spieler das System betritt oder verlässt!

Besonderheiten der Events von State bei bestimmten Funktionsaufrufen
Event | Funktion | Kommentar
ENTER_PREFADE | MissionLib.GetStarSystemId() get( "Logic.PlayerShip.systemIndex" ) | Liefert die ungültige SystemId 65535.
 | MissionLib.GetStarSystemHandle() get( "Logic.PlayerShip.systemId" ) | Liefert dementsprechend auch ein ungültiges Systemhandle.
 | MissionLib.GetStarClusterHandle() get( "Logic.PlayerShip.clusterId" ) | Liefert das vorherige Clusterhandle, also wo der Spieler gerade herkommt.
 | MissionLib.GetStarClusterId() | Liefert dementsprechend auch die vorherige ClusterId.
 | NStarSystem.GetIdFromHandle(…).Id und ….GetHandleFromId(…).Handlle | Funktioniert, da Data.System der Parametertabelle das korrekte Systemhandle liefert. Alle sonstigen Befehle auf Basis von Data.System funktionieren daher ebenfalls. Funktionen, welche also mit get ("Logic.PlayerShip…") arbeiten, dürfen in diesem Event noch nicht verwendet werden!
ENTER_PRECAM | Ab hier funktionieren auch alle Funktionsaufrufe mit "Logic.PlayerShip…" wieder.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
System | unsigned int | CStarHandle | Handle des Systems
State | enum | ENTER_PREFADE, ENTER_PRECAM, ENTER_POSTCAM, LEAVE_SYSTEM | Spieler betritt das System oder verlässt es, ENTER_xx sind verschiedene Zustände während des Systemeintritts.

Rückgabetabelle
leer

Werte für State
Konstante | Kommentar | Wert
ENTER_PREFADE | Spieler betritt das System, der Tunnel ist noch sichtbar | 0
ENTER_PRECAM | Der Tunnel wird gleich abgeschaltet | 1
ENTER_POSTCAM | Die Systemeintrittskamera startet, sobald sie endet, erlangt der Spieler wieder die Kontrolle über sein Schiff | 2
LEAVE_SYSTEM | Spieler verlässt das System, Eintritt in den Tunnel | 3

Beispiel

{   -- Zielsystem ist erreicht, alle Missionsobjekte vor der Systemeintritts-Kamera erzeugen
    -- 1.) mit NStarSystem.GetIdFromHandle, funktioniert auch in ENTER_PREFADE
    1, 1, "System", function( V, Data )
    if  Data.State == ENTER_PRECAM
        and NStarSystem.GetIdFromHandle( { Handle = Data.System } ).Id == V.TargetSystemId then
        -- Objekte erzeugen
        V.Step = 2
     end
    end
},

{   -- 2.) das Gleiche mit NStarSystem.GetHandleFromId, auch in ENTER_PREFADE
    1, 1, "System", function( V, Data )
    if  Data.State == ENTER_PRECAM
        and Data.System = NStarSystem.GetHandleFromId( { Id = V.TargetSystemId } ).Handle then
        -- Objekte erzeugen
        V.Step = 2
     end
    end
},

{   -- 3.) und mit MissionLib.GetStarSystemId(), funktioniert nicht in ENTER_PREFADE
    1, 1, "System", function( V, Data )
    if  Data.State == ENTER_PRECAM
        and MissionLib.GetStarSystemId() = V.TargetSystemId then
        -- Objekte erzeugen
        V.Step = 2
     end
    end
},

{   -- Mission fehlgeschlagen, wenn der Spieler hier das System verlässt
    2, 3, "System", function( V, Data )
    if Data.State == LEAVE_SYSTEM then
        NMission.SetState( { State = MSTATE_FAILED } )
    end
    end
},


TargetSelect

TargetSelect : { Target } : {}

Der Spieler hat ein Ziel ausgewählt.

Auslöser
Spieler selektiert ein Objekt in der Targetliste oder über die Zielwahltasten.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Target | unsigned int | CObjectHandle | Handlewert des ausgewählten Objekts

Rückgabetabelle
leer

Beispiel

{   -- Rumpfschaden der DSO ermitteln, wenn ein Ziel selektiert wird
    -- und zuletzt angewähltes Ziel in V.Target merken
    2, nil, "TargetSelect", function( V, Data )
    V.Hull = get( "Logic.PlayerShip.hullCondition" )
    V.Target = Data.Target
    end
},


Use : {} : {}

Der Spieler hat einen Gegenstand aus der Item-Liste benutzt.
Achung: Funktioniert nicht mit dem Missionstyp MTYPE_ALWAYS, da von "Item" keine Benutzen-Taste erzeugt wird!

Auslöser
Spieler betätigt die 'Benutzen'-Taste (F).

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel

{   -- Turbo-Booster des Nachbrenners mit der Use-Taste umschalten
    1, nil, "Use", function( V, Data )
    if V.Turbo then
        -- Turbo ausschalten
        NPlayer.SetMultipliers({})
        V.Turbo = false
    else
        -- Turbo einschalten
        NPlayer.SetMultipliers( { BoostFactor = 10.0 } )
        V.Turbo = true
    end
end },


Run : {} : {}

Die Simulation erhält einen neuen Zeitschritt. Dieses Ereignis sollte nur in Ausnahmefällen vom Skript verwendet werden, Timer sind idR die bessere Wahl.

Auslöser
Programmseitig beim Berechnen einen neuen Simulationszeitschritts.

Parametertabelle
leer

Rückgabetabelle
leer

Beispiel


Shield

Shield : { Ship, Wing, Event, ShieldType } : {}

Der Schild eines Schiffs erreicht oder unterscheitet einen bestimmten Grenzwert.

Auslöser
Programmseitig, sobald der Schildzustand eines Schiffs einen bestimmten Wert erreicht oder unterschreitet.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Wing | unsigned int | CWingHandle | Handle des Wings des Schiffs
Event | enum | SHIELD_HALF, SHIELD_DOWN | Schildzustand
ShieldType | enum | SHIELD_BACK, SHIELD_FRONT, SHIELD_BOTH | Betroffener Schild

Rückgabetabelle
leer

Beispiel

{   -- Piratenfrachter soll seine Container abwerfen
    2, nil, "Shield", function( V, Data )
    if Data.Ship == V.PirateFreighter then
    if Data.Event == SHIELD_DOWN and Data.ShieldType == SHIELD_BOTH then
        NShip.DumpCargo( { Ship = V.PirateFreighter, Destroy = false } )
    end
    end
end },


StarShip

StarShip : { Ship, Wing, Event } : {}

Schild- oder Hüllenwert unterschreitet einen bestimmten Grenzwert.
Auf Schreibweise achten: StarShip!

Auslöser
Das Schiff wurde getroffen oder gerammt und eine Zustandsgrenze wurde unterschritten.
Das Schiff ist in einem Hangar gelandet und wird danach automatisch zerstört.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Wing | unsigned int | CWingHandle | Handle vom Wing des Schiffs
Event | enum | siehe Tabelle | Beschreibung des Ereignisses

Rückgabetabelle
leer

Typtabelle für den Parameter 'Event'
Wert | Beschreibung | Wert
SHIP_SHIELD_50 | Der Schildzustand des Schiffes ist unter 50% gesunken. | 0
SHIP_SHIELD_25 | Der Schildzustand des Schiffes ist unter 25% gesunken. | 1
SHIP_SHIELD_0 | Der Schildzustand des Schiffes ist auf 0% gesunken. | 2
SHIP_HULL_75 | Der Hüllenzustand des Schiffes ist unter 75% gesunken. | 3
SHIP_HULL_50 | Der Hüllenzustand des Schiffes ist unter 50% gesunken. | 4
SHIP_HULL_25 | Der Hüllenzustand des Schiffes ist unter 25% gesunken. | 5
SHIP_HULL_10 | Der Hüllenzustand des Schiffes ist unter 10% gesunken. | 6
SHIP_LANDED | Das Schiff ist gelandet ( und wird danach zerstört ) | 7

Beispiel


StarshipCreated : { ? } : { ? }

Undokumentiertes Event.

Auslöser
Ein Schiff wurde erzeugt?

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
? | ? | ? | ?

Rückgabetabelle
unbekannt

Beispiel


StarshipDeath

StarshipDeath : { Ship, Wing } : {}

Der Hüllenzustand eines Schiffs erreicht 0% und die Todesanimation beginnt. Das Event wird vor "StarshipDestroyed" ausgelöst.
Hinweis: Ist das Schiff sehr schwach relativ zum Spielerschiff, dann kann es passieren, dass "StarshipDeath" nicht triggert, wenn der Spieler es mit seinen Frontwaffen abschießt. Beim Abschuss durch die Geschütztürme des Spielers tritt dieses Problem idR nicht auf.
Interessanter Nebeneffekt: Solange das Event "StarshipDestroyed" noch nicht getriggert hat und man macht das Schiff nach "StarshipDeath" entweder mit NShip.Protect unsterblich oder mit NShip.SetInvulnerable unverwundbar, dann lebt es plötzlich wieder, obwohl die Todesanimation mit Trudeln und Explosionen bereits begonnen hat. Sogar ein aktuell laufender Dialog mit dem Schiff kann noch bedient werden. Bei Kreuzern lässt sich das sehr gut beobachten, da zwischen den beiden Events etliche Sekunden vergehen und die Animation lange läuft.
Achtung: "StarshipDeath" triggert nicht auf die Zerstörung von Satelliten!

Auslöser
Programmseitig, sobald der Hüllenwert auf 0 sinkt.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Wing | unsigned int | CWingHandle | Handle vom Wing des Schiffs

Rückgabetabelle
leer

Beispiel

{   -- Todeskamera starten
    2, 3, "StarshipDeath", function( V, Data )
    if Data.Ship == V.HunterShip then
        V.Cam = NCamera.CreateDeath( { Object = Data.Ship, Time = 3 } ).Camera
    end
end },


StarshipDestroyed

StarshipDestroyed : { Ship, Wing, Killer, Wreck } : {}

Der Hüllenwert eines Schiffs wurde auf 0 gesenkt und das Schiff wird endgültig zerstört.
Wird nicht aufgerufen, wenn das Schiff einfach so gelöscht wird (z.B. wenn der Wing des Schiffs in den Hyperraum springt und entfernt wird).
Wird nach dem Event "StarshipDeath" ausgelöst und nachdem die Todesanimation abgelaufen ist.

Achtung: Das Schiff ist an dieser Stelle noch nicht aus dem Wing gelöscht! Hatte der Wing vor dem Abschuss beispielsweise 5 Schiffe, dann liefert eine Abfrage mit der Funktion "MissionLib.GetShipCountInWing" immer noch 5. War das Schiff der Wingleader und man möchte in diesem Event sofort einen neuen zuweisen, muss man den ersten Wingman nehmen und nicht den Leader. Siehe auch Beispiel 2.

Auslöser
Programmseitig, wenn der Hüllenzustand 0% erreicht, unmittelbar vor der Löschung des Schiffs.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Ship | unsigned int | CStarShipHandle | Handle des Schiffs
Wing | unsigned int | CWingHandle | Handle vom Wing des Schiffs
Killer | unsigned int | CStarShipHandle | Handle des Schiffs, das den tödlichen Treffer verursacht hat (kann auch ungültig sein)
Wreck | unsigned int | CObjectHandle | Handle vom Wrack, falls das Schiff ein Kreuzer ist

Rückgabetabelle
leer

Beispiel 1

{   -- Kreuzerwrack in beliebigem Event erzeugen
    nil, nil, "MissionStart", function( V, Data )
    V.CruiserWing = NWing.Create( {
        WingType = WINGTYPE_CRUISER1,
        Race     = RACE_OCTO,
        Number   = 1,
        PosType  = POSDESCR_RESEARCHSTATION
    } ).Wing
    MissionLib.WingWingAiActionInaktiv( V.CruiserWing )
    V.Cruiser = MissionLib.GetWingLeader( V.CruiserWing )
    MissionLib.SetHull( V.Cruiser, 0.0 )
    V.Step = 1
end },

{   -- Handle und Position des Wracks holen und im Zielcomputer sichtbar machen
    1, 1, "StarshipDestroyed", function( V, Data )
    if Data.Wing == V.Cruiser then
        V.Cruiser = nil
        V.CruiserWreck = Data.Wreck
        V.PosWreck = MissionLib.GetShipPos( Data.Ship )  -- Data.Wreck geht auch
        NObject.RadarMapColor( { Object = V.CruiserWreck, Color = RADARMAP_BLUE_ORBITER } )
    end
end },

Beispiel 2

{   -- Boss ist tot, das nächste Schiff aus dem Wing als Boss zuweisen (neuer Wingleader ist es sowieso)
    1, 1, "StarshipDestroyed", function( V, Data )
    if Data.Ship == V.PoliceBoss then
        -- Neuer Boss (Achtung: das abgeschossene Schiff ist hier noch nicht aus dem Wing gelöscht!)
        if MissionLib.GetShipCountInWing( V.PoliceWing ) > 1 then
            V.PoliceBoss = MissionLib.GetWingMember( V.PoliceWing, 1 )
            NObject.SetMissionFlag( { Object = V.PoliceBoss, Set = 1 } )
        else
            V.PoliceBoss = nil
        end
    end
end },


Tutorial

Tutorial : { Element } : {}

Ein spezieller Teil des Tutorials wurde absolviert.

Auslöser
Spieler betätigt bestimmte Buttons oder drückt bestimmt Tasten.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Element | enum | 0..12, siehe Typtabelle für die Konstanten | Aktion des Spielers

Rückgabetabelle
leer

Typtabelle für den Parameter 'Element'
Konstante | Beschreibung | Wert
TUTORIAL_ONCLICK_NAVMAP | Navigationskarte wurde geöffnet | 0
TUTORIAL_ONCLICK_TARGETMAP | Targetmap wurde geöffnet | 1
TUTORIAL_ONCLICK_HYPERJUMP | Hyperraumsprung wurde ausgelöst | 2
TUTORIAL_ONCLICK_CLUSTERMAP |  | 3
TUTORIAL_ONCLICK_PLAYERCRUISER |  | 4
TUTORIAL_ONCLICK_UPGRADESCREEN | Button "Upgrade verfügbar" wurde angeklickt | 5
TUTORIAL_ONCLOSE_NAVMAP | Navigationskarte wurde geschlossen | 6
TUTORIAL_ONCLOSE_TARGETMAP | Targetmap wurde geschlossen | 7
TUTORIAL_ONCLOSE_CLUSTERMAP |  | 8
TUTORIAL_ONCLOSE_PLAYERCRUISER |  | 9
TUTORIAL_ONCLOSE_HELPDIALOG | Hilfedialog wurde geschlossen | 10
TUTORIAL_ONCLOSE_UPGRADESCREEN | Upgradedialog wurde geschlossen | 11
TUTORIAL_ONCLOSE_LOGBOOK | Ausrüstungsliste oder Logbuch wurde geschlossen | 12
TUTORIAL_ONCLICK_LOGBOOK | Ausrüstungsliste oder Logbuch wurde geöffnet | nil
TUTORIAL_ONHAS_HYPERJUMP | undefiniert | nil
TUTORIAL_ONHAS_LANDING | undefiniert | nil

Beispiel


TutorialPopup

TutorialPopup : { Popup } : {}

Das Tutorial Popup wurde geschlossen.

Auslöser
Spieler schließt das Popup-Fenster.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Popup | unsigned int | n/a | ID des Popups

Rückgabetabelle
leer

Beispiel


Wing

Wing : { Wing, Event } : {}

Ein Wing hat eine bestimmte Aktion ausgeführt oder es ist eine bestimmte Situation eingetreten. Über den Parameter 'Event' kann das Ereignis differenziert werden ( siehe Typtabelle ).

Auslöser
Ein Wing hat eine der definierten Aktionen ausgeführt oder ein definierter Zustand ist eingetreten.
Wird auch ausgelöst, wenn der Wing in den Hyperraum springt und dabei gelöscht wird.

Parametertabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wing | unsigned int | CWingHandle | Handle des Wings
Event | enum | WING_NO_TARGET ... WING_ACTIONLIST_EMPTY | Genaue Beschreibung des Ereignisses (siehe Tabelle)

Rückgabetabelle
leer

Typtabelle für den Parameter 'Event'
Konstante | Beschreibung | Wert
WING_NO_TARGET | Der Wing hat kein Ziel zum Angreifen mehr. | 1
WING_DESTROYED | Das letzte Schiff des Wings wurde zerstört und der Wing wird unmittelbar im Anschluß gelöscht. | 2
WING_TARGET_REACHED | Der Wingleader hat eine vorher festgelegte Raumkoordinate erreicht. Triggert nicht auf AI_ACTION_PATROUILLE. | 3
WING_ENTER_SYSTEM | Alle Schiffe des Wings haben das aktive System betreten. Triggert nicht bei Starts aus einem Hangar. | 4
WING_LEAVE_SYSTEM | Alle Schiffe des Wings verlassen gleich das aktive System. | 5
WING_SHIP_SHIELDDOWN | Ein Schiff hat im Kampf seinen Schild verloren. | 6
WING_SHIP_DESTROYED_1 | Der Wing hat das erste Schiff im Kampf verloren. | 7
WING_SHIP_DESTROYED_2 | Der Wing hat die Hälfte seiner Schiffe im Kampf verloren. | 8
WING_SHIP_DESTROYED_3 | Der Wing hat nur noch ein Schiff. | 9
WING_SHIPS_LANDED | Das letzte Schiff des Wings ist in einem Hangar gelandet. Danach wird WING_DESTROYED ausgelöst. | 10
WING_FIRST_ENEMY | Die Gegnerliste des Wings war leer, enthält jetzt aber wieder einen Gegner. | 11
WING_CARGO_GRABBED | Der Wing hat eine Frachtdrohne zur Containeraufnahme hinausgeschickt. Der Container muß nicht aufgenommen worden sein. | 12
WING_ACTIONLIST_EMPTY | Die Aktionsliste des Wings ist leer. | 13

Beispiel


Functions

PropertySystem Funktionen
  • Logic
    • get-Funktionen
      • Orbiter
      • Player
      • PlayerShip
      • StarFinder
      • StarShips
      • StarSystems
      • Startwerte
      • Walhalla
      • Wings
    • set-Funktionen
      • Player
      • PlayerShip
      • StarFinder
      • StarShips
      • StarSystems
      • Walhalla
    • list-Funktionen
Lua Funktionen
Kurzreferenz der im Skriptsystem implementierten Lua-Funktionen und allgemeine Hinweise zu Lua.
Darkstar One verwendet die Lua-Version 4.1.0 (ASCARON_LUA,modified 4.0.1 source), die gegenüber dem hier mit eingefügten Handbuch Lua 5.1 Reference Manual ein paar kleine Unterschiede aufweist. Gegebenenfalls wird bei den betroffenen Befehlen auch darauf hingewiesen.
Um die Funktionen nutzen zu können, müssen die entsprechenden Namespaces vorher importiert werden. Standardmäßig sind "lua" und "math" bereits von der "MissionLib.lua" importiert, "string" muss gegebenenfalls noch mit der Anweisung import "string" hinzugefügt werden (die "MissionLibEx.lua" importiert "string" automatisch, falls man sie einbindet).

Der Vollständigkeit halber sind hier alle im Skriptsystem enthaltenen Funktionen aufgeführt, auch wenn sie für eigene Skripts nicht benötigt werden. Da es durchaus möglich ist, für die bestehenden Namespaces neue Funktionen zu schreiben, kann man somit das versehentliche Überschreiben bestehender Funktionen vermeiden (oder sie sogar absichtlich ersetzen, was man aber besser sein lassen sollte).
  • lua
    • call
    • gc
    • getglobals
    • getn
    • getregistry
    • max
    • min
    • pack
    • rawget
    • rawset
    • setglobals
    • sizeof
    • tag
    • tofloat
    • tonumber
    • tostring
    • type
    • unpack
  • math
    • abs
    • acos
    • asin
    • atan
    • atan2
    • ceil
    • cos
    • deg
    • exp
    • floor
    • frexp
    • ldexp
    • length
    • log
    • log10
    • mod
    • normalize
    • pi
    • rad
    • random
    • randomseed
    • sin
    • sqrt
    • tan
  • string
    • at
    • erase
    • find
    • find_first_of
    • find_last_of
    • format
    • is_valid
    • length
    • replace
    • substr
    • tokenize
    • tolower
    • toupper


Functions_Lua

Allgemeine Lua-Funktionen

Datentypen

Im Referenzhandbuch für Lua 5.1 werden 8 vorhandene Basistypen aufgeführt:
nil, boolean, number, string, table, function, userdata und thread.
Dabei steht der Datentyp number sowohl für Integer- als auch Fließkommazahlen.
Letzteres ist in der hier implementierten Lua-Version anders, der Datentyp number steht hier ausschließlich für Ganzzahlen vom Typ int (signed und unsigned), während für die Fließkommazahlen noch der zusätzliche Datentyp float existiert. Der Datentyp boolean existiert dagegen nicht und wird emuliert, der Wert für true ist dabei vom Typ number und false ist gleich nil.
Somit gibt es für die Skripts in Darkstar One diese 8 Basisdatentypen:
nil, number, float, string, table, function, userdata und thread.

Vorsicht bei Vergleichen zwischen zwei Werten mit den ungleichen Datentypen number und float:
Bei den beiden Operatoren Gleich (==) und Ungleich (~=) werden bei Gleichheit der Werte falsche Ergebnisse geliefert und dürfen in diesem Fall nicht verwendet werden! Die anderen Operatoren (<, >, <=, >=) funktionieren dagegen korrekt. Man muss also entweder auf Kleiner (<) und Größer (>) prüfen oder wandelt den integer-Wert mit der Funktion lua.tofloat in eine Fließkommazahl um.

Beispiel:
local x = 0
local y = 0.0
local z = 0.1
-- Werte sind gleich:
if x == y then ...	-- Fehler, liefert false
if x ~= y then ...	-- Fehler, liefert true
-- Werte sind ungleich:
if x == z then ...	-- ist ok, liefert false
if x ~= z then ...	-- ist ok, liefert true

Am besten verzichtet man generell auf diese beiden Operatoren, wenn die Möglichkeit unterschiedlicher Datentypen gegeben ist.

Boolesche Algebra

Wichtig: Die logischen Verknüpfungen and und or kennen in der implementierten Lua-Version noch keine Rangfolge der Operatoren, weshalb das Setzen von Klammern sehr wichtig ist, da ansonsten falsche Ergebnisse geliefert werden können. Die im Lua 5.1 Referenzhandbuch, Kapitel 2.5.6 - Precedence, beschriebene Rangfolge gilt also in diesem Fall nicht für die hier verwendete Lua-Version.

Bei einem Ausdruck wie z.B.

A or B and C
hätte also die UND-Verknüpfung B and C keineswegs den allgemein üblichen Vorrang vor der ersten ODER-Verknüpfung, würde in der algebraisch korrekten Schreibweise wie folgt geschrieben werden und liefert auch genau dieses Ergebnis:
( A or B ) and C
Es entspricht somit auch:
( A and C ) or ( B and C )
...wobei hier die Klammern entfallen dürften, wenn die Rangfolge beachtet werden würde.

Soll nun die UND-Verknüpfung den ansonsten üblichen Vorrang vor der ODER-Verknüpfung haben, muss man diesen Teil vom Ausdruck in Klammern setzen, damit das gewünschte Ergebnis geliefert wird:

A or ( B and C )
Im Zweifelsfall sollte man also lieber ein Klammerpaar zu viel als zu wenig setzen, das produziert keinen zusätzlichen Binärcode und dient oftmals auch der besseren Lesbarkeit des Quellcodes vom Skript.

Bitweise Operationen (vgl. Bitweiser Operator) von Ganzzahlen sind hier mit den rein logischen Operatoren and, or und not leider nicht möglich. Zahlen werden immer als boolescher Wert true interpretiert, auch die Null ist true.

Tabellen

Im Kapitel 2.5.7 - Table Constructors des Lua Referenzhandbuchs ist für den Indexbereich von Tabellen die Untergrenze 1 angegeben, d.h., die Zählung der Array-Elemente beginnt standardmäßig bei 1. Eine Einstellmöglichkeit, um die Zählung bei 0 beginnen zu lassen, wie z.B. Option Base 0 von Visual Basic, gibt es in Lua nicht. Dennoch lässt sich der Index 0 für ein Datenfeld nutzen, muss dazu aber explizit eingefügt werden. Und nicht nur die 0, selbst negative Ganzzahlen dürfen in Lua für die Indicés genutzt werden.

Beispiel

-- Eine Standardtabelle mit 3 Feldern, der Indexbereich geht von 1 bis 3
V.Table = { "Element #1", "Element #2", "Element #3" }

-- Einen weiteren Eintrag an Index 0 einfügen, Indexbereich ist jetzt 0 bis 3
V.Table[0] = "Element #0"

-- Oder so, alles in einem Aufwasch:
V.Table = {
    [0] = "Element #0",
    [1] = "Element #1",
    [2] = "Element #2",
    [3] = "Element #3"
}

-- So gehts auch, erzeugt weniger Code. Man beachte das Semikolon:
V.Table = {
    [0] = "Element #0";
    "Element #1",
    "Element #2",
    "Element #3"
}

Die Tabelle enthält nun 4 Einträge. Ein Zugriff auf V.Table[4] löst jedoch einen Laufzeitfehler aus, da die Zählung jetzt bei 0 beginnt und der vierte Eintrag den Index 3 hat. Der letzte Eintrag ist hier also V.Table[3]. Dies muss man bei der Verwendung von Funktionen wie z.B. lua.sizeof berücksichtigen, die zurückgelieferte Anzahl der Einträge ist zwar mit 4 für dieses Beispiel korrekt, entspricht aber jetzt in lückenlosen Tabellen (also ohne nil-Werten darin) nicht mehr dem letzten Tabellenindex, man muss 1 davon abziehen. Oder man verwendet in dem Fall die Funktion lua.getn, welche den letzten Tabellenindex liefert.

-- Kopie mit einer einfachen for-Schleife in eine Standardtabelle mit dem Indexbereich von 1 bis 4
local tablecopy = {}
for i = 1, lua.sizeof( V.Table ) do
    tablecopy[i] = V.Table[i-1]
end

-- 1:1 Kopie; diese for-Variante berücksichtigt auch den Eintrag an Index 0 (Indicés 0 - 3)
for i, value in V.Table do
    tablecopy[i] = value
end

-- while-Schleife für eine 1:1 Kopie
local i = 0
while i < lua.sizeof( V.Table ) do
    tablecopy[i] = V.Table[i]
    i = i + 1
end

-- Gleiches mit repeat
local i = 0
repeat
    tablecopy[i] = V.Table[i]
    i = i + 1
until i == lua.sizeof( V.Table )

Die Tabelle darf auch rückwärts kopiert werden, die physikalische Position in der Tabelle ist nicht relevant, da immer nur auf den eingetragenen Index geachtet wird:

-- Auch hier eine 1:1 Kopie mit den Indicés von 0 bis 3
for i = lua.sizeof( V.Table )-1, 0, -1 do
    tablecopy[i] = V.Table[i]
end

-- Oder so, wieder in eine Standardtabelle von 1 - 4, ohne Schleife und ganz durcheinander
tablecopy[3] = V.Table[2]
tablecopy[1] = V.Table[0]
tablecopy[2] = V.Table[1]
tablecopy[4] = V.Table[3]

Beachten Sie auch, dass der Ausdruck lua.sizeof( V.Table ) in den Schleifen nur beim ersten Durchlauf berechnet wird. Es ist also nicht nötig, ihn vorher einer lokalen Variablen zuzuweisen, um diese dann für die Ende-Bedingung in der Schleife zu verwenden. Die Laufzeit würde dadurch nicht verkürzt.


lua

lua Funktionen

Die im Skriptsystem vorhandenen allgemeinen Lua-Funktionen.

call

Beispiel:

gc : table

Ist keine Funktion, sondern eine Tabelle. Wird für die Skript-Programmierung
nicht benötigt.

getglobals

Beispiel:

getn( table ) : number

Liefert die Größe einer Tabelle zurück, auch wenn nil-Werte darin
enthalten sind. Der übergebene Parameter "table" muss eine Tabelle sein, sonst
stürzt das Programm ab. Die Funktion zählt alle nil-Einträge innerhalb
der Tabelle mit, sodass die Tabellenindicés immer mit der tatsächlichen Position
des Wertes übereinstimmen. Der Index ist also nach einem nil nicht wie
bei der Funktion "lua.sizeof" verschoben, was bei der Abfrage in Schleifen von
großem Vorteil ist.
Hinweis: getn funktioniert nur
bei numerisch indizierten Tabellen. Feldnamen werden nicht mitgezählt.

Beispiel:
local size = lua.getn( Table )

getregistry

Beispiel:

max( var_1, var_2, ..., var_n ) : type( var_n )

Liefert den größten der übergebenen Werte zurück. Es dürfen sowohl Zahlen als
auch Strings übergeben werden, jedoch nicht gemischt, alle Variablen müssen vom
gleichen Datentyp sein. Somit ist auch eine lexikalische Auswahl möglich, die
Stringlänge spielt hierbei keine Rolle. Dabei gilt zu beachten, dass zwischen
Groß- und Kleinschreibung unterschieden wird, Kleinbuchstaben und Umlaute sind
also "größer" als Großbuchstaben. Das heißt, die Auswertung von Strings erfolgt
binär auf Basis des ANSI-Codes der einzelnen Zeichen.

Beispiel:
-- Liefert die 7 zurück
local max = lua.max( 6, 2, 5, 1, 7, 3, 4 )

-- Liefert "Bierdeckel" zurück
local max = lua.max( "BierDeckel", "Bierdeckel", "Aschaffenburg" )

min( var_1, var_2, ..., var_n ) : type( var_n )

Liefert den kleinsten der übergebenen Werte zurück, ansonsten gelten
dieselben Regeln wie bei max.

Beispiel:
-- Liefert die 1 zurück
local min = lua.min( 6, 2, 5, 1, 7, 3, 4 )

-- Liefert "Aschaffenburg" zurück
local min = lua.min( "BierDeckel", "Bierdeckel", "Aschaffenburg" )

pack

Beispiel:

rawget( table, index ) : type( table[ index ] )

Liefert aus der Tabelle table den Wert an der Position index.
Eine gesetzte Metatable wird dabei umgangen.

Beispiel:
V.Vector = { 0.0, 100.0, 5000.0 }
local posY = rawget( V.Vector, 2 )

rawset( table, index, value )

Setzt in der Tabelle table an der Position index den Wert
value. Eine gesetzte Metatable wird dabei umgangen.

Beispiel:
V.Vector = { 0.0, 100.0, 5000.0 }
-- Y-Position tiefer setzen
lua.rawset( V.Vector, 2, -50.0 )

setglobals

Beispiel:

sizeof( table ) : number

Liefert die Größe einer Tabelle zurück, auch wenn nil-Werte darin
enthalten sind. Der übergebene Parameter "table" muss eine Tabelle sein, sonst
stürzt das Programm ab. Die Funktion zählt die nil-Einträge innerhalb der
Tabelle nicht mit. Somit weichen die Tabellenindicés ab dem ersten
Vorkommen von nil von der tatsächlichen Position des Wertes in der
Tabelle ab. Dies muss man bei der Abfrage in Schleifen berücksichtigen, da es
ansonsten zu falschen Ergebnissen oder sogar zum Absturz kommen kann.

Hinweis: sizeof funktioniert im Gegensatz zu getn
mit beiden Tabellentypen, also bei numerisch und den über Feldnamen indizierten
Tabellen.

Beispiel:
local size = lua.sizeof( Table )

tag : table

Ist keine Funktion, sondern eine Tabelle. Wird für die Skript-Programmierung
nicht benötigt.

tofloat( var ) : float

Liefert var als Fließkommazahl zurück, falls möglich. Ist der
übergebene Wert schon vom Typ "float" oder "number",
wird er unverändert als "float" zurückgegeben. Stellt var
keine Zahl dar oder ist vom falschen Datentyp ("table", "function" usw.), gibt
die Funktion nil zurück. Ist oftmals für Vergleiche wichtig, da dabei auf
die Datentypen geachtet wird. Zum Beispiel würde ein Vergleich zwischen einer
Zahl vom Datentyp "string" und einer echten Zahl vom Typ "number" oder "float"
zum Absturz des Programms führen.

Beispiel:
-- Liefert die Fließkommazahl -123.456:
local str = "-123.456000"
local value = lua.tofloat( str )

-- Liefert den numerischen Wert 123 als "float" (123.0):
local value = lua.tofloat( 123 )
local value = lua.tofloat( "123" )
local value = lua.tofloat( "123.000" )

-- Die String-Variable in eine Fließkommazahl umwandeln, damit der Vergleich funktioniert:
local value1 = 123.456
local value2 = "123.456"
if value1 == lua.tofloat( value2 ) then
    machwas
end

tonumber( var ) : number

Liefert var als ganzzahligen numerischen Wert zurück, falls möglich.
Nachkommastellen von Fließkommazahlen werden abgeschnitten. Ist der übergebene
Wert schon vom Typ "number", wird er unverändert zurückgegeben.
Stellt var keine Zahl dar oder ist vom falschen Datentyp ("table",
"function" usw.), gibt die Funktion nil zurück. Ist oftmals für
Vergleiche wichtig, da dabei auf die Datentypen geachtet wird. Zum Beispiel
würde ein Vergleich zwischen einer Zahl vom Datentyp "string" und einer echten
Zahl vom Typ "number" oder "float" zum Absturz des Programms führen.

Beispiel:
-- Liefert den Integer-Wert -123
local str = "-123.456"
local value = lua.tonumber( str ) )

-- Liefert nil, weil der übergebene Wert...
-- ...keine Zahl ist
value = lua.tonumber( "1AFFE" )
-- ...eine Tabelle ist
value = lua.tonumber( { 1, 2, 3 } )
-- ...eine Funktion ist
value = lua.tonumber( NWing.Create )

tostring( var ) : string

Liefert einen beliebigen numerischen Wert als String zurück. Ist die Variable
bereits ein String, wird er unverändert zurückgeliefert.

Beispiel:
-- Ergebnis in str ist "45054" und "123.5"
local str = lua.tostring( 45054 )
local str = lua.tostring( 123.5 )

-- Zahl in String umwandeln, damit der Vergleich funktioniert:
local value1 = 123.456
local value2 = "123.456"
if lua.tostring( value1 ) == value2 then
    machwas
end

type( var ) : string

Liefert den Datentyp der übergebenen Variablen als String. Die möglichen
Werte sind: "nil", "float", "number",
"string", "boolean", "table",
"function", "thread" und "userdata". Der
Typ "number" ist eine Ganzzahl (int und unsigned int
in C).

Beispiel:
-- Nur ausführen, wenn der Wert eine Tabelle ist, sonst Absturz:
if lua.type( value ) == "table" then
    V.One = value[1]
    V.Two = value[2]
end

unpack

Beispiel:


math

math Funktionen

Die im Skriptsystem vorhandenen mathematischen Funktionen. Alle von diesen Funktionen zurückgegebenen Werte sind vom Datentyp "float", auch wenn Integer-Werte übergeben werden und das Ergebnis eine ganze Zahl ist.

Hinweis: Winkelwerte müssen den Winkelfunktionen immer im Bogenmaß Radiant übergeben werden und werden auch immer im Bogenmaß zurückgeliefert (mit Ausnahme der Konvertierungsfunktionen deg und rad natürlich).

Vorsicht bei Divisionen mit dem Operator "/" und Integer-Werten:
Sind sowohl der Dividend als auch der Divisor vom Datentyp "number", dann ist der errechnete Wert in diesem Fall ebenfalls immer vom Datentyp "number". Die Nachkommastellen werden also abgeschnitten, wenn das Ergebnis keine Ganzzahl ist! Eine Division von 9 / 2 beispielsweise ergibt 4. Gegebenenfalls vorher oder bei der Übergabe einen der beiden Werte mit der Funktion lua.tofloat in eine Fließkommazahl konvertieren.

Berechnung                  Ergebnis      Datentyp
local value = 9 / 2	--> value = 4     "number"
local value = 9.0 / 2	--> value = 4.5   "float"
local value = 9 / 2.0	--> value = 4.5   "float"
local value = 9.0 / 2.0	--> value = 4.5   "float"

Man kann das aber auch bei der Division zweier Integer-Werte in dem Fall nutzen, wenn man sowieso einen abgerundeten Wert vom Datentyp "number" im Ergebnis haben will oder muss, und sich so die Konvertierung mit der Funktion lua.tonumber spart.

abs( x ) : float

Liefert den Absolutwert einer Zahl.

Beispiel:

-- Eine Zufallszahl zwischen -40 und 60
local random = math.random() * 100 - 40
-- In positive Zahl umwandeln, falls negativ
local value = math.abs( random )

acos( x ) : float

Liefert den Arcus-Cosinus einer Zahl.

Beispiel:

result = math.acos( value )

asin( x ) : float

Liefert den Arcus-Sinus einer Zahl.

Beispiel:

result = math.asin( value )

atan( x ) : float

Liefert den Arcus-Tangens einer Zahl.

Beispiel:

result = math.atan( value )

atan2( x, y ) : float

Liefert den Arcus-Tangens aus der Division x/y. Es werden die Vorzeichen beider Parameter berücksichtigt, um den richtigen Quadranten des Ergebnisses zu finden. Die Funktion liefert auch dann ein korrektes Ergebnis, wenn y = 0 ist.

Beispiel:

-- Liefert den Azimutwinkel Phi eines 3D-Vektors im Bogenmaß
local Vector = { 1000, 0, -500 }
local Azimut = math.atan2( Vector[1], Vector[2] )

ceil( x ) : float

Rundet auf die nächsthöhere ganze Zahl auf.

Beispiel:

-- Liefert die 2.0
local value = math.ceil( 1.234567 )

cos( x ) : float

Liefert den Cosinus einer Zahl.

Beispiel:

-- Liefert den Cosinus von 20°
local radian = math.rad( 20 )
local result = math.cos( radian )

deg( radians ) : float

Rechnet das Bogenmaß Radiant in Grad um.

Beispiel:

-- Ein 180° Winkel
local angle = math.deg( math.pi )

exp( x ) : float

Liefert den Wert für ex.

Beispiel:

-- Liefert die Eulersche Zahl selbst
V.e = exp( 1 )

-- Liefert die Wurzel n√x
local result = math.exp( math.log( x ) / n )

floor( x ) : float

Rundet auf die nächstniedrigere ganze Zahl ab.

Beispiel:

-- Positive Zahl: Schneidet die Nachkommastellen ab, liefert 3.0
local value = math.floor( 3.141592 )
local value = math.floor( 3.999999 )

-- Negative Zahl: Schneidet die Nachkommastellen ab und subtrahiert 1, liefert 4.0
local value = math.floor( -3.141592 )
local value = math.floor( -3.999999 )

frexp( x ) : float( f ), float( e )

Diese Funktion liefert zwei Werte, einen Faktor und den Exponenten von x zur Basis 2.
Der zurückgelieferte Exponent ist immer ein ganzzahliger Wert (aber trotzdem vom Typ float) und gerade hoch genug, damit der Faktor kleiner als 1 wird.

Beispiel:

local x = 768
-- Liefert 0.75 in factor und 10.0 in exponent ( 768 = 0.75 * 2^10 = 3 * 2^8 )
local factor, exponent = math.frexp( x )

ldexp( f, e ) : float

Die Umkehrfunktion von frexp.

Beispiel:

local factor = 3
local exponent = 8
-- Liefert 768.0 ( = 3 * 2^8 )
local result = math.ldexp( factor, exponent )

length

Scheint in Darkstar One nicht zu funktionieren, liefert immer nil zurück.

Beispiel:

log( x ) : float

Liefert den natürlichen Logarithmus (Logarithmus zur Basis e) einer Zahl.

Beispiel:
-- Liefert xn
local result = math.exp( math.log( x ) * n )

log10( x ) : float

Liefert den Logarithmus zur Basis 10 einer Zahl.

Beispiel:
-- 100 = 102 -> Logarithmus ist 2
local exponent = math.log10( 100 )

mod( x, y ) : float

Liefert den ganzzahligen Rest aus der Division x/y. (Lua 5.1: fmod
)
Hinweis: Den Modulo-Operator % gibt es in der
hier verwendeten Lua-Version nicht.

Beispiel:
-- Der Rest ist 3
local value = math.mod( 11, 4 )

normalize

Möglicherweise eine Funktion, um Vektoren zu normalisieren. (Gibt es in Lua
5.1 nicht.)

Beispiel:

pi : float

Keine Funktion, sondern eine Konstante für die Kreiszahl Pi.

Beispiel:
-- Ein 90° Winkel im Bogenmaß
local angle = math.pi / 2.0

rad( degrees ) : float

Rechnet Grad in das Bogenmaß Radiant um.

Beispiel:
-- Ein 25° Winkel im Bogenmaß
local angle = math.rad( 25 )

random() : float

Liefert eine Fließkomma-Zufallszahl zwischen 0.0 und 1.0, also ohne
den Werten 0.0 und 1.0 selbst.

Beispiel:
-- Eine Fließkomma-Zufallszahl zwischen 10.0 und 100.0
local value_float = math.random() * 90.0 + 10.0

-- Eine ganzzahlige Zufallszahl von 10 bis 100 einschließlich 10 und 100
local value_int = lua.tonumber( math.random() * 91 + 10 )

randomseed( x )

Lässt bessere Zufallszahlen von math.random liefern. Da beim PC alles
berechnet wird, gibt es eigentlich keinen Zufall. Es wird also eine Reihe von
irgendwie berechneten Zahlen ausgegeben. Welche Reihe genommen wird, beeinflußt
randomseed. Geben wir hier eine Zahl x ein, so kommt bei
math.random eine andere Reihe zum Zug. Allerdings gilt hier auch: gleiche
Zahl, gleiches Ergebnis. Das einzig wirklich Zufällige ist die Uhrzeit, wann das
Programm gestartet wurde. Daher würde es sich anbieten, diese Zeit zu nehmen. Da
jedoch das dafür notwendige Lua-Paket "os" hier nicht implementiert ist,
können wir auch mit NGame.GetTime die reale Zeit seit Spielstart in
Sekunden nehmen. Der Spielstart ist der Zeitpunkt, an dem ein neues Spiel
begonnen wurde.

Beispiel:
-- Setzt eine neue Zufallsreihe für math.random
math.randomseed( NGame.GetTime({}).Time )

sin( x ) : float

Liefert den Sinus einer Zahl.

Beispiel:
-- Liefert den Sinus von 20°
local radian = math.rad( 20 )
local result = math.sin( radian )

sqrt( x ) : float

Liefert die Quadratwurzel einer Zahl.
Hinweis: Das
Gegenstück zur Wurzelfunktion, nämlich die Potenzfunktion "pow",
wurde im Skriptsystem leider nicht mit implementiert. Auch der
Exponential-Operator ^ fehlt hier. Das läßt sich jedoch mit den
Funktionen exp und log realisieren, ebenso wie Wurzeln höherer
Ordnung.

Beispiel:
-- Wurzel aus 2 = 1.414213
local value = math.sqrt( 2 )

tan( x ) : float

Liefert den Tangens einer Zahl.

Beispiel:
-- Liefert den Tangens von 20°
local radian = math.rad( 20 )
local result = math.tan( radian )


string

string Funktionen

Die im Skriptsystem vorhandenen Zeichenketten-Funktionen.

at

Könnte das Äquivalent zu "instr" in VB oder "pos" von Pascal sein.

Beispiel:

erase

Teile im String löschen?

Beispiel:

find

Beispiel:

find_first_of( s, char ) : number

Sucht im übergebenen String s nach dem ersten Vorkommen des Zeichens
char und liefert die gefundene Position zurück oder nil, wenn das
Zeichen nicht existiert. Die Zählung der Position beginnt bei 0, welche somit
dem ersten Zeichen von s entspricht. Die Übergabe eines Strings für
char sollte man vermeiden, da das nicht wie eigentlich erwartet
funktioniert und hierbei das Ergebnis etwas seltsam ist.
Die in
Lua 5.1 beschriebenen optionalen Parameter init und plain gibt es
hier nicht.

Beispiel:

find_last_of( s, char ) : number

Sucht im übergebenen String s nach dem letzten Vorkommen des Zeichens
char und liefert die gefundene Position zurück oder nil, wenn das
Zeichen nicht existiert. Die Zählung der Position beginnt bei 0, welche somit
dem ersten Zeichen von s entspricht. Die Übergabe eines Strings für
char sollte man vermeiden, da das nicht wie eigentlich erwartet
funktioniert und hierbei das Ergebnis etwas seltsam ist.
Die in
Lua 5.1 beschriebenen optionalen Parameter init und plain gibt es
hier nicht.

Beispiel:

format

Beispiel:

is_valid( s, ? ) : ?

Beispiel:

length( s ) : number

Liefert die Länge des Strings zurück. Zahlen (number und
float) werden auch als String interpretiert. (Lua 5.1: len
)
Hinweise:
Für den Datentyp "float" wird
immer die maximale Stringlänge von 18 (Vorzeichen, 10 Vorkommastellen,
Dezimalpunkt, 6 Nachkommastellen) zurückgegeben, führende und abschließende
Nullen werden also immer mitgezählt. Die Funktion ist somit für Fließkommazahlen
ungeeignet. Mit Ganzzahlen vom Typ "number" klappt es dagegen korrekt.

Den Längen-Operator # gibt es in der hier verwendeten
Lua-Version nicht.

Beispiel:
-- Liefert die Stringlänge 56
local text = "Guten Morgen liebe Sorgen, seid ihr auch schon alle da?!"
local size = string.length( text )

replace( s, pattern, repl ) : string

Ersetzt im übergebenen String s alle Vorkommen des Teilstrings
pattern mit dem String repl und liefert den geänderten String
zurück.

(Lua 5.1: gsub )

Beispiel:
-- Liefert in msg2 den String "IDM_GLOBAL_022_MSG"
local msg1 = "IDM_GLOBAL_023_RADIO_MSG"
local msg2 = string.replace( msg1, "23", "22" )

substr( s, i, j ) : string

Liefert einen Teilstring aus dem übergebenen String s, beginnend bei
i und mit der Länge j. (Lua 5.1: sub )
Die
Zählung von i startet mit 0, das erste Zeichen hat also den Index 0, das
zweite 1 usw. und das letzte den Index Stringlänge-1. Ist j negativ (der
Wert an sich ist egal) oder überschreitet das Stringende, wird ein Teilstring
von i bis zum Stringende zurückgegeben. Im Gegensatz zur in Lua 5.1
beschriebenen Funktion string.sub darf i nicht
negativ sein und j muss mit angegeben werden.

Beispiel:
local src = "ABCDEFGH 12345678"
local dst = ""

-- Liefert "DE"
dst = string.substr( src, 3, 2 )

-- Liefert "H 12345678", der negative Wert von j spielt keine Rolle
dst = string.substr( src, 7, -1 )

-- Liefert "12345678", die Positionen hinter dem Stringende werden ignoriert
dst = string.substr( src, 9, 15 )

-- und noch ein "Affe" :-)
local s0 = string.substr( src, 0, 1 )
local s1 = string.tolower( string.substr( src, 4, 1 ) )
local s2 = string.tolower( string.substr( src, 5, 1 ) )
dst = s0..s2..s2..s1

tokenize

Beispiel:

tolower( s ) : string

Liefert den String in Kleinbuchstaben umgewandelt zurück. (Lua 5.1: lower
)

Beispiel:
-- wird zu "hallo welt"
local lowercase = string.tolower( "Hallo Welt" )

toupper( s ) : string

Liefert den String in Großbuchstaben umgewandelt zurück. (Lua 5.1:
upper )

Beispiel:
-- wird zu "HALLO WELT"
local uppercase = string.toupper( "Hallo Welt" )


getLogic

"get" Funktionen

Mit diesen Funktionen können viele Werte direkt ausgelesen werden und ergänzen somit das Skriptsystem um weitere Möglichkeiten, die in den Namespaces teilweise nicht vorhanden sind. Einige gleichartige Funktionen existieren auch im Skriptsystem und sollten idR vorzugsweise verwendet werden, da sie meistens schneller arbeiten als die entsprechenden get-Funktionen (wie z.B. das Auslesen der Positionen von Schiffen und Orbitern).

Syntax: Funktionsabhängig, hier z.B. wird in beiden Fällen dasselbe Ergebnis geliefert:
    -- Einfach:
    V.Hull = get( "Logic.PlayerShip.hullCondition" )

    -- Umständlich:
    local player = get( "Logic.PlayerShip.id" )
    V.Hull = get( "Logic.StarShips."..player..".hullCondition" )
Die in spitzen Klammern angegebenen Einträge sind Variablen, die der Funktion übergeben werden müssen. Es dürfen dabei sowohl Id's als auch Handles übergeben werden. Man kann sie aber auch direkt einsetzen, wenn es sich um bekannte Fixwerte handelt.
Beispiel:
    -- Regierungsform des aktuellen Systems auslesen:
    local system = get( "Logic.PlayerShip.systemIndex" )
    local govern = get( "Logic.StarSystems."..system..".government" )

    -- Einfacher, wenn das System feststeht, hier das Sol-System:
    local govern = get( "Logic.StarSystems.29.government" )
Falls ein übergebener Wert ungültig ist, dann besteht die Möglichkeit, dass das Programm deswegen mit einem Laufzeitfehler abstürzt. Dies kann verhindert werden, indem der get-Funktion ein zweiter Parameter als Default-Wert übergeben wird. Dieser wird dann im Falle eines Fehlschlags der Funktion zurückgeliefert.
    -- Gibt es im System keinen Asteroiden, liefert die Funktion einen Radius von Null zurück:
    local object = MissionLib.GetSystemAsteroid()
    local radius = get( "Logic.Orbiter."..object..".radius", 0 )

    -- Löscht die Variable V.Boss, falls der Wing nicht mehr existiert:
    V.Boss = get( "Logic.Wings."..V.Wing..".leader", nil )

Clusters
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.Clusters."..<ClusterId>..".id" ) | unsigned int | CClusterHandle | Handle des Clusters
get( "Logic.Clusters."..<ClusterId>..".isActive" ) | userdata | true/false | Spieler ist gegenwärtig in diesem Cluster?
get( "Logic.Clusters."..<ClusterId>..".nation" ) | unsigned int | 0..5 | Volk, zu dem der Cluster gehört
get( "Logic.Clusters."..<ClusterId>..".posX" ) | float | n/a | X-Position auf der Karte in Lichtjahren
get( "Logic.Clusters."..<ClusterId>..".posY" ) | float | n/a | Y-Position auf der Karte in Lichtjahren
get( "Logic.Clusters."..<ClusterId>..".stars" ) | unsigned int | n/a | Anzahl der Sternsysteme im Cluster
Für <ClusterId> darf sowohl die Id (0..29) als auch das Handle des Clusters eingesetzt werden.

Orbiter
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.Orbiter" ) |  |  |
get( "Logic.Orbiter."..<Object>..".id" ) | unsigned int | CObjectHandle | Liefert das Handle eines Orbiters
get( "Logic.Orbiter."..<Object>..".iniindex" ) | unsigned int | n/a | Eindeutige Id eines Orbiters (Datensatzindex in Planets.ini)
get( "Logic.Orbiter."..<Object>..".orbiterart" ) | unsigned int | Orbiter-Typen | Liefert den Objekt-Typ eines Orbiters
get( "Logic.Orbiter."..<Object>..".objecttype" ) | unsigned int | Space-Typen | Liefert den Space-Typ eines Orbiters
get( "Logic.Orbiter."..<Object>..".posX" ) | float | n/a | X-Position eines Orbiters
get( "Logic.Orbiter."..<Object>..".posY" ) | float | n/a | Y-Position eines Orbiters
get( "Logic.Orbiter."..<Object>..".posZ" ) | float | n/a | Z-Position eines Orbiters
get( "Logic.Orbiter."..<Object>..".radius" ) | float | n/a | Radius der Hüllkugel eines Orbiters

Player
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.Player.credits" ) | unsigned int | n/a | Kontostand des Spielers
get( "Logic.Player.fragcounter" ) | unsigned int | n/a | Anzahl aller abgeschossenen Schiffe
get( "Logic.Player.isPirateFriend" ) | unsigned int | n/a | > 0, wenn der Spieler zu Piraten freundlich eingestellt ist
get( "Logic.Player.raidcounter" ) | unsigned int | n/a | Anzahl der Raubüberfälle auf Frachter
get( "Logic.Player.wealth" ) | unsigned int | n/a | Wohlstandsindex des Spielers (testen)

PlayerShip
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.PlayerShip.actDrones" ) * | unsigned int | 0..3 | Anzahl der aktiven Frachtdrohnen (geschleppte Container)
get( "Logic.PlayerShip.clusterId" ) | unsigned int | CClusterHandle | Handle des aktuellen Clusters.
get( "Logic.PlayerShip.clusterId" ) - 2490368 | unsigned int | 0..29 | Durch Subtraktion von 2490368 erhält man die Id des Clusters
get( "Logic.PlayerShip.hangar" ) * | unsigned int | CObjectHandle | Handle des Hangars, in welchem die DSO gelandet ist. Identisch mit den Objekthandles von Handels- und Forschungsstationen, Asteroiden und großen Kreuzern.
get( "Logic.PlayerShip.hullCondition" ) | float | 0.0..1.0 | Rumpfzustand des Spielerschiffs (0..100%)
get( "Logic.PlayerShip.hyperJumpDest" ) * | unsigned int | 0..402 | SystemId des markierten Sprungziels. > 402, wenn kein Ziel markiert ist
get( "Logic.PlayerShip.id" ) | unsigned int | CStarShipHandle | Handle des Spielerschiffs
get( "Logic.PlayerShip.level" ) * | unsigned int | 0..30 | Mit den gesammelten Artefakten erreichbare Schiffsstufe. Kann höher als die tatsächliche Stufe sein, wenn die Artefakte noch nicht für mögliche Upgrades verwendet wurden.
get( "Logic.PlayerShip.maxDrones" ) | unsigned int | 1..3 | Anzahl der Frachtdrohnen (Containerhaken gesamt)
get( "Logic.PlayerShip.scan" ) | unsigned int | 0..3 | 0: das Spielerschiff darf gescannt werden 1: Polizei ist unterwegs 2: Schiff wurde gescannt und Schmuggelware gefunden 3: Scan auf illegale Ware wurde erfolgreich gestört
get( "Logic.PlayerShip.selection" ) * | unsigned int | CObjectHandle | Handle des selektierten Objekts
get( "Logic.PlayerShip.shieldConditionBack" ) | float | 0.0..1.0 | Schildzustand des Spielerschiffs hinten (0..100%)
get( "Logic.PlayerShip.shieldConditionFront" ) | float | 0.0..1.0 | Schildzustand des Spielerschiffs vorne (0..100%)
get( "Logic.PlayerShip.shipFrontX" ) | float | n/a | X-Ausrichtung des Spielerschiffs
get( "Logic.PlayerShip.shipFrontY" ) | float | n/a | Y-Ausrichtung des Spielerschiffs
get( "Logic.PlayerShip.shipFrontZ" ) | float | n/a | Z-Ausrichtung des Spielerschiffs
get( "Logic.PlayerShip.shipPosX" ) | float | n/a | X-Position des Spielerschiffs
get( "Logic.PlayerShip.shipPosY" ) | float | n/a | Y-Position des Spielerschiffs
get( "Logic.PlayerShip.shipPosZ" ) | float | n/a | Z-Position des Spielerschiffs
get( "Logic.PlayerShip.shipSpeed" ) | float | >= 0.0 | 4.0 = 100%, Geschwindigkeit des Spielerschiffs. Rückwärtsschub ist ebenfalls ein positiver Wert.
get( "Logic.PlayerShip.shipType" ) | unsigned int | 0 | Liefert den Typ des Spielerschiffs, ist immer ST_PLAYERSHIP.
get( "Logic.PlayerShip.systemId" ) | unsigned int | CStarHandle | Handle des aktuellen Systems
get( "Logic.PlayerShip.systemIndex" ) * | unsigned int | 0..402 | Index (SystemId) des aktuellen Systems
get( "Logic.PlayerShip.usedUpgrades" ) * | unsigned int | 0..30 | Aktuelle Schiffsstufe des Spielerschiffs, entspricht dem tatsächlichen Level des Schiffs ohne durch gesammelte Artefakte evtl. mögliche Upgrades.
get( "Logic.PlayerShip.wingId" ) | unsigned int | CWingHandle | Handle vom Wing des Spielerschiffs. Ist der Spieler in keinem Wing, hat das Handle den (ungültigen) Wert 720896.
Diese Funktionen sollte man nicht im ENTER_PREFADE-Event von "System" verwenden, da sie hier falsche oder ungültige Werte liefern könnten!
* Auch mit StarShips getestet, geht leider nicht (Absturz).

StarFinder
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.StarFinder.result" ) | unsigned int | CStarHandle | Liefert das SystemHandle, falls Starfinder ein System mit den angegebenen Kriterien gefunden hat, andernfalls 0. Siehe MissionLib.FindSystem.

StarShips
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.StarShips."..<ShipId> ) | userdata | true/false | Prüft das Vorhandensein eines Schiffs
get( "Logic.StarShips."..<ShipId>..".clusterId" ) | unsigned int | CClusterHandle | Handle des aktuellen Clusters.
get( "Logic.StarShips."..<ShipId>..".freeSlots" ) | unsigned int | 0..45 | Anzahl der freien Containerplätze von Frachtern. Liefert für andere Schiffe immer 0.
get( "Logic.StarShips."..<ShipId>..".hullCondition" ) | float | 0.0..1.0 | Rumpfzustand eines Schiffs (0..100%)
get( "Logic.StarShips."..<ShipId>..".id" ) | unsigned int | CStarShipHandle | Handle des Schiffs (dasselbe wie <ShipId>)
get( "Logic.StarShips."..<ShipId>..".maxDrones" ) | unsigned int | 0 | Anzahl der Frachtdrohnen, ist leider immer 0.
get( "Logic.StarShips."..<ShipId>..".race" ) | unsigned int | 0..6 | Volk, zu dem das Schiff gehört
get( "Logic.StarShips."..<ShipId>..".scan" ) | unsigned int | 0..3 | 0 = das Schiff darf gescannt werden 1 = Polizist ist unterwegs 2 = das Schiff wurde gescannt 3 = Polizei darf scannen aber wird nie fündig?
get( "Logic.StarShips."..<ShipId>..".shieldConditionBack" ) | float | 0.0..1.0 | Schildzustand eines Schiffs hinten (0..100%)
get( "Logic.StarShips."..<ShipId>..".shieldConditionFront" ) | float | 0.0..1.0 | Schildzustand eines Schiffs vorne (0..100%)
get( "Logic.StarShips."..<ShipId>..".shipFrontX" ) | float | n/a | X-Ausrichtung eines bestimmten Schiffs
get( "Logic.StarShips."..<ShipId>..".shipFrontY" ) | float | n/a | Y-Ausrichtung eines bestimmten Schiffs
get( "Logic.StarShips."..<ShipId>..".shipFrontZ" ) | float | n/a | Z-Ausrichtung eines bestimmten Schiffs
get( "Logic.StarShips."..<ShipId>..".shipPosX" ) | float | n/a | X-Position eines bestimmten Schiffs
get( "Logic.StarShips."..<ShipId>..".shipPosY" ) | float | n/a | Y-Position eines bestimmten Schiffs
get( "Logic.StarShips."..<ShipId>..".shipPosZ" ) | float | n/a | Z-Position eines bestimmten Schiffs
get( "Logic.StarShips."..<ShipId>..".shipSpeed" ) | float | >= 0.0 | 4.0 = 100%, Geschwindigkeit eines Schiffs. Rückwärtsschub ist ebenfalls ein positiver Wert.
get( "Logic.StarShips."..<ShipId>..".shipType" ) | unsigned int | n/a | Liefert den Typ eines Wings oder Schiffs
get( "Logic.StarShips."..<ShipId>..".systemId" ) | unsigned int | CStarHandle | Handle des aktuellen Systems
get( "Logic.StarShips."..<ShipId>..".wingId" ) | unsigned int | CWingHandle | Handle vom Wing des Schiffs. Ist das Schiff in keinem Wing, hat das Handle den Wert 720896.

StarSystems
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.StarSystems."..<SystemId>..".artefact" ) | unsigned int | 0, 2, 6, 8 | Prüft, ob im System ein Artefakt liegt
get( "Logic.StarSystems."..<SystemId>..".clusterId" ) | unsigned int | CClusterHandle | Handle vom Cluster des Systems
get( "Logic.StarSystems."..<SystemId>..".clusterId" ) - 2490368 | unsigned int | 0..29 | ClusterId des Systems = Handle - 2490368
get( "Logic.StarSystems."..<SystemId>..".economy" ) | unsigned int | 0..5 | Wirtschaft des Systems
get( "Logic.StarSystems."..<SystemId>..".faction" ) | unsigned int | 0..2 | Fraktion des Systems
get( "Logic.StarSystems."..<SystemId>..".gangcounter" ) | unsigned int | n/a | Anzahl der Vernichtungen der ansässigen Gang
get( "Logic.StarSystems."..<SystemId>..".gangid" ) | unsigned int | 0..65535 | ID der ansässigen Gang, 65535 = keine
get( "Logic.StarSystems."..<SystemId>..".goods"..<Index> ) | unsigned int | n/a | Warenmenge im System (Index = 0..23)
get( "Logic.StarSystems."..<SystemId>..".government" ) | unsigned int | 0..5 | Regierungsform des Systems
get( "Logic.StarSystems."..<SystemId>..".id" ) | unsigned int | CStarHandle | Handle des Systems
get( "Logic.StarSystems."..<SystemId>..".isActive" ) | bool | n/a | Spieler ist gegenwärtig in diesem System
get( "Logic.StarSystems."..<SystemId>..".isActiveMission" ) | bool | n/a | Prüft, ob im System eine Mission aktiv ist
get( "Logic.StarSystems."..<SystemId>..".nation" ) | unsigned int | 0..5 | Volk, zu dem das System gehört
get( "Logic.StarSystems."..<SystemId>..".posX" ) | float | n/a | X-Position auf der Karte in Lichtjahren
get( "Logic.StarSystems."..<SystemId>..".posY" ) | float | n/a | Y-Position auf der Karte in Lichtjahren
get( "Logic.StarSystems."..<SystemId>..".siege" ) | bool | n/a | Von Piraten besetztes System
get( "Logic.StarSystems."..<SystemId>..".wealth" ) | unsigned int | 0..2 | Lebensstandard (Wohlstand) des Systems
get( "Logic.StarSystems.PlayerShip.clusterId" ) | unsigned int | CClusterHandle | Handle des aktuellen Clusters
get( "Logic.StarSystems.PlayerShip.clusterId" ) - 2490368 | unsigned int | 0..29 | Id des aktuellen Clusters
Für <SystemId> darf sowohl die Id (0..402) als auch das Handle des Sternsystems eingesetzt werden.
Dasselbe gilt auch für fast alle entsprechenden Funktionen des Namespaces NStarSystem im Skriptsystem.

Wings
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Logic.Wings."..<WingId>..".count" ) | unsigned int | 1..11 | Anzahl der Schiffe im Wing
get( "Logic.Wings."..<WingId>..".leader" ) | unsigned int | CStarShipHandle | Handle vom Wingleader
get( "Logic.Wings."..<WingId>..".ship"..<Index> ) | unsigned int | CStarShipHandle | Handle vom Wingman (1..10), 0 für Leader geht nicht
get( "Logic.Wings."..<WingId>..".ship1" ) | unsigned int | CStarShipHandle | Handle vom ersten Wingman, ".ship0" geht nicht

Startwerte (Gameplay-Einstellungen aus der Datei config.bin)
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Startwerte.Application.Color32" ) | bool | n/a |
get( "Startwerte.Application.Difficulty" ) | unsigned int | 0..4 | Schwierigkeitsgrad (Anzeigewert-1)
get( "Startwerte.Application.FSAA" ) | unsigned int |  | Antialiasing -> aus | 2x | 4x
get( "Startwerte.Application.FullScreen" ) | bool | n/a | Vollbild aus/ein
get( "Startwerte.Application.GameClient.Effects" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.Height" ) | unsigned int |  | Höhe des Anwendungsfensters
get( "Startwerte.Application.GameClient.MenuStar" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.Objects" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.Quality" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.Resolution" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.SpeakerConfig" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.SpeakerDefinition" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.Textures" ) | unsigned int |  |
get( "Startwerte.Application.GameClient.VolumeAll" ) | float |  |
get( "Startwerte.Application.GameClient.VolumeAtmo" ) | float |  |
get( "Startwerte.Application.GameClient.VolumeMusic" ) | float |  |
get( "Startwerte.Application.GameClient.VolumeSfx" ) | float |  |
get( "Startwerte.Application.GameClient.VolumeUi" ) | float |  |
get( "Startwerte.Application.GameClient.VolumeVideo" ) | float |  |
get( "Startwerte.Application.GameClient.VolumeVoice" ) | float |  |
get( "Startwerte.Application.GameClient.Width" ) | unsigned int |  | Breite des Anwendungsfensters
get( "Startwerte.Application.guid1" ) | unsigned int |  |
get( "Startwerte.Application.guid2" ) | unsigned int |  |
get( "Startwerte.Application.guid3" ) | unsigned int |  |
get( "Startwerte.Application.guid4_0" ) | unsigned int |  |
get( "Startwerte.Application.guid4_1" ) | unsigned int |  |
get( "Startwerte.Application.guid4_2" ) | unsigned int |  |
get( "Startwerte.Application.guid4_3" ) | unsigned int |  |
get( "Startwerte.Application.guid4_4" ) | unsigned int |  |
get( "Startwerte.Application.guid4_5" ) | unsigned int |  |
get( "Startwerte.Application.guid4_6" ) | unsigned int |  |
get( "Startwerte.Application.guid4_7" ) | unsigned int |  |
get( "Startwerte.Application.InvertX" ) |  |  | on my controler it is the left stick (left-right axis)
get( "Startwerte.Application.InvertY" ) |  |  | on my controler it is the left stick (up-down axis)
get( "Startwerte.Application.InvertZ" ) |  |  | on my controler it is the right stick (left-right axis)
get( "Startwerte.Application.JoystickSense" ) |  |  |
get( "Startwerte.Application.Language" ) | unsigned int |  |
get( "Startwerte.Application.PlayHitSound" ) |  |  |
get( "Startwerte.Application.ReverseYAxis" ) | bool | n/a | on my controler it is the right stick (up-down axis)
get( "Startwerte.Application.RudderX" ) | unsigned int |  | it may be "00 00 00 01" for use it and "00 00 00 00" for don't use it.
get( "Startwerte.Application.RudderY" ) | unsigned int |  | it may be "00 00 00 01" for use it and "00 00 00 00" for don't use it.
get( "Startwerte.Application.RudderZ" ) | unsigned int |  | it may be "00 00 00 01" for use it and "00 00 00 00" for don't use it.
get( "Startwerte.Application.Rumble" ) | unsigned int |  | it may be "00 00 00 01" for use it and "00 00 00 00" for don't use it.
get( "Startwerte.Application.Shadows" ) | bool | n/a | Schatten aus/ein
get( "Startwerte.Application.Slider1" ) | unsigned int |  | it may be "00 00 00 01" for use it and "00 00 00 00" for don't use it.
get( "Startwerte.Application.Slider2" ) | unsigned int |  | it may be "00 00 00 01" for use it and "00 00 00 00" for don't use it.
get( "Startwerte.Application.SubRadio" ) |  |  |
get( "Startwerte.Application.SubVideo" ) |  |  |
get( "Startwerte.Application.Tooltips" ) |  |  |
get( "Startwerte.Application.UseJoystick" ) |  |  |
get( "Startwerte.Application.UseSound" ) |  |  |

Walhalla
Funktion | Datentyp | Wertebereich | Beschreibung
get( "Walhalla.WorldManager.Default._HdrPostProcess_.FogEnable" ) | bool | 0..1 | Effekte für Tunnelmissionen
get( "Walhalla.WorldManager.Default._HdrPostProcess_.FogEnd" ) | unsigned int | n/a |
get( "Walhalla.WorldManager.Default._HdrPostProcess_.FogIntensity" ) | float | n/a |
get( "Walhalla.WorldManager.Default._HdrPostProcess_.FogStart" ) | unsigned int | n/a |
get( "Walhalla.WorldManager.Default._HdrPostProcess_.Blurriness" ) | float | n/a |
get( "Walhalla.WorldManager.Default._HdrPostProcess_.MotionBlurIntensity" ) | float | n/a |


setLogic

"set" Funktionen

Mit diesen Funktionen können viele Werte direkt gesetzt werden und ergänzen somit das Skriptsystem um weitere Möglichkeiten, die in den Namespaces teilweise nicht vorhanden sind.

Player
Funktion | Datentyp | Wertebereich | Beschreibung
set( "Logic.Player.credits", value ) | unsigned int | n/a | Kontostand des Spielers ändern

PlayerShip
Funktion | Datentyp | Wertebereich | Beschreibung
set( "Logic.PlayerShip.hullCondition", value ) | float | 0.0..1.0 | Angezeigten Rumpfzustand des Spielerschiffs ändern (0..100%). Hat bei der Darkstar One keine Auswirkung auf den tatsächlichen Zustand.
set( "Logic.PlayerShip.shieldConditionBack", value ) | float | 0.0..1.0 | Angezeigten Schildzustand des Spielerschiffs hinten ändern (0..100%. Hat bei der Darkstar One keine Auswirkung auf den tatsächlichen Zustand.
set( "Logic.PlayerShip.shieldConditionFront", value ) | float | 0.0..1.0 | Angezeigten Schildzustand des Spielerschiffs vorne ändern (0..100%). Hat bei der Darkstar One keine Auswirkung auf den tatsächlichen Zustand.
set( "Logic.PlayerShip.scan", value ) | unsigned int | 0..3 | 0: das Spielerschiff soll gescannt werden 1: Polizist ist unterwegs 2: das Schiff wurde gescannt 3: Scan auf illegale Ware wurde erfolgreich gestört

StarFinder
Funktion | Datentyp | Wertebereich | Beschreibung
set( "Logic.StarFinder.param", value ) | unsigned int | 0..3 | Sichtbarkeitsklasse des Systems. Muss immer zuerst gesetzt werden!
set( "Logic.StarFinder.active", value ) | unsigned int | >= 0 | Schließt das aktive System von der Suche aus, wenn ungleich Null.
set( "Logic.StarFinder.crime", value ) | float | 0.0..5.0 | Kriminalitätspunkte des Spielers im System.
set( "Logic.StarFinder.economy", value ) | unsigned int | 0..5 | Wirtschaft des Systems.
set( "Logic.StarFinder.faction", value ) | unsigned int | 0..2 | Fraktion des Systems.
set( "Logic.StarFinder.gouvern", value ) | unsigned int | 0..5 | Regierungsform des Systems.
set( "Logic.StarFinder.jump", value ) | unsigned int | >= 0 | Ignoriert alle Systeme, die nicht mit einem Sprung erreicht werden können, wenn größer als Null.
set( "Logic.StarFinder.max_sys", value ) | unsigned int | - | Undokumentiert, aber vorhanden, Programm stürzt jedoch beim Aufruf ab.
set( "Logic.StarFinder.offset", value ) | unsigned int | >= 0 | Maximaler Wert, um den die SystemId variieren darf. Trotzdem sucht FindSystem nur im gegenwärtigen Cluster.
set( "Logic.StarFinder.orbiter", value ) | unsigned int | 0..15 | Orbitertyp im System.
set( "Logic.StarFinder.wealth", value ) | unsigned int | 0..2 | Wohlstand des Systems.
get( "Logic.StarFinder.result" ) | unsigned int | n/a | Liefert das Systemhandle, falls der Starfinder ein System mit den in set angegebenen Kriterien gefunden hat. Siehe auch MissionLib.FindSystem.

StarShips
Funktion | Datentyp | Wertebereich | Beschreibung
set( "Logic.StarShips."..<ShipId>..".hullCondition", value ) | float | 0.0..1.0 | Rumpfzustand eines Schiffs ändern (0..100%)
set( "Logic.StarShips."..<ShipId>..".shieldConditionBack", value ) | float | 0.0..1.0 | Schildzustand eines Schiffs hinten ändern
set( "Logic.StarShips."..<ShipId>..".shieldConditionFront", value ) | float | 0.0..1.0 | Schildzustand eines Schiffs vorne ändern

StarSystems
Funktion | Datentyp | Wertebereich | Beschreibung
set( "Logic.StarSystems."..<SystemId>..".gangid", value ) | unsigned int | 0..65535 | Setzt eine GangId für das System, 65535=keine Gang

Walhalla
Funktion | Datentyp | Wertebereich | Beschreibung
set( "Walhalla.WorldManager.Default._HdrPostProcess_.FogEnable", value ) | bool | 0..1 | Effekte für Tunnelmissionen
set( "Walhalla.WorldManager.Default._HdrPostProcess_.FogEnd", value ) | unsigned int | n/a |
set( "Walhalla.WorldManager.Default._HdrPostProcess_.FogIntensity", value ) | float | n/a |
set( "Walhalla.WorldManager.Default._HdrPostProcess_.FogStart", value ) | unsigned int | n/a |
set( "Walhalla.WorldManager.Default._HdrPostProcess_.Blurriness", value ) | float | n/a |
set( "Walhalla.WorldManager.Default._HdrPostProcess_.MotionBlurIntensity", value ) | float | n/a |


listLogic

"list" Funktionen

In Vorbereitung


BattleLib

Die Skriptbibliothek "BattleLib.lua" ist in der Installation frei zugänglich und beinhaltet eine Vielzahl von hilfreichen Zusatzfunktionen für die Erzeugung großer Schlachtfelder.

Tipp: Wem die Flakmissionen zu schwer sind, kann die BattleLib.lua so modifizieren, dass jene beiden Missionen entschärft werden. Wie das genau funktioniert, wird im Supernature-Forum im Thema Darkstar One - Flakmissions-Patch ausführlich beschrieben. Weitere Tipps und Tools, nicht nur für die Flakmission, können im Thema Gameplay FAQ nachgelesen und heruntergeladen werden.

Quellcode der BattleLib.lua
--------------------------------------------------------------------------------
-- Dark Star One (TM) - Script library
-- Copyright (C) Ascaron Entertainment GmbH
-- All Rights Reserved.
------------------------------[ Info ]------------------------------------------
-- Author: Peter Grimsehl
-- Build Version 2.7 by [SNF]Norbert
------------------------------[ Description ]-----------------------------------
-- Utility functions for instantiating large battles
------------------------------[ Notes (nk) ]------------------------------------
-- XWing Modifikation eingebaut, damit keine unerwünschten Superfrachter erzeugt
-- werden, falls sie in der StarShip.ini definiert wurden. Damit diese Änderung
-- funktioniert, muss die MissionLibEx.lua unbedingt auch in der MissionLib.lua
-- eingebunden worden sein.
-- Wo eine Verwechslung von Bezeichnern und Handles bei der Parameterübergabe
-- möglich ist, wurden die Variablennamen so geändert, dass man sie leichter
-- voneinander unterscheiden kann. Beispiel:
--   sWing -> Präfix "s" = Bezeichner (string, z.B. "WingA0" )
--   pWing -> Präfix "p" = Handlewert (pointer bzw. unsigned int)
------------------------------[ Import ]----------------------------------------

source "lua/mission/MissionLib.lua"	-- Verschiedene Hilfsfunktionen
source "lua/mission/CameraLib.lua"	-- Zusätzliche Kameras

------------------------------[ Collection ]------------------------------------

BattleLib = {}

--------------------------------------------------------------------------------

-- Erzeugt ein Schlachtfeld
BattleLib.CreateBG = function( Data )
    return {
        Wings  = {},
        Defs   = Data.Defs,
        Center = Data.Center,
        Groups = NGroupAi.Create({}),
        Player = get( PLAYER_SHIP_ID )
    }
end

-- Aktualisiert die Gegnerliste von 'sWing' und trägt aktuelle Handles der Feinde ein. In die Gegnerlisten
-- aller anderen erzeugten Wings wird das Handle von 'sWing' eingetragen, falls er als Feind aufgeführt ist.
-- Im Gegensatz zur originalen Version werden bereits eingetragene Gegner nicht mehrfach aktualisiert.
BattleLib.UpdateEnemies = function( BG, sWing )
    local bgWings  = BG.Wings
    local pWing    = bgWings[sWing]
    local AddEnemy = NWing.AddEnemy
    for name, def in BG.Defs do
        if def.Enemies then
            -- Zuerst schauen, ob es 'sWing' ist und die eigene Feindliste aktualisieren
            if name == sWing then
                for i, enemy in def.Enemies do
                    local target = enemy.Target
                    if bgWings[target] then
                        AddEnemy( {
                            Wing = pWing,
                            Target = bgWings[target],
                            Priority = enemy.Priority
                        } )
                    elseif target == "Player" then
                        AddEnemy( {
                            Wing = pWing,
                            Target = BG.Player,
                            Priority = enemy.Priority
                        } )
                    elseif target == "ActionTurret" then
                        AddEnemy( {
                            Wing = pWing,
                            Target = NObject.GetActionTurret({}).Handle,
                            Priority = enemy.Priority
                        } )
                    end
                end
            -- Es ist ein anderer Wing, prüfen, ob 'sWing' dort als Feind eingetragen werden soll
            elseif bgWings[name] then
                for i, enemy in def.Enemies do
                    if enemy.Target == sWing then
                        AddEnemy( {
                            Wing = bgWings[name],
                            Target = pWing,
                            Priority = enemy.Priority
                        } )
                        break
                    end
                end
            end
        end
    end
end

-- Entfernt einen Wing aus der Wingliste
BattleLib.UpdateWingList = function( BG, pWing )
    for sWing, wing in BG.Wings do
        if wing == pWing then
            BG.Wings[sWing] = nil
            return
        end
    end
end

-- Erzeugt einen Wing anhand einer Wingdefinition
BattleLib.CreateWing = function( BG, Data )
    local sWing = Data.WingId
    local pWing = BG.Wings[sWing]
    local wingDef = BG.Defs[sWing]

    -- Abbruch, wenn der Wing schon vorhanden ist oder nicht definiert wurde
    if pWing or not wingDef then return; end

    local restore = Data.Restore
    local create = wingDef.Create
    if not create then
        create = wingDef.Define
    end

    local temp = MissionLib.CopyTable( create )

    -- Früheren Wing an bestimmter Position wiederherstellen
    if restore then
        temp.PosType = POSDESCR_EXPLICIT
        temp.Position = restore.Position
        if restore.Number then
            temp.Number = restore.Number
        end

    -- Start aus einem Hangar oder Erzeugung neben einem Wing
    elseif create.Object then
        local object = create.Object
        local wing = BG.Wings[object]
        if wing then
            if create.Distance then
                -- POSDESCR_WINGDISTANCE: Erzeugung neben einem Wing
                temp.Object = wing
            else
                -- POSDESCR_HANGAR: Start aus einem Kreuzer, nur HUNTER- und MILITARY-Wings!
                temp.Object = get( "Logic.Wings."..wing..".leader" )
            end
        elseif object == "TradeStation" then
            temp.Object = MissionLib.GetSystemTradeStation()
        elseif object == "ResearchStation" then
            temp.Object = MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
        elseif object == "Asteroid" then
            temp.Object = MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
        -- Prüfen, ob Handle eines Asteroiden oder einer Station
        elseif not MissionLib.IsStation( object ) then
            -- Wing kann hier nicht erzeugt werden, Objekt mit Hangar nicht vorhanden
            return
        end

    -- Erzeugung an einer Position, BG Koordinaten in absolute Koordinaten umrechnen
    elseif create.Position and not wingDef.Absolute then
        temp.Position = MissionLib.AddVector( BG.Center, create.Position )
    end

    if wingDef.Define then
        -- Level oder LevelOffset in alle Schiffe eintragen, Level hat Priorität
        local level
        if create.Level then
            level = "Level"
        elseif create.LevelOffset then
            level = "LevelOffset"
        end
        if level then
            local value = create[level]
            for i, ship in temp.Ships do
                ship[level] = value
            end
        end
        -- Wing erzeugen
        pWing = NWing.Define( temp ).Wing
    else
        -- neue XWing-Funktion zur Vermeidung unerwünschter Superfrachter verwenden
        pWing = XWing.Create( temp ).Wing
    end

    -- Neuen Wing in den Battleground eintragen
    BG.Wings[sWing] = pWing

    -- Zusätzliche Feindtypen eintragen
    if wingDef.EnemyTypes then
        for i, shiptype in wingDef.EnemyTypes do
            NWing.SetInvalidEnemy( { Wing = pWing, TypeId = shiptype, Set = 0 } )
        end
    end

    -- Feindlisten aller erzeugten Wings aktualisieren
    BattleLib.UpdateEnemies( BG, sWing )

    -- Einmal die Liste aller Schiffe des Wings ermitteln
    local shiplist = NWing.List( { Wing = pWing } ).ShipList
    local pLeader = shiplist[1]

    -- Spielerstatus
    local player = Data.Player
    if player then
        if player == "enemy" then
            -- Spieler soll sofort feindlich sein
            NWing.AddEnemy( { Wing = pWing, Target = BG.Player } )
        elseif player == "friend" then
            -- Spielerbeschuss wird weniger ernst genommen
            for i, ship in shiplist do
                NShip.SetPlayerFriend( { Ship = ship, Set = 1 } )
            end
        elseif player == "invalid" then
            -- Spieler wird niemals feindlich
            NWing.SetInvalidEnemy( { Wing = pWing, TypeId = ST_PLAYERSHIP } )
        end
    end

    -- Gruppenzugehörigkeit
    if wingDef.Group and BG.Groups then
        NGroupAi.AddWings( { Group = BG.Groups[wingDef.Group], WingList = { pWing } } )
    end

    -- Schiffe markieren
    local marker = wingDef.Marker
    if marker then
        if marker == "all" then
            -- Alle Schiffe markieren
            NObject.SetMissionFlag( { Object = pWing, Set = 1 } )
        elseif lua.type( marker ) == "table" then
            -- Bestimmte Schiffe markieren
            for i, flag in marker do
                if flag > 0 and shiplist[i] then
                    NObject.SetMissionFlag( { Object = shiplist[i], Set = 1 } )
                end
            end
        else
            -- Schiffe von 1 bis n markieren, true markiert nur das erste Schiff
            for i = 1, marker do
                if shiplist[i] then
                    NObject.SetMissionFlag( { Object = shiplist[i], Set = 1 } )
                end
            end
        end
    end

    -- Boss
    local boss = wingDef.BossId
    if boss then
        if boss == "all" then
            -- Alle Schiffe als Boss setzen
            for i, ship in shiplist do
                NShip.SetBoss( { Ship = ship, BossId = 1 } )
            end
        elseif lua.type( boss ) == "table" then
            -- Bestimmte Schiffe als Boss setzen
            for i, id in boss do
                if id > 0 and shiplist[i] then
                    NShip.SetBoss( { Ship = shiplist[i], BossId = 1 } )
                end
            end
        else
            -- Schiffe von 1 bis n als Boss setzen
            for i = 1, boss do
                if shiplist[i] then
                    NShip.SetBoss( { Ship = shiplist[i], BossId = 1 } )
                end
            end
        end
    end

    -- Strafpunkte bei Beschuss
    if wingDef.Crime then
        for i, ship in shiplist do
            NShip.SetCrime( { Ship = ship, Set = 1 } )
        end
    end

    -- Unsterblich
    local protect = wingDef.Protect
    if protect then
        if protect == "all" then
            -- Alle Schiffe sind unsterblich
            for i, ship in shiplist do
                NShip.Protect( { Ship = ship, Protect = 1 } )
            end
        elseif lua.type( protect ) == "table" then
            -- Bestimmte Schiffe unsterblich machen
            for i, status in protect do
                if status > 0 and shiplist[i] then
                    NShip.Protect( { Ship = shiplist[i], Protect = 1 } )
                end
            end
        else
            -- Schiffe von 1 bis n unsterblich machen
            for i = 1, protect do
                if shiplist[i] then
                    NShip.Protect( { Ship = shiplist[i], Protect = 1 } )
                end
            end
        end
    end

    -- Rumpf- und Schildstärke individuell festlegen
    if wingDef.Durability then
        for i, durability in wingDef.Durability do
            if shiplist[i] then
                durability.Ship = shiplist[i]
                NShip.SetDurability( durability )
            end
        end
    end

    -- Keine Waffen
    if wingDef.NoWeapons then
        for i, ship in shiplist do
            NShip.RemoveWeapons( { Ship = ship } )
        end
    end

    -- Mit Raketen bestücken
    local missiles = wingDef.Missiles
    if missiles then
        if lua.type( missiles ) == "table" then
            -- Bestimmte Schiffe mit dem angegebenen Munitionstyp bestücken
            for i, ammo in missiles do
                if shiplist[i] and ammo >= 0 and ammo <= 18 then
                    NShip.UseMissiles( { Ship = shiplist[i], Ammo = ammo } )
                end
            end
        elseif missiles >= 0 and missiles <= 18 then
            -- Alle Schiffe mit einem Munitionstyp bestücken
            for i, ship in shiplist do
                NShip.UseMissiles( { Ship = ship, Ammo = missiles } )
            end
        end
    end

    -- Auf eine absolute Position oder ein Objekt ausrichten, nachträgliche Übergabe hat Priorität
    local lookat = Data.LookAt
    if not lookat then
        lookat = wingDef.LookAt
    end
    if lookat then
        local pos = create.Position
        if not pos then
            pos = NObject.GetPosition( { Object = pLeader } ).Position
        elseif not wingDef.Absolute then
            -- BG Koordinaten der Schiffsposition in absolute Koordinaten umrechnen
            pos = MissionLib.AddVector( BG.Center, pos )
        end
        if lua.type( lookat ) == "string" then
            local wing = BG.Wings[lookat]
            if wing then
                lookat = get( "Logic.Wings."..wing..".leader" )
            elseif lookat == "Player" then
                lookat = BG.Player
            end
        end
        NWing.Place( { Wing = pWing, Position = pos, LookAt = lookat } )

    -- Spezielle Ausrichtung auf eine Position, LookAt oder nachträgliche Übergabe haben Priorität
    else
        local align = Data.Alignment
        if not align then
            align = wingDef.Alignment
        end
        if align then
            local front = align.Front
            if create.Position and align.Relative then
                -- Front in BG Koordinaten umrechnen
                front = MissionLib.SubVector( front, create.Position )
            end
            for i, ship in shiplist do
                NShip.SetAlignment( { Ship = ship, Front = front, UpDir = align.UpDir } )
            end
        end
    end

    -- Wingformation
    if wingDef.Formation then
        NWing.SetFormation( { Wing = pWing, Formation = wingDef.Formation } )
    end

    -- Hyperraumtoreffekt: 0|2 = Effekt baut sich auf, 1|3 = sofort volle Größe
    local hyperin = wingDef.HyperIn
    if hyperin then
        if hyperin < 2 then
            -- Effekt für alle Schiffe im Wing (0 oder 1)
            for i, ship in shiplist do
                NObject.CreateHyper( { Object = ship, Open = hyperin } )
            end
        else
            -- Effekt nur für den Wingleader (2 oder 3)
            NObject.CreateHyper( { Object = pLeader, Open = hyperin - 2 } )
        end
    end

    -- Akteure
    if wingDef.Actor then
        -- Gleicher Akteur für alle Schiffe
        for i, ship in shiplist do
            NShip.SetActor( { Ship = ship, Actor = wingDef.Actor } )
        end
    elseif wingDef.ActorList then
        -- Akteure individuell eintragen
        for i, actor in wingDef.ActorList do
            if shiplist[i] then
                NShip.SetActor( { Ship = shiplist[i], Actor = actor } )
            end
        end
    end

    -- Frachter beladen, falls gewünscht
    local cargo = wingDef.Cargo
    if cargo then
        -- "Random" belädt alle Frachter voll mit Zufallswaren, ansonsten mit nur einer Warensorte
        local randomly = cargo == "Random"
        for i, ship in shiplist do
            for j = 1, NShip.GetNumCargoBays( { Ship = ship } ).NumCargoBays do
                if randomly then
                    cargo = lua.tonumber( math.random() * 24 )
                end
                NShip.EquipContainer( { Ship = ship, Goods = cargo } )
            end
        end
    else
        local cargolist = wingDef.CargoList
        if cargolist then
            -- Jeden einzelnen Container der Frachter im Wing mit den Waren aus der Liste beladen
            for i, ship in shiplist do
                if cargolist[i] then
                    local bays = NShip.GetNumCargoBays( { Ship = ship } ).NumCargoBays
                    for j, cargo in cargolist[i] do
                        if j <= bays then
                            NShip.EquipContainer( { Ship = ship, Goods = cargo } )
                        end
                    end
                end
            end
        end
    end

    -- Ladung entsichern
    if wingDef.UnprotectCargo then
        for i, ship in shiplist do
            NShip.ProtectCargo( { Ship = ship, Protect = 0 } )
        end
    end

    -- Zittern eines nach der Erzeugung stillstehenden Schiffs vermeiden
    -- Kommt häufig bei Frachtern vor und ist sinnvoll für Cutscenes
    if wingDef.NoTremor then
        local align = NShip.GetAlignment( { Ship = pLeader } )
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            Actions = { {
                Type = AI_ACTION_POSITION1,
                Position = MissionLib.GetPosInDistance( align.Pos, align.Front, 1 )
            } }
        } )
    end

    -- Aktionen für den neuen Wing kopieren
    if wingDef.Actions then
        for i, addaction in wingDef.Actions do
            -- Handlewerte konkretisieren
            local actionlist = {}
            local index = 0
            for j, action in addaction.Actions do
                local add = MissionLib.CopyTable( action )
                -- Hier muss ein Bezeichner in ein Handlewert verwandelt werden
                local name = add.Handle
                if name then
                    -- Spezialfälle Landen und Flug zu einem SpaceObject
                    local type = add.Type
                    local wing = BG.Wings[name]
                    if type == AI_ACTION_LANDEN
                    or type == AI_ACTION_SOFORTLANDEN
                    or ( name ~= "Player"   -- Spielerschiff wird weiter unten abgefragt
                        and (
                            type == AI_ACTION_OBJECT1 or
                            type == AI_ACTION_OBJECT2 or
                            type == AI_ACTION_FOLGESCHIFF
                        )
                    ) then
                        -- Wing, großer Kreuzer fürs Landen oder anderes Schiff als Ziel
                        if wing then
                            add.Handle = get( "Logic.Wings."..wing..".leader" )
                        -- Handelsstation
                        elseif name == "TradeStation" then
                            add.Handle = MissionLib.GetSystemTradeStation()
                        -- Forschungsstation
                        elseif name == "ResearchStation" then
                            add.Handle = MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
                        -- Asteroid
                        elseif name == "Asteroid" then
                            add.Handle = MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
                        -- Prüfen, ob Handle eines Asteroiden oder einer Station
                        elseif not MissionLib.IsStation( name ) then
                            -- geht nicht, kein Hangar
                            add = nil
                        end
                    -- Ein Wing im Battleground
                    elseif wing then
                        add.Handle = wing
                    -- Spielerwing
                    elseif name == "Player" then
                        add.Handle = BG.Player
                    else
                        add = nil
                    end
                -- BG Koordinaten der Position in absolute Koordinaten umrechnen
                elseif add.Position and not wingDef.Absolute then
                    add.Position = MissionLib.AddVector( BG.Center, add.Position )
                end
                -- Die Einzelaktion übernehmen
                if add then
                    index = index + 1
                    actionlist[index] = add
                end
            end
            -- Die Aktionsliste übernehmen
            if index > 0 then
                NWing.AddAction( {
                    Wing    = pWing,
                    List    = addaction.List,
                    First   = addaction.First,
                    Actions = actionlist
                } )
            end
        end
    end

    -- Wing- und Leader-Handle zurückliefern
    return pWing, pLeader
end

-- BG Koordinaten in absolute Koordinaten umrechnen
BattleLib.CalcAbsPos = function( BG, Position )
    return MissionLib.AddVector( BG.Center, Position )
end

-- Liefert den Bezeichner des Wings aus der Wingliste
BattleLib.GetWingId = function( BG, pWing )
    for sWing, wing in BG.Wings do
        if wing == pWing then
            return sWing
        end
    end
end

-- Eona labert was
BattleLib.CopilotMessage = function( Text )
    if NPlayer.IsEona({}).Eona then
        return NComm.AddMessage( { Text = Text, Actor = "eona" } ).Message
    end
end

-- Kayron quatscht
BattleLib.KayronMessage = function( Text )
    return NComm.AddMessage( { Text = Text, Actor = "kayron" } ).Message
end

-- Sendet eine Funknachricht. Ist 'MsgOnly' true, wird kein CommInOut abgespielt.
-- 'Sender' muss entweder ein Bezeichner oder ein beliebiges Stations-Handle sein.
BattleLib.SendMessage = function( BG, Sender, Text, MsgOnly )
    -- ein Wing
    local pWing = BG.Wings[Sender]
    if pWing then
        if NWing.IsWing( { Wing = pWing } ).IsWing == 0 then
            return
        end
        Sender = pWing
    -- das Spielerschiff
    elseif Sender == "Player" then
        Sender = BG.Player
    -- die Handelsstation
    elseif Sender == "TradeStation" then
        Sender = MissionLib.GetSystemTradeStation()
    -- erste Forschungsstation
    elseif Sender == "ResearchStation" then
        Sender = MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
    -- erster Asteroid
    elseif Sender == "Asteroid" then
        Sender = MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
    -- falls Sender kein gültiges Stations-Handle ist
    elseif not MissionLib.IsStation( Sender ) then
        return
    end

    return NComm.AddMessage( {
        Text = Text, Sender = Sender, CommInOut = not MsgOnly
    } ).Message
end

-- Sendet eine Funknachricht. Optional kann dabei ein Ziel 'sTarget' gefilmt werden.
-- 'Sender' muss entweder ein Bezeichner oder ein beliebiges Stations-Handle sein.
BattleLib.SendCamMessage = function( BG, Sender, sTarget, Text, sCamType, Zoom )
    local cam, station
    local bgWings = BG.Wings

    if bgWings[Sender] then
        Sender = bgWings[Sender]
    elseif Sender == "Player" then
        Sender = BG.Player
    else
        if Sender == "TradeStation" then
            Sender = MissionLib.GetSystemTradeStation()
        elseif Sender == "ResearchStation" then
            Sender = MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
        elseif Sender == "Asteroid" then
            Sender = MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
        elseif not MissionLib.IsStation( Sender ) then
            return
        end
        station = Sender
    end

    if bgWings[sTarget] then
        if sCamType and CameraLib[sCamType] then
            cam = CameraLib[sCamType]( bgWings[sTarget], 2000, Zoom )
        else
            cam = CameraLib.TalkCamLeader( bgWings[sTarget], 2000 )
        end
    elseif station then
        cam = CameraLib.ShowStation( NObject.GetPosition( { Object = station } ).Position, 2000 )
    end

    return cam, NComm.AddMessage( { Text = Text, Sender = Sender } ).Message
end

-- Spezialkamera für KI-Schiff mit Spieler in Formation 21 (Player-NPC-Formation).
-- Kamera steht rechts über und vor dem Objekt 'pCamObj' und schaut auf das Ziel 'pAimObj'.
BattleLib.DialogCamLeader = function( pCamObj, pAimObj, Filter )
    return CameraLib.DialogCam( pCamObj, pAimObj, { 25, 10, 20 }, Filter, true )
end

-- Spezialkamera für KI-Schiff mit Spieler in Formation 21 (Player-NPC-Formation).
-- Kamera steht links über und hinter dem Objekt 'pCamObj' und schaut auf das Ziel 'pAimObj'.
BattleLib.DialogCamOther = function( pCamObj, pAimObj, Filter )
    return CameraLib.DialogCam( pCamObj, pAimObj, { -25, 15, -20 }, Filter, true )
end

-- Den Spieler ein bestimmtes Schiff im Wing anvisieren lassen
BattleLib.AutoTarget = function( BG, sWing, Member )
    local ship = MissionLib.GetWingMember( BG.Wings[sWing], Member )
    if ship then
        NPlayer.SelectTarget( { Object = ship } )
    end
end

-- Hüllenwerte der Schiffe im Wing können nur bis knapp unter 10% sinken (unzerstörbare Schiffe).
-- Ist 'PlayerIsFriend' true, wird die Darkstar One nie von ihm angegriffen.
BattleLib.ProtectWing = function( BG, sWing, PlayerIsFriend )
    local pWing = BG.Wings[sWing]
    if pWing then
        for i, ship in NWing.List( { Wing = pWing } ).ShipList do
            NShip.Protect( { Ship = ship, Protect = 1 } )
        end
        if PlayerIsFriend then
            NWing.SetInvalidEnemy( { Wing = pWing, TypeId = ST_PLAYERSHIP } )
        end
    end
end

-- Setzt das Schiff auf die angegebene Position und richtet es auf den Vektor 'LookAt' aus.
BattleLib.PlaceShip = function( BG, pShip, Position, LookAt )
    if pShip then
        NShip.SetAlignment( {
            Ship = pShip,
            Position = MissionLib.AddVector( BG.Center, Position ),
            Front = MissionLib.SubVector( LookAt, Position )
        } )
    end
end

-- Setzt den Wing auf die angegebene Position und richtet ihn auf den Vektor 'LookAt' aus.
BattleLib.PlaceWing = function( BG, sWing, Position, LookAt )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.Place( {
            Wing = pWing,
            Position = MissionLib.AddVector( BG.Center, Position ),
            Front = MissionLib.SubVector( LookAt, Position )
        } )
    end
end

-- Der Wing greift seine Gegner an und springt anschließend in den Hyperraum
BattleLib.AttackAndHyper = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_CONTANGRIFF },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing greift alle seine Gegner an und wartet anschließend
BattleLib.AttackAndWait = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_CONTANGRIFF },
                { Type = AI_ACTION_WARTEN }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing greift den Spieler an
BattleLib.AttackPlayer = function( BG, sWing, Priority )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddEnemy( {
            Wing = pWing,
            Target = BG.Player,
            Priority = Priority
        } )
    end
end

-- Der Wing greift einen anderen Wing an
BattleLib.AttackWing = function( BG, sWing, sAimWing, Priority )
    local pWing = BG.Wings[sWing]
    if pWing then
        if BG.Wings[sAimWing] then
            NWing.AddEnemy( {
                Wing = pWing,
                Target = BG.Wings[sAimWing],
                Priority = Priority
            } )
        elseif sAimWing == "Player" then
            NWing.AddEnemy( {
                Wing = pWing,
                Target = BG.Player,
                Priority = Priority
            } )
        end
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position.
-- Gegner werden mit Türmen beschossen, ohne die Formation zu verlassen.
-- Optionalen Parameter 'Speed' hinzugefügt (nk).
BattleLib.Goto = function( BG, sWing, Position, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { {
                Type = AI_ACTION_POSITION1,
                Position = MissionLib.AddVector( BG.Center, Position ),
                Speed = Speed
            } }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt zur angegebenen Position.
-- Kleine Schiffe (auch als Leader) dürfen dabei die Formation verlassen, um Gegner anzugreifen.
-- Optionalen Parameter 'Speed' hinzugefügt (nk).
BattleLib.GotoEscort = function( BG, sWing, Position, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { {
                Type = AI_ACTION_ESKORTE,
                Position = MissionLib.AddVector( BG.Center, Position ),
                Speed = Speed
            } }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt zum angegebenen Objekt und greift alle seine Gegner an
BattleLib.GotoObjectAndAttack = function( BG, sWing, pObject )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_OBJECT2, Handle = pObject },
                { Type = AI_ACTION_CONTANGRIFF },
                { Type = AI_ACTION_WARTEN },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt zum angegebenen Objekt und wartet dort.
-- Optionalen Parameter 'Speed' hinzugefügt (nk).
BattleLib.GotoObjectAndWait = function( BG, sWing, pObject, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_OBJECT1, Handle = pObject, Speed = Speed },
                { Type = AI_ACTION_WARTEN }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position, auch wenn er angegriffen wird.
BattleLib.Retreat = BattleLib.Goto

-- Der Wing springt in den Hyperraum. Ist 'Immediate' true, werden Gegner nicht angegriffen.
BattleLib.HyperOut = function( BG, sWing, Immediate )
    local pWing = BG.Wings[sWing]
    if pWing and NWing.IsWing( { Wing = pWing } ).IsWing == 1 then
        local hyperjump = AI_ACTION_HYPERRAUM
        if Immediate then
            hyperjump = AI_ACTION_SOFORTSPRUNG
        end
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { { Type = hyperjump } }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position und greift dort seine Gegner an.
-- Anschließend springt er in den Hyperraum.
BattleLib.MoveAndAttack = function( BG, sWing, Position )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_POSITION1, Position = MissionLib.AddVector( BG.Center, Position ) },
                { Type = AI_ACTION_CONTANGRIFF },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position und wartet dort.
-- Optionalen Parameter 'Speed' hinzugefügt (nk).
BattleLib.MoveAndWait = function( BG, sWing, Position, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_POSITION1,
                  Position = MissionLib.AddVector( BG.Center, Position ),
                  Speed = Speed
                },
                { Type = AI_ACTION_WARTEN }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing landet auf der mit 'Hangar' angegebenen Station (Bezeichner oder Handle).
-- Bei Kreuzerhangars kann der Bezeichner des Wings, das Wing- oder das StarshipHandle
-- des Kreuzers übergeben werden, der Bezeichner darf aber nicht ungültig sein.
-- Ansonsten haben ungültige Handles und 'sWing'-Bezeichner keine Auswirkung.
BattleLib.Land = function( BG, sWing, Hangar, Immediate )
    local pWing = BG.Wings[sWing]
    if pWing and Hangar then
        local land = AI_ACTION_LANDEN
        if Immediate then
            land = AI_ACTION_SOFORTLANDEN
        end
        if Hangar == "TradeStation" then
            Hangar = MissionLib.GetSystemTradeStation()
        elseif Hangar == "ResearchStation" then
            Hangar = MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
        elseif Hangar == "Asteroid" then
            Hangar = MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
        elseif BG.Wings[Hangar] then
            Hangar = get( "Logic.Wings."..BG.Wings[Hangar]..".leader" )
        end
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { { Type = land, Handle = Hangar } }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Die angegebene Aktion wird von allen Wings in der Gruppe ausgeführt
BattleLib.GroupAction = function( BG, sGroup, Action, pObject )
    local action = {
        List = LIST_ACTIVE,
        First = 1,
        Actions = { { Type = Action, Handle = pObject } }
    }
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            action.Wing = pWing
            NWing.AddAction( action )
            NWing.ExecuteAi( action )
        end
    end
end

-- Der Hüllenwert aller Schiffe in der Gruppe kann nur bis knapp unter 10% sinken (unzerstörbar)
BattleLib.ProtectGroup = function( BG, sGroup )
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            MissionLib.ProtectWing( pWing, true )
        end
    end
end

-- Friert alle Wings der Gruppe ein oder taut sie wieder auf. Eingefrorene Wings erhalten keine
-- Zeitschritte mehr und haben auch keine Kollisionen (inklusive Projektilen und Explosionen).
BattleLib.FreezeGroup = function( BG, sGroup, Freeze )
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            MissionLib.FreezeWing( pWing, Freeze )
        end
    end
end

-- Prüft, ob der Wing einer bestimmten Gruppe angehört
BattleLib.IsWingInGroup = function( BG, pWing, sGroup )
    for sWing, wing in BG.Wings do
        if wing == pWing then
            return BG.Defs[sWing] and BG.Defs[sWing].Group == sGroup
        end
    end
end

-- Prüft, ob eine Gruppe nicht (mehr) existiert
BattleLib.IsGroupDestroyed = function( BG, sGroup )
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            return
        end
    end
    return 1
end

-- Löst alle Gruppen auf, ohne die darin enthaltenen Wings zu löschen
BattleLib.DeleteGroups = function( BG )
    if BG and BG.Groups then
        NGroupAi.Destroy( { Group = BG.Groups.GroupA } )
        NGroupAi.Destroy( { Group = BG.Groups.GroupB } )
        BG.Groups = nil
    end
end

-- Löscht alle Wings einer Gruppe, ohne die Gruppe selbst aufzulösen
BattleLib.DestroyGroup = function( BG, sGroup )
    if BG and BG.Groups then
        local defs = BG.Defs
        for sWing, pWing in BG.Wings do
            if defs[sWing] and defs[sWing].Group == sGroup then
                BG.Wings[sWing] = nil
                if NWing.IsWing( { Wing = pWing } ).IsWing == 1 then
                    NWing.Destroy( { Wing = pWing } )
                end
            end
        end
    end
end

-- Der Wing verlässt die Gruppe, der er gegenwärtig angehört
BattleLib.LeaveGroup = function( BG, sWing )
    if BG and BG.Groups and BG.Wings[sWing] then
        local defs = BG.Defs[sWing]
        if defs and defs.Group then
            NGroupAi.SubWings( { Group = BG.Groups[defs.Group], WingList = { BG.Wings[sWing] } } )
            defs.Group = nil
        end
    end
end

-- Der Wing wird einer bestehenden Gruppe hinzugefügt
BattleLib.JoinGroup = function( BG, sWing, sGroup )
    if BG then
        local groups = BG.Groups
        if groups and groups[sGroup] then
            local pWing = BG.Wings[sWing]
            if pWing then
                local defs = BG.Defs[sWing]
                if defs and defs.Group then
                    -- Der Wing verlässt die Gruppe, der er gegenwärtig angehört
                    NGroupAi.SubWings( { Group = groups[defs.Group], WingList = { pWing } } )
                end
                NGroupAi.AddWings( { Group = groups[sGroup], WingList = { pWing } } )
                defs.Group = sGroup
            end
        end
    end
end

-- RemoveWing entfernt einen Wing aus der Gruppe, funktionsgleich mit LeaveGroup
-- und dient nur noch der Kompatibilität mit den Skripts des Originalspiels.
BattleLib.RemoveWing = BattleLib.LeaveGroup

-- Zusätzliche Funktionen einbinden
source "lua/mission/BattleLibEx.lua"
BattleLib.lua Quellcode Ende


CreateBG

CreateBG( Data ) : { Wings, Defs, Center, Groups }

Erzeugt ein Schlachtfeld mit allen definierten Wings.
BattleLib.CreateBG = function( Data )
    local bg  = {}
    bg.Wings  = {}
    bg.Defs   = Data.Defs
    bg.Center = Data.Center
    bg.Groups = NGroupAi.Create({})
    return bg
end

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
Data | table[Defs, Center] | n/a | Tabelle mit allen Wingdefinitionen

Parametertabelle Data
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Defs | table[n] | n/a | Defs[n] : { Create|Define, Alignment, EnemyTypes, Enemies, Group, Marker, Crime, BossId, Actor|ActorList, Actions, Cargo, ProtectCargo }
Center | table[3] : float | n/a | Absolute Position des Zentrums

Parametertabelle Data.Defs[n]
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Create | table | NWing.Create | Parametertabelle für NWing.Create, ohne Ausrichtungsparameter 'Front' und 'UpDir'
Define | table | NWing.Define | Parametertabelle für NWing.Define, ohne Ausrichtungsparameter 'Front' und 'UpDir'
Alignment | table | n/a | Absolute oder relative Ausrichtung der Y- und Z-Achse des Wings
EnemyTypes | table[n] : unsigned int | Schiffstyp | Erlaubt die angegebenen Schiffstypen als Gegner des Wings
Enemies | table[n] | NWing.AddEnemy | Feindliste
Group | string | n/a | "GroupA" oder "GroupB"
Marker |  |  |
Crime | bool | false/true | Strafpunkte bei Beschuss durch den Spieler
BossId | table[n] : unsigned int | 0/1 | Das Schiff soll ein Bossgegner werden (1) oder nicht (0)
Actor |  |  |
ActorList |  |  |
Actions | table[n] : Action | NWing.AddAction | Aktionen für die Wings
Cargo |  |  |
ProtectCargo | bool | false/true | Verhindert, dass die Waren abgeworfen werden (true) oder nicht (false)

Parametertabelle für Defs[n].Alignment
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Relative | bool | false/true | Ausrichtung relativ zum BG-Zentrum (true) oder nicht (false)
Front | table[3] | n/a | Ausrichtung der Z-Achse (Ebene), eine absolute Konstante im Weltraum
UpDir | table[3] | n/a | Ausrichtung der Y-Achse (Höhe), eine absolute Konstante im Weltraum

Parametertabelle für Defs[n].Enemies[n]
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Target | string oder unsigned int | string oder CWingHandle/CStarShipHandle | "ActionTurret" / "Player" oder Wing / StarShip
Priority | float | > 0.0 | Gewichtung des Gegners

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Wings | table[n] : unsigned int | CWingHandle | Handles der definierten Wings
Defs | table[n] | n/a | Kopie von Data.Defs
Center | table[3] : float | n/a | Zentrum, Kopie von Data.Center
Groups | table[2] : unsigned int | CEventHandle | GroupA, GroupB

Strukturübersicht von 'Data.Defs[n]' und des Parameters 'Defs[n]' der Rückgabetabelle

Defs[n] = {
    ["Create"] = {
    ["WingType"],
    ["Number"],
    ["Level"],
    ["LevelOffset"],
    ["Names"],
    ["Race"],
    ["PosType"],
    ["Position"],
    ["Object"],
    ["Distance"]
    },
    ["Define"] = {
    ["WingType"],
    ["Ships"],
    ["Names"],
    ["PosType"],
    ["Position"],
    ["Object"],
    ["Distance"]
    },
    ["Alignment"] = {
    ["Relative"],
    ["Front"],
    ["UpDir"]
    },
    ["EnemyTypes"][n],
    ["Enemies"][n] = {	-- für "NWing.AddEnemy"
    ["Target"],	-- string "ActionTurret"|"Player" oder unsigned int WingHandle|StarShipHandle
    ["Priority"]	-- float > 0.0
    },
    ["Group"],
    ["Marker"],		-- string "all" oder unsigned int
    ["Crime"],		-- bool
    ["BossId"][n],		-- 0|1
    ["Actor"],
    ["ActorList"][n],
    ["Actions"][n] = {
    ["List"],
    ["First"],
    ["Actions"][n] = {
        ["Type"],
        ["Handle"],	-- string "TradeStation"|"Player" oder unsigned int CHandle
        ["Position"]
    },
    },
    ["Cargo"],		-- string "Random" | StringId | Konstante für Handelsware
    ["ProtectCargo"]	-- bool
}

Beispiel


BattleLibEx

Die Skriptbibliothek "BattleLibEx.lua" ist eine Erweiterung der BattleLib.lua und beinhaltet ein paar weitere hilfreiche Zusatzfunktionen für die Erzeugung großer Schlachtfelder.

Quellcode der BattleLibEx.lua
--------------------------------------------------------------------------------
-- Dark Star One (TM) - Script library
-- Copyright (C) Ascaron Entertainment GmbH
-- All Rights Reserved.
------------------------------[Info]--------------------------------------------
-- Author: Peter Grimsehl
-- Build Version 2.7.1 by [SNF]Norbert
------------------------------[Description]-------------------------------------
-- Utility functions for instantiating large battles
------------------------------[ Notes ]-----------------------------------------
-- Landungen der KI sind jetzt auf beliebigen Stationen und Asteroiden möglich.
-- Es kann nun auch ein Bezeichner für einen umkreisten Orbiter definiert werden.
--------------------------------------------------------------------------------

-- Erzeugt einen Satelliten anhand einer Wingdefinition
BattleLib.CreateSatellite = function( BG, Data )
    local sWing = Data.WingId
    local wingDef = BG.Defs[sWing]

    -- Abbruch, wenn der Wing nicht definiert wurde oder schon vorhanden ist
    if not wingDef or BG.Wings[sWing] then return; end

    local satDef = wingDef.Satellite
    local params = MissionLib.CopyTable( satDef )

    -- BG Koordinaten der Position in absolute Koordinaten umrechnen
    if not wingDef.Absolute then
        params.Position = MissionLib.AddVector( BG.Center, satDef.Position )
    end

    -- Alle im System möglichen (ersten) Orbiter
    local Orbiter = {
    Anomalie	= function() return MissionLib.GetSystemAnomalie(); end,
    Asteroid	= function() return MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID ); end,
    Hypergate	= function() return MissionLib.GetSystemOrbiter( OBJTYPE_GATE ); end,
    Meteorid	= function() return MissionLib.GetSystemOrbiter( OBJTYPE_METEOR ); end,
    Moon		= function() return MissionLib.GetSystemMoon(); end,
    Planet		= function() return MissionLib.GetSystemPlanet(); end,
    ResearchStation	= function() return MissionLib.GetSystemOrbiter( OBJTYPE_STATION ); end,
    TradeStation	= function() return MissionLib.GetSystemTradeStation(); end
    }

    -- Bezeichner eines umkreisten Orbiters in ein Handlewert umwandeln
    local center = satDef.Center
    if center then
        if not satDef.Distance then
            params.Center = nil
        elseif Orbiter[center] then
            params.Center = Orbiter[center]()
        elseif not MissionLib.IsOrbiter( center ) then
            -- Ungültiger Bezeichner oder kein gültiges Orbiter-Handle
            params.Center, params.Distance = nil
        end
    end

    -- Satellit erzeugen
    local sat = NObject.CreateSatellite( params )

    -- Starship- und Wing-Handle des Satelliten
    local satellite = sat.Satellite
    local satWing = sat.Wing

    -- Neuen Satelliten in den Battleground eintragen
    BG.Wings[sWing] = satWing

    -- Zusätzliche Feindtypen eintragen
    if wingDef.EnemyTypes then
        for i, typeId in wingDef.EnemyTypes do
            NWing.SetInvalidEnemy( { Wing = satWing, TypeId = typeId, Set = 0 } )
        end
    end

    -- Feindlisten aller erzeugten Wings aktualisieren
    BattleLib.UpdateWingEnemies( BG, sWing )

    -- Spielerstatus
    local player = Data.Player
    if player then
        if player == "enemy" then
            -- Spieler soll sofort feindlich sein
            NWing.AddEnemy( { Wing = satWing, Target = BG.Player } )
        elseif player == "friend" then
            -- Spielerbeschuss wird weniger ernst genommen
            NShip.SetPlayerFriend( { Ship = satellite, Set = 1 } )
        elseif player == "invalid" then
            -- Spieler wird niemals feindlich
            NWing.SetInvalidEnemy( { Wing = satWing, TypeId = ST_PLAYERSHIP } )
        end
    end

    -- Gruppenzugehörigkeit
    if wingDef.Group and BG.Groups then
        NGroupAi.AddWings( { Group = BG.Groups[wingDef.Group], WingList = { satWing } } )
    end

    -- Satellit markieren
    if wingDef.Marker then
        NObject.SetMissionFlag( { Object = satellite, Set = 1 } )
    end

    -- Strafpunkte bei Beschuss
    if wingDef.Crime then
        NShip.SetCrime( { Ship = satellite, Set = 1 } )
    end

    -- Unsterblich
    if wingDef.Protect then
        NShip.Protect( { Ship = satellite, Protect = 1 } )
    end

    -- Rumpf- und Schildstärke
    local durability = wingDef.Durability
    if durability then
        durability.Ship = satellite
        NShip.SetDurability( durability )
    end

    -- Spezielle Ausrichtung, nachträgliche Übergabe hat Priorität
    local align = Data.Alignment
    if not align then
        align = wingDef.Alignment
    end
    if align then
        -- Lookat in BG Koordinaten umrechnen?
        if align.Relative then
            align.Front = MissionLib.SubVector( align.Front, satDef.Position )
        end
        NShip.SetAlignment( { Ship = satellite, Front = align.Front, UpDir = align.UpDir } )
    end

    -- Akteur
    if wingDef.Actor then
        NShip.SetActor( { Ship = satellite, Actor = wingDef.Actor } )
    end

    -- Name
    if wingDef.Name then
        NObject.SetSpecialName( { Object = satellite, Name = wingDef.Name } )
    end

    -- Aktionen für den neuen Satelliten kopieren
    if wingDef.Actions then
        for i, addaction in wingDef.Actions do
            -- Handlewerte konkretisieren
            local actionlist = {}
            local index = 0
            for j, action in addaction.Actions do
                local add = MissionLib.CopyTable( action )
                -- Hier muss ein Bezeichner in ein Handlewert verwandelt werden
                local name = add.Handle
                if name then
                    if BG.Wings[name] then
                        add.Handle = BG.Wings[name]
                    else
                        add = nil
                    end
                -- BG Koordinaten der Position in absolute Koordinaten umrechnen
                elseif add.Position and not wingDef.Absolute then
                    add.Position = MissionLib.AddVector( BG.Center, add.Position )
                end
                -- Die Einzelaktion übernehmen
                if add then
                    index = index + 1
                    actionlist[index] = add
                end
            end
            -- Die Aktionsliste übernehmen
            if index > 0 then
                NWing.AddAction( {
                    Wing    = satWing,
                    List    = addaction.List,
                    First   = addaction.First,
                    Actions = actionlist
                } )
            end
        end
    end

    -- Wing- und Ship-Handle zurückliefern
    return satWing, satellite
end

-- Liefert das Handle des angegebenen Bezeichners
BattleLib.GetWingHandle = function( BG, sWing )
    return BG.Wings[sWing]
end

-- Liefert die Anzahl aller Schiffe in der Gruppe.
-- Wurde das letzte Schiff eines Wings zerstört und der Wing existiert noch, zählt das Schiff noch mit!
BattleLib.GetShipCountInGroup = function( BG, sGroup )
    local count = 0
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            count = count + get( "Logic.Wings."..pWing..".count", 0 )
        end
    end
    return count
end

-- Der Wing bleibt regungslos an seiner Position, feuert aber mit Türmen auf Gegner
BattleLib.HoldPosition = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { { Type = AI_ACTION_STATISCH } }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing greift seine Gegner an und landet anschließend
BattleLib.AttackAndLand = function( BG, sWing, Hangar )
    local pWing = BG.Wings[sWing]
    if pWing then
        if Hangar then
            if Hangar == "TradeStation" then
                Hangar = MissionLib.GetSystemTradeStation()
            elseif Hangar == "ResearchStation" then
                Hangar = MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
            elseif Hangar == "Asteroid" then
                Hangar = MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
            elseif BG.Wings[Hangar] then
                Hangar = get( "Logic.Wings."..BG.Wings[Hangar]..".leader" )
            end
        end
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_CONTANGRIFF },
                { Type = AI_ACTION_LANDEN, Handle = Hangar }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Entfernt die Missionsmarkierungen von allen Wings
BattleLib.UnmarkAll = function( BG )
    for sWing, pWing in BG.Wings do
        NObject.SetMissionFlag( { Object = pWing, Set = 0 } )
    end
end

-- Hebt die Unsterblichkeit eines Wings wieder auf
-- Ist es der Spielerwing und 'Player' ist true, wird die Darkstar wieder angegriffen.
BattleLib.UnProtectWing = function( BG, sWing, Player )
    local pWing = BG.Wings[sWing]
    if pWing then
        for i, ship in NWing.List( { Wing = pWing } ).ShipList do
            NShip.Protect( { Ship = ship, Protect = 0 } )
        end
        if Player then
            NWing.SetInvalidEnemy( { Wing = pWing, TypeId = ST_PLAYERSHIP, Set = 0 } )
        end
    end
end

-- Hebt die Unsterblichkeit aller Wings der Gruppe wieder auf
BattleLib.UnProtectGroup = function( BG, sGroup )
    for sWing, def in BG.Defs do
        if def.Group == sGroup then
            BattleLib.UnProtectWing( BG, sWing )
        end
    end
end

------------------------------[ Neue Funktionen (nk) ]--------------------------

-- Absolute Koordinaten in BG Koordinaten umrechnen
BattleLib.CalcRelPos = function( BG, Position )
    return MissionLib.SubVector( Position, BG.Center )
end

-- Selektiert den Wingleader als Ziel des Spielerschiffs.
BattleLib.AutoTargetLeader = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        NPlayer.SelectTarget( { Object = get( "Logic.Wings."..pWing..".leader", 0 ) } )
    end
end

-- Der Hüllenwert des Schiffs im Wing kann nicht unter 1% sinken (unzerstörbar).
-- Leader, wenn 'Member' weggelassen wird oder gleich 0 ist, ansonsten Wingman.
BattleLib.ProtectShip = function( BG, sWing, Member )
    local ship = MissionLib.GetWingMember( BG.Wings[sWing], Member )
    if ship then
        NShip.Protect( { Ship = ship, Protect = 1 } )
    end
end

-- Hebt die Unsterblichkeit eines Schiffs wieder auf.
BattleLib.UnProtectShip = function( BG, sWing, Member )
    local ship = MissionLib.GetWingMember( BG.Wings[sWing], Member )
    if ship then
        NShip.Protect( { Ship = ship, Protect = 0 } )
    end
end

-- Fügt alle Schiffe von 'sWing' dem 'sTargetWing' hinzu und löscht 'sWing' anschließend im BG.
BattleLib.JoinWings = function( BG, sWing, sTargetWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        local pTargetWing = BG.Wings[sTargetWing]
        if pTargetWing then
            BG.Wings[sWing] = nil
            for i, ship in NWing.List( { Wing = pWing } ).ShipList do
                NShip.JoinWing( { Ship = ship, Wing = pTargetWing } )
            end
        end
    end
end

-- Alle Schiffe außer dem Leader verlassen 'sWing' und gründen den neuen 'sNewWing' vom Typ 'WingType'.
-- Wird kein Wingtyp angegeben, gründet die Funktion einen Hunterwing.
-- War die Aufteilung erfolgreich, wird der neue Wing im BG eingetragen und sein Handle zurückgeliefert.
-- Nützlich für Frachterwings, bei denen der Geleitschutz für eigene Aktionen abgetrennt werden soll.
BattleLib.SplitWing = function( BG, sWing, sNewWing, WingType )
    local pWing = BG.Wings[sWing]
    if pWing then
        local shiplist = NWing.List( { Wing = pWing } ).ShipList
        local shipcount = lua.getn( shiplist )
        if shipcount > 1 then
            if not WingType then WingType = WINGTYPE_HUNTER; end
            local pNewWing = NShip.JoinWing( { Ship = shiplist[2], WingType = WingType } ).Wing
            for i = 3, shipcount do
                NShip.JoinWing( { Ship = shiplist[i], Wing = pNewWing } )
            end
            BG.Wings[sNewWing] = pNewWing
            return pNewWing
        end
    end
end

-- Zerstört den Wing, es wird kein WING_DESTROYED ausgelöst.
BattleLib.DestroyWing = function( BG, sWing )
    local bgWings = BG.Wings
    if bgWings[sWing] then
        NWing.Destroy( { Wing = bgWings[sWing] } )
        bgWings[sWing] = nil
    end
end

-- Zerstört alle Wings der Liste, es werden keine WING_DESTROYED Events ausgelöst.
BattleLib.DestroyWings = function( BG, sWingList )
    local bgWings = BG.Wings
    for i, sWing in sWingList do
        if bgWings[sWing] then
            NWing.Destroy( { Wing = bgWings[sWing] } )
            bgWings[sWing] = nil
        end
    end
end

-- Prüft, ob der Wing existiert und im Battleground ist.
BattleLib.WingExists = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing and NWing.IsWing( { Wing = pWing } ).IsWing == 1 then
        return 1
    end
end

-- Prüft, ob der Wing in der Liste und im Battleground ist.
BattleLib.IsWingInList = function( BG, pWing, sWingList )
    if pWing then
        for i, sWing in sWingList do
            if BG.Wings[sWing] == pWing then
                return 1
            end
        end
    end
end

-- Prüft, ob das Schiff einer bestimmten Gruppe angehört.
BattleLib.IsShipInGroup = function( BG, pShip, sGroup )
    if pShip then
        local pWing = get( "Logic.StarShips."..pShip..".wingId", nil )
        if pWing then
            return BattleLib.IsWingInGroup( BG, pWing, sGroup )
        end
    end
end

-- Setzt oder entfernt die Missionsmarkierungen von allen Wings in der Gruppe.
BattleLib.SetMissionFlagOnGroup = function( BG, sGroup, Set )
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            NObject.SetMissionFlag( { Object = pWing, Set = Set } )
        end
    end
end

-- Setzt die Missionsmarkierung auf den Leader des Wings.
BattleLib.SetMissionFlagOnLeader = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        local leader = get( "Logic.Wings."..pWing..".leader", nil )
        if leader then
            NObject.SetMissionFlag( { Object = leader, Set = 1 } )
        end
    end
end

-- Setzt die Missionsmarkierung auf ein bestimmtes Schiff im Wing.
BattleLib.SetMissionFlagOnMember = function( BG, sWing, Member )
    local ship = MissionLib.GetWingMember( BG.Wings[sWing], Member )
    if ship then
        NObject.SetMissionFlag( { Object = ship, Set = 1 } )
    end
end

-- Entfernt die Missionsmarkierung vom Wing.
BattleLib.UnmarkWing = function( BG, sWing )
    local pWing = BG.Wings[sWing]
    if pWing then
        NObject.SetMissionFlag( { Object = pWing, Set = 0 } )
    end
end

-- Liefert die Position des Schiffs in BG Koordinaten.
BattleLib.GetShipRelPos = function( BG, pShip )
    if pShip then
        return MissionLib.SubVector( NObject.GetPosition( { Object = pShip } ).Position, BG.Center )
    end
end

-- Setzt das Spielerschiff auf die angegebene Position und richtet es auf den Vektor 'LookAt' aus.
BattleLib.PlacePlayer = function( BG, Position, LookAt )
    NShip.SetAlignment( {
        Ship = BG.Player,
        Position = MissionLib.AddVector( BG.Center, Position ),
        Front = MissionLib.SubVector( LookAt, Position )
    } )
end

-- Ändert den Level des Wings im BattleGround Datenfeld. Hat Vorrang vor dem LevelOffset.
-- Muss nach "CreateBG" und vor "CreateWing" ausgeführt werden, sonst hat's keine Auswirkung.
BattleLib.SetLevel = function( BG, sWing, Level )
    local wingDef = BG.Defs[sWing]
    if wingDef.Create then
        wingDef.Create.Level = Level
    elseif wingDef.Define then
        for i, ship in wingDef.Define.Ships do
            ship.Level = Level
        end
    end
end

-- Ändert den LevelOffset des Wings im BattleGround Datenfeld.
-- Muss nach "CreateBG" und vor "CreateWing" ausgeführt werden, sonst hat's keine Auswirkung.
BattleLib.SetLevelOffset = function( BG, sWing, Offset )
    local wingDef = BG.Defs[sWing]
    if wingDef.Create then
        wingDef.Create.LevelOffset = Offset
    elseif wingDef.Define then
        for i, ship in wingDef.Define.Ships do
            ship.LevelOffset = Offset
        end
    end
end

-- Ein Wing, der auf Inaktiv oder Statisch steht, setzt sich in Bewegung und greift den Zielwing an.
-- Existiert das Ziel nicht, greift der Wing alle seine Gegner an.
BattleLib.WakeUpAndAttack = function( BG, sWing, sAimWing, Priority )
    local pWing = BG.Wings[sWing]
    if pWing then
        if BG.Wings[sAimWing] then
            NWing.AddEnemy( {
                Wing = pWing,
                Target = BG.Wings[sAimWing],
                Priority = Priority
            } )
        end
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { CONTANGRIFF, HYPERRAUM }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Ein Wing, der auf Inaktiv oder Statisch steht, setzt sich in Bewegung und greift den Spieler an.
BattleLib.WakeUpAndAttackPlayer = function( BG, sWing, Priority )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddEnemy( {
            Wing = pWing,
            Target = BG.Player,
            Priority = Priority
        } )
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { CONTANGRIFF, HYPERRAUM }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing beschützt einen anderen Wing und greift alle seine Gegner an.
-- 'Pos' ist ein optionaler Richtungsvektor vom Wingleader zum Leader des Zielwings.
BattleLib.GuardWing = function( BG, sWing, sAimWing, Pos )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_BESCHUETZEN, Handle = BG.Wings[sAimWing], Position = Pos },
                { Type = AI_ACTION_CONTANGRIFF },
                { Type = AI_ACTION_WARTEN },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt ohne Kursänderung zum angegebenen Objekt und springt anschließend
-- in den Hyperraum. Optional kann eine Geschwindigkeit in 'Speed' angegeben werden.
BattleLib.GotoObjectAndHyper = function( BG, sWing, pObject, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_OBJECT1, Handle = pObject, Speed = Speed },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position und springt anschließend
-- in den Hyperraum. Optional kann eine Geschwindigkeit in 'Speed' angegeben werden.
BattleLib.MoveAndHyper = function( BG, sWing, Position, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_POSITION1,
                  Position = MissionLib.AddVector( BG.Center, Position ),
                  Speed = Speed
                },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing fliegt ohne Kursänderung in der aktuellen Richtung bis zur angegebenen Entfernung
-- weiter geradeaus und springt anschließend in den Hyperraum. Kleine Schiffe dürfen die Formation
-- zur Abwehr von Feinden verlassen. Optional kann eine Geschwindigkeit in 'Speed' angegeben werden.
-- Wurde in 'Distance' keine Entfernung übergeben, fliegt der Wing 1000 Units weit.
BattleLib.MoveAheadAndHyper = function( BG, sWing, Distance, Speed )
    local pWing = BG.Wings[sWing]
    if pWing then
        if not Distance then Distance = 1000000; end
        local align = NShip.GetAlignment( { Ship = get( "Logic.Wings."..pWing..".leader" ) } )
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_ESKORTE,
                  Position = MissionLib.GetPosInDistance( align.Pos, align.Front, Distance ),
                  Speed = Speed
                },
                { Type = AI_ACTION_HYPERRAUM }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Der Wing zieht sich ohne Kursänderung zur angegebenen Position zurück und bleibt dort.
BattleLib.RetreatAndHold = function( BG, sWing, Position )
    local pWing = BG.Wings[sWing]
    if pWing then
        NWing.AddAction( {
            Wing = pWing,
            List = LIST_ACTIVE,
            First = 1,
            Actions = {
                { Type = AI_ACTION_POSITION1, Position = MissionLib.AddVector( BG.Center, Position ) },
                { Type = AI_ACTION_STATISCH }
            }
        } )
        NWing.ExecuteAi( { Wing = pWing } )
    end
end

-- Zwei Wings werden zueinander feindlich.
BattleLib.AddEnemies = function( BG, sWingA, sWingB, Priority )
    local pWingA = BG.Wings[sWingA]
    if pWingA then
        local pWingB = BG.Wings[sWingB]
        if pWingB then
            NWing.AddEnemy( { Wing = pWingA, Target = pWingB, Priority = Priority } )
            NWing.AddEnemy( { Wing = pWingB, Target = pWingA, Priority = Priority } )
        end
    end
end

-- Die angegebenen Aktionen werden von allen Wings in der Gruppe ausgeführt.
-- Die 'ActionList' muss genau dasselbe Format wie der Parameter 'Actions' von NWing.AddAction haben.
-- Ist der Parameter 'Absolute' true, werden Positionsangaben nicht in BG-Koordinaten umgerechnet.
BattleLib.GroupActions = function( BG, sGroup, ActionList, Absolute )
    local actionlist = ActionList
    if not Absolute then
        actionlist = MissionLib.DeepCopyTable( ActionList )
        for i, action in actionlist do
            if action.Position then
                action.Position = MissionLib.AddVector( BG.Center, action.Position )
            end
        end
    end
    local action = {
        List = LIST_ACTIVE,
        First = 1,
        Actions = actionlist
    }
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            action.Wing = pWing
            NWing.AddAction( action )
            NWing.ExecuteAi( action )
        end
    end
end

-- Liefert die Gruppe des Wings (z.B. "GroupA") oder nil, wenn er keiner Gruppe angehört.
BattleLib.GetGroup = function( BG, pWing )
    for sWing, wing in BG.Wings do
        if wing == pWing then
            return BG.Defs[sWing] and BG.Defs[sWing].Group
        end
    end
end

-- Liefert die Anzahl der Wings einer Gruppe.
BattleLib.GetWingCountInGroup = function( BG, sGroup )
    local count = 0
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            count = count + 1
        end
    end
    return count
end

-- Liefert eine Liste mit allen existierenden Wings einer Gruppe.
-- Der Tabellenindex enthält das Handle und der Wert den Bezeichner des Wings.
BattleLib.GetWingsInGroup = function( BG, sGroup )
    local winglist = {}
    local defs = BG.Defs
    for sWing, pWing in BG.Wings do
        if defs[sWing] and defs[sWing].Group == sGroup then
            winglist[pWing] = sWing
        end
    end
    return winglist
end

-- Löscht alle Wings in den Gruppen, ohne die Gruppen selbst aufzulösen.
-- Wings ohne Gruppe bleiben dabei erhalten.
BattleLib.DestroyGroups = function( BG )
    if BG and BG.Groups then
        local defs = BG.Defs
        for sWing, pWing in BG.Wings do
            if defs[sWing] and defs[sWing].Group then
                BG.Wings[sWing] = nil
                if NWing.IsWing( { Wing = pWing } ).IsWing == 1 then
                    NWing.Destroy( { Wing = pWing } )
                end
            end
        end
    end
end
BattleLibEx.lua Quellcode Ende


CreateSatellite

CreateSatellite( BG, Data )

Erzeugt einen Satelliten anhand einer Wingdefinition


CameraLib

Welche Kamera soll ich nehmen?

Kameras für bestimmte Situationen wie "Menace" sollten stets so verwendet werden wie hier dokumentiert. Bei den meisten Kameras kommt man allerdings nicht drum herum, sich die Spielsituation anzuschauen und selbst abzuschätzen, was sich gut eignet. Demzufolge enthält diese Liste Vorschläge, welche Situationen man wie darstellen kann.

Situation | Kamera | Parameter / Kommentar
Bedrohung | MenaceWing MenaceWingStrong MenacePlayerWing | Kamera fliegt auf den entsprechenden Wing frontal zu. Die Variante Strong ist dynamischer. 'MenacePlayerWing' berücksichtigt die Position des Spielers, aber die Orientierung im Raum ist noch nicht optimal.
Dialog | TalkCamLeader TalkCamFollower TalkCamBoth | Kamera hovert vor den Leuten, die was sagen. Bei einem längeren Monolog eines Hunters mit dem Spieler ist 'FlyPara' besser. In dem Fall muss man aber vorher beide ausrichten. Je nach Situation eignen sich manchmal andere Kameras besser, wie z.B. 'ShowShip' oder 'ZoomAway'.
Längerer Monolog | FlyPara | Kamera umkreist erst den Sprecher und fährt dann weiter weg, um auch den in Flugrichtung rechts daneben zu positionierenden Spieler zu zeigen.
Spielerschiff zeigen | TestSpline EnterCamPlayer Black JoinCam | TestSpline: Auswahl aus allen 41 verfügbaren Splinekameras. EnterCamPlayer: Kamera fliegt in das Spielerschiff hinein. Black: Kamera zeigt fest auf das Spielerschiff und bewegt sich mit ihm mit. JoinCam: Zeigt den Beitritt des Spielerschiffs zu einem NPC-Wing.
Ein Schiff aus der Spielerperspektive zeigen | PlayerShipCam1 PlayerShipCam2 | Beide zeigen das Zielschiff von der Spielerposition aus. Die erste Kamera ist auf der Oberseite und die zweite auf der Unterseite des Spielerschiffs angebracht. Ideal, um Angriffe auf den Spieler zu zeigen.
Besondere Schiffe zeigen | ShowShip BigBoy | Beide fahren um ein Schiff herum. Übergabeparameter ist aber ein Wing. Zoom einstellen.
Ganzen Wing zeigen | PSTotalBack WingCam | Die erste Kamera zeigt einen kompletten Wing von der Spielerposition aus und ist über dem Spielerschiff angebracht. Eignet sich gut für die Beobachtung miteinander verfeindeter KI-Wings beim Kampf. Die zweite zeigt den Wing aus fixer Position und frei wählbarem Winkel.
Frachter zeigen | ZoomAway | Fährt vom Cockpit nach hinten rechts weg, sodass der Fokus auf die Ladung gerückt wird.
Satellit zeigen | CloseUpSatellite | Kamera fährt je nach Übegabeparameter geradeaus oder im Bogen auf einen Satelliten zu und bleibt kurz vor ihm eine Sekunde lang stehen.
Station zeigen | ShowStation | Zeigt große stationäre Objekte (Raumstationen, Asteroiden, Sprungtor, Planeten und sonstige Orbiter, stillstehende Kreuzer sind auch geeignet).
Container zeigen | RewardContainer | Kamera rotiert spiralförmig auf ein Objekt zu (Artefakt-, Spezial- oder normaler Container).
Frachter oder Hunter wirft Container ab | ContainerDrop ContainerDrop2 | Kamera steht frontal vor dem Schiff und guckt auf den Container. ContainerDrop2 ist besser für Schiffe geeignet, die nicht stillstehen, da hier ein Offset von der Position übergeben werden kann.
Frachter oder Jägerwing springt in den Hyperraum | FreighterHyperspace HunterHyperspace | Kamera zeigt von einer festen Position aus einen ganzen Wing von hinten beim Wegfliegen. Nach Ablauf der Zeit folgt die Kamera dem Leader in einem geringen Abstand. Eignet sich gut für Frachterwings vor und während dem Hyperraumsprung.

Hinweise

Bei Verwendung der Kameras auf 4 Dinge achten:

  • Übergabeparameter - Die Nichtverwendung der Übergabeparameter wird nicht immer abgefangen, sodass es zum Crash kommen kann! Notfalls in der CameraLib nachschauen.
  • Timing
    • MenaceCam - Dem Spieler die Steuerung wegzunehmen ist nicht wünschenswert. Daher die Menace Cams nicht überstrapazieren, denn da droht ja oft direkte Gefahr, auf die der Spieler reagieren möchte.
    • CommEnd - Insbesondere Dialogkameras müssen meist auf CommEnd beendet werden. Daher übergibt man sehr lange Zeiten. Bei Kameras, die nicht auf Splines laufen bedeutet das, dass sie sehr langsam werden. Außerdem hat diese Kamera dann keinen BlackOut oder WhiteOut mehr, falls so ein Filter gesetzt wurde, außer man beendet sie mit der Funktion NCamera.End. Oftmals ist es besser, insbesondere für den letzten Comm eines Dialoges die Kamera kurz weiterlaufen zu lassen indem man in CommEnd einen Timer setzt, im Timer-Event dann die Kamera beendet oder zerstört und dann gegebenenfalls auf ActionCamEnd triggert.
    • Zeitschritte - Bei den Parametern TurnSteps und PostSteps der CreateObject Cam entspricht 1 Zeitschritt gleich 1/25 Sekunde. In allen anderen Kameras ist der Parameter Time eine Zeitangabe in Sekunden (float).
  • Zoom - Die Kameras sind meist auf bestimmte Schiffsgrößen eingestellt. Einen Hunter zum Beispiel. Bitte immer den Zoom einer Kamera prüfen. Das kann man auch kreativ nützen, mit einem Zoom von 100 kann man wunderschön das Universum umrunden. Im Gegensatz zu realen Kameras wird mit größeren Faktoren nicht heran-, sondern herausgezoomt. Je größer also der Zoomfaktor, desto kleiner ist das Ziel.
  • Crash - Der Befehl NCamera.Destroy( { Camera } ) zerstört nur die aktuell laufende Kamera. Gibt es gerade keine laufende Kamera, stürzt Darkstar ab. Folgt noch eine Kamera in der Liste, wird diese auch nicht gelöscht. Trick ist, erst noch eine Dummy-Kamera mit dem Parameter Immediate = true zu starten und die dann zu zerstören.

Einige Funktionen, in denen als Übergabeparameter eine ShipId eingetragen ist, können trotzdem auch für andere Objekte wie z. B. Raumstationen verwendet werden. Hier muss nur sichergestellt sein, dass innerhalb der Funktion kein Schiffs- oder Winghandle erwartet wird. CameraLib.Spline und CameraLib.PassByShip wären solche Beispiele. Umgekehrt gilt das gleiche, so könnte man u. a. CameraLib.ShowStation auch für Kreuzer verwenden.

CameraLib

  • Kameras (CameraLib):
    • BigBoy
    • Black
    • CamSequence
    • CloseUpWingLeader
    • ContainerDrop
    • EnterCamPlayer
    • EnterCamWing
    • FlyPara
    • FlyThrough
    • FreighterHyperspace
    • JoinCam
    • MenacePlayerWing
    • MenaceWing
    • MenaceWingStrong
    • PassBy
    • PassByShip
    • PlanetenCam
    • PlayerShipCam1
    • PlayerShipCam2
    • PSTotalBack
    • RewardContainer
    • ShowShip
    • ShowStation
    • Spline
    • TalkCam
    • TalkCamBoth
    • TalkCamEona
    • TalkCamFollower
    • TalkCamKayron
    • TalkCamLeader
    • TalkCamStatic
    • TestSpline
    • ZoomAway
    • ZoomWingCam

  • Kameras (CameraLibEx):
    • AddFilterBlack
    • AddFilterBlackIn
    • AddFilterBlackOut
    • AddFilterBlackInOut
    • AddFilterBlackInWhiteOut
    • AddFilterWhiteIn
    • AddFilterWhiteOut
    • AddFilterWhiteInOut
    • AddFilterWhiteInBlackOut
    • AddFilterBlur
    • AddFilterShake
    • AddFilterFlash
    • AddFilterFOV
    • BigBoyObject
    • CircleWing
    • CloseUpSatellite
    • ContainerDrop2
    • DialogCam
    • HunterHyperspace
    • ObjectCamTurn0
    • ObjectCamTurn1
    • ObjectCamTurn2
    • ObjectCamTurn3
    • ObjectCamTurn4
    • ObjectCamTurn5
    • PlayerShipCamBack
    • PlayerShipCamBottom
    • PlayerShipCamFront
    • PlayerShipCamLeft
    • PlayerShipCamLookAhead
    • PlayerShipCamLookAt
    • PlayerShipCamRight
    • PlayerShipCamTop
    • PlayerShipObjectCam
    • PlayerShipPosCam
    • RewardContainer2
    • ShowObject
    • TalkCamMember
    • TalkCamMemberStatic
    • TalkCamSpline
    • WingCam
    • Dummy
    • Destroy
    • ShortCam
    • BlackOut
    • WhiteOut

  • Positionen und allgemeine Funktionen:
    • AlignPlayerToWing
    • AlignWingToPlayer
    • FreezeWing
    • FrontPos
    • getNewCameraPos_MetricBias
    • getNewCameraPos_ParametricBias
    • GetZoomFactor

  • Beispiele:
    • Beispiel-Transitions

Quellcode der CameraLib.lua
--------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) Ascaron Entertainment GmbH
-- All Rights Reserved.
------------------------------[ Info ]------------------------------------------
-- Name: CameraLib.lua
-- Version: 1.0
-- Build Version 2.6.7 by [SNF]Norbert
------------------------------[ Description ]-----------------------------------
-- Viele vorgefertigte Kameras
------------------------------[ Notes ]-----------------------------------------
-- Viele unnötige Variablenzuweisungen entfernt und auch sonst aufgeräumt. (nk)
--------------------------------------------------------------------------------

------------------------------[ Import ]----------------------------------------

source "lua/mission/MissionLib.lua"	-- Verschiedene Hilfsfunktionen

------------------------------[ Collection ]------------------------------------

CameraLib = {}

------------------------------[ Globale Konstanten ]----------------------------

-- Für Dialoge geeignete vorgefertigte Splinekameras
TALKCAMLIST = { 0, 5, 7, 10, 11, 17, 18, 22, 27, 28, 29, 30, 31, 32 }

NO_FILTER = 1	-- Für die Abschaltung standardmäßig gesetzter Filter

FILTER_TYPE = {	-- Filterfunktionen ohne Parameter in CameraLibEx.lua
    [0] = "AddFilterBlack";
    "AddFilterBlackIn", "AddFilterBlackOut", "AddFilterBlackInOut", "AddFilterBlackInWhiteOut",
    "AddFilterWhiteIn", "AddFilterWhiteOut", "AddFilterWhiteInOut", "AddFilterWhiteInBlackOut",
    "AddFilterBlur", "AddFilterShake"
}

------------------------------[ Die Kameras ]-----------------------------------

-- Zeigt das Spielerschiff mit einer aus 41 verfügbaren Splinekameras.
-- Einfach hier bei dem Parameter 'Spline' die Spline-Nummer eingeben,
-- dann wird die Splinekamera auf das Spielerschiff ausgeführt.
-- Mögliche Werte für 'Spline' sind: 0 bis 36, "10s", "10x", "11s" und 50.
-- Existiert der Parameter 'InQueue' nicht oder ist false, wird die Kamera
-- sofort angezeigt, ansonsten wird sie in die Warteschlange eingehängt.
-- Einfach im VariablenManager für Missionen eintragen: import "CameraLib".
-- Beispiel mit BlackInOut: V.TestCam = CameraLib.TestSpline( 23, 10, 1, 3 )
CameraLib.TestSpline = function( Spline, Time, Zoom, Filter, InQueue )
    if not Spline then
        Spline = "3dview/ActionCams/SplineKamera11.xml"
    elseif Spline == "default" then
        Spline = "3dview/ActionCams/default.xml"
    else
        Spline = "3dview/ActionCams/SplineKamera"..Spline..".xml"
    end
    if not Time then Time = 10; end
    if not Zoom then Zoom = 1; end
    local player = get( PLAYER_SHIP_ID )

    local camera = NCamera.CreateSplineCam( {
        Name = Spline,
        Cam = player,
        Aim = player,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = not InQueue
    } ).Camera

    -- Mögliche Werte für den optionalen Filter (0..10):
    -- 1 = BLACK_IN | 2 = BLACK_OUT | 3 = BLACK_IN und BLACK_OUT | 4 = BLACK_IN und WHITE_OUT
    -- 5 = WHITE_IN | 6 = WHITE_OUT | 7 = WHITE_IN und WHITE_OUT | 8 = WHITE_IN und BLACK_OUT
    -- 0 = BLACK | 9 = BLUR | 10 = SHAKE
    if Filter then
        CameraLib[FILTER_TYPE[Filter]]( camera )
    end

    return camera
end

-- SplineCamWrapper (Achtung: ShipId oder ObjectId, aber kein Winghandle verwenden!)
-- Zeigt das Schiff oder ein anderes Objekt mit einer aus 41 verfügbaren Splinekameras.
-- Orbiter wie Stationen benötigen allerdings einen sehr großen Zoomfaktor (über 100).
CameraLib.Spline = function( ShipId, Spline, Time, Zoom, InQueue )
    if not ShipId then ShipId = get( PLAYER_SHIP_ID ); end
    if not Time then Time = 10; end
    if not Zoom then Zoom = 2; end
    if not Spline then
        Spline = "3dview/ActionCams/SplineKamera11.xml"
    elseif Spline == "default" then
        Spline = "3dview/ActionCams/default.xml"
    else
        Spline = "3dview/ActionCams/SplineKamera"..Spline..".xml"
    end

    return NCamera.CreateSplineCam( {
        Name = Spline,
        Cam = ShipId,
        Aim = ShipId,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = not InQueue
    } ).Camera
end

-- Fliegt einen Kreis um das Zielschiff, macht einen großen Bogen nach links,
-- sodass dort auch das Spielerschiff zu sehen ist. Eignet sich für längere Monologe.
-- Existiert der Parameter 'FilterOff', werden die standardmäßig gesetzten Filter abgeschaltet.
-- Parameter 'Zoom' für die Angabe eines beliebigen Zooms hinzugefügt. Standard ist 1.4, wenn false.
CameraLib.FlyPara = function( WingId, Time, Zoom, FilterOff, Immediate )
    if not Time then Time = 10; end
    if not Zoom then Zoom = 1.4; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    local camera = NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera10.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if not FilterOff then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )
    end

    return camera
end

-- Zeigt, wie der Frachter einen Container abwirft.
CameraLib.ContainerDrop = function( WingId, ContainerId, Time, Immediate )
    if not Time then Time = 10; end

    return NCamera.CreatePosCam( {
        Object = ContainerId,
        Position = CameraLib.FrontPos( WingId, 0.7 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera zeigt den Spieler und fliegt dann in die Richtung der Bedrohung, sodass eine räumliche
-- Orientierung möglich ist. Der optionale Parameter 'Time' ist die Laufzeit der jeweiligen Kamera an
-- Anfang und Ende der Cutscene (Kamera #1, #2 und #5; default = 4 Sekunden, also 12 Sekunden insgesamt).
-- Dem kommt noch eine Laufzeit von 7 - 13 Sekunden der Kameras 3 + 4 hinzu und wird anhand der Entfernung
-- des Zielwings berechnet, damit die Kamerafahrt vom Spielerschiff zum Zielschiff nicht zu schnell geht.
-- Falls sich der Wing bewegt, sollte er ggf. vor oder direkt nach dem Funktionsaufruf eingefroren werden.
CameraLib.MenacePlayerWing = function( WingId, Time, Immediate )
    -- Laufzeiten für Kameras 1, 2 und 5
    if not Time then Time = 4; end

    -- Positionen von Spielerschiff, Wingleader und Kamera kurz hinter dem Spielerschiff
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )
    local leaderObj = { Object = get( "Logic.Wings."..WingId..".leader" ) }
    local playerPos = align.Pos
    local leaderPos = NObject.GetPosition( leaderObj ).Position
    local cameraPos = MissionLib.GetPosInDistance( playerPos, align.Front, -30 )
    cameraPos[2] = cameraPos[2] - 10

    -- Kamera 1 schaut von hinten auf das Spielerschiff und fährt von oben (y+20) nach unten (y-10)
    NCamera.AddFilter( {
        Camera = NCamera.CreateFreeCam( {
            TabTargetPosition = { playerPos },
            TabCamPosition = { MissionLib.AddVectorY( cameraPos, 30 ), cameraPos },
            Time = Time,
            Immediate = Immediate
        } ).Camera,
        Filter = CAMERA_FILTER_BLACK_IN
    } )

    -- Kamera 2 schwenkt vom Spielerschiff auf den Zielwing.
    -- Die Länge des Vektors von der Kameraposition zur Position des Spielerschiffs wird gleich
    -- der Vektorlänge zum Ziel gesetzt, sonst kann der Schwenk zu schnell und ungleichmäßig gehen.
    local dist = NObject.DistanceFromPlayer( leaderObj ).Distance
    NCamera.CreateFreeCam( {
        TabTargetPosition = { MissionLib.SetVectorLengthRel( playerPos, cameraPos, dist ), leaderPos },
        TabCamPosition = { cameraPos },
        Time = Time
    } )

    -- Schöne Kameraposition am Ziel
    local targetPos = NCamera.GetWingRelPos( { Wing = WingId, Angle = 20 } ).Position
    -- Kameraposition kurz vor Zielwing (wie getNewCameraPos_ParametricBias), auf maximal 1u begrenzen
    local factor = 0.1
    if dist > 10000 then factor = 1000 / dist; end
    local frontPos = MissionLib.MulVectorLengthRel( playerPos, targetPos, factor )

    -- Laufzeit für die Kamerafahrt bis kurz vor dem Ziel, mindestens 4 bis maximal 10 Sekunden
    local runtime = dist / 1000
    if runtime < 4 then runtime = 4 elseif runtime > 10 then runtime = 10; end

    -- Kamera 3 fährt vom Spielerschiff vor den Zielwing
    NCamera.CreateFreeCam( {
        TabTargetPosition = { leaderPos },
        TabCamPosition = { cameraPos, frontPos },
        Time = runtime
    } )

    -- Kamera 4 fährt langsamer zum Zielwing weiter
    local cam4 = NCamera.CreateFreeCam( {
        TabTargetPosition = { leaderPos },
        TabCamPosition = { frontPos, targetPos },
        Time = 3
    } ).Camera

    -- Kamera 5 schaut dem Zielwing hinterher
    local cam5 = NCamera.CreatePosCam( {
        Object = WingId,
        Position = targetPos,
        Time = Time
    } ).Camera
    NCamera.AddFilter( { Camera = cam5, Filter = CAMERA_FILTER_FOV, Value1 = Time, Value2 = -0.1 } )
    NCamera.AddFilter( { Camera = cam5, Filter = CAMERA_FILTER_BLACK_OUT } )

    -- Wurde der Wing eingefroren, sollte er in ActionCamEnd von cam4 wieder aufgetaut werden
    return cam4, cam5
end

-- Kamera rast auf den Leader des Wings zu, dreht sich um ihn herum
-- und schaut dann dem ganzen Wing hinterher. Bei kleineren Objekten gut.
-- Parameter 'Zoom' hinzugefügt (nk).
CameraLib.MenaceWingStrong = function( WingId, Time, Zoom, Immediate )
    if not Time then Time = 10; end
    if not Zoom then Zoom = 1.5; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera20.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera fährt auf den Leader des Wings zu und dreht sich um ihn herum.
-- Parameter 'Zoom' hinzugefügt (nk).
CameraLib.MenaceWing = function( WingId, Time, Zoom, Immediate )
    if not Time then Time = 10; end
    if not Zoom then Zoom = 1.5; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera1.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera fährt vom Leader des Wings weg.
-- Parameter 'Zoom' hinzugefügt (nk).
CameraLib.ZoomAway = function( WingId, Time, Zoom, Immediate )
    if not Time then Time = 10; end
    if not Zoom then Zoom = 1.5; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera15.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera fährt am Leader des Wings vorbei.
-- Auf Frachter skaliert, für Kreuzer ist ein Zoom von 20 bis 50 besser.
CameraLib.ShowShip = function( WingId, Time, Zoom, Immediate )
    local leader = get( "Logic.Wings."..WingId..".leader" )
    if not Time then Time = 30; end
    if not Zoom then Zoom = CameraLib.GetZoomFactor( WingId, leader ); end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera11.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = { 0, MissionLib.RandomSignedInt( -15, 15 ), 0 },
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera rotiert spiralförmig auf einen Container (Spezialcontainer) zu.
CameraLib.RewardContainer = function( ContainerId, Time, Zoom, Immediate )
    if not Time then Time = 12; end
    if not Zoom then Zoom = 1; end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera23.xml",
        Cam = ContainerId,
        Aim = ContainerId,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera "betritt" den Leader des Wings.
-- Parameter 'Filter' hinzugefügt (nk).
CameraLib.EnterCamWing = function( WingId, Time, Filter, Immediate )
    if not Time then Time = 10; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    local camera = NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera1.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = 0.6,
        Time = Time,
        Immediate = Immediate
    } ).Camera

    -- Filter #1: BLACK_IN | Filter #2: BLACK_OUT | Filter #3: BLACK_IN und BLACK_OUT
    if Filter then
        if Filter == 1 or Filter == 3 then
            NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
        end
        if Filter == 2 or Filter == 3 then
            NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )
        end
    end

    return camera
end

-- Kamera "betritt" das Spielerschiff.
CameraLib.EnterCamPlayer = function( Immediate )
    local player = get( PLAYER_SHIP_ID )

    local camera = NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera1.xml",
        Cam = player,
        Aim = player,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = 1,
        Time = 4,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )

    return camera
end

-- Kamera fährt zügig an einem Schiff rechts (Spline25) oder links (Spline26) vorbei.
-- (Achtung: ShipHandle!) Parameter 'Side' für Linksvorbeiflug (wenn true) hinzugefügt (nk).
CameraLib.PassByShip = function( ShipId, Time, Zoom, Side, Immediate )
    if not Time then Time = 3; end
    if not Zoom then Zoom = 1; end
    if Side then Side = 26 else Side = 25; end  -- 25 = rechts, 26 = links vorbei

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera"..Side..".xml",
        Cam = ShipId,
        Aim = ShipId,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera zeigt einen Wing aus fixer Position und eignet sich gut für einen schnellen Vorbeiflug.
-- Existiert der Parameter 'FilterOff', werden die standardmäßig gesetzten Filter abgeschaltet.
CameraLib.PassBy = function( WingId, Time, FilterOff, Immediate )
    if not Time then Time = 10; end
    local targetPos = CameraLib.FrontPos( WingId, 0.6 )
    targetPos[1] = targetPos[1] + 30

    local camera = NCamera.CreatePosCam( {
        Object = WingId,
        Position = targetPos,
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if not FilterOff then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )
    end

    return camera
end

-- Kamera fährt rechtsherum seitlich an einem Wing von vorne nach hinten vorbei.
CameraLib.BigBoy = function( WingId, Time, Zoom, Immediate )
    if not Time then Time = 12; end
    if not Zoom then Zoom = 15; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    local camera = NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera19.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = { 0, MissionLib.RandomSignedInt( -30, 30 ), 0 },
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )

    return camera
end

-- Kamera zeigt von einer festen Position aus einen ganzen Wing von hinten beim Wegfliegen.
-- Nach Ablauf der Zeit folgt die Kamera dem Leader in einem geringen Abstand.
-- Eignet sich gut für Frachterwings vor und während dem Hyperraumsprung.
-- Parameter 'Time' hinzugefügt (nk).
CameraLib.FreighterHyperspace = function( WingId, Time, Immediate )
    if not Time then Time = 6; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    NCamera.CreatePosCam( {
        Object = leader,
        Position = NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position,
        Time = Time,
        Immediate = Immediate
    } )

    return NCamera.CreateObject( {
        Object = leader,
        TurnSteps = 75,    -- 3.0 s
        PostSteps = 2000,  -- 80.0 s
        AngleX1 = 0,
        AngleX2 = 0,
        AngleY1 = 0,
        AngleY2 = 0,
        Distance1 = 150,
        Distance2 = 150
    } ).Camera
end

-- Kamera startet mit der Ansicht des gesamten Wings im relativen Winkel 'StartAngle' und 20° über ihm.
-- Sie fährt sofort auf den Wingleader zu und hält dann 2 Sekunden lang dicht vor ihm in gleicher Höhe.
-- Geeignet für alle Wingtypen, von kleinen Polizeijägern bis hin zu großen Kreuzern und Superfrachtern.
--    0° = Start von hinten, Kamera fährt im Uhrzeigersinn vor den Leader,
--  360° = Start von hinten, Kamera fährt gegen den Uhrzeigersinn vor den Leader,
-- -360° = Start von hinten, Kamera fährt im Uhrzeigersinn 1½ mal um den Wing herum vor den Leader,
--  180° = Start von vorne (default), Kamera fährt geradeaus auf den Leader zu,
-- -180° = Start von vorne, Kamera fährt im Uhrzeigersinn einmal komplett um den Wing herum vor den Leader,
--   90° = Start von links, Kamera fährt im Uhrzeigersinn vor den Leader,
-- -270° = Start von links, Kamera fährt im Uhrzeigersinn 1¼ mal um den Wing herum vor den Leader,
--  -90° = Start von rechts, Kamera fährt im Uhrzeigersinn um den Wing herum vor den Leader,
--  270° = Start von rechts, Kamera fährt gegen den Uhrzeigersinn um den Wing herum vor den Leader.
CameraLib.CloseUpWingLeader = function( WingId, Time, StartAngle, Immediate )
    -- Übergebene Sekunden in Timesteps umwandeln
    if not Time then
        Time = 100  -- default = 4 Sekunden
    elseif Time <= 1 then
        Time = 25   -- mindestens eine Sekunde Laufzeit
    else
        Time = lua.tonumber( Time * 25 )  -- Ganzzahl!
    end
    if not StartAngle then StartAngle = 180; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    return NCamera.CreateObject( {
        Object = leader,
        TurnSteps = timesteps,
        PostSteps = 50,  -- 2.0 s Haltezeit
        AngleX1 = 20,
        AngleX2 = 0,
        AngleY1 = StartAngle,
        AngleY2 = 180,
        Distance1 = MissionLib.GetVectorDistance(
            NCamera.GetWingRelPos( { Wing = WingId, Angle = StartAngle } ).Position,
            NObject.GetPosition( { Object = leader } ).Position
        ),
        Distance2 = 10,
        Immediate = Immediate
    } ).Camera
end

-- Kamera zeigt ein großes stillstehendes Objekt, wie z.B. eine Raumstation.
-- Für 'ObjectPos' kann entweder die Position des Objekts oder sein Handle übergeben werden.
-- Existiert 'ObjectPos' nicht oder ist eine leere Tabelle, wird die Handelsstation gezeigt.
CameraLib.ShowStation = function( ObjectPos, Time, Immediate )
    if not Time then Time = 30; end

    local cameraPos = {
        { 0, -200, 600 },
        { 100, -100, 400 },
        { 200, 100, 200 },
        { 300, 300, 100 },
        { 300, 500, 100 },
        { -200, 500, 200 },
        { -400, 300, 100 },
        { -500, 100, 100 },
        { 0, 0, 1500 }
    }
    local targetPos = {
        { 0, -100, 0 },
        { 100, -50, 0 },
        { 200, 50, 0 },
        { 150, 100, 0 },
        { 100, -100, 0 },
        { 50, -50, 0 },
        { 0, 0, 0 },
        { 0, 0, 0 },
        { 0, 0, 0 }
    }

    if ObjectPos then
        if lua.type( ObjectPos ) == "number" then
            -- ObjectPos ist ein Handle, Position holen
            ObjectPos = NObject.GetPosition( { Object = ObjectPos } ).Position
        end
        if not MissionLib.IsVectorLengthNull( ObjectPos ) then
            local objPosX, objPosY, objPosZ = ObjectPos[1], ObjectPos[2], ObjectPos[3]
            for i, posTable in { cameraPos, targetPos } do
                for j, pos in posTable do
                    pos[1] = pos[1] + objPosX
                    pos[2] = pos[2] + objPosY
                    pos[3] = pos[3] + objPosZ
                end
            end
        end
    end

    local camera = NCamera.CreateFreeCam( {
        TabTargetPosition = targetPos,
        TabCamPosition = cameraPos,
        Time = Time,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )

    return camera
end

-- Zeigt aus verschiedenen Positionen, wie sich Wingleader und sein erster Wingman fortbewegen,
-- bis der Wing nicht mehr sichtbar ist. Hat der Wing keinen Wingman, wird an seiner Stelle
-- das Spielerschiff eingesetzt, dessen Handle in dem Fall nach der Kameraliste zurückgeliefert wird.
-- Es sollte während der Sequenz dem Leader (NPlayer.EscortNPC) oder Wing (NPlayer.StartFollow) folgen.
-- Eine Schlusskamera zeigt an, wo der Wing herkam.
CameraLib.PlanetenCam = function( WingId, Position, Immediate )
    local player
    local AddFilter = NCamera.AddFilter
    local targetLeader = get( "Logic.Wings."..WingId..".leader" )
    local targetFollower = get( "Logic.Wings."..WingId..".ship1" )
    if targetFollower == NO_SHIP_ID then
        player = get( PLAYER_SHIP_ID )
        targetFollower = player
    end
    local leaderPos = NObject.GetPosition( { Object = targetLeader } ).Position
    if not Position then
        Position = leaderPos
    end

    local pCam1 = NCamera.CreatePosCam( {
        Object = WingId,
        Position = NCamera.GetWingRelPos( { Wing = WingId, Angle = 70 } ).Position,
        Time = 5,
        Immediate = Immediate
    } ).Camera
    AddFilter( { Camera = pCam1, Filter = CAMERA_FILTER_BLACK_IN } )

    local pCam2 = NCamera.CreateBoundCam( {
        TargetObject = targetLeader,
        BindObject = targetFollower,
        Distance = 40,
        Time = 3
    } ).Camera

    local pCam3 = NCamera.CreateBoundCam( {
        TargetObject = targetFollower,
        BindObject = targetLeader,
        Distance = 40,
        Time = 3
    } ).Camera

    -- Position 0.05u unterschneiden, kann kollidieren!
    local pCam4 = NCamera.CreatePosCam( {
        Object = WingId,
        Position = MissionLib.AddVectorX( Position, 50 ),
        Time = 8
    } ).Camera

    local pCam5 = NCamera.CreatePosCam( {
        Object = WingId,
        Position = leaderPos,
        Time = 8
    } ).Camera
    for i, filter in { CAMERA_FILTER_BLUR, CAMERA_FILTER_SHAKE, CAMERA_FILTER_BLACK_OUT } do
        AddFilter( { Camera = pCam5, Filter = filter } )
    end

    return { pCam1, pCam2, pCam3, pCam4, pCam5 }, player
end

-- Dialogkamera, wenn beide Gesprächspartner in einem Wing sind. Boss spricht.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.TalkCamLeader = function( WingId, Time, Immediate )
    if not Time then Time = 60; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera0.xml",
        Cam = leader,
        Aim = leader,
        CamOffset = { 0, MissionLib.RandomSignedInt( -10, 10 ), 0 },
        AimOffset = OBJECT_CENTER,
        Zoom = CameraLib.GetZoomFactor( WingId, leader ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Dialogkamera, wenn beide Gesprächspartner in einem Wing sind. Wingman spricht.
-- Dauert lange, muss mit EndComm oder Timer beendet werden!
CameraLib.TalkCamFollower = function( WingId, Immediate )
    -- Position der Kamera näher am Wing (wie getNewCameraPos_ParametricBias)
    local pos = MissionLib.MulVectorLengthRel(
        NObject.GetPosition( { Object = get( "Logic.Wings."..WingId..".leader" ) } ).Position,
        NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position,
        0.01
    )
    pos[2] = pos[2] - 10

    return NCamera.CreatePosCam( {
        Object = get( "Logic.Wings."..WingId..".ship1" ),
        Position = pos,
        Time = 100,
        Immediate = Immediate
    } ).Camera
end

-- Dialogkamera, wenn beide Gesprächspartner in einem Wing sind. Beide sprechen.
-- Dauert lange, muss mit EndComm oder Timer beendet werden!
CameraLib.TalkCamBoth = function( WingId, Immediate )
    local pos = NCamera.GetWingRelPos( { Wing = WingId, Angle = 180 } ).Position
    pos[2] = pos[2] + 10

    return NCamera.CreatePosCam( {
        Object = WingId,
        Position = pos,
        Time = 100,
        Immediate = Immediate
    } ).Camera
end

-- Dialogkamera mit verschiedenen Variationen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.TalkCam = function( ShipId, Time, Zoom, Immediate )
    if not ShipId then ShipId = get( PLAYER_SHIP_ID ); end
    if not Time then Time = 60; end
    if not Zoom or Zoom < 2 then Zoom = 2; end

    -- Aus den verschiedenen geeigneten Splines in TALKCAMLIST einen zufällig auswählen
    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera"..TALKCAMLIST[MissionLib.RandomInt1( 14 )]..".xml",
        Cam = ShipId,
        Aim = ShipId,
        CamOffset = { 0, MissionLib.RandomSignedInt( -10, 10 ), 0 },
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Stehende Dialogkamera vor einem Schiff mit verschiedenen Variationen.
-- Default auf der RECHTEN Seite des Schiffs, LINKS: Side = 1 oder "left".
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.TalkCamStatic = function( ShipId, Time, Zoom, Side, Immediate )
    local offsetX = MissionLib.RandomInt0( 15 )
    if Side == 1 or Side == "left" then offsetX = -offsetX; end
    if not ShipId then ShipId = get( PLAYER_SHIP_ID ); end
    if not Time then Time = 60; end
    if not Zoom or Zoom < 0.5 then Zoom = 0.5; end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera36.xml",
        Cam = ShipId,
        Aim = ShipId,
        CamOffset = { offsetX, MissionLib.RandomInt0( 10 ) - 1, MissionLib.RandomInt0( 5 ) },
        AimOffset = { 0, 0, 7 },
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Standardkamera bei einem Dialog mit Kayron. Zeigt die Darkstar von vorne links.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
-- Optionalen Parameter 'Zoom' hinzugefügt (nk).
CameraLib.TalkCamKayron = function( Time, Zoom, Immediate )
    if not Time then Time = 2000; end
    if not Zoom then Zoom = 0.5; end
    return CameraLib.TalkCamStatic( get( PLAYER_SHIP_ID ), Time, Zoom, 1, Immediate )
end

-- Standardkamera bei einem Dialog mit Eona. Zeigt die Darkstar von vorne rechts.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
-- Optionalen Parameter 'Zoom' hinzugefügt (nk).
CameraLib.TalkCamEona = function( Time, Zoom, Immediate )
    if not Time then Time = 2000; end
    if not Zoom then Zoom = 0.5; end
    return CameraLib.TalkCamStatic( get( PLAYER_SHIP_ID ), Time, Zoom, 0, Immediate )
end

-- Die Kamera ist etwas über dem Spielerschiff angebracht und zeigt in Richtung
-- der übergebenen ShipId. Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCam1 = function( ShipId, Time, Immediate )
    if not Time then Time = 2000; end
    local pos = MissionLib.GetPlayerPos()
    pos[2] = pos[2] + 6

    local camera = NCamera.CreatePosCam( {
        Object = ShipId,
        Position = pos,
        Time = Time,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )

    return camera
end

-- Die Kamera ist etwas unter dem Spielerschiff angebracht und zeigt in Richtung
-- der übergebenen ShipId. Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCam2 = function( ShipId, Time, Immediate )
    if not Time then Time = 2000; end
    local pos = MissionLib.GetPlayerPos()
    pos[2] = pos[2] - 6

    local camera = NCamera.CreatePosCam( {
        Object = ShipId,
        Position = pos,
        Time = Time,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )

    return camera
end

-- Kamera vom Spielerschiff auf den Wing in der Totalen.
-- Dauert lange, sollte mit EndComm oder Timer beendet werden!
-- Originalfunktion stark vereinfacht (nk).
CameraLib.PSTotalBack = function( WingId, Zoom, Immediate )
    local pos = MissionLib.GetPlayerPos()
    pos[2] = pos[2] + 20

    return NCamera.CreatePosCam( {
        Object = WingId,
        Position = pos,
        Time = 100,
        Immediate = Immediate
    } ).Camera
end

-- Kamera schaut vom Spielerschiff aus etwas über den Wing und schwenkt auf den Leader, während sie
-- von der Spielerposition innerhalb von 'Time' schräg links hinter den Wing fährt. Von dort behält
-- sie den Wingleader längere Zeit fest im Blick und sollte mit EndComm oder Timer beendet werden!
CameraLib.ZoomWingCam = function ( WingId, Time, Immediate )
    if not Time then Time = 10; end
    local leader = get( "Logic.Wings."..WingId..".leader" )
    local aimPos = NObject.GetPosition( { Object = leader } ).Position
    local camPos = NCamera.GetWingRelPos( { Wing = WingId, Angle = 30 } ).Position

    local cam1 = NCamera.CreateFreeCam( {
        TabTargetPosition = { MissionLib.AddVectorY( aimPos, 500 ), aimPos },
        TabCamPosition = { MissionLib.GetPlayerPos(), camPos },
        Time = Time,
        Immediate = Immediate
    } ).Camera

    local cam2 = NCamera.CreatePosCam( {
        Object = leader,
        Position = camPos,
        Time = 60
    } ).Camera

    return cam1, cam2
end

-- Kamera zeigt fest auf das Spielerschiff und bewegt sich mit ihm mit.
-- Parameter 'BlackOut' hinzugefügt (nk).
CameraLib.Black = function( Time, BlackOut, Immediate )
    if not Time then Time = 2; end

    local camera = NCamera.CreateObject( {
        Object = get( PLAYER_SHIP_ID ),
        TurnSteps = 0,
        PostSteps = lua.tonumber( Time * 25),	-- MUSS unsigned int sein!
        AngleX1 = 0,
        AngleX2 = 0,
        AngleY1 = 0,
        AngleY2 = 0,
        Distance1 = 50,
        Distance2 = 50,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK } )
    if BlackOut then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )
    end

    return camera
end

-- Diese Kamera fährt seitlich an einem Wing von vorne nach hinten vorbei.
-- Die relative Größe des Wings wird berücksichtigt. Falls sich der Wing bewegt,
-- sollte er ggf. vor oder direkt nach dem Funktionsaufruf eingefroren werden.
CameraLib.FlyThrough = function( WingId, Time, Zoom, Immediate )
    if not Time then Time = 10; end
    if not Zoom or Zoom == 0 then Zoom = 1; end

    -- Raumkoordinaten relativ zum Objekt berechnen, sie bewegen sich nicht mit dem Objekt mit!
    local align = NShip.GetAlignment( { Ship = get( "Logic.Wings."..WingId..".leader" ) } )
    local leaderPos = align.Pos
    -- Zielpositionen
    local frontRel = MissionLib.SubVector(
        leaderPos, NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position
    )
    local frontRelPos = MissionLib.MulVectorLength(
        align.Front, MissionLib.GetVectorLength( frontRel ) * Zoom * 0.7    -- näher vorne dran
    )
    local frontPos = MissionLib.AddVector( leaderPos, frontRelPos )
    local backPos  = MissionLib.SubVector( leaderPos, frontRelPos )
    -- Kamerapositionen
    local sideRelPos = MissionLib.SubVector(
        leaderPos, NCamera.GetWingRelPos( { Wing = WingId, Angle = 90 } ).Position
    )
    local distance = MissionLib.GetVectorLength( sideRelPos ) * Zoom * 0.5  -- näher seitlich dran
    local sideFrontPos = MissionLib.AddVectorX( frontPos, distance )
    local sideBackPos  = MissionLib.AddVectorX( backPos, distance )

    local camera = NCamera.CreateFreeCam( {
        TabTargetPosition = { frontPos, backPos },
        TabCamPosition = { sideFrontPos, sideBackPos },
        Time = Time,
        Immediate = Immediate
    } ).Camera
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )

    return camera
end

-- Zeigt den Beitritt des Spielerschiffs zu einem NPC-Wing.
CameraLib.JoinCam = function( WingId, Immediate )
    local player = get( PLAYER_SHIP_ID )

    NCamera.CreateBoundCam( {
        TargetObject = player,
        BindObject = get( "Logic.Wings."..WingId..".leader" ),
        Distance = -150,
        Time = 3,
        Immediate = Immediate
    } )

    -- Kameraposition vorne über dem Wing
    local pos = NCamera.GetWingRelPos( { Wing = WingId, Angle = 180 } ).Position
    pos[2] = pos[2] + 30
    NCamera.CreatePosCam( {
        Object = WingId,
        Position = pos,
        Time = 1.5
    } )

    return NCamera.CreateObject( {
        Object = player,
        TurnSteps = 0,     -- 0 s
        PostSteps = 75,    -- 3 s
        AngleX1 = 180,
        AngleX2 = 180,
        AngleY1 = 0,
        AngleY2 = 0,
        Distance1 = 200,
        Distance2 = 200
    } ).Camera
end

-- Kamera zeigt einen Wing aus fixer Position. Auswahl aus 4 Kameras (1-4).
-- Ist 'CamNumber' = nil, wird eine der 4 Kameras zufällig ausgewählt (nk).
CameraLib.CamSequence = function( WingId, CamNumber, WaitForCommEnd, Immediate )
    local leader = get( "Logic.Wings."..WingId..".leader" )
    local mintime = { 10, 5, 3, 1.5 }
    if not CamNumber then
        CamNumber = MissionLib.RandomIn1( 4 )
    elseif CamNumber < 1 then
        CamNumber = 1
    elseif CamNumber > 4 then
        CamNumber = 4
    end
    local time = mintime[CamNumber]
    if WaitForCommEnd then time = time + WaitForCommEnd * 100; end

    if CamNumber < 3 then
        -- Position der Kamera näher am Wing (wie getNewCameraPos_ParametricBias)
        return NCamera.CreatePosCam( {
            Object = leader,
            Position = MissionLib.MulVectorLengthRel(
                NObject.GetPosition( { Object = leader } ).Position,
                NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position,
                0.3
            ),
            Time = time,
            Immediate = Immediate
        } ).Camera
    end

    return NCamera.CreateBoundCam( {
        TargetObject = leader,
        BindObject = get( PLAYER_SHIP_ID ),
        Distance = 40,
        Time = time,
        Immediate = Immediate
    } ).Camera
end

------------------------------[ Positionen und allgemeine Funktionen]-----------

-- Setzt den Spieler um den Vektor 'Position' versetzt neben den Leader des Wings.
CameraLib.AlignPlayerToWing = function( WingId, Position )
    if not Position then Position = { 40, 0, 0 }; end
    local align = NShip.GetAlignment( { Ship = get( "Logic.Wings."..WingId..".leader" ) } )
    NShip.SetAlignment( {
        Ship = get( PLAYER_SHIP_ID ),
        Position = MissionLib.AddVector( align.Pos, Position ),
        Front = align.Front,
        UpDir = align.UpDir
    } )
end

-- Setzt den Leader des Wings um den Vektor 'Position' versetzt neben den Spieler,
-- platziert alle weiteren Schiffe auf ihre Wingpositionen und richtet den Wing wie die DSO aus.
CameraLib.AlignWingToPlayer = function( WingId, Position )
    if not Position then Position = { 40, 0, 0 }; end
    NWing.Place( {
        Wing = WingId,
        Position = Position,
        BaseObj = get( PLAYER_SHIP_ID ),
        LookAt = OBJECT_CENTER
    } )
end

-- Friert den Zielwing UND das Spielerschiff ein oder taut es auf.
CameraLib.FreezeWing = function( WingId, Freeze )
    local shiplist = NWing.List( { Wing = WingId } ).ShipList
    shiplist[0] = get( PLAYER_SHIP_ID )
    for i, ship in shiplist do
        NObject.Freeze( { Object = ship, Freeze = Freeze } )
    end
end

-- Diese Funktion ermittelt eine Position vor dem Leader des Wings und modifiziert ihn mit einem Faktor.
-- Positionen mit Faktoren zwischen 0 und 1 liegen näher am Leader und größere als 1 weiter von ihm weg.
-- Bei negativen Faktoren liegt die Position in gleichem Abstand wie die positiven hinter dem Leader.
CameraLib.FrontPos = function( WingId, Factor )
    local align = NShip.GetAlignment( { Ship = get( "Logic.Wings."..WingId..".leader" ) } )
    local leaderPos = align.Pos
    local wingRelPos = NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position
    return MissionLib.GetPosInDistance(
        leaderPos,
        align.Front,
        Factor * MissionLib.GetVectorDistance( leaderPos, wingRelPos )
    )
end

-- Gibt die Koordinaten für eine neue Kameraposition entlang des Vektors CamPos <-> WingPos zurück.
-- Inputs: 'WingId' für einen Wing, 'CamPos' für die aktuelle Kameraposition,
-- 'Offset' in mUnits für die Abweichung der neuen Position entlang des Vektors CamPos/WingPos.
CameraLib.getNewCameraPos_MetricBias = function( WingId, CamPos, Offset )
    local wingPos = NObject.GetPosition( { Object = get( "Logic.Wings."..WingId..".leader" ) } ).Position
    local camPosX, camPosY, camPosZ = CamPos[1], CamPos[2], CamPos[3]

    -- Vektor des Wings relativ zur Kameraposition
    local relPosX = wingPos[1] - camPosX
    local relPosY = wingPos[2] - camPosY
    local relPosZ = wingPos[3] - camPosZ

    -- Länge des relativen Vektors
    local len = math.sqrt( relPosX * relPosX + relPosY * relPosY + relPosZ * relPosZ )

    if len > 0 then
        -- Berechnung der Verschiebung (Umrechnung MilliUnits in Multiplikator)
        local factor = Offset / len
        return { -- Neue Position
            camPosX + factor * relPosX,
            camPosY + factor * relPosY,
            camPosZ + factor * relPosZ
        }
    end
    return CamPos
end

-- Gibt die Koordinaten für eine neue Kameraposition entlang des Vektors CamPos <-> WingPos zurück.
-- Inputs: 'WingId' für einen Wing, 'CamPos' für die aktuelle Kameraposition,
-- 'Zoom' als Floatwert für neue Position entlang des Vektors CamPos/WingPos.
-- Ein Wert von 0 für den Zoom liefert die aktuelle Kameraposition zurück, 1 die Wingposition,
-- Werte zwischen 0 und 1 eine Position näher am Wing, größer 1 eine Position auf der Gegenseite des Wings,
-- negative Werte eine Position weiter weg vom Wing und bisheriger 'CamPos' (-1 = doppelt so weit weg).
CameraLib.getNewCameraPos_ParametricBias = function( WingId, CamPos, Zoom )
    return MissionLib.MulVectorLengthRel(
        NObject.GetPosition( { Object = get( "Logic.Wings."..WingId..".leader" ) } ).Position,
        CamPos,
        Zoom
    )
end

-- Gibt einen halbwegs guten Zoomfaktor für eine Splinekamera zurück.
-- Optionalen Parameter 'ShipId' hinzugefügt, sollte idR der Wingleader sein (nk).
CameraLib.GetZoomFactor = function( WingId, ShipId )
    if not ShipId then
        ShipId = get( "Logic.Wings."..WingId..".leader" )
    end
    local distance = MissionLib.GetVectorDistance(
        NObject.GetPosition( { Object = ShipId } ).Position,
        NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position
    )
    return distance / 16.0 + 0.6
end

--------------------------------------------------------------------------------

--CameraLib.BigBoy = function( WingId, Time, Zoom )
-- Ähnliche Kamera ist bereits weiter oben mit dem selben Namen definiert.
-- Diese Kamera fährt seitlich an einem Wing von vorne nach hinten vorbei,
-- die relative Größe wird berücksichtigt, Objekt wird angehalten.
--    local frontCloser = 0.7    -- näher dran vorne
--    local sideCloser = 0.3        -- näher dran seite
--    local targetWing = WingId
--    local targetLeader = get( "Logic.Wings."..targetWing..".leader" )
--    local align = NShip.GetAlignment( { Ship = targetLeader } )
--    local leaderPos = align.Pos
--
-- Positionen um das Objekt berechnen, Raumkoordinaten relativ zum Objekt,
-- bewegen sich nicht mit dem Objekt mit!
--
--    local dist = NCamera.GetWingRelPos( { Wing = targetWing, Angle = 0 } ).Position
--    dist = NVector.Sub( { Vector1 = leaderPos, Vector2 = dist } ).Vector
--    frontDist = frontCloser * math.sqrt( dist[1]*dist[1] + dist[2]*dist[2] + dist[3]*dist[3] )
--    local frontPos = {
--        align.Front[1] * frontDist,
--        align.Front[2] * frontDist,
--        align.Front[3] * frontDist
--    }
--    frontPos = NVector.Add( { Vector1 = frontPos , Vector2 = leaderPos } ).Vector
--    local backDist = -1 * frontDist
--    local backPos = {
--        align.Front[1] * backDist,
--        align.Front[2] * backDist,
--        align.Front[3] * backDist
--    }
--    backPos = NVector.Add( { Vector1 = backPos , Vector2 = leaderPos } ).Vector
--    dist = NCamera.GetWingRelPos( { Wing = targetWing, Angle = 90 } ).Position
--    dist = NVector.Sub( { Vector1 = leaderPos, Vector2 = dist } ).Vector
--    sideDist = sideCloser * math.sqrt( dist[1]*dist[1] + dist[2]*dist[2] + dist[3]*dist[3] )
--
--    local sideFrontPos = { frontPos[1] + sideDist, frontPos[2], frontPos[3] }
--    local sideBackPos = { backPos[1] + sideDist, backPos[2], backPos[3] }
--
--    CameraLib.FreezeWing( WingId, true )
--
--    Camera = NCamera.CreateFreeCam( {
--        TabTargetPosition = { leaderPos },
--        TabCamPosition = { frontPos, sideFrontPos, sideBackPos, backPos },
--        Time=Time,
--        Immediate = false
--    } ).Camera
--    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_IN } )
--    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )
--
--    CameraLib.FreezeWing( WingId, false )
--
--    return camera
--end

--********************* Beispiel-Transitions *********************--

--    local _p1 = NObject.GetPosition( { Object = V.Player } ).Position
--    local _p2 = NObject.GetPosition( { Object = V.TargetLeader } ).Position
--    local _vec = NVector.Sub( { Vector1 = _p1, Vector2 = _p2 } ).Vector
--    local distance = math.sqrt( _vec[1]*_vec[1] + _vec[2]*_vec[2] + _vec[3]*_vec[3] )
--    local Distance = MissionLib.GetObjectDistance( V.Sat0, V.Wing1 )
--    local steps = 50
--    for counter = 1, steps do
--        V.Camera = NCamera.CreateBoundCam( {
--            TargetObject = V.TargetObject,
--            BindObject = V.BindObject,
--            Distance = distance * 0.9 / steps * counter,
--            Time = 0.075
--        } ).Camera
--    end

--    V.Camera = NCamera.CreateObject( {
--        Object = V.TargetWingHandle,
--        TurnSteps = 125,
--        PostSteps = 25,
--        AngleX1 = 45,
--        AngleX2 = 15,
--        AngleY1 = 180,
--        AngleY2 = 0,
--        Distance1 = 50,
--        Distance2 = 150,
--        Immediate = false
--    } ).Camera

--------------------------------------------------------------------------------

-- Blick von hinter dem Spieler Richtung Wing, 2 harte Schnitte zum Wing,
-- dann hinter dem Wing herschauen.
--    Ersatz für eine Fahrt
--    local _vec = NVector.Sub( { Vector1=_leaderPos, Vector2=_playerPos } ).Vector
--    local _distance = math.sqrt( _vec[1]*_vec[1] + _vec[2]*_vec[2] + _vec[3]*_vec[3] )
--    local steps=2
--    local _time = 1.5
--    for counter=0,steps do
--        Camera = NCamera.CreateBoundCam( {
--            TargetObject=_leader,
--            BindObject = _player,
--            Distance = ( _distance/steps * counter ) - 200,
--            Time= _time,
--            Immediate = false
--        } ).Camera
--    end

--------------------------------------------------------------------------------

-- Zusätzliche Funktionen einbinden
source "lua/mission/CameraLibEx.lua"
CameraLib.lua Quellcode Ende


CameraLibEx

Die Skriptbibliothek "CameraLibEx.lua" ist eine Erweiterung der mit Darkstar One ausgelieferten CameraLib.lua. Die CameraLibEx.lua beinhaltet eine Anzahl von weiteren vorgefertigten Kameras.
Um die Funktionen nutzen zu können, muss die CameraLibEx.lua zuerst im Skript importiert werden. Dies geschieht automatisch mit dem Import der CameraLib.lua, wenn dort die Zeile source "lua/mission/CameraLibEx.lua" am Ende hinzugefügt wurde. Andernfalls gilt dasselbe wie für die CameraLib.lua:

------------------------------[ Import ]---------------------------------------
source "lua/mission/CameraLib.lua"
source "lua/mission/CameraLibEx.lua"
-------------------------------------------------------------------------------

Quellcode der CameraLibEx.lua
--------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]------------------------------------------
-- Name: CameraLibEx.lua
-- Author: [SNF]Norbert
-- Version: 2.6
------------------------------[ Description ]-----------------------------------
-- Weitere vorgefertigte Kameras
------------------------------[ Import ]----------------------------------------

------------------------------[ Die Kameras ]-----------------------------------

-- Die Kamera ist vorne am Spielerschiff angebracht und zeigt in Richtung des übergebenen
-- Objekts (Schiff oder Spaceobjekt). Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamFront = function( ObjectId, Time, Shake, Immediate )
    if not Time then Time = 2000; end
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )

    local camera = NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = MissionLib.GetPosInDistance( align.Pos, align.Front, 10 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist hinten am Spielerschiff angebracht und zeigt in Richtung des übergebenen
-- Objekts (Schiff oder Spaceobjekt). Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamBack = function( ObjectId, Time, Shake, Immediate )
    if not Time then Time = 2000; end
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )

    local camera = NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = MissionLib.GetPosInDistance( align.Pos, align.Front, -10 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist links neben dem Spielerschiff angebracht und zeigt in Richtung des übergebenen
-- Objekts (Schiff oder Spaceobjekt). Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamLeft = function( ObjectId, Time, Shake, Immediate )
    if not Time then Time = 2000; end
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )
    -- Ausrichtung um 90° zur linken Seite drehen
    local left = MissionLib.RotateVector( align.Front, 0.0, PI * 1.5 )

    local camera = NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = MissionLib.GetPosInDistance( align.Pos, left, 10 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist rechts neben dem Spielerschiff angebracht und zeigt in Richtung des übergebenen
-- Objekts (Schiff oder Spaceobjekt). Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamRight = function( ObjectId, Time, Shake, Immediate )
    if not Time then Time = 2000; end
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )
    -- Ausrichtung um 90° zur rechten Seite drehen
    local right = MissionLib.RotateVector( align.Front, 0.0, PI * 0.5 )

    local camera = NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = MissionLib.GetPosInDistance( align.Pos, right, 10 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist etwas über dem Spielerschiff angebracht und zeigt in Richtung des übergebenen
-- Objekts (Schiff oder Spaceobjekt). Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamTop = function( ObjectId, Time, Shake, Immediate )
    if not Time then Time = 2000; end
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )

    local camera = NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = MissionLib.GetPosInDistance( align.Pos, align.UpDir, 6 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist etwas unter dem Spielerschiff angebracht und zeigt in Richtung des übergebenen
-- Objekts (Schiff oder Spaceobjekt). Ideal, um Angriffe auf das Spielerschiff zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamBottom = function( ObjectId, Time, Shake, Immediate )
    if not Time then Time = 2000; end
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )

    local camera = NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = MissionLib.GetPosInDistance( align.Pos, align.UpDir, -6 ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist vorne am Spielerschiff angebracht und zeigt geradeaus in Flugrichtung.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipCamLookAhead = function( Time, Shake, Immediate )
    if not Time then Time = 2000; end

    local camera = NCamera.CreateFreeCam( {
        TabTargetPosition = { { 0, 0, 20 } },
        TabCamPosition = { { 0, 0, 10 } },
        BaseObj = get( PLAYER_SHIP_ID ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
    if Shake then
        NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_SHAKE } )
    end

    return camera
end

-- Die Kamera ist etwas neben dem Spielerschiff in Richtung der übergebenen Position angebracht
-- und zeigt fest auf sie. Ideal, um allgemeine Vorgänge in der Umgebung der Position zu zeigen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipPosCam = function( Position, Time, Immediate )
    if not Time then Time = 2000; end

    return NCamera.CreateFreeCam( {
        TabTargetPosition = { Position },
        TabCamPosition = { MissionLib.AddToVectorLengthRel( MissionLib.GetPlayerPos(), Position, -6 ) },
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Statische Kamera, die aus der Richtung des Spielerschiffs auf ein Objekt oder eine Position schaut.
-- 'ObjectPos' darf entweder eine Positionsangabe oder ein Objekthandle sein, jedoch keine WingId.
-- 'Distance' ist der Kameraabstand zur Position bzw. zum beobachteten Objekt. Ist die Distanz größer als
-- die Entfernung des Spielerschiffs, ist es ebenfalls zu sehen und kann eventuell das Objekt verdecken.
-- Negative Distanzen platzieren die Kamera vom Schiff aus gesehen hinter die Position oder das Objekt.
-- Mit dem optionalen 3D-Vektor 'ObjectOfs' kann zur Zielposition ein Offset addiert werden, sodass die
-- Kamera nicht direkt auf 'ObjectPos' schaut. Auf die Kameraposition hat dieser Offset keinen Einfluss.
CameraLib.PlayerShipCamLookAt = function( ObjectPos, Distance, Time, ObjectOfs, Immediate )
    if not Time then Time = 2000; end
    if lua.type( ObjectPos ) == "number" then
        ObjectPos = NObject.GetPosition( { Object = ObjectPos } ).Position
    end
    local camPos = MissionLib.SetVectorLengthRel( MissionLib.GetPlayerPos(), ObjectPos, Distance )
    if ObjectOfs then
        ObjectPos = MissionLib.AddVector( ObjectPos, ObjectOfs )
    end

    return NCamera.CreateFreeCam( {
        TabTargetPosition = { ObjectPos },
        TabCamPosition = { camPos },
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera vom Spielerschiff auf ein Objekt im All (CWingHandle oder CObjectHandle).
-- 'RelCamPos' ist ein Vektor relativ zum Spielerschiff für die Kameraposition,
-- 'DummyObj' ein Hilfswegpunkt für die Platzierung der Kamera, der beim ersten Aufruf der Funktion
-- automatisch erzeugt und bei weiteren Aufrufen durch Übergabe seines Handles wiederverwendet wird.
-- Dauert lange, muss mit EndComm oder Timer beendet werden!
CameraLib.PlayerShipObjectCam = function( ObjectId, RelCamPos, DummyObj, Immediate )
    if not DummyObj then
        DummyObj = NWaypoint.Create( { Position = OBJECT_CENTER, Radius = 1 } ).Waypoint
    end
    NObject.Place( { Object = DummyObj, BaseObj = get( PLAYER_SHIP_ID ), Position = RelCamPos } )

    return NCamera.CreatePosCam( {
        Object = ObjectId,
        Position = NObject.GetPosition( { Object = DummyObj } ).Position,
        Time = 2000,
        Immediate = Immediate
    } ).Camera, DummyObj
end

-- Kamera zeigt einen Wing aus fixer Position und frei wählbarem Winkel.
CameraLib.WingCam = function( WingId, Angle, Time, Immediate )
    if not Angle then Angle = 0; end
    if not Time then Time = 10; end

    return NCamera.CreatePosCam( {
        Object = get( "Logic.Wings."..WingId..".leader" ),
        Position = NCamera.GetWingRelPos( { Wing = WingId, Angle = Angle } ).Position,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera startet mit der Ansicht des gesamten Wings im relativen Winkel 'Angle'
-- (default 0° = direkt hinter dem Wing) und fährt einmal komplett um ihn herum.
-- Wird 'OffsetY' übergeben, zeigt die Kamera den Wing von schräg oben oder unten.
-- Mit 'Turns' kann die Anzahl der Umkreisungen auf maximal 100 erhöht werden,
-- die übergebene Zeit gilt dabei weiterhin für jede einzelne Umrundung des Wings.
CameraLib.CircleWing = function( WingId, Time, Angle, OffsetY, Turns, Immediate )
    local leader = get( "Logic.Wings."..WingId..".leader" )
    local leaderPos = NObject.GetPosition( { Object = leader } ).Position
    local cameraPos = {}
    local SubVector = MissionLib.SubVector
    local CamRelPos = NCamera.GetWingRelPos

    if not Time then Time = 30; end
    if not Angle then Angle = 0; end
    if OffsetY then leaderPos[2] = leaderPos[2] - OffsetY; end

    for i = 1, 8 do
        cameraPos[i] = SubVector( CamRelPos( { Wing = WingId, Angle = Angle } ).Position, leaderPos )
        Angle = Angle + 45
    end
    local segments = 9	-- Anzahl aller 45°-Positionen; mindestens 8 + 1, um den Kreis zu schließen
    if Turns and Turns > 1 then
        if Turns > 100 then Turns = 100; end
        segments = Turns * 8 + 1
        Time = Time * Turns
    end
    for i = 9, segments do
        cameraPos[i] = cameraPos[i-8]
    end

    return NCamera.CreateFreeCam( {
        TabTargetPosition = { WING_CENTER },
        TabCamPosition = cameraPos,
        BaseObj = leader,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera zeigt von einer festen Position aus einen ganzen Wing von hinten beim Wegfliegen.
-- Nach Ablauf der Zeit folgt die Kamera dem Leader in einem geringen Abstand.
-- Wie FreighterHyperspace, besser für Hunterwings vor und während dem Hyperraumsprung geeignet.
CameraLib.HunterHyperspace = function( WingId, Time, Immediate )
    if not Time then Time = 8; end
    local leader = get( "Logic.Wings."..WingId..".leader" )

    NCamera.CreatePosCam( {
        Object = leader,
        Position = NCamera.GetWingRelPos( { Wing = WingId, Angle = 0 } ).Position,
        Time = Time,
        Immediate = Immediate
    } )

    return NCamera.CreateObject( {
        Object = leader,
        TurnSteps = 100,    -- 4.0 s
        PostSteps = 200,    -- 8.0 s
        AngleX1 = 0,
        AngleX2 = 0,
        AngleY1 = 0,
        AngleY2 = 0,
        Distance1 = 150,
        Distance2 = 300
    } ).Camera
end

-- Zeigt, wie der Frachter einen Container abwirft.
-- In 'CamOffset' kann eine Abweichung von der Kameraposition übergeben werden.
-- Standardmäßig steht die Kamera frontal und leicht überhöht vor dem Schiff.
CameraLib.ContainerDrop2 = function( WingId, ContainerId, Time, CamOffset, Immediate )
    if not Time then Time = 10; end
    if not CamOffset then CamOffset = { 0, 10, 0 }; end

    return NCamera.CreatePosCam( {
        Object = ContainerId,
        Position = MissionLib.AddVector( CameraLib.FrontPos( WingId, 0.7 ), CamOffset ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera fährt auf einen Container (Spezialcontainer) zu und dreht sich um ihn herum.
CameraLib.RewardContainer2 = function( ContainerId, Time, Zoom, Immediate )
    if not Time then Time = 12; end
    if not Zoom then Zoom = 0.5; end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera1.xml",
        Cam = ContainerId,
        Aim = ContainerId,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera fährt auf einen Satelliten zu und bleibt kurz vor ihm eine Sekunde lang stehen.
-- Wird kein TurnAngle angegeben oder ist er 0, zoomt die Kamera geradeaus auf den Satelliten zu.
-- Positive Winkel schwenken die Kamera während der Fahrt im Uhrzeigersinn um den Satelliten herum
-- und negative dagegen. Die Angabe "Random" schwenkt sie zwischen -45° bis +45° um den Satelliten.
CameraLib.CloseUpSatellite = function( ShipId, TurnAngle, Immediate )
    if not TurnAngle then
        TurnAngle = 0
    elseif TurnAngle == "Random" then
        TurnAngle = MissionLib.RandomSignedInt( -45, 45 )
    end

    return NCamera.CreateObject( {
        Object = ShipId,
        TurnSteps = 100,	-- 4.0 s
        PostSteps = 25,		-- 1.0 s
        AngleX1 = 0,
        AngleX2 = 0,
        AngleY1 = 180,
        AngleY2 = 180 + TurnAngle,
        Distance1 = 200,
        Distance2 = 20,
        Immediate = Immediate
    } ).Camera
end

-- Spezialkamera für KI-Schiff mit Spieler in Formation 21 (FORMATION_PLAYER_NPC).
-- Kamera steht um 'Offset' versetzt beim 'CamObj' und schaut auf das Ziel 'AimObj'.
-- Dauert lange und sollte mit EndComm oder Timer beendet werden!
CameraLib.DialogCam = function( CamObj, AimObj, Offset, Filter, Immediate )
    local camera = NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera7.xml",
        Cam = CamObj,
        Aim = AimObj,
        CamOffset = Offset,
        AimOffset = OBJECT_CENTER,
        Zoom = 0,
        Time = 2000,
        Immediate = Immediate
    } ).Camera
    if Filter then
        NCamera.AddFilter( { Camera = camera, Filter = Filter } )
    end
    return camera
end

-- Dialogkamera, wenn die Gesprächspartner in einem Wing sind.
-- Wie "CameraLib.TalkCamLeader", es wird jedoch ein Wingman gezeigt.
-- Für 'ShipId' kann das Schiffshandle des Wingman oder sein Index von 1 bis 10 übergeben werden.
-- Wird ein Index angegeben, muss man auch die WingId übergeben, beim Handle kann man sie weglassen.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.TalkCamMember = function( WingId, ShipId, Time, Immediate )
    if ShipId <= 10 and ShipId > 0 then
        ShipId = get( "Logic.Wings."..WingId..".ship"..ShipId )
    elseif not WingId then
        WingId = get( "Logic.StarShips."..ShipId..".wingId", nil )
    end
    if not Time then Time = 60; end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera0.xml",
        Cam = ShipId,
        Aim = ShipId,
        CamOffset = { 0, MissionLib.RandomSignedInt( -10, 10 ), 0 },
        AimOffset = OBJECT_CENTER,
        Zoom = CameraLib.GetZoomFactor( WingId, ShipId ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Stehende Dialogkamera für die Unterhaltung zwischen beliebigen Mitgliedern des Wings.
-- Wurde kein Member übergeben oder ist gleich 0, wird der Wingleader verwendet.
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.TalkCamMemberStatic = function( WingId, Member, Time, Zoom, Immediate )
    if not Time then Time = 60; end
    if not Zoom then Zoom = 0.7; end  -- Position der Kamera näher am Wing

    -- Kamera steht direkt vor dem Wing und schaut auf den Sprecher
    return NCamera.CreatePosCam( {
        Object = MissionLib.GetWingMember( WingId, Member ),
        Position = MissionLib.MulVectorLengthRel( -- siehe CameraLib.getNewCameraPos_ParametricBias
            NObject.GetPosition( { Object = get( "Logic.Wings."..WingId..".leader" ) } ).Position,
            NCamera.GetWingRelPos( { Wing = WingId, Angle = 180 } ).Position,
            Zoom
        ),
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Schöne Dialogkameras in verschiedenen Variationen (Spline = 1..14 oder "Random").
-- Dauert lange, wenn keine Zeit übergeben wird. Sollte mit EndComm oder Timer beendet werden!
CameraLib.TalkCamSpline = function( Object, Spline, Time, Zoom, Immediate )
    if not Object or Object == "Player" then
        Object = get( PLAYER_SHIP_ID )
    end
    if not Time then Time = 60; end
    if not Zoom then Zoom = 2; end

    -- Aus den verschiedenen geeigneten Splines einen auswählen
    if not Spline or Spline == "Random" then
        Spline = MissionLib.RandomInt1( 14 )
    elseif Spline < 1 or Spline > 14 then
        Spline = 1
    end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera"..TALKCAMLIST[Spline]..".xml",
        Cam = Object,
        Aim = Object,
        CamOffset = { 0, MissionLib.RandomSignedInt( -10, 10 ), 0 },  -- Verschiedene Y-Offsets
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera fährt rechtsherum seitlich an einem Objekt von vorne nach hinten vorbei.
-- Wie "CameraLib.BigBoy", aber ohne Filter und es kann ein beliebiges Objekt übergeben werden.
CameraLib.BigBoyObject = function( Object, Time, Zoom, Immediate )
    local leader = get( "Logic.Wings."..Object..".leader", nil )
    if leader then Object = leader; end
    if not Time then Time = 12; end
    if not Zoom then Zoom = 15; end

    return NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera19.xml",
        Cam = Object,
        Aim = Object,
        CamOffset = { 0, MissionLib.RandomSignedInt( -30, 30 ), 0 },
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- Kamera zeigt ein großes Objekt, fährt um dieses herum und folgt ihm dabei, falls es sich bewegt.
-- 'Zoom' ist ein optionaler Faktor für den Abstand der vorgegebenen Kamerapositionen zum Objekt
-- und mit dem optionalen Vektor 'Offset' kann ihnen noch ein Versatz übergeben werden.
CameraLib.ShowObject = function( Object, Time, Zoom, Offset, Immediate )
    if not Time then Time = 30; end

    local cameraPos = {
        { 0, -200, 600 },
        { 100, -100, 400 },
        { 200, 100, 200 },
        { 300, 300, 100 },
        { 300, 500, 100 },
        { -200, 500, 200 },
        { -400, 300, 100 },
        { -500, 100, 100 },
        { 0, 0, 1500 }
    }

    if Zoom and ( Zoom < 1 or Zoom > 1 ) then
        if Offset then
            local offsetX, offsetY, offsetZ = Offset[1], Offset[2], Offset[3]
            for i, pos in cameraPos do
                pos[1] = pos[1] * Zoom + offsetX
                pos[2] = pos[2] * Zoom + offsetY
                pos[3] = pos[3] * Zoom + offsetZ
            end
        else
            for i, pos in cameraPos do
                pos[1] = pos[1] * Zoom
                pos[2] = pos[2] * Zoom
                pos[3] = pos[3] * Zoom
            end
        end

    elseif Offset then
        local offsetX, offsetY, offsetZ = Offset[1], Offset[2], Offset[3]
        for i, pos in cameraPos do
            pos[1] = pos[1] + offsetX
            pos[2] = pos[2] + offsetY
            pos[3] = pos[3] + offsetZ
        end
    end

    return NCamera.CreateFreeCam( {
        TabTargetPosition = { OBJECT_CENTER },
        TabCamPosition = cameraPos,
        BaseObj = Object,
        Time = Time,
        Immediate = Immediate
    } ).Camera
end

-- ActionCams.ini: Objektkamera "TurnInfo005" für ein kurzes "Bildflackern".
-- Existiert der Parameter 'Immediate' und ist true, startet die Kamera sofort.
CameraLib.ObjectCamTurn0 = function( Object, Immediate )
    return NCamera.CreateObject( {
        Object = Object,
        TurnSteps = 1,		-- 0.04 s
        PostSteps = 0,		-- 0 s
        AngleX1 = 0,
        AngleX2 = 0,
        AngleY1 = 0,
        AngleY2 = 0,
        Distance1 = 0,
        Distance2 = 0,
        Immediate = Immediate
    } ).Camera
end

-- Die 5 folgenden ObjectCamTurn-Kameras drehen sich auf verschiedenen Bahnen um ein Objekt herum.

-- ActionCams.ini: Objektkamera "TurnInfo000" für große Ziele (Kreuzer, Stationen).
-- Existiert der Parameter 'Immediate' und ist true, startet die Kamera sofort.
CameraLib.ObjectCamTurn1 = function( Object, Immediate )
    return NCamera.CreateObject( {
        Object = Object,
        TurnSteps = 290,	-- 11.6 s
        PostSteps = 20,		-- 0.8 s
        AngleX1 = 18,
        AngleX2 = 8,
        AngleY1 = -150,
        AngleY2 = 80,
        Distance1 = 1300,
        Distance2 = 150,
        Immediate = Immediate
    } ).Camera
end

-- ActionCams.ini: Objektkamera "TurnInfo001" für mittelgroße Ziele (Frachter, Jäger).
-- Existiert der Parameter 'Immediate' und ist true, startet die Kamera sofort.
CameraLib.ObjectCamTurn2 = function( Object, Immediate )
    return NCamera.CreateObject( {
        Object = Object,
        TurnSteps = 320,	-- 12.8 s
        PostSteps = 0,		-- 0 s
        AngleX1 = -8,
        AngleX2 = 35,
        AngleY1 = 180,
        AngleY2 = 45,
        Distance1 = 350,
        Distance2 = 50,
        Immediate = Immediate
    } ).Camera
end

-- ActionCams.ini: Objektkamera "TurnInfo002" für mittelgroße Ziele (Frachter, Jäger).
-- Existiert der Parameter 'Immediate' und ist true, startet die Kamera sofort.
CameraLib.ObjectCamTurn3 = function( Object, Immediate )
    return NCamera.CreateObject( {
        Object = Object,
        TurnSteps = 210,	-- 8.4 s
        PostSteps = 10,		-- 0.4 s
        AngleX1 = -15,
        AngleX2 = 20,
        AngleY1 = 110,
        AngleY2 = 220,
        Distance1 = 350,
        Distance2 = 35,
        Immediate = Immediate
    } ).Camera
end

-- ActionCams.ini: Objektkamera "TurnInfo003" für mittelgroße Ziele (Frachter, Jäger).
-- Existiert der Parameter 'Immediate' und ist true, startet die Kamera sofort.
CameraLib.ObjectCamTurn4 = function( Object, Immediate )
    return NCamera.CreateObject( {
        Object = Object,
        TurnSteps = 300,	-- 12.0 s
        PostSteps = 10,		-- 0.4 s
        AngleX1 = 5,
        AngleX2 = -5,
        AngleY1 = 195,
        AngleY2 = 145,
        Distance1 = 100,
        Distance2 = 50,
        Immediate = Immediate
    } ).Camera
end

-- ActionCams.ini: Objektkamera "TurnInfo004" für kleine bis mittlere Ziele (Container, Jäger).
-- Existiert der Parameter 'Immediate' und ist true, startet die Kamera sofort.
CameraLib.ObjectCamTurn5 = function( Object, Immediate )
    return NCamera.CreateObject( {
        Object = Object,
        TurnSteps = 270,	-- 10.8 s
        PostSteps = 10,		-- 0.4 s
        AngleX1 = 1,
        AngleX2 = 45,
        AngleY1 = -165,
        AngleY2 = -33,
        Distance1 = 60,
        Distance2 = 90,
        Immediate = Immediate
    } ).Camera
end

-- Erzeugt eine Dummy Kamera.
CameraLib.Dummy = function()
    return CameraLib.ObjectCamTurn0( get( PLAYER_SHIP_ID ), true )
end

-- Erzeugt eine Dummy Kamera, die eine aktuell laufende sowie alle nachfolgenden Kameras
-- und auch sich selbst sofort zerstört. Hat keine Auswirkung, wenn gerade keine Kamera läuft.
CameraLib.Destroy = function()
    NCamera.Destroy( { Camera = NCamera.CreateBoundCam( {
        TargetObject = get( PLAYER_SHIP_ID ), Immediate = true
    } ) } )
end

-- Eine kurz laufende Kamera für die nächsten beiden Funktionen "BlackOut" und "WhiteOut".
CameraLib.ShortCam = function( Object, Zoom )
    if not Zoom then Zoom = 1; end

    local camera = NCamera.CreateSplineCam( {
        Name = "3dview/ActionCams/SplineKamera10x.xml",
        Cam = Object,
        Aim = Object,
        CamOffset = OBJECT_CENTER,
        AimOffset = OBJECT_CENTER,
        Zoom = Zoom,
        Time = 0.5,
        Immediate = true
    } ).Camera

    return camera
end

-- Kamera, die eine andere Kamera, welche auf 'Object' zeigt, mit BlackOut beendet.
-- Der Zoomfaktor sollte derselbe sein, wie der von der anderen Kamera. Die Variable der anderen
-- Kamera sollte entweder von dieser hier überschrieben oder sofort im Anschluss gelöscht werden.
CameraLib.BlackOut = function( Object, Zoom )
    local camera = CameraLib.ShortCam( Object, Zoom )
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_BLACK_OUT } )
    return camera
end

-- Kamera, die eine andere Kamera, welche auf 'Object' zeigt, mit WhiteOut beendet.
CameraLib.WhiteOut = function( Object, Zoom )
    local camera = CameraLib.ShortCam( Object, Zoom )
    NCamera.AddFilter( { Camera = camera, Filter = CAMERA_FILTER_WHITE_OUT } )
    return camera
end

-- Bild bleibt beim Kamerastart eine halbe Sekunde schwarz.
CameraLib.AddFilterBlack = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK } )
end

-- Blendet beim Kamerastart aus schwarz ein.
CameraLib.AddFilterBlackIn = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK_IN } )
end

 -- Blendet am Kameraende nach schwarz aus.
CameraLib.AddFilterBlackOut = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK_OUT } )
end

-- Blendet beim Kamerastart aus schwarz ein und am Kameraende nach schwarz aus.
CameraLib.AddFilterBlackInOut = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK_IN } )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK_OUT } )
end

-- Blendet beim Kamerastart aus schwarz ein und am Kameraende nach weiß aus.
CameraLib.AddFilterBlackInWhiteOut = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK_IN } )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_WHITE_OUT } )
end

-- Blendet beim Kamerastart aus weiß ein.
CameraLib.AddFilterWhiteIn = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_WHITE_IN } )
end

-- Blendet am Kameraende nach weiß aus.
CameraLib.AddFilterWhiteOut = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_WHITE_OUT } )
end

-- Blendet beim Kamerastart aus weiß ein und am Kameraende nach weiß aus.
CameraLib.AddFilterWhiteInOut = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_WHITE_IN } )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_WHITE_OUT } )
end

-- Blendet beim Kamerastart aus weiß ein und am Kameraende nach schwarz aus.
CameraLib.AddFilterWhiteInBlackOut = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_WHITE_IN } )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLACK_OUT } )
end

-- Das Bild wird während der gesamten Kameralaufzeit weichgezeichnet.
CameraLib.AddFilterBlur = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_BLUR } )
end

-- Kamera wackelt während ihrer gesamten Laufzeit.
CameraLib.AddFilterShake = function( Camera )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_SHAKE } )
end

-- Blendet beim Kamerastart nach weiß ein und geht dann wieder auf die normalen Werte zurück.
-- 'TimeIn' ist die Dauer der Blende nach weiß in Sekunden,
-- 'TimeOut' die Dauer der Blende von weiss auf die normalen Werte in Sekunden.
CameraLib.AddFilterFlash = function( Camera, TimeIn, TimeOut )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_FLASH, Value1 = TimeIn, Value2 = TimeOut } )
end

-- Field Of View: Ändert kontinuierlich den Kamerawinkel.
-- 'Time' ist die Dauer bis zur maximalen Winkeländerung in Sekunden,
-- 'Zoom' ist der Faktor für den Kamerawinkel, positive Werte zoomen weg und negative heran.
CameraLib.AddFilterFOV = function( Camera, Time, Zoom )
    NCamera.AddFilter( { Camera = Camera, Filter = CAMERA_FILTER_FOV, Value1 = Time, Value2 = Zoom } )
end
CameraLibEx.lua Quellcode Ende


PlayerShipCamBack

Syntax

PlayerShipCamBack( ShipId, Time )

Beschreibung

Beispiel


PlayerShipCamBottom

Syntax

PlayerShipCamBottom( ShipId, Time )

Beschreibung

Beispiel


PlayerShipCamFront

Syntax

PlayerShipCamFront( ShipId, Time )

Beschreibung

Beispiel


PlayerShipCamLeft

Syntax

PlayerShipCamLeft( ShipId, Time )

Beschreibung

Beispiel


PlayerShipCamRight

Syntax

PlayerShipCamRight( ShipId, Time )

Beschreibung

Beispiel


PlayerShipCamTop

Syntax

PlayerShipCamTop( ShipId, Time )

Beschreibung

Beispiel


MissionLib

Die Skriptbibliothek "MissionLib.lua" ist in der Installation frei zugänglich und beinhaltet eine Vielzahl von hilfreichen Zusatzfunktionen. Die hier vorliegende Fassung der Datei ist eine überarbeitete, optimierte und fehlerbereinigte Version. Des Weiteren sind jetzt die Funktionen für eine bessere Übersicht in logische Gruppen gegliedert. Alle Funktionen wurden nach den Änderungen auf korrekte Arbeitsweise getestet.
Um die Funktionen nutzen zu können, muss die MissionLib.lua zuerst im Skript importiert werden:

------------------------------[ Import ]---------------------------------------
source "lua/mission/MissionLib.lua"
-------------------------------------------------------------------------------

Quellcode der MissionLib.lua
--------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) Ascaron Entertainment GmbH
-- All Rights Reserved.
------------------------------[ Info ]------------------------------------------
-- Name: MissionLib.lua
-- Version: #0.4
-- Build Version 2.7.1 by [SNF]Norbert
------------------------------[ Description ]-----------------------------------
-- Verschiedene Hilfsfunktionen
------------------------------[ Notes ]-----------------------------------------
-- Optimiert, neu gegliedert und einige Fehler beseitigt.
-- Zusätzliche Funktionen durch Import der MissionLibEx.lua eingebunden.
--
------------------------------[ Import ]----------------------------------------

import "lua"
import "math"
import "PropertySystem"
import "ps"		-- Property System (StarFinder, get und set)
import "NCamera"
import "NComm"
import "NContainer"
import "NGame"
import "NGroupAi"
import "NGUI"
import "NMission"
import "NNPC"
import "NObject"
import "NPlayer"
import "NScript"
import "NShip"
import "NSound"
import "NStarSystem"
import "NTerminal"
import "NVector"
import "NWaypoint"
import "NWing"

------------------------------[ Collection ]------------------------------------

MissionLib = {}

------------------------------[ Orbiter ]---------------------------------------

-- Listet alle Orbiter des gleichen Typs im aktuellen System auf und liefert deren Typen
MissionLib.ListSystemOrbiter = function( OrbiterType )
    local orbiterlist = {}
    local idx = 0
    while NStarSystem.GetOrbiter( { Type = OrbiterType, Index = idx, Mode = 0 } ).Valid do
        idx = idx + 1
        orbiterlist[idx] = OrbiterType
    end
    return orbiterlist
end

-- Sucht einen (ersten) Orbiter im aktuellen System und liefert dessen Handle
MissionLib.GetSystemOrbiter = function( OrbiterType )
    local object = NStarSystem.GetOrbiter( { Type = OrbiterType, Index = 0, Mode = 0 } )
    if object.Valid then
        return object.Orbiter
    end
end

-- Anzahl aller Orbiter des gleichen Typs im aktuellen System
MissionLib.GetSystemOrbiterCount = function( OrbiterType )
    local idx = 0
    while NStarSystem.GetOrbiter( { Type = OrbiterType, Index = idx, Mode = 0 } ).Valid do
        idx = idx + 1
    end
    return idx
end

-- Sucht die TradeStation im aktuellen System
MissionLib.GetSystemTradeStation = function()
    local handle = NStarSystem.GetTradeStation({}).Handle
    if handle > 0 then
        return handle
    end
end

-- Sucht die erste Forschungsstation im aktuellen System
MissionLib.GetSystemResearchStation = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_STATION )
end

-- Sucht den ersten Asteroiden im aktuellen System
MissionLib.GetSystemAsteroid = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_ASTEROID )
end

-- Sucht das HyperGate im aktuellen System
MissionLib.GetSystemHyperGate = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_GATE )
end

-- Sucht die erste Anomalie im aktuellen System
MissionLib.GetSystemAnomalie = function()
    local handle = NObject.GetAnomalie({}).Handle
    if handle > 0 then
        return handle
    end
end

-- Sucht das erste Meteoritenfeld im aktuellen System
MissionLib.GetSystemMeteorid = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_METEOR )
end

------------------------------[ Sternsysteme ]----------------------------------

-- Liefert die SystemID des aktuellen Systems
MissionLib.GetStarSystemId = function()
    return get( "Logic.PlayerShip.systemIndex" )
end

-- Liefert das SystemHandle des aktuellen Systems
MissionLib.GetStarSystemHandle = function()
    return get( "Logic.PlayerShip.systemId" )
end

-- Sucht nach einem System mit bestimmten Eigenschaften.
-- Liefert ID und Handle des ersten gefundenen Systems, ansonsten false im Parameter 'Found'.
-- Die übergebene Tabelle 'Properties' kann die folgenden Einträge enthalten:
--  param   = Sichtbarkeitsklasse, MUSS immer angegeben werden!
--  active  = Aktives System ausschließen, wenn > 0
--  crime   = Kriminalitätspunkte des Spielers
--  economy = Wirtschaft
--  faction = Fraktion
--  gouvern = Regierung
--  jump    = System ist mit einem Sprung erreichbar, wenn > 0
--  offset  = Maximaler ± Wert, um den die SystemId variieren darf,
--            es wird aber immer nur im aktuellen Cluster gesucht
--  orbiter = Orbitertyp, der vorhanden sein muss
--  wealth  = Wohlstand
MissionLib.FindSystem = function( Properties )
    -- Sichtbarkeitsklasse sichern, da sie in der übergebenen Tabelle gleich gelöscht wird
    local param = Properties.param
    if param then
        set( "Logic.StarFinder.param", param )  -- Sichtbarkeitsklasse
        Properties.param = nil
    end
    for name, value in Properties do
        set( "Logic.StarFinder."..name, value )
    end
    -- Sichtbarkeitsklasse in übergebener Tabelle wiederherstellen
    Properties.param = param
    -- System gefunden, wenn > 0
    local systemhandle = get( "Logic.StarFinder.result" )
    if systemhandle > 0 then
        return {
            Found = true,
            Handle = systemhandle,
            Id = NStarSystem.GetIdFromHandle( { Handle = systemhandle } ).Id
        }
    end
    return {}
end

-- Sucht nach einer Kombination von n Systemen mit bestimmten Eigenschaften.
-- Falls eine Kombination gefunden wurde, wird im Ausgabeparameter 'Found' der Wert true geliefert
-- und in 'Systems' eine Tabelle mit n Einträgen, die jeweils Id und Handle eines Systems enthalten.
MissionLib.FindSystemGroup = function( Systems )
    local systemlist = {}
    -- Anzahl der zu ermittelnden Systeme
    local systemGroupSize = lua.sizeof( Systems )

    -- Anfrage für jedes System starten, solange Starfinder ein Ergebnis > 0 liefert
    local systempools = {}
    for i, systems in Systems do
        systempools[i] = {}
        local systemhandle
        local foundsystems = 0
        local param = systems.param  -- Sichtbarkeitsklasse sichern

        -- StarFinder flushen
        if param then
            set( "Logic.StarFinder.param", param )  -- Sichtbarkeitsklasse
            systems.param = nil
        end
        for name, value in systems do
            set( "Logic.StarFinder."..name, value )
        end
        systems.param = param  -- Sichtbarkeitsklasse wiederherstellen

        -- Jetzt den StarFinder leersaugen
        repeat
            systemhandle = get( "Logic.StarFinder.result" )  -- System gefunden, wenn > 0
            if systemhandle > 0 then
                -- Ergebnis in Tabelle für jeweiliges System
                foundsystems = foundsystems + 1
                systempools[i][foundsystems] = systemhandle
            elseif foundsystems == 0 then
                -- Für ein System gibt es keine Kandidaten: Sofort abbrechen
                return systemlist
            end
        until systemhandle == 0
    end

    -- systempools ist jetzt gefüllt mit N beliebig großen Mengen von
    -- passenden Sternsystemen, N ist die Anzahl der gesuchten Systeme
    local search = {}   -- Zeigt, an welcher Stelle in der Menge gerade gesucht wird
    local amount = {}   -- Größe der Menge
    local systems = {}  -- Temporärer Speicher für die Systemkombination

    -- Initialisieren
    for i, systempool in systempools do
        search[i] = 1
        amount[i] = lua.sizeof( systempool )
    end

    -- Prüfungsfunktion für ein identisches System in anderer Menge
    local ExistEqualSystem = function()
        for i = 1, %systemGroupSize do
            for j = 1, %systemGroupSize - 1 do
                -- Natürlich nur mit anderen vergleichen
                if i ~= j and %systems[i] == %systems[j] then
                    return 1
                end
            end
        end
    end

    repeat
        -- Kombination von Sternsystemen aus allen N Mengen ermitteln
        for i, systempool in systempools do
            systems[i] = systempool[search[i]]
        end
        -- Jetzt gucken, ob identisches System in anderer Menge vorliegt
        -- Jeder Kandidat guckt sich alle vorhergehenden Kandidaten an
        if ExistEqualSystem() then
            -- War diesmal nichts: Nächste Iteration vorbereiten
            -- Sind noch nicht alle Elemente der aktuellen Suchmenge geprüft worden?
            -- An niedrigster Stelle einen draufzählen
            search[1] = search[1] + 1
            for i = 1, systemGroupSize do
                -- Ggf. Übertrag
                if amount[i] < search[i] then
                    -- Ist ein Übertrag möglich?
                    if i < systemGroupSize then
                        -- Aktuellen Wert zurück auf 1, nächsten um 1 erhöhen.
                        search[i] = 1
                        search[i+1] = search[i+1] + 1
                    else
                        -- Kein Übertrag mehr möglich, dies war die letzte Kombination
                        return systemlist
                    end
                end
            end
        else
            -- Wir haben einen Treffer, Ergebnisse eintragen und fertig
            for i, systemhandle in systems do
                systemlist[i] = {
                    Handle = systemhandle,
                    Id = NStarSystem.GetIdFromHandle( { Handle = systemhandle } ).Id
                }
            end
            return { Found = true, Systems = systemlist }
        end
    until nil
end

-- Liefert eine Tabelle mit Informationen zum Sternensystem mit der angegebenen SystemId (0..402)
MissionLib.GetStarSystemInfo = function( SystemId )
    if SystemId >= 0 and SystemId <= 402 then
        SystemId = "Logic.StarSystems."..SystemId
        return {
            nation	    = get( SystemId..".nation" ),	    -- Rasse
            government	    = get( SystemId..".government" ),	    -- Regierung
            faction	    = get( SystemId..".faction" ),	    -- Regierungsbund
            economy	    = get( SystemId..".economy" ),	    -- Wirtschaft
            wealth	    = get( SystemId..".wealth" ),	    -- Wohlstand
            artefact	    = get( SystemId..".artefact" ),	    -- Artefakt vorhanden?
            gangid	    = get( SystemId..".gangid" ),	    -- Id der ansässigen Gang
            gangcounter	    = get( SystemId..".gangcounter" ),	    -- Anzahl Gang-Vernichtungen
            siege	    = get( SystemId..".siege" ),	    -- Besetztes System
            isActive	    = get( SystemId..".isActive" ),	    -- System ist aktiv
            isActiveMission = get( SystemId..".isActiveMission" ),  -- Eine Mission ist aktiv
            clusterId	    = get( SystemId..".clusterId" ),	    -- Handle vom Cluster
            posX	    = get( SystemId..".posX" ),		    -- X-Position auf der Karte
            posY	    = get( SystemId..".posY" )		    -- Y-Position auf der Karte
        }
    end
end

------------------------------[ Schiffe und Wings ]-----------------------------

-- Liefert das Handle des Spielerschiffs (CStarShipHandle)
MissionLib.GetPlayerHandle = function()
    return get( "Logic.PlayerShip.id" )
end

-- Liefert den Wing, dem das Spielerschiff angehört (CWingHandle)
MissionLib.GetPlayerWing = function()
    return get( "Logic.PlayerShip.wingId" )
end

-- Liefert die ID des Wingleaders, der Wing muss existieren
MissionLib.GetWingLeaderID = function( WingId )
    return get( "Logic.Wings."..WingId..".leader" )
end

-- Liefert das Handle vom Leader, falls der Wing existiert
MissionLib.GetWingLeader = function( WingId )
    if WingId then
        return get( "Logic.Wings."..WingId..".leader", nil )
    end
end

-- Liefert das Handle vom Leader oder einem Wingman, falls der Wing existiert.
-- Index von 1 bis 10 liefert den Wingman, ansonsten den Leader.
MissionLib.GetWingMember = function( WingId, Index )
    if WingId then
        -- Wingman
        if Index and Index > 0 and Index <= 10 then
            local shipId = get( "Logic.Wings."..WingId..".ship"..Index, nil )
            if shipId == NO_SHIP_ID then return; end
            return shipId
        end
        -- Leader für Index < 1 oder > 10 oder nil
        return get( "Logic.Wings."..WingId..".leader", nil )
    end
end

-- Holt die Position des Spielers
MissionLib.GetPlayerPos = function()
    return NObject.GetPosition( { Object = get( "Logic.PlayerShip.id" ) } ).Position
end

-- Holt die Position eines bestimmten Schiffes
MissionLib.GetShipPos = function( ShipId )
    if ShipId then
        return NObject.GetPosition( { Object = ShipId } ).Position
    end
end

-- Holt die Position des WingLeaders
MissionLib.GetWingLeaderPos = function( WingId )
    local leader = get( "Logic.Wings."..WingId..".leader", nil )
    if leader then
        return NObject.GetPosition( { Object = leader } ).Position
    end
end

-- Zeigt die Distanz zwischen Wing und Player
MissionLib.GetDistanceToPlayer = function( WingId )
    return NObject.DistanceFromPlayer( { Object = get( "Logic.Wings."..WingId..".leader" ) } ).Distance
end

-- Liefert die Anzahl der Schiffe in einem Wing.
-- Wurde das letzte Schiff des Wings zerstört und der Wing existiert noch, zählt das Schiff noch mit!
MissionLib.GetShipCountInWing = function( WingId )
    return get( "Logic.Wings."..WingId..".count", 0 )
end

-- Prüft, ob ein bestimmtes Schiff im Wing ist
MissionLib.IsShipInWing = function( ShipId, WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            if ship == ShipId then
                return 1
            end
        end
    end
end

-- Prüft das Vorhandensein eines Schiffes
MissionLib.ShipExists = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship, nil )
    end
end

-- Liefert den Typ eines Objekts (Wing, Ship oder Orbiter)
MissionLib.GetObjectType = function( Object )
    -- Identifizieren des Objekts:
    local leader = get( "Logic.Wings."..Object..".leader", nil)
    if leader then
        -- wenn es ein Wing ist:
        return { Type = "Ship", ObjType = get( "Logic.StarShips."..leader..".shipType" ) }
    end
    local ship = get( "Logic.StarShips."..Object..".shipType", nil )
    if ship then
        -- wenn es ein Schiff ist:
        return { Type = "Ship", ObjType = ship }
    end
    if get( "Logic.Orbiter."..Object..".objecttype", nil ) then
        -- wenn es ein Orbiter ist:
        return { Type = "Orbiter", ObjType = get( "Logic.Orbiter."..Object..".orbiterart" ) }
    end
end

-- Benennt alle Schiffe im Wing mit 'NewName', wenn eine StringId übergeben wurde.
-- Kein Name oder "RANDOM" benennt nur den Leader mit einem zufälligen Namen seiner Rasse.
MissionLib.SetWingName = function( WingId, NewName )
    if not NewName or NewName == "RANDOM" then
        local ship = get( "Logic.Wings."..WingId..".leader" )
        NObject.SetSpecialName( {
            Object = ship,
            Name = NObject.GetName( { Race = get( "Logic.StarShips."..ship..".race" ) } ).Name
        } )
    else
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NObject.SetSpecialName( { Object = ship, Name = NewName } )
        end
    end
end

-- Benennt jedes Schiff im Wing mit dem Namen der entsprechenden Rasse
MissionLib.SetShipNamesInWing = function( WingId )
    for i, ship in NWing.List( { Wing = WingId } ).ShipList do
        NObject.SetSpecialName( {
            Object = ship,
            Name = NObject.GetName( { Race = get( "Logic.StarShips."..ship..".race" ) } ).Name
        } )
    end
end

-- Hülle vom Schiff auf n% (1.0 = 100%), funktioniert nicht bei Satelliten
MissionLib.SetHull = function( Ship, Value )
    set( "Logic.StarShips."..Ship..".hullCondition", Value )
end

-- Schild hinten vom Schiff auf n%
MissionLib.SetShieldRear = function( Ship, Value )
    set( "Logic.StarShips."..Ship..".shieldConditionBack", Value )
end

-- Schild vorne vom Schiff auf n%
MissionLib.SetShieldFront = function( Ship, Value )
    set( "Logic.StarShips."..Ship..".shieldConditionFront", Value )
end

-- Schilde vom Schiff auf n%
MissionLib.SetShieldBoth = function( Ship, Value )
    Ship = "Logic.StarShips."..Ship
    set( Ship..".shieldConditionBack", Value )
    set( Ship..".shieldConditionFront", Value )
end

-- Hülle und Schilde vom Schiff auf 100%
MissionLib.RestoreShip = function( Ship )
    Ship = "Logic.StarShips."..Ship
    set( Ship..".hullCondition", 1.0 )
    set( Ship..".shieldConditionBack", 1.0 )
    set( Ship..".shieldConditionFront", 1.0 )
end

------------------------------[ Aktionen für Schiffe und Wings ]----------------

-- Wing trudelt und explodiert
MissionLib.WingExplode = function( WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.Explode( { Ship = ship } )
        end
    end
end

-- Wing macht einen HyperJump und verschwindet. Es wird nicht geprüft, ob er auch existiert.
MissionLib.WingHyperJump = function( WingId )
    NWing.AddAction( {
        Wing = WingId,
        List = LIST_ACTIVE,
        First = 1,
        Actions = { { Type = AI_ACTION_HYPERRAUM } }
    } )
end

-- WingAi Wrapper für Hyperraumsprung ins Nichts
MissionLib.WingAiActionHyperJump = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            -- alte Kommandoliste löschen (First=true) oder daran anhängen (First=false):
            First = not AddList,
            Actions = { { Type = AI_ACTION_HYPERRAUM } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_INAKTIV
MissionLib.WingAiActionInaktiv = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_INAKTIV } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_STATISCH
MissionLib.WingAiActionStatisch = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_STATISCH  } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_WARTEN
MissionLib.WingAiActionWarten = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_WARTEN  } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_KREISEN, kreist um die eigene Position
MissionLib.WingAiActionKreisen = function( WingId, AddList )
    if WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            NWing.AddAction( {
                Wing = WingId,
                List = LIST_ACTIVE,
                First = not AddList,
                Actions = { {
                    Type = AI_ACTION_KREISEN,
                    Position = NObject.GetPosition( { Object = leader } ).Position
                } }
            } )
        end
    end
end

-- WingAi Wrapper für AI_ACTION_ANGRIFF, zwei Wings greifen sich gegenseitig an
MissionLib.WingAiActionAngriff = function( WingId, AimWingId, AddList )
    if WingId and AimWingId then
        local actionlist = {
            Wing    = WingId,
            Target  = AimWingId,    -- Eintrag wird von NWing.AddAction ignoriert
            List    = LIST_ACTIVE,  -- Einträge ab hier werden von NWing.AddEnemy ignoriert
            First   = not AddList,
            Actions = { { Type = AI_ACTION_ANGRIFF } }
        }
        NWing.AddEnemy( actionlist )
        NWing.AddAction( actionlist )
        actionlist.Wing = AimWingId
        actionlist.Target = WingId
        NWing.AddEnemy( actionlist )
        NWing.AddAction( actionlist )
    end
end

-- WingAi Wrapper für AI_ACTION_ANGRIFF, Wing greift den Spieler an
MissionLib.WingAiActionAngriffPlayer = function( WingId, AddList )
    if WingId then
        local actionlist = {
            Wing    = WingId,
            Target  = get( "Logic.PlayerShip.id" ),
            List    = LIST_ACTIVE,
            First   = not AddList,
            Actions = { { Type = AI_ACTION_ANGRIFF } }
        }
        NWing.MakeHostile( actionlist )
        NWing.AddEnemy( actionlist )
        NWing.AddAction( actionlist )
    end
end

-- WingAi Wrapper fly to pos, Wing fliegt zu der angegebenen Position
MissionLib.WingAiActionFlyToPos = function( WingId, Pos, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_POSITION2, Position = Pos } }
        } )
    end
end

-- WingAi Wrapper fly to pos, Wing fliegt zu der angegebenen Pos, mit Geschwindigkeitangabe
MissionLib.WingAiActionFlyToPosEx = function( WingId, Pos, Speed, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { {
                Type = AI_ACTION_POSITION1,
                Speed = Speed,
                Position = Pos
            } }
        } )
    end
end

-- WingAi Wrapper für AI, Wing wird freundlich zum Spieler und kann diesen nicht mehr angreifen
MissionLib.WingAiActionSetWingLeaderAsFriend = function( WingId )
    if WingId then
        NObject.RadarMapColor( {
            Object = get( "Logic.Wings."..WingId..".leader" ), Color = RADARMAP_SHIP_FRIEND
        } )
        NWing.SetInvalidEnemy( { Wing = WingId, TypeId = ST_PLAYERSHIP } )
    end
end

-- WingAi Wrapper für AI, macht die Änderungen der MissionLib.WingAiActionSetWingAsFriend rückgängig
MissionLib.WingAiActionSetWingLeaderNotAsFriend = function( WingId )
    if WingId then
        NObject.RadarMapColor( {
            Object = get( "Logic.Wings."..WingId..".leader" ), Color = RADARMAP_INVALID
        } )
        NWing.SetInvalidEnemy( { Wing = WingId, TypeId = ST_PLAYERSHIP, Set = 0 } )
    end
end

-- Setzt die RadarMapColor eines ganzen Wings auf freundlich
MissionLib.WingAiActionSetWingAsFriend = function( WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NObject.RadarMapColor( { Object = ship, Color = RADARMAP_SHIP_FRIEND } )
        end
    end
end

-- Setzt die RadarMapColor eines ganzen Wings auf Standard zurück
MissionLib.WingAiActionSetWingRadarMapColorDefault = function( WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NObject.RadarMapColor( { Object = ship, Color = RADARMAP_INVALID } )
        end
    end
end

-- Setzt die Farbe eines ganzen Wings so wie man sie haben will.
-- Die Tabelle sollte so aussehen: { Wing = winghandle, Color = color }
-- Wurde keine Farbe übergeben, wird sie auf Standard zurückgesetzt.
MissionLib.RadarMapColor = function( Table )
    if Table.Wing then
        local color = Table.Color
        if not color then color = RADARMAP_INVALID; end
        for i, ship in NWing.List( { Wing = Table.Wing } ).ShipList do
            NObject.RadarMapColor( { Object = ship, Color = color } )
        end
    end
end

-- Markiert jedes Schiff in einem Wing als Missionsobjekt
MissionLib.WingSetAsMissionObject = function( WingId )
    if WingId then
        NObject.SetMissionFlag( { Object = WingId, Set = 1 } )
    end
end

-- Entfernt die Missionsmarkierung von jedem Schiff eines Wings
MissionLib.WingSetNotMissionObject = function( WingId )
    if WingId then
        NObject.SetMissionFlag( { Object = WingId, Set = 0 } )
    end
end

-- Setzt den Akteur in jedem Schiff eines Wings
MissionLib.WingSetAsActor = function( WingId, Actor )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetActor( { Ship = ship, Actor = Actor } )
        end
    end
end

-- Die Schiffe im Wing geben bei Beschuss Strafpunkte (Ja: Set=true|nil|1, Nein: Set=0, nicht false!)
MissionLib.WingSetCrime = function( WingId, Set )
    if WingId then
        if not Set then Set = 1; end
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetCrime( { Ship = ship, Set = Set } )
        end
    end
end

-- Die Schiffe im Wing werden bei Beschuss Strafpunkte geben
MissionLib.SetCrimeOnWing = function( WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetCrime( { Ship = ship, Set = 1 } )
        end
    end
end

-- Selektiert einen Wing als Ziel des Spielerschiffs und zeigt ihn im Zielcomputer an
-- Ist die WingId ungültig (nicht nil), wird das aktuell selektierte Ziel abgewählt
MissionLib.WingSetAsTarget = function( WingId )
    if WingId then
        NPlayer.SelectTarget( { Object = get( "Logic.Wings."..WingId..".leader", 0 ) } )
    end
end

-- WingAi Wrapper für AI, erzeugt einen freundlichen Boss
MissionLib.WingAiActionSetFriendlyBoss = function( WingId )
    if WingId then
        local ship = get( "Logic.Wings."..WingId..".leader" )
        NShip.SetBoss( { Ship = ship, BossId = 1 } )
        NObject.RadarMapColor( { Object = ship, Color = RADARMAP_SHIP_FRIEND } )
        NWing.SetInvalidEnemy( { Wing = WingId, TypeId = ST_PLAYERSHIP } )
    end
end

-- WingAi Wrapper für AI, erzeugt einen feindlichen Boss
MissionLib.WingAiActionSetEnemyBoss = function( WingId )
    if WingId then
        NShip.SetBoss( { Ship = get( "Logic.Wings."..WingId..".leader" ), BossId = 1 } )
        NWing.MakeHostile( { Wing = WingId } )
    end
end

-- Friert einen Wing ein (true) oder taut ihn auf (false). Ein eingefrorener Wing erhält
-- keine Zeitschritte und hat keine Kollisionen (inklusive Projektilen und Explosionen).
MissionLib.FreezeWing = function( WingId, Freeze )
    if WingId and NWing.IsWing( { Wing = WingId } ).IsWing == 1 then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NObject.Freeze( { Object = ship, Freeze = Freeze } )
        end
    end
end

-- Markiert den Wing als Missionsobjekt (Ja: Value=1, Nein: Value=0)
MissionLib.SetMissionFlagOnWing = function( WingId, Value )
    if WingId and NWing.IsWing( { Wing = WingId } ).IsWing == 1 then
        NObject.SetMissionFlag( { Object = WingId, Set = Value } )
    end
end

-- Markiert das Objekt als Missionsobjekt
MissionLib.SetMissionFlagOnObject = function( Object, Value )
    if Object then
        NObject.SetMissionFlag( { Object = Object, Set = Value } )
    end
end

------------------------------[ Container ]-------------------------------------

-- Erzeugt eine Matrix von Containern mit den angegebenen Parametern:
--	Size  = Größe des Containers
--	Pos   = Positionsvektor { x, y, z } für den ersten Container
--	Count = Anzahl der zu erstellenden Container
--	Dist  = Abstand der Container untereinander
--	Col   = Anzahl der Spalten (Y-Achsen)
--	Goods = Handels- oder Missionsware, ohne dem Parameter werden leere Container erzeugt
--
-- Die Anzahl der Reihen (Z-Achsen) ergibt sich automatisch aus 'Count' und 'Col'.
-- Ist 'Col' gleich 1, wird eine Containerkette auf der Z-Achse erstellt,
-- bei 'Col' kleiner oder gleich 0 liegt die Containerkette auf der Y-Achse.
-- Ist 'Dist' negativ, dann erfolgt die Erzeugung in negativen Y/Z-Richtungen.
--
-- Für eine saubere Ausrichtung der Container sollten folgende Abstände eingehalten werden:
--	CONTAINER_SPECIAL >= |15|
--	CONTAINER_SMALL   >= |20|
--	CONTAINER_MEDIUM  >= |25|
--	CONTAINER_LARGE   >= |30|

MissionLib.ContainerField = function( Size, Pos, Count, Dist, Col, Goods )
    local x = Pos[1]    -- Bleibt immer gleich
    local y = Pos[2]    -- Spalte (Col)
    local z = Pos[3]    -- Reihe
    local column = 1    -- Maximale Anzahl von Containern auf der Y-Achse (also in einer Spalte)
    local containerdata = { Type = CONTAINER_POSITION, Position = Pos, Size = Size }

    -- Containertabelle mit erstem Container erzeugen
    local containerlist = { NContainer.Create( containerdata ).Container }

    -- Alle weiteren Container erstellen
    for i = 2, Count do
        if column == Col then
            -- Maximale Anzahl für Col wurde erreicht, gehe in die nächste Reihe
            z = z + Dist    -- Reihe
            if Col > 1 then
                column = 1
                y = Pos[2]
            end
        else
            -- Abstand Y vergrößern
            y = y + Dist    -- Spalte
            column = column + 1
        end
        containerdata.Position = { x, y, z }
        containerlist[i] = NContainer.Create( containerdata ).Container
    end

    -- Alle Container mit einer Warensorte beladen, falls angegeben
    if Goods then
        for i, container in containerlist do
            NContainer.Equip( { Container = container, Goods = Goods } )
        end
    end
    return containerlist
end

-- Die beiden folgenden Funktionen dienen nur noch der Kompatibilität zum Originalspiel,
-- wo der völlig nutzlose und damit überflüssige Übergabeparameter 'Row' verwendet wird.
MissionLib.ContainerSQR = function( Containersize, Pos, Count, Dist, Row, Col )
    return MissionLib.ContainerField( Containersize, Pos, Count, Dist, Col )
end

MissionLib.ContainerSQRSpezial = function( Containersize, Pos, Count, Dist, Row, Col, Cargo )
    return MissionLib.ContainerField( Containersize, Pos, Count, Dist, Col, Cargo )
end

-- Füllt einen Container mit einer zufälligen Handelsware. Ohne 'Amount' wird er komplett gefüllt.
-- Containerhandle muss übergeben werden. Syntax: MissionLib.SetRandomCargo( { Container, Amount } )
-- Achtung: Die übergebene Tabelle wird geändert und es wird nicht geprüft, ob der Container existiert!
MissionLib.SetRandomCargo = function( Data )
    Data.Goods = lua.tonumber( math.random() * 24 )
    NContainer.Equip( Data )
end

-- Erstellt eine Liste für Container mit jeweils einer zufälligen Handelsware.
-- 'Count' gibt die Anzahl der Container an, 0 = Liste für einen leeren Container.
MissionLib.GetCargoList = function( Count )
    local cargolist = {}
    for i = 1, Count do
        cargolist[i] = lua.tonumber( math.random() * 24 )
    end
    return cargolist
end

-- Erzeugt für alle freien Containerplätze einen Container mit zufälliger Handelsware
-- und dockt den Container am Frachter an. Gleiche Funktion wie NShip.CreateRandomCargo,
-- funktioniert im Gegensatz dazu jedoch auch bei Piraten- und Superfrachtern,
-- liefert allerdings nur die Handles der neu hinzugefügten Container zurück.
MissionLib.LoadCargo = function( Ship )
    -- Liste für die Containerhandles und Datentabelle des Frachters
    local containerlist = {}
    local freighter = { Ship = Ship, Free = true }
    -- Alle freien Slots des Frachters beladen
    for i = 1, NShip.GetNumCargoBays( freighter ).NumCargoBays do
        freighter.Goods = lua.tonumber( math.random() * 24 )
        containerlist[i] = NShip.EquipContainer( freighter ).Container
    end
    -- Rückgabe der Handletabelle
    return containerlist
end

-- Schmeißt alle in 'ContainerList' angegebenen Container von einem Frachter.
MissionLib.DropContainerFromList = function( Ship, ContainerList )
    for i, container in ContainerList do
        NShip.DropContainer( { Ship = Ship, Container = container } )
    end
end

-- Prüft, ob der Spieler Missions- oder Specialname-Ware dabei hat (true|1 = Ja, false|nil = Nein)
MissionLib.PlayerCargo = function()
    local containerlist = NPlayer.GetContainer({})
    if containerlist.Number > 0 then
        containerlist.Number = nil
        -- Die Container des Spielers prüfen
        for i, container in containerlist do
            if NContainer.GetMissionGood( { Container = container } ).SpecialGood then
                return 1
            end
        end
    end
end

------------------------------[ Missionen ]-------------------------------------

-- Registriert eine Mission
MissionLib.RegisterMission = function( pMission )
    if not GLOBALS[pMission] then
        GLOBALS[pMission] = { Chapter = {}, Extension = {} }
    end
end

-- Entfernt eine Mission aus der Registierung
MissionLib.UnregisterMission = function( pMission )
    if GLOBALS[pMission] then
        GLOBALS[pMission] = nil
    end
end

-- Setzt den Status eines Kapitels
MissionLib.SetChapterState = function( pMission, pChapter, pValue )
    local mission = GLOBALS[pMission]
    if mission and mission.Chapter then
        mission.Chapter[pChapter] = pValue
    end
end

-- Liest den Status eines Kapitels
MissionLib.GetChapterState = function( pMission, pChapter )
    local mission = GLOBALS[pMission]
    if mission and mission.Chapter then
        return mission.Chapter[pChapter]
    end
end

-- Prüft, ob die Mission schon im Register ist
MissionLib.IsMissionInRegister = function( pMission )
    if GLOBALS[pMission] then
        return 1
    end
end

-- Setzt eine Mission als abgeschlossen
MissionLib.SetMissionDone = function( pName )
    GLOBALS[pName.."_Done"] = 1
end

-- Liefert true, falls die Mission bereits erfolgreich abgeschlossen wurde
MissionLib.IsMissionDone = function( pName )
    return GLOBALS[pName.."_Done"]
end

-- für Story Missionen, Ausgabe der Nachricht "Neues Missionsziel"
MissionLib.LogUpdateStory = function()
    NGUI.Blink( { Button = GUI_BTN_LOGBOOK } )
    NGUI.ShowInfoText( { Text = "IDM_MISSION_UPDATE" } )
end

-- für Story Missionen, Ausgabe der Nachricht "Mission erfüllt"
MissionLib.LogStoryAchieved = function()
    NGUI.ShowInfoText( { Text = "IDM_MISSION_ACHIEVED" } )
end

-- für globale Missionen, Ausgabe der Nachricht "Neues Auftragsziel"
MissionLib.LogUpdateTask = function()
    NGUI.ShowInfoText( { Text = "IDM_TASK_UPDATE" } )
end

-- für globale Missionen, Ausgabe der Nachricht "Auftrag erhalten"
MissionLib.LogNewTask = function()
    NGUI.ShowInfoText( { Text = "IDM_TASK_NEW" } )
end

------------------------------[ Listen und Tabellen ]---------------------------

-- Prüft, ob eine Liste leer ist
MissionLib.IsListEmpty = function( List )
    for i, item in List do
        return
    end
    return 1
end

-- Prüft, ob ein Element in einer Liste ist und liefert dessen Tabellenindex
MissionLib.IsInList = function( Element, List )
    for i, item in List do
        if item == Element then
            return i
        end
    end
end

-- Prüft, ob ein bestimmter Eintrag in der Tabelle ist
MissionLib.IsInTable = function( Table, Item, IsValue )
    if Item and lua.type( Table ) == "table" then
        if IsValue then
            -- Nach Wert prüfen
            for i, value in Table do
                if value == Item then
                    return 1
                end
            end
        else
            -- Nach Tabellenindex des Eintrags prüfen
            for i, value in Table do
                if i == Item then
                    return 1
                end
            end
        end
    end
end

-- Gibt die Größe einer Tabelle zurück, auch wenn NIL-Werte darin enthalten sind.
-- NIL-Einträge am Ende der Tabelle werden allerdings nicht mehr mitgezählt.
MissionLib.GetTableMax = function( Table )
    local count = 0
    for i, value in Table do
        count = i
    end
    return count
end

-- Kopiert eine Tabelle
MissionLib.CopyTable = function( Table )
    local newTable = {}
    for i, value in Table do
        newTable[i] = value
    end
    return newTable
end

-- Kopiert eine Tabelle ohne den Eintrag an Index
MissionLib.RemoveFromTable = function( Table, Index )
    local newTable = {}
    local count = 1
    for i, value in Table do
        if count ~= Index then
            newTable[count] = value
            count = count + 1
        end
    end
    return newTable
end

-- Fügt ein Element als neuen letzten Eintrag einem Array hinzu
MissionLib.AppendToTable = function( Table, Item )
    if lua.type( Table ) == "table" then
        Table[ lua.getn( Table ) + 1 ] = Item
    end
end

-- Fügt zwei Arrays aneinander und liefert das resultierende Array zurück
MissionLib.ConcatTables = function( Table1, Table2 )
    local newTable = {}
    local count = 1
    for i, value in Table1 do
        newTable[count] = value
        count = count + 1
    end
    for i, value in Table2 do
        newTable[count] = value
        count = count + 1
    end
    return newTable
end

------------------------------[ Vektoren ]--------------------------------------

-- Vektorlänge berechnen, Vector = { x, y, z }
MissionLib.GetVectorLength = function( Vector )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    return math.sqrt( x * x + y * y + z * z )
end

-- Liefert die Entfernung zwischen zwei Objektzentren
MissionLib.GetObjectDistance = function( Object1, Object2 )
    if Object1 and Object2 then
        local pos1 = NObject.GetPosition( { Object = Object1 } ).Position
        local pos2 = NObject.GetPosition( { Object = Object2 } ).Position
        local x = pos1[1] - pos2[1]
        local y = pos1[2] - pos2[2]
        local z = pos1[3] - pos2[3]
        return math.sqrt( x * x + y * y + z * z )
    end
end

------------------------------[ Zufallszahlen ]---------------------------------

-- Erstellt eine Zufallszahl, Faktor ist hier die maximale Differenz zur Minzahl.
-- Beispiel: Minzahl = -15, Faktor = 30 --> liefert eine Zahl im Bereich von -15 bis +14.
MissionLib.GenerateRandomNumber = function( Minzahl, Faktor )
    if Faktor == 0 then Faktor = 1; end
    return lua.tonumber( Minzahl + math.random() * Faktor )
end

-- Liefert eine ganzzahlige Zufallszahl von 0 bis 2147483647 (unsigned int)
MissionLib.RandomInteger = function( Min, Max )
    if Min < 0 then Min = 0; end
    if Min < Max then
        return lua.tonumber( Min + math.random() * ( Max - Min + 1 ) )
    end
    return Min
end

------------------------------[ Geld ]------------------------------------------

-- Weniger Geld
MissionLib.SubCreditsFromPlayer = function( Value )
    local money = get( "Logic.Player.credits" )
    if money > Value then
        money = money - lua.tonumber( Value )
    else
        money = 0
    end
    set( "Logic.Player.credits", money )
end

--------------------------------------------------------------------------------

-- Zusätzliche Funktionen einbinden
source "lua/mission/MissionLibEx.lua"
MissionLib.lua Quellcode Ende


DropContainerFromList

Syntax

DropContainerFromList (Ship, ContainerList)
Beschreibung

Beispiel


GetCargoList

Syntax

GetCargoList (maximum)
Beschreibung

Beispiel


LoadCargo

Syntax

LoadCargo (Ship)
Beschreibung

Beispiel


SetRandomCargo

Syntax

SetRandomCargo (table)
Beschreibung

Beispiel


ContainerSQR

Syntax

ContainerSQR (Containersize, Pos, Count, Dist , Row ,Col)
Beschreibung

Erstellt eine Matrix von Containern mit
    den angegebenen Parametern
Containersize = Größe des Containers
Pos =
    Positionsvector {}
Count = Anzahl der zu erstellenden Container
Dist =
    Abstand der Container untereinander
Row = Anzahl der Reihen
Col =
    Anzahl der Spalten

Anmerkung:
Wenn Row und Col = 1 , wird eine
    Containerkette erstellt.
Sonst wird geprüft, ob Count > Row * Col und
    auf Anzahl = Row * Col begrenzt
Beispiel
Pos = {1,2,3}
V.ContainerList1 = MissionLib.ContainerSQR(CONTAINER_LARGE,Pos ,9,15,3,3)


GetChapterState

Syntax

GetChapterState (Mission, Chapter)Beschreibung
Status eines kapitels auslesenBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
-- Vorheriges Kaiptel muss abgeschlossen sein
if "true" == MissionLib.GetChapterState( "IDM_HUMAN_003", 2 ) then
    return { Ready = true }
else
    return { Ready = false }
end


IsMissionDone

Syntax

IsMissionDone (MissionName)Beschreibung
Liefert true zurück, falls die Mission(sreihe) bereits abgeschlossen wurde.Beispiel


IsMissionInRegister

Syntax

IsMissionInRegister (Mission)Beschreibung
Prüfen ob Mission schon registriert wurdeBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
-- Vorheriges Kaiptel muss abgeschlossen sein
if "true" == MissionLib.IsMissionInRegister( "IDM_XYZ") then
    -- Code für true
else
    -- Code für false
end


LogNewTask

Syntax

LogNewTask ()Beschreibung
Erzeugt die Meldung "Auftrag erhalten"Beispiel


LogStoryAchieved

Syntax

LogStoryAchieved ()Beschreibung
Erzeugt die Meldung "Mission erfolgreich" Beispiel


LogUpdateStory()

Syntax

LogUpdateStory() ()Beschreibung
Erzeugt die Meldung "Neues Missionsziel"Beispiel


LogUpdateTask

Syntax

LogUpdateTask ()Beschreibung
Erzeugt die Meldung "Auftrag aktualisiert"Beispiel


RegisterMission

Syntax

RegisterMission (Mission)Beschreibung
Registriert eine MissionBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.RegisterMission("IDMXYZ")


SetChapterState

Syntax

SetChapterState (Mission, Chapter, Value)Beschreibung
Setzt den Status eines KapitelsBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.SetChapterState("IDMXYZ", 1, "false")


SetMissionDone

Syntax

SetMissionDone (MissionName)Beschreibung
Setzt eine Mission als abgeschlossen. Sollte in Verbindung mit 'IsMissionDone' für längere Missionen verwendet werden, die über mehrere Kapitel gehen. In diesem Falle darf das erste Kapitel nicht mehr starten, wenn das letzte Kapitel erfüllt wurde.Beispiel


UnregisterMission

Syntax

UnregisterMission (Mission)Beschreibung
Entfernt eine Mission aus der Registierung, und alle in der Extension gespeicherten informationen.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.UnregisterMission("IDMXYZ")


GetObjectDistance

Syntax

GetObjectDistance (Obj1, Obj2)
Beschreibung

Liefert die Entfernung zwischen zwei
    Objekten. Liefert nil falls einer der Parameter nil entspricht.
Obj1 =
    Handle des ersten Objekts.
Obj2 = Handle des zweiten Objekts.
Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
V.Con1=NContainer.Create({
    Type=CONTAINER_SPACE,
    Size=CONTAINER_SMALL,
    PosDesc=POSDESCR_TRADESTATION1
}).Container
V.Con2=NContainer.Create({
    Type=CONTAINER_SPACE,
    Size=CONTAINER_SMALL,
    PosDesc=POSDESCR_TRADESTATION2
}).Container
local _condist=MissionLib.GetObjectDistance( V.Con1, V.Con2 )


GetObjectType

Syntax

GetObjectType (Object)
Beschreibung

Liefert eine Tabelle mit dem Typ des
    Objektes zurück. Object = Kann eine Schiff, ein Wing oder ein Orbiter
    sein
Rückgabetabelle
Feldbezeichner Datentyp Wertebereich
    Kommentar
Type String "Orbiter", "Ship" Gibt an, ob angegebenes Objekt
    ein Shiff (Ship) oder Orbiter (Orbiter) ist.
ObjType CConst Ships,
    Orbiter Gibt die Konstante des Objekts zurück.
Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
local wing = MissionLib.GetObjectType( V.TestWing )


GetSystemResearchStation

Syntax

GetSystemResearchStation ()Beschreibung
Sucht die Forschungsstation im aktuellem System.
Gibt „nil“ zurück wenn die Funktion fehlschlägt.
if nil == TradeStationHandel then
NDebug.Message( { Message="IDM_GLOBALSPACE_004 GetSystemResearchStation() failed" } )
endBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------

ResearchStationHandel = GetSystemResearchStation()


GetSystemTradeStation

Syntax

GetSystemTradeStation ()Beschreibung
Sucht die HandelsStation im aktuellem System.
Gibt „nil“ zurück wenn die Funktion fehlschlägt.
if nil == TradeStationHandel then
NDebug.Message( { Message="IDM_GLOBALSPACE_004 GetSystemTradeStation() failed" } )
endBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------

TradeStationHandel = GetSystemTradeStation()


ListSystemOrbiter

ListSystemOrbiter( OrbiterType )

Listet alle Orbiter des gleichen Typs im aktuellem System auf und liefert deren Typen.
Die Liste enthält die gefundenen Orbiter in der umgekehrten Reihenfolge, wie sie in der Planets.ini eingetragen sind. Das heißt also, der zuletzt in der Planets.ini definierte Orbiter des Systems steht in dieser Liste an erster Stelle.

Parameter
Konstante | Beschreibung
ORBITART_SONNE | Sonnen des Systems
ORBITART_PLANET_TC | Technikplaneten
ORBITART_PLANET_BG | Agrarplaneten
ORBITART_PLANET_GR | Gasriesen
ORBITART_MOND | Monde
ORBITART_KOMET | Kometen
ORBITART_METEORE | Meteoritenfelder
ORBITART_DECO | Kreuzer- und Stationswracks

Gibt „nil“ zurück wenn die Funktion fehlschlägt:

if asteroidList[1] == nil then
    NDebug.Message( { Message="IDM_GLOBALSPACE_004 ListSystemOrbiter( ORBITART_ASTEROID ) failed" } )
end

Beispiel

------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------

local asteroidList = ListSystemOrbiter( ORBITART_ASTEROID )


GetSystemHyperGate

Syntax

GetSystemHyperGate ()
Beschreibung

Sucht das HyperGate im aktuellem
    System.
Gibt „nil“ zurück wenn die Funktion fehlschlägt.
if nil ==
    systemHyperGate then
NDebug.Message( { Message="IDM_GLOBALSPACE_004
    GetSystemHyperGate() failed" } )
end
Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------

local systemHyperGate = GetSystemHyperGate()


AppendToTable

Syntax

AppendToTable (table, item)Beschreibung
Fügt eine Element als neuen letzten Eintrag einem Array hinzu.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------


ConcatTables

Syntax

ConcatTables (table1, table2)Beschreibung
Fügt zwei Arrays aneinander und liefert den resultierenden Array zurück. table1 wird gefolgt von table2.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
friends = { handle1, handle2, handle3 }
foes = { handle4, handle5, handle6 }
alltogether = ConcatTables( friends, foes )


CopyTable

Syntax

CopyTable (Table)Beschreibung
Kopiert eine Tabelle und liefert die Kopie zurückBeispiel


GenerateRandomNumber

Syntax

GenerateRandomNumber (Minzahl, Faktor)Beschreibung
Erstellt eine Zufallszahl.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
local zufallszahl = MissionLib.GenerateRandomNumber( 10, 4 )


GetVectorLength

Syntax

GetVectorLength (Vector)Beschreibung
Liefert die Länge des dreispaltigen Vektors.
Vector = Tabelle mit drei Elementen.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
-- Abstand zwischen zwei Objekten ermitteln:
local _p1=NObject.GetPosition( { Object=Obj1 } ).Position
local _p2=NObject.GetPosition( { Object=Obj2 } ).Position
local _vec=NVector.Sub({ Vector1=_p1, Vector2=_p2 }).Vector
_dist=MissionLib.GetVectorLength( _vec )


IsInList

Syntax

IsInList (Element, List)Beschreibung
Prüft, ob ein Element in einer Liste ist
gibt die id oder nil zurückBeispiel


IsListEmpty

Syntax

IsListEmpty (List)Beschreibung
Prüft, ob eine Liste leer ist
gibt true oder false zurückBeispiel


RandomInteger

Syntax

RandomInteger (Min, Max)Beschreibung
Liefert einen zufällige Integerwert aus dem Intervall [ Min, Max ]. Der Rückgabewert kann also auch für Tabellenindices verwendet werden.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
local _random = MissionLib.RandomInteger( 2, 24 )
local _shipid = ships[ _random ]


GetPlayerHandle

Syntax

GetPlayerHandle ()Beschreibung
Gibt das Handle des Spielerschiffs.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
V.Player = MissionLib.GetPlayerHandle()


GetPlayerPos

Syntax

GetPlayerPos ()Beschreibung
Holt die Position des Spielers.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------
local playerPos = {}
playerPos = MissionLib.GetPlayerPos()

local playerPosX = Pos[1]
local playerPosY = Pos[2]
local playerPosZ = Pos[3]


GetPlayerWing

Syntax

GetPlayerWing ()Beschreibung
Liefert das Handle des Spielerwings zurück.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------------------------------------------------------
V.PlayerWing = MissionLib.GetPlayerWing()


WingSetAsTarget

Syntax

WingSetAsTarget (WingId)Beschreibung
Selektiert den wing leader als Ziel.
WingId
Die WingID des Wings, dessen leader als Ziel markiert werden soll.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
V.Pirates = NWing.Create( {
   WingType = WINGTYPE_PIRATES,
   Number = 5,
   Level = nil,
   Race = RACE_RANDOM,
   PosType = POSDESCR_EXPLICIT, Position={2000.0, 8000.0, 1000.0} } ).Wing

MissionLib.WingSetAsTarget( V.Pirates )


FindSystem

FindSystem( tablePar ) : { Found, Id, Handle }

Sucht nach einem System mit bestimmten Eigenschaften. Liefert Id und Handle des gefundenen Systems, wenn der Ausgabeparameter 'Found' true ist. Der Feldbezeichner 'param' für die Sichtbarkeitsklasse muss angegeben werden, andernfalls wird nichts zurückgeliefert, der Parameter 'Found' ist false. Alle anderen Eigenschaften können wie benötigt angegeben oder weggelassen werden. Die Funktion greift auf den StarFinder im Property System zu.
Achtung: Die drei "toten" Systeme Kajudeng, Metojang und Permakin (System-IDs 400-402) werden nicht mit zurückgeliefert, auch wenn die übergebenen Eigenschaften zutreffen!

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
tablePar | table[1..10] | unsigned int | Tabelle mit den gewünschten Eigenschaften des Systems

Parametertabelle für tablePar
Feldbezeichner | Datentyp | Wertebereich | Kommentar
param | unsigned int | STAR_GANGSYSTEM, STAR_MISSION, STAR_SYSTEMKEY, STAR_UNLOCKED | Sichtbarkeitsklasse des Systems Muss immer zuerst angegeben werden!
active | unsigned int | >= 0 | >0: Schließt das aktive System von der Suche aus
crime | float | 0.0..5.0 | Kriminalitätspunkte des Spielers im System
economy | unsigned int | SYSTEM_AGRICULTURE, SYSTEM_INDUSTRY, SYSTEM_MINING, SYSTEM_PHARMACEUTICS, SYSTEM_RESEARCH, SYSTEM_SERVICE | Wirtschaft des Systems
faction | unsigned int | FACTION_FEDERATION, FACTION_REBELS, FACTION_INDEPENDENT | Fraktion des Systems
gouvern | unsigned int | GOVERN_ANARCHY, GOVERN_CONCERN, GOVERN_DEMOCRACY, GOVERN_DICTATORSHIP, GOVERN_FEDERATION, GOVERN_MONARCHY | Regierungsform des Systems
orbiter | unsigned int | OBJTYPE_ASTEROID, OBJTYPE_BASE, OBJTYPE_GATE, OBJTYPE_KOMET, OBJTYPE_METEOR, OBJTYPE_MOON, OBJTYPE_PLANETBG, OBJTYPE_PLANETGR, OBJTYPE_PLANETTC, OBJTYPE_SUN, OBJTYPE_STATION, ORBITART_ANOMALIE | Orbitertyp im System
offset | unsigned int | >=0 | Maximaler Wert, um den die SystemId variieren darf. Trotzdem sucht FindSystem nur im gegenwärtigen Cluster.
wealth | unsigned int | WEALTH_POOR, WEALTH_WEALTHY, WEALTH_RICH | Wohlstand des Systems
jump | unsigned int | n/a | >0: ignoriert alle Sterne, die nicht mit einem Sprung erreicht werden können

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Found | boolean | false, true | true = Ein Sternensystem wurde gefunden
Id | unsigned int | 0..402 | Id des Sternensystems
Handle | unsigned int | n/a | Handle des Sternensystems

Beispiel

------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------------------------------------------------------
local Results = MissionLib.FindSystem( {
    active = 1,
    faction = FACTION_FEDERATION,
    param = STAR_UNLOCKED,
    offset = 2,
    wealth = WEALTH_WEALTHY
} )
local SystemId = Results.Id
local SystemHandle = Results.Handle


FindSystemGroup

FindSystemGroup( Systems )

Sucht nach einer Kombination von n Systemen mit bestimmten Eigenschaften. Liefert im Ausgabeparameter 'Found' den Wert true, falls eine Kombination gefunden wurde. Liefert eine Tabelle mit n Einträgen, die jeweils die Id und Handle eines Systems enthalten. Greift auf den StarFinder im Property System zu.

Der Parameter 'Systems' ist eine Tabelle mit n Tabellen, die Einträge nach dem gleichen Schema wie sie bei der MissionLib.FindSystem() gebraucht werden, enthalten.

Zum Algorithmus:
Es werden n Mengen von Sternensystemen ermittelt, jede nach eigenen Kriterien. Aus diesen muss eine Kombination von nicht identischen Sternensystemen zusammengestellt werden. Angenommen, es gibt 3 Mengen mit je 3 Elementen, dann wird in folgender Reihenfolge kombiniert (links nach rechts, oben nach unten):

( 1, 1, 1 ), ( 2, 1, 1 ), ( 3, 1, 1 ),

( 1, 2, 1 ), ( 2, 2, 1 ), ( 3, 2, 1 ),

( 1, 3, 1 ), ( 2, 3, 1 ), ( 3, 3, 1 ),

( 1, 1, 2 ), ( 2, 1, 2 ), ( 3, 1, 2 ),

( 1, 2, 2 ), ( 2, 2, 2 ), ( 3, 2, 2 ),

( 1, 3, 2 ), ( 2, 3, 2 ), ( 3, 3, 2 ),

( 1, 1, 3 ), ( 2, 1, 3 ), ( 3, 1, 3 ),

( 1, 2, 3 ), ( 2, 2, 3 ), ( 3, 2, 3 ),

( 1, 3, 3 ), ( 2, 3, 3 ), ( 3, 3, 3 )

Syntax:
test = MissionLib.FindSystemGroup( { tablePar_1, tablePar_2, ..., tablePar_n } )

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
Systems | table[n:tablePar[1..10]] | unsigned int | Tabellen, die die gewünschten Eigenschaften der Systeme enthalten

Parametertabelle für tablePar
Feldbezeichner | Datentyp | Wertebereich | Kommentar
param | unsigned int | STAR_GANGSYSTEM, STAR_MISSION, STAR_SYSTEMKEY, STAR_UNLOCKED | Sichtbarkeitsklasse des Systems Muss immer zuerst angegeben werden!
active | unsigned int | >= 0 | >0: Schließt das aktive System von der Suche aus
crime | float | 0.0..5.0 | Kriminalitätspunkte des Spielers im System
economy | unsigned int | SYSTEM_AGRICULTURE, SYSTEM_INDUSTRY, SYSTEM_MINING, SYSTEM_PHARMACEUTICS, SYSTEM_RESEARCH, SYSTEM_SERVICE | Wirtschaft des Systems
faction | unsigned int | FACTION_FEDERATION, FACTION_REBELS, FACTION_INDEPENDENT | Fraktion des Systems
gouvern | unsigned int | GOVERN_ANARCHY, GOVERN_CONCERN, GOVERN_DEMOCRACY, GOVERN_DICTATORSHIP, GOVERN_FEDERATION, GOVERN_MONARCHY | Regierungsform des Systems
orbiter | unsigned int | OBJTYPE_ASTEROID, OBJTYPE_BASE, OBJTYPE_GATE, OBJTYPE_KOMET, OBJTYPE_METEOR, OBJTYPE_MOON, OBJTYPE_PLANETBG, OBJTYPE_PLANETGR, OBJTYPE_PLANETTC, OBJTYPE_SUN, OBJTYPE_STATION, ORBITART_ANOMALIE | Orbitertyp im System
offset | unsigned int | 0..402 | Maximaler Wert, um den die System Id variieren darf. Trotzdem sucht FindSystem nur im gegenwärtigen Cluster.
wealth | unsigned int | WEALTH_POOR, WEALTH_WEALTHY, WEALTH_RICH | Wohlstand des Systems
jump | unsigned int | >= 0 | >0: ignoriert alle Sterne, die nicht mit einem Sprung erreicht werden können

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Found | boolean | false, true | true = Mindestens ein Sternensystem wurde gefunden
Systems | unsigned int | table[n] | Tabelle mit den gefundenen Systemen

'Systems'-Tabellen in der Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
Id | unsigned int | 0..402 | Id des Sternensystems
Handle | unsigned int | n/a | Handle des Sternensystems

Beispiel

  1. Anwendung:
    test = MissionLib.FindSystemGroup( {
    {
    param = STAR_UNLOCKED,
    faction = FACTION_FEDERATION,
    offset = 2,
    },
    {
    param = STAR_UNLOCKED,
    faction = FACTION_INDEPENDENT,
    offset = 5,
    },
    {
    param = STAR_UNLOCKED,
    faction = FACTION_INDEPENDENT,
    offset = 5,
    },
} )
  2. Ausgabe:
    FindSystemGroup: Trying to find 3 Systems. (no script)
FindSystemGroup: Candidate #1: 3 candidates found. (no script)
FindSystemGroup: 	 #1: 8; (no script)
FindSystemGroup: 	 #2: 10; (no script)
FindSystemGroup: 	 #3: 9; (no script)
FindSystemGroup: Candidate #2: 3 candidates found. (no script)
FindSystemGroup: 	 #1: 7; (no script)
FindSystemGroup: 	 #2: 11; (no script)
FindSystemGroup: 	 #3: 4; (no script)
FindSystemGroup: Candidate #3: 3 candidates found. (no script)
FindSystemGroup: 	 #1: 7; (no script)
FindSystemGroup: 	 #2: 4; (no script)
FindSystemGroup: 	 #3: 11; (no script)
FindSystemGroup: Starting search in set 1. (no script)
FindSystemGroup: 	 8, 7, 7,  (no script)
FindSystemGroup: 	 10, 7, 7,  (no script)
FindSystemGroup: 	 9, 7, 7,  (no script)
FindSystemGroup: 	 8, 11, 7,  (no script)
FindSystemGroup: Success. Systems: (no script)
FindSystemGroup: 	 #1: Id = 8 (no script)
FindSystemGroup: 	 #2: Id = 11 (no script)
FindSystemGroup: 	 #3: Id = 7 (no script)


GetStarSystemHandle()

Liefert das Handle des aktuellen Systems.

Parameter
leer

Beispiel

    local SystemHandle = GetStarSystemHandle()


GetStarSystemId()

Liefert die SystemId des aktuellen Systems.

Parameter
leer

Beispiel

    local SystemId = GetStarSystemId()


GetStarSystemInfo

GetStarSystemInfo( SystemId )

Liefert eine Tabelle mit Informationen zum Sternensystem mit der angegebenen SystemId.

Parameter
Feldbezeichner | Datentyp | Wertebereich | Kommentar
SystemId | unsigned int | 0..402 | Id des Sytems

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
siehe Tabelle für table | table[1..11] : { unsigned int, float } | n/a | Tabelle mit Infos zum System

Parametertabelle für table
Feldbezeichner | Datentyp | Wertebereich | Kommentar
nation | unsigned int | Rassen | Nation, der das System gehört
government | unsigned int | GOVERN_ANARCHY, GOVERN_CONCERN, GOVERN_DEMOCRACY, GOVERN_DICTATORSHIP, GOVERN_FEDERATION, GOVERN_MONARCHY | Regierungsform des Systems
faction | unsigned int | FACTION_FEDERATION, FACTION_REBELS, FACTION_INDEPENDENT | Fraktion des Systems
economy | unsigned int | SYSTEM_AGRICULTURE, SYSTEM_INDUSTRY, SYSTEM_MINING, SYSTEM_PHARMACEUTICS, SYSTEM_RESEARCH, SYSTEM_SERVICE | Wirtschaft des Systems
artefact | bool | ARTEFACT_RECEIVED | true, wenn ein Artefakt im System liegt
gangid | unsigned int | 0..46 | Id der ansässigen Piraten-Gang, falls vorhanden
siege | bool | n/a | true = Bedrohtes System (von Piraten besetzt)
wealth | unsigned int | WEALTH_POOR, WEALTH_WEALTHY, WEALTH_RICH | Wohlstandsindex
isActiveMission | bool | true, false | true, wenn im System eine Mission aktiv ist
posX | float | n/a | X-Position auf der Sternenkarte in Lichtjahren
posY | float | n/a | Y-Position auf der Sternenkarte in Lichtjahren

Beispiel

local starsysteminfo = MissionLib.GetStarSystemInfo( 29 )
local govern = starsysteminfo.government
local wealth = starsysteminfo.wealth


GetShipCountInWing

Syntax

GetShipCountInWing (WingId)Beschreibung
Gibt die Anzahl der schiffe in einem wing.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------
local wingCount = MissionLib.GetShipCountInWing( WingId )


GetShipPos

Syntax

GetShipPos (ShipId)Beschreibung
Holt die Position eines speziellen Schiffes.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------
local shipPos = {}
shipPos = MissionLib.GetShipPos( ShipId )

local shipPosX = Pos[1]
local shipPosY = Pos[2]
local shipPosZ = Pos[3]


GetWingLeader

Syntax

GetWingLeader (WingId)Beschreibung
Liefert die Shiphandle eines Wingleaders, falls der Wing existiert.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

shipHandle= MissionLib.GetWingLeader( WingId )


GetWingMember

Syntax

GetWingMember (WingId, Index)Beschreibung
Liefert Shiphandle eines Wingmitglieds. Index bezeichnet das entsprechende Schiff. Wenn 10 >= Index >= 1, dann wird einer der Wingmen geliefert (".ship1" bis ".ship10"). Ist Index < 1, dann wird der Wingleader geliefert.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

local _leader = MissionLib.GetWingMember( V.Wing1, 0 )
local _wingmen = {}
for i = 1, 10 do
    _wingmen[i]=MissionLib.GetWingMember( V.Wing1, i )
end


IsShipInWing

Syntax

IsShipInWing (Ship, Wing)Beschreibung
Prüft, ob das Schiff sich im angegebenen Wing befindet.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------
local _bInWing
if ( MissionLib.IsShipInWing( V.PlayerHandle, V.HornblowerHandle ) ) then _bInWing = true end


SetShipNamesInWing

Syntax

SetShipNamesInWing (WingId)
Beschreibung

Liest die Rasse des Leaders und benennt
    jedes schiff einzeln mit Namen aus der Liste der entsprechenden Rasse.
Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
V.Pirates = NWing.Create( {
   WingType = WINGTYPE_PIRATES,
   Number = 5,
   Level = nil,
   Race = RACE_RANDOM,
   PosType = POSDESCR_EXPLICIT, Position={2000.0, 8000.0, 1000.0} } ).Wing

MissionLib.SetShipNamesInWing( V.Pirates )


SetWingName

Syntax

SetWingName (WingId, NewName)
Beschreibung

Gibt einen ganzen Wing einen Namen, also
    jedes schiff bekommt denselben Namen.
Paramter für
    NewName:
RANDOM
Nur der Leader bekommt einen Namen.
Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------

V.Pirates = NWing.Create( {
    WingType = WINGTYPE_PIRATES,
    Number = 5,
    Level = nil,
    Race = RACE_RANDOM,
    PosType = POSDESCR_EXPLICIT, Position={2000.0, 8000.0, 1000.0}
} ).Wing

MissionLib.SetWingName( V.Pirates, RANDOM )


WingExplode

Syntax

WingExplode (WingId)Beschreibung
Wing trudelt und expoldiert.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------
MissionLib.WingExplode( WingId )


WingHyperJump

Syntax

WingHyperJump (WingId)Beschreibung
Wing macht einen HyperJump und verschwindet.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"

------------------------------[ Transitions ]---------------------------------
MissionLib.WingHyperJump( WingId )


WingAiActionAngriff

Syntax

WingAiActionAngriff (WingId, AimWingId, AddList)Beschreibung
WingAi Wrapper für AI_ACTION_ANGRIFF, Wing greift einen anderen wing an.
Parameter:
WingId
Die WingID des Wings der angreifen soll.
AimWingId
Die WingID des Wings der angreifen soll.
AddList
true Commando wird in an die Kommando Schlange angehangen.
false Kommando wird sofort ausgeführtBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionAngriff( Wing1, Wing2, false )


WingAiActionAngriffPlayer

Syntax

WingAiActionAngriffPlayer (WingId, AddList)Beschreibung
WingAi Wrapper für AI_ACTION_ANGRIFF, Wing greift den Spieler an.
Parameter:
WingId
Die WingID des Wings der den Spieler angreifen soll.
AddList
true Commando wird in an die Kommando Schlange angehangen.
false Kommando wird sofort ausgeführtBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionAngriffPlayer( Wing, false )


WingAiActionFlyToPos

Syntax

WingAiActionFlyToPos (WingId, Pos, AddList)Beschreibung
WingAi Wrapper für Hyperraumsprung ins nichts.
Parameter:
WingId
Die WingID des Wings der ins nichts jumpen soll.
Pos
Tabelle mit X, Y, Z werten
AddList
true Commando wird in an die Kommando Schlange angehangen.
false Kommando wird sofort ausgeführtBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionFlyToPos( WingId, Pos, AddList )


WingAiActionHyperJump

Syntax

WingAiActionHyperJump (WingId, AddList)
Beschreibung

WingAi Wrapper für Hyperraumsprung ins
    Nichts.
Parameter:
WingId
Die WingID des Wings der ins nichts
    jumpen soll.
AddList
true Commando wird in an die Kommando Schlange
    angehangen.
false Kommando wird sofort ausgeführt
Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionHyperJump( Wing, false )


WingAiActionInaktiv

Syntax

WingAiActionInaktiv (WingId, AddList)Beschreibung
WingAi Wrapper für AI_ACTION_INAKTIV.
Parameter:
WingId
Die WingID des Wings der Inaktiv sein soll.
AddList
true Commando wird in an die Kommando Schlange angehangen.
false Kommando wird sofort ausgeführtBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionInaktiv( Wing, false )


WingAiActionKreisen

Syntax

WingAiActionKreisen (WingId, AddList)Beschreibung
WingAi Wrapper für AI_ACTION_KREISEN, kreist um die eigene pos.
Parameter:
WingId
Die WingID des Wings der kreisen soll.
AddList
true Commando wird in an die Kommando Schlange angehangen.
false Kommando wird sofort ausgeführtBeispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionKreisen( Wing, false )


WingAiActionSetEnemyBoss

Syntax

WingAiActionSetEnemyBoss (WingId)Beschreibung
Wrapper für Ai, erzeugt einen Feindlichen Boss.
Parameter:
WingId

Die WingID des Wings dessen Leader als Feindlicher Boss (NPC)gestzt werden soll.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionSetEnemyBoss( Wing )


WingAiActionSetFriendlyBoss

Syntax

WingAiActionSetFriendlyBoss (WingId)Beschreibung
Wrapper für Ai, erzeugt einen Freundlichen Boss.
Parameter:
WingId
Die WingID des Wings dessen Leader als Freundlichen Boss (NPC)gestzt werden soll.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionSetFriendlyBoss( Wing )


WingAiActionSetWingAsFriend

Syntax

WingAiActionSetWingAsFriend (WingId)Beschreibung

Alle schiffe des wings sind freundlich und die RadarMapColor wird auf grün gesetzt.
WingId
Die WingID des Wings, dessen Gesinnung geändert werden soll.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
MissionLib.WingAiActionSetWingAsFriend( V.Pirates )


WingAiActionSetWingLeaderAsFriend

Syntax

WingAiActionSetWingLeaderAsFriend (WingId)Beschreibung
Wrapper für Ai, Wing wird freundlich zum Spieler, und kann diesen nicht mehr angreifen.
Parameter:
WingId
Die WingID des Wings dessen leader als Freund gestzt werden soll.Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Transitions ]---------------------------------
MissionLib.WingAiActionSetWingLeaderAsFriend( Wing )


WingAiActionSetWingLeaderNotAsFriend

Syntax

WingAiActionSetWingLeaderNotAsFriend (WingId)Beschreibung
Wrapper für Ai, macht die Änderungen der MissionLib.WingAiActionSetWingAsFriend rückgängig.Beispiel


WingAiActionSetWingRadarMapColorDefault

Syntax

WingAiActionSetWingRadarMapColorDefault (WingId)Beschreibung
RadarMapColor wird auf Standart zurückgesetzt.
WingId
Die WingID des Wings...Beispiel
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"
------------------------------[ Code ]----------------------------------------
MissionLib.WingAiActionSetWingRadarMapColorDefault( V.Pirates )


MissionLibEx

Die Skriptbibliothek "MissionLibEx.lua" ist eine Erweiterung der mit Darkstar One ausgelieferten MissionLib.lua. Die MissionLibEx.lua beinhaltet eine Vielzahl von weiteren hilfreichen Zusatzfunktionen, deren Arbeitsweise im ursprünglichen ModdingGuide z.T. nicht dokumentiert sind. So werden hier z.B. einige bisher undokumentierte "get"- und "set"-Funktionen eingesetzt.
Um die Funktionen nutzen zu können, muss die MissionLibEx.lua zuerst im Skript importiert werden. Dies geschieht automatisch mit dem Import der MissionLib.lua, wenn dort die Zeile source "lua/mission/MissionLibEx.lua" am Ende hinzugefügt wurde. Andernfalls gilt dasselbe wie für die MissionLib.lua:

------------------------------[ Import ]---------------------------------------
source "lua/mission/MissionLib.lua"
source "lua/mission/MissionLibEx.lua"
-------------------------------------------------------------------------------

Hinweise zu den Funktionen:
Ein paar Funktionen sind noch experimentell und nicht getestet oder es ist unklar, was sie für Werte zurückliefern. Diese Funktionen sind entsprechend kommentiert. Des Weiteren sind hier einige Funktionen definiert, deren Code so einfach ist, dass er auch direkt in den Skripts verwendet werden kann, wie z.B. GetClusterName. Diese dienen daher lediglich zum besseren Verständnis der vorhandenen Möglichkeiten. Außerdem gibt es noch Funktionen, die auf den ersten Blick nutzlos erscheinen, da die damit behandelten Objekte normalerweise nur einmal im System vorhanden sind, wie z.B. bei GetSystemPirateBases. Diese Funktionen berücksichtigen jedoch eventuelle Erweiterungen in der "Planets.ini" bzw. die Erzeugung solcher Objekte in den Skripts.

Nicht in jeder Funktion werden die übergebenen Parameter abgefangen und auf eventuelle Fehler überprüft, sodass es zum Crash kommen kann. Falls notwendig, sollte die Prüfung also vor dem Funktionsaufruf erfolgen.

Ein allgemeiner Hinweis zur Erzeugung von Objekten:
Hier sollte man immer ein Auge auf die Anzahl der erzeugten Objekte haben, da zu viele davon den Spielfluss erheblich verlangsamen und es zu schweren Rucklern und Aussetzern kommen kann. Mit einer 3 GHz Dualcore-CPU und einer Grafikkarte der mittleren Leistungsklasse kann zum Beispiel bei den Minenfeldern ein Richtwert von ca. 500 bis 800 Minen gelten, bevor die Framerate zu sehr in die Knie geht (extrem kann es werden, wenn die Minen alle gleichzeitig explodieren). Natürlich zählen da noch die anderen erzeugten Objekte mit, deren Leistungsbedarf z.T. erheblich höher als der einer einfachen Mine ist.

Hinweise zu trigonometrischen Berechnungen:
Winkel müssen den Funktionen immer im Bogenmaß Radiant und nicht in Grad übergeben werden. Ergebnisse werden auch immer im Bogenmaß zurückgeliefert. Trotzdem muss man nicht auf die Angabe von Winkeln in Grad verzichten, wenn man sie vor oder bei der Übergabe an die Funktion umrechnet: math.rad(360) z.B. wäre dasselbe wie 2*math.pi (360 Grad = 2π rad). Umgekehrt lässt sich die Einheit rad wieder ganz einfach mit math.deg(rad) in Grad zurückrechnen.

Quellcode der MissionLibEx.lua
--------------------------------------------------------------------------------
-- Dark Star One (TM) - Script library
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]------------------------------------------
-- Name: MissionLibEx.lua
-- Author: [SNF]Norbert
-- Version 2.7
------------------------------[ Description ]-----------------------------------
--
-- Funktionen:
--
-- ▼ Globale Konstanten, dürfen NICHT von den Skripts geändert werden!
-- ▼	Munition
-- ▼	Benutzeroberfläche (GUI)
-- ▼	Container und Waren
-- ▼	Kommunikation
-- ▼	Ausrüstung und Energiesysteme
-- ▼	Wing-Aktionen
-- ▼	Wing-Formationen
-- ▼	Objekte und Orbiter
-- ▼	Spielerschiff
-- ▼	Erzeugungsbereiche
-- ▼	Besetzte Piratensysteme und ihre regulären Regierungen
-- ▼	Völker
-- ▼	Radarmap-Farben
-- ▼	Scannstatus des Spielerschiffs
-- ▼	Schiffstypen
-- ▼	Schiffsklassen
-- ▼	Frachterindex
-- ▼	Wingtypen
-- ▼	Tunnel-Missionen
-- ▼	Missionen allgemein
-- ▼	Sternsysteme
-- ▼	Häufig benötigte Sounds
-- ▼	Häufig benötigte Vektoren
-- ▼	Zahlen
-- ▼	Zeichentabellen
-- ▼	Allgemeine Konstanten
-- ▼ Sternsysteme
-- ▼	Einzelne Funktionen für "GetStarSystemInfo"
-- ▼	Cluster
-- ▼ Orbiter
-- ▼ Objekte
-- ▼	Explosionseffekte
-- ▼ Schiffe und Wings
-- ▼	XWing-Funktionen (Erweiterungen für NWing)
-- ▼	Schiffstypen
-- ▼	Allgemeine Schiffsfunktionen
-- ▼	Energie und Ausrüstung
-- ▼	Munition
-- ▼	Aktionen für Schiffe und Wings
-- ▼ Kommunikation
-- ▼ Container und Waren
-- ▼	Spezielle Waren im System
-- ▼ Missionen
-- ▼ Tabellen (Arrays) und Strings
-- ▼ Mathematische Funktionen
-- ▼	Zufallszahlen
-- ▼	Logische Funktionen
-- ▼	Zeitfunktionen, Stoppuhr
-- ▼	Kontostand des Spielers manipulieren
-- ▼	Erzeugungsbereiche
-- ▼	Positionen anzeigen
-- ▼	Vektoren
-- ▼ Erzeugung von Objekten
-- ▼	Minenfelder
-- ▼	Schiffe und Wings
-- ▼ Gameplay Einstellungen
--
------------------------------[ Notes ]-----------------------------------------
-- Zum besseren Lesen die Tabulatorbreite im Editor auf 4 einstellen.
------------------------------[ Import ]----------------------------------------

import "string"
import "NCanyon"
import "NStory"

------------------------------[ Collection ]------------------------------------

XWing = {}

--============================[ Globale Konstanten ]============================

-- Munition
AMMO_TYPE_RAPTOR	= 10	-- Raptorwaffe
AMMO_TYPE_MINE		= 11	-- Mine
AMMO_TYPE_SHOOTER	= 12	-- Selbstfeuernde Mine
AMMO_TYPE_RAPTORBOSS	= 13	-- Stinger-Raketen ohne Reichweitenbeschränkung und hoher Feuerrate
AMMO_TYPE_TURRETMISSILE	= 14	-- Geschützturm als Raketenlafette
AMMO_TYPE_MINE_BRONIS	= 15	-- Selbstfeuernde Mine in der Waffenfabrik
AMMO_TYPE_LIGHT		= 16	-- Explosionseffekt
AMMO_TYPE_MORTOKBOSS	= 18	-- Eine leichte Hellfire, Raptor: ein ganzes Bündel Schwarmraketen
AMMO_TYPE_NONE		= -1	-- Keine Munition

AMMO_SWARM	= { Ammo = AMMO_TYPE_SWARM }
AMMO_HELLFIRE	= { Ammo = AMMO_TYPE_HELLFIRE }
AMMO_BIGBANG	= { Ammo = AMMO_TYPE_BIGBANG }
AMMO_RAPTOR	= { Ammo = AMMO_TYPE_RAPTOR }
AMMO_RAPTORBOSS	= { Ammo = AMMO_TYPE_RAPTORBOSS }
AMMO_MORTOKBOSS	= { Ammo = AMMO_TYPE_MORTOKBOSS }

AMMO_INDEX_SWARM	= { 0, 1, 2, 3, 4, 5, 82, 83, 84, 85 }
AMMO_INDEX_HELLFIRE	= { 0, 6, 7, 8, 9, 10, 78, 79, 80, 81 }
AMMO_INDEX_BIGBANG	= { 0, 6, 11, 12, 13, 14, 86, 87, 88, 89 }
AMMO_INDEX_RAPTOR	= { 27, 28, 29, 30, 31, 32, 33, 34, 35, 36 }
AMMO_INDEX_RAPTORBOSS	= { 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 }
AMMO_INDEX_MORTOKBOSS	= { 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 }

AMMO_INDEX = {
    [AMMO_TYPE_SWARM]	   = AMMO_INDEX_SWARM,
    [AMMO_TYPE_HELLFIRE]   = AMMO_INDEX_HELLFIRE,
    [AMMO_TYPE_BIGBANG]	   = AMMO_INDEX_BIGBANG,
    [AMMO_TYPE_RAPTOR]	   = AMMO_INDEX_RAPTOR,
    [AMMO_TYPE_RAPTORBOSS] = AMMO_INDEX_RAPTORBOSS,
    [AMMO_TYPE_MORTOKBOSS] = AMMO_INDEX_MORTOKBOSS
}

-- Benutzeroberfläche (GUI)
BUTTON_COMMUNICATION	= { Button = GUI_BTN_COMMUNICATION }	-- Ziel kontaktieren
BUTTON_CONTAINER_DROP	= { Button = GUI_BTN_CONTAINER_DROP }	-- Container abwerfen
BUTTON_CONTAINER_GET	= { Button = GUI_BTN_CONTAINER_GET }	-- Container aufnehmen
BUTTON_HYPERJUMP	= { Button = GUI_BTN_HYPERJUMP }	-- Hyperraumsprung ausführen
BUTTON_LOGBOOK		= { Button = GUI_BTN_LOGBOOK }		-- Logbuch öffnen
BUTTON_LOGBOOK_UPGRADE	= { Button = GUI_BTN_LOGBOOK_UPGRADE }	-- Upgradelog öffnen
BUTTON_MENU		= { Button = GUI_BTN_MENU }		-- Optionsmenü öffnen
BUTTON_NAVMAP		= { Button = GUI_BTN_NAVMAP }		-- Navigationskarte öffnen
BUTTON_PLASMA		= { Button = GUI_BTN_PLASMA }		-- Plasmawaffe auswählen
BUTTON_ROCKET		= { Button = GUI_BTN_ROCKET }		-- Raketensorte auswählen
BUTTON_TARGETMAP	= { Button = GUI_BTN_TARGETMAP }	-- Targetliste öffnen
BUTTON_TIME		= { Button = GUI_BTN_TIME }		-- Zeitbeschleunigung aktivieren
BUTTON_UPGRADE		= { Button = GUI_BTN_UPGRADE }		-- Upgrade durchführen

HELP_SHIPCONTROLS	= { Screen = 0 }	-- Schiffssteuerung
HELP_TARGET		= { Screen = 1 }	-- Ziel und Targetliste
HELP_CONTAINER		= { Screen = 2 }	-- Container aufnehmen/abwerfen
HELP_CONTGET_TIME	= { Screen = 3 }	-- Container aufnehmen, Zeitbeschleunigung
HELP_WEAPONS		= { Screen = 4 }	-- Waffenbedienung
HELP_ALL		= { Screen = 5 }	-- Alle Belegungen von Joystick, Maus und Tastatur

-- Container und Waren
CONTAINER_NONE	= -1	-- ist kein Container, z.B. für "NContainer.GetType"
GOODS_NONE	= 24	-- keine Handelswaren
GOODS_WEAPON	= 26	-- Geheimdienstwaffe
SPECIAL_GOODS	= { GOODS_VIDEOGAMES, GOODS_LUXURIES, GOODS_ANDROIDS, GOODS_DRUGS }  -- Spezielle Waren

CONTAINER_TONS = { -- Frachtkapazität der Container, Index ist die Größenklasse
    [0] =
    50;		-- CONTAINER_SMALL
    100,	-- CONTAINER_MEDIUM
    200,	-- CONTAINER_LARGE
    1,		-- CONTAINER_SPECIAL
    1,		-- CONTAINER_PASSENGER
    50,		-- CONTAINER_ROCK
    0		-- CONTAINER_ARTEFACT
}

ILLEGAL_GOODS = { -- Verbotene Spezialwaren eines Systems, Index ist dessen Regierungsform
    [0] =
    { GOODS_ANDROIDS, GOODS_DRUGS };		-- GOVERN_DEMOCRACY	Demokratie
    { GOODS_VIDEOGAMES, GOODS_LUXURIES },	-- GOVERN_DICTATORSHIP	Diktatur
    { GOODS_NONE },				-- GOVERN_FEDERATION	Staatenbund  (Alles ist erlaubt)
    { GOODS_NONE },				-- GOVERN_ANARCHY	Anarchie     (Alles ist erlaubt)
    { GOODS_VIDEOGAMES, GOODS_DRUGS },		-- GOVERN_CONCERN	Konzern
    { GOODS_LUXURIES, GOODS_ANDROIDS }		-- GOVERN_MONARCHY	Monarchie
--  { GOODS_VIDEOGAMES, GOODS_ANDROIDS }	-- n.a.
--  { GOODS_LUXURIES, GOODS_DRUGS }		-- n.a.
}

LEGAL_GOODS = { -- Erlaubte Spezialwaren eines Systems, Index ist dessen Regierungsform
    [0] =
    { GOODS_VIDEOGAMES, GOODS_LUXURIES };	-- GOVERN_DEMOCRACY	Demokratie
    { GOODS_ANDROIDS, GOODS_DRUGS },		-- GOVERN_DICTATORSHIP	Diktatur
    SPECIAL_GOODS,				-- GOVERN_FEDERATION	Staatenbund  (Alles ist erlaubt)
    SPECIAL_GOODS,				-- GOVERN_ANARCHY	Anarchie     (Alles ist erlaubt)
    { GOODS_LUXURIES, GOODS_ANDROIDS },		-- GOVERN_CONCERN	Konzern
    { GOODS_VIDEOGAMES, GOODS_DRUGS }		-- GOVERN_MONARCHY	Monarchie
}

MISSION_GOODS = { -- Liste mit den StringId's für diverse Missionswaren
    "ID_AMMO",				-- Munition
    "ID_APPLES",			-- Angebissene Äpfel
    "ID_ARKON_STEEL",			-- Arkon T-Stahl
    "ID_BUILDING_MATERIAL",		-- Baumaterial
    "ID_BLUMENKOHL",			-- Blumenkohl
    "ID_CANNABIS",			-- Cannabis
    "ID_COM_SAT",			-- Telekom-Satellit
    "ID_COTTON",			-- Baumwolle
    "ID_EQUIPMENT_20",			-- Equipment Nr. 20
    "ID_HJ_ACTUATOR",			-- Absprung-Aktuator
    "ID_HYDRAZIN",			-- Hydrazin
    "ID_MOHNSAMEN",			-- Mohnsamen
    "ID_NITROGLYCERIN",			-- Propantrioltrinitrat
    "ID_SHOP_ROCKET",			-- Raketen
    "ID_SHOP_SHIELD",			-- Energiesysteme
    "ID_SHOP_TECH",			-- Ausrüstung
    "ID_SHOP_WEAPONS",			-- Waffensysteme
    "ID_SPACEOBJ_ADVERTISMENT",		-- Werbetafel
    "ID_SPACEOBJ_DEBRIS",		-- Weltraumschrott
    "ID_SPACEOBJ_SCAT",			-- Schrott
    "ID_SPACEOBJ_SUBSTATION",		-- Stationsmodul
    "ID_SPINAT",			-- Spinat
    "ID_TELESCOPE",			-- Weltraum-Teleskop
    "ID_TERKONIT",			-- Terkonit-Stahl
    "ID_TV_SAT",			-- Fernseh-Satellit
    "ID_WEATHER_SAT",			-- Wetter-Satellit
    "ID_WERFT_ITEM_8",			-- Feldantrieb 10 Lj
    "ID_WERFT_ITEMSTRING_33",		-- Sprengköpfe
    "ID_YNKELONIUM",			-- Ynkelonium
    "IDM_ASCARONG_CONTAINERCONTENT",	-- Sprengstoff
    "IDM_BAR_00_CARGO",			-- Warp Pod 20 Lj
    "IDM_BAR_000_CONTAINER",		-- Androidenprototypen
    "IDM_BAR_002_03_MINING",		-- Bergbauausrüstung
    "IDM_BAR_002_03_TNT",		-- Trinitrotoluol (TNT)
    "IDM_GLOBAL_002_CONTAINER_CONTENT",	-- Computerteile
    "IDM_GLOBAL_006_CARGO",		-- Handelsgüter
    "IDM_GLOBAL_009_CONTAINER",		-- Gemischte Blumen
    "IDM_GLOBAL_024_ITEM",		-- Portscanner
    "IDM_GLOBAL_025_CONTAINER",		-- Forschungsausrüstung
    "IDM_GLOBAL_031_GOODS",		-- Chip-Prototypen
    "IDM_GLOBAL_041_SATNAME1",		-- Langstreckensensor
    "IDM_GLOBAL_041_SATNAME2",		-- Forschungssatellit
    "IDM_GLOBAL_042_CONTAINER",		-- Ersatzteile
    "IDM_PASSIV_004_TOOLS",		-- Werkzeuge
    "IDM_STORY_007_CONTAINER",		-- Schmuggelware
    "IDM_STORY_011_COMSAT_NAME",	-- Langstreckentransmitter
    "IDM_STORY_013_SATELLITE",		-- XPV/3 Sensor
    "IDM_STORY_016_CONTAINER1",		-- Alkoholische Getränke
    "IDM_STORY_018_CONTAINER_CONTENT",	-- Satellit
    "IDM_STORY_018_SCANNER_ITEM",	-- Satellitenscanner
    "UQM_1",				-- Aqua Helix
    "UQM_2",				-- Burvix Caster
    "UQM_3",				-- Clear Spindle
    "UQM_4",				-- Mycon Egg Case
    "UQM_5",				-- Glowing Rod
    "UQM_6",				-- Moon Base
    "UQM_7",				-- Quasi Portal
    "UQM_8",				-- Rosy Sphere
    "UQM_9",				-- Shofixti Maidens
    "UQM_10",				-- Sun Device
    "UQM_11",				-- Syreen Shuttle
    "UQM_12",				-- Taalo Shield
    "UQM_13",				-- Talking Pet
    "UQM_14",				-- Ultron
    "UQM_15",				-- Umgah Caster
    "UQM_16",				-- Utwig Bomb
    "UQM_17",				-- VUX Beast
    "UQM_18"				-- Wimbli’s Trident
}

TRADE_GOODS = { -- Exportwaren der Systeme, Index ist die SystemId
    -- Lalande
    [0] =
    { 0, 1, 3, 12, 23 };    -- Witon        Kohlenhydrate, Proteine, Pflanzenfasern, Medizin, Drogen
    { 2, 5, 16, 17, 18 },   -- Cloosa       Lebensformen, Edelmetalle, Energiezellen, Brennstäbe, Isotope
    { 0, 1, 3, 19, 20 },    -- Weca         Kohlenhydrate, Proteine, Pflanzenfasern, Supraleiter, Videospiele
    { 4, 6, 7, 15, 17 },    -- Pecola       Metalle, Kristalle, Legierungen, Dünger, Brennstäbe
    { 3, 9, 10, 11, 13 },   -- Obas         Pflanzenfasern, Elekronik, Computer, Schiffstechnik, Chemikalien
    { 4, 12, 13, 14, 19 },  -- Hu           Metalle, Medizin, Chemikalien, Spirituosen, Supraleiter
    { 16, 18, 21, 22, 23 }, -- Yankni       Energiezellen, Isotope, Luxusartikel, Androiden, Drogen
    { 4, 8, 12, 13, 15 },   -- Natshorim    Metalle, Maschinen, Medizin, Chemikalien, Dünger
    { 8, 12, 14, 15, 20 },  -- Pencah       Maschinen, Medizin, Spirituosen, Dünger, Videospiele
    { 6, 14, 20, 21, 22 },  -- Athasho      Kristalle, Spirituosen, Videospiele, Luxusartikel, Androiden
    { 0, 1, 2, 5, 19 },     -- Yarie        Kohlenhydrate, Proteine, Lebensformen, Edelmetalle, Supraleiter
    { 7, 8, 9, 10, 11 },    -- Pachee       Legierungen, Maschinen, Elekronik, Computer, Schiffstechnik
    -- Barnard
    { 0, 1, 2, 3, 14 },     -- Patorwalla   Kohlenhydrate, Proteine, Lebensformen, Pflanzenfasern, Spirituosen
    { 9, 17, 18, 19, 20 },  -- Kalima       Elekronik, Brennstäbe, Isotope, Supraleiter, Videospiele
    { 13, 14, 15, 16, 21 }, -- Zuos         Chemikalien, Spirituosen, Dünger, Energiezellen, Luxusartikel
    { 0, 1, 2, 10, 11 },    -- Tanee        Kohlenhydrate, Proteine, Lebensformen, Computer, Schiffstechnik
    { 4, 5, 7, 12, 13 },    -- Metharon     Metalle, Edelmetalle, Legierungen, Medizin, Chemikalien
    { 4, 5, 6, 8, 23 },     -- Mesehkane    Metalle, Edelmetalle, Kristalle, Maschinen, Drogen
    { 3, 6, 8, 10, 11 },    -- Anomi        Pflanzenfasern, Kristalle, Maschinen, Computer, Schiffstechnik
    { 15, 16, 21, 22, 23 }, -- Ta           Dünger, Energiezellen, Luxusartikel, Androiden, Drogen
    -- Tau Ceti
    { 5, 9, 16, 18, 19 },   -- Oma          Edelmetalle, Elekronik, Energiezellen, Isotope, Supraleiter
    { 4, 15, 21, 22, 23 },  -- Tasakane     Metalle, Dünger, Luxusartikel, Androiden, Drogen
    { 1, 8, 16, 18, 19 },   -- Patiak       Proteine, Maschinen, Energiezellen, Isotope, Supraleiter
    { 6, 7, 8, 9, 11 },     -- Ote          Kristalle, Legierungen, Maschinen, Elekronik, Schiffstechnik
    { 0, 2, 3, 10, 20 },    -- Taba         Kohlenhydrate, Lebensformen, Pflanzenfasern, Computer, Videospiele
    { 1, 12, 13, 14, 17 },  -- Zuoria       Proteine, Medizin, Chemikalien, Spirituosen, Brennstäbe
    -- Alpha Centauri
    { 8, 9, 10, 12, 16 },   -- Echee        Maschinen, Elekronik, Computer, Medizin, Energiezellen
    { 5, 8, 10, 11, 12 },   -- Page         Edelmetalle, Maschinen, Computer, Schiffstechnik, Medizin
    { 2, 4, 6, 7, 9 },      -- Yankwalla    Lebensformen, Metalle, Kristalle, Legierungen, Elekronik
    { 1, 13, 14, 15, 18 },  -- Sol          Proteine, Chemikalien, Spirituosen, Dünger, Isotope
    { 0, 1, 3, 6, 19 },     -- Spocheewalla Kohlenhydrate, Proteine, Pflanzenfasern, Kristalle, Supraleiter
    { 10, 14, 20, 22, 23 }, -- Pani         Computer, Spirituosen, Videospiele, Androiden, Drogen
    { 4, 5, 7, 14, 18 },    -- Keoshotu     Metalle, Edelmetalle, Legierungen, Spirituosen, Isotope
    { 4, 11, 20, 21, 23 },  -- Waba         Metalle, Schiffstechnik, Videospiele, Luxusartikel, Drogen
    { 1, 3, 16, 17, 18 },   -- Shoma        Proteine, Pflanzenfasern, Energiezellen, Brennstäbe, Isotope
    { 2, 5, 6, 7, 17 },     -- Parim        Lebensformen, Edelmetalle, Kristalle, Legierungen, Brennstäbe
    { 0, 2, 16, 17, 19 },   -- Wini         Kohlenhydrate, Lebensformen, Energiezellen, Brennstäbe, Supraleiter
    { 9, 17, 18, 19, 22 },  -- Yankton      Elekronik, Brennstäbe, Isotope, Supraleiter, Androiden
    { 3, 12, 13, 15, 22 },  -- Ete          Pflanzenfasern, Medizin, Chemikalien, Dünger, Androiden
    { 8, 9, 10, 15, 21 },   -- Witha        Maschinen, Elekronik, Computer, Dünger, Luxusartikel
    { 11, 16, 20, 21, 22 }, -- Teha         Schiffstechnik, Energiezellen, Videospiele, Luxusartikel, Androiden
    -- Grotok
    { 1, 2, 3, 4, 21 },     -- Sassudia     Proteine, Lebensformen, Pflanzenfasern, Metalle, Luxusartikel
    { 4, 6, 7, 9, 15 },     -- Baylona      Metalle, Kristalle, Legierungen, Elekronik, Dünger
    { 11, 16, 17, 18, 22 }, -- Albadiz      Schiffstechnik, Energiezellen, Brennstäbe, Isotope, Androiden
    { 2, 13, 16, 17, 19 },  -- Masba        Lebensformen, Chemikalien, Energiezellen, Brennstäbe, Supraleiter
    { 6, 8, 9, 10, 18 },    -- Alarluz      Kristalle, Maschinen, Elekronik, Computer, Isotope
    { 1, 8, 10, 11, 23 },   -- Neplocruz    Proteine, Maschinen, Computer, Schiffstechnik, Drogen
    { 4, 6, 7, 14, 23 },    -- Lugoferra    Metalle, Kristalle, Legierungen, Spirituosen, Drogen
    { 2, 3, 12, 13, 14 },   -- Arrosloca    Lebensformen, Pflanzenfasern, Medizin, Chemikalien, Spirituosen
    { 0, 1, 2, 7, 17 },     -- Albola       Kohlenhydrate, Proteine, Lebensformen, Legierungen, Brennstäbe
    { 4, 12, 13, 14, 17 },  -- Lucia        Metalle, Medizin, Chemikalien, Spirituosen, Brennstäbe
    { 5, 8, 16, 18, 19 },   -- Alegenla     Edelmetalle, Maschinen, Energiezellen, Isotope, Supraleiter
    { 9, 10, 11, 13, 16 },  -- Matada       Elekronik, Computer, Schiffstechnik, Chemikalien, Energiezellen
    { 7, 9, 10, 11, 12 },   -- Aranjar      Legierungen, Elekronik, Computer, Schiffstechnik, Medizin
    { 3, 6, 20, 22, 23 },   -- Rubiro       Pflanzenfasern, Kristalle, Videospiele, Androiden, Drogen
    { 4, 8, 10, 11, 20 },   -- Camvilje     Metalle, Maschinen, Computer, Schiffstechnik, Videospiele
    { 1, 8, 10, 11, 19 },   -- Mandedulce   Proteine, Maschinen, Computer, Schiffstechnik, Supraleiter
    { 0, 16, 18, 19, 22 },  -- Lular        Kohlenhydrate, Energiezellen, Isotope, Supraleiter, Androiden
    { 5, 8, 10, 11, 15 },   -- Alfabalas    Edelmetalle, Maschinen, Computer, Schiffstechnik, Dünger
    { 0, 1, 2, 20, 21 },    -- Bramurcia    Kohlenhydrate, Proteine, Lebensformen, Videospiele, Luxusartikel
    { 5, 15, 20, 21, 23 },  -- Martotacon   Edelmetalle, Dünger, Videospiele, Luxusartikel, Drogen
    { 7, 8, 9, 10, 12 },    -- Naro         Legierungen, Maschinen, Elekronik, Computer, Medizin
    -- Pertok
    { 3, 6, 8, 9, 10 },     -- Eicete       Pflanzenfasern, Kristalle, Maschinen, Elekronik, Computer
    { 14, 16, 17, 18, 21 }, -- Arotorracin  Spirituosen, Energiezellen, Brennstäbe, Isotope, Luxusartikel
    { 0, 2, 3, 5, 21 },     -- Rulote       Kohlenhydrate, Lebensformen, Pflanzenfasern, Edelmetalle, Luxusartikel
    { 4, 7, 8, 9, 11 },     -- Rocete       Metalle, Legierungen, Maschinen, Elekronik, Schiffstechnik
    { 0, 16, 20, 22, 23 },  -- Alaniz       Kohlenhydrate, Energiezellen, Videospiele, Androiden, Drogen
    { 4, 6, 7, 11, 21 },    -- Cavcala      Metalle, Kristalle, Legierungen, Schiffstechnik, Luxusartikel
    { 2, 5, 13, 14, 15 },   -- Biarnar      Lebensformen, Edelmetalle, Chemikalien, Spirituosen, Dünger
    -- Stromok
    { 0, 1, 3, 8, 9 },      -- Sarzar       Kohlenhydrate, Proteine, Pflanzenfasern, Maschinen, Elekronik
    { 0, 1, 3, 15, 20 },    -- Arber        Kohlenhydrate, Proteine, Pflanzenfasern, Dünger, Videospiele
    { 9, 11, 20, 22, 23 },  -- Cabracoy     Elekronik, Schiffstechnik, Videospiele, Androiden, Drogen
    { 0, 1, 3, 19, 20 },    -- Capella      Kohlenhydrate, Proteine, Pflanzenfasern, Supraleiter, Videospiele
    { 1, 2, 3, 11, 15 },    -- Alsavia      Proteine, Lebensformen, Pflanzenfasern, Schiffstechnik, Dünger
    { 5, 6, 7, 12, 19 },    -- Majarin      Edelmetalle, Kristalle, Legierungen, Medizin, Supraleiter
    { 8, 16, 17, 18, 22 },  -- Lucero       Maschinen, Energiezellen, Brennstäbe, Isotope, Androiden
    { 5, 8, 10, 11, 15 },   -- Adeviegar    Edelmetalle, Maschinen, Computer, Schiffstechnik, Dünger
    { 6, 9, 12, 14, 15 },   -- Rusiefes     Kristalle, Elekronik, Medizin, Spirituosen, Dünger
    { 5, 6, 7, 12, 18 },    -- Manorciras   Edelmetalle, Kristalle, Legierungen, Medizin, Isotope
    { 4, 7, 16, 17, 19 },   -- Haorta       Metalle, Legierungen, Energiezellen, Brennstäbe, Supraleiter
    { 14, 16, 17, 18, 21 }, -- Telbeigro    Spirituosen, Energiezellen, Brennstäbe, Isotope, Luxusartikel
    { 13, 17, 20, 21, 23 }, -- Anmansa      Chemikalien, Brennstäbe, Videospiele, Luxusartikel, Drogen
    { 13, 16, 18, 19, 21 }, -- Arromazan    Chemikalien, Energiezellen, Isotope, Supraleiter, Luxusartikel
    { 0, 8, 21, 22, 23 },   -- Risafes      Kohlenhydrate, Maschinen, Luxusartikel, Androiden, Drogen
    { 8, 12, 13, 14, 17 },  -- Pinzar       Maschinen, Medizin, Chemikalien, Spirituosen, Brennstäbe
    { 2, 9, 10, 11, 23 },   -- Lorbeisua    Lebensformen, Elekronik, Computer, Schiffstechnik, Drogen
    { 2, 12, 13, 14, 18 },  -- Sorfulla     Lebensformen, Medizin, Chemikalien, Spirituosen, Isotope
    { 12, 14, 21, 22, 23 }, -- Cenposta     Medizin, Spirituosen, Luxusartikel, Androiden, Drogen
    { 4, 5, 6, 7, 10 },     -- Odia         Metalle, Edelmetalle, Kristalle, Legierungen, Computer
    -- Klatok
    { 6, 9, 10, 11, 14 },   -- Biardorra    Kristalle, Elekronik, Computer, Schiffstechnik, Spirituosen
    { 5, 6, 7, 10, 22 },    -- Sarbrejar    Edelmetalle, Kristalle, Legierungen, Computer, Androiden
    { 1, 2, 3, 11, 20 },    -- Ferreriquera Proteine, Lebensformen, Pflanzenfasern, Schiffstechnik, Videospiele
    { 5, 6, 12, 13, 14 },   -- Petevegua    Edelmetalle, Kristalle, Medizin, Chemikalien, Spirituosen
    { 1, 4, 5, 6, 21 },     -- Grajuez      Proteine, Metalle, Edelmetalle, Kristalle, Luxusartikel
    { 1, 13, 16, 17, 18 },  -- Argozazu     Proteine, Chemikalien, Energiezellen, Brennstäbe, Isotope
    { 8, 9, 10, 14, 16 },   -- Aychena      Maschinen, Elekronik, Computer, Spirituosen, Energiezellen
    { 7, 16, 21, 22, 23 },  -- Albocos      Legierungen, Energiezellen, Luxusartikel, Androiden, Drogen
    { 0, 11, 12, 13, 14 },  -- Miganda      Kohlenhydrate, Schiffstechnik, Medizin, Chemikalien, Spirituosen
    { 8, 10, 11, 15, 18 },  -- Vielvietona  Maschinen, Computer, Schiffstechnik, Dünger, Isotope
    { 7, 15, 20, 21, 23 },  -- Aguamaniz    Legierungen, Dünger, Videospiele, Luxusartikel, Drogen
    { 0, 2, 3, 14, 17 },    -- Siedillo     Kohlenhydrate, Lebensformen, Pflanzenfasern, Spirituosen, Brennstäbe
    { 5, 12, 13, 15, 17 },  -- Cuendo       Edelmetalle, Medizin, Chemikalien, Dünger, Brennstäbe
    { 0, 1, 3, 12, 20 },    -- Horcruz      Kohlenhydrate, Proteine, Pflanzenfasern, Medizin, Videospiele
    { 0, 7, 16, 18, 19 },   -- Cazviecife   Kohlenhydrate, Legierungen, Energiezellen, Isotope, Supraleiter
    { 1, 2, 3, 4, 19 },     -- Fuenxadas    Proteine, Lebensformen, Pflanzenfasern, Metalle, Supraleiter
    { 4, 8, 9, 11, 12 },    -- Alquebayo    Metalle, Maschinen, Elekronik, Schiffstechnik, Medizin
    { 1, 2, 3, 9, 15 },     -- Ubeties      Proteine, Lebensformen, Pflanzenfasern, Elekronik, Dünger
    { 13, 16, 20, 22, 23 }, -- Mostorga     Chemikalien, Energiezellen, Videospiele, Androiden, Drogen
    { 2, 8, 17, 18, 19 },   -- Bielturias   Lebensformen, Maschinen, Brennstäbe, Isotope, Supraleiter
    { 0, 7, 21, 22, 23 },   -- Altazaarfe   Kohlenhydrate, Legierungen, Luxusartikel, Androiden, Drogen
    { 0, 2, 16, 17, 18 },   -- Avilmurcia   Kohlenhydrate, Lebensformen, Energiezellen, Brennstäbe, Isotope
    { 9, 10, 11, 20, 22 },  -- Fribeicon    Elekronik, Computer, Schiffstechnik, Videospiele, Androiden
    { 2, 4, 5, 6, 13 },     -- Tero         Lebensformen, Metalle, Edelmetalle, Kristalle, Chemikalien
    { 0, 5, 17, 18, 19 },   -- Fuenbocete   Kohlenhydrate, Edelmetalle, Brennstäbe, Isotope, Supraleiter
    { 3, 13, 14, 15, 19 },  -- Camrracin    Pflanzenfasern, Chemikalien, Spirituosen, Dünger, Supraleiter
    -- Humok
    { 4, 13, 14, 15, 16 },  -- Agualote     Metalle, Chemikalien, Spirituosen, Dünger, Energiezellen
    { 4, 5, 7, 8, 22 },     -- Rodia        Metalle, Edelmetalle, Legierungen, Maschinen, Androiden
    { 1, 2, 3, 14, 15 },    -- Zaniz        Proteine, Lebensformen, Pflanzenfasern, Spirituosen, Dünger
    { 0, 3, 16, 17, 19 },   -- Cadacala     Kohlenhydrate, Pflanzenfasern, Energiezellen, Brennstäbe, Supraleiter
    { 1, 2, 5, 6, 7 },      -- Eitanar      Proteine, Lebensformen, Edelmetalle, Kristalle, Legierungen
    { 3, 12, 13, 15, 21 },  -- Canniozar    Pflanzenfasern, Medizin, Chemikalien, Dünger, Luxusartikel
    { 1, 2, 3, 9, 12 },     -- Antetaber    Proteine, Lebensformen, Pflanzenfasern, Elekronik, Medizin
    { 10, 14, 21, 22, 23 }, -- Vipacoy      Computer, Spirituosen, Luxusartikel, Androiden, Drogen
    { 0, 8, 10, 11, 21 },   -- Cesella      Kohlenhydrate, Maschinen, Computer, Schiffstechnik, Luxusartikel
    { 9, 10, 11, 18, 20 },  -- Manzahuvia   Elekronik, Computer, Schiffstechnik, Isotope, Videospiele
    { 0, 12, 17, 18, 19 },  -- Arnelajarin  Kohlenhydrate, Medizin, Brennstäbe, Isotope, Supraleiter
    { 6, 13, 17, 18, 19 },  -- Alsaro       Kristalle, Chemikalien, Brennstäbe, Isotope, Supraleiter
    { 8, 9, 11, 13, 16 },   -- Fresgar      Maschinen, Elekronik, Schiffstechnik, Chemikalien, Energiezellen
    -- Raptor Alpha
    { 0, 1, 2, 12, 22 },    -- Zhusomol     Kohlenhydrate, Proteine, Lebensformen, Medizin, Androiden
    { 6, 9, 10, 11, 16 },   -- Nostromo     Kristalle, Elekronik, Computer, Schiffstechnik, Energiezellen
    { 3, 8, 14, 15, 19 },   -- Teirov       Pflanzenfasern, Maschinen, Spirituosen, Dünger, Supraleiter
    { 14, 17, 20, 21, 23 }, -- Tamburg      Spirituosen, Brennstäbe, Videospiele, Luxusartikel, Drogen
    { 4, 5, 7, 13, 18 },    -- Lysmir       Metalle, Edelmetalle, Legierungen, Chemikalien, Isotope
    -- Raptor Nova
    { 0, 1, 2, 12, 16 },    -- Borriev      Kohlenhydrate, Proteine, Lebensformen, Medizin, Energiezellen
    { 1, 11, 20, 21, 22 },  -- Zapul        Proteine, Schiffstechnik, Videospiele, Luxusartikel, Androiden
    { 0, 3, 5, 6, 7 },      -- Goro         Kohlenhydrate, Pflanzenfasern, Edelmetalle, Kristalle, Legierungen
    { 10, 12, 16, 18, 19 }, -- Brakann      Computer, Medizin, Energiezellen, Isotope, Supraleiter
    { 4, 7, 13, 14, 15 },   -- Mynok        Metalle, Legierungen, Chemikalien, Spirituosen, Dünger
    { 4, 6, 7, 8, 13 },     -- Vidal        Metalle, Kristalle, Legierungen, Maschinen, Chemikalien
    { 5, 9, 16, 17, 19 },   -- Komkannmir   Edelmetalle, Elekronik, Energiezellen, Brennstäbe, Supraleiter
    { 0, 2, 3, 10, 20 },    -- Zareck       Kohlenhydrate, Lebensformen, Pflanzenfasern, Computer, Videospiele
    { 6, 8, 9, 10, 22 },    -- Nizbin       Kristalle, Maschinen, Elekronik, Computer, Androiden
    { 6, 15, 17, 18, 19 },  -- Eletsmir     Kristalle, Dünger, Brennstäbe, Isotope, Supraleiter
    { 5, 8, 9, 11, 22 },    -- Khimzan      Edelmetalle, Maschinen, Elekronik, Schiffstechnik, Androiden
    { 1, 2, 3, 6, 15 },     -- Bogojol      Proteine, Lebensformen, Pflanzenfasern, Kristalle, Dünger
    { 5, 12, 13, 14, 18 },  -- Kosrod       Edelmetalle, Medizin, Chemikalien, Spirituosen, Isotope
    -- Raptor Gamma
    { 8, 10, 11, 13, 15 },  -- Bogozan      Maschinen, Computer, Schiffstechnik, Chemikalien, Dünger
    { 1, 6, 16, 18, 19 },   -- Schel        Proteine, Kristalle, Energiezellen, Isotope, Supraleiter
    { 0, 9, 10, 11, 20 },   -- Chernomen    Kohlenhydrate, Elekronik, Computer, Schiffstechnik, Videospiele
    { 0, 1, 3, 12, 23 },    -- Mana         Kohlenhydrate, Proteine, Pflanzenfasern, Medizin, Drogen
    { 0, 1, 2, 5, 16 },     -- Malopul      Kohlenhydrate, Proteine, Lebensformen, Edelmetalle, Energiezellen
    { 0, 4, 5, 6, 16 },     -- Suzga        Kohlenhydrate, Metalle, Edelmetalle, Kristalle, Energiezellen
    { 5, 6, 7, 8, 9 },      -- Eletssk      Edelmetalle, Kristalle, Legierungen, Maschinen, Elekronik
    { 10, 14, 21, 22, 23 }, -- Kostrono     Computer, Spirituosen, Luxusartikel, Androiden, Drogen
    { 4, 6, 7, 9, 15 },     -- Balasom      Metalle, Kristalle, Legierungen, Elekronik, Dünger
    { 2, 12, 13, 14, 20 },  -- Desno        Lebensformen, Medizin, Chemikalien, Spirituosen, Videospiele
    { 4, 5, 7, 18, 21 },    -- Goronezh     Metalle, Edelmetalle, Legierungen, Isotope, Luxusartikel
    { 9, 12, 14, 15, 21 },  -- Twerkano     Elekronik, Medizin, Spirituosen, Dünger, Luxusartikel
    { 7, 12, 14, 15, 21 },  -- Simcow       Legierungen, Medizin, Spirituosen, Dünger, Luxusartikel
    { 2, 17, 20, 22, 23 },  -- Nakhod       Lebensformen, Brennstäbe, Videospiele, Androiden, Drogen
    { 4, 5, 7, 8, 9 },      -- Murnij       Metalle, Edelmetalle, Legierungen, Maschinen, Elekronik
    { 3, 19, 21, 22, 23 },  -- Vidlukau     Pflanzenfasern, Supraleiter, Luxusartikel, Androiden, Drogen
    { 12, 13, 14, 17, 20 }, -- Celna        Medizin, Chemikalien, Spirituosen, Brennstäbe, Videospiele
    { 7, 13, 17, 18, 19 },  -- Yarosny      Legierungen, Chemikalien, Brennstäbe, Isotope, Supraleiter
    { 0, 1, 3, 6, 10 },     -- Zelenonezh   Kohlenhydrate, Proteine, Pflanzenfasern, Kristalle, Computer
    { 4, 8, 9, 11, 16 },    -- Mornamur     Metalle, Maschinen, Elekronik, Schiffstechnik, Energiezellen
    { 4, 9, 17, 18, 19 },   -- Tjuma        Metalle, Elekronik, Brennstäbe, Isotope, Supraleiter
    { 8, 10, 11, 19, 22 },  -- Sakaterin    Maschinen, Computer, Schiffstechnik, Supraleiter, Androiden
    { 0, 2, 3, 11, 15 },    -- Chakin       Kohlenhydrate, Lebensformen, Pflanzenfasern, Schiffstechnik, Dünger
    { 5, 6, 7, 15, 20 },    -- Abariev      Edelmetalle, Kristalle, Legierungen, Dünger, Videospiele
    { 3, 13, 17, 18, 19 },  -- Oren         Pflanzenfasern, Chemikalien, Brennstäbe, Isotope, Supraleiter
    -- Raptor Delta
    { 1, 2, 3, 6, 11 },     -- Archangelsk  Proteine, Lebensformen, Pflanzenfasern, Kristalle, Schiffstechnik
    { 1, 8, 9, 10, 12 },    -- Nakhodlu     Proteine, Maschinen, Elekronik, Computer, Medizin
    { 0, 2, 3, 15, 23 },    -- Koro         Kohlenhydrate, Lebensformen, Pflanzenfasern, Dünger, Drogen
    { 4, 5, 7, 22, 23 },    -- Chanschat    Metalle, Edelmetalle, Legierungen, Androiden, Drogen
    { 16, 17, 19, 20, 21 }, -- Saraschat    Energiezellen, Brennstäbe, Supraleiter, Videospiele, Luxusartikel
    { 7, 8, 9, 10, 12 },    -- Jegutna      Legierungen, Maschinen, Elekronik, Computer, Medizin
    { 0, 13, 14, 15, 18 },  -- Morkann      Kohlenhydrate, Chemikalien, Spirituosen, Dünger, Isotope
    { 4, 5, 6, 11, 22 },    -- Toggrad      Metalle, Edelmetalle, Kristalle, Schiffstechnik, Androiden
    -- Raptor Epsilon
    { 0, 13, 14, 15, 21 },  -- Amkovo       Kohlenhydrate, Chemikalien, Spirituosen, Dünger, Luxusartikel
    { 7, 12, 13, 15, 21 },  -- Kaschi       Legierungen, Medizin, Chemikalien, Dünger, Luxusartikel
    { 3, 16, 20, 21, 23 },  -- Penol        Pflanzenfasern, Energiezellen, Videospiele, Luxusartikel, Drogen
    { 0, 2, 3, 4, 9 },      -- Nizpul       Kohlenhydrate, Lebensformen, Pflanzenfasern, Metalle, Elekronik
    { 8, 9, 10, 14, 22 },   -- Simpawlo     Maschinen, Elekronik, Computer, Spirituosen, Androiden
    { 4, 6, 7, 8, 20 },     -- Charodpul    Metalle, Kristalle, Legierungen, Maschinen, Videospiele
    { 2, 4, 8, 10, 11 },    -- Abanaul      Lebensformen, Metalle, Maschinen, Computer, Schiffstechnik
    { 5, 11, 16, 17, 19 },  -- Beldets      Edelmetalle, Schiffstechnik, Energiezellen, Brennstäbe, Supraleiter
    { 0, 1, 3, 12, 18 },    -- Perekin      Kohlenhydrate, Proteine, Pflanzenfasern, Medizin, Isotope
    { 1, 2, 3, 12, 16 },    -- Khimtishy    Proteine, Lebensformen, Pflanzenfasern, Medizin, Energiezellen
    { 6, 18, 20, 22, 23 },  -- Petrokau     Kristalle, Isotope, Videospiele, Androiden, Drogen
    { 4, 5, 7, 9, 17 },     -- Permnaja     Metalle, Edelmetalle, Legierungen, Elekronik, Brennstäbe
    { 5, 10, 17, 18, 19 },  -- Desnodal     Edelmetalle, Computer, Brennstäbe, Isotope, Supraleiter
    -- Sion'nach
    { 8, 9, 11, 20, 23 },   -- Ken’ore      Maschinen, Elekronik, Schiffstechnik, Videospiele, Drogen
    { 3, 18, 20, 21, 22 },  -- Rhilo’chan   Pflanzenfasern, Isotope, Videospiele, Luxusartikel, Androiden
    { 12, 13, 16, 18, 19 }, -- Gans’clie    Medizin, Chemikalien, Energiezellen, Isotope, Supraleiter
    { 0, 4, 13, 14, 15 },   -- Li’atrie     Kohlenhydrate, Metalle, Chemikalien, Spirituosen, Dünger
    { 6, 10, 16, 17, 19 },  -- Ca’ore       Kristalle, Computer, Energiezellen, Brennstäbe, Supraleiter
    { 8, 10, 11, 16, 19 },  -- Kil’ore      Maschinen, Computer, Schiffstechnik, Energiezellen, Supraleiter
    { 1, 2, 3, 4, 12 },     -- Gallt’air    Proteine, Lebensformen, Pflanzenfasern, Metalle, Medizin
    { 5, 6, 7, 9, 12 },     -- Lon’ore      Edelmetalle, Kristalle, Legierungen, Elekronik, Medizin
    { 5, 8, 20, 21, 23 },   -- Abria’chan   Edelmetalle, Maschinen, Videospiele, Luxusartikel, Drogen
    { 4, 5, 7, 17, 18 },    -- Ann’at       Metalle, Edelmetalle, Legierungen, Brennstäbe, Isotope
    { 0, 1, 2, 22, 23 },    -- Kill’ate     Kohlenhydrate, Proteine, Lebensformen, Androiden, Drogen
    { 1, 2, 3, 8, 17 },     -- L’air        Proteine, Lebensformen, Pflanzenfasern, Maschinen, Brennstäbe
    { 10, 11, 13, 14, 15 }, -- Coill’ore    Computer, Schiffstechnik, Chemikalien, Spirituosen, Dünger
    -- Sirius
    { 1, 16, 17, 19, 20 },  -- Mechez       Proteine, Energiezellen, Brennstäbe, Supraleiter, Videospiele
    { 0, 2, 3, 13, 17 },    -- Wichita      Kohlenhydrate, Lebensformen, Pflanzenfasern, Chemikalien, Brennstäbe
    { 10, 13, 20, 22, 23 }, -- Ozurim       Computer, Chemikalien, Videospiele, Androiden, Drogen
    { 10, 12, 20, 21, 23 }, -- Wama         Computer, Medizin, Videospiele, Luxusartikel, Drogen
    { 0, 1, 4, 6, 7 },      -- Tezutiak     Kohlenhydrate, Proteine, Metalle, Kristalle, Legierungen
    { 0, 1, 3, 6, 13 },     -- Witeni       Kohlenhydrate, Proteine, Pflanzenfasern, Kristalle, Chemikalien
    { 5, 8, 21, 22, 23 },   -- Wica         Edelmetalle, Maschinen, Luxusartikel, Androiden, Drogen
    { 2, 11, 12, 14, 15 },  -- Ponniseh     Lebensformen, Schiffstechnik, Medizin, Spirituosen, Dünger
    { 0, 8, 9, 11, 20 },    -- Wallawalla   Kohlenhydrate, Maschinen, Elekronik, Schiffstechnik, Videospiele
    { 1, 12, 14, 15, 21 },  -- Patu         Proteine, Medizin, Spirituosen, Dünger, Luxusartikel
    { 6, 16, 18, 19, 22 },  -- Yaha         Kristalle, Energiezellen, Isotope, Supraleiter, Androiden
    { 5, 8, 9, 11, 21 },    -- Wenee        Edelmetalle, Maschinen, Elekronik, Schiffstechnik, Luxusartikel
    { 3, 9, 13, 14, 15 },   -- Cloma        Pflanzenfasern, Elekronik, Chemikalien, Spirituosen, Dünger
    { 4, 5, 7, 10, 18 },    -- Zute         Metalle, Edelmetalle, Legierungen, Computer, Isotope
    { 3, 8, 9, 11, 17 },    -- Pazuspell    Pflanzenfasern, Maschinen, Elekronik, Schiffstechnik, Brennstäbe
    -- Madra'mor
    { 5, 8, 17, 18, 19 },   -- Lochcar’ron  Edelmetalle, Maschinen, Brennstäbe, Isotope, Supraleiter
    { 7, 9, 10, 11, 20 },   -- Am’atn’atua  Legierungen, Elekronik, Computer, Schiffstechnik, Videospiele
    { 4, 5, 16, 17, 19 },   -- Ach’air      Metalle, Edelmetalle, Energiezellen, Brennstäbe, Supraleiter
    { 8, 9, 10, 11, 19 },   -- Ad’vie       Maschinen, Elekronik, Computer, Schiffstechnik, Supraleiter
    { 5, 8, 9, 10, 15 },    -- B’rochel     Edelmetalle, Maschinen, Elekronik, Computer, Dünger
    { 2, 3, 16, 18, 19 },   -- Sliga’chan   Lebensformen, Pflanzenfasern, Energiezellen, Isotope, Supraleiter
    { 0, 2, 3, 17, 19 },    -- Dochgar’roch Kohlenhydrate, Lebensformen, Pflanzenfasern, Brennstäbe, Supraleiter
    { 5, 6, 7, 11, 21 },    -- Bena’vie     Edelmetalle, Kristalle, Legierungen, Schiffstechnik, Luxusartikel
    { 4, 11, 13, 14, 15 },  -- Boath’vic    Metalle, Schiffstechnik, Chemikalien, Spirituosen, Dünger
    { 8, 16, 20, 21, 22 },  -- Bara’ore     Maschinen, Energiezellen, Videospiele, Luxusartikel, Androiden
    { 4, 6, 7, 15, 17 },    -- Lyn’ore      Metalle, Kristalle, Legierungen, Dünger, Brennstäbe
    { 1, 12, 13, 14, 19 },  -- D’ores       Proteine, Medizin, Chemikalien, Spirituosen, Supraleiter
    { 1, 2, 3, 13, 18 },    -- A’chill      Proteine, Lebensformen, Pflanzenfasern, Chemikalien, Isotope
    { 1, 13, 20, 21, 23 },  -- Loth’ore     Proteine, Chemikalien, Videospiele, Luxusartikel, Drogen
    { 4, 12, 20, 21, 23 },  -- Drum’unie    Metalle, Medizin, Videospiele, Luxusartikel, Drogen
    { 16, 17, 18, 22, 23 }, -- Ardmo’lich   Energiezellen, Brennstäbe, Isotope, Androiden, Drogen
    { 6, 12, 13, 14, 17 },  -- Ardar’roch   Kristalle, Medizin, Chemikalien, Spirituosen, Brennstäbe
    { 0, 1, 3, 19, 23 },    -- Skullo’mie   Kohlenhydrate, Proteine, Pflanzenfasern, Supraleiter, Drogen
    { 0, 1, 2, 12, 14 },    -- Achnab’at    Kohlenhydrate, Proteine, Lebensformen, Medizin, Spirituosen
    { 0, 2, 3, 4, 22 },     -- Garty’ore    Kohlenhydrate, Lebensformen, Pflanzenfasern, Metalle, Androiden
    { 0, 1, 3, 18, 22 },    -- Lynch’at     Kohlenhydrate, Proteine, Pflanzenfasern, Isotope, Androiden
    { 10, 12, 14, 15, 23 }, -- C’atlodge    Computer, Medizin, Spirituosen, Dünger, Drogen
    -- Prea'chan
    { 8, 10, 11, 12, 13 },  -- Tor’ore      Maschinen, Computer, Schiffstechnik, Medizin, Chemikalien
    { 6, 17, 20, 21, 23 },  -- Tul’lich     Kristalle, Brennstäbe, Videospiele, Luxusartikel, Drogen
    { 13, 16, 17, 19, 22 }, -- Ach’ore      Chemikalien, Energiezellen, Brennstäbe, Supraleiter, Androiden
    { 4, 6, 7, 8, 16 },     -- Bal’ore      Metalle, Kristalle, Legierungen, Maschinen, Energiezellen
    { 7, 14, 17, 18, 19 },  -- Kinloch’ore  Legierungen, Spirituosen, Brennstäbe, Isotope, Supraleiter
    { 0, 12, 13, 14, 16 },  -- Led’ore      Kohlenhydrate, Medizin, Chemikalien, Spirituosen, Energiezellen
    { 5, 6, 7, 12, 22 },    -- Ormsaig’nie  Edelmetalle, Kristalle, Legierungen, Medizin, Androiden
    { 4, 15, 21, 22, 23 },  -- Lyne’ore     Metalle, Dünger, Luxusartikel, Androiden, Drogen
    { 2, 11, 12, 14, 15 },  -- Garb’at      Lebensformen, Schiffstechnik, Medizin, Spirituosen, Dünger
    { 5, 10, 16, 18, 19 },  -- Dalmiga’vie  Edelmetalle, Computer, Energiezellen, Isotope, Supraleiter
    { 8, 9, 11, 15, 20 },   -- Sana’chan    Maschinen, Elekronik, Schiffstechnik, Dünger, Videospiele
    { 12, 19, 20, 22, 23 }, -- Achvaras’dal Medizin, Supraleiter, Videospiele, Androiden, Drogen
    { 0, 1, 2, 4, 18 },     -- Slie’ore     Kohlenhydrate, Proteine, Lebensformen, Metalle, Isotope
    { 1, 2, 3, 5, 9 },      -- Olgrin’nie   Proteine, Lebensformen, Pflanzenfasern, Edelmetalle, Elekronik
    { 3, 5, 6, 7, 14 },     -- Arpafee’lie  Pflanzenfasern, Edelmetalle, Kristalle, Legierungen, Spirituosen
    { 0, 1, 3, 10, 13 },    -- Sh’oreton    Kohlenhydrate, Proteine, Pflanzenfasern, Computer, Chemikalien
    -- Ross 128
    { 3, 4, 6, 7, 12 },     -- Shovis       Pflanzenfasern, Metalle, Kristalle, Legierungen, Medizin
    { 0, 1, 2, 8, 19 },     -- Yate         Kohlenhydrate, Proteine, Lebensformen, Maschinen, Supraleiter
    { 9, 18, 21, 22, 23 },  -- Penchi       Elekronik, Isotope, Luxusartikel, Androiden, Drogen
    { 16, 20, 21, 22, 23 }, -- Eosa         Energiezellen, Videospiele, Luxusartikel, Androiden, Drogen
    { 11, 13, 14, 15, 17 }, -- Pontiac      Schiffstechnik, Chemikalien, Spirituosen, Dünger, Brennstäbe
    { 3, 18, 20, 21, 22 },  -- Tenatori     Pflanzenfasern, Isotope, Videospiele, Luxusartikel, Androiden
    { 5, 6, 7, 9, 10 },     -- Omatu        Edelmetalle, Kristalle, Legierungen, Elekronik, Computer
    -- Bear'mor
    { 2, 4, 5, 7, 11 },     -- Ardul’lie    Lebensformen, Metalle, Edelmetalle, Legierungen, Schiffstechnik
    { 12, 16, 18, 19, 20 }, -- D’unie       Medizin, Energiezellen, Isotope, Supraleiter, Videospiele
    { 5, 6, 7, 11, 17 },    -- Sc’atraig    Edelmetalle, Kristalle, Legierungen, Schiffstechnik, Brennstäbe
    { 0, 1, 3, 14, 21 },    -- Al’vie       Kohlenhydrate, Proteine, Pflanzenfasern, Spirituosen, Luxusartikel
    { 8, 9, 10, 13, 15 },   -- Glen’ore     Maschinen, Elekronik, Computer, Chemikalien, Dünger
    -- Gab'har
    { 4, 6, 10, 13, 21 },   -- Sona’chan    Metalle, Kristalle, Computer, Chemikalien, Luxusartikel
    { 6, 19, 21, 22, 23 },  -- Tar’vie      Kristalle, Supraleiter, Luxusartikel, Androiden, Drogen
    { 6, 16, 18, 19, 23 },  -- Lairg’uie    Kristalle, Energiezellen, Isotope, Supraleiter, Drogen
    { 12, 13, 16, 17, 19 }, -- Newton’ore   Medizin, Chemikalien, Energiezellen, Brennstäbe, Supraleiter
    { 10, 11, 16, 18, 19 }, -- Lone’ron     Computer, Schiffstechnik, Energiezellen, Isotope, Supraleiter
    { 4, 16, 20, 21, 22 },  -- Lairin’vie   Metalle, Energiezellen, Videospiele, Luxusartikel, Androiden
    { 2, 9, 10, 11, 20 },   -- Sc’atwell    Lebensformen, Elekronik, Computer, Schiffstechnik, Videospiele
    { 8, 14, 20, 21, 23 },  -- Sort’at      Maschinen, Spirituosen, Videospiele, Luxusartikel, Drogen
    { 12, 17, 20, 22, 23 }, -- Linside’ore  Medizin, Brennstäbe, Videospiele, Androiden, Drogen
    { 0, 2, 3, 6, 14 },     -- Tom’atin     Kohlenhydrate, Lebensformen, Pflanzenfasern, Kristalle, Spirituosen
    { 1, 2, 3, 9, 11 },     -- Archrea’mie  Proteine, Lebensformen, Pflanzenfasern, Elekronik, Schiffstechnik
    { 10, 12, 13, 15, 21 }, -- Bad’aul      Computer, Medizin, Chemikalien, Dünger, Luxusartikel
    { 1, 9, 10, 11, 14 },   -- Clash’ore    Proteine, Elekronik, Computer, Schiffstechnik, Spirituosen
    { 8, 13, 14, 15, 17 },  -- L’athe’ron   Maschinen, Chemikalien, Spirituosen, Dünger, Brennstäbe
    { 13, 15, 17, 18, 19 }, -- Achnas’aul   Chemikalien, Dünger, Brennstäbe, Isotope, Supraleiter
    { 4, 5, 7, 9, 17 },     -- Rhe’ore      Metalle, Edelmetalle, Legierungen, Elekronik, Brennstäbe
    { 0, 1, 3, 18, 20 },    -- Insh’ore     Kohlenhydrate, Proteine, Pflanzenfasern, Isotope, Videospiele
    { 0, 8, 16, 17, 18 },   -- Bin’dal      Kohlenhydrate, Maschinen, Energiezellen, Brennstäbe, Isotope
    { 4, 5, 7, 12, 16 },    -- Dunb’ath     Metalle, Edelmetalle, Legierungen, Medizin, Energiezellen
    { 2, 4, 5, 7, 8 },      -- Altand’uin   Lebensformen, Metalle, Edelmetalle, Legierungen, Maschinen
    { 0, 1, 3, 5, 9 },      -- Dalna’vie    Kohlenhydrate, Proteine, Pflanzenfasern, Edelmetalle, Elekronik
    { 5, 6, 7, 15, 22 },    -- Achand’unie  Edelmetalle, Kristalle, Legierungen, Dünger, Androiden
    { 0, 1, 3, 12, 15 },    -- Ard’ore      Kohlenhydrate, Proteine, Pflanzenfasern, Medizin, Dünger
    { 0, 7, 12, 13, 15 },   -- Badic’aul    Kohlenhydrate, Legierungen, Medizin, Chemikalien, Dünger
    -- Hive-AC3
    { 8, 13, 21, 22, 23 },  -- Pachaung     Maschinen, Chemikalien, Luxusartikel, Androiden, Drogen
    { 8, 10, 11, 13, 18 },  -- Pyidaung     Maschinen, Computer, Schiffstechnik, Chemikalien, Isotope
    { 2, 5, 20, 21, 22 },   -- Gaungbwa     Lebensformen, Edelmetalle, Videospiele, Luxusartikel, Androiden
    { 9, 12, 13, 15, 20 },  -- Laikuku      Elekronik, Medizin, Chemikalien, Dünger, Videospiele
    { 6, 8, 12, 14, 15 },   -- Zajatpyu     Kristalle, Maschinen, Medizin, Spirituosen, Dünger
    { 4, 9, 16, 17, 18 },   -- Aingya       Metalle, Elekronik, Energiezellen, Brennstäbe, Isotope
    { 0, 1, 2, 5, 18 },     -- Hulaung      Kohlenhydrate, Proteine, Lebensformen, Edelmetalle, Isotope
    { 4, 9, 10, 11, 20 },   -- Mingin       Metalle, Elekronik, Computer, Schiffstechnik, Videospiele
    { 0, 9, 10, 11, 23 },   -- Tamaung      Kohlenhydrate, Elekronik, Computer, Schiffstechnik, Drogen
    { 0, 1, 2, 7, 14 },     -- Inwaing      Kohlenhydrate, Proteine, Lebensformen, Legierungen, Spirituosen
    { 0, 1, 2, 3, 15 },     -- Sinkwe       Kohlenhydrate, Proteine, Lebensformen, Pflanzenfasern, Dünger
    { 4, 9, 10, 11, 13 },   -- Honnaing     Metalle, Elekronik, Computer, Schiffstechnik, Chemikalien
    { 4, 5, 6, 7, 19 },     -- Shwege       Metalle, Edelmetalle, Kristalle, Legierungen, Supraleiter
    { 7, 12, 21, 22, 23 },  -- Tinmaung     Legierungen, Medizin, Luxusartikel, Androiden, Drogen
    { 0, 4, 5, 7, 14 },     -- Kinzan       Kohlenhydrate, Metalle, Edelmetalle, Legierungen, Spirituosen
    { 5, 14, 16, 17, 18 },  -- Haiken       Edelmetalle, Spirituosen, Energiezellen, Brennstäbe, Isotope
    { 3, 6, 16, 17, 19 },   -- Natkyigon    Pflanzenfasern, Kristalle, Energiezellen, Brennstäbe, Supraleiter
    { 1, 19, 21, 22, 23 },  -- Ascarong     Proteine, Supraleiter, Luxusartikel, Androiden, Drogen
    { 3, 16, 17, 19, 20 },  -- Wakkai       Pflanzenfasern, Energiezellen, Brennstäbe, Supraleiter, Videospiele
    -- Hive-F17
    { 3, 9, 20, 22, 23 },   -- Uyin         Pflanzenfasern, Elekronik, Videospiele, Androiden, Drogen
    { 4, 5, 6, 7, 14 },     -- Lakai        Metalle, Edelmetalle, Kristalle, Legierungen, Spirituosen
    { 0, 2, 3, 4, 23 },     -- Yagyat       Kohlenhydrate, Lebensformen, Pflanzenfasern, Metalle, Drogen
    { 0, 2, 8, 9, 11 },     -- Sinbyuchi    Kohlenhydrate, Lebensformen, Maschinen, Elekronik, Schiffstechnik
    { 6, 7, 12, 13, 15 },   -- Zanabok      Kristalle, Legierungen, Medizin, Chemikalien, Dünger
    { 8, 9, 11, 19, 20 },   -- Kujung       Maschinen, Elekronik, Schiffstechnik, Supraleiter, Videospiele
    { 1, 2, 3, 16, 23 },    -- Kindat       Proteine, Lebensformen, Pflanzenfasern, Energiezellen, Drogen
    { 5, 10, 20, 21, 22 },  -- Wegyaung     Edelmetalle, Computer, Videospiele, Luxusartikel, Androiden
    { 8, 9, 11, 13, 19 },   -- Songon       Maschinen, Elekronik, Schiffstechnik, Chemikalien, Supraleiter
    { 0, 8, 16, 17, 18 },   -- Yalagaung    Kohlenhydrate, Maschinen, Energiezellen, Brennstäbe, Isotope
    { 1, 12, 17, 18, 19 },  -- Rankse       Proteine, Medizin, Brennstäbe, Isotope, Supraleiter
    { 4, 11, 16, 17, 18 },  -- Changrang    Metalle, Schiffstechnik, Energiezellen, Brennstäbe, Isotope
    { 10, 13, 14, 15, 21 }, -- Ngobin       Computer, Chemikalien, Spirituosen, Dünger, Luxusartikel
    -- Hive-CU7
    { 10, 11, 12, 13, 14 }, -- Sainolin     Computer, Schiffstechnik, Medizin, Chemikalien, Spirituosen
    { 1, 2, 3, 9, 11 },     -- Wetluaing    Proteine, Lebensformen, Pflanzenfasern, Elekronik, Schiffstechnik
    { 6, 13, 14, 15, 23 },  -- Kandaya      Kristalle, Chemikalien, Spirituosen, Dünger, Drogen
    { 0, 1, 3, 5, 6 },      -- Myaunggon    Kohlenhydrate, Proteine, Pflanzenfasern, Edelmetalle, Kristalle
    { 2, 4, 20, 22, 23 },   -- Ringhku      Lebensformen, Metalle, Videospiele, Androiden, Drogen
    { 4, 8, 10, 11, 23 },   -- Molin        Metalle, Maschinen, Computer, Schiffstechnik, Drogen
    { 0, 17, 18, 19, 22 },  -- Kindaung     Kohlenhydrate, Brennstäbe, Isotope, Supraleiter, Androiden
    { 5, 7, 16, 18, 19 },   -- Ingynbin     Edelmetalle, Legierungen, Energiezellen, Isotope, Supraleiter
    { 10, 12, 14, 15, 16 }, -- Wadan        Computer, Medizin, Spirituosen, Dünger, Energiezellen
    { 0, 4, 6, 7, 20 },     -- Mayinlon     Kohlenhydrate, Metalle, Kristalle, Legierungen, Videospiele
    { 8, 12, 13, 15, 17 },  -- Lewingon     Maschinen, Medizin, Chemikalien, Dünger, Brennstäbe
    { 5, 6, 7, 9, 12 },     -- Kindaw       Edelmetalle, Kristalle, Legierungen, Elekronik, Medizin
    { 14, 17, 18, 19, 21 }, -- Aingdama     Spirituosen, Brennstäbe, Isotope, Supraleiter, Luxusartikel
    { 8, 9, 10, 16, 21 },   -- Kinmin       Maschinen, Elekronik, Computer, Energiezellen, Luxusartikel
    -- Hive-B52
    { 10, 11, 12, 13, 14 }, -- Ngakin       Computer, Schiffstechnik, Medizin, Chemikalien, Spirituosen
    { 1, 2, 3, 4, 9 },      -- Shanzeik     Proteine, Lebensformen, Pflanzenfasern, Metalle, Elekronik
    { 15, 16, 17, 18, 23 }, -- Maleindon    Dünger, Energiezellen, Brennstäbe, Isotope, Drogen
    { 0, 5, 6, 7, 8 },      -- Minshwe      Kohlenhydrate, Edelmetalle, Kristalle, Legierungen, Maschinen
    -- Hive-DC
    { 0, 1, 2, 4, 14 },     -- Chanthagon   Kohlenhydrate, Proteine, Lebensformen, Metalle, Spirituosen
    { 4, 5, 7, 13, 15 },    -- Chaing       Metalle, Edelmetalle, Legierungen, Chemikalien, Dünger
    { 17, 18, 19, 20, 21 }, -- Thidaya      Brennstäbe, Isotope, Supraleiter, Videospiele, Luxusartikel
    { 8, 15, 21, 22, 23 },  -- Pindon       Maschinen, Dünger, Luxusartikel, Androiden, Drogen
    { 5, 6, 7, 12, 13 },    -- Tegyigon     Edelmetalle, Kristalle, Legierungen, Medizin, Chemikalien
    { 1, 17, 20, 7, 22 },   -- Pegin        Proteine, Brennstäbe, Videospiele, Legierungen, Androiden
    { 1, 2, 3, 11, 19 },    -- Segin        Proteine, Lebensformen, Pflanzenfasern, Schiffstechnik, Supraleiter
    { 6, 9, 12, 14, 15 },   -- Sibingwe     Kristalle, Elekronik, Medizin, Spirituosen, Dünger
    { 4, 5, 6, 10, 21 },    -- Atet         Metalle, Edelmetalle, Kristalle, Computer, Luxusartikel
    { 0, 9, 20, 21, 22 },   -- Ekyigon      Kohlenhydrate, Elekronik, Videospiele, Luxusartikel, Androiden
    { 8, 10, 11, 16, 23 },  -- Mepok        Maschinen, Computer, Schiffstechnik, Energiezellen, Drogen
    { 4, 6, 7, 9, 12 },     -- Sagon        Metalle, Kristalle, Legierungen, Elekronik, Medizin
    { 1, 17, 20, 22, 23 },  -- Beinn        Proteine, Brennstäbe, Videospiele, Androiden, Drogen
    { 3, 14, 16, 18, 19 },  -- Magyibok     Pflanzenfasern, Spirituosen, Energiezellen, Isotope, Supraleiter
    { 10, 11, 16, 18, 19 }, -- Sagagon      Computer, Schiffstechnik, Energiezellen, Isotope, Supraleiter
    { 0, 2, 3, 17, 18 },    -- Yama         Kohlenhydrate, Lebensformen, Pflanzenfasern, Brennstäbe, Isotope
    -- Hive-ET9
    { 1, 2, 5, 6, 7 },      -- Nepaling     Proteine, Lebensformen, Edelmetalle, Kristalle, Legierungen
    { 4, 8, 9, 11, 13 },    -- Letpan       Metalle, Maschinen, Elekronik, Schiffstechnik, Chemikalien
    { 2, 10, 11, 14, 20 },  -- Kamaing      Lebensformen, Computer, Schiffstechnik, Spirituosen, Videospiele
    { 15, 18, 21, 22, 23 }, -- Bonchaung    Dünger, Isotope, Luxusartikel, Androiden, Drogen
    { 3, 12, 16, 17, 19 },  -- Chondrha     Pflanzenfasern, Medizin, Energiezellen, Brennstäbe, Supraleiter
    { 0, 1, 2, 15, 21 },    -- Khopyin      Kohlenhydrate, Proteine, Lebensformen, Dünger, Luxusartikel
    { 0, 5, 6, 7, 18 },     -- Katpanbok    Kohlenhydrate, Edelmetalle, Kristalle, Legierungen, Isotope
    { 10, 14, 20, 22, 23 }, -- Binga        Computer, Spirituosen, Videospiele, Androiden, Drogen
    -- Hive-G8
    { 0, 1, 2, 12, 15 },    -- Pantok       Kohlenhydrate, Proteine, Lebensformen, Medizin, Dünger
    { 9, 11, 21, 22, 23 },  -- Pagandi      Elekronik, Schiffstechnik, Luxusartikel, Androiden, Drogen
    { 0, 1, 3, 5, 17 },     -- Daingnat     Kohlenhydrate, Proteine, Pflanzenfasern, Edelmetalle, Brennstäbe
    { 0, 12, 14, 15, 19 },  -- Lethagon     Kohlenhydrate, Medizin, Spirituosen, Dünger, Supraleiter
    { 10, 16, 17, 18, 20 }, -- Gamnim       Computer, Energiezellen, Brennstäbe, Isotope, Videospiele
    { 5, 18, 20, 21, 23 },  -- Shwebangon   Edelmetalle, Isotope, Videospiele, Luxusartikel, Drogen
    { 9, 10, 11, 13, 22 },  -- Bao          Elekronik, Computer, Schiffstechnik, Chemikalien, Androiden
    { 4, 6, 7, 8, 13 },     -- Obingon      Metalle, Kristalle, Legierungen, Maschinen, Chemikalien
    { 4, 5, 6, 7, 16 },     -- Thabyedaw    Metalle, Edelmetalle, Kristalle, Legierungen, Energiezellen
    { 1, 2, 3, 14, 19 },    -- Yedaw        Proteine, Lebensformen, Pflanzenfasern, Spirituosen, Supraleiter
    -- Communa
    { 3, 5, 12, 13, 14 },   -- Bailebeag    Pflanzenfasern, Edelmetalle, Medizin, Chemikalien, Spirituosen
    { 0, 16, 20, 21, 23 },  -- Achintraid   Kohlenhydrate, Energiezellen, Videospiele, Luxusartikel, Drogen
    { 7, 8, 12, 13, 15 },   -- Clachtoll    Legierungen, Maschinen, Medizin, Chemikalien, Dünger
    { 4, 6, 7, 10, 21 },    -- Inchlaggan   Metalle, Kristalle, Legierungen, Computer, Luxusartikel
    { 12, 14, 15, 17, 22 }, -- Dalmigavie   Medizin, Spirituosen, Dünger, Brennstäbe, Androiden
    { 9, 12, 17, 18, 19 },  -- Ramasaig     Elekronik, Medizin, Brennstäbe, Isotope, Supraleiter
    { 3, 6, 8, 9, 10 },     -- Faebait      Pflanzenfasern, Kristalle, Maschinen, Elekronik, Computer
    { 1, 2, 3, 4, 15 },     -- Aberloch     Proteine, Lebensformen, Pflanzenfasern, Metalle, Dünger
    { 0, 1, 2, 12, 16 },    -- Eilanreach   Kohlenhydrate, Proteine, Lebensformen, Medizin, Energiezellen
    { 7, 11, 20, 21, 23 },  -- Aberchald    Legierungen, Schiffstechnik, Videospiele, Luxusartikel, Drogen
    { 9, 17, 18, 19, 22 },  -- Pitcalnie    Elekronik, Brennstäbe, Isotope, Supraleiter, Androiden
    { 1, 18, 21, 22, 23 },  -- Ormiscaig    Proteine, Isotope, Luxusartikel, Androiden, Drogen
    { 4, 8, 10, 11, 18 },   -- Glaschoil    Metalle, Maschinen, Computer, Schiffstechnik, Isotope
    { 5, 6, 7, 13, 19 },    -- Cuidrach     Edelmetalle, Kristalle, Legierungen, Chemikalien, Supraleiter
    { 11, 15, 16, 17, 19 }, -- Keodale      Schiffstechnik, Dünger, Energiezellen, Brennstäbe, Supraleiter
    { 5, 8, 9, 10, 20 },    -- Ardarroch    Edelmetalle, Maschinen, Elekronik, Computer, Videospiele
    { 0, 1, 2, 11, 16 },    -- Fearnbeg     Kohlenhydrate, Proteine, Lebensformen, Schiffstechnik, Energiezellen
    { 0, 2, 3, 6, 14 },     -- Todhair      Kohlenhydrate, Lebensformen, Pflanzenfasern, Kristalle, Spirituosen
    -- Hyma
    { 3, 5, 12, 13, 14 },   -- Laggan       Pflanzenfasern, Edelmetalle, Medizin, Chemikalien, Spirituosen
    { 0, 16, 20, 21, 23 },  -- Dalchalm     Kohlenhydrate, Energiezellen, Videospiele, Luxusartikel, Drogen
    { 8, 9, 11, 15, 18 },   -- Clayock      Maschinen, Elekronik, Schiffstechnik, Dünger, Isotope
    { 4, 6, 7, 10, 17 },    -- Dorusduain   Metalle, Kristalle, Legierungen, Computer, Brennstäbe
    -- Hive-B52
    { 24, 24, 24, 24, 24 }, -- Kajudeng     Keine Waren
    { 24, 24, 24, 24, 24 }, -- Metojang     Keine Waren
    -- Raptor Delta
    { 24, 24, 24, 24, 24 }  -- Permakin     Keine Waren
}

-- Kommunikation
BLOCK_DIALOG	= { BlockDlg = true }
DIALOG_START	= -1
DIALOG_END	= -2
COMM_START	= 0	-- Rückgabewert in "CommEnd", wenn eine NPC-Mitteilung als "Dialog"-Event beginnt
NO_MESSAGE	= -1	-- Rückgabewert von NComm.AddMessage: eine Nachricht konnte nicht abgespielt werden

-- Ausrüstung und Energiesysteme
EQUIPMENT_ENERGY_COLLECTOR	= 9
EQUIPMENT_ENERGYFLUX		= 10
EQUIPMENT_SHIELDFLUX		= 11
EQUIPMENT_LANDING_COMPUTER	= 12
EQUIPMENT_TRADE_COMPUTER	= 13
EQUIPMENT_REPAIRBOT		= 14
EQUIPMENT_PLASMA_BOOSTER	= 15
EQUIPMENT_SHIELD_BOOSTER	= 16
EQUIPMENT_AFTERBURNER_BOOSTER	= 17
EQUIPMENT_GRAVITON		= 18
EQUIPMENT_ACTUATOR_REFILL	= 19

EQUIPMENT_NAME = { -- Liefert den Namen eines Ausrüstungsgegenstands, Index ist dessen Typ
    [0] =
    "Shieldgenerator";		-- Energieschild	EQUIPMENT_SHIELD_GENERATOR	(Energiesysteme)
    "Afterburner",		-- Nachbrenner		EQUIPMENT_AFTERBURNER		(Energiesysteme)
    "Hyperdrive",		-- Feldantrieb		EQUIPMENT_HYPERDRIVE		(Energiesysteme)
    "Scanner",			-- Frachtscanner	EQUIPMENT_SCANNER		(Energiesysteme)
    "Jammer",			-- Scanner-Jammer	EQUIPMENT_SCANNER_JAMMER	(Ausrüstung)
    "Generator",		-- Generator		EQUIPMENT_GENERATOR		(Energiesysteme)
    "Capacitor",		-- Kondensator		EQUIPMENT_CAPACITOR		(Energiesysteme)
    "Cargocomputer",		-- Frachtcomputer	EQUIPMENT_CARGO_COMPUTER	(Energiesysteme)
    "Orecollector",		-- Erzsammler		EQUIPMENT_ORE_COLLECTOR		(Ausrüstung)
    "Energycollector",		-- Energiesammler	EQUIPMENT_ENERGY_COLLECTOR	(Ausrüstung)
    "Energyflux",		-- Energieflux		EQUIPMENT_ENERGYFLUX		(Ausrüstung)
    "Shieldflux",		-- Schildflux		EQUIPMENT_SHIELDFLUX		(Ausrüstung)
    "Landingcomputer",		-- Landecomputer	EQUIPMENT_LANDING_COMPUTER	(Ausrüstung)
    "Tradecomputer",		-- Handelscomputer	EQUIPMENT_TRADE_COMPUTER	(Ausrüstung)
    "Repairbot",		-- Reparaturbot		EQUIPMENT_REPAIRBOT		(Ausrüstung)
    "Plasmabooster",		-- Plasma-Booster	EQUIPMENT_PLASMA_BOOSTER	(Ausrüstung)
    "Shieldbooster",		-- Schild-Booster	EQUIPMENT_SHIELD_BOOSTER	(Ausrüstung)
    "Afterburnerbooster",	-- Nachbrenner-Booster	EQUIPMENT_AFTERBURNER_BOOSTER	(Ausrüstung)
    "Graviton",			-- Graviton-Schub	EQUIPMENT_GRAVITON		(Ausrüstung)
    "Actuatorrefill"		-- Aktuator-Refill	EQUIPMENT_ACTUATOR_REFILL	(Ausrüstung)
}

EQUIPMENT_TYPE = { -- Liefert den numerischen Typ des namentlich angegebenen Ausrüstungsgegenstands
    Shieldgenerator	= 0,	-- Energieschild	EQUIPMENT_SHIELD_GENERATOR	(Energiesysteme)
    Afterburner		= 1,	-- Nachbrenner		EQUIPMENT_AFTERBURNER		(Energiesysteme)
    Hyperdrive		= 2,	-- Feldantrieb		EQUIPMENT_HYPERDRIVE		(Energiesysteme)
    Scanner		= 3,	-- Frachtscanner	EQUIPMENT_SCANNER		(Energiesysteme)
    Jammer		= 4,	-- Scanner-Jammer	EQUIPMENT_SCANNER_JAMMER	(Ausrüstung)
    Generator		= 5,	-- Generator		EQUIPMENT_GENERATOR		(Energiesysteme)
    Capacitor		= 6,	-- Kondensator		EQUIPMENT_CAPACITOR		(Energiesysteme)
    Cargocomputer	= 7,	-- Frachtcomputer	EQUIPMENT_CARGO_COMPUTER	(Energiesysteme)
    Orecollector	= 8,	-- Erzsammler		EQUIPMENT_ORE_COLLECTOR		(Ausrüstung)
    Energycollector	= 9,	-- Energiesammler	EQUIPMENT_ENERGY_COLLECTOR	(Ausrüstung)
    Energyflux		= 10,	-- Energieflux		EQUIPMENT_ENERGYFLUX		(Ausrüstung)
    Shieldflux		= 11,	-- Schildflux		EQUIPMENT_SHIELDFLUX		(Ausrüstung)
    Landingcomputer	= 12,	-- Landecomputer	EQUIPMENT_LANDING_COMPUTER	(Ausrüstung)
    Tradecomputer	= 13,	-- Handelscomputer	EQUIPMENT_TRADE_COMPUTER	(Ausrüstung)
    Repairbot		= 14,	-- Reparaturbot		EQUIPMENT_REPAIRBOT		(Ausrüstung)
    Plasmabooster	= 15,	-- Plasma-Booster	EQUIPMENT_PLASMA_BOOSTER	(Ausrüstung)
    Shieldbooster	= 16,	-- Schild-Booster	EQUIPMENT_SHIELD_BOOSTER	(Ausrüstung)
    Afterburnerbooster	= 17,	-- Nachbrenner-Booster	EQUIPMENT_AFTERBURNER_BOOSTER	(Ausrüstung)
    Graviton		= 18,	-- Graviton-Schub	EQUIPMENT_GRAVITON		(Ausrüstung)
    Actuatorrefill	= 19	-- Aktuator-Refill	EQUIPMENT_ACTUATOR_REFILL	(Ausrüstung)
}

EQUIPMENT_LEVEL = { -- Liefert den Ausrüstungslevel (1..10), Index ist der Schiffslevel von 0 bis 30
        -- 0         5        10        15        20         25             30	  -- Schiffslevel
    Weapon = { [0]=1;2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,9,10,10,10,10,10,10 }, -- Waffen
    Energy = { [0]=1;1,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,10,10,10,10 }, -- Energie
    Device = { [0]=1;1,1,2,2,3,3,3,4,4,4,5,5,5,6,6,7,7,7,8,8,8,9,9,9,10,10,10,10,10,10 }  -- Ausrüstung
}

-- Wing-Aktionen					Type#	Kommentar
INAKTIV		= { Type = AI_ACTION_INAKTIV }		-- 0
STATISCH	= { Type = AI_ACTION_STATISCH }		-- 1
WARTEN		= { Type = AI_ACTION_WARTEN }		-- 2
ANGRIFF		= { Type = AI_ACTION_ANGRIFF }		-- 3
CONTANGRIFF	= { Type = AI_ACTION_CONTANGRIFF }	-- 4
LANDEN		= { Type = AI_ACTION_LANDEN }		-- 9	Kein Hangar angegeben -> Standardaktion
KREISEN		= { Type = AI_ACTION_KREISEN }		-- 10
ABWERFEN	= { Type = AI_ACTION_ABWERFEN }		-- 15	Alle Container werden abgeworfen
HYPERRAUM	= { Type = AI_ACTION_HYPERRAUM }	-- 16
BOSSKREISEN	= { Type = AI_ACTION_BOSSKREISEN }	-- 17
SOFORTSPRUNG	= { Type = AI_ACTION_SOFORTSPRUNG }	-- 25
SOFORTLANDEN	= { Type = AI_ACTION_SOFORTLANDEN }	-- 26	Kein Hangar angegeben -> Standardaktion
GETLIST		= { Type = AI_ACTION_GETLIST }		-- 33
STANDARD	= { Type = AI_ACTION_STANDARD }		-- 34

-- Wing-Formationen für "NWing.SetFormation" ( Werte = Index für die WingInfo.ini )
-- WICHTIGER HINWEIS: Mehr als 32 Formationen (0..31) dürfen nicht definiert werden,
-- das bringt viele der vorhergehenden durcheinander und es wird meistens nur eine
-- Kette (FORMATION_CHAIN) gebildet!
FORMATION_DELTA		= 0
FORMATION_DELTA_2	= 1
FORMATION_V_SHAPE	= 2
FORMATION_ESCORT	= 3
FORMATION_CHAIN		= 4
FORMATION_SKAA		= 5
FORMATION_LINE_RIGHT	= 6
FORMATION_PLAYER_WING	= 7
FORMATION_SKAA_10	= 8
FORMATION_SKAA_9	= 9
FORMATION_SKAA_8	= 10
FORMATION_SKAA_7	= 11
FORMATION_SKAA_6	= 12
FORMATION_SKAA_5	= 13
FORMATION_SKAA_4	= 14
FORMATION_SKAA_3	= 15
FORMATION_SKAA_2	= 16
FORMATION_SKAA_1	= 17
FORMATION_CRUISER	= 18
FORMATION_WEAPONBASE	= 19
FORMATION_CLUSTER_GROUP	= 20
FORMATION_PLAYER_NPC	= 21
FORMATION_SUPERFRACHTER	= 22
-- Selbst erstellte Formationen:
FORMATION_DELTA_INV	= 23	-- Wie DELTA, aber invertiert. Boss fliegt hinten.
FORMATION_ARROW_10	= 24	-- Pfeil
FORMATION_ARROW_2_10	= 25	-- Doppelpfeil
FORMATION_ARROW_3D_10	= 26	-- Pfeil 3D
FORMATION_DIAMOND_10	= 27	-- Raute, Boss im Zentrum
FORMATION_CIRCLE_8	= 28	-- Kreis, Boss im Zentrum
FORMATION_PYRAMID	= 29	-- Pyramide
FORMATION_LINE_CENTER	= 30	-- Gerade Linie auf der X-Achse, Leader im Zentrum.
FORMATION_CRUISER_ESCORT= 31	-- Flankenschutz für Kreuzer

-- Objekte und Orbiter
NO_ARTEFACT	= 655359	-- Handle von NObject.GetArtefact, wenn kein Artefakt existiert
NO_GANG		= 65535		-- GangId, wenn keine Gang im System existiert
NO_HIDEOUT_SHIP	= 327679	-- Schiffshandle von NShip.GetHideOut, wenn kein Piratenversteck existiert
NO_HIDEOUT_WING	= 720895	-- Winghandle von NShip.GetHideOut, wenn kein Piratenversteck existiert
NO_OBJECT	= 2147483647	-- Objekt existiert nicht oder ungültiger Handlewert
NO_CLUSTER	= -2031617	-- ClusterId für ungültiges Clusterhandle (Handle = 458751)
NO_SYSTEM	= 65535		-- SystemId, wenn kein System in der Nav-Karte angewählt wurde
NO_SHIP_ID	= 327679	-- Schiffshandle eines nicht existenten Wingman (wie NO_HIDEOUT_SHIP)
NO_WING_ID	= 720895	-- WingId eines Schiffs ohne Wing (auch die Darkstar One)
WRECK_0		= 3342335	-- Basis von Zählern für Wrack- (nur NShip.CreateWreck!) und Ringhandles
WRECK_1		= 3342336	-- Handle des ersten Wracks oder Rings im System
WRECK_2		= 3342337	-- Handle des zweiten Wracks oder Rings im System
WRECK_3		= 3342338	-- :
WRECK_4		= 3342339	-- :
WRECK_5		= 3342340	-- :
WRECK_6		= 3342341	-- :
WRECK_7		= 3342342	-- :
WRECK_8		= 3342343	-- :
WRECK_9		= 3342344	-- :
WRECK_10	= 3342345	-- Handle des zehnten Wracks oder Rings im System

OBJTYPE_DECORATION	= 11	-- Kreuzer- und Stationswracks (nur statisch in Planets.ini definierte!)
OBJTYPE_ANOMALIE	= 12	-- Anomalie
OBJTYPE_DISPLAY		= 13	-- Werbetafel
OBJTYPE_BLACKHOLE	= 14	-- Schwarzes Loch
OBJTYPE_BASESHIP	= 15	-- Piratenbasis, NObject.GetPosition liefert aber {0,0,0},
                --   daher NStarSystem.GetPirateField vorher ausführen!
ORBITART_SONNE		= 1	-- Fehlt im System, obwohl dokumentiert
ORBITART_PLANET_TC	= 2	-- Technikplanet	"
ORBITART_PLANET_BG	= 3	-- Agrarplanet		"
ORBITART_PLANET_GR	= 4	-- Gasriese		"
ORBITART_MOND		= 6	-- Mond			"
ORBITART_KOMET		= 9	-- Komet		"
ORBITART_METEORE	= 10	-- Meteoritenfeld	"
ORBITART_DECORATION	= 11	-- Schiffswracks	"
ORBITART_DISPLAY	= 13	-- Werbetafel

BLACKHOLE_NAME = { -- Liefert den Namen eines schwarzen Lochs, Index ist die SystemId
     [21] = "IDL_BLACKHOLE_MONO",	-- Tasakane	"Schwarzes Loch Monocerotis"
    [128] = "IDL_BLACKHOLE_URSA",	-- Zhusomol	"Schwarzes Loch Ursae Majoris"
    [129] = "IDL_BLACKHOLE_CYGX1",	-- Nostromo	"Schwarzes Loch Cygnus X-1"
    [130] = "IDL_BLACKHOLE_CYGNI",	-- Teirov	"Schwarzes Loch V404 Cygni"
    [131] = "IDL_BLACKHOLE_XTE",	-- Tamburg	"Schwarzes Loch XTE J1650-500"
    [132] = "IDL_BLACKHOLE_SAGI"	-- Lysmir	"Schwarzes Loch Sagittarii"
}

-- Spielerschiff
PLAYER_HULL	    = "Logic.PlayerShip.hullCondition"		-- Rumpfzustand
PLAYER_SHIELD_BACK  = "Logic.PlayerShip.shieldConditionBack"	-- Schildzustand hinten
PLAYER_SHIELD_FRONT = "Logic.PlayerShip.shieldConditionFront"	-- Schildzustand vorne
PLAYER_CREDITS	    = "Logic.Player.credits"		-- Kontostand des Spielers
PLAYER_HANGAR	    = "Logic.PlayerShip.hangar"		-- Station oder Kreuzer, wo der Spieler gelandet ist
PLAYER_KILLS	    = "Logic.Player.fragcounter"	-- Anzahl aller vom Spieler abgeschossenen Schiffe
PLAYER_LEVEL	    = "Logic.PlayerShip.level"		-- Erreichbarer Level mit gesammelten Artefakten
PLAYER_UPGRADES	    = "Logic.PlayerShip.usedUpgrades"	-- Tatsächlicher Schiffslevel
PLAYER_JUMP_DEST    = "Logic.PlayerShip.hyperJumpDest"	-- Sprungziel der DSO
PLAYER_SPEED	    = "Logic.PlayerShip.shipSpeed"	-- Aktuelle Geschwindigkeit
PLAYER_TARGET	    = "Logic.PlayerShip.selection"	-- Selektiertes Ziel
PLAYER_SHIP_ID	    = "Logic.PlayerShip.id"		-- Schiffshandle der DSO
PLAYER_WING_ID	    = "Logic.PlayerShip.wingId"		-- Winghandle der DSO, wenn sie in einem KI-Wing ist
PLAYER_AFTERBURNER_SPEED = { -- Geschwindigkeiten mit Nachbrenner abhängig vom Energielevel ( 1..10 )
    150.0, 160.0, 180.0, 200.0, 250.0, 300.0, 350.0, 400.0, 450.0, 500.0
}

-- Erzeugungsbereiche
POSDESCR_RESEARCH	= 6	-- Kurzform für POSDESCR_RESEARCHSTATION
POSDESCR_ANOMALIE	= 18	-- Kugel 1 Unit hinter einer Anomalie mit einem Radius von 0.5 Units
POSDESCR_METEORID	= 19	-- Kugel 1 Unit hinter dem Zentrum eines Meteoritenfelds mit 0.5 Units Radius
POSDESCR_PLANET		= 20	-- Halbkugel hinter einem Planeten 5 Units über der Oberfläche
POSDESCR_BLACKHOLE	= 21	-- Kugel 3 Units vor einem schwarzen Loch mit einem Radius von 2 Units
POSDESCR_HYPERGATE	= 22	-- Kugel 1 Unit vor dem Hyperraumtor mit einem Radius von 0,5 Units
POSDESCR_WELCOME2	= 23	-- Ring 0,1 Units vor dem Hangar der Handelsstation, Radius 0,15 Units
POSDESCR_ASTEROID2	= 24	-- Kugelschale um einen Asteroiden im Abstand von 1-3 Units vom Zentrum
POSDESCR_RESEARCH2	= 25	-- Kugelschale um eine Forschungsstation im Abstand von 1-3 Units vom Zentrum
POSDESCR_RESEARCHSTATION2 = 25	-- Langform für POSDESCR_RESEARCH2
POSDESCR_ANOMALIE2	= 26	-- Kugel um eine Anomalie mit einem Radius von 2 Units
POSDESCR_METEORID2	= 27	-- Kugelschale in einem Meteoritenfeld im Abstand von 0,5-2 Units vom Zentrum
POSDESCR_PLANET2	= 28	-- Kugelschale um einen Planeten 3-6 Units über der Oberfläche
POSDESCR_BLACKHOLE2	= 29	-- Kugelschale um ein schwarzes Loch im Abstand von 2-6 Units vom Zentrum
POSDESCR_HYPERGATE2	= 30	-- Kugelschale um ein Hyperraumtor im Abstand von 0,5-2 Units vom Zentrum
POSDESCR_OBJECT		= 31	-- Kugelschale um ein Objekt im Abstand von 0-3 Units von der Hüllkugel

-- Erzeugungsbereiche ohne Parameter für die Funktion "NVector.GetPos"
AREA_PLAYERSHIP		= { Area = POSDESCR_PLAYERSHIP }
AREA_INTERCEPTION	= { Area = POSDESCR_INTERCEPTION }
AREA_OFFSET		= { Area = POSDESCR_OFFSET }
AREA_ASTEROID		= { Area = POSDESCR_ASTEROID }
AREA_TRADESTATION1	= { Area = POSDESCR_TRADESTATION1 }
AREA_TRADESTATION2	= { Area = POSDESCR_TRADESTATION2 }
AREA_RESEARCHSTATION	= { Area = POSDESCR_RESEARCHSTATION }
AREA_WELCOME		= { Area = POSDESCR_WELCOME }
AREA_METEROIDS		= { Area = POSDESCR_METEROIDS }
AREA_ESCORT		= { Area = POSDESCR_ESCORT }
AREA_HYPERSPACE		= { Area = POSDESCR_HYPERSPACE }
AREA_HYPERSPACE_CRUISER	= { Area = POSDESCR_HYPERSPACE_CRUISER }
AREA_FIRST_PLANET	= { Area = POSDESCR_FIRST_PLANET }

-- Besetzte Piratensysteme und ihre regulären Regierungen
PIRATESYSTEM_GOVERNMENT = { -- Index ist die SystemId
     [19] = 3,	-- Ta		Anarchie
     [25] = 0,	-- Zuoria	Demokratie
     [39] = 4,	-- Witha	Konzern
     [41] = 2,	-- Sassudia	Staatenbund
     [62] = 4,	-- Eicete	Konzern
     [88] = 0,	-- Odia		Demokratie
     [89] = 4,	-- Biardorra	Konzern
    [132] = 2,	-- Lysmir	Staatenbund
    [137] = 2,	-- Mynok	Staatenbund
    [143] = 4,	-- Khimzan	Konzern
    [152] = 4,	-- Eletssk	Konzern
    [154] = 4,	-- Balasom	Konzern
    [164] = 5,	-- Zelenonezh	Monarchie
    [176] = 4,	-- Jegutna	Konzern
    [185] = 4,	-- Abanaul	Konzern
    [198] = 5,	-- Gallt'air	Monarchie
    [199] = 4,	-- Lon'ore	Konzern
    [206] = 0,	-- Wichita	Demokratie
    [209] = 4,	-- Tezutiak	Konzern
    [210] = 2,	-- Witeni	Staatenbund
    [224] = 4,	-- B'rochel	Konzern
    [227] = 4,	-- Bena'vie	Konzern
    [275] = 3,	-- Leirin'vie	Anarchie
    [282] = 1,	-- Clash'ore	Diktatur
    [285] = 4,	-- Rhe'ore	Konzern
    [289] = 4,	-- Altand'uin	Konzern
    [305] = 4,	-- Honnaing	Konzern
    [329] = 2,	-- Myaunggon	Staatenbund
    [337] = 4,	-- Kindaw	Konzern
    [340] = 0,	-- Ngakin	Demokratie
    [343] = 4,	-- Minshwe	Konzern
    [352] = 4,	-- Atet		Konzern
    [355] = 4,	-- Sagon	Konzern
    [360] = 4,	-- Nepaling	Konzern
    [361] = 4,	-- Letpan	Konzern
    [376] = 4,	-- Thabyedaw	Konzern
    [381] = 4,	-- Inchlaggan	Konzern
    [387] = 3,	-- Aberchald	Anarchie
    [399] = 4	-- Dorusduain	Konzern
}

-- Völker
NATION		= { [0] = "hum"; "mor", "rap", "oct", "arr", "thu" }	-- Rassenkürzel für die Akteure
NATION_CL	= { [0] = "HUM"; "MOR", "RAP", "OCT", "ARR", "THU" }	-- Rassenkürzel in Großbuchstaben
RACE_NAMES	= { [0] = "HUMAN"; "MORTOK", "RAPTOR", "OCTO", "ARRACK", "THUL" }
RACE_1704	= 7	-- Nicht vorhandene Rasse "1704"
RACE_CLUSTER	= -1	-- Automatische Rassenverteilung des aktuellen Clusters

-- Automatische Rassenverteilung in allen Clustern der Galaxis
-- Index der Tabellen ist die ClusterId, Index der Einträge die Rasse
RACE_ALLOCATION = { [0] =
    -- hum mor rap oct arr thu
    { [0] = 50; 25,  0, 25,  0,  0 };	-- Lalande
    { [0] = 50; 25,  0, 25,  0,  0 },	-- Barnard
    { [0] = 50; 25,  0, 25,  0,  0 },	-- Tau Ceti
    { [0] = 50; 25,  0, 25,  0,  0 },	-- Alpha Centauri
    { [0] = 25; 50,  0, 25,  0,  0 },	-- Grotok
    { [0] = 25; 50, 25,  0,  0,  0 },	-- Pertok
    { [0] = 25; 50, 25,  0,  0,  0 },	-- Stromok
    { [0] =  0; 60, 40,  0,  0,  0 },	-- Klatok
    { [0] =  0; 60, 40,  0,  0,  0 },	-- Humok
    { [0] =  0; 25, 50,  0,  0, 25 },	-- Raptor Alpha
    { [0] =  0; 25, 50,  0,  0, 25 },	-- Raptor Nova
    { [0] =  0; 25, 50,  0, 25,  0 },	-- Raptor Gamma
    { [0] =  0; 25, 50,  0, 25,  0 },	-- Raptor Delta
    { [0] =  0; 25, 50,  0, 25,  0 },	-- Raptor Epsilon
    { [0] = 25; 25,  0, 50,  0,  0 },	-- Sion'nach
    { [0] = 60;  0,  0, 40,  0,  0 },	-- Sirius
    { [0] = 25;  0,  0, 50, 25,  0 },	-- Madra'mor
    { [0] =  0;  0,  0, 60, 40,  0 },	-- Prea'chan
    { [0] = 50;  0, 25, 25,  0,  0 },	-- Ross 128
    { [0] =  0;  0,  0, 60, 40,  0 },	-- Bear'mor
    { [0] =  0;  0,  0, 60, 40,  0 },	-- Gab'har
    { [0] =  0;  0, 25, 25, 50,  0 },	-- Hive-AC3
    { [0] =  0;  0,  0, 30, 70,  0 },	-- Hive-F17
    { [0] =  0;  0, 25,  0, 50, 25 },	-- Hive-CU7
    { [0] =  0;  0, 40,  0, 60,  0 },	-- Hive-B52
    { [0] =  0;  0,  0,  0, 70, 30 },	-- Hive-DC
    { [0] =  0;  0, 25,  0, 50, 25 },	-- Hive-ET9
    { [0] =  0;  0,  0,  0, 60, 40 },	-- Hive-G8
    { [0] =  0;  0, 25,  0, 25, 50 },	-- Communa
    { [0] =  0;  0, 25,  0, 25, 50 }	-- Hyma
}

-- Format der Namen: RADARMAP_<Farbe>_<Spalte in Targetliste>
-- In der Spalte "Offiziell" der Targetliste sind ORBITER oben und SHIP unten gelistet
RADARMAP_NONE_HIDDEN	= 0	-- Unsichtbar, wird in der Targetliste nicht angezeigt
RADARMAP_GREEN_FRIEND	= 1	-- Freundliches Objekt
RADARMAP_GREEN_FRIEND2	= 2	-- Freundliches Objekt
RADARMAP_RED_ENEMY	= 3	-- Feindliches Objekt
RADARMAP_RED_ENEMY2	= 4	-- Feindliches Objekt
RADARMAP_BLUE_SHIP	= 5	-- Dynamische Objekte, dunkelblau in Targetliste, mittelblau im Raum
RADARMAP_BLUE_SHIP2	= 6	-- Dynamische Objekte, dunkelblau in Targetliste, mittelblau im Raum
RADARMAP_BLUE_SHIP3	= 7	-- Dynamische Objekte, dunkelblau in Targetliste, mittelblau im Raum
RADARMAP_BLUE_SHIP4	= 8	-- Dynamische Objekte, dunkelblau in Targetliste, mittelblau im Raum
RADARMAP_GREEN_FRIEND3	= 9	-- Freundliches Objekt
RADARMAP_GREEN_FRIEND4	= 10	-- Freundliches Objekt
RADARMAP_WHITE_HIDDEN	= 11	-- Neutral, wird in der Targetliste nicht angezeigt
RADARMAP_WHITE_SHIP	= 12	-- Neutral, offizielles Objekt in der Targetliste
RADARMAP_BLUE_ORBITER	= 13	-- Statische Objekte, mittelblau in Targetliste, dunkelblau im Raum
RADARMAP_BLUE_ORBITER2	= 14	-- Statische Objekte, mittelblau in Targetliste, dunkelblau im Raum
RADARMAP_WHITE_FRIEND	= 15	-- Neutral, freundliches Objekt in der Targetliste
RADARMAP_WHITE_FRIEND2	= 16	-- Neutral, freundliches Objekt in der Targetliste
RADARMAP_WHITE_HIDDEN2	= 17	-- Neutral, wird in der Targetliste nicht angezeigt
RADARMAP_STANDARD	= 18	-- Farbe ist vom Objekt abhängig

-- Scannstatus des Spielerschiffs
SCAN_ALLOWED		= 0	-- Schiff darf gescannt werden
SCAN_POLICE_NEAR	= 1	-- Polizei nähert sich zum Scannen
SCAN_POLICE_SUCCESS	= 2	-- Polizei hat das Schiff gescannt und wurde fündig
SCAN_POLICE_FAILED	= 3	-- Scan auf illegale Ware wurde erfolgreich gestört

-- Index für Schiffe in der StarShip.ini, referenziert die erste Zahl im Sektionsnamen
SPACE_SUPERFREIGHTER	= 5	-- Superfrachter (hier als SPACE_TRANSPORTER definiert)
SPACE_SKAADRONE		= 17	-- War im System ohne Wert definiert und gibt es in der StarShip.ini nicht

-- Index für Schiffe in der StarShip.ini, referenziert die zweite Zahl im Sektionsnamen
-- Schiffsmodelle: 'ObjIndex' in der Funktion "NWing.Define"

-- SPACE_HUNTER --------- Geleitschutz- und Kopfgeldjäger
SI_HUNTER_HUMAN		= 0	-- Terranerjäger mit einem Triebwerk
SI_HUNTER_MORTOK	= 1
SI_HUNTER_RAPTOR	= 2
SI_HUNTER_OCTO		= 3
SI_HUNTER_ARRACK	= 4
SI_HUNTER_THUL		= 5
SI_HUNTER2_HUMAN	= 6	-- Terranerjäger mit zwei Triebwerken, Schildstärke 1.5x HUNTER_HUMAN
SI_HUNTER_SKAA		= 7     -- S’kaa-Drohnen, einzeln oder im Schwarm
SI_HUNTER2_SKAA		= 8	-- Schutzschild leuchtet gleichmäßig blau wie beim Skaa-Mutterschiff (neu)
SI_HUNTER_1704		= 9	-- Wie HUNTER_HUMAN,  doppelte Hitpoints und Schildstärke (neu)
SI_HUNTER2_1704		= 10	-- Wie HUNTER2_HUMAN, doppelte Hitpoints und Schildstärke (neu)

-- SPACE_MILITARY ------- Militärjäger
SI_MILITARY_HUMAN	= 0
SI_MILITARY_MORTOK	= 1
SI_MILITARY_RAPTOR	= 2
SI_MILITARY_OCTO	= 3
SI_MILITARY_ARRACK	= 4
SI_MILITARY_THUL	= 5
SI_MILITARY_SKAA	= 6	-- Schutzschild leuchtet wie Diamanten, 8×Hitpoints, 2×Schildstärke (neu)

-- SPACE_POLICE --------- Polizeijäger
SI_POLICE_HUMAN		= 0
SI_POLICE_MORTOK	= 1
SI_POLICE_RAPTOR	= 2
SI_POLICE_OCTO		= 3
SI_POLICE_ARRACK	= 4
SI_POLICE_THUL		= 5
SI_POLICE_SKAA		= 6	-- Schutzschild leuchtet feurig auf, 8×Hitpoints, 2×Schildstärke (neu)

-- SPACE_PIRATE --------- Piratenjäger
SI_PIRATE_HUMAN		= 0	-- Terranerjäger mit einem Triebwerk
SI_PIRATE_MORTOK	= 1
SI_PIRATE_RAPTOR	= 2
SI_PIRATE_OCTO		= 3
SI_PIRATE_ARRACK	= 4
SI_PIRATE_THUL		= 5
SI_PIRATE2_HUMAN	= 6	-- Terranerjäger mit zwei Triebwerken
SI_PIRATE_SKAA		= 7	-- Schutzschild leuchtet feurig grün,   8×Hitpoints, 2×Schildstärke (neu)
SI_PIRATE2_SKAA		= 8	-- Schutzschild leuchtet feurig orange, 8×Hitpoints, 2×Schildstärke (neu)

-- SPACE_CRUISER -------- Kreuzer
SI_CRUISER2_HUMAN	= 0	-- CRUISER2 = klein
SI_CRUISER1_HUMAN	= 1	-- CRUISER1 = groß
SI_CRUISER2_MORTOK	= 2
SI_CRUISER1_MORTOK	= 3
SI_CRUISER1_RAPTOR	= 4
SI_CRUISER2_RAPTOR	= 5
SI_CRUISER2_OCTO	= 6
SI_CRUISER1_OCTO	= 7
SI_CRUISER2_ARRACK	= 8
SI_CRUISER1_ARRACK	= 9
SI_CRUISER2_THUL	= 10
SI_CRUISER1_THUL	= 11
SI_CRUISER2_SKAA	= 12	-- S’kaa Mutterschiff "klein"
SI_CRUISER1_SKAA	= 13	-- S’kaa Mutterschiff "groß" (neu in StarShip.ini)

-- SPACE_TRANSPORTER ---- Handelsfrachter
SI_TRADER_4X50T_HUMAN	= 0	-- 200t, für 4 Container á 50t
SI_TRADER_2X100T_HUMAN	= 1	-- 200t, für 2 Container á 100t
SI_TRADER_8X50T_HUMAN	= 2	-- 400t, für 8 Container á 50t
SI_TRADER_4X100T_HUMAN	= 3	-- 400t, für 4 Container á 100t
SI_TRADER_6X100T_HUMAN	= 4	-- 600t, für 6 Container á 100t
SI_TRADER_3X200T_HUMAN	= 5	-- 600t, für 3 Container á 200t

SI_TRADER_4X50T_MORTOK	= 6	-- 200t, für 4 Container á 50t
SI_TRADER_2X100T_MORTOK	= 7	-- 200t, für 2 Container á 100t
SI_TRADER_8X50T_MORTOK	= 8	-- 400t, für 8 Container á 50t
SI_TRADER_4X100T_MORTOK	= 9	-- 400t, für 4 Container á 100t
SI_TRADER_6X100T_MORTOK	= 10	-- 600t, für 6 Container á 100t
SI_TRADER_3X200T_MORTOK	= 11	-- 600t, für 3 Container á 200t

SI_TRADER_4X50T_RAPTOR	= 13	-- 200t, für 4 Container á 50t   -- Achtung, Wert ist nicht in Reihenfolge!
SI_TRADER_4X100T_RAPTOR	= 14	-- 400t, für 4 Container á 100t  -- Achtung, Wert ist nicht in Reihenfolge!
SI_TRADER_3X200T_RAPTOR	= 15	-- 600t, für 3 Container á 200t  -- Achtung, Wert ist nicht in Reihenfolge!

SI_TRADER_4X50T_OCTO	= 12	-- 200t, für 4 Container á 50t   -- Achtung, Wert ist nicht in Reihenfolge!
SI_TRADER_4X100T_OCTO	= 16	-- 400t, für 4 Container á 100t
SI_TRADER_3X200T_OCTO	= 17	-- 600t, für 3 Container á 200t

SI_TRADER_4X50T_ARRACK	= 18	-- 200t, für 4 Container á 50t
SI_TRADER_4X100T_ARRACK	= 19	-- 400t, für 4 Container á 100t
SI_TRADER_3X200T_ARRACK	= 20	-- 600t, für 3 Container á 200t

SI_TRADER_4X50T_THUL	= 21	-- 200t, für 4 Container á 50t
SI_TRADER_4X100T_THUL	= 22	-- 400t, für 4 Container á 100t
SI_TRADER_3X200T_THUL	= 23	-- 600t, für 3 Container á 200t

-- Superfrachter mit den Indicés der originalen StarShip.ini:
SI_SUPERTRADER_W_HUMAN	= 24	-- 9000t, Superfrachter für 45 Geheimdienstwaffen-Container
SI_SUPERTRADER_W_ARRACK	= 25	-- 8400t, Superfrachter für 42 Geheimdienstwaffen-Container
SI_SUPERTRADER_W_RAPTOR	= 26	-- 8000t, Superfrachter für 40 Geheimdienstwaffen-Container

-- Der StarShip.ini neu hinzugefügte Superfrachter:
SI_SUPERTRADER_S_HUMAN	= 24	-- 2250t, Superfrachter für 45 Container á 50t
SI_SUPERTRADER_M_HUMAN	= 25	-- 4500t, Superfrachter für 45 Container á 100t
SI_SUPERTRADER_L_HUMAN	= 26	-- 9000t, Superfrachter für 45 Container á 200t

SI_SUPERTRADER_S_ARRACK	= 27	-- 2100t, Superfrachter für 42 Container á 50t
SI_SUPERTRADER_M_ARRACK	= 28	-- 4200t, Superfrachter für 42 Container á 100t
SI_SUPERTRADER_L_ARRACK	= 29	-- 8400t, Superfrachter für 42 Container á 200t

SI_SUPERTRADER_S_RAPTOR	= 30	-- 2000t, Superfrachter für 40 Container á 50t
SI_SUPERTRADER_M_RAPTOR	= 31	-- 4000t, Superfrachter für 40 Container á 100t
SI_SUPERTRADER_L_RAPTOR	= 32	-- 8000t, Superfrachter für 40 Container á 200t

-- Der StarShip.ini neu hinzugefügte Geheimdienstwaffenfrachter:
SI_BOMBER_B2_HUMAN	= 33	--  400t, Frachter für 2 Geheimdienstwaffen-Container
SI_BOMBER_B3_HUMAN	= 34	--  600t, Frachter für 3 Geheimdienstwaffen-Container
SI_BOMBER_B4_HUMAN	= 35	--  800t, Frachter für 4 Geheimdienstwaffen-Container
SI_BOMBER_B6_HUMAN	= 36	-- 1200t, Frachter für 6 Geheimdienstwaffen-Container
SI_BOMBER_B8_HUMAN	= 37	-- 1600t, Frachter für 8 Geheimdienstwaffen-Container

SI_BOMBER_B2_MORTOK	= 38	--  400t, Frachter für 2 Geheimdienstwaffen-Container
SI_BOMBER_B3_MORTOK	= 39	--  600t, Frachter für 3 Geheimdienstwaffen-Container
SI_BOMBER_B4_MORTOK	= 40	--  800t, Frachter für 4 Geheimdienstwaffen-Container
SI_BOMBER_B6_MORTOK	= 41	-- 1200t, Frachter für 6 Geheimdienstwaffen-Container
SI_BOMBER_B8_MORTOK	= 42	-- 1600t, Frachter für 8 Geheimdienstwaffen-Container

SI_BOMBER_B3_RAPTOR	= 43	--  600t, Frachter für 3 Geheimdienstwaffen-Container
SI_BOMBER_B4_RAPTOR	= 44	--  800t, Frachter für 4 Geheimdienstwaffen-Container

SI_BOMBER_B3_OCTO	= 45	--  600t, Frachter für 3 Geheimdienstwaffen-Container
SI_BOMBER_B4_OCTO	= 46	--  800t, Frachter für 4 Geheimdienstwaffen-Container

SI_BOMBER_B3_ARRACK	= 47	--  600t, Frachter für 3 Geheimdienstwaffen-Container
SI_BOMBER_B4_ARRACK	= 48	--  800t, Frachter für 4 Geheimdienstwaffen-Container

SI_BOMBER_B3_THUL	= 49	--  600t, Frachter für 3 Geheimdienstwaffen-Container
SI_BOMBER_B4_THUL	= 50	--  800t, Frachter für 4 Geheimdienstwaffen-Container

-- Die originalen Superfrachter müssen immer am Ende der Handelsfrachter stehen:
SI_SUPERBOMBER_HUMAN	= 51	-- 9000t, Superfrachter für 45 Geheimdienstwaffen-Container
SI_SUPERBOMBER_ARRACK	= 52	-- 8400t, Superfrachter für 42 Geheimdienstwaffen-Container
SI_SUPERBOMBER_RAPTOR	= 53	-- 8000t, Superfrachter für 40 Geheimdienstwaffen-Container

-- SPACE_PIRATE_FREIGHTER Piratenfrachter
SI_PIRATE_4X50T_HUMAN	= 0	-- 200t, für 4 Container á 50t
SI_PIRATE_2X100T_HUMAN	= 1	-- 200t, für 2 Container á 100t
SI_PIRATE_8X50T_HUMAN	= 2	-- 400t, für 8 Container á 50t
SI_PIRATE_4X100T_HUMAN	= 3	-- 400t, für 4 Container á 100t
SI_PIRATE_6X100T_HUMAN	= 4	-- 600t, für 6 Container á 100t
SI_PIRATE_3X200T_HUMAN	= 5	-- 600t, für 3 Container á 200t

SI_PIRATE_4X50T_MORTOK	= 6	-- 200t, für 4 Container á 50t
SI_PIRATE_2X100T_MORTOK	= 7	-- 200t, für 2 Container á 100t
SI_PIRATE_8X50T_MORTOK	= 8	-- 400t, für 8 Container á 50t
SI_PIRATE_4X100T_MORTOK	= 9	-- 400t, für 4 Container á 100t
SI_PIRATE_6X100T_MORTOK	= 10	-- 600t, für 6 Container á 100t
SI_PIRATE_3X200T_MORTOK	= 11	-- 600t, für 3 Container á 200t

SI_PIRATE_4X50T_RAPTOR	= 12	-- 200t, für 4 Container á 50t
SI_PIRATE_4X100T_RAPTOR	= 13	-- 400t, für 4 Container á 100t
SI_PIRATE_3X200T_RAPTOR	= 14	-- 600t, für 3 Container á 200t

SI_PIRATE_4X50T_OCTO	= 15	-- 200t, für 4 Container á 50t
SI_PIRATE_4X100T_OCTO	= 16	-- 400t, für 4 Container á 100t
SI_PIRATE_3X200T_OCTO	= 17	-- 600t, für 3 Container á 200t

SI_PIRATE_4X50T_ARRACK	= 18	-- 200t, für 4 Container á 50t
SI_PIRATE_4X100T_ARRACK	= 19	-- 400t, für 4 Container á 100t
SI_PIRATE_3X200T_ARRACK	= 20	-- 600t, für 3 Container á 200t

SI_PIRATE_4X50T_THUL	= 21	-- 200t, für 4 Container á 50t
SI_PIRATE_4X100T_THUL	= 22	-- 400t, für 4 Container á 100t
SI_PIRATE_3X200T_THUL	= 23	-- 600t, für 3 Container á 200t

-- Der StarShip.ini neu hinzugefügte spezielle Piratenfrachter:
SI_PIRATE_2X50T_HUMAN	= 24	--  100t, für 2 Container á 50t
SI_PIRATE_3X50T_HUMAN	= 25	--  150t, für 3 Container á 50t
SI_PIRATE_6X50T_HUMAN	= 26	--  300t, für 6 Container á 50t
SI_PIRATE_3X100T_HUMAN	= 27	--  300t, für 3 Container á 100t
SI_PIRATE_2X200T_HUMAN	= 28	--  400t, für 2 Container á 200t
SI_PIRATE_8X100T_HUMAN	= 29	--  800t, für 8 Container á 100t
SI_PIRATE_4X200T_HUMAN	= 30	--  800t, für 4 Container á 200t
SI_PIRATE_6X200T_HUMAN	= 31	-- 1200t, für 6 Container á 200t
SI_PIRATE_8X200T_HUMAN	= 32	-- 1600t, für 8 Container á 200t

SI_PIRATE_2X50T_MORTOK	= 33	--  100t, für 2 Container á 50t
SI_PIRATE_3X50T_MORTOK	= 34	--  150t, für 3 Container á 50t
SI_PIRATE_6X50T_MORTOK	= 35	--  300t, für 6 Container á 50t
SI_PIRATE_3X100T_MORTOK	= 36	--  300t, für 3 Container á 100t
SI_PIRATE_2X200T_MORTOK	= 37	--  400t, für 2 Container á 200t
SI_PIRATE_8X100T_MORTOK	= 38	--  800t, für 8 Container á 100t
SI_PIRATE_4X200T_MORTOK	= 39	--  800t, für 4 Container á 200t
SI_PIRATE_6X200T_MORTOK	= 40	-- 1200t, für 6 Container á 200t
SI_PIRATE_8X200T_MORTOK	= 41	-- 1600t, für 8 Container á 200t

SI_PIRATE_3X50T_RAPTOR	= 42	--  150t, für 3 Container á 50t
SI_PIRATE_3X100T_RAPTOR	= 43	--  300t, für 3 Container á 100t
SI_PIRATE_4X200T_RAPTOR	= 44	--  800t, für 4 Container á 200t

SI_PIRATE_3X50T_OCTO	= 45	--  150t, für 3 Container á 50t
SI_PIRATE_3X100T_OCTO	= 46	--  300t, für 3 Container á 100t
SI_PIRATE_4X200T_OCTO	= 47	--  800t, für 4 Container á 200t

SI_PIRATE_3X50T_ARRACK	= 48	--  150t, für 3 Container á 50t
SI_PIRATE_3X100T_ARRACK	= 49	--  300t, für 3 Container á 100t
SI_PIRATE_4X200T_ARRACK	= 50	--  800t, für 4 Container á 200t

SI_PIRATE_3X50T_THUL	= 51	--  150t, für 3 Container á 50t
SI_PIRATE_3X100T_THUL	= 52	--  300t, für 3 Container á 100t
SI_PIRATE_4X200T_THUL	= 53	--  800t, für 4 Container á 200t

-- S'kaadrohnen als Piratenfrachter, theoretisch für Spezial-Container, Drohnen haben aber keine Docks
SI_PIRATE_WHITE_SKAA	= 54	-- Weiß-blauer Schutzschild (Hypergate-Effekt)
SI_PIRATE_RED_SKAA	= 55	-- Roter Schutzschild
SI_PIRATE_GREEN_SKAA	= 56	-- Grüner Schutzschild
SI_PIRATE_BLUE_SKAA	= 57	-- Blauer Schutzschild (Gravur)
SI_PIRATE_VIOLET_SKAA	= 58	-- Violetter Schutzschild
SI_PIRATE_RED2_SKAA	= 59	-- Roter Schutzschild (Thul-Animation)

-- SPACE_HIDEOUT -------- Piratenbasis mit 12 Geschütztürmen
SI_PIRATEBASE_HUMAN	= 0
SI_PIRATEBASE_MORTOK	= 1
SI_PIRATEBASE_RAPTOR	= 2
SI_PIRATEBASE_OCTO	= 3
SI_PIRATEBASE_ARRACK	= 4
SI_PIRATEBASE_THUL	= 5
SI_PIRATEBASE_SKAA	= 6	-- Keine sichtbaren Turrets, feuert mit S’kaadrill, 4-fache Hitpoints
SI_PIRATEBASE_1704	= 7	-- 16 Laserturrets, doppelte Hitpoints einer terranischen Piratenbasis

-- SPACE_WEAPONBASE ----- Waffenplattformen
SI_WEAPONBASE1_HUMAN	= 0	-- 1 Geschützturm
SI_WEAPONBASE2_HUMAN	= 1	-- 2 Geschütztürme
SI_WEAPONBASE1_MORTOK	= 2
SI_WEAPONBASE2_MORTOK	= 3
SI_WEAPONBASE1_RAPTOR	= 4
SI_WEAPONBASE2_RAPTOR	= 5
SI_WEAPONBASE1_OCTO	= 6
SI_WEAPONBASE2_OCTO	= 7
SI_WEAPONBASE1_ARRACK	= 8
SI_WEAPONBASE2_ARRACK	= 9
SI_WEAPONBASE1_THUL	= 10
SI_WEAPONBASE2_THUL	= 11
SI_WEAPONBASE1_SKAA	= 12	-- Keine sichtbaren Turrets, feuert S’kaadrill, 4-fache Hitpoints (2.4)
SI_WEAPONBASE2_SKAA	= 13	-- Keine sichtbaren Turrets, feuert S’kaadrill, 4-fache Hitpoints (9.6)
SI_WEAPONBASE1_1704	= 14	-- Laserturrets, doppelte Hitpoints einer terranischen Plattform 1 (1.2)
SI_WEAPONBASE2_1704	= 15	-- Laserturrets, doppelte Hitpoints einer terranischen Plattform 2 (4.8)

-- SPACE_SHIELDGEN ------ Schildgeneratoren
SI_GEN_CANYON		= 0	-- GENERATOR_KABRO	der Generator am Ende des Kabro-Canyons
SI_GEN_BLUE		= 1	-- GENERATOR_BRONIS_0	blauer Generator in der Waffenfabrik
SI_GEN_RED		= 2	-- GENERATOR_BRONIS_1	roter  Generator in der Waffenfabrik
SI_GEN_GREEN		= 3	-- GENERATOR_BRONIS_2	grüner Generator in der Waffenfabrik
SI_GEN_SKAA		= 4	-- GENERATOR_SKAA,	ein Generator im S’kaa-Tunnel
SI_GEN_SKAACORE		= 5	-- GENERATOR_SKAA_CORE	der Hauptreaktor des S’kaa-Mutterschiffs

-- SPACE_SKAASWARM ------ S’kaa-Schwarm
SI_SKAA			= 0

-- SPACE_STATION -------- Handelsstationen
SI_STATION_3DOCKS	= 0	-- Station mit 3 Frachterdocks
SI_STATION_4DOCKS	= 1	-- Station mit 4 Frachterdocks

-- SPACE_TAXI ----------- Shuttles
SI_TAXI_HUMAN		= 0
SI_TAXI_MORTOK		= 1
SI_TAXI_RAPTOR		= 2
SI_TAXI_OCTO		= 3
SI_TAXI_ARRACK		= 4
SI_TAXI_THUL		= 5
SI_TAXI_SKAA		= 6	-- Schutzschild leuchtet Artefakt-grün, 4×Hitpoints, 4×Schildstärke (neu)

-- SPACE_PLAYERTURRET --- Actionturrets (Flak)
SI_TURRET_HUMAN		= 0
SI_TURRET_MORTOK	= 1
SI_TURRET_RAPTOR	= 2
SI_TURRET_OCTO		= 3
SI_TURRET_ARRACK	= 4
SI_TURRET_THUL		= 5

-- SPACE_CARGODRONE ----- Frachtdrohne zur Be- und Entladung an den Frachterdocks
SI_CARGODRONE		= 0

-- SPACE_COMMSAT -------- Kommunikations-Satellit, optional mit 1 oder 2 Geschütztürmen
SI_SAT_HUMAN		= 0	-- Satelliten mit 2 Geschütztürmen
SI_SAT_MORTOK		= 1
SI_SAT_RAPTOR		= 2
SI_SAT_OCTO		= 3
SI_SAT_ARRACK		= 4
SI_SAT_THUL		= 5
SI_SAT_SKAA		= 6	-- Keine sichtbaren Turrets, feuert S’kaadrill, 4-fache Hitpoints (1.2)
SI_SAT_1704		= 7	-- Laserturrets, doppelte Hitpoints eines normalen Satelliten (0.6)

-- Schiffsklassen: 'ObjType' in der Funktion "NWing.Define"
ST_PASSENGER_SHUTTLE	= 21	-- Transportshuttle für Fahrgäste (Taxi)
ST_BASESHIP		= 22	-- Piratenbasis
ST_SUPERFREIGHTER	= 23	-- Superfrachter

-- Frachterindex nach Wingtyp, Anzahl der Containerplätze und Rasse des Frachters
TRADER_INDEX = {
    -- WingType
    [WINGTYPE_FREIGHTER50T] = {
        -- Anzahl Containerplätze
        [4] = {     -- 200t
            -- Rasse
            [RACE_HUMAN]  = SI_TRADER_4X50T_HUMAN,
            [RACE_MORTOK] = SI_TRADER_4X50T_MORTOK,
            [RACE_RAPTOR] = SI_TRADER_4X50T_RAPTOR,   -- Achtung, Wert ist nicht in Reihenfolge!
            [RACE_OCTO]   = SI_TRADER_4X50T_OCTO,     -- Achtung, Wert ist nicht in Reihenfolge!
            [RACE_ARRACK] = SI_TRADER_4X50T_ARRACK,
            [RACE_THUL]   = SI_TRADER_4X50T_THUL
        },
        [8] = {     -- 400t
            [RACE_HUMAN]  = SI_TRADER_8X50T_HUMAN,
            [RACE_MORTOK] = SI_TRADER_8X50T_MORTOK
        },
        [40] = {    -- 2000t
            [RACE_RAPTOR] = SI_SUPERTRADER_S_RAPTOR
        },
        [42] = {    -- 2100t
            [RACE_ARRACK] = SI_SUPERTRADER_S_ARRACK
        },
        [45] = {    -- 2250t
            [RACE_HUMAN]  = SI_SUPERTRADER_S_HUMAN
        }
    },

    [WINGTYPE_FREIGHTER100T] = {
        -- Anzahl Containerplätze
        [2] = {     -- 200t
            -- Rasse
            [RACE_HUMAN]  = SI_TRADER_2X100T_HUMAN,
            [RACE_MORTOK] = SI_TRADER_2X100T_MORTOK
        },
        [4] = {     -- 400t
            [RACE_HUMAN]  = SI_TRADER_4X100T_HUMAN,
            [RACE_MORTOK] = SI_TRADER_4X100T_MORTOK,
            [RACE_RAPTOR] = SI_TRADER_4X100T_RAPTOR,  -- Achtung, Wert ist nicht in Reihenfolge!
            [RACE_OCTO]   = SI_TRADER_4X100T_OCTO,
            [RACE_ARRACK] = SI_TRADER_4X100T_ARRACK,
            [RACE_THUL]   = SI_TRADER_4X100T_THUL
        },
        [6] = {     -- 600t
            [RACE_HUMAN]  = SI_TRADER_6X100T_HUMAN,
            [RACE_MORTOK] = SI_TRADER_6X100T_MORTOK
        },
        [40] = {    -- 4000t
            [RACE_RAPTOR] = SI_SUPERTRADER_M_RAPTOR
        },
        [42] = {    -- 4200t
            [RACE_ARRACK] = SI_SUPERTRADER_M_ARRACK
        },
        [45] = {    -- 4500t
            [RACE_HUMAN]  = SI_SUPERTRADER_M_HUMAN
        }
    },

    [WINGTYPE_FREIGHTER200T] = {
        -- Anzahl Containerplätze
        [3] = {     -- 600t
            -- Rasse
            [RACE_HUMAN]  = SI_TRADER_3X200T_HUMAN,
            [RACE_MORTOK] = SI_TRADER_3X200T_MORTOK,
            [RACE_RAPTOR] = SI_TRADER_3X200T_RAPTOR,  -- Achtung, Wert ist nicht in Reihenfolge!
            [RACE_OCTO]   = SI_TRADER_3X200T_OCTO,
            [RACE_ARRACK] = SI_TRADER_3X200T_ARRACK,
            [RACE_THUL]   = SI_TRADER_3X200T_THUL
        },
        [40] = {    -- 8000t
            [RACE_RAPTOR] = SI_SUPERTRADER_L_RAPTOR
        },
        [42] = {    -- 8400t
            [RACE_ARRACK] = SI_SUPERTRADER_L_ARRACK
        },
        [45] = {    -- 9000t
            [RACE_HUMAN]  = SI_SUPERTRADER_L_HUMAN
        }
    },

    [WINGTYPE_PIRATEFREIGHTER50T] = {
        -- Anzahl Containerplätze
        [2] = {     -- 100t
            -- Rasse
            [RACE_HUMAN]  = SI_PIRATE_2X50T_HUMAN,    -- neu
            [RACE_MORTOK] = SI_PIRATE_2X50T_MORTOK    -- neu
        },
        [3] = {     -- 150t
            [RACE_HUMAN]  = SI_PIRATE_3X50T_HUMAN,    -- neu
            [RACE_MORTOK] = SI_PIRATE_3X50T_MORTOK,   -- neu
            [RACE_RAPTOR] = SI_PIRATE_3X50T_RAPTOR,   -- neu
            [RACE_OCTO]   = SI_PIRATE_3X50T_OCTO,     -- neu
            [RACE_ARRACK] = SI_PIRATE_3X50T_ARRACK,   -- neu
            [RACE_THUL]   = SI_PIRATE_3X50T_THUL      -- neu
        },
        [4] = {     -- 200t
            [RACE_HUMAN]  = SI_PIRATE_4X50T_HUMAN,
            [RACE_MORTOK] = SI_PIRATE_4X50T_MORTOK,
            [RACE_RAPTOR] = SI_PIRATE_4X50T_RAPTOR,   -- Hier ist der Wert in Reihenfolge!
            [RACE_OCTO]   = SI_PIRATE_4X50T_OCTO,     -- Hier ist der Wert in Reihenfolge!
            [RACE_ARRACK] = SI_PIRATE_4X50T_ARRACK,
            [RACE_THUL]   = SI_PIRATE_4X50T_THUL
        },
        [6] = {     -- 300t
            [RACE_HUMAN]  = SI_PIRATE_6X50T_HUMAN,    -- neu
            [RACE_MORTOK] = SI_PIRATE_6X50T_MORTOK    -- neu
        },
        [8] = {     -- 400t
            [RACE_HUMAN]  = SI_PIRATE_8X50T_HUMAN,
            [RACE_MORTOK] = SI_PIRATE_8X50T_MORTOK
        }
    },

    [WINGTYPE_PIRATEFREIGHTER100T] = {
        -- Anzahl Containerplätze
        [2] = {     -- 200t
            -- Rasse
            [RACE_HUMAN]  = SI_PIRATE_2X100T_HUMAN,
            [RACE_MORTOK] = SI_PIRATE_2X100T_MORTOK
        },
        [3] = {     -- 300t
            [RACE_HUMAN]  = SI_PIRATE_3X100T_HUMAN,   -- neu
            [RACE_MORTOK] = SI_PIRATE_3X100T_MORTOK,  -- neu
            [RACE_RAPTOR] = SI_PIRATE_3X100T_RAPTOR,  -- neu
            [RACE_OCTO]   = SI_PIRATE_3X100T_OCTO,    -- neu
            [RACE_ARRACK] = SI_PIRATE_3X100T_ARRACK,  -- neu
            [RACE_THUL]   = SI_PIRATE_3X100T_THUL     -- neu
        },
        [4] = {     -- 400t
            [RACE_HUMAN]  = SI_PIRATE_4X100T_HUMAN,
            [RACE_MORTOK] = SI_PIRATE_4X100T_MORTOK,
            [RACE_RAPTOR] = SI_PIRATE_4X100T_RAPTOR,  -- Hier ist der Wert in Reihenfolge!
            [RACE_OCTO]   = SI_PIRATE_4X100T_OCTO,
            [RACE_ARRACK] = SI_PIRATE_4X100T_ARRACK,
            [RACE_THUL]   = SI_PIRATE_4X100T_THUL
        },
        [6] = {     -- 600t
            [RACE_HUMAN]  = SI_PIRATE_6X100T_HUMAN,
            [RACE_MORTOK] = SI_PIRATE_6X100T_MORTOK
        },
        [8] = {     -- 800t
            [RACE_HUMAN]  = SI_PIRATE_8X100T_HUMAN,   -- neu
            [RACE_MORTOK] = SI_PIRATE_8X100T_MORTOK   -- neu
        }
    },

    [WINGTYPE_PIRATEFREIGHTER200T] = {
        -- Anzahl Containerplätze
        [2] = {     -- 400t
            -- Rasse
            [RACE_HUMAN]  = SI_PIRATE_2X200T_HUMAN,   -- neu
            [RACE_MORTOK] = SI_PIRATE_2X200T_MORTOK   -- neu
        },
        [3] = {     -- 600t
            [RACE_HUMAN]  = SI_PIRATE_3X200T_HUMAN,
            [RACE_MORTOK] = SI_PIRATE_3X200T_MORTOK,
            [RACE_RAPTOR] = SI_PIRATE_3X200T_RAPTOR,  -- Hier ist der Wert in Reihenfolge!
            [RACE_OCTO]   = SI_PIRATE_3X200T_OCTO,
            [RACE_ARRACK] = SI_PIRATE_3X200T_ARRACK,
            [RACE_THUL]   = SI_PIRATE_3X200T_THUL
        },
        [4] = {     -- 800t
            [RACE_HUMAN]  = SI_PIRATE_4X200T_HUMAN,   -- neu
            [RACE_MORTOK] = SI_PIRATE_4X200T_MORTOK,  -- neu
            [RACE_RAPTOR] = SI_PIRATE_4X200T_RAPTOR,  -- neu
            [RACE_OCTO]   = SI_PIRATE_4X200T_OCTO,    -- neu
            [RACE_ARRACK] = SI_PIRATE_4X200T_ARRACK,  -- neu
            [RACE_THUL]   = SI_PIRATE_4X200T_THUL     -- neu
        },
        [6] = {     -- 1200t
            [RACE_HUMAN]  = SI_PIRATE_6X200T_HUMAN,   -- neu
            [RACE_MORTOK] = SI_PIRATE_6X200T_MORTOK   -- neu
        },
        [8] = {     -- 1600t
            [RACE_HUMAN]  = SI_PIRATE_8X200T_HUMAN,   -- neu
            [RACE_MORTOK] = SI_PIRATE_8X200T_MORTOK   -- neu
        }
    }
}

TRADER_INDEX[WINGTYPE_FREIGHTER200CAP] = {
    -- Anzahl Containerplätze
    [2] = TRADER_INDEX[WINGTYPE_FREIGHTER100T][2],
    [4] = TRADER_INDEX[WINGTYPE_FREIGHTER50T][4]
}

TRADER_INDEX[WINGTYPE_FREIGHTER400CAP] = {
    -- Anzahl Containerplätze
    [4] = TRADER_INDEX[WINGTYPE_FREIGHTER100T][4],
    [8] = TRADER_INDEX[WINGTYPE_FREIGHTER50T][8]
}

TRADER_INDEX[WINGTYPE_FREIGHTER600CAP] = {
    -- Anzahl Containerplätze
    [3] = TRADER_INDEX[WINGTYPE_FREIGHTER200T][3],
    [6] = TRADER_INDEX[WINGTYPE_FREIGHTER100T][6]
}

-- Frachterindex nach Anzahl der Containerplätze und Rasse des Frachters für Spezialcontainer Klasse 3
BOMBER_INDEX = {
    -- Anzahl Containerplätze
    [2] = {     -- 400t
        -- Rasse
        [RACE_HUMAN]  = SI_BOMBER_B2_HUMAN,
        [RACE_MORTOK] = SI_BOMBER_B2_MORTOK
    },
    [3] = {     -- 600t
        [RACE_HUMAN]  = SI_BOMBER_B3_HUMAN,
        [RACE_MORTOK] = SI_BOMBER_B3_MORTOK,
        [RACE_RAPTOR] = SI_BOMBER_B3_RAPTOR,
        [RACE_OCTO]   = SI_BOMBER_B3_OCTO,
        [RACE_ARRACK] = SI_BOMBER_B3_ARRACK,
        [RACE_THUL]   = SI_BOMBER_B3_THUL
    },
    [4] = {     -- 800t
        [RACE_HUMAN]  = SI_BOMBER_B4_HUMAN,
        [RACE_MORTOK] = SI_BOMBER_B4_MORTOK,
        [RACE_RAPTOR] = SI_BOMBER_B4_RAPTOR,
        [RACE_OCTO]   = SI_BOMBER_B4_OCTO,
        [RACE_ARRACK] = SI_BOMBER_B4_ARRACK,
        [RACE_THUL]   = SI_BOMBER_B4_THUL
    },
    [6] = {     -- 1200t
        [RACE_HUMAN]  = SI_BOMBER_B6_HUMAN,
        [RACE_MORTOK] = SI_BOMBER_B6_MORTOK
    },
    [8] = {     -- 1600t
        [RACE_HUMAN]  = SI_BOMBER_B8_HUMAN,
        [RACE_MORTOK] = SI_BOMBER_B8_MORTOK
    },
    [40] = {    -- 8000t
        [RACE_RAPTOR] = SI_SUPERBOMBER_HUMAN
    },
    [42] = {    -- 8400t
        [RACE_ARRACK] = SI_SUPERBOMBER_ARRACK
    },
    [45] = {    -- 9000t
        [RACE_HUMAN]  = SI_SUPERBOMBER_RAPTOR
    }
}

-- Anzahl der Containerplätze von Superfrachtern
CARGOBAYS_SUPERFREIGHTER = { [RACE_HUMAN] = 45, [RACE_RAPTOR] = 40, [RACE_ARRACK] = 42 }

-- Taxis
SHUTTLE_TYPE = { -- Tabellenindex und Wert für ShipType sind gleich
     [2] = ST_SHUTTLE,			-- Beladungs-Shuttle an den Frachterdocks der Handelsstation
     [3] = ST_CONSUMPTION_SHUTTLE,	-- Versorgungs-Shuttle von der Handelsstation zu den Orbitern
     [4] = ST_PRODUCTION_SHUTTLE,	-- Produktions-Shuttle von den Orbitern zur Handelsstation
    [18] = ST_COLLECTOR_SHUTTLE,	-- Sammler-Shuttle? Bisher noch nicht entdeckt
    [21] = ST_PASSENGER_SHUTTLE		-- Passagier-Shuttle (Taxi)
}

-- Wingtypen
WINGTYPE_SUPERFREIGHTER	= 21	-- Superfrachter für den Handel

-- Für Patches in missions.bin wegen "NWing.Create"-Problem mit Superfrachtern
WINGTYPE_FREIGHTER50C	= 16	-- Wie WINGTYPE_FREIGHTER200CAP, anstelle von WINGTYPE_FREIGHTER50T
WINGTYPE_FREIGHTER100C	= 17	-- Wie WINGTYPE_FREIGHTER400CAP, anstelle von WINGTYPE_FREIGHTER100T
WINGTYPE_FREIGHTER200C	= 18	-- Wie WINGTYPE_FREIGHTER600CAP, anstelle von WINGTYPE_FREIGHTER200T

-- Tunnel-Missionen
TUNNEL_KABRO		= 0	-- Wechsel in den Planeten-Canyon mit NCanyon.ChangeToCanyon
TUNNEL_SKAA		= 1	-- Wechsel in das Skaa-Mutterschiff mit NCanyon.ChangeToCanyon

-- Kraftfelder für die Tunnel-Missionen
BARRIER			= 0	-- Große Energiebarriere
BLOCKER_4_RAY		= 1	-- Energiesperre mit 4 Strahlen
BLOCKER_5_RAY		= 2	-- Energiesperre mit 5 Strahlen
BLOCKER_HIDDEN		= 3	-- Unsichtbare Energiesperre, ist daher sehr gefährlich

-- Für Missionen
ACHIEVED    = { State = MSTATE_ACHIEVED }
ENDED	    = { State = MSTATE_ENDED }
FAILED	    = { State = MSTATE_FAILED }
OFFERING    = { State = MSTATE_OFFERING }
RUNNING	    = { State = MSTATE_RUNNING }
READY	    = { Ready = 1 }			-- Mission darf starten
NOW	    = { Timeout = 0 }			-- Mission beenden und sofort wieder anbieten
NEVER	    = { Timeout = -1 }			-- Mission beenden und nie wieder anbieten
NOW_QUIET   = { Timeout = 0, Text = "" }	-- Mission leise beenden und sofort wieder anbieten
NEVER_QUIET = { Timeout = -1, Text = "" }	-- Mission leise beenden und nie wieder anbieten
RED_TEXT    = "ID_HYPERJUMPINFO_ENTRY_ILLEGAL"	-- Zwei Platzhalter für roten Text in NGUI.ShowInfoText
NPC_DATA    = { Name = "", Model = "", Location = "" }	-- Parametertabelle für NNPC.Create

-- Subtypes der Terminalmissionen, bestimmt das Bild vom Auftrag
GFX_TRANSPORT	= { Subtype = SUBTYPE_TRANSPORT }	-- Transportauftrag
GFX_HEADHUNT	= { Subtype = SUBTYPE_HEADHUNT }	-- Kopfgeldjagd
GFX_PIRATES	= { Subtype = SUBTYPE_PIRATES }		-- Piratenjagd
GFX_SABOTAGE	= { Subtype = SUBTYPE_SABOTAGE }	-- Sabotageauftrag
GFX_PROTECT	= { Subtype = SUBTYPE_PROTECT }		-- Missionsziel beschützen
GFX_RESCUE	= { Subtype = SUBTYPE_RESCUE }		-- Bergungs- oder Rettungsauftrag
GFX_POLITICAL	= { Subtype = SUBTYPE_POLITICAL }	-- Politischer Auftrag

-- Sternsysteme, Parameter für die "get"-Funktion
SYSTEM_ID	= "Logic.PlayerShip.systemIndex"	-- Liefert die aktuelle SystemId
SYSTEM_HANDLE	= "Logic.PlayerShip.systemId"		-- Liefert das aktuelle SystemHandle
CLUSTER_HANDLE	= "Logic.PlayerShip.clusterId"		-- Liefert das aktuelle ClusterHandle

-- Für die Funktionen NPlayer.LockHyperJump und NPlayer.LockSystemEntry
LOCK	= { Lock = 1, Locked = 1 }	-- Hyperraumsprung oder Systemeintritt sperren
UNLOCK	= {}				-- Hyperraumsprung oder Systemeintritt freigeben

-- Häufig benötigte Sounds
SND_ACCELERATE		= "FX.Trench.AcceleratorEffect.Skaabooster-11"
SND_AFTERBURNER		= "FX.PlayerAfterburner.Beschleunigung_05"
SND_ALARM		= "FX.UI.WarningKlaxon.FX_ShipInBadState-Alarm-09"
SND_BRAKE		= "FX.PlayerBrake.FX_PlayerBrake08"
SND_DATA_TRANSMISSION1	= "FX.UI.DataTransmission"
SND_DATA_TRANSMISSION2	= "FX.UI.DataTransmission2"
SND_ENEMY_BEHIND	= "FX.UI.PursuerAlert.Enemy_Behind_Loop_17_norm"
SND_ENEMY_ROCKET	= "FX.UI.EnemyRocket.enemy_rocket"
SND_ENGINE_LARGE	= "FX.PlayerEngine.Internal.Large.FX_Player_Engine_Large_01"
SND_ENGINE_MEDIUM	= "FX.PlayerEngine.Internal.Medium.FX_Player_Engine_Medium_01"
SND_ENGINE_SMALL	= "FX.PlayerEngine.Internal.Small.FX_Player_Engine_Small_01"
SND_ENERGY		= "FX.Trench.AcceleratorEffect.SkaBoosterEnergieFeld-01"
SND_EXPLOSION_FAR	= "FX.Turbo.Stop.FX_ZeitBeschleinigungEnde-04"
SND_FIRE_EMP		= "FX.Spell.EMP.Fire.FX_EMPStereo-06"
SND_FIRE_OVERLOAD	= "FX.Spell.Overload.Fire.FX_Overload-Trigger-Stereo-07"
SND_FIRE_TIMESHOCK	= "FX.Spell.TimeShock.Fire.FX_TimeShockTrackSlammerStereo-04"
SND_FLAK_TURN		= "FX.Flak.Turn.FX_FlakMove-08"
SND_HOLOCAM1		= "FX.UI.FX_HoloCam-01"
SND_HOLOCAM2		= "FX.UI.FX_HoloCam-02"
SND_INFO_MESSAGE	= "Special.UI.InfoMessage"
SND_JAMMER_ACTIVE	= "FX.UI.Jammer.Active.FX_Jammer-02"
SND_JAMMER_SUCCESS	= "FX.UI.Jammer.Success.FX_JammerSuccess-01"
SND_MISSILE_BIGBANG	= "FX.Missile.BigBang.Fire.FX_BigBang-Trigger-09"
SND_MISSILE_HELLFIRE	= "FX.Missile.Hellfire.Fire.FX_HellFire_Trigger-01"
SND_MISSILE_SWARM	= "FX.Missile.Swarm.Fire.Spellshot2-02"
SND_MISSILE_LOCKING	= "FX.UI.MissileLocking\UI_MissleLocking-04"
SND_MOUSEOVER1		= "Special.UI.ClusterMouseover.FX_Starmap_MouseOver-01"
SND_MOUSEOVER2		= "Special.UI.ClusterMouseover.FX_Starmap_MouseOver-02"
SND_MOUSEOVER3		= "Special.UI.ClusterMouseover.FX_Starmap_MouseOver-03"
SND_NEGATIV		= "FX.UI.Negativ"
SND_POSITIV		= "FX.UI.Positiv"
SND_SHIP_DAMAGED	= "FX.PlayerShipDamaged.FX_ShipInBadState-13"
SND_STATIC		= "FX.UI.Static"
SND_OFF			= { Sound = "" }

SND_CONTAINER_COLLECT1	= "FU.Container.Dock.FX_Container_Collect-1"
SND_CONTAINER_COLLECT2	= "FU.Container.Dock.FX_Container_Collect-2"
SND_CONTAINER_DROP1	= "FU.Container.Undock.FX_Container_Drop-1"
SND_CONTAINER_DROP2	= "FU.Container.Undock.FX_Container_Drop-2"
SND_MINE_DROP1		= "FU.DropMine.FX_drop_mine-1"
SND_MINE_DROP2		= "FU.DropMine.FX_drop_mine-2"

SND_COMBAT_FLYING_ACES	= "MUSIC.FightLoop.15_combat_intro_flying_aces"
SND_COMBAT_SPACE_LORDS	= "MUSIC.FightLoop.13_combat_intro_space_lords"
SND_COMBAT_THE_VOID	= "MUSIC.FightLoop.07_combat_intro_the_void"
SND_COMBAT_TROOPERS	= "MUSIC.FightLoop.09_combat_intro_troopers"

SND_GAME_OVER			= "MUSIC.Death.66_gameover_final"
SND_MISSION_FAILED_LONG		= "MUSIC.Failed.04_ui_maintheme_fail"
SND_MISSION_FAILED_SHORT	= "MUSIC.FailedShort.04_ui_maintheme_fail_short"
SND_MISSION_SUCCESS_LONG	= "MUSIC.Success.03_ui_maintheme_success"
SND_MISSION_SUCCESS_SHORT	= "MUSIC.SuccessShort.03_ui_maintheme_success_short"

GIGGLE_LIST = {
    "IDC_S4_Hehehe", "IDC_S4_Hehehe2", "IDC_S4_Hehehehe",
    "IDC_S4_Hihagaga", "IDC_S4_Hihahaha", "IDC_S4_Huhuhuhahaa"
}
EONA_DEATH_MSG = { -- Eona schreit: "Aaaaaaargh!!!"
    Text  = "IDC_COMBAT_KILL_01A_THUPIR07",
    Voice = "COMBAT_Kill1a_thupir.IDC_COMBAT_KILL_01A_THUPIR07_SPOKEN_thupir00",
    Actor = "eona"
}
KAYRON_TAUNT_1 = { "05", "10", "38", "40", "50", "56", "65", "76" }

-- Häufig benötigte Vektoren
NULL_VECTOR	= { 0, 0, 0 }
SYSTEM_CENTER	= NULL_VECTOR		-- Handelsstation ist absoluter Koordinatenursprung
OBJECT_CENTER	= NULL_VECTOR		-- Relatives Zentrum eines Objekts
WING_CENTER	= NULL_VECTOR		-- Relative Position des Wingleaders
BG_CENTER	= NULL_VECTOR		-- Relatives Zentrum eines Schlachtfelds
SYSTEM_GATE	= { 0, 0, 10000 }	-- Hypergate (aber nicht für das System Permakin)
PERMAKIN_GATE	= { 0, 4000, 16000 }	-- Hypergate im Permakin-System
FAR_AWAY	= { 0, 0, 10000000 }	-- 10000 Units hinter dem Hypergate
DIR_RIGHT	= { 1, 0, 0 }		-- Ausrichtung +X
DIR_LEFT	= { -1, 0, 0 }		-- Ausrichtung -X
DIR_UP		= { 0, 1, 0 }		-- Ausrichtung +Y
DIR_DOWN	= { 0, -1, 0 }		-- Ausrichtung -Y
DIR_FRONT	= { 0, 0, 1 }		-- Ausrichtung +Z
DIR_BACK	= { 0, 0, -1 }		-- Ausrichtung -Z
LANDING_CROSS	= { -53.5, 13.5, 16.0 }	-- Relatives Zentrum der Landeplattform einer Piratenbasis
AIRFIELD_POS	= { -54, 20, 16 }	-- Relative Position über dem Landefeld einer Piratenbasis
HYPERGATE_FRONT	= { -0.153971, 0.171579, 0.973064 } -- Ausrichtung vom Hypergate in Richtung +Z

IKOSAEDER_L2 = { -- Die 12 Ecken eines Ikosaeders mit der Kantenlänge 2 (Umkugelradius ~ 1,902)
    { 0, 1, 1.618034 }, { 0, 1, -1.618034 }, { 0, -1, 1.618034 }, { 0, -1, -1.618034 },
    { 1, 1.618034, 0 }, { 1, -1.618034, 0 }, { -1, 1.618034, 0 }, { -1, -1.618034, 0 },
    { 1.618034, 0, 1 }, { 1.618034, 0, -1 }, { -1.618034, 0, 1 }, { -1.618034, 0, -1 }
}
IKOSAEDER_R1 = { -- Die 12 Ecken eines Ikosaeders mit dem Umkugelradius 1 (Kantenlänge ~ 1,051)
    { 0, 0.525731, 0.850651 }, { 0, 0.525731, -0.850651 }, { 0, -0.525731, 0.850651 }, { 0, -0.525731, -0.850651 },
    { 0.525731, 0.850651, 0 }, { 0.525731, -0.850651, 0 }, { -0.525731, 0.850651, 0 }, { -0.525731, -0.850651, 0 },
    { 0.850651, 0, 0.525731 }, { 0.850651, 0, -0.525731 }, { -0.850651, 0, 0.525731 }, { -0.850651, 0, -0.525731 }
}

-- Zahlen
MAX_INT	    =  2147483647
MIN_INT	    = -2147483648
PI	    = math.pi
PERMUTATION = { { 1, 2, 3 }, { 1, 3, 2 }, { 2, 1, 3 }, { 2, 3, 1 }, { 3, 1, 2 }, { 3, 2, 1 } }

-- Zeichentabellen
ABC = { [0] = "";
    "A","B","C","D","E","F","G","H","I","J","K","L","M",
    "N","O","P","Q","R","S","T","U","V","W","X","Y","Z"
}

CHARACTERS = { -- StringId's für Umlaute, Operatoren, Satz- und Sonderzeichen
    ["ä"] = "LO_AE",
    ["ö"] = "LO_OE",
    ["ü"] = "LO_UE",
    ["ß"] = "LO_SZ",
    ["Ä"] = "UP_AE",
    ["Ö"] = "UP_OE",
    ["Ü"] = "UP_UE",
    [" "] = "ID_BLANK",
    ["."] = "ID_DOT",
    [","] = "ID_COMMA",
    [":"] = "ID_COLON",
    [";"] = "ID_SEMICOLON",
    ["!"] = "ID_EXCLAMATION",
    ["?"] = "ID_QUESTION",
    ["_"] = "ID__",
    ["+"] = "ID_PLUS",
    ["-"] = "ID_MINUS",
    ["*"] = "ID_MUL",
    ["/"] = "ID_DIV",
    ["="] = "ID_EQ",
    ["<"] = "ID_LT",		-- "<" wird aus unerfindlichem Grund nicht dargestellt,
    [">"] = "ID_GT",		--     daher in user_strings durch "‹" ersetzt (ID_LT1)
    ["#"] = "ID_NUM",
    ["("] = "ID_BRACE0_L",
    [")"] = "ID_BRACE0_R",
    ["["] = "ID_BRACE1_L",
    ["]"] = "ID_BRACE1_R",
    ["{"] = "ID_BRACE2_L",
    ["}"] = "ID_BRACE2_R",
    ["\\"]= "ID_BACKSLASH",	-- muss doppelt sein, sonst Sonderbedeutung
    ["&"] = "ID_AMP",
    ["%"] = "ID_PERCENT",
    ["‰"] = "ID_PROMILLE",
    ['"'] = "ID_QUOT",		-- Anführungszeichen gerade,
    ["„"] = "ID_QUOT_L",	-- Anführungszeichen links,
    ["“"] = "ID_QUOT_LH",	-- Anführungszeichen links hochgestellt
    ["”"] = "ID_QUOT_R",	-- Anführungszeichen rechts
    ["'"] = "ID_APO",		-- Apostroph
    ["‘"] = "ID_APO_L",		-- Apostroph links
    ["’"] = "ID_APO_R",		-- Apostroph rechts
    ["´"] = "ID_AKUT",
    ["`"] = "ID_GRAVIS",
    ["@"] = "ID_AT",
    ["^"] = "ID_CARET",
    ["°"] = "ID_GRAD",
    ["~"] = "ID_TILDE",
    ["—"] = "ID_HBAR",		-- Gedankenstrich
    ["|"] = "ID_VBAR",
    ["µ"] = "ID_MU",
    ["‹"] = "ID_LT1",
    ["›"] = "ID_GT1",
    ["«"] = "ID_LEFT",
    ["»"] = "ID_RIGHT",
    ["$"] = "ID_DOLLAR",
    ["€"] = "ID_EURO",
    ["£"] = "ID_POUND",
    ["¥"] = "ID_YEN",
    ["¢"] = "ID_CENT",
    ["Ø"] = "ID_NULL",
    ["…"] = "ID_MORE",
    ["¹"] = "ID_UP_1",
    ["²"] = "ID_UP_2",
    ["³"] = "ID_UP_3",
    ["½"] = "ID_1_DIV_2",	-- 1/3, 1/8 und 2/3 geht nicht
    ["¼"] = "ID_1_DIV_4",
    ["¾"] = "ID_3_DIV_4",
    ["±"] = "ID_PLUSMINUS",
    ["×"] = "ID_MULT",
    ["÷"] = "ID_DIVI",
    ["•"] = "ID_LI",
    ["¶"] = "ID_PI"
}

SPECIAL_CHAR_LOWER = { -- Internationale Sonderzeichen klein
    "à","á","â","ã","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ñ","ò","ó","ô","õ","÷","ø","ù","ú","û"
}

SPECIAL_CHAR_UPPER = { -- Internationale Sonderzeichen groß
    "À","Á","Â","Ã","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ñ","Ò","Ó","Ô","Õ","×","Ø","Ù","Ú","Û"
}

-- Allgemeine Konstanten
APPEND    = 1
ATTACK    = 1
DEFEND    = 1
DESTROY   = 1
IMMEDIATE = 1
SELECT    = 1
SWAP_ID_0 = { [0]=1; 0 }  -- Index 0 nach Index 1 und umgekehrt
SWAP_ID_1 = { 2, 1 }	  -- Index 1 nach Index 2 und umgekehrt

--============================[ Sternsysteme ]==================================

---------------------[ aus "MissionLib.GetStarSystemInfo" ]---------------------

-- Nation/Rasse (0-5, Konstante RACE_HUMAN..RACE_THUL)
MissionLib.GetStarSystemNation = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".nation" )
end

-- Regierung (0-5, Konstante GOVERN_DEMOCRACY..GOVERN_MONARCHY)
MissionLib.GetStarSystemGovernment = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".government" )
end

-- Fraktion (0-2, Konstante FACTION_FEDERATION..FACTION_INDEPENDENT)
MissionLib.GetStarSystemFaction = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".faction" )
end

-- Wirtschaft (0-5, Konstante SYSTEM_AGRICULTURE..SYSTEM_SERVICE)
MissionLib.GetStarSystemEconomy = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".economy" )
end

-- Wohlstand, Lebensstandard (0-2, Konstante WEALTH_POOR..WEALTH_RICH)
MissionLib.GetStarSystemWealth = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".wealth" )
end

-- Artefaktstatus (0: Vorhanden / 2: kein / 6: kein / 8: Konstante ARTEFACT_RECEIVED)
MissionLib.GetStarSystemArtefact = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".artefact" )
end

-- ID der im System ansässigen Gang (0-46), liefert 65535, wenn keine Gang existiert.
-- Liefert auch dann 65535, wenn man den Cluster nach Vernichtung der Gang verlassen hat UND solange
-- er noch nicht wieder betreten wurde. Die ID wird also erst bei Rückkehr automatisch neu gesetzt!
MissionLib.GetStarSystemGangId = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".gangid" )
end

-- Anzahl der Vernichtungen der Gang im Sternsystem (>=0)
MissionLib.GetStarSystemGangCounter = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".gangcounter" )
end

-- Von Piraten besetztes System (true/false)
MissionLib.GetStarSystemSiege = function( SystemId )
    if get( "Logic.StarSystems."..SystemId..".siege" ) > 0 then
        return 1
    end
end

-- Das System ist aktiv (true/false)
MissionLib.GetStarSystemIsActive = function( SystemId )
    if get( "Logic.StarSystems."..SystemId..".isActive" ) > 0 then
        return 1
    end
end

-- Im System ist eine Terminal- oder Bar-Mission (Sidequest) aktiv. (true/false)
-- Aktive Storymissionen werden mit dieser Funktion nicht angezeigt.
MissionLib.GetStarSystemIsActiveMission = function( SystemId )
    if get( "Logic.StarSystems."..SystemId..".isActiveMission" ) > 0 then
        return 1
    end
end

-- Liefert das ClusterHandle des Systems
MissionLib.GetStarSystemCluster = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".clusterId" )
end

-- X- und Y-Position auf der Sternenkarte in Lichtjahren (table[2]:float)
MissionLib.GetStarSystemPos = function( SystemId )
    SystemId = "Logic.StarSystems."..SystemId
    return { get( SystemId..".posX" ), get( SystemId..".posY" ) }
end

--------------------------------------------------------------------------------

-- Prüft, ob das aktuelle System der übergebenen Nation angehört
MissionLib.IsSystemNation = function( Race )
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".nation" ) == Race then
        return 1
    end
end

-- Prüft, ob das aktuelle System die übergebene Regierung hat
MissionLib.IsSystemGovernment = function( Government )
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".government" ) == Government then
        return 1
    end
end

-- Prüft, ob das aktuelle System der übergebenen Fraktion angehört
MissionLib.IsSystemFaction = function( Faction )
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".faction" ) == Faction then
        return 1
    end
end

-- Prüft, ob das aktuelle System die übergebene Wirtschaft hat
MissionLib.IsSystemEconomy = function( Economy )
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".economy" ) == Economy then
        return 1
    end
end

-- Prüft, ob das aktuelle System den übergebenen Wohlstand hat
MissionLib.IsSystemWealth = function( Wealth )
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".wealth" ) == Wealth then
        return 1
    end
end

-- Prüft, ob ein Artefakt im aktuellen System existiert
MissionLib.ExistArtefact = function()
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".artefact" ) == 0 then
        return 1
    end
end

-- Prüft, ob das aktuelle System von Piraten besetzt ist
MissionLib.IsSystemSiege = function()
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".siege" ) > 0 then
        return 1
    end
end

-- Prüft, ob im aktuellen System eine Terminal-, Space- oder Bar-Mission aktiv ist
MissionLib.IsSystemActiveMission = function()
    if get( "Logic.StarSystems."..get( SYSTEM_ID )..".isActiveMission" ) > 0 then
        return 1
    end
end

--------------------------------------------------------------------------------

-- Liefert das Handle eines Systems. Ist der Parameter 'SystemId' nicht vorhanden
-- oder ungültig, wird das Handle des aktuellen Systems zurückgeliefert.
MissionLib.GetHandleFromId = function( SystemId )
    if SystemId and SystemId >= 0 and SystemId <= 402 then
        return get( "Logic.StarSystems."..SystemId..".id" )
    end
    return get( SYSTEM_HANDLE )
end

-- Sucht im aktuellen Cluster nach allen Systemen mit bestimmten und gleichen Eigenschaften.
-- Liefert IDs, Handles und Anzahl der gefundenen Systeme, ansonsten nil im Parameter 'Found'.
-- Rückgabetabelle: { Found:unsigned int, Systems:table[n] }
-- Die übergebene Tabelle 'Properties' kann die folgenden Einträge enthalten:
--  param   = Sichtbarkeitsklasse, MUSS immer angegeben werden!
--  active  = Aktives System ausschließen, wenn > 0
--  crime   = Kriminalitätspunkte des Spielers
--  economy = Wirtschaft
--  faction = Fraktion
--  gouvern = Regierung
--  jump    = System ist mit einem Sprung erreichbar, wenn > 0
--  offset  = Maximaler ± Wert, um den die SystemId variieren darf,
--            es wird aber immer nur im aktuellen Cluster gesucht
--  orbiter = Orbitertyp, der vorhanden sein muss
--  wealth  = Wohlstand
MissionLib.FindSystems = function( Properties )
    local foundsystems = 0           -- Anzahl gefundener Systeme
    local systems = {}               -- Temporärer Speicher für die Systeme
    local param = Properties.param   -- Sichtbarkeitsklasse sichern
    -- StarFinder flushen
    if param then                    -- Sichtbarkeitsklasse, muss immer zuerst gesetzt werden!
        set( "Logic.StarFinder.param", param )
        Properties.param = nil
    end
    for name, value in Properties do
        set( "Logic.StarFinder."..name, value )
    end
    Properties.param = param         -- Sichtbarkeitsklasse wiederherstellen
    -- Jetzt den StarFinder leersaugen
    repeat
        local systemhandle = get( "Logic.StarFinder.result" )
        if systemhandle > 0 then     -- System gefunden wenn > 0, Ergebnis in die Tabelle
            foundsystems = foundsystems + 1
            systems[foundsystems] = {
                Handle = systemhandle,
                Id = NStarSystem.GetIdFromHandle( { Handle = systemhandle } ).Id
            }
        else
            if foundsystems == 0 then
                return systems       -- Kein System gefunden, leere Tabelle zurückliefern
            end
            return { Found = foundsystems, Systems = systems }   -- Alle Systeme gefunden
        end
    until nil
end

-- Prüft, ob das System freigeschaltet ist. Das System muss im aktuellen Cluster liegen.
-- Für den Parameter 'SystemId' kann sowohl die Id als auch das Handle des Systems übergeben werden.
MissionLib.StarSystemUnlocked = function( SystemId )
    if SystemId <= 402 then
        SystemId = NStarSystem.GetHandleFromId( { Id = SystemId } ).Handle
    end
    local systemhandle
    set( "Logic.StarFinder.param", STAR_UNLOCKED )
    repeat
        systemhandle = get( "Logic.StarFinder.result" )
        if systemhandle == SystemId then
            return 1
        end
    until systemhandle == 0
end

-- Liefert eine Tabelle mit Informationen zum Artefaktstatus eines Systems
MissionLib.GetSystemArtefactInfo = function( SystemId )
    local handle
    local artefact = get( "Logic.StarSystems."..SystemId..".artefact" )
    if artefact == 0 and SystemId == get( SYSTEM_ID ) then
        handle = NObject.GetArtefact({}).Handle
    end
    return {
        Status = artefact,		-- Der numerische Wert vom Status
        Exists = ( artefact == 0 ),	-- Im System gibt es ein Artefakt, wenn true
        Handle = handle,		-- Handle des Artefakts im aktuellen System
        Retrieved = ( artefact == 8 ),	-- Artefakt wurde bereits aufgenommen (ARTEFACT_RECEIVED)
        NotExist1 = ( artefact == 6 ),	-- Kein Artefakt, Status = 6
        NotExist2 = ( artefact == 2 )	-- Kein Artefakt, Status = 2
    }
end

-- Liefert die Entfernung zweier Systeme in Lichtjahren. Ist der zweite Parameter
-- 'SystemId2' nicht vorhanden, wird die SystemId des aktuellen Systems verwendet.
MissionLib.GetStarSystemDistance = function( SystemId1, SystemId2 )
    if not SystemId2 then
        SystemId2 = get( SYSTEM_ID )
    end
    local x = get( "Logic.StarSystems."..SystemId1..".posX" )
            - get( "Logic.StarSystems."..SystemId2..".posX" )
    local y = get( "Logic.StarSystems."..SystemId1..".posY" )
            - get( "Logic.StarSystems."..SystemId2..".posY" )
    return math.sqrt( x * x + y * y )
end

-- Liefert true, wenn das angegebene System in Reichweite des Hyperraumantriebs liegt.
MissionLib.IsInRange = function( SystemId )
    local target = get( "Logic.StarSystems."..SystemId..".id" )
    for i, system in NStarSystem.List( { Mode = 0 } ).SystemList do
        if system == target then
            return 1
        end
    end
end

-- Liefert Id und Handle des nächstbesten Systems in Reichweite des Hyperraumantriebs.
MissionLib.GetSystemInRange = function()
    set( "Logic.StarFinder.param", STAR_UNLOCKED )
    set( "Logic.StarFinder.active", 1 )
    set( "Logic.StarFinder.jump", 1 )
    local systemhandle = get( "Logic.StarFinder.result" )
    return {
        Handle = systemhandle,
        Id = NStarSystem.GetIdFromHandle( { Handle = systemhandle } ).Id
    }
end

-- Liefert eine Liste mit allen System-IDs und -Handles in Reichweite des Hyperraumantriebs.
MissionLib.ListSystemsInRange = function()
    local systems = {}
    for i, systemhandle in NStarSystem.List( { Mode = 0 } ).SystemList do
        systems[i] = {
            Handle = systemhandle,
            Id = NStarSystem.GetIdFromHandle( { Handle = systemhandle } ).Id
        }
    end
    return systems
end

-- Liefert den Kostenfaktor eines Systems.
-- Arm = 0.8 (80%), Normal = 1.0 (100%), Reich = 1.2 (120%)
MissionLib.GetStarSystemCostFactor = function( SystemId )
    return get( "Logic.StarSystems."..SystemId..".wealth", 1 ) * 0.2 + 0.8
end

-- Liefert die Rasse des aktuellen Systems (0-5, Konstante RACE_HUMAN..RACE_THUL)
MissionLib.GetSystemRace = function()
    return get( "Logic.StarSystems."..get( SYSTEM_ID )..".nation" )
end

-- Liefert die StringId für einen Systemnamen aus der global.res.
-- 'SystemId' darf sowohl die Id als auch das Handle des Systems sein.
MissionLib.GetSystemName = function( SystemId )
    if SystemId > 402 then
        SystemId = NStarSystem.GetIdFromHandle( { Handle = SystemId } ).Id
    end
    return "ID_SYSTEMNAME_"..SystemId
end

-- Liefert die SystemId vom übergebenen Systemnamen (exakter Name, keine StringId).
MissionLib.GetSystemIdFromName = function( SystemName )
    for id, name in SYSTEMNAMES do
        if SystemName == name then
            return id
        end
    end
end

-- Liefert die StringId eines Konzernnamens des Systems.
-- In jedem Cluster gibt es 3 verschiedene Konzerne mit dem Index von 0 bis 2.
-- Wird kein Index angegeben, liefert die Funktion einen zufälligen Namen zurück.
MissionLib.GetCombineName = function( SystemId, Index )
    if not Index then
        Index = MissionLib.RandomInt0( 2 )
    end
    local cluster = MissionLib.GetStarClusterId( SystemId )
    if cluster < 10 then cluster = "0"..cluster; end
    return "IDL_TRADER_"..cluster.."_0"..Index
end

-- Liefert die StringId für einen Gangnamen aus der global.res
MissionLib.GetGangName = function( GangId )
    return "ID_GANGNAME_"..GangId
end

-- Prüft, ob im System eine Gang existiert (true/false)
-- Ist der Parameter 'SystemId' nicht vorhanden, wird das aktuelle System geprüft.
-- ACHTUNG: Wurde die Gang vernichtet, dann wird sie erst wieder erzeugt,
-- wenn man den Cluster für kurze Zeit verlässt UND ihn wieder betritt.
-- Solange er nicht wieder besucht wurde, bleibt der Wert auf 65535 und damit false!
MissionLib.GangExists = function( SystemId )
    if not SystemId then
        SystemId = get( SYSTEM_ID )
    end
    if get( "Logic.StarSystems."..SystemId..".gangid" ) < 65535 then
        return 1
    end
end

-- Setzt die ID der Gang im angegebenen Sternsystem (Originalspiel: 0-46, Mod: 0-54)
-- Existiert keine Gang (mehr), kann die GangId auf 65535 gesetzt werden.
MissionLib.SetStarSystemGangId = function( SystemId, GangId )
    set( "Logic.StarSystems."..SystemId..".gangid", GangId )
end

-- Liefert eine Tabelle mit allen Gangsystemen der Galaxis. Der Tabellenindex entspricht dem Gangindex.
MissionLib.GetGangSystems = function()
    return {	-- Sternsysteme Piratengangs (Index) im Spiel
    [0] =
         4;	-- Obas		Karmiti-Gang (0)
    11,	-- Pachee	Akim-Gang (1)
    18,	-- Anomi	Elsu-Gang (2)
    26,	-- Echee	Taini-Gang (3)
    34,	-- Shoma	Aponi-Gang (4)
    42,	-- Baylona	Fortun-Gang (5)
    43,	-- Albadiz	Ordonho-Gang (6)
    46,	-- Neplocruz	Ramiro-Gang (7)
    48,	-- Arrosloca	Vasco-Gang (8)
    64,	-- Rulote	Boaventura-Gang (9)
    57,	-- Lular	Alvito-Gang (10)
    58,	-- Alfabalas	Mendo-Gang (11)
    75,	-- Lucero	Galindo-Gang (12)
    80,	-- Telbeigro	Gil-Gang (13)
    90,	-- Sarbrejar	Tiago-Gang (14)
    95,	-- Aychena	Marjo-Gang (15)
    110,	-- Avilmurcia	Helder-Gang (16)
    112,	-- Tero		Armengol-Gang (17)
    135,	-- Goro		Boris-Gang (18)
    138,	-- Vidal	Sergej-Gang (19)
    141,	-- Nizbin	Igor-Gang (20)
    155,	-- Desno	Jurij-Gang (21)
    157,	-- Twerkano	Wladislaw-Gang (22)
    171,	-- Archangelsk	Sascha-Gang (23)
    172,	-- Nakhodlu	Danilo-Gang (24)
    179,	-- Amkovo	Andrei-Gang (25)
    184,	-- Charodpul	Jorg-Gang (26)
    194,	-- Gans'clie	Let'han-Gang (27)
    197,	-- Kil'ore	Gor'ogh-Gang (28)
    211,	-- Wica		Mascha-Gang (29)
    217,	-- Cloma	Macawi-Gang (30)
    231,	-- D'ores	Tor'hal-Gang (31)
    274,	-- Lone'ron	Mar'ghal-Gang (32)
    284,	-- Achnas'aul	Sav'ghal-Gang (33)
    295,	-- Pyidaung	Shakunt-fu-Gang (34)
    297,	-- Laikuku	Dakshe-ne-Gang (35)
    301,	-- Mingin	Jitendra-ko-Gang (36)
    326,	-- Sainolin	Janath-ai-Gang (37)
    332,	-- Kindaung	Eknath-ko-Gang (38)
    339,	-- Kinmin	Al'ogh-Gang (39)
    345,	-- Chaing	Tarak-fu-Gang (40)
    346,	-- Thidaya	Uday-ne-Gang (41)
    348,	-- Tegyigon	Alok-ne-Gang (42)
    385,	-- Aberloch	Domhnall-Gang (43)
    392,	-- Keodale	Laoghaire-Gang (44)
    393,	-- Ardarroch	Lennox-Gang (45)
    395,	-- Todhair	Mathuin-Gang (46)
        -- Der Mod neu hinzugefügte Piratengangs
    22,	-- Patiak	Xanten-Gang (47)
    122,	-- Vipacoy	Figueres-Gang (48)
    130,	-- Teirov	Asimov-Gang (49)
    242,	-- Tor'ore	Mor'dor-Gang (50)
    263,	-- Tenatori	Rossi-Gang (51)
    269,	-- Glen'ore	Ker'mit-Gang (52)
    324,	-- Changrang	Tarantu-la-Gang (53)
    377	-- Yedaw	Formicu-la-Gang (54)
    }
end

-- Liefert die Anzahl der Gangs in der Galaxis, unabhängig davon, ob sie noch existieren.
MissionLib.GetGalaxyGangCount = function()
    return lua.sizeof( MissionLib.GetGangSystems() )
end

-- Liefert tatsächliche Regierung und verbotene Waren eines besetzten Systems.
-- Syntax: V.Info = MissionLib.GetStarSystemSiegeInfo( SystemId ) : { Government, IllegalGoods }
MissionLib.GetStarSystemSiegeInfo = function( SystemId )
    if MissionLib.GetStarSystemSiege( SystemId ) then
        local government = PIRATESYSTEM_GOVERNMENT[SystemId]
        return {
            Government = government,
            IllegalGoods = MissionLib.CopyTable( ILLEGAL_GOODS[government] )
        }
    end
end

-- Tabelle mit allen Systemen, die einen Lavaplaneten haben.
-- Planets.ini: Model = 65529 + 65534 (Feuer-Planet) und 65535 (Crack-Planet)
MissionLib.LavaPlanetSystems = {
     17,	-- Mesehkane	Barnard		Crack-Planet, 65535
     74,	-- Majarin	Stromok		Feuer-Planet, 65534
    122,	-- Vipacoy	Humok		Feuer-Planet, 65534 (neu)
    151,	-- Suzga	Raptor Gamma	Feuer-Planet, 65529
    190,	-- Permnaja	Raptor Epsilon	Crack-Planet, 65535
    265,	-- Ardul'lie	Bear'mor	Crack-Planet, 65535 (neu)
    352,	-- Atet		Hive-DC		Feuer-Planet, 65529
    373		-- Shwebangon	Hive-G8		Feuer-Planet, 65529 + 65534 (neu)
}

-- Tabelle mit allen Systemen, die mindestens einen Planeten mit Ring haben.
MissionLib.RingPlanetSystems = { -- Planets.ini: Model = 65530
      5,	-- Hu		Lalande
     29,	-- Sol		Alpha Centauri
     67,	-- Cavcala	Pertok
    101,	-- Cuendo	Klatok
    145,	-- Kosrod	Raptor Nova
    174,	-- Chanschat	Raptor Delta
    270,	-- Sona'chan	Gab'har
    291,	-- Achand'unie	Gab'har
    306,	-- Shwege	Hive-AC3 (neu)
    308,	-- Kinzan	Hive-AC3
    328		-- Kandaya	Hive-CU7
}

-- Tabelle mit allen Systemen, die einen Komet haben.
MissionLib.KometSystems = {
     29,	-- Sol		Alpha Centauri (neu)
     55,	-- Camvilje	Grotok
     64,	-- Rulote	Pertok
     71,	-- Cabracoy	Stromok
    173,	-- Koro		Raptor Delta
    200,	-- Abria'chan	Sion'nach
    210,	-- Witeni	Sirius
    234,	-- Drum'unie	Madra'mor
    281,	-- Bad'aul	Gab'har
    380		-- Clachtoll	Communa
}

-- Tabelle mit allen Systemen, die ein schwarzes Loch haben.
MissionLib.BlackholeSystems = {
     21,	-- Tasakane	Tau Ceti (neu)
    128,	-- Zhusomol	Raptor Alpha
    129,	-- Nostromo	Raptor Alpha
    130,	-- Teirov	Raptor Alpha
    131,	-- Tamburg	Raptor Alpha
    132		-- Lysmir	Raptor Alpha
}

------------------------------[ Cluster ]---------------------------------------

-- Liefert eine Tabelle mit Informationen zum Cluster mit der angegebenen ClusterId.
-- 'ClusterId' darf sowohl die Id als auch das Handle des Clusters sein.
-- Ist der Parameter 'ClusterId' nicht vorhanden, wird die Info des aktuellen Clusters geliefert.
MissionLib.GetStarClusterInfo = function( ClusterId )
    if not ClusterId then
        ClusterId = "Logic.Clusters."..MissionLib.GetStarClusterId()
    else
        ClusterId = "Logic.Clusters."..ClusterId
    end
    return {
        nation   = get( ClusterId..".nation" ),	  -- Rasse
        stars    = get( ClusterId..".stars" ),	  -- Anzahl der Sternsysteme
        isActive = get( ClusterId..".isActive" ), -- Cluster ist aktiv
        handle   = get( ClusterId..".id" ),	  -- Handle des Clusters
        posX     = get( ClusterId..".posX" ),	  -- X-Position des Zentrums
        posY     = get( ClusterId..".posY" )	  -- Y-Position des Zentrums
    }
end

-- Liefert die ClusterId eines Systems. Ist der Parameter 'SystemId'
-- nicht vorhanden, wird die ClusterId des aktuellen Systems geliefert.
MissionLib.GetStarClusterId = function( SystemId )
    if not SystemId then
        return get( CLUSTER_HANDLE ) - 2490368
    end
    return get( "Logic.StarSystems."..SystemId..".clusterId" ) - 2490368
end

-- Liefert das ClusterHandle eines Systems. Ist der Parameter 'SystemId'
-- nicht vorhanden, wird das ClusterHandle des aktuellen Systems geliefert.
MissionLib.GetStarClusterHandle = function( SystemId )
    if not SystemId then
        return get( CLUSTER_HANDLE )
    end
    return get( "Logic.StarSystems."..SystemId..".clusterId" )
end

-- Liefert die Anzahl der Sternsysteme eines Clusters.
MissionLib.GetClusterStarsCount = function( ClusterId )
    return get( "Logic.Clusters."..ClusterId..".stars", 0 )
end

-- Liefert die Nation/Rasse eines Clusters (0-5, Konstante RACE_HUMAN..RACE_THUL)
MissionLib.GetStarClusterNation = function( ClusterId )
    return get( "Logic.Clusters."..ClusterId..".nation" )
end

-- X- und Y-Position eines Clusterzentrums auf der Sternenkarte in Lichtjahren (table[2]:float)
MissionLib.GetStarClusterPos = function( ClusterId )
    ClusterId = "Logic.Clusters."..ClusterId
    return { get( ClusterId..".posX" ), get( ClusterId..".posY" ) }
end

-- Liefert die System-IDs vom ersten und letzten Sternsystem eines Clusters.
-- Ist 'ClusterId' nicht angegeben oder ungültig, wird der aktuelle Cluster verwendet.
-- GetStarClusterSystemRange( ClusterId ) : { First, Last, Special }
MissionLib.GetStarClusterSystemRange = function( ClusterId )
    local lastSystem = { [0] = -1;
         11, 19, 25, 40, 61, 68, 88,114,127,132,145,170,178,191,204,
        219,241,257,264,269,293,312,325,339,343,359,367,377,395,399
    }
    if not ClusterId then
        ClusterId = MissionLib.GetStarClusterId()
    elseif ClusterId > 29 then
        ClusterId = ClusterId - 2490368
    end
    local systems = {
        First = lastSystem[ClusterId] + 1,
        Last  = lastSystem[ClusterId + 1]
    }
    -- Die Indicés der 3 zerstörten Systeme fallen aus der Reihe und stehen am Ende
    if ClusterId == 12 then		-- Raptor Delta:
        systems.Special = { 402 }	--  Permakin
    elseif ClusterId == 24 then		-- Hive-B52:
        systems.Special = { 400, 401 }	--  Kajudeng, Metojang
    end
    return systems
end

-- Liefert eine Tabelle mit der automatischen Rassenverteilung (in %) eines Clusters.
-- Ist 'ClusterId' nicht angegeben oder ungültig, wird die Verteilung im aktuellen Cluster geliefert.
-- GetRaceAllocation( ClusterId ) : { Human, Mortok, Raptor, Octo, Arrack, Thul, All }
MissionLib.GetRaceAllocation = function( ClusterId )
    if not ClusterId then
        ClusterId = MissionLib.GetStarClusterId()
    elseif ClusterId > 29 then
        ClusterId = ClusterId - 2490368
    end
    -- Tabelle der Rassenverteilung des Clusters kopieren, die Indicés entsprechen den Rassen
    local alloc = RACE_ALLOCATION[ClusterId]
    return {
        Human  = alloc[0],
        Mortok = alloc[1],
        Raptor = alloc[2],
        Octo   = alloc[3],
        Arrack = alloc[4],
        Thul   = alloc[5],
        All    = MissionLib.CopyTable( alloc )
    }
end

-- Liefert die IDs der ansässigen Piratengangs eines Clusters. Ist 'ClusterId'
-- nicht angegeben oder ungültig, werden die Gang-IDs des aktuellen Clusters geliefert.
MissionLib.GetStarClusterGangs = function( ClusterId )
    local gangs = { [0] =
    { 0, 1 };		-- Lalande
    { 2 },			-- Barnard
    { 47 },			-- Tau Ceti
    { 3, 4 },		-- Alpha Centauri
    { 5, 6, 7, 8, 10, 11 },	-- Grotok
    { 9 },			-- Pertok
    { 12, 13 },		-- Stromok
    { 14, 15, 16, 17 },	-- Klatok
    { 48 },			-- Humok
    { 49 },			-- Raptor Alpha
    { 18, 19, 20 },		-- Raptor Nova
    { 21, 22 },		-- Raptor Gamma
    { 23, 24 },		-- Raptor Delta
    { 25, 26 },		-- Raptor Epsilon
    { 27, 28 },		-- Sion'nach
    { 29, 30 },		-- Sirius
    { 31 },			-- Madra'mor
    { 50 },			-- Prea'chan
    { 51 },			-- Ross 128
    { 52 },			-- Bear'mor
    { 32, 33 },		-- Gab'har
    { 34, 35, 36 },		-- Hive-AC3
    { 53 },			-- Hive-F17
    { 37, 38, 39 },		-- Hive-CU7
    {},			-- Hive-B52
    { 40, 41, 42 },		-- Hive-DC
    {},			-- Hive-ET9
    { 54 },			-- Hive-G8
    { 43, 44, 45, 46 },	-- Communa
    {}			-- Hyma
    }
    if not ClusterId then
        ClusterId = MissionLib.GetStarClusterId()
    elseif ClusterId > 29 then
        ClusterId = ClusterId - 2490368
    end
    return gangs[ClusterId]
end

-- Liefert die StringId für einen Clusternamen aus der global.res.
-- 'ClusterId' darf sowohl die Id als auch das Handle des Clusters sein.
-- Ist 'ClusterId' nicht angegeben oder ungültig, wird der aktuelle Cluster verwendet.
MissionLib.GetClusterName = function( ClusterId )
    if not ClusterId then
        ClusterId = MissionLib.GetStarClusterId()
    elseif ClusterId > 29 then
        ClusterId = ClusterId - 2490368
    end
    return "ID_CLUSTER_"..ClusterId
end

-- Liefert die StringId für einen Clannamen aus der global.res.
-- Ist 'ClusterId' nicht angegeben oder ungültig, wird der aktuelle Cluster verwendet.
MissionLib.GetClanName = function( ClusterId )
    if not ClusterId then
        ClusterId = MissionLib.GetStarClusterId()
    elseif ClusterId > 29 then
        ClusterId = ClusterId - 2490368
    end
    return "IDM_CLANNAME_CLUSTER_"..ClusterId
end

-- Liefert eine Tabelle mit den StringId's der 3 Konzernnamen des Clusters.
-- Den vierten Namen gibt es in einigen Clustern nur in der Mod „Versteckte Cluster”.
-- Ist 'ClusterId' nicht angegeben oder ungültig, wird der aktuelle Cluster verwendet.
MissionLib.GetCombineNames = function( ClusterId )
    if not ClusterId then
        ClusterId = MissionLib.GetStarClusterId()
    elseif ClusterId > 29 then
        ClusterId = ClusterId - 2490368
    end
    if ClusterId < 10 then ClusterId = "0"..ClusterId; end
    local name = "IDL_TRADER_"..ClusterId.."_0"
    return { name..0, name..1, name..2, name..3 }
end

-- Verbietet den Sprung in andere Cluster. Nur im "Tutorial"-Event verwenden!
-- Dem Parameter 'Event' muss der Tutorial-Parameter "Data.Element" und optional
-- kann eine StringId in 'Message' für eine anzuzeigende Nachricht übergeben werden.
MissionLib.LockClusterJump = function( Event, Message )
    if Event == TUTORIAL_ONCLOSE_NAVMAP then
        local target = MissionLib.GetPlayerJumpDestination()
        if MissionLib.GetStarClusterId( target ) ~= MissionLib.GetStarClusterId() then
            NPlayer.LockHyperJump( LOCK )
            GLOBALS.ClusterLocked = true
            if Message then
                NGUI.ShowInfoText( { Text = Message, Replace = { "ID_SYSTEMNAME_"..target } } )
            end

        elseif GLOBALS.ClusterLocked then
            NPlayer.LockHyperJump( UNLOCK )
            GLOBALS.ClusterLocked = nil
        end
    end
end

--============================[ Orbiter ]=======================================

-- Prüft, ob das Objekt ein Orbiter ist
MissionLib.IsOrbiter = function( Object )
    if get( "Logic.Orbiter."..Object..".objecttype", nil ) then
        return 1
    end
end

-- Liefert den Spacetyp (Objecttype) eines Orbiters
MissionLib.GetOrbiterSpaceType = function( Object )
    return get( "Logic.Orbiter."..Object..".objecttype", nil )
end

-- Liefert den Objekttyp (Orbiterart) eines Orbiters
MissionLib.GetOrbiterType = function( Object )
    if get( "Logic.Orbiter."..Object..".objecttype", nil ) then
        return get( "Logic.Orbiter."..Object..".orbiterart" )
    end
end

-- Liefert Spacetyp ("objecttype") und Objekttyp ("orbiterart") eines Orbiters
MissionLib.GetOrbiterTypes = function( Object )
    local orbiter = get( "Logic.Orbiter."..Object..".objecttype", nil )
    if orbiter then
        return {
            SpaceType = orbiter,
            ObjectType = get( "Logic.Orbiter."..Object..".orbiterart" )
        }
    end
end

-- Liefert das Handle eines Orbiters
MissionLib.GetOrbiterHandle = function( Object )
    return get( "Logic.Orbiter."..Object..".id" )
end

-- Liefert die Id eines Orbiters (Datensatzindex in Planets.ini)
-- Sollte nicht verwendet werden, da sich der Index durch Mods ändern kann.
MissionLib.GetOrbiterId = function( Object )
    return get( "Logic.Orbiter."..Object..".iniindex" )
end

-- Prüft, ob der Orbiter ein Asteroid, eine Forschungsstation oder eine Handelsstation ist
MissionLib.IsStation = function( Orbiter )
    if get( "Logic.Orbiter."..Orbiter..".objecttype", nil ) then
        local type = get( "Logic.Orbiter."..Orbiter..".orbiterart" )
        if type == OBJTYPE_ASTEROID or type == OBJTYPE_STATION or type == OBJTYPE_BASE then
            return 1
        end
    end
end

-- Prüft, ob der Orbiter ein Planet ist (ohne Lavaplaneten oder Planetenringe)
-- SPACE_PLANET liefert Planeten und Monde, daher müssen die Monde herausgefiltert werden
MissionLib.IsPlanet = function( Orbiter )
    if  get( "Logic.Orbiter."..Orbiter..".objecttype", nil ) == SPACE_PLANET
    and get( "Logic.Orbiter."..Orbiter..".orbiterart" ) ~= OBJTYPE_MOON then
        return 1
    end
end

-- Prüft, ob der Orbiter ein Lavaplanet oder Planetenring ist
MissionLib.IsSpecialPlanet = function( Orbiter )
    if get( "Logic.Orbiter."..Orbiter..".objecttype", nil ) == SPACE_SPECIALPLANET then
        return 1
    end
end

-- Prüft, ob der Orbiter ein Planet ist, einschließlich Lavaplaneten und Planetenringe
MissionLib.IsPlanetEx = function( Orbiter )
    local planet = get( "Logic.Orbiter."..Orbiter..".objecttype", nil )
    if planet == SPACE_SPECIALPLANET
    or ( planet == SPACE_PLANET and get( "Logic.Orbiter."..Orbiter..".orbiterart" ) ~= OBJTYPE_MOON ) then
        return 1
    end
end

-- Prüft, ob der Orbiter ein Mond ist
MissionLib.IsMoon = function( Orbiter )
    if  get( "Logic.Orbiter."..Orbiter..".objecttype", nil ) == SPACE_PLANET
    and get( "Logic.Orbiter."..Orbiter..".orbiterart" ) == OBJTYPE_MOON then
        return 1
    end
end

-- Holt die Position eines bestimmten Orbiters (ist viel langsamer als NObject.GetPosition)
MissionLib.GetOrbiterPos = function( Orbiter )
    if Orbiter then
        Orbiter = "Logic.Orbiter."..Orbiter
        return {
            get( Orbiter..".posX", nil ),
            get( Orbiter..".posY", nil ),
            get( Orbiter..".posZ", nil )
        }
    end
end

-- Liefert die Position eines Orbiters vom angegebenen Typ (OBJTYPE_TRADESTATION .. OBJTYPE_BASESHIP)
-- Wurde kein Index übergeben oder ist er <= 1, liefert die Funktion die Position vom ersten Orbiter.
MissionLib.GetSystemOrbiterPos = function( OrbiterType, Index )
    if Index and Index > 0 then Index = Index - 1 else Index = 0; end
    local object = NStarSystem.GetOrbiter( { Type = OrbiterType, Index = Index, Mode = 0 } )
    if object.Valid then
        return NObject.GetPosition( { Object = object.Orbiter } ).Position
    end
end

-- Liefert die Position des Orbiters, wo die Piratengang beheimatet ist. Die Gang muss nicht da sein.
MissionLib.GetPirateFieldPos = function()
    return NObject.GetPosition( { Object = NStarSystem.GetPirateField({}).Orbiter } ).Position
end

-- Liefert den Radius der Hüllkugel eines Orbiters.
MissionLib.GetOrbiterRadius = function( Orbiter )
    return get( "Logic.Orbiter."..Orbiter..".radius", 0 )
end

-- Liefert eine Tabelle mit dem gemeinsamen Zentrum (Schwerpunkt) von mehreren Orbitern,
-- dem Radius der gemeinsamen Hüllkugel, die von diesen Orbitern gebildet wird,
-- sowie den Positionen und Hüllkugelradien jedes einzelnen Orbiters.
-- Rückgabetabelle: { Center:table[3], Radius:float, OrbiterCenter:table[n], OrbiterRadius:table[n] }
MissionLib.GetOrbiterCluster = function( OrbiterList )
    local count = lua.sizeof( OrbiterList )
    if count > 0 then
        local radiusTable = {}
        local vectorTable = {}
        local x, y, z = 0.0, 0.0, 0.0
        -- Positionen und Radien der Orbiter sammeln und alle Vektoren addieren
        for i, orbiter in OrbiterList do
            local pos = NObject.GetPosition( { Object = orbiter } ).Position
            radiusTable[i] = get( "Logic.Orbiter."..orbiter..".radius", 0 )
            vectorTable[i] = pos
            x, y, z = x + pos[1], y + pos[2], z + pos[3]
        end
        -- Gemeinsames Zentrum berechnen
        local x0, y0, z0 = x / count, y / count, z / count
        -- Gemeinsamen Hüllkugelradius berechnen
        local radius = 0
        for i, pos in vectorTable do
            -- Relative Position des Orbiters zum gemeinsamen Zentrum
            local x, y, z = pos[1] - x0, pos[2] - y0, pos[3] - z0
            -- Relative Vektorlänge + Hüllkugelradius des Orbiters
            local length = math.sqrt( x * x + y * y + z * z ) + radiusTable[i]
            -- Größten Radius merken
            if length > radius then radius = length; end
        end
        return {
            Center = { x0, y0, z0 },        -- Zentrum der gemeinsamen Hüllkugel
            Radius = radius,                -- Radius der gemeinsamen Hüllkugel
            OrbiterCenter = vectorTable,    -- Tabelle mit den Positionen aller Orbiter
            OrbiterRadius = radiusTable     -- Tabelle mit den Hüllkugelradien aller Orbiter
        }
    end
end

-- Liefert die Entfernung des Mondmittelpunkts zur Planetenoberfläche und den zugehörigen Planeten.
-- Syntax: V.Orbit = MissionLib.GetMoonOrbit( Moon ) : { Distance, Planet }
MissionLib.GetMoonOrbit = function( Moon )
    local planet
    for i, orbiter in MissionLib.GetSystemPlanetsAndMoons() do
        if get( "Logic.Orbiter."..orbiter..".orbiterart" ) ~= OBJTYPE_MOON then
            planet = orbiter
        elseif orbiter == Moon then
            local distance = MissionLib.GetObjectDistance( Moon, planet )
            local radius = get( "Logic.Orbiter."..planet..".radius", 0 )
            return { Distance = distance - radius, Planet = planet }
        end
    end
end

-- Liefert den vom angegebenen Mond umkreisten Planeten.
MissionLib.GetPlanetOfMoon = function( Moon )
    local planet
    for i, orbiter in MissionLib.GetSystemPlanetsAndMoons() do
        if get( "Logic.Orbiter."..orbiter..".orbiterart" ) ~= OBJTYPE_MOON then
            planet = orbiter
        elseif orbiter == Moon then
            return planet
        end
    end
end

-- Liefert eine Tabelle mit allen Monden des angegebenen Planeten und deren Anzahl.
-- Syntax: V.Moons = MissionLib.GetPlanetMoons( Planet ) : { List, Count }
MissionLib.GetPlanetMoons = function( Planet )
    local moons
    local count = 0
    for i, orbiter in MissionLib.GetSystemPlanetsAndMoons() do
        if moons then
            if get( "Logic.Orbiter."..orbiter..".orbiterart" ) == OBJTYPE_MOON then
                count = count + 1
                moons[count] = orbiter
            else
                break
            end
        elseif orbiter == Planet then
            moons = {}
        end
    end
    return { List = moons, Count = count }
end

-- Prüft, ob ein Orbiter bestimmten Typs im aktuellen System existiert (mit Spezialplaneten)
MissionLib.ExistOrbiter = function( OrbiterType )
    return NStarSystem.GetOrbiter( { Type = OrbiterType, Index = 0, Mode = 0 } ).Valid
end

-- Prüft, ob alle in der Tabelle genannten Orbitertypen im aktuellen System existieren (mit Spezialplaneten)
MissionLib.ExistOrbiters = function( OrbiterTypeTable )
    for i, objtype in OrbiterTypeTable do
        if not NStarSystem.GetOrbiter( { Type = objtype, Index = 0, Mode = 0 } ).Valid then
            return
        end
    end
    return 1
end

-- Prüft, ob keiner der genannten Orbitertypen im aktuellen System existiert (mit Spezialplaneten)
MissionLib.ExistNoOrbiters = function( OrbiterTypeTable )
    for i, objtype in OrbiterTypeTable do
        if NStarSystem.GetOrbiter( { Type = objtype, Index = 0, Mode = 0 } ).Valid then
            return
        end
    end
    return 1
end

-- Prüft, ob eine Handelsstation im aktuellen System existiert
MissionLib.ExistTradeStation = function()
    if NStarSystem.GetTradeStation({}).Handle > 0 then
        return 1
    end
end

-- Prüft, ob eine Forschungsstation im aktuellen System existiert
MissionLib.ExistResearchStation = function()
    return MissionLib.ExistOrbiter( OBJTYPE_STATION )
end

-- Prüft, ob ein Asteroid im aktuellen System existiert
MissionLib.ExistAsteroid = function()
    return MissionLib.ExistOrbiter( OBJTYPE_ASTEROID )
end

-- Prüft, ob eine Anomalie im aktuellen System existiert
MissionLib.ExistAnomalie = function()
    if NObject.GetAnomalie({}).Handle > 0 then
        return 1
    end
end

-- Prüft, ob ein Meteoritenfeld im aktuellen System existiert
MissionLib.ExistMeteorid = function()
    return MissionLib.ExistOrbiter( OBJTYPE_METEOR )
end

-- Prüft, ob eine Dekoration (Schiffswrack) im aktuellen System existiert
MissionLib.ExistDecoration = function()
    return MissionLib.ExistOrbiter( OBJTYPE_DECORATION )
end

-- Prüft, ob eine Werbetafel im aktuellen System existiert
MissionLib.ExistDisplay = function()
    return MissionLib.ExistOrbiter( OBJTYPE_DISPLAY )
end

-- Prüft, ob eine Piratenbasis im aktuellen System existiert
MissionLib.ExistPirateBase = function()
    return MissionLib.ExistOrbiter( OBJTYPE_BASESHIP )
end

-- Prüft, ob ein Agrarplanet im aktuellen System existiert
MissionLib.ExistAgriPlanet = function()
    return MissionLib.ExistOrbiter( OBJTYPE_PLANETBG )
end

-- Prüft, ob ein Gasriese im aktuellen System existiert
MissionLib.ExistGasPlanet = function()
    return MissionLib.ExistOrbiter( OBJTYPE_PLANETGR )
end

-- Prüft, ob ein Technikplanet im aktuellen System existiert
MissionLib.ExistTechPlanet = function()
    return MissionLib.ExistOrbiter( OBJTYPE_PLANETTC )
end

-- Prüft, ob ein Lavaplanet oder Planetenring im aktuellen System existiert
MissionLib.ExistSpecialPlanet = function()
    for i, orbiter in NStarSystem.ListOrbiters({}).OrbiterList do
        if get( "Logic.Orbiter."..orbiter..".objecttype" ) == SPACE_SPECIALPLANET then
            return 1
        end
    end
end

-- Prüft, ob ein Mond im aktuellen System existiert
MissionLib.ExistMoon = function()
    return MissionLib.ExistOrbiter( OBJTYPE_MOON )
end

-- Prüft, ob ein Komet im aktuellen System existiert
MissionLib.ExistKomet = function()
    return MissionLib.ExistOrbiter( OBJTYPE_KOMET )
end

-- Prüft, ob ein schwarzes Loch im aktuellen System existiert
MissionLib.ExistBlackHole = function()
    return MissionLib.ExistOrbiter( OBJTYPE_BLACKHOLE )
end

--------------------------------------------------------------------------------

-- Sucht die erste Sonne im aktuellen System
MissionLib.GetSystemSun = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_SUN )
end

-- Sucht den ersten Planet im aktuellen System (ohne Spezialplaneten)
MissionLib.GetSystemPlanet = function()
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    -- NStarSystem.ListOrbiters liefert absteigend sortierte Listen,
    -- die am weitesten entfernten Objekte stehen also oben. Umdrehen!
    for i = lua.getn( orbiters ), 1, -1 do
        if MissionLib.IsPlanet( orbiters[i] ) then
            return orbiters[i]
        end
    end
end

-- Sucht den der Handelsstation am nächsten stehenden Planet im aktuellen System (ohne Spezialplaneten).
-- Meistens ist das zwar auch der erste Planet im System, allerdings nicht immer!
MissionLib.GetFirstSystemPlanet = function()
    local distMin = 1000000
    local planet
    for i, orbiter in NStarSystem.ListOrbiters({}).OrbiterList do
        if MissionLib.IsPlanet( orbiter ) then
            local pos = NObject.GetPosition( { Object = orbiter } ).Position
            local dist = MissionLib.GetVectorLength( pos )
            if dist < distMin then
                distMin = dist
                planet = orbiter
            end
        end
    end
    return planet
end

-- Sucht den ersten Agrarplanet (BG) im aktuellen System
MissionLib.GetSystemAgriPlanet = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_PLANETBG )
end

-- Sucht den ersten Gasriesen (GR) im aktuellen System
MissionLib.GetSystemGasPlanet = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_PLANETGR )
end

-- Sucht den ersten Technikplanet (TC) im aktuellen System
MissionLib.GetSystemTechPlanet = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_PLANETTC )
end

-- Sucht den ersten Lavaplanet oder Planetenring (SPACE_SPECIALPLANET) im aktuellen System
MissionLib.GetSystemSpecialPlanet = function()
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    for i = lua.getn( orbiters ), 1, -1 do
        if get( "Logic.Orbiter."..orbiters[i]..".objecttype" ) == SPACE_SPECIALPLANET then
            return orbiters[i]
        end
    end
end

-- Sucht den ersten Mond im aktuellen System
MissionLib.GetSystemMoon = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_MOON )
end

-- Sucht das erste schwarze Loch im aktuellen System
MissionLib.GetSystemBlackHole = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_BLACKHOLE )
end

-- Sucht den ersten Komet im aktuellen System
MissionLib.GetSystemKomet = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_KOMET )
end

-- Sucht die erste Dekoration (Schiffswracks) im aktuellen System
MissionLib.GetSystemDecoration = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_DECORATION )
end

-- Sucht die erste Werbetafel im aktuellen System
MissionLib.GetSystemDisplay = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_DISPLAY )
end

-- Sucht die erste Piratenbasis im aktuellen System
MissionLib.GetSystemPirateBase = function()
    return MissionLib.GetSystemOrbiter( OBJTYPE_BASESHIP )
end

--------------------------------------------------------------------------------

-- Sucht einen bestimmten Orbiter im aktuellen System (Index >= 1, mit Spezialplaneten)
MissionLib.GetSystemOrbiterNr = function( OrbiterType, Index )
    if Index > 0 then
        local object = NStarSystem.GetOrbiter( { Type = OrbiterType, Index = Index-1, Mode = 0 } )
        if object.Valid then
            return object.Orbiter
        end
    end
end

-- Sucht eine bestimmte Forschungsstation im aktuellen System
MissionLib.GetSystemResearchStationNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_STATION, Index )
end

-- Sucht einen bestimmten Asteroiden im aktuellen System
MissionLib.GetSystemAsteroidNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_ASTEROID, Index )
end

-- Sucht eine bestimmte Anomalie im aktuellen System
MissionLib.GetSystemAnomalieNr = function()
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_ANOMALIE, Index )
end

-- Sucht ein bestimmtes Meteoritenfeld im aktuellen System
MissionLib.GetSystemMeteoridNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_METEOR, Index )
end

-- Sucht eine bestimmte Sonne im aktuellen System
MissionLib.GetSystemSunNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_SUN, Index )
end

-- Sucht einen bestimmten Agrarplaneten (BG) im aktuellen System
MissionLib.GetSystemAgriPlanetNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_PLANETBG, Index )
end

-- Sucht einen bestimmten Gasriesen (GR) im aktuellen System
MissionLib.GetSystemGasPlanetNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_PLANETGR, Index )
end

-- Sucht einen bestimmten Technikplaneten (TC) im aktuellen System
MissionLib.GetSystemTechPlanetNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_PLANETTC, Index )
end

-- Sucht einen bestimmten Mond im aktuellen System
MissionLib.GetSystemMoonNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_MOON, Index )
end

-- Sucht ein bestimmtes schwarzes Loch im aktuellen System
MissionLib.GetSystemBlackHoleNr = function(Index)
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_BLACKHOLE, Index )
end

-- Sucht einen bestimmten Kometen im aktuellen System
MissionLib.GetSystemKometNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_KOMET, Index )
end

-- Sucht eine bestimmte Dekoration (Schiffswrack) im aktuellen System
MissionLib.GetSystemDecorationNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_DECORATION, Index )
end

-- Sucht eine bestimmte Werbetafel im aktuellen System
MissionLib.GetSystemDisplayNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_DISPLAY, Index )
end

-- Sucht eine bestimmte Piratenbasis im aktuellen System
MissionLib.GetSystemPirateBaseNr = function( Index )
    return MissionLib.GetSystemOrbiterNr( OBJTYPE_BASESHIP, Index )
end

--------------------------------------------------------------------------------

-- Listet alle Orbiter im aktuellen System auf und liefert deren Typen in aufsteigender Reihenfolge
-- (ListOrbiters liefert die Orbiter in umgekehrter Reihenfolge als in der Planets.ini definiert)
MissionLib.ListSystemOrbiters = function()
    local orbiterlist = {}
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    local i = 0
    for j = lua.getn( orbiters ), 1, -1 do
        i = i + 1
        orbiterlist[i] = get( "Logic.Orbiter."..orbiters[j]..".orbiterart" )
    end
    return orbiterlist
end

-- Listet alle Orbiter im aktuellen System auf und liefert deren Handles in aufsteigender Reihenfolge
MissionLib.ListSystemOrbiterHandles = function()
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    local i = 1
    local j = lua.getn( orbiters )
    -- In aufsteigender Reihenfolge zurückliefern
    while i < j do
        orbiters[i], orbiters[j] = orbiters[j], orbiters[i]
        i = i + 1
        j = j - 1
    end
    return orbiters
end

-- Liefert eine Tabelle mit den Handles, Space- und Objekttypen von allen Orbitern im System
-- GetSystemOrbitersData() : table[n: { Handle, SpaceType, ObjectType }]
MissionLib.GetSystemOrbitersData = function()
    local orbiterlist = {}
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    local i = 0
    for j = lua.getn( orbiters ), 1, -1 do
        i = i + 1
        local orbiter = orbiters[j]
        orbiterlist[i] = {
            Handle = orbiter,
            SpaceType = get( "Logic.Orbiter."..orbiter..".objecttype" ),
            ObjectType = get( "Logic.Orbiter."..orbiter..".orbiterart" )
        }
    end
    return orbiterlist
end

-- Diese Funktionen suchen alle Orbiter eines bestimmten Typs im System und liefern deren IDs
-- Beispiel:
--   V.Asteroids = MissionLib.GetSystemOrbiters( OBJTYPE_ASTEROID )	-- Liste aller Asteroiden
--   V.Asteroids = MissionLib.GetSystemAsteroids()			-- Dasselbe wie oben
--   V.AstrCount = lua.sizeof( V.Asteroids )				-- Anzahl der Asteroiden
--   V.Asteroid2 = V.Asteroids[2]					-- Der zweite Asteroid
-- (MissionLib.GetSystemOrbiters -> mit Spezialplaneten)
MissionLib.GetSystemOrbiters = function( OrbiterType )
    local orbiterlist = {}
    local i = 0
    repeat
        local object = NStarSystem.GetOrbiter( { Type = OrbiterType, Index = i, Mode = 0 } )
        if object.Valid then
            i = i + 1
            orbiterlist[counter] = object.Orbiter
        elseif i > 0 then
            return orbiterlist
        else
            return
        end
    until nil
end

-- Sucht alle Forschungsstationen im aktuellen System
MissionLib.GetSystemResearchStations = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_STATION )
end

-- Sucht alle Asteroiden im aktuellen System
MissionLib.GetSystemAsteroids = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_ASTEROID )
end

-- Sucht alle Anomalien im aktuellen System
MissionLib.GetSystemAnomalies = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_ANOMALIE )
end

-- Sucht alle Meteoritenfelder im aktuellen System
MissionLib.GetSystemMeteorids = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_METEOR )
end

-- Sucht alle Sonnen im aktuellen System
MissionLib.GetSystemSuns = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_SUN )
end

-- Sucht alle Planeten und Monde im aktuellen System (ohne Spezialplaneten)
MissionLib.GetSystemPlanetsAndMoons = function()
    local orbiterlist = {}
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    local i = 0
    for j = lua.getn( orbiters ), 1, -1 do
        -- Der Objekttyp SPACE_PLANET liefert sowohl Planeten als auch Monde
        if get( "Logic.Orbiter."..orbiters[j]..".objecttype" ) == SPACE_PLANET then
            i = i + 1
            orbiterlist[i] = orbiters[j]
        end
    end
    return orbiterlist
end

-- Sucht alle Planeten im aktuellen System (ohne Spezialplaneten)
MissionLib.GetSystemPlanets = function()
    local orbiterlist = {}
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    local i = 0
    for j = lua.getn( orbiters ), 1, -1 do
        if MissionLib.IsPlanet( orbiters[j] ) then
            i = i + 1
            orbiterlist[i] = orbiters[j]
        end
    end
    return orbiterlist
end

-- Sucht alle Agrarplaneten (BG) im aktuellen System (mit Spezialplaneten)
MissionLib.GetSystemAgriPlanets = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_PLANETBG )
end

-- Sucht alle Gasriesen (GR) im aktuellen System (mit Spezialplaneten)
MissionLib.GetSystemGasPlanets = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_PLANETGR )
end

-- Sucht alle Technikplaneten (TC) im aktuellen System (mit Spezialplaneten)
MissionLib.GetSystemTechPlanets = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_PLANETTC )
end

-- Sucht alle Lavaplaneten und Planetenringe (SPACE_SPECIALPLANET) im aktuellen System
MissionLib.GetSystemSpecialPlanets = function()
    local orbiterlist = {}
    local orbiters = NStarSystem.ListOrbiters({}).OrbiterList
    local i = 0
    for j = lua.getn( orbiters ), 1, -1 do
        if get( "Logic.Orbiter."..orbiters[j]..".objecttype" ) == SPACE_SPECIALPLANET then
            i = i + 1
            orbiterlist[i] = orbiters[j]
        end
    end
    return orbiterlist
end

-- Sucht alle Monde im aktuellen System
MissionLib.GetSystemMoons = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_MOON )
end

-- Sucht alle schwarzen Löcher im aktuellen System
MissionLib.GetSystemBlackHoles = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_BLACKHOLE )
end

-- Sucht alle Kometen im aktuellen System
MissionLib.GetSystemKomets = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_KOMET )
end

-- Sucht alle Dekorationen (Schiffswracks) im aktuellen System
MissionLib.GetSystemDecorations = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_DECORATION )
end

-- Sucht alle Werbetafeln im aktuellen System
MissionLib.GetSystemDisplays = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_DISPLAY )
end

-- Sucht alle Piratenbasen im aktuellen System
MissionLib.GetSystemPirateBases = function()
    return MissionLib.GetSystemOrbiters( OBJTYPE_BASESHIP )
end

--------------------------------------------------------------------------------

-- Anzahl aller Orbiter (alle Typen) im aktuellen System
MissionLib.GetSystemOrbitersCount = function()
    return lua.getn( NStarSystem.ListOrbiters({}).OrbiterList )
end

-- Anzahl aller Forschungsstationen im aktuellen System
MissionLib.GetSystemResearchStationCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_STATION )
end

-- Anzahl aller Asteroiden im aktuellen System
MissionLib.GetSystemAsteroidCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_ASTEROID )
end

-- Anzahl aller Anomalien im aktuellen System
MissionLib.GetSystemAnomalieCount = function()
    return MissionLib.GetSystemOrbiterCount( ORBITART_ANOMALIE )
end

-- Anzahl aller Meteoritenfelder im aktuellen System
MissionLib.GetSystemMeteoridCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_METEOR )
end

-- Anzahl aller Sonnen im aktuellen System
MissionLib.GetSystemSunCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_SUN )
end

-- Anzahl aller Planeten und Monde im aktuellen System (ohne Spezialplaneten)
MissionLib.GetSystemPlanetAndMoonCount = function()
    local counter = 0
    for i, object in NStarSystem.ListOrbiters({}).OrbiterList do
        if get( "Logic.Orbiter."..object..".objecttype" ) == SPACE_PLANET then
            counter = counter + 1
        end
    end
    return counter
end

-- Anzahl aller Planeten im aktuellen System (ohne Spezialplaneten)
MissionLib.GetSystemPlanetCount = function()
    local counter = 0
    for i, object in NStarSystem.ListOrbiters({}).OrbiterList do
        if MissionLib.IsPlanet( object ) then
            counter = counter + 1
        end
    end
    return counter
end

-- Anzahl aller Agrarplaneten (BG) im aktuellen System (mit Spezialplaneten)
MissionLib.GetSystemAgriPlanetCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_PLANETBG )
end

-- Anzahl aller Gasriesen (GR) im aktuellen System (mit Spezialplaneten)
MissionLib.GetSystemGasPlanetCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_PLANETGR )
end

-- Anzahl aller Technikplaneten (TC) im aktuellen System (mit Spezialplaneten)
MissionLib.GetSystemTechPlanetCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_PLANETTC )
end

-- Anzahl aller Lavaplaneten und Planetenringe im aktuellen System
MissionLib.GetSystemSpecialPlanetCount = function()
    local counter = 0
    for i, object in NStarSystem.ListOrbiters({}).OrbiterList do
        if get( "Logic.Orbiter."..object..".objecttype" ) == SPACE_SPECIALPLANET then
            counter = counter + 1
        end
    end
    return counter
end

-- Anzahl aller Monde im aktuellen System
MissionLib.GetSystemMoonCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_MOON )
end

-- Anzahl aller schwarzen Löcher im aktuellen System
MissionLib.GetSystemBlackHoleCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_BLACKHOLE )
end

-- Anzahl aller Kometen im aktuellen System
MissionLib.GetSystemKometCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_KOMET )
end

-- Anzahl aller Dekorationen (Schiffswracks) im aktuellen System
MissionLib.GetSystemDecorationCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_DECORATION )
end

-- Anzahl aller Werbetafeln im aktuellen System
MissionLib.GetSystemDisplayCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_DISPLAY )
end

-- Anzahl aller Piratenbasen im aktuellen System
MissionLib.GetSystemPirateBaseCount = function()
    return MissionLib.GetSystemOrbiterCount( OBJTYPE_BASESHIP )
end

--------------------------------------------------------------------------------

-- Liefert die StringId (aus user_strings.res) für die Bezeichnung des Orbiters
MissionLib.GetOrbiterText = function( OrbiterType )
    if not OrbiterType then
        return "ID_OBJTYPE_NIL"
    end
    if OrbiterType > 15 then
        return "ID_"..OrbiterType
    end
    return "ID_OBJTYPE_"..OrbiterType
end

--============================[ Objekte ]=======================================

-- Liefert true, wenn das Objekt (jede Art) existiert, ansonsten false
MissionLib.IsObject = function( Object )
    if Object and Object ~= NO_OBJECT then
        return 1
    end
end

-- Liefert die ST_<Konstante> eines Objekts ("Wing", "Ship" oder "Orbiter").
-- Wie "MissionLib.GetObjectType", unterscheidet aber jetzt zwischen "Wing" und "Ship".
-- Ist das Objekt unbekannt, liefert die Funktion dessen Datentyp in 'ObjType' zurück.
MissionLib.GetObjectType2 = function( Object )
    if Object then
        local leader = get( "Logic.Wings."..Object..".leader", nil)
        if leader then
            -- es ist ein Wing:
            return { Type = "Wing", ObjType = get( "Logic.StarShips."..leader..".shipType" ) }
        end
        local ship = get( "Logic.StarShips."..Object..".shipType", nil )
        if ship then
            -- es ist ein Schiff:
            return { Type = "Ship", ObjType = ship }
        end
        local objtype = get( "Logic.Orbiter."..Object..".objecttype", nil )
        if objtype then
            local orbiter = get( "Logic.Orbiter."..Object..".orbiterart" )
            if orbiter then
                -- es ist ein Orbiter:
                return { Type = "Orbiter", ObjType = orbiter }
            end
            -- es ist ein anderes Space-Objekt:
            return { Type = "Object", ObjType = objtype }
        end
        -- es ist ein unbekanntes Objekt, Datentyp zurückliefern:
        return { Type = "Unknown", ObjType = lua.type( Object ) }
    end
end

-- Liefert die Position eines Objekts.
MissionLib.GetObjectPos = MissionLib.GetShipPos

-- Liefert eine Tabelle mit allen Positionen im Asteroiden, an denen
-- a) Minenwaren erzeugt werden (auf den Plattformen, wenn der Parameter 'GetPos' = nil ist),
-- b) weitere Objekte erzeugt werden können (über den Plattformen, wenn 'GetPos' ~= nil ist).
-- Der Rückgabewert 'count' enthält die Anzahl der gefundenen Positionen.
MissionLib.GetAsteroidPosTable = function( Asteroid, GetPos )
    if not GetPos then
        GetPos = NObject.GetAsteroidPos
    else
        GetPos = NObject.GetAsteroidPosCont
    end
    local count = 0
    local pos1 = { 0.0, 0.0, 0.0 }
    local posTable = { pos1 }
    repeat
        local pos = GetPos( { Asteroid = Asteroid, Index = count } ).Position
        if pos[1] ~= pos1[1] or pos[2] ~= pos1[2] or pos[3] ~= pos1[3] then
            count = count + 1
            posTable[count] = pos
            if count == 1 then pos1 = pos; end
        else
            return posTable, count  -- es wurden alle Positionen gefunden
        end
    until nil
end

-- Liefert wie "NObject.GetHangarPos" die Position und Ausrichtung eines Hangars zurück,
-- berücksichtigt jedoch auch kleine Kreuzer und setzt deren Hangarposition auf {0,0,0}.
-- Syntax: V.Pos = MissionLib.GetHangarPos( Object ) : { Position, Front, UpDir }
MissionLib.GetHangarPos = function( Object )
    local object = { Object = Object }
    local hangar = NObject.GetHangarPos( object )
    if get( "Logic.StarShips."..Object..".shipType", nil ) == ST_CRUISER then
        local hangarPos = hangar.Position
        for i, shipPos in NObject.GetPosition( object ).Position do
            if shipPos - hangarPos[i] ~= 0.0 then
                return hangar
            end
        end
        hangar.Position = { 0.0, 0.0, 0.0 }
    end
    return hangar
end

-- Liefert Position und Ausrichtung eines Objekts.
-- Zusammenfassung der Funktionen NObject.GetPosition, NObject.GetFrontDir und NObject.GetUpDir.
MissionLib.GetObjectAlignment = function( Object )
    if Object then
        Object = { Object = Object }
        return {
            Pos   = NObject.GetPosition( Object ).Position,
            Front = NObject.GetFrontDir( Object ).FrontDir,
            UpDir = NObject.GetUpDir( Object ).UpDir
        }
    end
end

-- Liefert das Handle des vom Spieler selektierten Objekts.
MissionLib.GetPlayerTarget = function()
    return get( PLAYER_TARGET )
end

-- Ein selektiertes Objekt wird abgewählt und nicht mehr im Zielcomputer angezeigt.
-- Wurde ein 'Object' übergegeben und ist selektiert, wird nur dieses abgewählt.
MissionLib.DeselectTarget = function( Object )
    if not Object or get( PLAYER_TARGET ) == Object then
        NPlayer.SelectTarget( { Object = 0 } )
    end
end

-- Selektiert ein Objekt als Ziel des Spielerschiffs und liefert das bisher angewählte Objekt zurück.
MissionLib.ChangeTarget = function( Object )
    local target = get( PLAYER_TARGET )
    NPlayer.SelectTarget( { Object = Object } )
    return target
end

-- Selektiert ein Objekt als Ziel des Spielerschiffs und setzt die Missionmarkierung darauf.
MissionLib.SelectAsMissionObject = function( Object )
    if Object then
        local target = { Object = Object, Set = 1 }
        NObject.SetMissionFlag( target )
        NPlayer.SelectTarget( target )
    end
end

-- Setzt die Missionmarkierung auf alle Schiffe im Wing und selektiert den Leader als Ziel.
MissionLib.SelectAsMissionWing = function( WingId )
    if WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            NObject.SetMissionFlag( { Object = WingId, Set = 1 } )
            NPlayer.SelectTarget( { Object = leader } )
        end
    end
end

-- Setzt die Missionsmarkierung auf den Leader des Wings.
MissionLib.SetMissionFlagOnLeader = function( WingId )
    if WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            NObject.SetMissionFlag( { Object = leader, Set = 1 } )
        end
    end
end

-- Setzt die Missionsmarkierung auf einen bestimmten Wingman im Wing (Member 1-10).
MissionLib.SetMissionFlagOnMember = function( WingId, Member )
    if WingId then
        local ship = get( "Logic.Wings."..WingId..".ship"..Member, nil )
        if ship then
            NObject.SetMissionFlag( { Object = ship, Set = 1 } )
        end
    end
end

-- Setzt die Missionsmarkierung auf den neuen Leader im Wing, wenn der bisherige Leader zerstört wurde
-- und liefert das Schiffshandle zurück. Optional kann im Index (1-10) anstelle des nächsten Schiffs
-- auch ein anderer Wingman angegeben werden. Ist der Index größer als die noch existierenden Schiffe,
-- liefert die Funktion nil zurück. Achtung: Es wird nicht geprüft, ob der Wing auch vorhanden ist.
MissionLib.SetMissionFlagOnNextMember = function( WingId, Index )
    if not Index then Index = 1; end
    if get( "Logic.Wings."..WingId..".count", 0 ) > Index then
        local wingman = get( "Logic.Wings."..WingId..".ship"..Index )
        NObject.SetMissionFlag( { Object = wingman, Set = 1 } )
        return wingman
    end
end

-- Markiert ein Spaceobjekt (Schiff, Wing, Artefakt oder Orbiter) als Missionsobjekt
-- Syntax: MissionLib.SetMissionFlag( ObjectId )
MissionLib.SetMissionFlag = MissionLib.WingSetAsMissionObject

-- Entfernt die Missionsmarkierung wieder vom Objekt
-- Syntax: MissionLib.ResetMissionFlag( ObjectId )
MissionLib.ResetMissionFlag = MissionLib.WingSetNotMissionObject

-- Markiert mehrere Objekte als Missionsobjekte (Ja: Value=1, Nein: Value=0)
MissionLib.SetMissionFlagOnObjects = function( ObjectList, Value )
    for i, object in ObjectList do
        NObject.SetMissionFlag( { Object = object, Set = Value } )
    end
end

-- Markiert einen Wegpunkt als Missionsobjekt und zeigt ihn an (Ja: Show=1|true, Nein: Show=0|false)
MissionLib.ShowWaypoint = function( Waypoint, Show )
    NWaypoint.Show( { Waypoint = Waypoint, Show = Show } )
    NObject.SetMissionFlag( { Object = Waypoint, Set = Show } )
end

-- Macht einen Wegpunkt sichtbar und wählt ihn an
MissionLib.SelectWaypoint = function( Waypoint )
    NWaypoint.Show( { Waypoint = Waypoint, Show = 1 } )
    NPlayer.SelectTarget( { Object = Waypoint } )
end

------------------------------[ Explosionseffekte ] ----------------------------

-- Tabelle mit allen in der Datei "Explosion.ini" vorhandenen Explosionseffekten.
EXPLOSIONS = { [0] =			-- Tabellenindex und Beschreibung:
    "EXPLOSION_PLAYER_SHIP";		-- 0	JägerA, FrachterA, Grüner Ring	(Explosion012+019+002)
    "EXPLOSION_PLASMA_OVERLOAD",	-- 1	Blitzentladungen		(Explosion000)
    "EXPLOSION_PLASMA_EMP",		-- 2	Schneeschauer Im-/Explosion	(Explosion001)
    "EXPLOSION_PLASMA_TIMESHOCK",	-- 3	Grüner Ring			(Explosion002)
    "EXPLOSION_PLASMA_WEAPON",		-- 4	Schneeschauer Im-/Explosion	(Explosion003)
    "EXPLOSION_PLASMA_SHIELD",		-- 5	Schneeschauer Im-/Explosion	(Explosion004)
    "EXPLOSION_PLASMA_INVUL",		-- 6	Schneeschauer Im-/Explosion	(Explosion037)
    "EXPLOSION_DEBRIS_A",		-- 7	Trümmer, Terraner		(Explosion005)
    "EXPLOSION_DEBRIS_C",		-- 8	Trümmer, Mortok			(Explosion006)
    "EXPLOSION_DEBRIS_B",		-- 9	Trümmer, Raptor			(Explosion007)
    "EXPLOSION_DEBRIS_F",		-- 10	Trümmer, Oc’to			(Explosion008)
    "EXPLOSION_DEBRIS_D",		-- 11	Trümmer, Arrack			(Explosion009)
    "EXPLOSION_DEBRIS_E",		-- 12	Trümmer, Thul			(Explosion010)
    "EXPLOSION_DEBRIS_G",		-- 13	Trümmer, S’kaa			(Explosion011)
    "EXPLOSION_FIGHTER_A",		-- 14	Jäger A, Terraner		(Explosion012)
    "EXPLOSION_FIGHTER_C",		-- 15	Jäger C, Mortok			(Explosion013)
    "EXPLOSION_FIGHTER_B",		-- 16	Jäger B, Raptor			(Explosion014)
    "EXPLOSION_FIGHTER_F",		-- 17	Jäger F, Oc’to			(Explosion015)
    "EXPLOSION_FIGHTER_D",		-- 18	Jäger D, Arrack			(Explosion016)
    "EXPLOSION_FIGHTER_E",		-- 19	Jäger E, Thul			(Explosion017)
    "EXPLOSION_FIGHTER_G",		-- 20	Jäger G, S’kaa			(Explosion018)
    "EXPLOSION_FREIGHTER_A",		-- 21	Frachter A, Terraner		(Explosion019)
    "EXPLOSION_FREIGHTER_C",		-- 22	Frachter C, Mortok		(Explosion020)
    "EXPLOSION_FREIGHTER_B",		-- 23	Frachter B, Raptor		(Explosion021)
    "EXPLOSION_FREIGHTER_F",		-- 24	Frachter F, Oc’to		(Explosion022)
    "EXPLOSION_FREIGHTER_D",		-- 25	Frachter D, Arrack		(Explosion023)
    "EXPLOSION_FREIGHTER_E",		-- 26	Frachter E, Thul		(Explosion024)
    "EXPLOSION_FREIGHTER_G",		-- 27	Frachter G, S’kaa		(Explosion025)
    "EXPLOSION_CRUISER_A_0",		-- 28	Kleiner Kreuzer A, Terraner	(Explosion026)
    "EXPLOSION_CRUISER_C_0",		-- 29	Kleiner Kreuzer C, Mortok	(Explosion027)
    "EXPLOSION_CRUISER_B_0",		-- 30	Kleiner Kreuzer B, Raptor	(Explosion028)
    "EXPLOSION_CRUISER_F_0",		-- 31	Kleiner Kreuzer F, Oc’to	(Explosion029)
    "EXPLOSION_CRUISER_D_0",		-- 32	Kleiner Kreuzer D, Arrack	(Explosion030)
    "EXPLOSION_CRUISER_E_0",		-- 33	Kleiner Kreuzer E, Thul		(Explosion031)
    "EXPLOSION_CRUISER_G_0",		-- 34	Kleiner Kreuzer G, S’kaa	(Explosion032)
    "EXPLOSION_CRUISER_A_1",		-- 35	Großer Kreuzer A, Terraner	(Explosion038)
    "EXPLOSION_CRUISER_C_1",		-- 36	Großer Kreuzer C, Mortok	(Explosion039)
    "EXPLOSION_CRUISER_B_1",		-- 37	Großer Kreuzer B, Raptor	(Explosion040)
    "EXPLOSION_CRUISER_F_1",		-- 38	Großer Kreuzer F, Oc’to		(Explosion041)
    "EXPLOSION_CRUISER_D_1",		-- 39	Großer Kreuzer D, Arrack	(Explosion042)
    "EXPLOSION_CRUISER_E_1",		-- 40	Großer Kreuzer E, Thul		(Explosion043)
    "EXPLOSION_MISSILE_SWARM",		-- 41	Schwarm Rakete			(Explosion033)
    "EXPLOSION_MISSILE_HELLFIRE",	-- 42	Hellfire			(Explosion034)
    "EXPLOSION_MISSILE_BIGBANG",	-- 43	Bigbang				(Explosion035)
    "EXPLOSION_MISSILE_BIGBANG_CENTER",	-- 44	Bigbang mit Zentrumblitz	(Explosion036)
    "EXPLOSION_HIDEOUT",		-- 45	Piratenbasis			(Explosion045)
    "EXPLOSION_METEROID1",		-- 46	Meteoriten aus Stein		(Explosion044)
    "EXPLOSION_METEROID_0",		-- 47	Stein 25m			(Explosion049)
    "EXPLOSION_METEROID_1",		-- 48	Stein 50m			(Explosion050)
    "EXPLOSION_METEROID_5",		-- 49	Stein 75m			(Explosion051)
    "EXPLOSION_METEROID_2",		-- 50	Stein 100m			(Explosion052)
    "EXPLOSION_METEROID_3",		-- 51	Stein 150m			(Explosion053)
    "EXPLOSION_METEROID_4",		-- 52	Stein 750m			(Explosion054)
    "EXPLOSION_MET_DEBRIS1",		-- 53	Meteoriten aus Metall		(Explosion048)
    "EXPLOSION_MET_DEBRIS_0",		-- 54	Trümmerteile 10m		(Explosion055)
    "EXPLOSION_MET_DEBRIS_1",		-- 55	Trümmerteile 25m		(Explosion056)
    "EXPLOSION_MET_DEBRIS_2",		-- 56	Trümmerteile 30m		(Explosion057)
    "EXPLOSION_MET_DEBRIS_3",		-- 57	Trümmerteile 50m		(Explosion058)
    "EXPLOSION_MET_DEBRIS_4",		-- 58	Trümmerteile 75m		(Explosion059)
    "EXPLOSION_MET_DEBRIS_5",		-- 59	Trümmerteile 100m		(Explosion060)
    "EXPLOSION_MET_DEBRIS_6",		-- 60	Trümmerteile 130m		(Explosion061)
    "EXPLOSION_MET_ICE1",		-- 61	Meteoriten aus Eis		(Explosion046)
    "EXPLOSION_MET_ICE_0",		-- 62	Eis 50m				(Explosion062)
    "EXPLOSION_MET_ICE_1",		-- 63	Eis 100m			(Explosion063)
    "EXPLOSION_MET_ICE_2",		-- 64	Eis 150m			(Explosion064)
    "EXPLOSION_MET_CRYSTAL1",		-- 65	Meteoriten aus Kristall		(Explosion047)
    "EXPLOSION_MET_CRYSTAL_0",		-- 66	Kristalle 30m			(Explosion065)
    "EXPLOSION_MET_CRYSTAL_1",		-- 67	Kristalle 50m			(Explosion066)
    "EXPLOSION_MET_CRYSTAL_2",		-- 68	Kristalle 75m			(Explosion067)
    "EXPLOSION_MET_CRYSTAL_3",		-- 69	Kristalle 100m			(Explosion068)
    "EXPLOSION_MET_CRYSTAL_4",		-- 70	Kristalle 130m			(Explosion069)
    "EXPLOSION_PLASMA_EMP_FLASH",	-- 71	Schneeschauer mit Zentrumblitz	(Explosion070)
    "EXPLOSION_MISSILE_SWARM_2" 	-- 72	Schwarm Rak mit dumpfem Knall	(Explosion071)
}

-- Erzeugt einen Explosionseffekt ohne Schadenswirkung an der angegebenen Position.
-- Der Index referenziert den gewünschten Effekt in der Tabelle EXPLOSIONS.
MissionLib.CreateExplosionEffect = function( Position, Index )
    if EXPLOSIONS[Index] then
        NObject.CreateExplosion( { Position = Position, Type = EXPLOSIONS[Index] } )
    end
end

-- Erzeugt mehrere Explosionen an der angegebenen Position mit den Effekten aus 'TypeTable'.
-- Optional kann in 'Damage' und 'Size' Gesamtschaden und Wirkungsradius übergeben werden.
MissionLib.CreateExplosions = function( Position, TypeTable, Damage, Size )
    local explosion = { Position = Position }
    if Damage then
        if TypeTable[2] then  -- schneller Trick anstelle von lua.sizeof zur Prüfung ob > 1
            Damage = Damage * 1.0 / lua.sizeof( TypeTable )  -- * 1.0 ist schneller als lua.tofloat
        end
        explosion.Damage = Damage
        if Size then
            explosion.Size = Size
        end
    end
    for i, effect in TypeTable do
        explosion.Type = effect
        NObject.CreateExplosion( explosion )
    end
end

--============================[ Schiffe und Wings ]=============================

-- Ersetzt "NWing.Create", wenn keine Superfrachter in Frachterwings mit den Wingtypen
-- WINGTYPE_FREIGHTER50T, WINGTYPE_FREIGHTER100T und WINGTYPE_FREIGHTER200T erwünscht sind.
-- Da häufig benötigt, wird in der Rückgabetabelle zusätzlich der Wingleader geliefert.
XWing.Create = function( Params )
    local data = NWing.Create( Params )
    local ship = get( "Logic.Wings."..data.Wing..".leader" )
    local type = Params.WingType
    if type <= WINGTYPE_FREIGHTER200T and type >= WINGTYPE_FREIGHTER50T then
        local race = get( "Logic.StarShips."..ship..".race" )
        if race == RACE_HUMAN then
            while NShip.GetNumCargoBays( { Ship = ship } ).NumCargoBays > 8 do
                NWing.Destroy( { Wing = data.Wing } )
                data = NWing.Create( Params )
                ship = get( "Logic.Wings."..data.Wing..".leader" )
            end
        elseif race == RACE_RAPTOR or race == RACE_ARRACK then
            if NShip.GetNumCargoBays( { Ship = ship } ).NumCargoBays > 4 then
                NWing.Destroy( { Wing = data.Wing } )
                -- WingType in WINGTYPE_FREIGHTERxxxCAP ändern:
                Params.WingType = type + 15
                data = NWing.Create( Params )
                ship = get( "Logic.Wings."..data.Wing..".leader" )
                -- WingType in referenzierter Tabelle wiederherstellen:
                Params.WingType = type
            end
        end
    end
    data.Leader = ship
    return data
end

-- Erzeugt einen Wing mit dem Leader der Rasse 'Race' und Wingmen der Rasse 'Race2' (auch RACE_RANDOM).
-- Macht nur Sinn, wenn der Leader einer bestimmten Rasse angehören soll und nicht alleine im Wing ist.
-- Die Übergabetabelle ist gleich der von "NWing.Create", mit einem neuen optionalen Parameter 'Race2'.
-- Die Rückgabetabelle liefert im neuen Parameter 'MemberList' die Handles der Wingmen zurück.
XWing.CreateWithLeaderRace = function( Params )
    local number = Params.Number
    -- Wingleader
    Params.Number = 1
    local data = NWing.Create( Params )
    -- Wingmembers
    if number > 0 then		-- Anzahl der Wingmen eintragen
        Params.Number = number - 1
    elseif number == 0 then	-- Standardwing mit insgesamt 4 Schiffen
        Params.Number = 3
    else			-- Negative Werte erzeugen einen Wing in maximaler Größe
        Params.Number = 10
    end
    if Params.Number > 0 then
        local type = Params.WingType
        if type > WINGTYPE_HUNTER then
            if type <= WINGTYPE_FREIGHTER200T
            or ( type >= WINGTYPE_PIRATEFREIGHTER50T and type <= WINGTYPE_FREIGHTER600CAP ) then
                Params.WingType = WINGTYPE_HUNTER   -- Geleitschutzjäger bei Frachterwings
            end
        end
        local race = Params.Race
        Params.Race = Params.Race2
        local names = Params.Names
        if names and names[2] then
            local membernames = {}
            for i = 2, lua.getn( names ) do
                membernames[i-1] = names[i]
            end
            Params.Names = membernames
        end
        data.MemberList = NWing.List( { Wing = NWing.Create( Params ).Wing } ).ShipList
        for i, ship in data.MemberList do
            NShip.JoinWing( { Ship = ship, Wing = data.Wing } )
        end
        -- Daten in der Übergabetabelle wiederherstellen
        Params.Race = race
        Params.WingType = type
        if names then Params.Names = names; end
    end
    Params.Number = number
    return data
end

-- Wird anstelle von "NWing.Create" ausschließlich für die Erzeugung von Jägern in Hangars verwendet
-- und deckt den Fall ab, dass der erzeugte Wing trotz Angriffsbefehl nicht angreifen will.
-- Anders als in "NWing.Define" muss 'WingType' übergeben werden, daraus wird der Schiffstyp ermittelt.
-- 'Object' muss ebenfalls übergeben werden und 'PosType' wird automatisch auf POSDESCR_HANGAR gesetzt.
-- Wenn der optionale Parameter 'PosType' angegeben wurde (Wert beliebig), hat der Wing die Standard-KI.
-- Nur Wingtypen und Rassen für Hunter, Militär, Piraten und Polizei, aber keine S'kaa oder 1704!
-- Achtung: Piratenwings können nicht in Kreuzerhangars erzeugt werden, sondern nur in Orbiterhangars!
-- Syntax: Define( { WingType, Number, Race, Names, Object, Level | LevelOffset } ) : { Wing, Position }
XWing.Define = function( Params )
    -- Gemeinsame Daten von Create und Define in die Parametertabelle
    local data = {
        PosType = POSDESCR_HANGAR,
        Object  = Params.Object,
        Names   = Params.Names
    }
    if Params.PosType then
        data.WingType = Params.WingType
    end
    -- Schiffe definieren
    local number = Params.Number
    if not number or number == 0 then
        number = 4
    elseif number < 0 or number > 11 then
        number = 11
    end
    local shiptype = {
        [WINGTYPE_HUNTER]   = ST_WINGMAN,
        [WINGTYPE_POLICE]   = ST_POLICE,
        [WINGTYPE_MILITARY] = ST_MILITARYFIGHTER,
        [WINGTYPE_PIRATES]  = ST_PIRATESHIP,
        [WINGTYPE_RAIDERS]  = ST_PIRATESHIP
    }
    shiptype = shiptype[Params.WingType]
    local isHunterOrPirate = shiptype == ST_WINGMAN or shiptype == ST_PIRATESHIP
    local race = Params.Race
    local shiplist = {}
    if not isHunterOrPirate and not race then
        -- Polizei und Militär
        race = MissionLib.GetSystemRace()
    end
    if not race or race == RACE_RANDOM or race == RACE_CLUSTER then
        -- Zusammensetzung des Wings nach Rassenverteilung
        shiplist = MissionLib.RandomRaceList( number )
    else
        -- Zusammensetzung des Wings aus einer einzigen Rasse
        for i = 1, number do
            shiplist[i] = race
        end
    end
    local level = "Level"
    local value = Params[level]
    if not value then
        level = "LevelOffset"
        value = Params[level]
    end
    for i, race in shiplist do
        if race == RACE_HUMAN and isHunterOrPirate and math.random() > 0.5 then
            race = 6    -- Terranischer Jäger mit 2 Triebwerken
        end
        shiplist[i] = { ObjType = shiptype, ObjIndex = race, [level] = value }
    end
    data.Ships = shiplist
    return NWing.Define( data )
end

-- Erzeugt einen Satelliten an einer definierten Position im Raum.
-- Funktionsgleich mit "NObject.CreateSatellite", zusätzlich kann noch ein Name übergeben werden.
-- Wing- und Ship-Handle des Satelliten werden nicht als Tabelle, sondern direkt zurückgeliefert.
XWing.CreateSatellite = function( Params )
    local data = NObject.CreateSatellite( Params )
    if Params.Name then
        NObject.SetSpecialName( { Object = data.Satellite, Name = Params.Name } )
    end
    return data.Wing, data.Satellite
end

-- Nur zur Vermeidung vereinzelter Abstürze, wenn die Datei "missions.bin" mit dem
-- Aufruf von "XWing.Create" gepatcht wurde. Wird für eigene Skripts nicht benötigt.
XWing.AddAction = NWing.AddAction

--------------------------------[ Schiffstypen ]--------------------------------

-- Liefert den Schiffstyp, wenn das Objekt ein Schiff ist, ansonsten nil
MissionLib.IsShip = function( Object )
    if Object and get( "Logic.StarShips."..Object, nil ) then
        return get( "Logic.StarShips."..Object..".shipType" )
    end
end

-- Liefert den Schiffstyp vom Schiff oder Leader, wenn das Objekt ein Schiff oder Wing ist
MissionLib.GetShipType = function( Object )
    -- wenn es ein Wing ist:
    local ship = get( "Logic.Wings."..Object..".leader", nil )
    if ship then
        Object = ship
    elseif Object == NO_WING_ID then
        -- Objekt hat keine WingId, ist entweder kein Schiff oder der Spieler ohne Wing
        return 0
    end
    -- Handle vom Schiff zurückliefern
    return get( "Logic.StarShips."..Object..".shipType", nil )
end

-- Zeigt den Schiffstyp vom Schiff oder Wingleader an
MissionLib.ShowShipType = function( Object )
    local shiptype = MissionLib.GetShipType( Object )
    if shiptype then
        if shiptype > ST_SUPERFREIGHTER then
            shiptype = "ID_UNKNOWN"
        else
            shiptype = "ID_SHIPTYPE_"..shiptype
        end
    else
        shiptype = "ID_NIL"
    end
    NGUI.ShowInfoText( { Text = "ID_SHIPTYPE", Replace = { shiptype } } )
end

-- Liefert den Schiffstyp eines Shuttles (ST_SHUTTLE .. ST_PASSENGER_SHUTTLE)
MissionLib.GetShuttleType = function( ShipId )
    -- Ist es kein Schiff, muss die get-Funktion einen ungültigen Index (0) liefern, nicht nil!
    -- In diesem Fall oder wenn das Schiff kein Shuttle ist, liefert die Tabelle nil zurück
    return SHUTTLE_TYPE[get( "Logic.StarShips."..ShipId..".shipType", 0 )]
end

-- Liefert den Wingtyp eines Kreuzers
MissionLib.GetCruiserWingType = function( ShipId )
    if get( "Logic.StarShips."..ShipId..".shipType", nil ) == ST_CRUISER then
        local cruiser = { Object = ShipId }
        local hangarPos = NObject.GetHangarPos( cruiser ).Position
        for i, shipPos in NObject.GetPosition( cruiser ).Position do
            if shipPos - hangarPos[i] ~= 0.0 then
                return WINGTYPE_CRUISER1
            end
        end
        return WINGTYPE_CRUISER2
    end
end

-- Ermittelt den Objektindex eines Frachters anhand von Wingtyp, Anzahl der Containerplätze und Rasse.
-- Damit kann später exakt der gleiche Frachter mit NWing.Define erzeugt werden.
MissionLib.GetFreighterIndex = function( ShipId, WingType )
    local bays = NShip.GetNumCargoBays( { Ship = ShipId } ).NumCargoBays
    local race = get( "Logic.StarShips."..ShipId..".race" )
    return TRADER_INDEX[WingType][bays][race]
end

-- Prüft, ob das Schiff das Spielerschiff ist
MissionLib.IsPlayerShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_PLAYERSHIP then
        return 1
    end
end

-- Prüft, ob das Schiff ein Hunter ist
MissionLib.IsHunterShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_WINGMAN then
        return 1
    end
end

-- Prüft, ob das Schiff ein Piratenjäger ist
MissionLib.IsPirateShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_PIRATESHIP then
        return 1
    end
end

-- Prüft, ob das Schiff ein Polizeijäger ist
MissionLib.IsPoliceShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_POLICE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Militärjäger ist
MissionLib.IsMilitaryShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_MILITARYFIGHTER then
        return 1
    end
end

-- Prüft, ob das Schiff ein Frachter ist
MissionLib.IsFreighter = function( Ship )
    local type = get( "Logic.StarShips."..Ship..".shipType", nil )
    if type and ( type == ST_TRADERSHIP or type == ST_PIRATEFREIGHTER or type == ST_SUPERFREIGHTER ) then
        return 1
    end
end

-- Prüft, ob das Schiff ein Handelsfrachter ist
MissionLib.IsTraderShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_TRADERSHIP then
        return 1
    end
end

-- Prüft, ob das Schiff ein Superfrachter ist
MissionLib.IsSuperFreighter = function( Ship )
    local type = get( "Logic.StarShips."..Ship..".shipType", nil )
    if type and ( type == ST_SUPERFREIGHTER --> Nur Superfrachter für Spezialcontainer Klasse 3
    or ( type == ST_TRADERSHIP and NShip.GetNumCargoBays( { Ship = Ship } ).NumCargoBays > 8 ) ) then
        return 1
    end
end

-- Prüft, ob das Schiff ein Piratenfrachter ist
MissionLib.IsPirateFreighter = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_PIRATEFREIGHTER then
        return 1
    end
end

-- Prüft, ob das Schiff ein Kreuzer ist
MissionLib.IsCruiser = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CRUISER then
        return 1
    end
end

-- Prüft, ob das Schiff ein großer Kreuzer ist
MissionLib.IsCruiser1 = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CRUISER then
        local cruiser = { Object = Ship }
        local hangarPos = NObject.GetHangarPos( cruiser ).Position
        for i, shipPos in NObject.GetPosition( cruiser ).Position do
            if shipPos - hangarPos[i] ~= 0.0 then
                return 1
            end
        end
    end
end

-- Prüft, ob das Schiff ein kleiner Kreuzer ist
MissionLib.IsCruiser2 = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CRUISER then
        local cruiser = { Object = Ship }
        local hangarPos = NObject.GetHangarPos( cruiser ).Position
        for i, shipPos in NObject.GetPosition( cruiser ).Position do
            if shipPos - hangarPos[i] ~= 0.0 then
                return
            end
        end
        return 1
    end
end

-- Prüft, ob das Schiff eine S’kaadrohne ist
MissionLib.IsSkaaDrone = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_SKAADRONE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Canyonschiff ist
MissionLib.IsCanyonShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CANYONSHIP then
        return 1
    end
end

-- Prüft, ob das Schiff eine Piratenbasis ist
MissionLib.IsBaseShip = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_BASESHIP then
        return 1
    end
end

-- Prüft, ob das Schiff eine Waffenplattform ist
MissionLib.IsWeaponBase = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_WEAPONBASE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Satellit ist
MissionLib.IsSatellite = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_COMMSAT then
        return 1
    end
end

-- Prüft, ob das Schiff ein Shuttle ist (Taxi)
-- Funktionsgleich mit "GetShuttleType" und ist nur ein anderer Name dafür
MissionLib.IsShuttle = MissionLib.GetShuttleType

-- Prüft, ob das Schiff ein Beladungs-Shuttle zwischen Cargodocks und Frachtern ist
MissionLib.IsCargoShuttle = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_SHUTTLE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Sammler?-Shuttle ist
MissionLib.IsCollectorShuttle = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_COLLECTOR_SHUTTLE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Versorgungs-Shuttle (Taxi) von der Handelsstation zu anderen Orbitern ist
MissionLib.IsConsumptionShuttle = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CONSUMPTION_SHUTTLE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Produktions-Shuttle (Taxi) von den Orbitern zur Handelsstation ist
MissionLib.IsProductionShuttle = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_PRODUCTION_SHUTTLE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Taxi mit Passagiermodul ist
MissionLib.IsPassengerShuttle = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_PASSENGER_SHUTTLE then
        return 1
    end
end

-- Prüft, ob das Schiff eine Frachtdrohne von Jägern ist
MissionLib.IsCargoDrone = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_CARGODRONE then
        return 1
    end
end

-- Prüft, ob das Schiff eine Frachtdrohne von Frachtern ist
MissionLib.IsTraderDrone = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_TRADERDRONE then
        return 1
    end
end

-- Prüft, ob das Schiff ein Schildgenerator ist
MissionLib.IsShieldGen = function( Ship )
    if get( "Logic.StarShips."..Ship..".shipType", nil ) == ST_SHIELDGEN then
        return 1
    end
end

-- TEST: Liefert true, wenn das Objekt ein Kreuzerwrack ist
-- Beginnt mit 3342336, das letzte Handle ist aber noch unbekannt
MissionLib.IsWreck = function( Object )
    if Object then
        if MissionLib.GetOrbiterType( Object ) == OBJTYPE_DECORATION
        or ( Object >= 3342336 and Object <= 3343336 ) then
            return 1
        end
    end
end

--------------------------------[ Allgemeine Schiffsfunktionen ]----------------

-- Liefert das CStarShipHandle der DSO, ist nur ein anderer Name für "GetPlayerHandle".
MissionLib.GetPlayerShip = MissionLib.GetPlayerHandle

-- Liefert die ID eines Wingman, der Wing muss existieren (Index = 1..10)
-- Existiert der Wingman nicht, wird 327679 (NO_SHIP_ID) zurückgeliefert.
MissionLib.GetWingMemberID = function( WingId, Index )
    return get( "Logic.Wings."..WingId..".ship"..Index )
end

-- Liefert eine Liste aller Wingmen des Wings und im zweiten Rückgabewert den Wingleader.
MissionLib.GetMemberList = function( WingId )
    local memberlist = {}
    local shiplist = NWing.List( { Wing = WingId } ).ShipList
    for i = 2, lua.getn( shiplist ) do
        memberlist[i-1] = shiplist[i]
    end
    return memberlist, shiplist[1]
end

-- Liefert die WingId eines Schiffs
MissionLib.GetWingId = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship..".wingId", nil )
    end
end

-- Liefert das Handle vom Leader des Schiffs
MissionLib.GetWingLeaderOfShip = function( Ship )
    if Ship then
        local wing = get( "Logic.StarShips."..Ship..".wingId", nil )
        if wing then
            return get( "Logic.Wings."..wing..".leader" )
        end
    end
end

-- Prüft, ob der Wing nur (noch) ein Schiff hat. WingId muss existieren, darf aber ungültig sein.
-- Ist auch dann true, wenn das letzte Schiff des Wings zerstört wurde und der Wing noch existiert.
MissionLib.LastShipInWing = function( WingId )
    if get( "Logic.Wings."..WingId..".count", 0 ) == 1 then
        return 1
    end
end

-- Liefert die Ausrichtung eines Schiffs (ist viel langsamer als NShip.GetAlignment)
MissionLib.GetShipFrontDir = function( Ship )
    if Ship then
        Ship = "Logic.StarShips."..Ship
        return {
            get( Ship..".shipFrontX", nil ),
            get( Ship..".shipFrontY", nil ),
            get( Ship..".shipFrontZ", nil )
        }
    end
end

-- Liefert die Ausrichtung der DSO (ist viel langsamer als NShip.GetAlignment)
MissionLib.GetPlayerFrontDir = function()
    return {
        get( "Logic.PlayerShip.shipFrontX" ),
        get( "Logic.PlayerShip.shipFrontY" ),
        get( "Logic.PlayerShip.shipFrontZ" )
    }
end

-- Liefert direkt vor dem Schiff eine Position in der angegebenen Entfernung.
-- In den Rückgabeparametern 2 und 3 wird die Ausrichtung, im 4. die Position des Schiffs zurückgegeben.
-- Negative Distanzen liefern eine Position hinter dem Schiff.
MissionLib.ShipFrontPos = function( Ship, Distance )
    if Ship then
        local align = NShip.GetAlignment( { Ship = Ship } )
        local front = align.Front
        local pos = align.Pos
        return {
            pos[1] + Distance * front[1],
            pos[2] + Distance * front[2],
            pos[3] + Distance * front[3]
        }, front, align.UpDir, pos
    end
end

-- Liefert vor dem Spielerschiff eine Position in der angegebenen Entfernung.
-- In den Rückgabeparametern 2 und 3 wird die Ausrichtung und im 4. die Position der DSO zurückgegeben.
-- Negative Distanzen liefern eine Position hinter der Darkstar One.
MissionLib.PlayerFrontPos = function( Distance )
    local align = NShip.GetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )
    local front = align.Front
    local pos = align.Pos
    return {
        pos[1] + Distance * front[1],
        pos[2] + Distance * front[2],
        pos[3] + Distance * front[3]
    }, front, align.UpDir, pos
end

-- Liefert aus dem Wing Handle und Entfernung des Schiffs, das der DSO am nächsten ist.
MissionLib.GetNearestShip = function( WingId )
    if WingId then
        local nearest
        local mindist = 1000000
        local GetDistance = NObject.DistanceFromPlayer
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            local dist = GetDistance( { Object = ship } ).Distance
            if dist < mindist then
                mindist = dist
                nearest = ship
            end
        end
        return nearest, mindist
    end
end

-- Liefert die Entfernung eines Objekts (Schiff, Station, Wegpunkt, usw.) zum Leader eines Wings.
MissionLib.GetDistanceToWing = function( Object, WingId )
    if Object and WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            return MissionLib.GetObjectDistance( Object, leader )
        end
    end
    return -1
end

-- Liefert die Entfernung eines Objekts oder Vektors zum nächststehenden Schiff eines Wings.
-- Ein übergebenes Objekthandle wird dabei automatisch in die Objektposition umgerechnet.
MissionLib.GetMinDistanceToWing = function( Object, WingId )
    if Object and WingId then
        local nearest
        local mindist = 1000000000000.0
        local GetPosition = NObject.GetPosition
        local GetDistance = MissionLib.GetVectorDistance
        if lua.type( Object ) ~= "table" then
            Object = GetPosition( { Object = Object } ).Position
        end
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            local dist = GetDistance( Object, GetPosition( { Object = ship } ).Position )
            if dist < mindist then
                mindist = dist
                nearest = ship
            end
        end
        if nearest then
            return mindist, nearest
        end
    end
    return -1
end

-- Liefert aus mehreren Wings Handle und Entfernung des Schiffs, das der DSO am nächsten ist.
MissionLib.GetNearestShipInWings = function( WingList )
    local nearest
    local mindist = 1000000
    local GetDistance = NObject.DistanceFromPlayer
    for i, wing in WingList do
        for j, ship in NWing.List( { Wing = wing } ).ShipList do
            local dist = GetDistance( { Object = ship } ).Distance
            if dist < mindist then
                mindist = dist
                nearest = ship
            end
        end
    end
    return nearest, mindist
end

-- Liefert aus mehreren Wings Handle und Entfernung des Schiffs, das dem Zielschiff am nächsten ist.
MissionLib.GetNearestShipInWingsToShip = function( WingList, AimShip )
    if AimShip then
        local nearest
        local mindist = 1000000
        local GetPosition = NObject.GetPosition
        local GetDistance = MissionLib.GetVectorDistance
        local aimShipPos = GetPosition( { Object = AimShip } ).Position
        for i, wing in WingList do
            for j, ship in NWing.List( { Wing = wing } ).ShipList do
                local dist = GetDistance( aimShipPos, GetPosition( { Object = ship } ).Position )
                if dist < mindist then
                    mindist = dist
                    nearest = ship
                end
            end
        end
        return nearest, mindist
    end
end

-- Ist der Spieler in einem Wing, liefert PlayerEscort die Schiffsklasse vom Wingleader
-- (z.B. ST_TRADERSHIP) sowie sein Wing- und Schiffshandle zurück, ansonsten nil.
-- Das kann auch der Spieler selbst sein (ST_PLAYERSHIP), falls er Leader des Wings ist.
MissionLib.PlayerEscort = function()
    local wingId = get( PLAYER_WING_ID )
    local leader = get( "Logic.Wings."..wingId..".leader", nil )
    if leader then
        return get( "Logic.StarShips."..leader..".shipType" ), wingId, leader
    end
end

-- Liefert die Anzahl aller vom Spieler abgeschossenen Schiffe.
MissionLib.GetPlayerKills = function()
    return get( PLAYER_KILLS )
end

-- Liefert die Anzahl aller Überfälle des Spielers auf Frachter.
MissionLib.GetPlayerRaidCount = function()
    return get( "Logic.Player.raidcounter" )
end

-- Liefert den Wohlstandsindex des Spielers.
MissionLib.GetPlayerWealth = function()
    return get( "Logic.Player.wealth" )
end

-- Liefert true, wenn der Spieler ein Freund von Piraten ist.
MissionLib.PlayerIsPirateFriend = function()
    if get( "Logic.Player.isPirateFriend" ) > 0 then
        return 1
    end
end

-- Liest die Rassenzugehörigkeit eines Schiffs ( 0..6, RACE_HUMAN..RACE_SKAA )
MissionLib.GetRace = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship..".race" )
    end
end

-- Liefert aus dem Wing das erste Schiff mit der angegebenen Rasse, falls eins existiert.
MissionLib.GetRaceInWing = function( WingId, Race )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            if get( "Logic.StarShips."..ship..".race" ) == Race then
                return ship
            end
        end
    end
end

-- Liest die Rassenzugehörigkeit von allen Schiffen im Wing und liefert sie als Tabelle zurück.
-- Der Tabellenindex entspricht dabei dem Schiffshandle und der Wert der zugehörigen Rasse.
MissionLib.GetRacesInWing = function( WingId )
    if WingId then
        local racelist = {}
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            racelist[ship] = get( "Logic.StarShips."..ship..".race" )
        end
        return racelist
    end
end

-- Liest den Hüllenzustand eines Schiffs ( 1.0 = 100% )
MissionLib.GetHull = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship..".hullCondition" )
    end
end

-- Liest den Hüllenzustand der DSO ( 1.0 = 100% )
MissionLib.GetPlayerHull = function()
    return get( PLAYER_HULL )
end

-- Liest den Schildzustand hinten vom Schiff ( 1.0 = 100% )
MissionLib.GetShieldRear = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship..".shieldConditionBack" )
    end
end

-- Liest den Schildzustand hinten von der DSO ( 1.0 = 100% )
MissionLib.GetPlayerShieldRear = function()
    return get( PLAYER_SHIELD_BACK )
end

-- Liest den Schildzustand vorne vom Schiff ( 1.0 = 100% )
MissionLib.GetShieldFront = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship..".shieldConditionFront" )
    end
end

-- Liest den Schildzustand vorne von der DSO ( 1.0 = 100% )
MissionLib.GetPlayerShieldFront = function()
    return get( PLAYER_SHIELD_FRONT )
end

-- Liest den mittleren Zustand beider Schilde vom Schiff ( 1.0 = 100% )
MissionLib.GetShield = function( Ship )
    if Ship then
        local back  = get( "Logic.StarShips."..Ship..".shieldConditionBack" )
        local front = get( "Logic.StarShips."..Ship..".shieldConditionFront" )
        return ( back + front ) * 0.5
    end
end

-- Liest den mittleren Zustand beider Schilde von der DSO ( 1.0 = 100% )
MissionLib.GetPlayerShield = function()
    local back = get( PLAYER_SHIELD_BACK )
    local front = get( PLAYER_SHIELD_FRONT )
    return ( back + front ) * 0.5
end

-- Ermittelt den Gesamtzustand eines Schiffs ( 1.0 = 100% )
MissionLib.GetShipCondition = function( Ship )
    if Ship then
        Ship = "Logic.StarShips."..Ship
        local hull = get( Ship..".hullCondition" )
        -- Wenn der Rumpf kaputt ist, nützen auch die Schilde nichts mehr
        if hull == 0.0 then
            return hull
        end
        local back  = get( Ship..".shieldConditionBack" )
        local front = get( Ship..".shieldConditionFront" )
        return ( back + front ) * 0.25 + hull * 0.5
    end
end

-- Ermittelt den Gesamtzustand der DSO ( 1.0 = 100% )
MissionLib.GetPlayerCondition = function()
    local hull  = get( PLAYER_HULL )
    local back  = get( PLAYER_SHIELD_BACK )
    local front = get( PLAYER_SHIELD_FRONT )
    -- Test auf Hüllenwert 0 hier nicht nötig, da das Spiel dann sowieso vorbei ist
    return ( back + front ) * 0.25 + hull * 0.5
end

-- Ermittelt den Gesamtzustand von jedem Schiff in 'ShipList' und liefert das erste
-- am wenigsten beschädigte Schiff und dessen Zustandswert zurück ( 1.0 = 100% )
MissionLib.GetBestShip = function( ShipList )
    local condition = 0
    local bestShip
    for i, ship in ShipList do
        local integrity = MissionLib.GetShipCondition( ship )
        if integrity == 1.0 then
            return ship, integrity
        end
        if integrity > condition then
            condition = integrity
            bestShip = ship
        end
    end
    return bestShip, condition
end

-- Ermittelt den Gesamtzustand von jedem Schiff im Wing und liefert das erste
-- am wenigsten beschädigte Schiff und dessen Zustandswert zurück ( 1.0 = 100% )
MissionLib.GetBestShipInWing = function( WingId )
    if WingId then
        return MissionLib.GetBestShip( NWing.List( { Wing = WingId } ).ShipList )
    end
end

-- Ermittelt den Gesamtzustand von jedem Schiff in allen übergebenen Wings und liefert das erste
-- am wenigsten beschädigte Schiff, dessen WingId und seinen Zustandswert zurück ( 1.0 = 100% )
MissionLib.GetBestShipInWings = function( WingList )
    local condition = 0
    local bestShip, wingId
    for i, wing in WingList do
        for j, ship in NWing.List( { Wing = wing } ).ShipList do
            local integrity = MissionLib.GetShipCondition( ship )
            if integrity == 1.0 then
                return ship, wing, integrity
            end
            if integrity > condition then
                condition = integrity
                bestShip = ship
                wingId = wing
            end
        end
    end
    return bestShip, wingId, condition
end

-- Ermittelt den Gesamtzustand von jedem Schiff in 'ShipList' und liefert das erste
-- am schwersten beschädigte Schiff und dessen Zustandswert zurück ( 1.0 = 100% )
-- Es werden jedoch keine Schiffe berücksichtigt, deren Hüllenwerte bereits auf 0 gefallen sind.
MissionLib.GetWorstShip = function( ShipList )
    local condition = 2
    local worstShip
    for i, ship in ShipList do
        local integrity = MissionLib.GetShipCondition( ship )
        if integrity > 0 and integrity < condition then
            condition = integrity
            worstShip = ship
        end
    end
    return worstShip, condition
end

-- Ermittelt den Gesamtzustand von jedem Schiff im Wing und liefert das erste
-- am schwersten beschädigte Schiff und dessen Zustandswert zurück ( 1.0 = 100% )
-- Es werden jedoch keine Schiffe berücksichtigt, deren Hüllenwerte bereits auf 0 gefallen sind.
MissionLib.GetWorstShipInWing = function( WingId )
    if WingId then
        return MissionLib.GetWorstShip( NWing.List( { Wing = WingId } ).ShipList )
    end
end

-- Ermittelt den Gesamtzustand von jedem Schiff in allen übergebenen Wings und liefert das erste
-- am schwersten beschädigte Schiff, dessen WingId und seinen Zustandswert zurück ( 1.0 = 100% )
-- Es werden jedoch keine Schiffe berücksichtigt, deren Hüllenwerte bereits auf 0 gefallen sind.
MissionLib.GetWorstShipInWings = function( WingList )
    local condition = 2
    local worstShip, wingId
    for i, wing in WingList do
        for j, ship in NWing.List( { Wing = wing } ).ShipList do
            local integrity = MissionLib.GetShipCondition( ship )
            if integrity > 0 and integrity < condition then
                condition = integrity
                worstShip = ship
                wingId = wing
            end
        end
    end
    return worstShip, wingId, condition
end

-- Liest den durch gesammelte Artefakte erreichbaren Schiffslevel der DSO ( 0..30 )
MissionLib.GetPlayerLevel = function()
    return get( PLAYER_LEVEL )
end

-- Liest den tatsächlich erreichten Schiffslevel der DSO ( 0..30 )
MissionLib.GetRealPlayerLevel = function()
    return get( PLAYER_UPGRADES )
end

-- HINWEIS:
-- Die folgenden 5 Funktionen liefern Levelwerte von 1 bis 10, so wie sie auch angezeigt werden.
-- Intern rechnet DS1 aber mit Werten von 0 bis 9. Dies muss man in Verbindung mit Funktionen
-- wie z.B. "NPlayer.EquipmentInfo", welche den internen Wert ausgeben, berücksichtigen!
-- Existiert der Parameter 'ShipLevel', wird der tatsächlich erreichte Level zurückgegeben,
-- ansonsten der durch gesammelte und noch nicht eingesetzte Artefakte erreichbare Level.

-- Ermittelt die Energieklasse der DSO ( 1..10 )
MissionLib.GetPlayerEnergyLevel = function( ShipLevel )
    if ShipLevel then
        ShipLevel = PLAYER_UPGRADES	-- Aktuelle Energieklasse
    else
        ShipLevel = PLAYER_LEVEL	-- Erreichbare Energieklasse
    end
    return EQUIPMENT_LEVEL.Energy[get( ShipLevel )]
end

-- Ermittelt die Waffenklasse der DSO ( 1..10 )
MissionLib.GetPlayerWeaponLevel = function( ShipLevel )
    if ShipLevel then
        ShipLevel = PLAYER_UPGRADES	-- Aktuelle Waffenklasse
    else
        ShipLevel = PLAYER_LEVEL	-- Erreichbare Waffenklasse
    end
    return EQUIPMENT_LEVEL.Weapon[get( ShipLevel )]
end

-- Ermittelt die Ausrüstungsklasse der DSO ( 1..10 )
MissionLib.GetPlayerEquipmentLevel = function( ShipLevel )
    if ShipLevel then
        ShipLevel = PLAYER_UPGRADES	-- Aktuelle Ausrüstungsklasse
    else
        ShipLevel = PLAYER_LEVEL	-- Erreichbare Ausrüstungsklasse
    end
    return EQUIPMENT_LEVEL.Device[get( ShipLevel )]
end

-- Liefert eine Tabelle mit allen 4 oben definierten Levels
-- GetPlayerLevels() : { Ship, Energy, Weapon, Equipment }
MissionLib.GetPlayerLevels = function( ShipLevel )
    if ShipLevel then
        ShipLevel = get( PLAYER_UPGRADES )
    else
        ShipLevel = get( PLAYER_LEVEL )
    end
    return {
        Ship = ShipLevel,
        Energy = EQUIPMENT_LEVEL.Energy[ShipLevel],
        Weapon = EQUIPMENT_LEVEL.Weapon[ShipLevel],
        Equipment = EQUIPMENT_LEVEL.Device[ShipLevel]
    }
end

-- Liefert Informationen über einen Ausrüstungsgegenstand. ( Level: 1..10! )
-- Die zurückgelieferten Werte hängen vom Ausrüstungsgegenstand ab. Falls erforderlich,
-- kann ein Skript angegeben werden, welches die Werte in die GLOBALS-Tabelle eingetragen hat.
-- Syntax: V.Info = MissionLib.EquipmentInfo( Type, Script ) : { Level, Count, Size }
MissionLib.EquipmentInfo = function( Type, Script )
    local info = NPlayer.EquipmentInfo( { Type = Type } )
    if Type == EQUIPMENT_CARGO_COMPUTER then
        info.Level = info.Level + 1
    elseif Type == EQUIPMENT_ORE_COLLECTOR then
        if info.Level > 0 then
            info.Level = info.Level + 1
        end
    else
        if not Script then Script = "ALWAYS_02"; end
        local level = GLOBALS[Script][EQUIPMENT_NAME[Type]]
        if level and level > 0 then
            info.Level = level
            info.Count = 1
            if Type == EQUIPMENT_AFTERBURNER then
                -- 'Size' wird als Höchstgeschwindigkeit mit Nachbrenner interpretiert
                info.Size = GLOBALS[Script].MaxSpeed
            elseif Type == EQUIPMENT_HYPERDRIVE then
                -- 'Size' wird als Reichweite des Hyperraumantriebs interpretiert
                info.Size = GLOBALS[Script].HyperdriveRange
            end
        end
    end
    return info
end

-- Reichweite des Hyperraumantriebs in Lichtjahren.
-- Der Antriebslevel muss vorher mittels Skript in die GLOBALS-Tabelle eingetragen worden sein.
MissionLib.GetHyperdrive = function( Script )
    if not Script then Script = "ALWAYS_02"; end
    return GLOBALS[Script].HyperdriveRange
end

-- Anzahl der Frachtdrohnen der DSO ( 1..3, ob frei oder nicht )
MissionLib.GetPlayerCargoDrones = function()
    return get( "Logic.PlayerShip.maxDrones" )
end

-- Anzahl der aktiven Frachtdrohnen der DSO ( 0..3 geschleppte Container )
MissionLib.GetPlayerActiveDrones = function()
    return get( "Logic.PlayerShip.actDrones" )
end

-- Anzahl der freien Frachtdrohnen der DSO ( 0..3 )
-- ( Geht leider nicht für Schiffe, liefert immer nur 0 )
MissionLib.GetPlayerFreeDrones = function()
    return get( "Logic.PlayerShip.maxDrones" ) - get( "Logic.PlayerShip.actDrones" )
end

-- Anzahl der freien Containerplätze eines Frachters ( 0..45 )
-- Ist nur für Frachter geeignet und liefert für andere Schiffe immer 0.
-- ( Ist um den Faktor 10 langsamer als NShip.GetNumCargoBays )
MissionLib.GetFreeCargoBays = function( Freighter )
    return get( "Logic.StarShips."..Freighter..".freeSlots" )
end

-- Liest die Geschwindigkeit eines Schiffs ( 4.0 = 100% )
MissionLib.GetSpeed = function( Ship )
    if Ship then
        return get( "Logic.StarShips."..Ship..".shipSpeed" )
    end
end

-- Liest die Geschwindigkeit der DSO ( 4.0 = 100% )
MissionLib.GetPlayerSpeed = function()
    return get( PLAYER_SPEED )
end

-- Liest die Geschwindigkeit eines Schiffs in % ( Rückwärtsschub ist auch eine positive Zahl )
MissionLib.GetSpeedPercent = function( Ship )
    if Ship then
        return MissionLib.Rnd( get( "Logic.StarShips."..Ship..".shipSpeed" ) * 25 )
    end
end

-- Liest die Geschwindigkeit der DSO in % ( Rückwärtsschub ist auch eine positive Zahl )
MissionLib.GetPlayerSpeedPercent = function()
    return MissionLib.Rnd( get( PLAYER_SPEED ) * 25 )
end

-- Liest die SystemId vom Sprungziel der DSO ( nil = kein Ziel markiert )
MissionLib.GetPlayerJumpDestination = function()
    local systemId = get( PLAYER_JUMP_DEST )  -- 65535 = kein Ziel
    if systemId <= 402 then
        return systemId
    end
end

-- Liefert das Handle des Hangars, in welchem die DSO gelandet ist
-- Ist identisch mit den Objekthandles von Stationen, Asteroiden und großen Kreuzern.
-- Beispiel: if MissionLib.GetPlayerHangar() == MissionLib.GetSystemAsteroid() then ...
MissionLib.GetPlayerHangar = function()
    return get( PLAYER_HANGAR )
end

-- Liefert Position, Ausrichtung und Handle des Hangars, in welchem die DSO gelandet ist.
-- Syntax: GetPlayerHangarPos() : { Position, Front, UpDir, Handle }
MissionLib.GetPlayerHangarPos = function()
    local hangar = get( PLAYER_HANGAR )
    local hangarPos = NObject.GetHangarPos( { Object = hangar } )
    hangarPos.Handle = hangar
    return hangarPos
end

-- Liefert den Scannstatus des Spielerschiffs (0..3)
MissionLib.GetPlayerScan = function()
    return get( "Logic.PlayerShip.scan" )
end

-- Liefert die StringId für einen Kreuzernamen.
-- (Id = 0..62, vgl. die Sektion [Kreuzer_Spielstart] in \inifiles\Infos\Konzept.ini).
-- Geradzahlige Ids liefern den Namen eines großen Kreuzers, ungerade den eines kleinen.
MissionLib.GetCruiserName = function( Id )
    return "ID_CRUISER_"..Id
end

-- Liefert eine Tabelle mit StringId's für alle 60 Piratennamen der Rasse. Der Index beginnt bei 0.
-- Für 'Race' darf sowohl ihre Konstante (z.B. RACE_OCTO) als auch ein String ("OCTO") übergeben werden.
MissionLib.GetPirateNames = function( Race )
    -- "HUMAN", "MORTOK", "RAPTOR", "OCTO", "ARRACK" oder "THUL"
    if lua.type( Race ) == "number" then Race = RACE_NAMES[Race]; end
    local name = "ID_NAME_"..Race.."_"
    local namearray = {}
    for i = 0, 59 do
        namearray[i] = name..i
    end
    return namearray
end

-- Liefert eine Tabelle mit 'Number' StringId's für Piratennamen der Rasse. Der Index beginnt bei 1.
-- Für 'Race' muss ihre Konstante (0-5, RACE_HUMAN..RACE_THUL) übergeben werden.
MissionLib.GetRandomNames = function( Race, Number )
    local namearray = {}
    local race = { Race = Race }
    local GetName = NObject.GetName
    for i = 1, Number do
        namearray[i] = GetName( race ).Name
    end
    return namearray
end

-- Liefert eine Tabelle mit 'Number' Paaren aus StringId's eines Piratennamens und der zugehörigen Rasse.
-- Funktionsgleich mit "NObject.GetNameArray", jedoch können die Namen aller Rassen geliefert werden
-- und die Anzahl der Paare ist nahezu unbegrenzt (kein stack overflow bei Number > 1025).
MissionLib.GetNameArray = function( Number )
    local namearray = {}
    local GetName = NObject.GetName
    local random = math.random
    local tonumber = lua.tonumber
    for i = 1, Number do
        local race = tonumber( random() * 6 )
        namearray[i] = { GetName( { Race = race } ).Name, race }
    end
    return namearray
end

-- Liest die Rasse des Schiffs und benennt es mit einem Namen aus der Liste dieser Rasse.
MissionLib.SetShipName = function( Ship )
    NObject.SetSpecialName( {
        Object = Ship,
        Name = NObject.GetName( { Race = get( "Logic.StarShips."..Ship..".race" ) } ).Name
    } )
end

-- Benennt das Schiff mit einem Konzernnamen des angegebenen Sternsystems.
MissionLib.SetShipCombineName = function( Ship, SystemId )
    NObject.SetSpecialName( {
        Object = Ship,
        Name = NStarSystem.GetCombineName( { System = SystemId } ).Name
    } )
end

-- Benennt einen Piratenfrachter mit Angabe seiner Gesamtkapazität (z.B. "Piratenfrachter 600t").
-- Im optionalen Parameter 'Goods' kann eine Ware für den erzeugten Container übergeben werden,
-- in dem Fall wird der Container nicht zerstört und die Funktion liefert sein Handle zurück.
-- ACHTUNG: Damit das klappt, muss der Frachter noch mindestens einen Containerplatz frei haben!
MissionLib.SetPirateFreighterName = function( Ship, Goods )
    local cargo = ""
    if Goods then cargo = Goods; end
    local container = NShip.EquipContainer( { Ship = Ship, Goods = cargo } ).Container
    local size = NContainer.GetType( { Container = container } ).Type
    local tons = CONTAINER_TONS[size] * NShip.GetNumCargoBays( { Ship = Ship } ).NumCargoBays
    NObject.SetSpecialName( { Object = Ship, Name = "ID_PIRATEFREIGHTER_"..tons } )
    if Goods then
        return container
    end
    NContainer.Destroy( { Container = container } )
end

-- Hülle der DSO auf n% ( 1.0 = 100% )
-- Es wird leider nur die angezeigte Farbe des Zustands geändert, der tatsächliche Zustand bleibt
MissionLib.SetPlayerHull = function( Value )
    set( PLAYER_HULL, Value )
end

-- Schild hinten der DSO auf n% ( 1.0 = 100% )
MissionLib.SetPlayerShieldRear = function( Value )
    set( PLAYER_SHIELD_BACK, Value )
end

-- Schild vorne der DSO auf n% ( 1.0 = 100% )
MissionLib.SetPlayerShieldFront = function( Value )
    set( PLAYER_SHIELD_FRONT, Value )
end

-- Schilde der DSO auf n% ( 1.0 = 100% )
MissionLib.SetPlayerShieldBoth = function( Value )
    set( PLAYER_SHIELD_BACK, Value )
    set( PLAYER_SHIELD_FRONT, Value )
end

-- Hülle und Schilde der DSO auf 100% ( 1.0 = 100% Testen! Problem mit Rumpf, s.o. )
MissionLib.RestorePlayerShip = function()
    set( PLAYER_HULL, 1.0 )
    set( PLAYER_SHIELD_BACK, 1.0 )
    set( PLAYER_SHIELD_FRONT, 1.0 )
end

-- Maximale Endgeschwindigkeit der DSO mit Nachbrenner in Prozent ( >= 0.0 )
-- Wird kein Wert übergeben, wird der Standardwert des eingebauten Nachbrenners gesetzt.
-- ACHTUNG: Es wird nicht geprüft, ob der beste verfügbare Nachbrenner auch gekauft wurde!
MissionLib.SetPlayerAfterburnerSpeed = function( Speed )
    if not Speed then
        NPlayer.SetMultipliers({})
    else
        local energylevel = EQUIPMENT_LEVEL.Energy[get( PLAYER_UPGRADES )]
        NPlayer.SetMultipliers( { BoostFactor = Speed / PLAYER_AFTERBURNER_SPEED[energylevel] } )
    end
end

-- Der Rumpfzustand der Schiffe im Wing kann nur bis knapp unter 10% sinken; true=Ja, false=Nein
MissionLib.ProtectWing = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.Protect( { Ship = ship, Protect = Set } )
        end
    end
end

-- Der Rumpfzustand aller Schiffe der Liste kann nur bis knapp unter 10% sinken; true=Ja, false=Nein
MissionLib.ProtectShips = function( ShipList, Set )
    for i, ship in ShipList do
        NShip.Protect( { Ship = ship, Protect = Set } )
    end
end

-- Der Rumpfzustand der DSO kann nur bis knapp unter 10% sinken; true=Ja, false=Nein (geht nicht)
MissionLib.ProtectPlayer = function( Set )
    NShip.Protect( { Ship = get( PLAYER_SHIP_ID ), Protect = Set } )
end

-- Einen ganzen Wing für den Targetcomputer verstecken; true=Ja, false=Nein
MissionLib.SetWingHidden = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetHidden( { Ship = ship, Set = Set } )
        end
    end
end

-- Die DSO für die Targetcomputer der Gegner verstecken; true=Ja, false=Nein
-- Die Zielcomputer der Feinde können nicht mehr automatisch auf die Darkstar feuern.
MissionLib.SetPlayerHidden = function( Set )
    NShip.SetHidden( { Ship = get( PLAYER_SHIP_ID ), Set = Set } )
end

-- Einen ganzen Wing unsichtbar machen; true=Ja, false=Nein
MissionLib.SetWingCloaked = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetCloaked( { Ship = ship, Set = Set } )
        end
    end
end

-- Die DSO unsichtbar machen; true=Ja, false=Nein
MissionLib.SetPlayerCloaked = function( Set )
    NShip.SetCloaked( { Ship = get( PLAYER_SHIP_ID ), Set = Set } )
end

-- Das Schiff wird unsichtbar und versteckt es für die Zielerfassung des Targetcomputers (true/false).
MissionLib.SetInvisible = function( Ship, Set )
    local ship = { Ship = Ship, Set = Set }
    NShip.SetCloaked( ship )
    NShip.SetHidden( ship )
end

-- Der Wing wird unsichtbar und versteckt ihn für die Zielerfassung des Targetcomputers (true/false).
MissionLib.SetWingInvisible = function( WingId, Set )
    if WingId then
        local member = { Set = Set }
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            member.Ship = ship
            NShip.SetCloaked( member )
            NShip.SetHidden( member )
        end
    end
end

-- Setzt für jedes Schiff im Wing einen Multiplikator für die maximalen Rumpf- und Schildpunkte.
-- Syntax: MissionLib.SetWingDurability( { Wing, Hull, Shield } )
MissionLib.SetWingDurability = function( Data )
    if Data.Wing then
        local durability = { Hull = Data.Hull, Shield = Data.Shield }
        for i, ship in NWing.List( { Wing = Data.Wing } ).ShipList do
            durability.Ship = ship
            NShip.SetDurability( durability )
        end
    end
end

-- Setzt einen Multiplikator für die maximalen Rumpf- und Schildpunkte eines Schiffs.
-- Im Gegensatz zu "NShip.SetDurability" wird das Schiff dabei nicht repariert.
-- Syntax: MissionLib.SetDurability( { Ship, Hull, Shield } )
MissionLib.SetDurability = function( Data )
    if Data.Ship then
        local ship = "Logic.StarShips."..Data.Ship
        local hullCondition        = ship..".hullCondition"
        local shieldConditionBack  = ship..".shieldConditionBack"
        local shieldConditionFront = ship..".shieldConditionFront"
        local hull  = get( hullCondition )
        local back  = get( shieldConditionBack )
        local front = get( shieldConditionFront )
        NShip.SetDurability( Data )
        set( hullCondition, hull )
        set( shieldConditionBack, back )
        set( shieldConditionFront, front )
    end
end

-- Setzt die Multiplikatoren wieder auf Standard zurück, ohne dabei das Schiff zu reparieren
MissionLib.ResetDurability = function( Ship )
    MissionLib.SetDurability( { Ship = Ship } )
end

-- Setzt einen Multiplikator für die maximalen Rumpf- und Schildpunkte der DSO ( > 0.0 )
MissionLib.SetPlayerDurability = function( Body, Shields )
    NShip.SetDurability( { Ship = get( PLAYER_SHIP_ID ), Hull = Body, Shield = Shields } )
end

-- Das Schiff erhält einen neuen Powergenerator, der die Energiespeicher für Waffen und Schilde in den
-- angegebenen Zeiten wieder auflädt. Wie "NShip.SetRecharge", ohne jedoch die Schilde sofort aufzuladen.
-- Syntax: MissionLib.SetRecharge( { Ship, EnergySecs, ShieldSecs, PlasmaSecs } )
MissionLib.SetRecharge = function( Data )
    if Data.Ship then
        local ship = "Logic.StarShips."..Data.Ship
        local shieldConditionBack  = ship..".shieldConditionBack"
        local shieldConditionFront = ship..".shieldConditionFront"
        local back  = get( shieldConditionBack )
        local front = get( shieldConditionFront )
        NShip.SetRecharge( Data )
        set( shieldConditionBack, back )
        set( shieldConditionFront, front )
    end
end

-- Setzt den Rumpf- und Schildzustand eines Schiffs ( 1.0 = 100% )
-- Syntax: MissionLib.SetShipCondition( { Ship, Hull, Shield } )
MissionLib.SetShipCondition = function( Data )
    if Data.Ship then
        local ship = "Logic.StarShips."..Data.Ship
        set( ship..".hullCondition", Data.Hull )
        set( ship..".shieldConditionBack", Data.Shield )
        set( ship..".shieldConditionFront", Data.Shield )
    end
end

-- Einen ganzen Wing unverwundbar machen; true=Ja, false=Nein
MissionLib.SetWingInvulnerable = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetInvulnerable( { Ship = ship, Set = Set } )
        end
    end
end

-- Die DSO immun gegen sämtliche Schäden machen; true=Ja, false=Nein
MissionLib.SetPlayerInvulnerable = function( Set )
    NShip.SetInvulnerable( { Ship = get( PLAYER_SHIP_ID ), Set = Set } )
end

-- Der Wing verglüht nicht mehr in der Atmosphäre von Planeten, wenn 'Set'=false ist
MissionLib.SetWingOrbiterEvasion = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetOrbiterEvasion( { Ship = ship, Set = Set } )
        end
    end
end

-- Der Wing kann durch Planeten hindurch fliegen, wenn 'Set'=false ist
MissionLib.SetWingPlanetCollision = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetPlanetCollision( { Ship = ship, Set = Set } )
        end
    end
end

-- Das Schiff kann durch Planeten hindurch fliegen verglüht nicht mehr in der Atmosphäre (Set=true)
MissionLib.SetShipPlanetFlight = function( Ship, Set )
    if Ship then
        local ship = { Ship = Ship, Set = not Set }
        NShip.SetOrbiterEvasion( ship )
        NShip.SetPlanetCollision( ship )
    end
end

-- Der Wing kann durch Planeten hindurch fliegen verglüht nicht mehr in der Atmosphäre (Set=true)
MissionLib.SetWingPlanetFlight = function( WingId, Set )
    if WingId then
        local ship = { Set = not Set }
        for i, shipId in NWing.List( { Wing = WingId } ).ShipList do
            ship.Ship = shipId
            NShip.SetOrbiterEvasion( ship )
            NShip.SetPlanetCollision( ship )
        end
    end
end

-- Die DSO verglüht in der Atmosphäre von Planeten (Standard); true=Ja, false=Nein
-- Ist 'Set'=false, kann die DSO in die Atmosphäre einfliegen,
-- wird aber bei einer Kollision mit dem Planeten zerstört.
MissionLib.SetPlayerAtmosphereCollision = function( Set )
    NShip.SetOrbiterEvasion( { Ship = get( PLAYER_SHIP_ID ), Set = Set } )
end

-- Die DSO wird bei Kollisionen mit Planeten zerstört (Standard); true=Ja, false=Nein
-- Abschalten funktioniert leider nicht mit der DSO, "SetInvulnerable" stattdessen verwenden.
MissionLib.SetPlayerPlanetCollision = function( Set )
    NShip.SetPlanetCollision( { Ship = get( PLAYER_SHIP_ID ), Set = Set } )
end

-- Die DSO kann durch Planeten hindurch fliegen und verglüht nicht mehr in der Atmosphäre (Set=true)
MissionLib.SetPlayerPlanetFlight = function( Set )
    local player = get( PLAYER_SHIP_ID )
    NShip.SetInvulnerable( { Ship = player, Set = Set } )
    NShip.SetOrbiterEvasion( { Ship = player, Set = not Set } )
end

-- Die DSO erhält eine Boss-Id ( Testen, ob's was bringt )
MissionLib.SetPlayerBoss = function( Number )
    NShip.SetBoss( { Ship = get( PLAYER_SHIP_ID ), BossId = Number } )
end

-- Setzt den Scannstatus des Spielerschiffs (0..3)
MissionLib.SetPlayerScan = function( Value )
    set( "Logic.PlayerShip.scan", Value )
end

-- Setzt die RadarMapColor eines ganzen Wings auf eine bestimmte Farbe
-- Falls 'Color' nicht übergeben wird, verwendet die Funktion die Standardfarbe
MissionLib.SetWingColor = function( WingId, Color )
    if WingId then
        local RadarMapColor = NObject.RadarMapColor
        if not Color then Color = RADARMAP_INVALID; end
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            RadarMapColor( { Object = ship, Color = Color } )
        end
    end
end

-- Setzt die RadarMapColor eines Kreuzerwracks auf Blau
-- Funktioniert nur im "StarshipDestroyed"-Event bei der Vernichtung eines Kreuzers
MissionLib.SetWreckColor = function( Wreck )
    NObject.RadarMapColor( { Object = Wreck, Color = RADARMAP_BLUE_ORBITER } )
end

-- Prüft, ob der Wing existiert
MissionLib.WingExists = function( WingId )
    if WingId and NWing.IsWing( { Wing = WingId } ).IsWing == 1 then
        return 1
    end
end

-- Prüft, ob der Wing existiert und sich mit allen Schiffen im All befindet
MissionLib.IsWingInSpace = function( WingId )
    if WingId and NWing.IsWing( { Wing = WingId } ).IsWing == 1 then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            if NShip.IsInSpace( { Ship = ship } ).InSpace == 0 then
                return
            end
        end
        return 1
    end
end

-- Prüft, ob das Schiff existiert und sich im All befindet
MissionLib.IsShipInSpace = function( Ship )
    if Ship and NShip.IsInSpace( { Ship = Ship } ).InSpace == 1 then
        return 1
    end
end

-- Die Schiffe des Wings reagieren weniger stark auf Spielerbeschuss (Ja: Set=1|true, Nein: Set=0|false)
MissionLib.WingSetPlayerFriend = function( WingId, Set )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetPlayerFriend( { Ship = ship, Set = Set } )
        end
    end
end

-- Die Schiffe in der Liste werden bei Beschuss Strafpunkte geben
MissionLib.SetCrimeOnShips = function( ShipList )
    for i, ship in ShipList do
        NShip.SetCrime( { Ship = ship, Set = true } )
    end
end

-- Die Schiffe in der Liste geben bei Beschuss keine Strafpunkte
MissionLib.SetNoCrimeOnShips = function( ShipList )
    for i, ship in ShipList do
        NShip.SetCrime( { Ship = ship, Set = false } )
    end
end

-- Die Schiffe im Wing geben bei Beschuss keine Strafpunkte
MissionLib.SetNoCrimeOnWing = function( WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.SetCrime( { Ship = ship, Set = false } )
        end
    end
end

-- Die Schiffe aller Wings in der Gruppe werden bei Beschuss Strafpunkte geben
MissionLib.SetCrimeOnGroup = function( Group )
    if Group then
        for i, wing in Group do
            for j, ship in NWing.List( { Wing = wing } ).ShipList do
                NShip.SetCrime( { Ship = ship, Set = true } )
            end
        end
    end
end

-- Die Schiffe aller Wings in der Gruppe geben bei Beschuss keine Strafpunkte
MissionLib.SetNoCrimeOnGroup = function( Group )
    if Group then
        for i, wing in Group do
            for j, ship in NWing.List( { Wing = wing } ).ShipList do
                NShip.SetCrime( { Ship = ship, Set = false } )
            end
        end
    end
end

-- Ist der Spieler in einem Wing, wird er einer bestehenden Gruppe hinzugefügt
-- und liefert bei erfolgreichem Beitritt zur Gruppe das Winghandle zurück.
MissionLib.PlayerWingJoinGroup = function( Group )
    if Group then
        local playerwing = get( PLAYER_WING_ID )
        if playerwing ~= NO_WING_ID then
            NGroupAi.AddWings( { Group = Group, WingList = { playerwing } } )
            return playerwing
        end
    end
end

-- Löst alle Gruppen auf, ohne die darin enthaltenen Wings zu löschen
MissionLib.DeleteGroups = function( Groups )
    if Groups then
        NGroupAi.Destroy( { Group = Groups.GroupA } )
        NGroupAi.Destroy( { Group = Groups.GroupB } )
    end
end

------------------------------[ Munition (Projectiles.ini) ]--------------------

-- Liefert den mittleren Schaden einer Munitionssorte des angegebenen Levels
-- Ohne Angabe des Levels wird der aktuelle Waffenlevel des Spielers verwendet
MissionLib.GetAmmoDamageAverage = function( AmmoType, Level )
    local hitpoints = NObject.GetAmmoDamage( { Ammo = AmmoType, Level = Level } )
    return ( hitpoints.DamageHull + hitpoints.DamageShield ) * 0.5
end

-- Liefert den Gesamtschaden einer Munitionssorte des angegebenen Levels
-- Ohne Angabe des Levels wird der aktuelle Waffenlevel des Spielers verwendet
MissionLib.GetAmmoDamageTotal = function( AmmoType, Level )
    local hitpoints = NObject.GetAmmoDamage( { Ammo = AmmoType, Level = Level } )
    return hitpoints.DamageHull + hitpoints.DamageShield
end

-- Bestimmte Schiffe im Wing werden mit Raketen einer Sorte ausgerüstet
-- Der Parameter 'Ships' muss eine Tabelle mit den Indicés (1..11) der Schiffe sein
MissionLib.ShipsUseMissiles = function( WingId, Ships, AmmoType )
    if WingId then
        local shiplist = NWing.List( { Wing = WingId } ).ShipList
        for i, index in Ships do
            local ship = shiplist[index]
            if ship then
                NShip.UseMissiles( { Ship = ship, Ammo = AmmoType } )
            end
        end
    end
end

-- Alle Schiffe im Wing werden mit Raketen einer Sorte ausgerüstet
MissionLib.WingUseMissiles = function( WingId, AmmoType )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.UseMissiles( { Ship = ship, Ammo = AmmoType } )
        end
    end
end

-- Die Schiffe im Wing werden mit Raketen der in der Tabelle 'AmmoList' angegebenen Sorte ausgerüstet
-- Der Tabellenindex (1..11) entspricht dabei dem Schiffsindex der von NWing.List erstellten Tabelle
-- Wird AMMO_TYPE_NONE oder nil angeben, erhält das Schiff am Tabellenindex keine Raketen.
MissionLib.WingUseMissileList = function( WingId, AmmoList )
    if WingId then
        local shiplist = NWing.List( { Wing = WingId } ).ShipList
        for i, ammo in AmmoList do
            if shiplist[i] and ammo ~= AMMO_TYPE_NONE then
                NShip.UseMissiles( { Ship = shiplist[i], Ammo = ammo } )
            end
        end
    end
end

-- Liefert den Index aus der Projectiles.ini für die angegebene Raketensorte und deren Level 1-10
MissionLib.AmmoIndex = function( AmmoType, Level )
    if AMMO_INDEX[AmmoType] then
        return AMMO_INDEX[AmmoType][Level]
    end
end

-- Liefert den Index aus der Projectiles.ini für Schwarmraketen des realen Spielerlevels.
MissionLib.SwarmIndex = function()
    return AMMO_INDEX_SWARM[MissionLib.GetPlayerWeaponLevel( 1 )]
end

-- Liefert den Index aus der Projectiles.ini für Hellfires des realen Spielerlevels.
-- Ist der Waffenlevel des Spielers noch auf 1, wird der Index für Schwarmraketen geliefert.
MissionLib.HellfireIndex = function()
    return AMMO_INDEX_HELLFIRE[MissionLib.GetPlayerWeaponLevel( 1 )]
end

-- Liefert den Index aus der Projectiles.ini für BigBangs des realen Spielerlevels.
-- Ist der Waffenlevel des Spielers noch auf 1, wird der Index für Schwarmraketen
-- und beim Waffenlevel von 2 der Index für Hellfires geliefert.
MissionLib.BigBangIndex = function()
    return AMMO_INDEX_BIGBANG[MissionLib.GetPlayerWeaponLevel( 1 )]
end

-- Rüstet die DSO mit Schwarmraketen des realen Spielerlevels aus
-- und liefert die Anzahl der tatsächlich geladenen Raketen zurück.
-- Fehlt der Parameter 'Count', wird nur eine Rakete geladen.
MissionLib.AddSwarm = function( Count )
    if not Count then Count = 1; end
    return NPlayer.AddAmmo( { Ammo = MissionLib.SwarmIndex(), Number = Count } ).Stored
end

-- Rüstet die DSO ab Waffenlevel 2 mit Hellfires des realen Spielerlevels aus
-- und liefert die Anzahl der tatsächlich geladenen Raketen zurück.
-- Ist der Waffenlevel niedriger, werden Schwarmraketen geladen.
MissionLib.AddHellfire = function( Count )
    if not Count then Count = 1; end
    return NPlayer.AddAmmo( { Ammo = MissionLib.HellfireIndex(), Number = Count } ).Stored
end

-- Rüstet die DSO ab Waffenlevel 3 mit BigBangs des realen Spielerlevels aus
-- und liefert die Anzahl der tatsächlich geladenen Torpedos zurück.
-- Ist der Waffenlevel niedriger, werden Schwarmraketen oder Hellfires geladen.
MissionLib.AddBigBang = function( Count )
    if not Count then Count = 1; end
    return NPlayer.AddAmmo( { Ammo = MissionLib.BigBangIndex(), Number = Count } ).Stored
end

------------------------------[ Aktionen für Schiffe und Wings ] ---------------

-- Der Spieler selektiert ein bestimmtes Schiff im Wing, 'Member' = 0 oder nil ist der Wingleader.
MissionLib.AutoTarget = function( WingId, Member )
    local ship = MissionLib.GetWingMember( WingId, Member )
    if ship then
        NPlayer.SelectTarget( { Object = ship } )
    end
end

-- Das angegebene Schiff verlässt den aktuellen Wing und erzeugt einen neuen Wing.
-- Die Funktion liefert dessen Handle zurück. In 'WingType' wird die Art des neuen
-- Wings übergeben. Fehlt 'WingType', wird ein Wing vom Typ WINGTYPE_HUNTER erzeugt.
MissionLib.LeaveWing = function( Ship, WingType )
    if Ship then
        if not WingType then WingType = 0; end
        return NShip.JoinWing( { Ship = Ship, WingType = WingType } ).Wing
    end
end

-- Fügt alle Schiffe von 'WingId' dem Wing 'TargetWingId' hinzu.
-- Anschließend wird ein WING_DESTROYED Event ausgelöst und 'WingId' sollte gelöscht werden.
MissionLib.JoinWings = function( WingId, TargetWingId )
    if WingId and TargetWingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NShip.JoinWing( { Ship = ship, Wing = TargetWingId } )
        end
    end
end

-- Erzeugt einen Spielerwing. Ist der Spieler in einem KI-Wing, dann wird dieser verlassen.
MissionLib.CreatePlayerWing = function()
    return NShip.JoinWing( { Ship = get( PLAYER_SHIP_ID ), WingType = 0 } ).Wing
end

-- Platziert den Leader des Wings an die eigene Position. Die Ausrichtung wird dabei nicht verändert.
-- Nützlich, um das manchmal vor allem in Videos lästige Zittern eines stillstehenden Schiffs zu vermeiden.
-- Mit "NShip.SetAlignment" funktioniert das leider nicht, deshalb muss "NWing.Place" verwendet werden.
MissionLib.DummyPlaceWing = function( WingId )
    local ship = get( "Logic.Wings."..WingId..".leader", nil )
    if ship then
        NWing.Place( { Wing = WingId, Position = NObject.GetPosition( { Object = ship } ).Position } )
    end
end

-- Ein Schiff relativ zur aktuellen Position versetzen.
MissionLib.DisplaceShip = function( Ship, Offset )
    if Ship then
        NShip.SetAlignment( {
            Ship = Ship,
            Position = MissionLib.AddVector( NObject.GetPosition( { Object = Ship } ).Position, Offset )
        } )
    end
end

-- Spielerschiff relativ zur aktuellen Position versetzen.
MissionLib.DisplacePlayer = function( Offset )
    local player = get( PLAYER_SHIP_ID )
    NShip.SetAlignment( {
        Ship = player,
        Position = MissionLib.AddVector( NObject.GetPosition( { Object = player } ).Position, Offset )
    } )
end

-- Spielerschiff vom Gate wegsetzen, um Kollisionen zu vermeiden.
-- Vorher beim Systemeintritt einen Timer mit ca. 1 Sekunde starten.
MissionLib.AvoidCollisionAtSystemEntry = function( Player )
    if not Player then Player = get( PLAYER_SHIP_ID ); end
    NShip.SetAlignment( { Ship = Player, Position = { -200, 0, 9800 } } )
end

-- Richtet das Schiff automatisch aus.
MissionLib.AutoAlignShip = function( Ship )
    if Ship then
        NShip.SetAlignment( { Ship = Ship } )
    end
end

-- Richtet die DSO automatisch aus.
MissionLib.AutoAlignPlayer = function()
    NShip.SetAlignment( { Ship = get( PLAYER_SHIP_ID ) } )
end

-- Erzeugt einen Hyperraumtoreffekt für alle Schiffe im Wing.
MissionLib.WingCreateHyper = function( WingId, Open )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NObject.CreateHyper( { Object = ship, Open = Open } )
        end
    end
end

-- Setzt den Akteur vom Leader des Wings.
MissionLib.SetLeaderAsActor = function( WingId, Actor )
    if WingId then
        local ship = get( "Logic.Wings."..WingId..".leader", nil )
        if ship then
            NShip.SetActor( { Ship = ship, Actor = Actor } )
        end
    end
end

-- Setzt den Akteur eines Wingman des Wings (Member 1-10).
MissionLib.SetMemberAsActor = function( WingId, Member, Actor )
    if WingId then
        local ship = get( "Logic.Wings."..WingId..".ship"..Member, nil )
        if ship then
            NShip.SetActor( { Ship = ship, Actor = Actor } )
        end
    end
end

-- Setzt den Akteur für alle Schiffe im Frachterwing.
-- Frachter und Geleitschutz können unterschiedliche Akteure haben.
MissionLib.SetActorFreighterWing = function( WingId, ActorFreighter, ActorWingman )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            if i == 2 then ActorFreighter = ActorWingman; end
            NShip.SetActor( { Ship = ship, Actor = ActorFreighter } )
        end
    end
end

-- Setzt den Standardakteur für alle Schiffe im Wing.
MissionLib.WingResetActor = function( WingId )
    if WingId then
        for i, ship in NWing.List( { Wing = WingId } ).ShipList do
            NObject.ResetActor( { Object = ship } )
        end
    end
end

-- Prüft, ob der Spieler ein Feind des Wings ist.
MissionLib.IsHostilePlayer = function( WingId )
    if WingId then
        return NWing.IsHostileShip( { Wing = WingId, Ship = get( PLAYER_SHIP_ID ) } ).Hostile
    end
end

-- Prüft, ob der angegebene Wing 'AimWingId' ein Feind des Wings ist.
MissionLib.IsHostileWing = function( WingId, AimWingId )
    if WingId and AimWingId then
        local ship = get( "Logic.Wings."..AimWingId..".leader", nil )
        if ship then
            return NWing.IsHostileShip( { Wing = WingId, Ship = ship } ).Hostile
        end
    end
end

-- Die Feindliste des Wings wird gelöscht. Mit Prüfung, ob der Wing auch existiert.
MissionLib.WingNoEnemy = function( WingId )
    if WingId and NWing.IsWing( { Wing = WingId } ).IsWing == 1 then
        NWing.NoEnemy( { Wing = WingId } )
    end
end

-- Friert das Schiff ein und schaltet die Unsterblichkeit aus, wenn 'Status' true|1 ist,
-- umgekehrt wird es mit 'Status' = false|0 aufgetaut und macht es wieder unsterblich.
MissionLib.FreezeAndUnprotectShip = function( ShipId, Status )
    NObject.Freeze( { Object = ShipId, Freeze = Status } )
    NShip.Protect( { Ship = ShipId, Protect = not Status } )
end

-- Friert die in 'ShipList' übergebenen Schiffe ein (true) oder taut sie auf (false).
-- Eingefrorene Schiffe erhalten keine Zeitschritte und keine Kollisions-Ereignisse mehr.
MissionLib.FreezeShips = function( ShipList, Freeze )
    for i, ship in ShipList do
        NObject.Freeze( { Object = ship, Freeze = Freeze } )
    end
end

-- WingAi Wrapper für AI_ACTION_STANDARD, startet die Standardlogik eines Wings.
MissionLib.WingAiActionStandard = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_STANDARD } }
        } )
    end
end

-- Der Wing springt sofort in den Hyperraum. Es wird nicht geprüft, ob er auch existiert.
MissionLib.WingHyperJumpNow = function( WingId )
    NWing.AddAction( {
        Wing = WingId,
        List = LIST_ACTIVE,
        First = 1,
        Actions = { SOFORTSPRUNG }
    } )
end

-- Der Wing springt in den Hyperraum. Ist 'Immediate' true, werden Gegner nicht angegriffen.
MissionLib.WingHyperOut = function( WingId, Immediate )
    if WingId and NWing.IsWing( { Wing = WingId } ).IsWing == 1 then
        local hyperjump = HYPERRAUM
        if Immediate then hyperjump = SOFORTSPRUNG; end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { hyperjump }
        } )
        NWing.ExecuteAi( { Wing = WingId } )
    end
end

-- WingAi Wrapper für AI_ACTION_OBJECT, Wing fliegt zum angegebenen Objekt, mit Geschwindigkeitangabe.
-- Gegner werden angegriffen, wenn der Parameter 'Attack' existiert
MissionLib.WingAiActionFlyToObject = function( WingId, Object, Speed, Attack, AddList )
    if WingId and Object then
        local goto = AI_ACTION_OBJECT1
        if Attack then goto = AI_ACTION_OBJECT2; end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = goto, Speed = Speed, Handle = Object } }
        } )
    end
end

-- Der Wing fliegt ohne Kursänderung zum angegebenen Objekt und springt anschließend in den Hyperraum.
MissionLib.WingAiActionFlyToObjectAndHyper = function( WingId, Object, AddList )
    if WingId and Object then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_OBJECT1, Handle = Object }, HYPERRAUM }
        } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position und wartet dort.
MissionLib.WingAiActionFlyToPosAndWait = function( WingId, Position, Speed, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = {
                { Type = AI_ACTION_POSITION1, Position = Position, Speed = Speed },
                WARTEN
            }
        } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur angegebenen Position und springt anschließend in den Hyperraum.
MissionLib.WingAiActionFlyToPosAndHyper = function( WingId, Position, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_POSITION1, Position = Position }, HYPERRAUM }
        } )
    end
end

-- Der Wing fliegt ohne Kursänderung zur Position und führt anschließend die angegebene Aktion aus.
-- Kleine Schiffe (auch als Wingleader) dürfen die Formation zur Abwehr von Feinden verlassen.
-- Wurde keine Aktion angegeben, geht der Wing am Ziel zur Standardlogik über.
MissionLib.WingGotoEscortAndAction = function( WingId, Position, Action, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_ESKORTE, Position = Position }, Action }
        } )
    end
end

-- Die Feindliste des Wings wird gelöscht und er zieht sich zur angegebenen Position zurück.
-- Optional kann eine Geschwindigkeit und eine zweite anschließende Aktion übergeben werden.
MissionLib.RetreatNow = function( WingId, Pos, Speed, Action )
    if WingId then
        local wing = {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { { Type = AI_ACTION_POSITION1, Position = Pos, Speed = Speed }, Action }
        }
        NWing.NoEnemy( wing )
        NWing.AddAction( wing )
        NWing.ExecuteAi( wing )
    end
end

-- Der Wing fliegt ohne Kursänderung in der aktuellen Richtung bis zur angegebenen Entfernung
-- weiter geradeaus. Kleine Schiffe dürfen die Formation zur Abwehr von Feinden verlassen.
-- Wurde in 'Distance' keine Entfernung übergeben, fliegt der Wing 1000 Units weit.
MissionLib.WingAiActionMoveAhead = function( WingId, Distance, AddList )
    if WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            if not Distance then Distance = 1000000; end
            local align = NShip.GetAlignment( { Ship = leader } )
            NWing.AddAction( {
                Wing = WingId,
                List = LIST_ACTIVE,
                First = not AddList,
                Actions = { {
                    Type = AI_ACTION_ESKORTE,
                    Position = MissionLib.GetPosInDistance( align.Pos, align.Front, Distance )
                } }
            } )
        end
    end
end

-- Manchmal ignoriert ein Wing den nächsten Aktionsbefehl und springt stattdessen in den Hyperraum.
-- Dem kann mit diesem Marschbefehl zur eigenen Position des Wings entgegengewirkt werden.
MissionLib.WingAiActionDummyMove = function( WingId, AddList )
    if WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            NWing.AddAction( {
                Wing = WingId,
                List = LIST_ACTIVE,
                First = not AddList,
                Actions = { {
                    Type = AI_ACTION_POSITION1,
                    Position = NObject.GetPosition( { Object = leader } ).Position
                } }
            } )
        end
    end
end

-- WingAi Wrapper für AI_ACTION_BOSSKREISEN, kreist um die eigene Position.
-- Der Wing feuert auf Gegner, wenn er angegriffen wird, beendet das Kreisen aber nicht.
MissionLib.WingAiActionBossKreisen = function( WingId, Radius, AddList )
    if WingId then
        local leader = get( "Logic.Wings."..WingId..".leader", nil )
        if leader then
            NWing.AddAction( {
                Wing = WingId,
                List = LIST_ACTIVE,
                First = not AddList,
                Actions = { {
                    Type = AI_ACTION_BOSSKREISEN,
                    Speed = Radius,
                    Position = NObject.GetPosition( { Object = leader } ).Position
                } }
            } )
        end
    end
end

-- WingAi Wrapper für AI_ACTION_BERGEN, Wing soll einen einzelnen Container aufnehmen.
MissionLib.WingAiActionBergen = function( WingId, Container, AddList )
    if WingId and Container then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_BERGEN, Handle = Container } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_BERGEN, Wing soll einen oder mehrere Container aufnehmen.
-- Der Parameter 'ContainerList' muss eine Tabelle mit den Handles der Container sein.
MissionLib.WingAiActionBergenEx = function( WingId, ContainerList, AddList )
    if WingId and lua.type( ContainerList ) == "table" then
        local pickup = {}
        for i, container in ContainerList do
            pickup[i] = { Type = AI_ACTION_BERGEN, Handle = container }
        end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = pickup
        } )
        end
    end
end

-- WingAi Wrapper für AI_ACTION_BERGEN, Frachterwing soll einen oder mehrere Container aufnehmen.
-- Der Parameter 'ContainerList' muss eine Tabelle mit den Handles der Container sein.
-- Frachter benötigen einen Zwischenschritt, sonst hauen sie nach Aufnahme des ersten Containers ab.
-- Die Aktion muss vom Typ AI_ACTION_OBJECT1 sein, AI_ACTION_OBJECT2 geht nicht.
MissionLib.WingAiActionBergenFrachter = function( WingId, ContainerList, AddList )
    if WingId and lua.type( ContainerList ) == "table" then
        local pickup = {}
        local i = 1
        for n, container in ContainerList do
            pickup[i] = { Type = AI_ACTION_OBJECT1, Handle = container }
            pickup[i+1] = { Type = AI_ACTION_BERGEN, Handle = container }
            i = i + 2
        end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = pickup
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_BERGEN, Wing soll einen einzelnen Container aufnehmen und dann landen.
MissionLib.WingAiActionRescueAndLand = function( WingId, Container, Hangar, AddList )
    if WingId and Container then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = {
                { Type = AI_ACTION_BERGEN, Handle = Container },
                { Type = AI_ACTION_LANDEN, Handle = Hangar }
            }
        } )
    end
end

-- Der Wing soll einen einzelnen Container abwerfen und dann die angegebene Aktion ausführen.
-- Wurde kein Container angegeben, werfen alle Schiffe des Wings alle ihre Container ab.
-- Wurde keine Aktion angegeben, geht der Wing nach dem Abwurf zur Standardlogik über.
MissionLib.DropContainerAndAction = function( WingId, Container, Action, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_ABWERFEN, Handle = Container }, Action }
        } )
    end
end

-- Der Wing soll mehrere Container abwerfen und dann die angegebene Aktion ausführen.
-- Der Parameter 'ContainerList' muss eine Tabelle mit den Handles der Container sein.
-- Existiert ein Container nicht oder ist nicht am Wing, wird sein Eintrag ignoriert.
-- Wurde keine Aktion angegeben, geht der Wing nach dem Abwurf zur Standardlogik über.
MissionLib.DropContainerListAndAction = function( WingId, ContainerList, Action, AddList )
    if WingId then
        local drop = {}
        local index = 1
        for i, container in ContainerList do
            if NContainer.GetType( { Container = container } ).Type ~= CONTAINER_NONE then
                drop[index] = { Type = AI_ACTION_ABWERFEN, Handle = container }
                index = index + 1
            end
        end
        if Action then
            drop[index] = Action
        end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = drop
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_DESTROYOBJ, Wing soll ein oder mehrere Objekte zerstören.
-- 'Objects' sollte eine Tabelle mit den Handles der Objekte sein (meistens Container),
-- es darf aber auch ein einzelnes Objekt übergeben werden.
MissionLib.WingAiActionDestroyObjects = function( WingId, Objects, AddList )
    if WingId then
        local destroy = {}
        if lua.type( Objects ) ~= "table" then
            destroy[1] = { Type = AI_ACTION_DESTROYOBJ, Handle = Objects }
        else
            for i, object in Objects do
                destroy[i] = { Type = AI_ACTION_DESTROYOBJ, Handle = object }
            end
        end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = destroy
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_LANDEN bzw. AI_ACTION_SOFORTLANDEN, Wing soll (sofort) landen.
-- 'Hangar' ist eine Handelsstation, eine Forschungsstation, ein Asteroid oder ein Kreuzer.
MissionLib.WingAiActionLanden = function( WingId, Hangar, Immediate, AddList )
    if WingId and Hangar then
        local land = AI_ACTION_LANDEN
        if Immediate then land = AI_ACTION_SOFORTLANDEN; end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = land, Handle = Hangar } }
        } )
    end
end

-- Wie "MissionLib.WingAiActionLanden", mit Geschwindigkeitsangabe.
MissionLib.WingAiActionLandenEx = function( WingId, Hangar, Speed, Immediate, AddList )
    if WingId then
        local land = AI_ACTION_LANDEN
        if Immediate then land = AI_ACTION_SOFORTLANDEN; end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = land, Handle = Hangar, Speed = Speed } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_FOLGESCHIFF, der Wing folgt dem Spieler.
-- Offset (optional) ist ein Richtungsvektor vom Spieler zum Leader des Wings.
MissionLib.WingAiActionFollowPlayer = function( WingId, Offset, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { {
                Type = AI_ACTION_FOLGESCHIFF,
                Handle = get( PLAYER_SHIP_ID ),
                Position = Offset
            } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_FOLGESCHIFF, der Wing folgt einem anderen Schiff.
-- Offset (optional) bestimmt die Position des Wings relativ zum Leader des Zielwings.
MissionLib.WingAiActionFollowShip = function( WingId, AimShip, Offset, AddList )
    if WingId and AimShip then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_FOLGESCHIFF, Handle = AimShip, Position = Offset } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_BESCHUETZEN, Wing soll einen anderen Wing beschützen.
-- Offset (optional) bestimmt die Position des Wings relativ zum Leader des Zielwings.
-- PROBLEM: Soll ein Militärwing aus mehreren Schiffen von einem Kreuzer starten und man
-- weist ihm gleich nach der Erzeugung diese Aktion zu, startet nur ein einziges Schiff
-- und danach selbst dann keins mehr, wenn man einen neuen Wing im Hangar erzeugt!
MissionLib.WingAiActionBeschuetzen = function( WingId, AimWingId, Offset, AddList )
    if WingId and AimWingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_BESCHUETZEN, Handle = AimWingId, Position = Offset } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_FOLGESCHIFF mit anschließendem AI_ACTION_BESCHUETZEN.
-- Der Wing folgt einem anderen Schiff und beschützt es und seinen Wing im Falle eines Angriffs.
-- Offset (optional) bestimmt die Position des Wings relativ zum Leader des Zielwings.
-- Funktioniert auch beim Start eines Militärwings aus mehreren Schiffen von einem Kreuzer!
MissionLib.WingAiActionProtectShip = function( WingId, AimShip, Offset, AddList )
    if WingId and AimShip then
        local aimWing = get( "Logic.StarShips."..AimShip..".wingId", nil )
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = {
                { Type = AI_ACTION_FOLGESCHIFF, Handle = AimShip, Position = Offset },
                { Type = AI_ACTION_BESCHUETZEN, Handle = aimWing, Position = Offset }
            }
        } )
    end
end

-- Zwei Wings werden zueinander feindlich.
MissionLib.AddEnemies = function( WingA, WingB, Priority )
    if WingA and WingB then
        NWing.AddEnemy( { Wing = WingA, Target = WingB, Priority = Priority } )
        NWing.AddEnemy( { Wing = WingB, Target = WingA, Priority = Priority } )
    end
end

-- WingAi Wrapper für AI_ACTION_WARTEN mit anschließendem AI_ACTION_CONTANGRIFF.
-- Der Wing soll regungslos warten, bis seine Gegnerliste einen Eintrag erhält.
-- Dann geht er zum Angriff über.
MissionLib.WingAiActionWaitAndAttack = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { WARTEN, CONTANGRIFF, HYPERRAUM }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_ANGRIFF, Wing greift einen anderen Wing an.
-- Der gegnerische Wing wird aber erst bei tatsächlichem Beschuss feindlich.
-- Der Parameter 'AimWingId' des Ziels darf auch ein einzelnes Schiff sein.
MissionLib.WingAiActionAttack = function( WingId, AimWingId, AddList )
    if WingId then
        if AimWingId then
            NWing.AddEnemy( { Wing = WingId, Target = AimWingId } )
        end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { ANGRIFF }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_CONTANGRIFF, Wing greift alle seine Feinde an.
MissionLib.WingAiActionContAttack = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { CONTANGRIFF }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_CONTANGRIFF, Wing greift einen anderen Wing an.
-- Der gegnerische Wing wird aber erst bei tatsächlichem Beschuss feindlich.
-- Der Parameter 'AimWingId' des Ziels darf auch ein einzelnes Schiff sein.
MissionLib.WingAiActionContAngriff = function( WingId, AimWingId, AddList )
    if WingId then
        if AimWingId then
            NWing.AddEnemy( { Wing = WingId, Target = AimWingId } )
        end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { CONTANGRIFF }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_CONTANGRIFF, Wing greift alle Gegner an und wartet anschließend.
MissionLib.WingAiActionAttackAndWait = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { CONTANGRIFF, WARTEN }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_ANGRIFF, Wing greift den Spieler an.
MissionLib.WingAiActionAttackPlayer = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { { Type = AI_ACTION_ANGRIFF, Handle = get( PLAYER_SHIP_ID ) } }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_ANGRIFF mit anschließendem Hyperraumsprung.
MissionLib.WingAiActionAttackAndHyper = function( WingId, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { ANGRIFF, HYPERRAUM }
        } )
    end
end

-- WingAi Wrapper für AI_ACTION_ANGRIFF mit anschließender Landung.
MissionLib.WingAiActionAttackAndLand = function( WingId, Hangar, AddList )
    if WingId and Hangar then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = { ANGRIFF, { Type = AI_ACTION_LANDEN, Handle = Hangar } }
        } )
    end
end

-- WingAi Wrapper für beliebige aufeinanderfolgende Aktionen.
-- Dem Parameter 'ActionList' wird eine Tabelle mit den durchzuführenden Aktionen übergeben.
MissionLib.WingAiAddActions = function( WingId, ActionList, AddList )
    if WingId then
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = not AddList,
            Actions = ActionList
        } )
    end
end

-- Wing macht einen HyperJump ins angegebene System.
-- Für den Parameter 'SystemId' kann sowohl die Id als auch das Handle des Systems übergeben werden.
-- Geht nur, wenn die DSO dem Wing beigetreten ist, ansonsten wird der Wing nach dem Sprung gelöscht.
MissionLib.WingHyperJumpTo = function( WingId, SystemId, Immediate )
    if WingId then
        if SystemId <= 402 then
            SystemId = NStarSystem.GetHandleFromId( { Id = SystemId } ).Handle
        end
        local hyperjump = AI_ACTION_HYPERRAUM
        if Immediate then hyperjump = AI_ACTION_SOFORTSPRUNG; end
        NWing.AddAction( {
            Wing = WingId,
            List = LIST_ACTIVE,
            First = 1,
            Actions = { { Type = hyperjump, Handle = SystemId } }
        } )
        NWing.ExecuteAi( { Wing = WingId } )
    end
end

-- Die DSO macht einen sofortigen HyperJump ins angegebene System.
-- Für den Parameter 'SystemId' kann sowohl die Id als auch das Handle des Systems übergeben werden.
-- Funktioniert leider nur, wenn die DSO einem KI-Wing beigetreten ist, nicht aber alleine.
MissionLib.PlayerHyperJumpTo = function( SystemId )
    if SystemId <= 402 then
        SystemId = NStarSystem.GetHandleFromId( { Id = SystemId } ).Handle
    end
    local player = get( PLAYER_WING_ID )
    NWing.AddAction( {
        Wing = player,
        List = LIST_ACTIVE,
        First = 1,
        Actions = { { Type = AI_ACTION_SOFORTSPRUNG, Handle = SystemId } }
    } )
    NWing.ExecuteAi( { Wing = player } )
end

-- Testsprung des Spielerschiffs zusammen mit einem Hunter in ein beliebiges System.
-- Nach Ankunft im Zielsystem sollte der Spieler mit NPlayer.EndEscort({}) wieder aus dem
-- Wing entlassen werden, sonst kann er nicht springen, solange der Hunter noch existiert.
MissionLib.PlayerTestJumpTo = function( SystemId )
    local hunter = NWing.Create( {
        WingType = WINGTYPE_HUNTER,
        Number   = 1,
        PosType  = POSDESCR_PLAYERSHIP
    } ).Wing
    NPlayer.EscortNPC( { Ship = MissionLib.GetWingLeaderID( hunter ) } )
    MissionLib.WingHyperJumpTo( hunter, SystemId )
    return hunter
end

-- Testsprung ist beendet, Eskorte beenden und Hunter zerstören.
MissionLib.EndTestJump = function( WingId )
    if not WingId then WingId = get( PLAYER_WING_ID ); end
    if WingId ~= NO_WING_ID then
        NPlayer.EndEscort({})
        NWing.Destroy( { Wing = WingId } )
    end
end

-- Eona schreit, wenn das Spielerschiff zerstört wird.
-- Sollte im "StarshipDeath"-Event aufgerufen werden, in "StarshipDestroyed" kann es schon zu spät sein.
MissionLib.PlayerDeath = function()
    if NPlayer.IsEona({}).Eona and NStory.Progress({}).Chapter < 6 then
        NComm.AddMessage( EONA_DEATH_MSG )
    end
    NSound.PlayUserSound( { File = "FU.Battle.explosion1" } )
end

--============================[ Kommunikation ]=================================

-- Eona labert was. Ohne Prüfung, ob sie auch an Bord ist.
MissionLib.EonaMessage = function( Text )
    return NComm.AddMessage( { Text = Text, Actor = "eona" } ).Message
end

-- Eona ärgert sich. Ohne Prüfung, ob sie auch an Bord ist.
MissionLib.EonaAngryMessage = function( Text )
    return NComm.AddMessage( {
        Text  = Text,
        Actor = "eona",
        Video = "video/radio/radio_eona_angry.bik"
    } ).Message
end

-- Kayron quatscht. Für Skripts, in denen die BattleLib.lua nicht importiert wird.
MissionLib.KayronMessage = function( Text )
    return NComm.AddMessage( { Text = Text, Actor = "kayron" } ).Message
end

-- Kayron droht. Es muss ein einzelner Funkspruch aus den Drohmeldungen übergeben werden, wie z.B.
-- "IDC_KAYRON_TAUNT_63". Pfad und Suffix werden automatisch ergänzt und sind nicht mit anzugeben.
MissionLib.KayronTaunt = function( Taunt )
    return NComm.AddMessage( {
        Text  = Taunt,
        Voice = "VOICE.KAYRON_TAUNT_kayron."..Taunt.."_SPOKEN_kayron",
        Actor = "kayron"
    } ).Message
end

-- Kayron droht. Zufällige Auswahl aus allen vorhandenen Funksprüchen.
-- Mit dem optionalen Parameter 'MessageList' kann die Auswahl der Sprüche auf die
-- in der Liste (z.B. KAYRON_TAUNT_1) enthaltenen Message-IDs eingeschränkt werden.
MissionLib.KayronTauntMessage = function( MessageList )
    local taunt = ""    -- Bei Zufallssprüchen ist keine Textanzeige möglich
    local voice = "VOICE.KAYRON_TAUNT_kayron"
    if MessageList then -- Hier ist die Textanzeige möglich
        taunt = "IDC_KAYRON_TAUNT_"..MissionLib.RandomFromTable( MessageList )
        voice = voice.."."..taunt.."_SPOKEN_kayron"
    end
    return NComm.AddMessage( { Text = taunt, Voice = voice, Actor = "kayron" } ).Message
end

-- Sendet eine Funknachricht von der Handelsstation, wenn kein Sender angegeben ist.
-- Für den Sender kann ein beliebiges Handle einer Station, Wings oder Schiffs übergeben werden.
-- Das sendende Objekt muss existieren und der Text sollte den passenden Akteur referenzieren.
MissionLib.SendMessage = function( Text, Sender )
    if not Sender then
        Sender = NStarSystem.GetTradeStation({}).Handle
    end
    return NComm.AddMessage( { Text = Text, Sender = Sender, CommInOut = 1 } ).Message
end

-- Sendet eine Funknachricht und zeigt dabei das Ziel 'Target' mit der angegebenen Kamera an.
-- Anders als bei der Funktion BattleLib.SendCamMessage wird der Sender immer als Handle-Wert
-- übergeben und es können außerdem auch beliebige Sender, Kameras und Ziele angegeben werden.
-- Dem Parameter 'Data' muss eine Tabelle mit allen für die verwendete Kamera benötigten
-- Parametern außer dem ersten übergeben werden. Der erste Parameter ist immer das Target und
-- meistens ein Wing- oder Starship-Handle, im Falle von ShowStation auch eine Positionsangabe.
-- Die Funktion liefert eine Tabelle mit den Werten 'Message' und 'Camera' zurück.
-- Im folgenden Beispiel sendet der Spieler eine Nachricht an einen Wing,
-- dabei wird der Wing mit der BigBoy-Kamera aus der CameraLib.lua gefilmt:
--   local video = MissionLib.SendCamMessage( V.Player, "IDM_BLA", V.Wing, "BigBoy", { time, zoom } )
--   V.Msg = video.Message
--   V.Cam = video.Camera
MissionLib.SendCamMessage = function( Sender, Text, Target, Camera, Data )
    local table = {}
    local par1, par2, par3, par4
    if lua.type( Data ) == "table" then
        if Data[1] then par1 = Data[1]; end
        if Data[2] then par2 = Data[2]; end
        if Data[3] then par3 = Data[3]; end
        if Data[4] then par4 = Data[4]; end
    end
    table.Message = NComm.AddMessage( { Sender = Sender, Text = Text } ).Message
    table.Camera = CameraLib[Camera]( Target, par1, par2, par3, par4 ).Camera
    return table
end

-- Bricht eine laufende Funknachricht sofort ab. Optional kann ein Sender angegeben werden.
MissionLib.EndMessage = function( Sender )
    if not NComm.IsQueueEmpty({}).Empty then
        if Sender then
            NComm.AddMessage( {
                Text = "",
                Voice = "IDM_COMMON_RADIO_NOTHING", -- 1/40 Sekunde Stille
                Sender = Sender
            } )
        else
            NComm.AddMessage( { Text = "" } )
        end
    end
end

--============================[ Container und Waren ]===========================

-- Liefert eine Liste mit allen Handelswaren.
MissionLib.CargoList = function()
    return {
    0,	-- GOODS_COALHYDRATES
    1,	-- GOODS_PROTEINS
    2,	-- GOODS_LIFEFORMS
    3,	-- GOODS_VEGFIBERS
    4,	-- GOODS_METALS
    5,	-- GOODS_PRECMETALS
    6,	-- GOODS_CRYSTALS
    7,	-- GOODS_ALLOYS
    8,	-- GOODS_MACHINERY
    9,	-- GOODS_ELECTRONICS
    10,	-- GOODS_COMPUTERS
    11,	-- GOODS_SHIPTECHS
    12,	-- GOODS_MEDICINE
    13,	-- GOODS_CHEMICALS
    14,	-- GOODS_LIQUOR
    15,	-- GOODS_FERTILIZER
    16,	-- GOODS_ENERGYCELLS
    17,	-- GOODS_FUELRODS
    18,	-- GOODS_ISOTOPES
    19,	-- GOODS_SUPERCONDUCTORS
    20,	-- GOODS_VIDEOGAMES
    21,	-- GOODS_LUXURIES
    22,	-- GOODS_ANDROIDS
    23	-- GOODS_DRUGS
    }
end

-- Liefert eine Liste mit allen Importwaren des Systems (immer genau 19 Güter).
MissionLib.ImportList = function( SystemId )
    local importlist = MissionLib.CargoList()
    for i, goods in TRADE_GOODS[SystemId] do	-- Liste der Exportwaren
        importlist[goods + 1] = nil  -- Exportware in der Warenliste löschen
    end
    return MissionLib.CompactTable( importlist )
end

-- Liefert eine Liste mit Importwaren des Systems ohne spezielle Waren (15 bis 19 Güter).
MissionLib.ImportListEx = function( SystemId )
    local importlist = {}
    local first = 0
    local count = 0
    for i, export in TRADE_GOODS[SystemId] do	-- Liste der Exportwaren
        if export > GOODS_SUPERCONDUCTORS then
            return importlist, count
        end
        for goods = first, export - 1 do
            count = count + 1
            importlist[count] = goods
        end
        first = export + 1
    end
    return importlist, count
end

-- Liefert eine Kopie der Liste mit diversen Missionswaren und deren Anzahl.
MissionLib.MissionCargoList = function()
    return MissionLib.CopyTable( MISSION_GOODS ), lua.getn( MISSION_GOODS )
end

-- Liefert eine zufällige Handelsware.
MissionLib.RandomGoods = function()
    return lua.tonumber( math.random() * 24 )
end

-- Liefert eine zufällige Handelsware ohne spezielle Waren.
MissionLib.RandomTradeGoods = function()
    return lua.tonumber( math.random() * 20 )
end

-- Liefert eine zufällige spezielle Ware.
MissionLib.RandomSpecialGoods = function()
    return lua.tonumber( math.random() * 4 + 20 )
end

-- Liefert eine zufällige Exportware des Systems.
MissionLib.RandomExportGoods = function( SystemId )
    return TRADE_GOODS[SystemId][MissionLib.RandomInt1( 5 )]
end

-- Liefert eine zufällige Exportware des Systems ohne spezielle Ware.
MissionLib.RandomExportGoodsEx = function( SystemId )
    local tradegoods = TRADE_GOODS[SystemId]    -- Liste der Exportwaren
    for i = 5, 1, -1 do
        if tradegoods[i] <= GOODS_SUPERCONDUCTORS then
            return tradegoods[MissionLib.RandomInt1( i )]
        end
    end
end

-- Liefert eine zufällige Importware des Systems.
MissionLib.RandomImportGoods = function( SystemId )
    return MissionLib.ImportList( SystemId )[MissionLib.RandomInt1( 19 )]
end

-- Liefert eine zufällige Importware des Systems ohne spezielle Ware.
MissionLib.RandomImportGoodsEx = function( SystemId )
    local importlist, count = MissionLib.ImportListEx( SystemId )
    return importlist[MissionLib.RandomInt1( count )]
end

-- Erstellt eine Liste für Container mit jeweils einer zufälligen Exportware des Systems.
-- Der Parameter 'Count' gibt die maximal gewünschte Anzahl der Container an.
MissionLib.RandomExportList = function( SystemId, Count )
    local cargolist = {}
    local tradegoods = TRADE_GOODS[SystemId]	-- Liste der Exportwaren
    for i = 1, Count do
        cargolist[i] = tradegoods[MissionLib.RandomInt1( 5 )]
    end
    return cargolist
end

-- Erstellt eine Liste für Container mit jeweils einer zufälligen Importware des Systems.
-- Der Parameter 'Count' gibt die maximal gewünschte Anzahl der Container an.
MissionLib.RandomImportList = function( SystemId, Count )
    local cargolist = {}
    local importlist = MissionLib.ImportList( SystemId )
    for i = 1, Count do
        cargolist[i] = importlist[MissionLib.RandomInt1( 19 )]
    end
    return cargolist
end

-- Liefert eine zufällige Missionsware oder auch mehrere, falls 'Count' angeben wurde.
-- Ist 'Count' größer als 1, wird eine Liste mit der Anzahl zufälliger Missionswaren geliefert.
MissionLib.RandomMissionCargo = function( Count )
    local listsize = lua.getn( MISSION_GOODS )
    if Count and Count > 1 then
        local missioncargo = {}
        for i = 1, Count do
            missioncargo[i] = MISSION_GOODS[MissionLib.RandomInt1( listsize )]
        end
        return missioncargo
    end
    return MISSION_GOODS[MissionLib.RandomInt1( listsize )]
end

-- Liefert die im System vorhandene Menge der angegebenen (auch verbotenen) Ware.
MissionLib.GetAmountOfGoods = function( SystemId, Goods )
    return get( "Logic.StarSystems."..SystemId..".goods"..Goods, 0 )
end

-- Liefert eine Liste mit den im System vorhandenen Mengen aller Waren.
-- Der Tabellenindex beginnt bei Null (Kohlenhydrate) und ist somit gleich dem Warenindex.
MissionLib.GetAmountOfAllGoods = function( SystemId )
    local amount = {}
    local goods = "Logic.StarSystems."..SystemId..".goods"
    for i = 0, 23 do
        amount[i] = get( goods..i, 0 )
    end
    return amount
end

-- Liefert eine Liste mit den im System vorhandenen Mengen der speziellen Waren.
-- Selbst verbotene Waren, die nicht im System erhältlich sind, werden berücksichtigt.
-- Der Tabellenindex beginnt bei 20 (Videospiele) und ist somit gleich dem Warenindex.
MissionLib.GetAmountOfSpecialGoods = function( SystemId )
    local amount = {}
    local goods = "Logic.StarSystems."..SystemId..".goods"
    for i = 20, 23 do
        amount[i] = get( goods..i, 0 )
    end
    return amount
end

-- Prüft, ob der angegebene Container existiert und sich im All befindet.
MissionLib.IsContainerInSpace = function( Container )
    if Container and NContainer.IsInSpace( { Container = Container } ).InSpace == 1 then
        return 1
    end
end

-- Liefert die Containergröße, wenn das Objekt ein Container ist, ansonsten nil.
MissionLib.IsContainer = function( Object )
    if Object then
        local size = NContainer.GetType( { Container = Object } ).Type
        if size ~= CONTAINER_NONE then
            return size
        end
    end
end

-- Liefert Gesamtkapazität, Containergröße und Anzahl der Containerplätze (auch freie) eines Frachters.
-- Nützlich für Frachter, die mit zufällig bestimmten und daher unbekannten Werten erzeugt wurden.
-- (z.B. WINGTYPE_PIRATEFREIGHTER) Es wird lediglich das Schiffshandle für diese Funktion benötigt.
-- ( Anm.: Funktioniert hier nur, wenn der Frachter noch nicht voll beladen ist, siehe Kommentare.
--   Daher sollte dieser Code besser direkt im Missionsskript umgesetzt werden.)
MissionLib.GetFreighterCapacity = function( Ship )
    local size, bays
    local free = NShip.GetNumCargoBays( { Ship = Ship, Free = true } ).NumCargoBays
    if free == 0 then
        local containerlist = NShip.DumpCargo( { Ship = Ship } ).ContainerList
        size = NContainer.GetType( { Container = containerlist[1] } ).Type
        bays = lua.getn( containerlist )
        -- Funktioniert hier nicht, Absturz! Das Andocken muss zeitverzögert erfolgen:
        for i, container in containerlist do
            NShip.AddContainer( { Ship = Ship, Container = container } )
        end
    else
        -- Geht nur, wenn der Container für den letzten freien Platz noch nicht aufgenommen wurde:
        local container = NShip.EquipContainer( { Ship = Ship, Goods = "" } ).Container
        size = NContainer.GetType( { Container = container } ).Type
        bays = NShip.GetNumCargoBays( { Ship = Ship } ).NumCargoBays
        NContainer.Destroy( { Container = container } )
    end
    return CONTAINER_TONS[size] * bays, size, bays, free
end

-- Füllt einen Container mit der angegebenen oder einer zufälligen Ware.
-- Das Containerhandle muss übergeben werden, Ware und Menge sind optional.
MissionLib.EquipContainer = function( Container, Goods, Amount )
    if not Goods or Goods == "Random" then
        Goods = lua.tonumber( math.random() * 24 )
    end
    NContainer.Equip( { Container = Container, Goods = Goods, Amount = Amount } )
end

-- Erzeugt für alle freien Containerplätze eines Frachters Container,
-- die mit einer einzigen Warensorte beladen sind und dockt sie am Schiff an.
MissionLib.LoadCargoGoods = function( Ship, CargoToLoad )
    local containerlist = {}
    local cargo = { Ship = Ship, Goods = CargoToLoad }
    for i = 1, NShip.GetNumCargoBays( { Ship = Ship, Free = true } ).NumCargoBays do
        containerlist[i] = NShip.EquipContainer( cargo ).Container
    end
    return containerlist
end

-- Erzeugt für alle freien Containerplätze einen Container mit zufälliger Ware
-- und dockt den Container am Schiff an. Liefert je eine Liste mit der Ladung
-- und den Containerhandles zurück:  EquipShip( Ship ) : { ContainerList, CargoList }
MissionLib.EquipShip = function( Ship )
    local containerlist = {}
    local freebays = NShip.GetNumCargoBays( { Ship = Ship, Free = true } ).NumCargoBays
    local cargolist = MissionLib.GetCargoList( freebays )
    for i, cargo in cargolist do
        containerlist[i] = NShip.EquipContainer( { Ship = Ship, Goods = cargo } ).Container
    end
    return { ContainerList = containerlist, CargoList = cargolist }
end

-- Erzeugt für jeden freien Containerplatz einen mit genau einer zufälligen Ware gefüllten Container
-- und dockt ihn am Frachter an. Es werden dafür maximal 'NrOfGoods' unterschiedlicher Waren ermittelt.
-- Übersteigt 'NrOfGoods' die Anzahl freier Plätze, wird die Anzahl entsprechend gekürzt.
-- Ist 'NrOfGoods' = 0 oder nil, wird der Frachter mit leeren Containern beladen.
MissionLib.LoadCargoMax = function( Ship, NrOfGoods )
    local containerlist = {}
    local freebays = NShip.GetNumCargoBays( { Ship = Ship, Free = true } ).NumCargoBays

    -- Leere Liste zurückliefern, falls kein Containerplatz mehr frei ist
    if freebays > 0 then

        -- Keine Warenanzahl angegeben, Frachter komplett mit leeren Containern bestücken
        if not NrOfGoods or NrOfGoods <= 0 then
            -- NShip.EquipContainer lässt keine leeren Container zu, daher Spezialcontainer
            -- Diese werden beim Andocken in passende und leere Frachtcontainer umgewandelt
            local container = { Type = CONTAINER_SHIP, Size = CONTAINER_SPECIAL, Ship = Ship }
            for i = 1, freebays do
                containerlist[i] = NContainer.Create( container ).Container
            end

        -- Frachter mit angegebener Anzahl von zufälligen Waren beladen
        else
            -- Maximale Warenanzahl prüfen
            if NrOfGoods > 24 then NrOfGoods = 24; end
            if NrOfGoods > freebays then NrOfGoods = freebays; end
            -- Einen Warenkorb mit der maximalen Anzahl unterschiedlicher Waren erzeugen
            local cargolist = MissionLib.CargoList()	-- Warenliste mit allen Handelswaren
            local cargo = {}				-- Warenkorb initialisieren
            local random = MissionLib.RandomInt1	-- Zufallsfunktion für Warenauswahl
            if NrOfGoods == 24 then
                cargo = cargolist			-- Alle Waren in den Korb
            else
                local fillpos = 0			-- Position im Korb
                local listsize = 24			-- Größe der Warenliste
                -- Jetzt den Warenkorb füllen:
                while fillpos < NrOfGoods do
                    local item = random( listsize )	-- Warenindex
                    fillpos = fillpos + 1		-- Nächste freie Position im Korb
                    cargo[fillpos] = cargolist[item]	-- Zufällige Ware in den Korb
                    -- Ist noch Platz im Korb?
                    if fillpos < NrOfGoods then
                        -- Letzter Eintrag wird ungültig, Größe der Warenliste anpassen
                        listsize = listsize - 1
                        -- Ware aus der Warenliste entfernen
                        for i = item, listsize do
                            cargolist[i] = cargolist[i+1]
                        end
                    end
                end
            end
            -- Von jeder Ware aus dem Warenkorb einen Container füllen und andocken
            for i, goods in cargo do
                containerlist[i] = NShip.EquipContainer( { Ship = Ship, Goods = goods } ).Container
            end
            -- Wenn noch Containerplätze frei sind, diese mit zufälligen Waren aus dem Korb beladen
            for i = NrOfGoods + 1, freebays do
                containerlist[i] = NShip.EquipContainer( {
                    Ship = Ship, Goods = cargo[random( NrOfGoods )]
                } ).Container
            end
        end
    end
    return containerlist
end

-- Erzeugt einen Spezialcontainer an der angegebenen Position und füllt ihn mit Handels- oder Missionsware.
-- Optional kann dem Container auch ein anderer Name anstelle des Standardnamens gegeben werden.
MissionLib.CreateSpecialContainer = function( Pos, Goods, Name )
    local container = NContainer.Create( {
        Type = CONTAINER_POSITION, Size = CONTAINER_SPECIAL, Position = Pos
    } ).Container
    NContainer.Equip( { Container = container, Goods = Goods } )
    if Name then
        NObject.SetSpecialName( { Object = container, Name = Name } )
    end
    return container
end

-- Erzeugt einen Spezial-Container und dockt ihn an den angegebenen Frachter an.
-- Dieser muss zum Transport von Containern der Größe CONTAINER_SPECIAL geeignet sein!
-- Der Container kann mit einer beliebigen Ware 'Goods' (StringId oder Handelsware)
-- befüllt werden, bei der Angabe von GOODS_WEAPON wird eine Geheimdienstwaffe hineingelegt.
-- Fehlt der Wert für 'Goods', wird ein leerer Spezial-Container erzeugt und angedockt.
MissionLib.EquipSpecialContainer = function( Freighter, Goods )
    local container = NContainer.Create( {
        Type = CONTAINER_SHIP, Size = CONTAINER_SPECIAL, Ship = Freighter
    } ).Container
    if Goods then
        if Goods == GOODS_WEAPON then
            NContainer.SetUniqueItems( { Container = container, Number = 1 } )
            Goods = "IDL_WEAPON_04"
        end
        NContainer.Equip( { Container = container, Goods = Goods } )
    end
    return container
end

-- Erzeugt einen Spezialcontainer des angegebenen Typs und legt eine Geheimdienstwaffe hinein.
-- Je nach Typ wird in 'Location' ein Erzeugungsbereich, ein Schiffshandle oder eine Position übergeben.
MissionLib.CreateWeapon = function( Type, Location )
    local data = { [0] =
        "PosDesc";	-- für Type = CONTAINER_SPACE
        "",		-- für Type = CONTAINER_ASTEROID (der Parameter ist noch unbekannt)
        "Ship",		-- für Type = CONTAINER_SHIP
        "Position"	-- für Type = CONTAINER_POSITION
    }
    local weapon = NContainer.Create( {
        Type = Type, Size = CONTAINER_SPECIAL, [data[Type]] = Location
    } ).Container
    NContainer.SetUniqueItems( { Container = weapon, Number = 1 } )
    NContainer.Equip( { Container = weapon, Goods = "IDL_WEAPON_04" } )
    return weapon
end

-- Erzeugt an der Position eines explodierenden Schiffs einen Spezialcontainer mit einer Geheimdienstwaffe.
-- Im Gegensatz zur Funktion "NContainer.CreateLoot" wird der Inhalt beim Scannen auch angezeigt.
MissionLib.CreateLoot = function( Ship )
    local weapon = NContainer.CreateLoot( { Ship = Ship, UniqueItems = 1 } ).Container
    NContainer.Equip( { Container = weapon, Goods = "IDL_WEAPON_04" } )
    return weapon
end

-- Setzt die RadarMapColor von ein oder mehreren Containern auf eine bestimmte Farbe.
-- Falls 'Color' nicht übergeben wird, verwendet die Funktion die Standardfarbe.
-- 'ContainerList' darf anstatt einer Tabelle auch ein einzelner Container sein.
MissionLib.SetContainerColor = function( ContainerList, Color )
    local RadarMapColor = NObject.RadarMapColor
    if not Color then Color = RADARMAP_INVALID end
    if lua.type( ContainerList ) == "table" then
        for i, container in ContainerList do
            RadarMapColor( { Object = container, Color = Color } )
        end
    else
        RadarMapColor( { Object = ContainerList, Color = Color } )
    end
end

-- Setzt oder entfernt das Scannersymbol an allen Containern in der Liste.
MissionLib.SetContainerScanningFlag = function( ContainerList, Set )
    for i, container in ContainerList do
        NObject.SetScanningFlag( { Object = container, Set = Set } )
    end
end

-- Liefert die Containerhandles des Spielers als numerische Tabelle sowie deren Anzahl zurück.
MissionLib.GetPlayerContainer = function()
    local containerlist = {}
    local cargo = NPlayer.GetContainer({})
    for i = 1, cargo.Number do
        containerlist[i] = cargo["Container"..(i-1)]
    end
    return containerlist, cargo.Number
end

-- Liefert die Handles der Container mit Handelswaren des Spielers als numerische Tabelle zurück.
-- Container mit Missionswaren werden dabei nicht mit in die Rückgabetabelle eingetragen.
MissionLib.GetPlayerTradeContainer = function()
    local count = 0
    local containerlist = {}
    local cargo = NPlayer.GetContainer({})
    for i = 0, cargo.Number - 1 do
        local container = cargo["Container"..i]
        if not NContainer.GetMissionGood( { Container = container } ).SpecialGood then
            count = count + 1
            containerlist[count] = container
        end
    end
    return containerlist
end

-- Prüft, ob der Spieler eine bestimmte Missionsware dabei hat und liefert deren Anzahl zurück.
MissionLib.PlayerHasMissionGood = function( Goods )
    local count = 0
    local container = NPlayer.GetContainer({})
    if container.Number > 0 then
        container.Number = nil
        for i, cargo in container do
            if NContainer.GetMissionGood( { Container = cargo } ).SpecialName == Goods then
                count = count + 1
            end
        end
    end
    return count
end

-- Diese Funktion prüft den übergebenen Container darauf, ob er schon zum "Geister-Container" wurde.
-- Warencontainer im All haben eine Lebensdauer von ca. 10-12 Minuten, bevor sie einfach verschwinden.
-- Werden sie zuvor aufgenommen und wieder abgeworfen, startet der Timeout für die Lebenszeit erneut.
-- In der Targetliste werden sie nach ihrem Verschwinden noch mit "-1.$u Container" angezeigt, können
-- jedoch nicht mehr angewählt werden. Ihre Handles sind aber noch weiterhin vorhanden und gültig.
-- Ist 'Destroy' = true, wird der Container in dem Fall sofort gelöscht.
-- Auch mit dem Neuladen des aktuellen Spielstands ist die Anzeige in der Targetliste wieder normal
-- und die unsichtbaren Geister-Container sind dann wirklich weg.
MissionLib.ContainerLifeTimeOver = function( Container, Destroy )
    if Container
    and NContainer.IsInSpace( { Container = Container } ).InSpace == 1
    and lua.tostring( NObject.DistanceFromPlayer( { Object = Container } ).Distance ) == "-1.#IND" then
        if Destroy then
            -- Es wird kein CONTAINER_DESTROYED Event ausgelöst!
            NContainer.Destroy( { Container = Container } )
        end
        return 1
    end
end

------------------------------[ Spezielle Waren ]-------------------------------

-- Ermittelt die verbotenen Spezialwaren eines Systems.
-- Fehlt der Parameter 'SystemId', wird die Id des aktuellen Systems verwendet.
MissionLib.GetIllegalGoods = function( SystemId )
    if not SystemId then SystemId = get( SYSTEM_ID ); end
    return MissionLib.CopyTable( ILLEGAL_GOODS[MissionLib.GetStarSystemGovernment( SystemId )] )
end

-- Ermittelt die erlaubten Spezialwaren eines Systems.
-- Fehlt der Parameter 'SystemId', wird die Id des aktuellen Systems verwendet.
MissionLib.GetLegalGoods = function( SystemId )
    if not SystemId then SystemId = get( SYSTEM_ID ); end
    return MissionLib.CopyTable( LEGAL_GOODS[MissionLib.GetStarSystemGovernment( SystemId )] )
end

-- Liefert eine Tabelle mit den erlaubten und verbotenen Spezialwaren eines Systems.
-- Fehlt der Parameter 'SystemId', wird die Id des aktuellen Systems verwendet.
-- Syntax: V.Goods = MissionLib.GetSpecialGoods( SystemId ) : { Legal, Illegal }
MissionLib.GetSpecialGoods = function( SystemId )
    if not SystemId then SystemId = get( SYSTEM_ID ); end
    local government = MissionLib.GetStarSystemGovernment( SystemId )
    return {
        Legal   = MissionLib.CopyTable( LEGAL_GOODS[government] ),
        Illegal = MissionLib.CopyTable( ILLEGAL_GOODS[government] )
    }
end

--============================[ Missionen ]=====================================

-- für allgemeine Missionen, Ausgabe der Nachricht "Mission erledigt!"
MissionLib.LogMissionAchieved = function()
    NGUI.ShowInfoText( { Text = "IDM_TUNNEL_001_WIN" } )
end

-- für allgemeine Missionen, Ausgabe der Nachricht "Mission erfolgreich"
MissionLib.LogMissionSuccess = function()
    NGUI.ShowInfoText( { Text = "IDM_MISSION_SUCCESS" } )
end

-- für Story Missionen, Ausgabe der Nachricht "Mission gescheitert"
MissionLib.LogStoryFailed = function()
    NGUI.ShowInfoText( { Text = "IDM_MISSION_FAILED" } )
end

-- für Story Missionen, Ausgabe der Nachricht "Neue Nachricht erhalten"
MissionLib.LogNewEmail = function()
    NGUI.ShowInfoText( { Text = "IDM_NEW_EMAIL" } )
end

-- für globale Missionen, Ausgabe der Nachricht "Neuer Tagebucheintrag"
MissionLib.LogNewEntry = function()
    NGUI.ShowInfoText( { Text = "IDM_NEW_LOGENTRY" } )
end

-- für globale Missionen, Ausgabe der Nachricht "Auftrag erfüllt"
MissionLib.LogTaskAchieved = function()
    NGUI.ShowInfoText( { Text = "IDM_TASK_ACHIEVED" } )
end

-- für globale Missionen, Ausgabe der Nachricht "Auftrag gescheitert"
MissionLib.LogTaskFailed = function()
    NGUI.ShowInfoText( { Text = "IDM_TASK_FAILED" } )
end

-- für globale Missionen, Ausgabe der Nachricht "Auftrag abgebrochen!"
MissionLib.LogTaskCanceled = function()
    NGUI.ShowInfoText( { Text = "IDM_TASK_CANCEL" } )
end

-- für globale Missionen, Ausgabe der Nachricht "'Credits' Cr Bonus erhalten"
-- Die maximal 7-stellige Prämie 'Credits' wird mit Tausendertrennzeichen angezeigt (z.B. "6.590")
MissionLib.LogBonusReceived = function( Credits )
    NGUI.ShowInfoText( { Text = "ID_BONUS", Replace = MissionLib.FormatNumber( Credits ) } )
end

-- für globale Missionen, Ausgabe der Nachricht "'Credits' Cr Kopfgeld erhalten"
-- Die maximal 7-stellige Prämie 'Credits' wird mit Tausendertrennzeichen angezeigt (z.B. "6.590")
MissionLib.LogPirateKilled = function( Credits )
    NGUI.ShowInfoText( { Text = "ID_PIRATE_KILL", Replace = MissionLib.FormatNumber( Credits ) } )
end

-- Liefert true mit einer Wahrscheinlichkeit von 'Percent' für Missionsstarts.
-- Ist der Parameter 'Percent' ungültig, wird der übergebene Defaultwert verwendet.
MissionLib.StartMission = function( Percent, Default )
    if lua.type( Percent ) ~= "number" then Percent = Default; end
    if Percent >= math.random() * 100 then
        return 1
    end
end

-- Setzt eine Mission als abgeschlossen, wurde aber nicht aus der Registrierung entfernt.
-- Die GLOBALS-Tabelle enthält noch Einträge, die von anderen Missionen verwendet werden können.
MissionLib.SetMissionAchieved = function( pMission )
    if GLOBALS[pMission] then
        GLOBALS[pMission].Achieved = true
    end
end

-- Liefert true, falls die Mission bereits erfolgreich abgeschlossen wurde und noch
-- Einträge von ihr zur weiteren Verwendung in der GLOBALS-Tabelle vorhanden sind.
MissionLib.IsMissionAchieved = function( pMission )
    if GLOBALS[pMission] then
        return GLOBALS[pMission].Achieved
    end
end

-- Liefert die komplette GLOBALS-Tabelle einer Mission, falls vorhanden.
MissionLib.GetGlobalsTable = function( pMission )
    return GLOBALS[pMission]
end

-- Gibt die Größe der GLOBALS-Tabelle zurück.
MissionLib.SizeOfGlobalsTable = function()
    return lua.sizeof( GLOBALS )
end

-- Liefert die V-Tabelle des angegebenen Skripts.
MissionLib.GetVTable = function( Script )
    return MISSION_TABLE[NMission.GetMissionHandle( { Script = Script } ).MissionList[1]]
end

-- ACHTUNG, das gilt für alle Funktionen für das Auftragsterminal:
-- Nicht direkt nach der Landung auf einer Handelsstation die Zustände abfragen oder ändern.
-- Zu dem Zeitpunkt sind die Terminal-Missionen noch nicht registriert (Zustand ist noch MSTATE_NONE)
-- und es wird ein Laufzeitfehler wegen ungültiger oder angeblich fehlender Übergabeparameter ausgelöst!
-- Man sollte zunächst im "Station"-Event 'Data.Enter' einen kurzen Timer starten,
-- wonach die Missionen dann initialisiert sein sollten und bearbeitet werden können.

-- Liefert eine Tabelle mit Informationen zu einer Mission.
-- Der Funktion muss entweder das Handle der Mission oder ihr Scriptname übergeben werden.
-- Syntax: GetMissionInfo( { Handle | Script } ) : { State, Script, Handle, Id, Owner, Version }
MissionLib.GetMissionInfo = function( Mission )
    local vtable
    local handle = Mission.Handle
    if handle then
        vtable = MISSION_TABLE[handle]
    end
    if not vtable and Mission.Script then
        handle = NMission.GetMissionHandle( { Script = Mission.Script } ).MissionList[1]
        vtable = MISSION_TABLE[handle]
    end
    if vtable then
        return {
            Script  = vtable.SCRIPT,	-- string
            State   = vtable.STATE,	-- enum
            Handle  = handle,		-- CMissionHandle
            Id      = vtable.ID,	-- CMissionHandle
            Owner   = vtable.OWNER,	-- Handle
            Version = vtable.VERSION	-- unsigned int
        }
    end
    return { State = MSTATE_NONE }
end

-- Liefert eine Tabelle mit den Namen aller aktiven Missionen im Index und den Handles im Wert.
MissionLib.GetActiveMissions = function()
    local scripts = {}
    for handle, vtable in MISSION_TABLE do
        scripts[vtable.SCRIPT] = handle
    end
    return scripts
end

-- Liefert eine Tabelle mit den Namen aller aktiven Alwaysmissionen im Index und den Handles im Wert.
MissionLib.GetActiveAlwaysMissions = function()
    local scripts = {}
    for handle, vtable in MISSION_TABLE do
        if vtable.STATE == MSTATE_RUNNING and SCRIPT_TABLE[vtable.SCRIPT].TYPE == MTYPE_ALWAYS then
            scripts[vtable.SCRIPT] = handle
        end
    end
    return scripts
end

-- Liefert eine Tabelle mit den Namen aller aktiven Spacemissionen im Index und den Handles im Wert.
MissionLib.GetActiveSpaceMissions = function()
    local scripts = {}
    for handle, vtable in MISSION_TABLE do
        if vtable.STATE == MSTATE_RUNNING then
            local mtype = SCRIPT_TABLE[vtable.SCRIPT].TYPE
            if mtype == MTYPE_SPACE or mtype == MTYPE_USER_SPACE then
                scripts[vtable.SCRIPT] = handle
            end
        end
    end
    return scripts
end

-- Liefert eine Tabelle mit den Namen aller aktiven Terminalmissionen im Index und den Handles im Wert.
-- Wird für 'State' MSTATE_OFFERING übergeben, werden die angebotenen Terminalmissionen zurückgeliefert.
MissionLib.GetActiveTerminalMissions = function( State )
    local scripts = {}
    if State ~= MSTATE_OFFERING then State = MSTATE_RUNNING; end
    for handle, vtable in MISSION_TABLE do
        if vtable.STATE == State then
            local mtype = SCRIPT_TABLE[vtable.SCRIPT].TYPE
            if mtype == MTYPE_TERMINAL or mtype == MTYPE_USER_TERMINAL then
                scripts[vtable.SCRIPT] = handle
            end
        end
    end
    return scripts
end

-- Prüft, ob der Spieler einen aktiven Terminalauftrag hat und liefert das erste gefundene Handle zurück.
MissionLib.IsActiveTerminalMission = function()
    for handle, vtable in MISSION_TABLE do
        if vtable.STATE == MSTATE_RUNNING then
            local mtype = SCRIPT_TABLE[vtable.SCRIPT].TYPE
            if mtype == MTYPE_TERMINAL or mtype == MTYPE_USER_TERMINAL then
                return handle
            end
        end
    end
end

-- Liefert die Anzahl der angebotenen Terminalmissionen.
MissionLib.GetTerminalMissionCount = function()
    local count = 0
    for handle, vtable in MISSION_TABLE do
        if vtable.STATE == MSTATE_OFFERING then
            local mtype = SCRIPT_TABLE[vtable.SCRIPT].TYPE
            if mtype == MTYPE_TERMINAL or mtype == MTYPE_USER_TERMINAL then
                count = count + 1
            end
        end
    end
    return count
end

-- Liefert den Missionstyp eines Skripts. 'Script' ist der registrierte Name der Mission.
MissionLib.GetMissionType = function( Script )
    if SCRIPT_TABLE[Script] then
        return SCRIPT_TABLE[Script].TYPE
    end
    return MTYPE_NONE
end

-- Zeigt den Typ einer Mission an.
MissionLib.ShowMissionType = function( Script )
    NGUI.ShowInfoText( {
        Text = "ID_MTYPE", Replace = { "ID_MTYPE_"..MissionLib.GetMissionType( Script ) }
    } )
end

-- Liefert den Zustand einer Mission (wie V.STATE, für beliebige Missionen).
-- Der Funktion muss entweder das Handle der Mission oder ihr Scriptname übergeben werden.
-- Syntax: GetMissionState( { Handle | Script } )
MissionLib.GetMissionState = function( Mission )
    local handle = Mission.Handle
    if handle then
        if MISSION_TABLE[handle] then
            return MISSION_TABLE[handle].STATE
        end
    else
        handle = NMission.GetMissionHandle( { Script = Mission.Script } ).MissionList[1]
        if handle then
            return MISSION_TABLE[handle].STATE
        end
    end
    return MSTATE_NONE
end

-- Setzt den Zustand einer Mission (V.STATE, für beliebige Missionen).
-- Der Funktion muss in 'Script' der Scriptname der Mission übergeben werden.
MissionLib.SetMissionState = function( Script, State )
    local handle = NMission.GetMissionHandle( { Script = Script } ).MissionList[1]
    if handle then
        if MISSION_TABLE[handle].STATE == MSTATE_ENDED then
            -- NMission.SetState funktioniert in diesem Fall nicht
            MISSION_TABLE[handle].STATE = State
        else
            NMission.SetState( { Mission = handle, State = State } )
        end
    end
end

-- Prüft, ob die in 'Script' angegebene Mission angeboten wird und liefert ihr Handle zurück.
MissionLib.IsMissionOffered = function( Script )
    local handle = NMission.GetMissionHandle( { Script = Script } ).MissionList[1]
    if handle and MISSION_TABLE[handle].STATE == MSTATE_OFFERING then
        return handle
    end
end

-- Prüft, ob die in 'Script' angegebene Mission läuft und liefert ihr Handle zurück.
MissionLib.IsMissionRunning = function( Script )
    local handle = NMission.GetMissionHandle( { Script = Script } ).MissionList[1]
    if handle and MISSION_TABLE[handle].STATE == MSTATE_RUNNING then
        return handle
    end
end

-- Prüft, ob mindestens eine der Missionen in 'ScriptList' im angegebenen Zustand 'State' ist.
-- In die Liste werden die gesuchten registrierten Skriptnamen eingetragen.
MissionLib.IsMissionInList = function( ScriptList, State )
    if not State then State = MSTATE_RUNNING; end
    for i, script in ScriptList do
        local handle = NMission.GetMissionHandle( { Script = script } ).MissionList[1]
        if handle and MISSION_TABLE[handle].STATE == State then
            return 1
        end
    end
end

-- Zeigt den Zustand einer Mission an.
MissionLib.ShowMissionState = function( Script, Title )
    local state = "ID_MSTATE_"..MissionLib.GetMissionState( { Script = Script } )
    if Title then
        NGUI.ShowInfoText( { Text = "ID_MISSION_STATE", Replace = { Title, state } } )
    else
        NGUI.ShowInfoText( { Text = state } )
    end
end

-- Zeigt Skriptname und Zustand aller aktiven Missionen an.
-- Ist der optionale Parameter 'ShowTitle' true, wird auch der Titel angezeigt,
-- falls er im Missionsskript in die Variable V.TITLE eingetragen wurde.
MissionLib.ShowMissions = function()
    local index = 0
    local state = { [0] = "NONE"; "OFFERING", "RUNNING", "ACHIEVED", "FAILED", "ENDED", "IDLE" }
    local missionlist = {}
    for handle, vtable in MISSION_TABLE do
        local mission = vtable.SCRIPT.." : "..state[vtable.STATE]
        if ShowTitle and vtable.TITLE then
            mission = mission.." —————————————————— "..vtable.TITLE
        end
        index = index + 1
        missionlist[index] = mission
    end
    if index > 0 then
        if index > 1 then
            MissionLib.QSort( missionlist, 1, index )
        end
        for i, mission in missionlist do
            MissionLib.ShowString( mission )
        end
    end
end

-- Reduziert die im Terminal angebotenen Aufträge auf die angegebene Anzahl.
-- Alle weiteren Terminalmissionen werden beendet und deren Handles in einer Tabelle zurückgeliefert.
-- Optional kann in MissionToStay ein Skript angegeben werden, welches im Auftragsangebot bleiben soll.
-- In dem Fall ruft man SetTerminalMissionCount am besten im "Create"-Event jenes Skripts auf.
MissionLib.SetTerminalMissionCount = function( Count, MissionToStay )
    local ended = 0
    local endedmissions = {}
    if MissionToStay then
        MissionToStay = NMission.GetMissionHandle( { Script = MissionToStay } ).MissionList[1]
        if MissionToStay then Count = Count - 1 end
    end
    for handle, vtable in MISSION_TABLE do
        if handle ~= MissionToStay and vtable.STATE == MSTATE_OFFERING then
            local mtype = SCRIPT_TABLE[vtable.SCRIPT].TYPE
            if mtype == MTYPE_TERMINAL or mtype == MTYPE_USER_TERMINAL then
                if Count > 0 then
                    Count = Count - 1
                else
                    NMission.SetState( { Mission = handle, State = MSTATE_ENDED } )
                    ended = ended + 1
                    endedmissions[ended] = handle
                end
            end
        end
    end
    return endedmissions
end

-- Beendet alle Terminalmissionen, deren Skripts nicht in MissionList aufgeführt sind.
-- Die Funktion liefert alle Handles der beendeten Missionen in einer Tabelle zurück.
MissionLib.SetTerminalMissionsOffered = function( MissionList )
    local ended = 0
    local endedmissions = {}
    for handle, vtable in MISSION_TABLE do
        if vtable.STATE == MSTATE_OFFERING
        and not MissionLib.IsInList( vtable.SCRIPT, MissionList ) then
            local mtype = SCRIPT_TABLE[vtable.SCRIPT].TYPE
            if mtype == MTYPE_TERMINAL or mtype == MTYPE_USER_TERMINAL then
                NMission.SetState( { Mission = handle, State = MSTATE_ENDED } )
                ended = ended + 1
                endedmissions[ended] = handle
            end
        end
    end
    return endedmissions
end

-- Bietet alle mit "MissionLib.SetTerminalMissionCount" oder "MissionLib.SetTerminalMissionsOffered"
-- beendeten Terminalmissionen wieder an, sofern sie noch in der Missionstabelle vorhanden sind.
MissionLib.RestoreTerminalMissions = function( MissionList )
    for i, handle in MissionList do
        if MISSION_TABLE[handle] then
            MISSION_TABLE[handle].STATE = MSTATE_OFFERING
        end
    end
end

-- Liefert das aktuelle Kapitel und Unterkapitel der Story als float.
MissionLib.GetStoryChapter = function()
    local story = NStory.Progress({})
    return story.Chapter + story.Subchapter / 100.0
end

-- Liefert den Fortschritt der Story anhand des aktuellen Kapitels und Unterkapitels
-- als Tabelle mit StringIds für die Verwendung in 'Replace' von "NGUI.ShowInfoText".
MissionLib.Progress = function()
    local story = NStory.Progress({})
    return { "ID_"..story.Chapter, "ID_"..story.Subchapter }
end

-- Trägt ein System als Storysystem in der GLOBALS-Tabelle ein oder aus.
MissionLib.SetGlobalsStoryTarget = function( SystemId, Set )
    if not GLOBALS.StoryTargets then
        -- Liste der Missionsziele initialisieren
        GLOBALS.StoryTargets = {}
    end
    GLOBALS.StoryTargets[SystemId] = Set
end

-- Markiert ein System als Storysystem oder entfernt die Markierung wieder
-- und trägt es in der GLOBALS-Tabelle ein bzw. aus.
-- Vereint die Funktionen "MissionLib.SetGlobalsStoryTarget" und "NStarSystem.SetAsStoryTarget".
MissionLib.SetAsStoryTarget = function( SystemId, Set, Hidden )
    if not GLOBALS.StoryTargets then
        -- Liste der Missionsziele initialisieren
        GLOBALS.StoryTargets = {}
    end
    GLOBALS.StoryTargets[SystemId] = Set
    NStarSystem.SetAsStoryTarget( { System = SystemId, Set = Set, Hidden = Hidden } )
end

-- Setzt die Markierung als Storysystem auf ein anderes System und entfernt sie
-- vom bisherigen. Die Änderung wird auch in die GLOBALS-Tabelle eingetragen.
-- Syntax: MissionLib.ChangeStoryTarget( { From, To, Hidden } ) : {}
MissionLib.ChangeStoryTarget = function( Systems )
    MissionLib.SetAsStoryTarget( Systems.From, false )
    MissionLib.SetAsStoryTarget( Systems.To, true, Systems.Hidden )
end

-- Setzt die Markierung als Storysystem auf ein anderes System und entfernt sie
-- vom bisherigen. Die Änderung wird NICHT in die GLOBALS-Tabelle eingetragen.
-- Syntax: MissionLib.ChangeAsStoryTarget( { From, To, Hidden } ) : {}
MissionLib.ChangeAsStoryTarget = function( Systems )
    NStarSystem.SetAsStoryTarget( { System = Systems.From, Set = false } )
    NStarSystem.SetAsStoryTarget( { System = Systems.To, Set = true, Hidden = Systems.Hidden } )
end

-- Setzt die Markierung als Missionssystem auf ein anderes System und entfernt sie vom
-- bisherigen. Der Parameter 'Hidden' ist wie bei "NStarSystem.SetAsMissionTarget" optional.
-- Syntax: MissionLib.ChangeMissionTarget( { From, To, Hidden } ) : {}
MissionLib.ChangeMissionTarget = function( Systems )
    NStarSystem.SetAsMissionTarget( { System = Systems.From, Set = false } )
    NStarSystem.SetAsMissionTarget( { System = Systems.To, Set = true, Hidden = Systems.Hidden } )
end

-- Das System wurde als Storysystem in die GLOBALS-Tabelle eingetragen (true/false).
-- Im Gegensatz zu anderen Missionen lassen sich aktive Storymissionen nicht mit
-- der Funktion get("Logic.StarSystems."..SystemId..".isActiveMission") abfragen.
-- MissionLib.FindSystem( { param = STAR_MISSION } ) funktioniert ebenfalls nicht.
MissionLib.IsStoryTarget = function( SystemId )
    if GLOBALS.StoryTargets then
        return GLOBALS.StoryTargets[SystemId]
    end
end

-- Im System ist eine Story-, Terminal- oder Bar-Mission aktiv oder es ist von Piraten besetzt.
MissionLib.SystemMissionTarget = function( SystemId )
    if ( GLOBALS.StoryTargets and GLOBALS.StoryTargets[SystemId] )
    or get( "Logic.StarSystems."..SystemId..".isActiveMission" ) > 0
    or get( "Logic.StarSystems."..SystemId..".siege" ) > 0 then
        return 1
    end
end

-- Liefert eine Tabelle der System-IDs aller in die GLOBALS-Tabelle eingetragenen Storysysteme.
MissionLib.GetStoryTargets = function()
    local systems = {}
    if GLOBALS.StoryTargets then
        local index = 0
        for system, value in GLOBALS.StoryTargets do
            index = index + 1
            systems[index] = system
        end
    end
    return systems
end

-- Zeigt alle aktuellen Storysysteme an.
MissionLib.ShowStoryTargets = function()
    if GLOBALS.StoryTargets then
        for system, value in GLOBALS.StoryTargets do
            NGUI.ShowInfoText( { Text = "ID_SYSTEMNAME_"..system } )
        end
    end
end

-- Löscht alle in die GLOBALS-Tabelle eingetragenen Storysysteme.
-- Existiert die Tabelle 'Systems', werden nur die darin aufgeführten Systeme gelöscht.
MissionLib.ClearStoryTargets = function( Systems )
    local targets = GLOBALS.StoryTargets
    if targets then
        if lua.type( Systems ) == "table" then
            for i, system in Systems do
                targets[system] = nil
            end
            if not MissionLib.IsListEmpty( targets ) then
                return
            end
        end
        GLOBALS.StoryTargets = nil
    end
end

-- Legt einen Spielstand des mit einer StringId angegebenen Namens an
-- und fügt ihm die übergebene Kapitel- und Unterkapitelnummer mit hinzu.
MissionLib.Save = function( Name, Chapter, Subchapter )
    NMission.SetName( { Name = Name } )
    NGame.Save( { Chapter = Chapter, Subchapter = Subchapter } )
end

-- Zerstört den NPC, falls V.NPC existiert. Es wird nur die V-Tabelle übergeben.
MissionLib.DestroyNPC = function( V )
    if V.NPC then
        NNPC.Destroy( { NPC = V.NPC } ); V.NPC = nil
    end
end

--============================[ Tabellen und Strings ]==========================

-- Liefert den Datentyp der übergebenen Variablen als String. Die möglichen Rückgabewerte sind:
-- "NIL", "FLOAT", "NUMBER", "STRING", "BOOLEAN", "TABLE", "FUNCTION", "THREAD" und "USERDATA".
-- Wie "lua.type", mit Umwandlung des zurückgegebenen Strings in Großbuchstaben.
MissionLib.Type = function( Item )
    return string.toupper( lua.type( Item ) )
end

-- Liefert true, wenn 'Str' in eine Zahl umgewandelt werden kann.
MissionLib.IsNumber = function( Str )
    if lua.tonumber( Str ) then
        return 1
    end
end

-- Liefert true, wenn 'Item' eine Tabelle ist.
MissionLib.IsTable = function( Item )
    if lua.type( Item ) == "table" then
        return 1
    end
end

-- Prüft, ob mindestens ein Eintrag der Tabelle ebenfalls eine Tabelle ist.
-- Liefert Index oder Bezeichner der ersten Tabelle, wenn eine gefunden wurde.
MissionLib.IsTableInList = function( Table )
    for i, item in Table do
        if lua.type( item ) == "table" then
            return i
        end
    end
end

-- Liefert true, wenn alle Einträge der Tabelle ebenfalls Tabellen sind.
MissionLib.IsListOfTables = function( Table )
    for i, item in Table do
        if lua.type( item ) ~= "table" then
            return
        end
    end
    return 1
end

-- Liefert 'Item' als Tabelle, falls es noch keine ist.
MissionLib.MakeTable = function( Item )
    if lua.type( Item ) ~= "table" then
        return { Item }
    end
    return Item
end

-- Liefert nil für leere Tabellen oder wandelt einfache Variablen in Tabellen um.
MissionLib.ConvertToTable = function( Item )
    if lua.type( Item ) == "table" then
        for i, value in Item do
            return Item
        end
    elseif Item then
        return { Item }
    end
end

-- Gibt die Größe einer Tabelle zurück, auch wenn nil-Werte darin enthalten sind.
-- nil-Einträge in der Tabelle werden allerdings nicht mitgezählt (wie bei "lua.sizeof").
-- Funktioniert im Gegensatz zu "MissionLib.GetTableMax" auch für Tabellen mit Feldnamen.
MissionLib.SizeOf = function( Table )
    local count = 0
    for i, value in Table do
        count = count + 1
    end
    return count
end

-- Gibt die Größe einer Tabelle zurück, auch wenn nil-Werte darin enthalten sind.
-- nil-Einträge innerhalb der Tabelle werden mitgezählt (aber nicht am Ende).
-- Vorteil: Der Index verschiebt sich nicht nach einem nil bei der Abfrage in Schleifen.
-- Nachteil: Funktioniert nur bei numerisch indizierten Tabellen.
MissionLib.GetN = function( Table )
    return lua.getn( Table )
end

-- Liefert den kleinsten Wert aus einer Tabelle zurück, ähnlich wie lua.min(...)
MissionLib.GetMin = function( Table )
    local min = MissionLib.FirstItemInList( Table )
    for i, value in Table do
        if value < min then min = value; end
    end
    return min
end

-- Liefert den größten Wert aus einer Tabelle zurück, ähnlich wie lua.max(...)
MissionLib.GetMax = function( Table )
    local max = MissionLib.FirstItemInList( Table )
    for i, value in Table do
        if value > max then max = value; end
    end
    return max
end

-- Addiert alle numerischen Werte der Tabelle und liefert die Summe zurück.
MissionLib.GetSum = function( Table )
    local sum = 0
    for i, value in Table do
        sum = sum + value
    end
    return sum
end

-- Liefert true, wenn die beiden Tabellen gleich sind.
MissionLib.CompareTables = function( Table1, Table2 )
    if lua.type( Table1 ) == "table" and lua.type( Table2 ) == "table"
    and lua.sizeof( Table1 ) == lua.sizeof( Table2 ) then
        for i, value1 in Table1 do
            local value2 = Table2[i]
            local type1 = lua.type( value1 )

            -- Wert 1 ist ein Zeiger auf eine Tabelle
            if type1 == "table" then
                if not MissionLib.CompareTables( value1, value2 ) then
                    -- Untertabellen sind ungleich, sofort abbrechen
                    return
                end

            -- Wert 1 ist ein einfacher Wert (Zahl, String, Handle oder nil)
            else
                -- Ungleiche Datentypen?
                local type2 = lua.type( value2 )
                if type1 ~= type2 then
                    -- Vergleich zwischen "number" und "float" wird zugelassen
                    if ( type1 == "number" and type2 == "float" )
                    or ( type2 == "number" and type1 == "float" ) then
                        -- Vergleiche zwischen den Datentypen "number" und "float"
                        -- liefern hier in Lua 4.1 mit den Operatoren '==' und '~='
                        -- bei Gleichheit false, deshalb auf '<' und '>' prüfen!
                        if value1 < value2 or value1 > value2 then
                            -- Werte sind ungleich, sofort abbrechen
                            return
                        end
                    else
                        -- Ungleiche Datentypen außer "number" und "float", Abbruch
                        return
                    end

                -- Datentypen sind gleich
                elseif value1 ~= value2 then
                    -- Werte sind ungleich, sofort abbrechen
                    return
                end
            end
        end
        return 1
    end
end

-- Liefert den Index vom ersten Eintrag einer Liste.
MissionLib.FirstIndexInList = function( List )
    for index, value in List do
        return index
    end
end

-- Liefert den Wert vom ersten Eintrag einer Liste.
MissionLib.FirstItemInList = function( List )
    for index, value in List do
        return value
    end
end

-- Liefert Index und Wert vom ersten gültigen Eintrag einer Liste.
MissionLib.FirstIndexAndItemInList = function( List )
    for index, value in List do
        return index, value
    end
end

-- Liefert aus einer Tabelle den Index des ersten Vorkommens von nil.
-- Enthält die Tabelle keine Lücken, wird die Anzahl der Einträge + 1 geliefert (1, wenn sie leer ist).
MissionLib.FirstNilInList = function( Table )
    for index, value in Table do
        if not value then
            return index
        end
    end
    return lua.sizeof( Table ) + 1
end

-- Entfernt einen Eintrag aus der Liste und liefert dessen Tabellenindex (Bezeichner oder Nummer).
-- Gibt nil zurück, wenn der Eintrag nicht gefunden wurde.
MissionLib.DeleteInList = function( Item, List )
    for index, value in List do
        if value == Item then
            List[index] = nil
            return index
        end
    end
end

-- Entfernt den Eintrag an 'Index' (Bezeichner oder Nummer) aus der Liste und liefert dessen Wert.
-- Gibt nil zurück, wenn der Eintrag nicht existiert.
MissionLib.DeleteIndexInList = function( Index, List )
    local value = List[Index]
    if value then
        List[Index] = nil
        return value
    end
end

-- Liefert den Tabellenindex des Feldnamens 'Item' ('Item' ist ein String!).
-- Gibt 0 zurück, wenn nichts gefunden wurde.
MissionLib.GetTableIndex = function( Table, Item )
    local index = 0
    for name, value in Table do
        index = index + 1
        if name == Item then
            return index
        end
    end
    return 0
end

-- Liefert aus einer Tabelle den Eintrag an der Position 'Index'.
-- Ist für Tabellen mit (teilweise) unbekannten Feldnamen nützlich.
MissionLib.GetTableItem = function( Table, Index )
    local count = 0
    for i, value in Table do
        count = count + 1
        if count == Index then
            return value
        end
    end
end

-- Liefert aus einer Tabelle, die Funktionen mit (teilweise) unbekannten Namen enthält,
-- die Funktion (nicht den String) an der Position 'Index'. nil, wenn es keine Funktion ist.
-- Wie "MissionLib.GetTableItem", liefert aber nur Einträge vom Datentyp "function".
MissionLib.GetFunction = function( Namespace, Index )
    local count = 0
    for i, command in Namespace do
        count = count + 1
        if count == Index then
            if lua.type( command ) == "function" then
                return command
            end
            return
        end
    end
end

-- Liefert aus einer Tabelle den Feldnamen (String) an der Position 'Index'.
-- Ist für Tabellen mit (teilweise) unbekannten Feldnamen nützlich.
MissionLib.GetTableItemName = function( Table, Index )
    local count = 0
    for name, value in Table do
        count = count + 1
        if count == Index then
            return name
        end
    end
end

-- Liefert aus einer Tabelle, die Funktionen mit (teilweise) unbekannten Namen enthält,
-- den Funktionsnamen (String) an der Position 'Index'. nil, wenn es keine Funktion ist.
-- Wie "MissionLib.GetTableItemName", liefert aber nur Einträge vom Datentyp "function".
MissionLib.GetFunctionName = function( Namespace, Index )
    local count = 0
    for name, command in Namespace do
        count = count + 1
        if count == Index then
            if lua.type( command ) == "function" then
                return name
            end
            return
        end
    end
end

-- Kopiert eine Tabelle 1:1. Im Gegensatz zu "MissionLib.CopyTable" werden auch alle
-- darin enthaltenen Tabellen rekursiv kopiert und nicht nur die Referenzen (Zeiger).
MissionLib.DeepCopyTable = function( Table )
    local newTable = {}
    for index, value in Table do
        if lua.type( value ) == "table" then
            value = MissionLib.DeepCopyTable( value )
        end
        newTable[index] = value
    end
    return newTable
end

-- Fügt ein neues Element 'Item' an der Position 'Index' in die Tabelle ein.
-- Fehlt der Index oder ist er ungültig, wird der Eintrag an der ersten Stelle
-- eingefügt, ist der Index dagegen zu groß, wird der Eintrag am Ende angehängt.
-- Die referenzierte Tabelle wird nicht als Kopie zurückgeliefert, sondern direkt geändert!
MissionLib.InsertInTable = function( Table, Item, Index )
    local tabSize = lua.getn( Table )
    if not Index or Index < 1 then Index = 1; end
    if Index > tabSize then
        Table[tabSize + 1] = Item
    else
        for i = tabSize, Index, -1 do
            Table[i + 1] = Table[i]
        end
        Table[Index] = Item
    end
end

-- Entfernt wie "MissionLib.RemoveFromTable" den Eintrag an der Position 'Index' aus der Tabelle.
-- Die referenzierte Tabelle wird jedoch nicht als Kopie zurückgeliefert, sondern direkt geändert!
MissionLib.RemoveInTable = function( Table, Index )
    if Index > 0 then
        local tabSize = lua.getn( Table )
        if tabSize > 0 then
            for i = Index, tabSize - 1 do
                Table[i] = Table[i + 1]
            end
            Table[tabSize] = nil
        end
    end
end

-- Entfernt alle Vorkommen von nil aus einer numerisch indizierten Tabelle
-- und liefert eine Kopie mit fortlaufendem Index sowie die Anzahl der Einträge zurück.
-- Kann man auch für die Konvertierung einer Hash-Tabelle in eine numerische verwenden,
-- wobei die Feldbezeichner verloren gehen und durch den fortlaufenden Index ersetzt werden.
MissionLib.CompactTable = function( Table )
    local newTable = {}
    local count = 0
    for i, value in Table do
        count = count + 1
        newTable[count] = value
    end
    return newTable, count
end

-- Liefert einen String mit der Anzahl 'Count' des Zeichens oder Strings 'Char'.
MissionLib.StringOf = function( Char, Count )
    local string = ""
    for i = 1, Count do
        string = string..Char
    end
    return string
end

-- Liefert eine Tabelle mit der Anzahl 'Count' der Einträge 'Item'.
-- 'Item' kann ein Zeichen, eine Zahl, ein String oder wiederum eine Tabelle sein.
MissionLib.TableOf = function( Item, Count )
    local table = {}
    for i = 1, Count do
        table[i] = Item
    end
    return table
end

-- Liefert eine numerisch indizierte Tabelle invertiert zurück. Der Tabellenindex muss bei 1 beginnen.
MissionLib.InvertTable = function( Table )
    local revTable = {}
    local index = lua.getn( Table )
    for i = 1, index do
        revTable[i] = Table[index]
        index = index - 1
    end
    return revTable
end

-- Wandelt einen String in ein Array mit den einzelnen Zeichen um.
MissionLib.String2Table = function( String )
    local table = {}
    local substr = string.substr
    for i = 1, string.length( String ) do
        table[i] = substr( String, i-1, 1 )
    end
    return table
end

-- Fügt ein Array zu einem String zusammen.
MissionLib.Table2String = function( Table )
    local string = ""
    for i, value in Table do
        string = string..value
    end
    return string
end

-- Fügt beliebig viele Arrays, Strings oder Zahlen aneinander und liefert das resultierende Array zurück.
-- 'Tables' ist eine Tabelle, die alle zusammenzufügenden Tabellen, Zeichenketten oder Zahlen enthält.
-- Beispiel: V.Table = MissionLib.ConcatTablesEx( { Table_1, Value, "String", Table_n } )
MissionLib.ConcatTablesEx = function( Tables )
    local newTable = {}
    local count = 0
    local type = lua.type
    for i, item in Tables do
        if type( item ) == "table" then
            for j, value in item do
                count = count + 1
                newTable[count] = value
            end
        else
            count = count + 1
            newTable[count] = item
        end
    end
    return newTable
end

-- Korrigiert Tabellen mit mehr als 9 StringId's für die Ersetzungen in "NGUI.ShowInfoText".
-- Der Hintergrund ist ein Fehler in "NGUI.ShowInfoText":
-- Sind in 'Replace' mehr als 9 Ersetzungen vorhanden, muss jede 10. Stelle (%10, %20, usw.)
-- DOPPELT besetzt werden, sonst wird der Text dieser Stelle nicht angezeigt! Man kann einen
-- beliebigen String vor jeder 10. Stelle einsetzen, auch ein Leerstring (nicht nil) genügt.
MissionLib.CorrectReplaceTable = function( Table )
    local newTable = {}
    local pos, ofs = 1, 0
    for i, stringId in Table do
        if pos == 10 then
            newTable[i + ofs] = ""
            ofs = ofs + 1
            pos = 1
        else
            pos = pos + 1
        end
        newTable[i + ofs] = stringId
    end
    return newTable
end

-- Sortiert eine Tabelle mit Zeichenketten oder numerischen Werten binär.
-- Das heißt: Es wird zwischen Groß- und Kleinschreibung unterschieden.
-- Länderspezifische Zeichen wie Umlaute stehen hinter den normalen Zeichen,
-- so ist z.B. "Ä" (Ansicode 196) größer als "Z" (Ansicode 90)!
MissionLib.QSort = function( Table, l, r )
    local i, j = l, r
    local centerValue = Table[( l + r ) / 2]
    repeat
        while Table[i] < centerValue do i = i + 1; end
        while Table[j] > centerValue do j = j - 1; end
        if i <= j then
            Table[i], Table[j] = Table[j], Table[i]
            i = i + 1
            j = j - 1
        end
    until i > j
    if l < j then MissionLib.QSort( Table, l, j ); end
    if i < r then MissionLib.QSort( Table, i, r ); end
end

-- Sortiert eine Tabelle im Bereich von 1 bis 'Count'
MissionLib.QuickSort = function( Table, Count )
    local size = lua.getn( Table )
    if Count and Count > 0 and Count < size then
        size = Count
    end
    MissionLib.QSort( Table, 1, size )
end

-- Liefert eine maximal 7-stellige positive Ganzzahl als Tabelle mit StringId's
-- der einzelnen Ziffern und eingefügten Tausendertrennzeichen zurück.
MissionLib.FormatNumber = function( Value )
    local number = { "", "", "", "", "", "", "", "", "" }
    local substr = string.substr
    local index = 9
    for i = string.length( Value ) - 1, 0, -1 do
        if index == 6 or index == 2 then
            number[index] = "ID_DOT"
            index = index - 1
        end
        number[index] = "ID_"..substr( Value, i, 1 )
        index = index - 1
    end
    return number
end

-- Liefert den übergebenen Prozentwert als Tabelle mit 2 StringId's für maximal 3 Vorkomma-
-- und 2 Nachkommastellen zurück. Der ganzzahlige Wert darf nicht größer als 405 sein.
MissionLib.FormatPercent = function( Value )
    local decimalplaces = "ID_0"
    local dotpos = string.find_first_of( Value, "." )
    if dotpos then
        decimalplaces = "ID_"..string.substr( Value, dotpos + 1, 2 )
    end
    return { "ID_"..lua.tonumber( Value ), decimalplaces }
end

-- Zerlegt eine Integer-Zahl mit maximal 4 Stellen in Teilstrings
-- á 2 Stellen plus Vorzeichen und liefert deren StringId's zurück.
MissionLib.Fragment4 = function( Value )
    Value = lua.tonumber( Value )
    local result = { "", "", "" }
    if Value < 0 then
        Value = -Value
        result[1] = "ID_MINUS"
    end
    local div = Value / 100
    local mod = lua.tonumber( math.mod( Value, 100 ) )
    if div > 0 then
        result[2] = "ID_"..div
        if mod < 10 then mod = "0"..mod; end
        result[3] = "ID_"..mod
    else
        result[2] = "ID_"..mod
    end
    return result
end

-- Zerlegt eine Integer-Zahl mit maximal 10 Stellen in Teilstrings
-- á 2 Stellen plus Vorzeichen und liefert deren StringId's zurück.
MissionLib.FragmentInt = function( Value )
    Value = lua.tonumber( Value )
    local result = { "", "", "", "", "", "" }
    local resultIndex = 1
    local stringIndex = 0
    if Value < 0 then
        result[1] = "ID_MINUS"
        stringIndex = 1
    end
    for i = stringIndex, string.length( Value ) - 1, 2 do
        resultIndex = resultIndex + 1
        result[resultIndex] = "ID_"..string.substr( Value, i, 2 )
    end
    return result
end

-- Zerlegt eine Fließkommazahl in Teilstrings á 2 Stellen und liefert deren StringId's zurück.
-- Die Zahl muss kleiner als 10 Milliarden sein, sie darf also maximal 10 Vorkommastellen haben.
-- Fehlt der Parameter 'DecimalPlaces', werden die StringId's für 6 Nachkommastellen geliefert.
MissionLib.FragmentFloat = function( Value, DecimalPlaces )
    local result = { "", "", "", "", "", "", "", "", "" }

    local Str1 = function( value )
        value = value / 10.0
        if value < 9 then
            return "ID_"..MissionLib.Rnd( value )
        end
        return "ID_9"
    end

    local Str2 = function( value )
        if value < 10 then
            return "ID_0"..value
        end
        return "ID_"..value
    end

    -- Vorkommastellen extrahieren und umwandeln, maximal 10 Stellen ( = 5 StringId's )
    if Value < 0 then
        Value = -Value
        result[1] = "ID_MINUS"
    end
    local int = lua.tonumber( Value )
    local div = lua.tostring( int )
    local i = 2
    for j = 0, string.length( div ) - 1, 2 do
        result[i] = "ID_"..string.substr( div, j, 2 )
        i = i + 1
    end

    -- Nachkommastellen extrahieren und umwandeln, maximal 6 Stellen ( = 3 StringId's )
    div = MissionLib.Rnd( 1000000 * ( Value - int ) )
    if not DecimalPlaces then
        DecimalPlaces = 6
        local exp = 10
        for i = 1, 5 do
            if math.mod( div, exp ) == 0.0 then
                DecimalPlaces = DecimalPlaces - 1
                exp = exp * 10
            else
                break
            end
        end
    end
    local mod = {}
    for cnt = 1, 3 do
        mod[cnt] = lua.tonumber( math.mod( div, 100 ) )
        div = lua.tonumber( div / 100 )
    end
    -- Umsortieren, da die Reihenfolge der Stellen umgekehrt ist und in StringId's umwandeln
    if DecimalPlaces < 2 then
        result[7] = Str1( mod[3] )
    else
        result[7] = Str2( mod[3] )
        if DecimalPlaces >= 3 then
            if DecimalPlaces < 4 then
                result[8] = Str1( mod[2] )
            else
                result[8] = Str2( mod[2] )
                if DecimalPlaces >= 5 then
                    if DecimalPlaces < 6 then
                        result[9] = Str1( mod[1] )
                    else
                        result[9] = Str2( mod[1] )
                    end
                end
            end
        end
    end

    return result
end

-- Wandelt den Vektor (x,y,z) in StringId's für die Anzeige mit "NGUI.ShowInfoText" um.
-- In der user_strings.res müssen dafür zwei StringId's angelegt werden, eine für Integer-
-- Zahlen, wenn der Parameter 'DecimalPlaces' fehlt, z.B. "ID_XYZ_INT" mit dem Inhalt
-- "X: %1%2%3%4%5%6   Y: %7%8%9%10%11%12   Z: %13%14%15%16%17%18"
-- und eine für Fließkommazahlen, wenn der Parameter 'DecimalPlaces' einen Wert enthält
-- (0..6, Anzahl der Nachkommastellen), z.B. "ID_XYZ_FLOAT" mit dem Inhalt
-- "X: %1%2%3%4%5%6,%7%8%9   Y: %10%11%12%13%14%15,%16%17%18   Z: %19%20%21%22%23%24,%25%26%27"
MissionLib.MakeInfoTextXYZ = function( Vector, DecimalPlaces )
    -- Integer-Werte
    if not DecimalPlaces then
        local x = MissionLib.FragmentInt( Vector[1] )
        local y = MissionLib.FragmentInt( Vector[2] )
        local z = MissionLib.FragmentInt( Vector[3] )
        x[7] = y[1]
        x[8] = y[2]
        x[9] = y[3]
        x[10] = ""	-- "Replace"-Korrektur an 10. Stelle in Rückgabetabelle
        x[11] = y[4]
        x[12] = y[5]
        x[13] = y[6]
        for i, id in z do
            x[i+13] = id
        end
        return x
    end
    -- Float-Werte
    local x = MissionLib.FragmentFloat( Vector[1], DecimalPlaces )
    local y = MissionLib.FragmentFloat( Vector[2], DecimalPlaces )
    local z = MissionLib.FragmentFloat( Vector[3], DecimalPlaces )
    -- x[1] bis x[9]	-- 1. bis 9. Stelle, x wird als Rückgabetabelle verwendet
    x[10] = ""		-- "Replace"-Korrektur = 10. Stelle in Rückgabetabelle
    for i, id in y do
        x[i+10] = id	-- 10. bis 18. Stelle = 11. bis 19. in Rückgabetabelle
    end
    x[20] = z[1]	-- 19. Stelle = 20. in Rückgabetabelle
    x[21] = ""		-- "Replace"-Korrektur = 21. Stelle in Rückgabetabelle
    for i = 2, 9 do
        x[i+20] = z[i]	-- 20. bis 27. Stelle = 22. bis 29. in Rückgabetabelle
    end
    return x
end

-- Wandelt einen String in eine Tabelle mit den StringId's der einzelnen Zeichen um.
-- Optional kann eine Mindestlänge für die zurückgelieferte Tabelle übergeben werden.
-- Ist der String kürzer, dann wird die Tabelle bis zum Ende mit NUL-Zeichen gefüllt.
-- Bei Strings länger als 9 Zeichen wird die ID-Tabelle automatisch korrigiert.
MissionLib.FragmentString = function( String, LengthMin )
    local idTable = {}
    local ucase  = string.toupper
    local substr = string.substr
    local length = string.length( String )
    local charId = MissionLib.IsInList
    local i, pos = 0, 1
    for n = 0, length - 1 do
        i = i + 1
        if pos == 10 then   -- "Replace"-Korrektur
            idTable[i] = ""
            i = i + 1
            pos = 1
        else
            pos = pos + 1
        end
        local ch = substr( String, n, 1 )
        if     ch >= "a" and ch <= "z" then idTable[i] = "LO_"..ucase( ch )
        elseif ch >= "A" and ch <= "Z" then idTable[i] = "UP_"..ch
        elseif ch >= "0" and ch <= "9" then idTable[i] = "ID_"..ch
        elseif CHARACTERS[ch] then          idTable[i] = CHARACTERS[ch]
        elseif ch >= "à" and ch <= "û" then idTable[i] = "LO_CHR_"..charId( ch, SPECIAL_CHAR_LOWER )
        elseif ch >= "À" and ch <= "Û" then idTable[i] = "UP_CHR_"..charId( ch, SPECIAL_CHAR_UPPER )
        else
            -- Unbekanntes Zeichen, ist nicht in den Tabellen und wird durch "¿" ersetzt
            idTable[i] = "ID_QUESTION_INV"
        end
    end
    -- Tabelle bis zum Ende mit NUL-Zeichen füllen, falls der String kürzer als 'LengthMin' ist
    if LengthMin then
        for n = length + 1, LengthMin do
            i = i + 1
            if pos == 10 then   -- "Replace"-Korrektur
                idTable[i] = ""
                i = i + 1
                pos = 1
            else
                pos = pos + 1
            end
            idTable[i] = ""
        end
    end
    return idTable
end

-- Zeigt Strings und Zahlen an und ist die Zusammenfassung der beiden nachfolgenden Einzel-
-- Funktionen "MissionLib.ShowString" und "MissionLib.ShowValue" in eine allgemeine Form.
MissionLib.Print = function( Value, Bool )
    local type = lua.type( Value )
    if type == "number" then
        if Bool then
            NGUI.ShowInfoText( { Text = "ID_TRUE" } )
        else
            NGUI.ShowInfoText( { Text = "ID_INT", Replace = MissionLib.FragmentInt( Value ) } )
        end
    elseif type == "float" then
        NGUI.ShowInfoText( { Text = "ID_FLOAT", Replace = MissionLib.FragmentFloat( Value ) } )
    elseif type == "string" then
        local len = string.length( Value )
        if len > 90 then
            len = 99
        elseif len > 10 then
            local mod = math.mod( len, 10 )
            if mod > 0.0 then
                len = len + 10 - lua.tonumber( mod )
            end
        end
        NGUI.ShowInfoText( { Text = "ID_TEXT"..len, Replace = MissionLib.FragmentString( Value, len ) } )
    elseif Bool and not Value then
        NGUI.ShowInfoText( { Text = "ID_FALSE" } )
    else -- "table" oder "nil"
        NGUI.ShowInfoText( { Text = "ID_TYPE", Replace = { "ID_TYPE_"..string.toupper( type ) } } )
        if type == "table" then
            NGUI.ShowInfoText( {
                Text = "ID_SIZE_INT", Replace = MissionLib.FragmentInt( lua.sizeof( Value ) )
            } )
        end
    end
end

-- Zeigt Strings bis zu einer Länge von 99 Zeichen an. Längere Strings werden abgeschnitten.
-- Unbekannte Zeichen werden mit einem "¿" dargestellt. Siehe Liste oben in "FragmentString".
MissionLib.ShowString = function( String )
    local type = lua.type( String )
    if type == "number" or type == "float" then
        String = lua.tostring( String )
        type = "string"
    end
    if type == "string" then
        local len = string.length( String )
        if len > 90 then
            len = 99
        elseif len > 10 then
            local mod = math.mod( len, 10 )
            if mod > 0.0 then
                len = len + 10 - lua.tonumber( mod )
            end
        end
        NGUI.ShowInfoText( {
            Text = "ID_TEXT"..len, Replace = MissionLib.FragmentString( String, len )
        } )
    end
end

-- Zeigt Integer- und Floatwerte an.
-- Ist 'Value' eine StringId, wird deren Text aus dem Lokalisierungs-Tool angezeigt.
MissionLib.ShowValue = function( Value, Bool )
    local type = lua.type( Value )
    if type == "number" then
        if Bool then
            NGUI.ShowInfoText( { Text = "ID_TRUE" } )
        else
            NGUI.ShowInfoText( { Text = "ID_INT", Replace = MissionLib.FragmentInt( Value ) } )
        end
    elseif type == "float" then
        NGUI.ShowInfoText( { Text = "ID_FLOAT", Replace = MissionLib.FragmentFloat( Value ) } )
    elseif type == "string" then
        NGUI.ShowInfoText( { Text = Value } )
    elseif Bool and not Value then
        NGUI.ShowInfoText( { Text = "ID_FALSE" } )
    else -- "table" oder "nil"
        NGUI.ShowInfoText( { Text = "ID_TYPE", Replace = { "ID_TYPE_"..string.toupper( type ) } } )
        if type == "table" then
            NGUI.ShowInfoText( {
                Text = "ID_SIZE_INT", Replace = MissionLib.FragmentInt( lua.sizeof( Value ) )
            } )
        end
    end
end

-- Zeigt einen Handlewert an.
-- Ist der übergebene Wert keine Ganzzahl, wird dessen Datentyp angezeigt.
MissionLib.ShowHandle = function( Handle )
    local type = lua.type( Handle )
    if type == "number" then
        Handle = MissionLib.FragmentInt( Handle )
    else
        Handle = { "ID_TYPE_"..string.toupper( type ), "", "", "", "", "" }
    end
    NGUI.ShowInfoText( { Text = "ID_HANDLE", Replace = Handle } )
end

-- Zeigt den Name des übergebenen Sternsystems an.
-- 'SystemId' darf sowohl die Id als auch das Handle des Systems sein.
MissionLib.ShowSystemName = function( SystemId )
    NGUI.ShowInfoText( { Text = MissionLib.GetSystemName( SystemId ) } )
end

--============================[ Mathematische Funktionen ]======================

-- Liefert die Potenz von x^n
-- Negative und positive Zahlen sind erlaubt, negatives 'x' aber nur bei ganzzahligem Exponent.
MissionLib.Pow = function( x, n )
    local f = math.exp( math.log( math.abs( x ) ) * n )
    if x < 0 and math.mod( n, 2 ) ~= 0.0 then
        return -f
    end
    return f
end

-- Liefert die Potenz von 2^n
MissionLib.Pow2 = function( n )
    return math.exp( math.log( 2 ) * n )
end

-- Liefert die Potenz von 10^n
MissionLib.Pow10 = function( n )
    return math.exp( math.log( 10 ) * n )
end

-- Liefert die 'n'te Wurzel von 'x' (nur positive Zahlen für 'x', negative Wurzel geht aber)
MissionLib.Root = function( n, x )
    return math.exp( math.log( x ) / n )
end

-- Liefert die Fakultät von x (nur positive Zahlen für 'x', ansonsten ist das Ergebnis ungültig)
-- Wegen 32-Bit Integer ist hier der größtmögliche Wert für 'x' = 12 (12! = 479.001.600)
MissionLib.Fac = function( x )
    if x < 2 then return 1; end
    for i = 2, x - 1 do
        x = x * i
    end
    return x
end

-- Zerlegt eine Zahl in Vor- und Nachkommastellen, wie "math.modf( x )" in LUA 5.1
MissionLib.ModF = function( x )
    local int = math.floor( x )	-- Vorkommastellen
    return int, x - int		-- Nachkommastellen
end

-- Auf/Abrunden
MissionLib.Rnd = function( x )
    local f = lua.tonumber( x )
    if ( x - f ) > 0.5 then
        return f + 1
    end
    return f
end

-- Vorzeichen ermitteln; true, wenn negativ
MissionLib.Sgn = function( x )
    if x < 0 then
        return 1
    end
end

-- Vorzeichen ermitteln, liefert "N"egativ oder "P"ositiv für die Verwendung in der user_strings.res
MissionLib.Sign = function( x )
    if x < 0 then
        return "N"
    end
    return "P"
end

-- Liefert true, wenn die Zahl gerade ist
MissionLib.IsEven = function( x )
    if math.mod( x, 2 ) == 0.0 then
        return 1
    end
end

-- Liefert true, wenn die Zahl ungerade ist
MissionLib.IsOdd = function( x )
    if math.mod( x, 2 ) ~= 0.0 then
        return 1
    end
end

-- Kugeloberfläche
MissionLib.SphericalSurface = function( Radius )
    return PI * Radius * Radius * 4.0
end

-- Kugelvolumen
MissionLib.SphericalVolume = function( Radius )
    return PI * Radius * Radius * Radius * 4.0 / 3.0
end

------------------------------[ Zufallszahlen ]--------------------------------

-- Lässt bessere Zufallszahlen von math.random erzeugen
MissionLib.RandomSeed = function()
    math.randomseed( NGame.GetTime({}).Time )
end

-- Liefert einen boolschen Zufallswert
MissionLib.RandomBool = function()
    if math.random() >= 0.5 then
        return 1
    end
end

-- Liefert ein zufälliges Bit (0 oder 1)
MissionLib.RandomBit = function()
    if math.random() >= 0.5 then
        return 1
    end
    return 0
end

-- Liefert true mit einer Wahrscheinlichkeit von 'Percent'% (0..100)
MissionLib.RandomChance = function( Percent )
    if Percent >= math.random() * 100 then
        return 1
    end
end

-- Liefert ein zufälliges Vorzeichen ( -1 wenn true, ansonsten +1 )
MissionLib.RandomSign = function()
    if math.random() < 0.5 then
        return -1
    end
    return 1
end

-- Liefert eine ganzzahlige Zufallszahl von 0 bis Max
MissionLib.RandomInt0 = function( Max )
    if Max > 0 then
        return lua.tonumber( math.random() * ( Max + 1 ) )
    end
    return 0
end

-- Liefert eine ganzzahlige Zufallszahl von 1 bis Max
MissionLib.RandomInt1 = function( Max )
    if Max > 1 then
        return lua.tonumber( math.random() * Max + 1 )
    end
    return 1
end

-- Liefert eine ganzzahlige Zufallszahl von 0 bis 2147483647
MissionLib.RandomMaxInt = function()
    -- Faktor muss "float" sein, sonst wird -2147483648 als "number" daraus!
    return lua.tonumber( math.random() * 2147483648.0 )
end

-- Liefert eine ganzzahlige vorzeichenbehaftete Zufallszahl (signed int) im angegebenen Bereich.
-- Zwar sollte möglichst der kleinere Wert in 'Min' übergeben werden, die Reihenfolge ist aber egal.
MissionLib.RandomSignedInt = function( Min, Max )
    if Min > Max then
        Min, Max = Max, Min
    end
    return lua.tonumber( math.floor( math.random() * ( Max - Min + 1 ) + Min ) )
end

-- Liefert eine zufällige Fließkommazahl, die Reihenfolge von 'Min' und 'Max' ist egal.
MissionLib.RandomFloat = function( Min, Max )
    if Min > Max then
        Min, Max = Max, Min
    end
    return Min + math.random() * ( Max - Min )
end

-- Liefert eine zufällige SystemId
MissionLib.RandomSystemId = function()
    return lua.tonumber( math.random() * 403 )
end

-- Liefert eine zufällige SystemId des aktuellen Clusters (aber kein totes System)
MissionLib.RandomClusterSystemId = function()
    local systems = MissionLib.GetStarClusterSystemRange()
    return MissionLib.RandomInteger( systems.First, systems.Last )
end

-- Liefert zufällig einen der beiden Werte
MissionLib.RandomFrom2 = function( Value1, Value2 )
    if math.random() < 0.5 then
        return Value1
    end
    return Value2
end

-- Liefert einen zufällig ausgewählten Wert aus der übergebenen Tabelle.
-- Nur für numerisch indizierte Tabellen, der Index muss bei 1 beginnen.
MissionLib.RandomFromTable = function( Table )
    return Table[MissionLib.RandomInt1( lua.getn( Table ) )]
end

-- Liefert einen zufällig ausgewählten Wert aus der übergebenen Hash-Tabelle.
MissionLib.RandomFromHashTable = function( Table )
    local array, count = MissionLib.CompactTable( Table )
    if count > 0 then
        return array[MissionLib.RandomInt1( count )]
    end
end

-- Liefert eine Tabelle mit einer zufälligen Kombination der Zahlen von 1 bis 3.
MissionLib.RandomCombination = function()
    return PERMUTATION[MissionLib.RandomInt1( 6 )]
end

-- Liefert eine Tabelle mit Zahlen von 1 bis 'Number' in zufälliger Reihenfolge.
-- Permutation wie "MissionLib.RandomCombination", jedoch für beliebig viele Zahlen.
MissionLib.RandomOrderNumber = function( Number )
    -- Tabelle mit den Zahlen von 1 bis Number erzeugen
    local numbers = {}
    for i = 1, Number do
        numbers[i] = i
    end
    -- Jetzt die Zahlen aus dieser Tabelle in zufälliger Reihenfolge in die Rückgabetabelle schreiben
    local randomOrder = {}
    for i = 1, Number do
        local index = MissionLib.RandomInt1( Number )
        randomOrder[i] = numbers[index]
        Number = Number - 1
        for j = index, Number do
            numbers[j] = numbers[j+1]
        end
    end
    return randomOrder
end

-- Liefert eine Kopie der übergebenen Tabelle mit zufällig sortierten Einträgen zurück.
MissionLib.RandomOrderTable = function( Table )
    -- Wichtig: mit temporärer Kopie der Tabelle arbeiten!
    local table = MissionLib.DeepCopyTable( Table )
    local count = lua.getn( table )
    -- Jetzt die Einträge durcheinander gewürfelt in die Rückgabetabelle schreiben
    local randomOrder = {}
    for i = 1, count do
        local index = MissionLib.RandomInt1( count )
        randomOrder[i] = table[index]
        count = count - 1
        for j = index, count do
            table[j] = table[j+1]
        end
    end
    return randomOrder
end

-- Liefert eine Tabelle mit Zahlen von 1 bis 'Value' in zufälliger Reihenfolge, wenn 'Value' eine Zahl ist.
-- Ist 'Value' eine Tabelle, liefert RandomOrder eine Kopie davon mit zufällig sortierten Einträgen zurück.
-- ( Zusammenfassung der Funktionen "MissionLib.RandomOrderNumber" und "MissionLib.RandomOrderTable" )
MissionLib.RandomOrder = function( Value )
    if lua.type( Value ) == "table" then
        return MissionLib.RandomOrderTable( Value )
    end
    return MissionLib.RandomOrderNumber( Value )
end

-- Liefert eine zufällige Rasse unter Verwendung der automatischen Rassenverteilung des Clusters.
-- Gibt man keine ClusterId an, wird die Rassenverteilung des aktuellen Clusters verwendet.
-- Ist der optionale Parameter 'RandomHuman' true, dann wird von den beiden möglichen Objektindicés
-- für terranische Geleitschutz- und Piratenjäger einer zufällig ausgewählt (0|6). 'RandomHuman' ist
-- für Ships[n].ObjIndex von NWing.Define gedacht und darf nur für diesem Fall verwendet werden!
MissionLib.RandomRace = function( ClusterId, RandomHuman )
    local random = MissionLib.RandomInt1( 100 )
    local chance = 0
    for race, percent in MissionLib.GetRaceAllocation( ClusterId ).All do
        if percent > 0 then
            chance = chance + percent
            if random <= chance then
                if RandomHuman and race == RACE_HUMAN and math.random() > 0.5 then
                    return 6    -- Terranischer Jäger mit 2 Triebwerken
                end
                return race
            end
        end
    end
    return RACE_RANDOM
end

-- Liefert eine Liste mit der Anzahl 'Count' zufälliger Rassen unter Verwendung der automatischen
-- Rassenverteilung des aktuellen Clusters.
-- Für den optionalen Parameter 'RandomHuman' gilt dasselbe wie oben bei "MissionLib.RandomRace".
MissionLib.RandomRaceList = function( Count, RandomHuman )
    local racelist = {}
    local raceAllocation = MissionLib.GetRaceAllocation().All
    for i = 1, Count do
        local random = MissionLib.RandomInt1( 100 )
        local chance = 0
        for race, percent in raceAllocation do
            if percent > 0 then
                chance = chance + percent
                if random <= chance then
                    if RandomHuman and race == RACE_HUMAN and math.random() > 0.5 then
                        racelist[i] = 6    -- Terranischer Jäger mit 2 Triebwerken
                    else
                        racelist[i] = race
                    end
                    break
                end
            end
        end
    end
    return racelist
end

-- Liefert einen Handelsfrachter-Wingtyp zur Verwendung in "NWing.Create" und "NWing.Define".
-- Zufällige Auswahl aus WINGTYPE_FREIGHTER50T/100T/200T, Superfrachter werden ebenfalls erzeugt.
MissionLib.WINGTYPE_FREIGHTER = function()
    return lua.tonumber( math.random() * 3 + 1 )
end

-- Liefert einen Handelsfrachter-Wingtyp zur Verwendung in "NWing.Create" und "NWing.Define".
-- Zufällige Auswahl aus WINGTYPE_FREIGHTER200CAP/400CAP/600CAP, Superfrachter werden nicht erzeugt.
MissionLib.WINGTYPE_FREIGHTER_CAP = function()
    return lua.tonumber( math.random() * 3 + 16 )
end

-- Liefert einen Piratenfrachter-Wingtyp zur Verwendung in "NWing.Create" und "NWing.Define".
-- Zufällige Auswahl aus WINGTYPE_PIRATEFREIGHTER50T/100T/200T.
MissionLib.WINGTYPE_PIRATEFREIGHTER = function()
    return lua.tonumber( math.random() * 3 + 13 )
end

-- Liefert den Objektindex eines zufällig ausgewählen Superfrachters für normale Container.
-- Gibt den Frachterindex der entsprechenden Rasse zurück, wenn der Parameter 'Race' existiert.
MissionLib.RandomSuperfreighter = function( Race )
    if Race then
        if Race == RACE_HUMAN then
            return MissionLib.RandomInteger( SI_SUPERTRADER_S_HUMAN, SI_SUPERTRADER_L_HUMAN )
        end
        if Race == RACE_ARRACK then
            return MissionLib.RandomInteger( SI_SUPERTRADER_S_ARRACK, SI_SUPERTRADER_L_ARRACK )
        end
        if Race == RACE_RAPTOR then
            return MissionLib.RandomInteger( SI_SUPERTRADER_S_RAPTOR, SI_SUPERTRADER_L_RAPTOR )
        end
    end
    return MissionLib.RandomInteger( SI_SUPERTRADER_S_HUMAN, SI_SUPERTRADER_L_RAPTOR )
end

------------------------------[ Logische Funktionen ]---------------------------

-- Antivalenz, liefert nur dann true, wenn ein Parameter true und der andere false ist.
MissionLib.XOR = function( a, b )
    return ( a and not b ) or ( b and not a )
end

-- Äquivalenz, liefert nur true, wenn beide Parameter entweder true oder false/nil sind.
MissionLib.EQU = function( a, b )
    return ( a and b ) or not ( a or b )
end

------------------------------[ Zeitfunktionen, Stoppuhr ]----------------------

-- Umrechnung Sekunden -> Zeitschritte
MissionLib.GetTimeSteps = function( Seconds )
    return Seconds * 25
end

-- Umrechnung Zeitschritte -> Sekunden
MissionLib.GetSeconds = function( TimeSteps )
    return TimeSteps / 25.0
end

-- Initialisiert eine neue Stoppuhr oder setzt eine bestehende auf 0 zurück.
-- 'Timer' kann ein String mit dem Namen der Stoppuhr sein oder auch ein numerischer Index.
MissionLib.TimerInit = function( Timer )
    if not GLOBALS.TIMER_TABLE then GLOBALS.TIMER_TABLE = {}; end
    GLOBALS.TIMER_TABLE[Timer] = { Start = 0.0, Stop = 0.0, Total = 0.0 }
end

-- Startet eine Stoppuhr mit dem Namen oder Index 'Timer'.
-- Die Stoppuhr muss zuvor initialisiert worden sein.
MissionLib.TimerStart = function( Timer )
    GLOBALS.TIMER_TABLE[Timer].Start = NGame.GetTime({}).Time
end

-- Stoppt eine Stoppuhr mit dem Namen oder Index 'Timer'.
-- Bei mehrmaligem Aufruf hintereinander wird die zuvor gestoppte Zeit überschrieben.
MissionLib.TimerStop = function( Timer )
    GLOBALS.TIMER_TABLE[Timer].Stop = NGame.GetTime({}).Time
end

-- Liefert die gestoppte Zeit in Sekunden (float).
-- Wurde die Uhr vorher nicht gestartet, wird die Zeit seit Spielstart zurückgeliefert.
MissionLib.StopTime = function( Timer )
    local timer = GLOBALS.TIMER_TABLE[Timer]
    if timer then
        return timer.Stop - timer.Start
    end
    return 0.0
end

-- Stoppt bei jedem Aufruf eine Stoppuhr mit dem Namen oder Index 'Timer', ermittelt und setzt die
-- vergangene Gesamtzeit seit dem Start der Uhr, startet sie neu und liefert die Gesamtzeit zurück.
-- Die Stoppuhr muss zuvor initialisiert worden sein. Eignet sich zum zyklischen Aufruf.
MissionLib.SetTimeSummary = function( Timer )
    local timer = GLOBALS.TIMER_TABLE[Timer]
    local total = timer.Total
    local start = timer.Start
    local stop  = NGame.GetTime({}).Time
    if start > stop then
        total = total + stop
    else
        total = total + stop - start
    end
    GLOBALS.TIMER_TABLE[Timer] = { Start = stop, Stop = stop, Total = total }
    return total
end

-- Löscht eine Stoppuhr mit dem Namen oder Index 'Timer'.
MissionLib.TimerDelete = function( Timer )
    GLOBALS.TIMER_TABLE[Timer] = nil
end

-- Liefert eine unformatierte Tabelle mit der gestoppten Zeit.
-- Außer den Milli- und Mikrosekunden enthält jeder Wert die Gesamtzeit (float).
MissionLib.GetTimeDiff = function( TimeValue )
    local tail = TimeValue - math.floor( TimeValue )
    return {
        Years   = TimeValue / 31536000.0,
        Months  = TimeValue / 2628000.0,
        Days    = TimeValue / 86400.0,
        Hours   = TimeValue / 3600.0,
        Minutes = TimeValue / 60.0,
        Seconds = TimeValue,
        Milli   = tail * 1000,
        Micro   = tail * 1000000
    }
end

-- Liefert eine formatierte Tabelle mit der gestoppten Zeit (Y,M,d,h,m,s,ms,µs).
-- Die Summe aller Werte entspricht dabei der Gesamtzeit.
MissionLib.GetTimeDifference = function( TimeValue )
    local time = { Raw = TimeValue }
    local int = lua.tonumber
    time.Years   = int( TimeValue / 31536000 );  TimeValue = TimeValue - time.Years * 31536000
    time.Months  = int( TimeValue / 2628000 );   TimeValue = TimeValue - time.Months * 2628000
    time.Days    = int( TimeValue / 86400 );     TimeValue = TimeValue - time.Days * 86400
    time.Hours   = int( TimeValue / 3600 );      TimeValue = TimeValue - time.Hours * 3600
    time.Minutes = int( TimeValue / 60 );        TimeValue = TimeValue - time.Minutes * 60
    time.Seconds = int( TimeValue );             TimeValue = TimeValue - time.Seconds
    time.Milli   = int( TimeValue * 1000 );      TimeValue = TimeValue - time.Milli / 1000
    time.Micro   = MissionLib.Rnd( TimeValue * 1000000 )
    return time
end

------------------------------[ Kontostand ]------------------------------------

-- Kontostand des Spielers auslesen
MissionLib.GetCreditsFromPlayer = function()
    return get( PLAYER_CREDITS )
end

-- Kontostand auf einen beliebigen Wert setzen
MissionLib.SetCreditsFromPlayer = function( Value )
    if Value >= 0 then
        set( PLAYER_CREDITS, lua.tonumber( Value ) )
    end
end

-- Kontostand reduzieren, Gegenstück zu NPlayer.AddCredits.
-- Syntax: MissionLib.SubCredits( { Credits, Message } )
MissionLib.SubCredits = function( Data )
    local value = lua.tonumber( Data.Credits )
    local money = get( PLAYER_CREDITS )
    if money > value then
        money = money - value
    else
        value = money
        money = 0
    end
    set( PLAYER_CREDITS, money )
    if Data.Message then
        local credits = MissionLib.FormatNumber( value )
        if value > 9999999 then
            credits[1] = "ID_"..lua.tonumber( value / 1000000 )
        end
        NGUI.ShowInfoText( { Text = "ID_SUBCREDITS", Replace = credits } )
    end
end

------------------------------[ Erzeugungsbereiche ]----------------------------

-- Eine Position 1u vor dem Hangar der Handelsstation, die beim Abflug genau im Zielkreuz liegt.
MissionLib.CenterPosHangarFront = function()
    return { -36, 70, 1000 }
end

-- Liefert Position und Ausrichtung des Hangars einer Handelsstation.
-- Syntax: GetHangarPosTradeStation() : { Position, Front, UpDir }
MissionLib.GetHangarPosTradeStation = function()
    return NObject.GetHangarPos( { Object = NStarSystem.GetTradeStation({}).Handle } )
end

-- Liefert Position und Ausrichtung des Hangars einer Forschungsstation.
-- Bei mehreren Forschungsstationen kann im Index die gewünschte Station angegeben werden.
-- Syntax: GetHangarPosResearchStation( Index ) : { Position, Front, UpDir }
MissionLib.GetHangarPosResearchStation = function( Index )
    if not Index then Index = 1; end
    return NObject.GetHangarPos( { Object = MissionLib.GetSystemOrbiterNr( OBJTYPE_STATION, Index ) } )
end

-- Liefert Position und Ausrichtung des Hangars eines Asteroiden.
-- Bei mehreren Asteroiden kann im Index der gewünschte Asteroid angegeben werden.
-- Syntax: GetHangarPosAsteroid( Index ) : { Position, Front, UpDir }
MissionLib.GetHangarPosAsteroid = function( Index )
    if not Index then Index = 1; end
    return NObject.GetHangarPos( { Object = MissionLib.GetSystemOrbiterNr( OBJTYPE_ASTEROID, Index ) } )
end

-- Liefert wie "NVector.GetPos" eine Position im angegebenen Erzeugungsbereich 'Area'.
-- Im Parameter 'Orbiter' kann das Handle vom gewünschten Orbiter übergeben werden, damit
-- wird bei mehreren gleichen Objekten nicht wie mit "NVector.GetPos" eins zufällig gewählt.
MissionLib.GetPos = function( Area, Orbiter )
    if Orbiter then
        if Area == POSDESCR_ASTEROID then
            return MissionLib.GetPosAsteroid( Orbiter )
        end
        if Area == POSDESCR_RESEARCH then
            return MissionLib.GetPosResearchStation( Orbiter )
        end
        if Area == POSDESCR_PLANET then
            return MissionLib.GetPosPlanet( Orbiter )
        end
        if Area == POSDESCR_ANOMALIE then
            return MissionLib.GetPosAnomalie( Orbiter )
        end
        if Area == POSDESCR_METEORID then
            return MissionLib.GetPosMeteorid( Orbiter )
        end
        if Area == POSDESCR_BLACKHOLE then
            return MissionLib.GetPosBlackhole( Orbiter )
        end
        if Area == POSDESCR_HYPERGATE then
            return MissionLib.GetPosHypergate( Orbiter )
        end
        if Area == POSDESCR_WELCOME2 then
            return MissionLib.GetPosWelcome()
        end
        if Area == POSDESCR_ASTEROID2 then
            return MissionLib.GetPosAsteroid2( Orbiter )
        end
        if Area == POSDESCR_RESEARCH2 then
            return MissionLib.GetPosResearchStation2( Orbiter )
        end
        if Area == POSDESCR_PLANET2 then
            return MissionLib.GetPosPlanet2( Orbiter )
        end
        if Area == POSDESCR_ANOMALIE2 then
            return MissionLib.GetPosAnomalie2( Orbiter )
        end
        if Area == POSDESCR_METEORID2 then
            return MissionLib.GetPosMeteorid2( Orbiter )
        end
        if Area == POSDESCR_BLACKHOLE2 then
            return MissionLib.GetPosBlackhole2( Orbiter )
        end
        if Area == POSDESCR_HYPERGATE2 then
            return MissionLib.GetPosHypergate2( Orbiter )
        end
        if Area == POSDESCR_OBJECT then
            return MissionLib.GetPosObject( Orbiter, 3000 )
        end
    end
    return NVector.GetPos( { Area = Area } ).Pos
end

-- Liefert wie POSDESCR_WELCOME eine Position im Erzeugungsbereich vor der Handelsstation.
-- Im Gegensatz zu "NVector.GetPos" wird die Position irgendwo auf dem ganzen Ring erzeugt.
MissionLib.GetPosWelcome = function()
    local angle = math.random() * PI * 2
    return { math.sin( angle ) * 150, math.cos( angle ) * 150 - 7, 200 }
end

-- Liefert eine Position innerhalb einer Zylinderschale mit dem Radius von 1u bis 3u um die Z-Achse
-- zwischen Handelsstation und Hypergate, von 2u bis 8u von der Handelstation entfernt in Richtung Tor.
-- Optional kann in 'Radius' auch eine beliebige Entfernung von der Z-Achse angegeben werden.
MissionLib.GetPosOffset2 = function( Radius )
    local angle = math.random() * PI * 2
    if not Radius then
        Radius = MissionLib.RandomInteger( 1000, 3000 )
    end
    return {
        math.sin( angle ) * Radius,
        math.cos( angle ) * Radius,
        MissionLib.RandomInteger( 2000, 8000 )
    }
end

-- Liefert wie POSDESCR_ASTEROID eine Position im Erzeugungsbereich eines Asteroiden.
-- Im Gegensatz zu "NVector.GetPos" wird der Asteroid also nicht zufällig ausgewählt.
MissionLib.GetPosAsteroid = function( Asteroid )
    -- Zentrum des Erzeugungsbereichs liegt 1u hinter der Hüllkugel des Asteroiden
    local centerArea = MissionLib.AddToVectorLength(
        NObject.GetPosition( { Object = Asteroid } ).Position,
        get( "Logic.Orbiter."..Asteroid..".radius", 0 ) + 1000
    )
    return MissionLib.GetRandomPosition( centerArea, 0, 500 )
end

-- Liefert wie POSDESCR_RESEARCHSTATION eine Position im Erzeugungsbereich einer Forschungsstation.
-- Im Gegensatz zu "NVector.GetPos" wird die Forschungsstation also nicht zufällig ausgewählt.
MissionLib.GetPosResearchStation = function( Station )
    -- Zentrum des Erzeugungsbereichs liegt 1u hinter der Hüllkugel der Forschungsstation
    local centerArea = MissionLib.AddToVectorLength(
        NObject.GetPosition( { Object = Station } ).Position,
        get( "Logic.Orbiter."..Station..".radius", 0 ) + 1000
    )
    return MissionLib.GetRandomPosition( centerArea, 0, 500 )
end

-- Liefert wie POSDESCR_FIRST_PLANET eine Position im Erzeugungsbereich eines Planeten.
-- Der Erzeugungsbereich ist eine Halbkugel 5 Units über der Oberfläche auf der Planetenrückseite.
-- Im Gegensatz zu "NVector.GetPos" wird also nicht nur der erste Planet genommen (POSDESCR_PLANET).
MissionLib.GetPosPlanet = function( Planet )
    -- Relative Koordinaten berechnen
    local relPos = MissionLib.GetVectorCartesian(
        get( "Logic.Orbiter."..Planet..".radius", 0 ) + 5000,  -- Radius der Halbkugel
        PI * math.random(),           -- Zufälliger Azimutwinkel 0° bis 180°
        PI * ( math.random() + 0.5 )  -- Zufälliger Polarwinkel 90° bis 270°
    )
    -- Planetenposition als Offset addieren
    return MissionLib.AddVector( relPos, NObject.GetPosition( { Object = Planet } ).Position )
end

-- Liefert eine Position im Erzeugungsbereich einer Anomalie
-- auf der von der Handelsstation abgewandten Seite (POSDESCR_ANOMALIE).
MissionLib.GetPosAnomalie = function( Anomalie )
    -- Zentrum des Erzeugungsbereichs liegt 1u hinter der Anomalie
    local centerArea = MissionLib.AddToVectorLength(
        NObject.GetPosition( { Object = Anomalie } ).Position, 1000
    )
    return MissionLib.GetRandomPosition( centerArea, 0, 500 )
end

-- Liefert eine Position im Erzeugungsbereich eines Meteoritenfelds
-- auf der von der Handelsstation abgewandten Seite des Zentrums (POSDESCR_METEORID).
MissionLib.GetPosMeteorid = function( Meteorid )
    -- Zentrum des Erzeugungsbereichs liegt 1u hinter dem Meteoritenfeldzentrum
    local centerArea = MissionLib.AddToVectorLength(
        NObject.GetPosition( { Object = Meteorid } ).Position, 1000
    )
    return MissionLib.GetRandomPosition( centerArea, 0, 500 )
end

-- Liefert eine Position im Erzeugungsbereich eines schwarzen Lochs
-- auf der der Handelsstation zugewandten Seite (POSDESCR_BLACKHOLE).
MissionLib.GetPosBlackhole = function( Blackhole )
    -- Zentrum des Erzeugungsbereichs liegt 3u vor dem schwarzen Loch
    local centerArea = MissionLib.AddToVectorLength(
        NObject.GetPosition( { Object = Blackhole } ).Position, -3000
    )
    return MissionLib.GetRandomPosition( centerArea, 0, 2000 )
end

-- Liefert eine Position im Erzeugungsbereich eines Hyperraumtors
-- auf der der Handelsstation zugewandten Seite (POSDESCR_HYPERGATE).
-- Bei Standardposition des Tors in 10 Units Entfernung kann der Parameter weggelassen werden.
MissionLib.GetPosHypergate = function( Hypergate )
    -- Zentrum des Erzeugungsbereichs liegt 1u vor dem Hyperraumtor
    local centerArea = { 0, 0, 9000 }
    if Hypergate then
        centerArea = MissionLib.AddToVectorLength(
            NObject.GetPosition( { Object = Hypergate } ).Position, -1000
        )
    end
    return MissionLib.GetRandomPosition( centerArea, 0, 500 )
end

-- Liefert eine Position innerhalb einer Kugelschale um den angegebenen Asteroiden
-- im Abstand von 1-3 Units vom Zentrum (POSDESCR_ASTEROID2).
MissionLib.GetPosAsteroid2 = function( Asteroid )
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Asteroid } ).Position, 1000, 3000
    )
end

-- Liefert eine Position innerhalb einer Kugelschale um die angegebene Forschungsstation
-- im Abstand von 1-3 Units vom Zentrum (POSDESCR_RESEARCH2).
MissionLib.GetPosResearchStation2 = function( Station )
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Station } ).Position, 1000, 3000
    )
end

-- Liefert eine Position innerhalb einer Kugelschale um den angegebenen Planeten
-- im Abstand von 3-6 Units von seiner Oberfläche (POSDESCR_PLANET2).
MissionLib.GetPosPlanet2 = function( Planet )
    local innerRadius = get( "Logic.Orbiter."..Planet..".radius", 0 ) + 3000
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Planet } ).Position,
        innerRadius,        -- Innenradius der Kugelschale
        innerRadius + 3000  -- Außenradius der Kugelschale
    )
end

-- Liefert eine Position in der Nähe der angegebenen Anomalie
-- innerhalb einer Kugel mit dem Radius von 2 Units (POSDESCR_ANOMALIE2).
MissionLib.GetPosAnomalie2 = function( Anomalie )
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Anomalie } ).Position, 0, 2000
    )
end

-- Liefert eine Position innerhalb einer Kugelschale im angegebenen Meteoritenfeld
-- im Abstand von 0,5-2 Units vom Zentrum (POSDESCR_METEORID2).
MissionLib.GetPosMeteorid2 = function( Meteorid )
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Meteorid } ).Position, 500, 2000
    )
end

-- Liefert eine Position innerhalb einer Kugelschale um das angegebene schwarze Loch
-- im Abstand von 2-6 Units von der Singularität (POSDESCR_BLACKHOLE2).
MissionLib.GetPosBlackhole2 = function( Blackhole )
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Blackhole } ).Position, 2000, 6000
    )
end

-- Liefert eine Position innerhalb einer Kugelschale um das Hyperraumtor
-- im Abstand von 0,5-2 Units vom Zentrum (POSDESCR_HYPERGATE2).
-- Bei Standardposition des Tors in 10 Units Entfernung kann der Parameter weggelassen werden.
MissionLib.GetPosHypergate2 = function( Hypergate )
    local posOrbiter = SYSTEM_GATE
    if Hypergate then
        posOrbiter = NObject.GetPosition( { Object = Hypergate } ).Position
    end
    return MissionLib.GetRandomPosition( posOrbiter, 500, 2000 )
end

-- Liefert wie "MissionLib.GetPosWelcome" eine Position auf einem ringförmigen Erzeugungsbereich
-- eines Hyperraumtors und 0,5u vom Tor entfernt auf der der Handelsstation zugewandten Seite.
-- Die etwas schräg liegende Ausrichtung des Tors nach links unten wird dabei nicht berücksichtigt,
-- das Ringzentrum liegt immer genau auf der Z-Achse. Der Radius des Rings beträgt konstant 0,5u.
MissionLib.GetPosHypergateWelcome = function()
    local angle = math.random() * PI * 2
    return { math.sin( angle ) * 500, math.cos( angle ) * 500, 9500 }
end

-- Liefert eine Position im Erzeugungsbereich eines beliebigen Objekts (POSDESCR_OBJECT).
-- Kugelschale im Abstand von 0 bis 'MaxDistance' Milliunits von der Hüllkugel des Objekts.
MissionLib.GetPosObject = function( Object, MaxDistance )
    local objRadius = get( "Logic.Orbiter."..Object..".radius", 0 )
    return MissionLib.GetRandomPosition(
        NObject.GetPosition( { Object = Object } ).Position,
        objRadius,               -- Innenradius der Kugelschale
        objRadius + MaxDistance  -- Außenradius der Kugelschale
    )
end

------------------------------[ Positionen anzeigen ]---------------------------

-- Zeigt die übergebene Position in 1/1000 Units an.
MissionLib.ShowPosition = function( Vector, DecimalPlaces )
    local type = lua.type( Vector )
    if type == "table" then
        local pos = MissionLib.MakeInfoTextXYZ( Vector, DecimalPlaces )
        if DecimalPlaces then
            NGUI.ShowInfoText( { Text = "ID_XYZ_FLOAT", Replace = pos } )
        else
            NGUI.ShowInfoText( { Text = "ID_XYZ_INT", Replace = pos } )
        end
    else
        NGUI.ShowInfoText( { Text = "ID_TYPE", Replace = { "ID_TYPE_"..string.toupper( type ) } } )
    end
end

-- Zeigt die Position des Objekts (Schiff oder sonstiges Spaceobjekt) in 1/1000 Units an.
MissionLib.ShowObjectPos = function( SpaceObj )
    NGUI.ShowInfoText( {
        Text = "ID_XYZ_INT",
        Replace = MissionLib.MakeInfoTextXYZ( NObject.GetPosition( { Object = SpaceObj } ).Position )
    } )
end

-- Zeigt die Entfernung zwischen den beiden Vektoren in 1/1000 Units an.
-- Ist 'Units' true, wird sie in ganzen Units + angegebenen Nachkommastellen angezeigt.
MissionLib.ShowDistance = function( Vector1, Vector2, DecimalPlaces, Units )
    local dist = MissionLib.GetVectorDistance( Vector1, Vector2 )
    if Units then dist = dist / 1000; end
    if DecimalPlaces then
        NGUI.ShowInfoText( {
            Text = "ID_DISTANCE_FLOAT",
            Replace = MissionLib.FragmentFloat( dist, DecimalPlaces )
        } )
    else
        NGUI.ShowInfoText( {
            Text = "ID_DISTANCE_INT",
            Replace = MissionLib.FragmentInt( MissionLib.Rnd( dist ) )
        } )
    end
end

------------------------------[ Vektoren ]--------------------------------------

-- Addiert zwei Vektoren.
-- Liefert z.B. die absolute Position eines relativen Vektors zum einem Koordinatenursprung.
-- Ersetzt die langsame Funktion "NVector.Add" und ist etwas mehr als doppelt so schnell.
-- Ein weiterer Geschwindigkeitszuwachs um ca. das 4-fache (8-fach gegenüber NVector.Add)
-- wird erreicht, wenn der Code direkt im Skript eingebunden wird, anstatt diese Funktion
-- aufzurufen. Dasselbe gilt auch für die nächste Funktion "MissionLib.SubVector".
MissionLib.AddVector = function( Vector1, Vector2 )
    return {
        Vector1[1] + Vector2[1],
        Vector1[2] + Vector2[2],
        Vector1[3] + Vector2[3]
    }
end

-- Subtrahiert 'Vektor2' von 'Vector1'.
-- Liefert z.B. die relative Position des Vektors 'Vector1' zum Koordinatenursprung 'Vector2'.
-- Ersetzt die langsame Funktion "NVector.Sub".
MissionLib.SubVector = function( Vector1, Vector2 )
    return {
        Vector1[1] - Vector2[1],
        Vector1[2] - Vector2[2],
        Vector1[3] - Vector2[3]
    }
end

-- Multipliziert zwei Vektoren.
MissionLib.MulVector = function( Vector1, Vector2 )
    return {
        Vector1[1] * Vector2[1],
        Vector1[2] * Vector2[2],
        Vector1[3] * Vector2[3]
    }
end

-- Liefert den Gegenvektor.
MissionLib.NegVector = function( Vector )
    return { - Vector[1], - Vector[2], - Vector[3] }
end

-- Liefert die Koordinaten des Vektors einzeln zurück.
MissionLib.SplitVector = function( Vector )
    return Vector[1], Vector[2], Vector[3]
end

-- Erhöht oder verringert die X-Koordinate des Vektors.
MissionLib.AddVectorX = function( Vector, Value )
    return { Vector[1] + Value, Vector[2], Vector[3] }
end

-- Erhöht oder verringert die Y-Koordinate des Vektors.
MissionLib.AddVectorY = function( Vector, Value )
    return { Vector[1], Vector[2] + Value, Vector[3] }
end

-- Erhöht oder verringert die Z-Koordinate des Vektors.
MissionLib.AddVectorZ = function( Vector, Value )
    return { Vector[1], Vector[2], Vector[3] + Value }
end

-- Erhöht oder verringert die XY-Koordinaten des Vektors.
MissionLib.AddVectorXY = function( Vector, AddX, AddY )
    return { Vector[1] + AddX, Vector[2] + AddY, Vector[3] }
end

-- Erhöht oder verringert die XZ-Koordinaten des Vektors.
MissionLib.AddVectorXZ = function( Vector, AddX, AddZ )
    return { Vector[1] + AddX, Vector[2], Vector[3] + AddZ }
end

-- Erhöht oder verringert die YZ-Koordinaten des Vektors.
MissionLib.AddVectorYZ = function( Vector, AddY, AddZ )
    return { Vector[1], Vector[2] + AddY, Vector[3] + AddZ }
end

-- Erhöht oder verringert alle drei Koordinaten des Vektors um den selben Wert.
MissionLib.AddVectorXYZ = function( Vector, Value )
    return { Vector[1] + Value, Vector[2] + Value, Vector[3] + Value }
end

-- Normalisiert den Vektor (Länge 1).
MissionLib.Normalize = function( Vector )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    local len = math.sqrt( x * x + y * y + z * z )
    if len > 0 then
        return { x / len, y / len, z / len }
    end
    return Vector
end

-- Prüft, ob der Wert ein 3D-Vektor ist.
MissionLib.IsVector = function( Vector )
    if lua.type( Vector ) == "table" and lua.sizeof( Vector ) == 3 then
        return 1
    end
end

-- Prüft, ob die beiden Vektoren gleich sind.
MissionLib.IsVectorEqual = function( Vector1, Vector2 )
    for i, pos in Vector1 do
        if math.abs( pos - Vector2[i] ) > 0 then
            return
        end
    end
    return 1
end

-- Prüft, ob die Vektorlänge gleich Null ist.
-- Nicht mit '==' oder '~=' prüfen, liefert bei float-Werten und Gleichheit ein falsches Ergebnis!
-- Würde man dagegen die 0 durch 0.0 ersetzen, passiert dasselbe bei übergebenen Integer-Werten.
-- Umwandlung in float-Werte mit "lua.tofloat" ist langsamer, daher die Operatoren '<' und '>'.
MissionLib.IsVectorLengthNull = function( Vector )
    for i, pos in Vector do
        if pos < 0 or pos > 0 then
            return
        end
    end
    return 1
end

-- Prüft, ob die beiden Vektoren fast gleich sind (Fuzzylogik bzw. Unschärfe).
-- Die erlaubte Abweichung liegt innerhalb eines Würfels (kartesische Koordinaten).
-- 'Offset' ist ein Absolutwert für die maximal erlaubte Achsen-Abweichung.
MissionLib.IsVectorSimilar = function( Vector1, Vector2, Offset )
    for i, pos in Vector1 do
        if math.abs( pos - Vector2[i] ) > Offset then
            return
        end
    end
    return 1
end

-- Prüft, ob die beiden Vektoren fast gleich sind (Fuzzylogik bzw. Unschärfe).
-- Die erlaubte Abweichung liegt innerhalb einer Kugel (Polarkoordinaten).
-- 'Offset' ist ein Absolutwert für die maximal erlaubte Radius-Abweichung.
MissionLib.IsVectorSimilarPolar = function( Vector1, Vector2, Offset )
    local x = Vector1[1] - Vector2[1]
    local y = Vector1[2] - Vector2[2]
    local z = Vector1[3] - Vector2[3]
    if math.sqrt( x * x + y * y + z * z ) <= Offset then
        return 1
    end
end

-- Berechnet die Vektorlänge zwischen zwei Raumkoordinaten.
-- Wie "MissionLib.GetObjectDistance", für beliebige Vektoren.
MissionLib.GetVectorDistance = function( Vector1, Vector2 )
    local x = Vector1[1] - Vector2[1]
    local y = Vector1[2] - Vector2[2]
    local z = Vector1[3] - Vector2[3]
    return math.sqrt( x * x + y * y + z * z )
end

-- Verlängert oder verkürzt den Vektor um den Betrag 'Value' und liefert die neuen Koordinaten zurück.
-- Ist der Absolutwert eines negativen Betrags größer als die Vektorlänge, kehrt sich die Richtung um.
-- Wurde ein Nullvektor übergeben, wird er unverändert wieder zurückgeliefert.
MissionLib.AddToVectorLength = function( Vector, Value )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    local len = math.sqrt( x * x + y * y + z * z )
    if len > 0 then
        local factor = ( len + Value ) / len
        return { x * factor, y * factor, z * factor }
    end
    return Vector
end

-- Wie "AddToVectorLength", bezogen auf ein relatives Zentrum (z.B. ein Planet).
MissionLib.AddToVectorLengthRel = function( Vector, Center, Value )
    local x0, y0, z0 = Center[1], Center[2], Center[3]
    local x, y, z = Vector[1] - x0, Vector[2] - y0, Vector[3] - z0
    local len = math.sqrt( x * x + y * y + z * z )
    if len > 0 then
        local factor = ( len + Value ) / len
        return { x * factor + x0, y * factor + y0, z * factor + z0 }
    end
    return Center
end

-- Verlängert oder verkürzt den Vektor um den Faktor 'Factor' und liefert die Koordinaten zurück.
-- Ist der Faktor negativ, kehrt sich die Richtung um (Gegenvektor bei 'Factor' = -1).
MissionLib.MulVectorLength = function( Vector, Factor )
    return {
        Vector[1] * Factor,
        Vector[2] * Factor,
        Vector[3] * Factor
    }
end

-- Wie "MulVectorLength", bezogen auf ein relatives Zentrum (z.B. ein Planet).
MissionLib.MulVectorLengthRel = function( Vector, Center, Factor )
    local x0, y0, z0 = Center[1], Center[2], Center[3]
    return {
        ( Vector[1] - x0 ) * Factor + x0,
        ( Vector[2] - y0 ) * Factor + y0,
        ( Vector[3] - z0 ) * Factor + z0
    }
end

-- Setzt die 3 Achsen der Position auf die im Richtungsvektor 'Direction' übergebene Richtung
-- und liefert die neuen Koordinaten zurück. Es sollte mindestens einer Achse eine Ausrichtung
-- übergeben werden, nicht {0,0,0}. 0 = unveränderte, 1 = positive, -1 = negative Ausrichtung.
MissionLib.SetDirection = function( Position, Direction )
    local alignment = {}
    for i, pos in Position do
        if ( Direction[i] < 0 and pos > 0 )
        or ( Direction[i] > 0 and pos < 0 ) then
            pos = -pos
        end
        alignment[i] = pos
    end
    return alignment
end

-- Liefert einen Vektor in der angegebenen Richtung und Entfernung von der Position.
-- 'Direction' ist ein Richtungsvektor der Länge 1, wie er u.a. von GetAlignment geliefert wird.
-- Richtungsvektoren ungleich der Länge 1 sollten zuvor mit NVector.SetMag normalisiert werden.
MissionLib.GetPosInDistance = function( Position, Direction, Distance )
    return {
        Position[1] + Direction[1] * Distance,
        Position[2] + Direction[2] * Distance,
        Position[3] + Direction[3] * Distance
    }
end

-- Liefert einen zufälligen Richtungsvektor.
-- Ist 'Normalize' true, wird der Vektor normalisiert (Länge 1).
-- Hinweis: Nicht mit "math.random() - 0.5" berechnen, Vektor könnte zu Null werden!
MissionLib.GetRandomDirection = function( Normalize )
    local lookat = {}
    local random = math.random
    for i = 1, 3 do
        if random() > 0.5 then lookat[i] = random() else lookat[i] = -random(); end
    end
    if Normalize then
        return MissionLib.Normalize( lookat )
    end
    return lookat
end

-- Liefert einen Vektor in zufälliger Richtung und Entfernung zwischen 'RadiusMin' und 'RadiusMax'
-- von der Position. Wird 'RadiusMax' nicht angegeben oder ist gleich 'RadiusMin',
-- liefert die Funktion einen Vektor in der Entfernung von 'RadiusMin'.
-- Gleiche Wirkungsweise wie "MissionLib.RandomPosGlobe", ist aber rund 33% schneller.
MissionLib.GetRandomPosition = function( Position, RadiusMin, RadiusMax )
    if RadiusMax then
        -- Zufällige Entfernung zwischen RadiusMin und RadiusMax
        RadiusMin = MissionLib.RandomFloat( RadiusMin, RadiusMax )
    end

    -- Zufälligen Richtungsvektor erzeugen und normalisieren
    local random = math.random
    local x, y, z = random() - 0.5, random() - 0.5, random() - 0.5
    local len = math.sqrt( x * x + y * y + z * z )
    if len == 0.0 then
        z = 1.0
    else
        x, y, z = x / len, y / len, z / len
    end

    -- Koordinaten berechnen
    return {
        Position[1] + x * RadiusMin,
        Position[2] + y * RadiusMin,
        Position[3] + z * RadiusMin
    }
end

-- Liefert einen Vektor in zufälliger Entfernung zwischen 'RadiusMin' und 'RadiusMax' von der Position.
-- Im anzugebenden Richtungsvektor 'Direction' wird die gewünschte Ausrichtung der 3 Achsen übergeben.
-- 0 = zufällige, 1 = positive, -1 = negative Richtung. Es sollte mindestens einer Achse eine Richtung
-- übergeben werden, nicht {0,0,0}, andernfalls sollte "MissionLib.GetRandomPosition" verwendet werden.
MissionLib.GetRandomPositionDir = function( Position, Direction, RadiusMin, RadiusMax )
    local randompos = MissionLib.GetRandomPosition( Position, RadiusMin, RadiusMax )
    for i, pos in randompos do
        if ( Direction[i] < 0 and pos > 0 )
        or ( Direction[i] > 0 and pos < 0 ) then
            randompos[i] = -pos
        end
    end
    return randompos
end

-- Liefert eine zufällige Position auf der Linie zwischen zwei Raumkoordinaten.
MissionLib.GetRandomVector = function( Vector1, Vector2 )
    local x1, y1, z1, factor = Vector1[1], Vector1[2], Vector1[3], math.random()
    return {
        ( Vector2[1] - x1 ) * factor + x1,
        ( Vector2[2] - y1 ) * factor + y1,
        ( Vector2[3] - z1 ) * factor + z1
    }
end

-- Berechnet die mittlere Position zwischen zwei Raumkoordinaten.
MissionLib.GetVectorCenter = function( Vector1, Vector2 )
    return {
        ( Vector1[1] + Vector2[1] ) / 2.0,
        ( Vector1[2] + Vector2[2] ) / 2.0,
        ( Vector1[3] + Vector2[3] ) / 2.0
    }
end

-- Berechnet die mittlere Position (Schwerpunkt) zwischen beliebig vielen Raumkoordinaten.
MissionLib.GetCenterOfVectors = function( VectorTable )
    local count = lua.sizeof( VectorTable )
    if count > 0 then
        local x, y, z = 0.0, 0.0, 0.0
        for i, vector in VectorTable do
            x, y, z = x + vector[1], y + vector[2], z + vector[3]
        end
        return { x / count, y / count, z / count }
    end
end

-- Berechnet die mittlere Position zwischen den Zentren von zwei Objekten.
MissionLib.GetObjectCenter = function( Object1, Object2 )
    if Object1 and Object2 then
        local pos1 = NObject.GetPosition( { Object = Object1 } ).Position
        local pos2 = NObject.GetPosition( { Object = Object2 } ).Position
        return {
            ( pos1[1] + pos2[1] ) / 2.0,
            ( pos1[2] + pos2[2] ) / 2.0,
            ( pos1[3] + pos2[3] ) / 2.0
        }
    end
end

-- Berechnet die mittlere Position (Schwerpunkt) zwischen beliebig vielen Objekten.
-- Ungültige Objekte werden dabei ignoriert, es muss aber mindestens eins gültig sein.
MissionLib.GetCenterOfObjects = function( ObjectTable )
    local count = lua.sizeof( ObjectTable )
    if count > 0 then
        local x, y, z = 0.0, 0.0, 0.0
        for i, object in ObjectTable do
            local pos = NObject.GetPosition( { Object = object } ).Position
            x, y, z = x + pos[1], y + pos[2], z + pos[3]
        end
        return { x / count, y / count, z / count }
    end
end

-- Setzt den Vektor auf eine neue Länge und liefert die kartesischen Koordinaten zurück.
-- Ist 'Length' nicht angegeben oder gleich 1, wird der Vektor normalisiert (Länge = 1).
-- Ist mit ca. 0,9 µs Laufzeit bei 4 GHz etwa doppelt so schnell wie "NVector.SetMag".
MissionLib.SetVectorLength = function( Vector, Length )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    -- Aktuelle Vektorlänge:
    local len = math.sqrt( x * x + y * y + z * z )
    if len == 0.0 then
        -- Multiplikator für die neue Länge berechnen:
        if not Length then Length = 1.0; end
        local factor = Length / len
        return { x * factor, y * factor, z * factor }
    end
    -- 'Vector' liegt im Systemzentrum
    return Vector
end

-- Wie "SetVectorLength", bezogen auf ein relatives Zentrum (z.B. ein Planet).
MissionLib.SetVectorLengthRel = function( Vector, Center, Length )
    local x0, y0, z0 = Center[1], Center[2], Center[3]
    -- Relative Vektorlänge:
    local x, y, z = Vector[1] - x0, Vector[2] - y0, Vector[3] - z0
    local len = math.sqrt( x * x + y * y + z * z )
    if len > 0 then
        -- Multiplikator für die neue Länge berechnen:
        local factor = Length / len
        -- Absoluten Vektor zurückliefern:
        return { x * factor + x0, y * factor + y0, z * factor + z0 }
    end
    -- 'Vector' und 'Center' sind gleich
    return Vector
end

-- Setzt den Vektor auf die Maximallänge 'Length', falls er länger ist.
-- Ist der Vektor nicht länger als angegeben, wird er unverändert zurückgeliefert.
MissionLib.SetVectorLengthMax = function( Vector, Length )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    local len = math.sqrt( x * x + y * y + z * z )
    if len > Length then
        local factor = Length / len
        return { x * factor, y * factor, z * factor }
    end
    return Vector
end

-- Ermittelt wie "NVector.GetPos" eine Position in dem angegebenen Erzeugungsbereich
-- und begrenzt ihren Vektor auf die Maximallänge 'Length', falls er länger ist.
-- Ist der Vektor nicht länger, wird die von GetPos ermittelte Position zurückgeliefert.
-- Es dürfen nur parameterlose Erzeugungsbereiche übergeben werden.
MissionLib.SetPos = function( Area, Length )
    local vector = NVector.GetPos( { Area = Area } ).Pos
    local x, y, z = vector[1], vector[2], vector[3]
    local len = math.sqrt( x * x + y * y + z * z )
    if len > Length then
        local factor = Length / len
        return { x * factor, y * factor, z * factor }
    end
    return vector
end

-- Liefert den Azimutwinkel Phi des Vektors im Bogenmaß ( 0..2Pi ).
-- ( Winkel zwischen der positiven y-Achse (UpDir) und r(xy), 0° bis 360° )
-- Hinweis: Normalerweise wird der atan2-Funktion der Vektor als ( y, x ) übergeben,
-- allerdings ist das Koordinatensystem in Darkstar One um 180° verdreht, daher atan2( x, y ).
MissionLib.GetVectorAzimut = function( Vector )
    return math.atan2( Vector[1], Vector[2] )
end

-- Liefert den Polarwinkel Lambda des Vektors im Bogenmaß ( 0..Pi )
-- ( Winkel zwischen der positiven z-Achse (FrontDir) und r, 0° bis 180° )
MissionLib.GetVectorPolar = function( Vector )
    local x, y = Vector[1], Vector[2]
    local sqrVec = x * x + y * y
    if sqrVec > 0 then
        return( PI / 2.0 - math.atan( Vector[3] / math.sqrt( sqrVec ) ) )
    end
    return sqrVec
end

-- Errechnet den Vektor (x,y,z) aus Vektorlänge, Azimut- und Polarwinkel.
-- ( Umrechnung von Kugelkoordinaten in Kartesische Koordinaten )
-- Als Besonderheit dürfen dieser Funktion die 3 Werte auch als Tabelle in
-- 'Radius' übergeben und die anderen beiden Parameter weggelassen werden.
MissionLib.GetVectorCartesian = function( Radius, Azimut, Polar )
    if lua.type( Radius ) == "table" then
        Azimut = Radius[2]
        Polar  = Radius[3]
        Radius = Radius[1]
    end
    local radius_sin_p = Radius * math.sin( Polar )
    return {
        radius_sin_p * math.sin( Azimut ),
        radius_sin_p * math.cos( Azimut ),
        Radius * math.cos( Polar )
    }
end

-- Rechnet Kartesische Koordinaten (x,y,z) in Kugelkoordinaten (r, Phi, Lambda) um.
-- Liefert eine Tabelle mit den Parametern 'Radius', 'Azimut' und 'Polar' zurück.
-- Vereint die Funktionen "GetVectorLength", "GetVectorAzimut" und "GetVectorPolar".
MissionLib.GetVectorSpherical = function( Vector )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    local sqrVec = lua.tofloat( x * x + y * y )
    local polar = 0.0
    if sqrVec > 0 then
        polar = PI / 2.0 - math.atan( z / math.sqrt( sqrVec ) )
    end
    return {
        Radius = math.sqrt( sqrVec + z * z ),
        Azimut = math.atan2( x, y ),
        Polar  = polar
    }
end

-- Errechnet den Vektor (x,y,z) aus Torusradius (R), Kreisradius (r), Azimut- und Polarwinkel.
-- ( Umrechnung von Toruskoordinaten in Kartesische Koordinaten. Ist für Volltori geeignet.)
-- Dieser Funktion dürfen die 4 Werte 'RadiusTorus', 'RadiusCircle', 'Azimut' und 'Polar' auch
-- als Tabelle in 'RadiusTorus' übergeben und die anderen drei Parameter weggelassen werden.
MissionLib.GetVectorCartesianTorus = function( RadiusTorus, RadiusCircle, Azimut, Polar )
    if lua.type( RadiusTorus ) == "table" then
        RadiusCircle = RadiusTorus[2]
        Azimut       = RadiusTorus[3]
        Polar        = RadiusTorus[4]
        RadiusTorus  = RadiusTorus[1]
    end
    local radius_cos_p = RadiusCircle * math.cos( Polar ) + RadiusTorus
    return {
        radius_cos_p * math.sin( Azimut ),
        radius_cos_p * math.cos( Azimut ),
        RadiusCircle * math.sin( Polar )
    }
end

-- Errechnet aus den Kartesischen Koordinaten (x,y,z) und dem Torusradius (R) den Kreisradius (r).
MissionLib.GetVectorRadiusTorus = function( Vector, RadiusTorus )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    local len2dXY = math.sqrt( x * x + y * y ) - RadiusTorus
    return math.sqrt( len2dXY * len2dXY + z * z )
end

-- Dreht den Vektor (x,y,z) um die Winkel 'AngleY' (Azimutwinkel Phi = Ausrichtung der Y-Achse)
-- und 'AngleZ' (Polarwinkel Lambda = Ausrichtung der Z-Achse) und liefert die neue Position zurück.
MissionLib.RotateVector = function( Vector, AngleY, AngleZ )
    local spherical = MissionLib.GetVectorSpherical( Vector )
    local azimut = spherical.Azimut + AngleY
    local polar  = spherical.Polar  + AngleZ
    return MissionLib.GetVectorCartesian( spherical.Radius, azimut, polar )
end

-- Dreht den Vektor auf die angegebenen Y- und Z-Winkel und liefert die neue Position zurück.
MissionLib.RotateVectorTo = function( Vector, AngleY, AngleZ )
    local x, y, z = Vector[1], Vector[2], Vector[3]
    local radius = math.sqrt( x * x + y * y + z * z )
    return MissionLib.GetVectorCartesian( radius, AngleY, AngleZ )
end

-- Verschiebt den Vektor um den Betrag 'Distance' in Richtung 'AngleY' und 'AngleZ'
-- auf eine neue Position und liefert die neuen Koordinaten zurück (Translation).
-- Dieser Funktion dürfen 'Distance', 'AngleY' und 'AngleZ' auch als Tabelle
-- in 'Distance' übergeben und die anderen beiden Parameter weggelassen werden.
MissionLib.MoveVector = function( Vector, Distance, AngleY, AngleZ )
    if lua.type( Distance ) == "table" then
        AngleY   = Distance[2]
        AngleZ   = Distance[3]
        Distance = Distance[1]
    end
    local relpos = MissionLib.GetVectorCartesian( Distance, AngleY, AngleZ )
    return {
        Vector[1] + relpos[1],
        Vector[2] + relpos[2],
        Vector[3] + relpos[3]
    }
end

-- Verschiebt den Nullpunkt des Vektors auf eine neue Position 'Center'
-- und liefert die neuen Koordinaten zurück (Translation).
MissionLib.MoveVectorTo = function( Vector, Center )
    return {
        Vector[1] + Center[1],
        Vector[2] + Center[2],
        Vector[3] + Center[3]
    }
end

-- Dreht das ganze Koordinatenfeld 'VectorTable' um die Winkel 'AngleY' und 'AngleZ'
-- und liefert eine Tabelle mit den neu berechneten Vektoren zurück (Rotation).
-- Damit lassen sich die mit den weiter unten stehenden Funktionen erzeugten und parallel
-- zu den xyz-Achsen ausgerichteten Koordinatenfelder in beliebige Positionen verdrehen.
-- In 'Center' kann ein Vektor als Bezugspunkt für die Rotationsachse übergeben werden, wie z.B.
-- das eigene Zentrum, ansonsten wird das Feld um das Systemzentrum (die Handelsstation) gedreht.
MissionLib.RotateVectorTable = function( VectorTable, AngleY, AngleZ, Center )
    if lua.type( VectorTable ) == "table" and lua.sizeof( VectorTable ) > 0 and AngleY and AngleZ then
        local table = {}
        if MissionLib.IsVector( Center ) then
            local x0, y0, z0 = Center[1], Center[2], Center[3]
            for i, vector in VectorTable do
                local relpos = { vector[1] - x0, vector[2] - y0, vector[3] - z0 }
                relpos = MissionLib.RotateVector( relpos, AngleY, AngleZ )
                table[i] = { relpos[1] + x0, relpos[2] + y0, relpos[3] + z0 }
            end
        else
            for i, vector in VectorTable do
                table[i] = MissionLib.RotateVector( vector, AngleY, AngleZ )
            end
        end
        return table
    end
end

-- Dreht das ganze Koordinatenfeld 'VectorTable' auf die angegebenen Y- und Z-Winkel
-- und liefert eine Tabelle mit den neu berechneten Vektoren zurück (Rotation).
-- Soll das Feld um sein eigenes oder ein anderes Zentrum gedreht werden, muss dieser Vektor in
-- 'Center' übergeben werden, ansonsten wird es um das Systemzentrum (die Handelsstation) gedreht.
MissionLib.RotateVectorTableTo = function( VectorTable, AngleY, AngleZ, Center )
    if lua.type( VectorTable ) == "table" and lua.sizeof( VectorTable ) > 0 and AngleY and AngleZ then
        local table = {}
        if MissionLib.IsVector( Center ) then
            local x0, y0, z0 = Center[1], Center[2], Center[3]
            for i, vector in VectorTable do
                local relpos = { vector[1] - x0, vector[2] - y0, vector[3] - z0 }
                relpos = MissionLib.RotateVectorTo( relpos, AngleY, AngleZ )
                table[i] = { relpos[1] + x0, relpos[2] + y0, relpos[3] + z0 }
            end
        else
            for i, vector in VectorTable do
                table[i] = MissionLib.RotateVectorTo( vector, AngleY, AngleZ )
            end
        end
        return table
    end
end

-- Verschiebt das ganze Koordinatenfeld 'VectorTable' um den Betrag 'Distance' in Richtung 'AngleY'
-- und 'AngleZ' und liefert eine Tabelle mit den neu berechneten Vektoren zurück (Translation).
MissionLib.MoveVectorTable = function( VectorTable, Distance, AngleY, AngleZ )
    if  lua.type( VectorTable ) == "table" and lua.sizeof( VectorTable ) > 0
    and Distance and AngleY and AngleZ then
        local table = {}
        for i, vector in VectorTable do
            table[i] = MissionLib.MoveVector( vector, Distance, AngleY, AngleZ )
        end
        return table
    end
end

-- Verschiebt den Nullpunkt des ganzen Koordinatenfeldes 'VectorTable' auf eine neue Position
-- 'Center' und liefert eine Tabelle mit den neu berechneten Vektoren zurück (Translation).
MissionLib.MoveVectorTableTo = function( VectorTable, Center )
    if  lua.type( VectorTable ) == "table" and lua.sizeof( VectorTable ) > 0
    and MissionLib.IsVector( Center ) then
        local table = {}
        local x0, y0, z0 = Center[1], Center[2], Center[3]
        for i, vector in VectorTable do
            table[i] = { vector[1] + x0, vector[2] + y0, vector[3] + z0 }
        end
        return table
    end
end

--------------------------------------------------------------------------------

-- Liefert eine zufällige Position innerhalb einer Kugelschale zwischen den Entfernungen
-- 'RadiusMin' und 'RadiusMax' vom Mittelpunkt 'Center'. Wird 'RadiusMax' nicht angegeben,
-- liegt die Position innerhalb einer Kugel mit 'RadiusMin'. Ist 'RadiusMin' = 'RadiusMax',
-- liefert die Funktion eine Position an der Kugeloberfläche.
MissionLib.RandomPosGlobe = function( Center, RadiusMin, RadiusMax )
    if RadiusMin then
        if not RadiusMax then    -- Kugel, keine Kugelschale
            RadiusMax = RadiusMin
            RadiusMin = 0.0
        end
        -- zufällige Vektorlänge zwischen RadiusMin und RadiusMax:
        local radius = MissionLib.RandomFloat( RadiusMin, RadiusMax )
        -- zufällige Richtung (PI = 180°):
        local azimut = math.random() * PI * 2.0  -- Azimutwinkel y -> r(xy)
        local polar  = math.random() * PI        -- Polarwinkel  z -> r
        -- relative Koordinaten berechnen:
        local pos = MissionLib.GetVectorCartesian( radius, azimut, polar )
        -- absolute Koordinaten zurückliefern:
        return {
            pos[1] + Center[1],
            pos[2] + Center[2],
            pos[3] + Center[3]
        }
    end
end

-- Liefert eine zufällige Position innerhalb eines Torus zwischen den Kreisradien 'RadiusMin'
-- und 'RadiusMax'. Im Innenring mit 'RadiusMin' werden keine Koordinaten erzeugt (Röhre).
-- Der Kreismittelpunkt hat den Abstand 'RadiusTorus' vom Torusmittelpunkt 'Center'.
-- Wird 'RadiusMax' nicht angegeben, liegt die Position innerhalb des Torus mit 'RadiusMin'.
-- Ist 'RadiusMin' = 'RadiusMax', liefert die Funktion eine Position an der Torusoberfläche.
-- Abhängig davon, wie man die Radien setzt, lassen sich mit dieser Funktion die Positionen
-- in allen drei Toritypen erzeugen: In einem Spindeltorus, Horntorus oder Ringtorus.
MissionLib.RandomPosTorus = function( Center, RadiusTorus, RadiusMin, RadiusMax )
    if RadiusTorus and RadiusMin then
        if not RadiusMax then    -- Volltorus, keine Torusschale bzw. Röhre
            RadiusMax = RadiusMin
            RadiusMin = 0.0
        end
        local radius = MissionLib.RandomFloat( RadiusMin, RadiusMax )
        local azimut = math.random() * PI * 2.0
        local polar  = math.random() * PI
        local pos = MissionLib.GetVectorCartesianTorus( RadiusTorus, radius, azimut, polar )
        return {
            pos[1] + Center[1],
            pos[2] + Center[2],
            pos[3] + Center[3]
        }
    end
end

-- Liefert eine zufällige Position innerhalb eines Zylinders mit der Länge 'Length'
-- zwischen dem Innenradius 'RadiusMin' und dem Außenradius 'RadiusMax'. In der inneren
-- Röhre mit 'RadiusMin' werden keine Koordinaten erzeugt, außer, wenn der Wert = 0 ist
-- oder 'RadiusMax' nicht angegeben wurde. In letzterem Fall liegt die Position innerhalb
-- des Zylinders mit 'RadiusMin'. Ist 'RadiusMin' = 'RadiusMax', liefert die Funktion eine
-- Position an der Zylinderoberfläche. Der Parameter 'Axis' bestimmt die Längsausrichtung
-- des Zylinders: 1 = x-Achse, 2 = y-Achse und 3 = z-Achse.
-- 'Center' ist die absolute Position des Zylinderzentrums im Raum.
MissionLib.RandomPosCylinder = function( Center, Axis, Length, RadiusMin, RadiusMax )
    if Axis and Length and RadiusMin then
        if Axis < 1 or Axis > 3 then Axis = 3; end
        if not RadiusMax then    -- Vollzylinder, keine Röhre
            RadiusMax = RadiusMin
            RadiusMin = 0.0
        end
        local random = math.random
        local radius = MissionLib.RandomFloat( RadiusMin, RadiusMax )
        local angle = random() * PI * 2.0
        local posA = radius * math.sin( angle )
        local posB = radius * math.cos( angle )
        local posC = random() * Length / 2.0
        if random() > 0.5 then
            posC = Center[Axis] + posC
        else
            posC = Center[Axis] - posC
        end
        if Axis == 3 then
            return { posA + Center[1], posB + Center[2], posC }
        elseif Axis == 2 then
            return { posA + Center[1], posC, posB + Center[3] }
        else
            return { posC, posA + Center[2], posB + Center[3] }
        end
    end
end

-- Liefert eine zufällige Position innerhalb eines gleichseitigen Tetraeders mit der
-- Kantenlänge 'LengthMax'. Für den inneren Tetraeder mit der Kantenlänge 'LengthMin'
-- werden keine Koordinaten erzeugt, außer, wenn der Wert = 0 ist oder 'LengthMax'
-- nicht angegeben wurde. In letzterem Fall liegt die Position innerhalb des Tetraeders
-- mit 'LengthMin'. Ist 'LengthMin' = 'LengthMax', liefert die Funktion eine Position
-- an der Tetraederoberfläche. Der Parameter 'Axis' bestimmt die Ausrichtung einer der
-- Spitzen: 1 = x-Achse, 2 = y-Achse und 3 = z-Achse.
-- 'Center' ist die absolute Position des Tetraederzentrums im Raum.
MissionLib.RandomPosTetraeder = function( Center, Axis, LengthMin, LengthMax )
    -- (in Vorbereitung)
end

-- Liefert eine zufällige Position innerhalb eines Würfels mit der Kantenlänge 'LengthMax'.
-- Für den inneren Würfel mit der Kantenlänge 'LengthMin' werden keine Koordinaten erzeugt,
-- außer, wenn der Wert = 0 ist oder 'LengthMax' nicht angegeben wurde. In letzterem Fall
-- liegt die Position innerhalb des Würfels mit 'LengthMin'. Ist 'LengthMin' = 'LengthMax',
-- liefert die Funktion eine Position an der Würfeloberfläche.
-- 'Center' ist wiederum die absolute Position des Würfelzentrums im Raum.
MissionLib.RandomPosCube = function( Center, LengthMin, LengthMax )
    if LengthMin then
        local vector = {}
        LengthMin = LengthMin / 2.0
        if LengthMax then
            LengthMax = LengthMax / 2.0
        else
            LengthMax = LengthMin
            LengthMin = 0.0
        end
        local random = math.random
        if LengthMin == 0.0 then
        -- Position im gesamten Würfel
            for i, pos in Center do
                local length = random() * LengthMax
                if random() > 0.5 then
                    vector[i] = pos + length
                else
                    vector[i] = pos - length
                end
            end
        elseif LengthMin == LengthMax then
        -- Position nur an der Oberfläche
            local length
            local axis = lua.tonumber( 1 + random() * 3 )
            for i, pos in Center do
                if random() > 0.5 then
                    length = LengthMax
                else
                    length = -LengthMax
                end
                if i == axis then
                    vector[i] = pos + length
                else
                    vector[i] = pos + random() * length
                end
            end
        else
        -- Position zwischen Innen- und Außenwürfel
            -- zufällige Achse wählen
            local axis = lua.tonumber( 1 + random() * 3 )
            -- neue Maximallänge = Minimallänge plus zufällige Differenzlänge
            LengthMax = LengthMin + random() * ( LengthMax - LengthMin )
            -- zufällige Seitenfläche wählen und die erste Koordinate setzen
            if random() > 0.5 then
                vector[axis] = Center[axis] + LengthMax
            else
                vector[axis] = Center[axis] - LengthMax
            end
            -- die anderen 2 Koordinaten irgendwo in der Ebene 'vector[axis]' setzen
            for i, pos in Center do
                if i ~= axis then
                    local length = random() * LengthMax
                    if random() > 0.5 then
                        vector[i] = pos + length
                    else
                        vector[i] = pos - length
                    end
                end
            end
        end
        return vector
    end
end

--============================[ Erzeugung von Objekten ]========================

------------------------------[ Minenfelder ]-----------------------------------

-- Erzeugt ein Minenfeld mit zufälliger Verteilung im angegebenen Erzeugungsbereich.
-- In 'Area' können nur Erzeugungsbereiche ohne Parameter angegeben werden. Kann kein Bereich gefunden
-- werden, da ein entsprechendes Objekt fehlt, z.B. ein Asteroid, hat die Funktion keine Auswirkung.
MissionLib.CreateMineFieldArea = function( Area, MineCount )
    local area = { Area = Area }
    local RandomPos = NVector.GetPos
    if not MissionLib.IsVectorLengthNull( RandomPos( area ).Pos ) then
        local CreateMine = NObject.CreateMine
        local mineField = {}
        for i = 1, MineCount do
            mineField[i] = CreateMine( { Position = RandomPos( area ).Pos } ).Mine
        end
        return mineField
    end
end

-- Erzeugt eine Kugel oder Kugelschale aus Minen mit zufälliger Verteilung.
-- 'Coordinates' ist eine Tabelle mit folgendem Aufbau:
--    Coordinates[1] = table[3]:float - Vektor (x,y,z) des Kugelzentrums
--    Coordinates[2] = float - Innenradius der Kugelschale
--    Coordinates[3] = float - Außenradius der Kugel
-- Ist der Innenradius = 0 und der Außenradius wurde übergeben, sind die Minen in der
-- ganzen Kugel verteilt. Wird der Außenradius weggelassen, dann gilt der Innenradius
-- als Außenradius und es werden nur Minen an der Kugeloberfläche erzeugt.
MissionLib.CreateMineFieldGlobe = function( Coordinates, MineCount )
    local center = Coordinates[1]
    local radMin = Coordinates[2]
    local radMax = Coordinates[3]
    local CreateMine = NObject.CreateMine
    local RandomPos = MissionLib.RandomPosGlobe
    local mineField = {}
    for i = 1, MineCount do
        mineField[i] = CreateMine( { Position = RandomPos( center, radMin, radMax ) } ).Mine
    end
    return mineField
end

-- Erzeugt einen Torus aus Minen mit zufälliger Verteilung.
-- 'Coordinates' ist eine Tabelle mit folgendem Aufbau:
--    Coordinates[1] = table[3]:float - Vektor (x,y,z) des Toruszentrums
--    Coordinates[2] = float - Torusradius (R)
--    Coordinates[3] = float - Innenradius (r) der Torusröhre
--    Coordinates[4] = float - Außenradius (r) der Torusröhre
-- Ist der Innenradius = 0 oder wird der Außenradius weggelassen (Innenradius
-- gilt dann als Außenradius), sind die Minen im ganzen Torus verteilt.
MissionLib.CreateMineFieldTorus = function( Coordinates, MineCount )
    local center = Coordinates[1]
    local radius = Coordinates[2]
    local radMin = Coordinates[3]
    local radMax = Coordinates[4]
    local CreateMine = NObject.CreateMine
    local RandomPos = MissionLib.RandomPosTorus
    local mineField = {}
    for i = 1, MineCount do
        mineField[i] = CreateMine( { Position = RandomPos( center, radius, radMin, radMax ) } ).Mine
    end
    return mineField
end

-- Erzeugt einen Zylinder aus Minen mit zufälliger Verteilung.
-- 'Coordinates' ist eine Tabelle mit folgendem Aufbau:
--    Coordinates[1] = table[3]:float - Vektor (x,y,z) des Zylinderzentrums
--    Coordinates[2] =  int  - Ausrichtung der Zylinderachse (1=x, 2=y, 3=z)
--    Coordinates[3] = float - Länge des Zylinders
--    Coordinates[4] = float - Innenradius (r) des Zylinders
--    Coordinates[5] = float - Außenradius (r) des Zylinders
-- Ist der Innenradius = 0 oder wird der Außenradius weggelassen (Innenradius
-- gilt dann als Außenradius), sind die Minen im ganzen Zylinder verteilt.
MissionLib.CreateMineFieldCylinder = function( Coordinates, MineCount )
    local center = Coordinates[1]
    local axis   = Coordinates[2]
    local length = Coordinates[3]
    local radMin = Coordinates[4]
    local radMax = Coordinates[5]
    local CreateMine = NObject.CreateMine
    local RandomPos = MissionLib.RandomPosCylinder
    local mineField = {}
    for i = 1, MineCount do
        mineField[i] = CreateMine( { Position = RandomPos( center, axis, length, radMin, radMax ) } ).Mine
    end
    return mineField
end

-- Erzeugt einen Tetraeder aus Minen mit zufälliger Verteilung. (in Vorbereitung)
-- 'Coordinates' ist eine Tabelle mit folgendem Aufbau:
--    Coordinates[1] = table[3]:float - Vektor (x,y,z) des Tetraederzentrums
--    Coordinates[2] =  int  - Ausrichtung einer Tetraederachse (1=x, 2=y, 3=z)
--    Coordinates[3] = float - Kantenlänge des Innentetraeders
--    Coordinates[4] = float - Kantenlänge des Außentetraeders
-- Ist die innere Kantenlänge = 0 oder wird die äußere Kantenlänge weggelassen
-- (Innenlänge ist dann Außenlänge), sind die Minen im ganzen Tetraeder verteilt.
MissionLib.CreateMineFieldTetraeder = function( Coordinates, MineCount )
    local center = Coordinates[1]
    local axis   = Coordinates[2]
    local lenMin = Coordinates[3]
    local lenMax = Coordinates[4]
    local CreateMine = NObject.CreateMine
    local RandomPos = MissionLib.RandomPosTetraeder
    local mineField = {}
    for i = 1, MineCount do
        mineField[i] = CreateMine( { Position = RandomPos( center, axis, lenMin, lenMax ) } ).Mine
    end
    return mineField
end

-- Erzeugt einen Würfel aus Minen mit zufälliger Verteilung,
-- wobei der innere Würfel, falls angegeben, frei von Minen bleibt.
-- 'Coordinates' ist eine Tabelle mit folgendem Aufbau:
--    Coordinates[1] = table[3]:float - Vektor (x,y,z) des Würfelzentrums
--    Coordinates[2] = float - Kantenlänge des Innenwürfels
--    Coordinates[3] = float - Kantenlänge des Außenwürfels
-- Ist die innere Kantenlänge = 0 oder wird die äußere Kantenlänge weggelassen
-- (Innenlänge ist dann Außenlänge), sind die Minen im ganzen Würfel verteilt.
MissionLib.CreateMineFieldCube = function( Coordinates, MineCount )
    local center = Coordinates[1]
    local lenMin = Coordinates[2]
    local lenMax = Coordinates[3]
    local CreateMine = NObject.CreateMine
    local RandomPos = MissionLib.RandomPosCube
    local mineField = {}
    for i = 1, MineCount do
        mineField[i] = CreateMine( { Position = RandomPos( center, lenMin, lenMax ) } ).Mine
    end
    return mineField
end

-- Erzeugt ein mittelgroßes Minenfeld aus 100 Minen.
-- Es wird ein quadratisches Minenfeld in der XY-Ebene erzeugt und die Minen werden in
-- unterschiedliche Z-Richtungen verschoben, sodass eine ungefähre Würfelform entsteht.
MissionLib.CreateMineField = function( Center )
    local xPos = Center[1] - 135
    local yOfs = Center[2] - 135
    local zOfs = Center[3]
    local xIdx = 0
    local sin = math.sin
    local CreateMine = NObject.CreateMine
    local mineField = {}
    for x = 1, 10 do
        local xSin = sin( x * 1.5 ) * 100
        local yPos = yOfs
        for y = 1, 10 do
            mineField[xIdx + y] = CreateMine( {
                Position = { xPos, yPos, xSin + sin( y * 1.5 ) * 200 + zOfs }
            } ).Mine
            yPos = yPos + 30
        end
        xIdx = xIdx + 10
        xPos = xPos + 30
    end
    return mineField
end

-- Erzeugt einen Würfel aus 1000 Minen, mit "Zündschnur"
MissionLib.CreateMineFieldBigCube = function()
    local index = 0
    local CreateMine = NObject.CreateMine
    local mineField = {}
    for x = 50, 500, 50 do
        for y = 50, 500, 50 do
            for z = 50, 500, 50 do
                index = index + 1
                mineField[index] = CreateMine( { Position = { x - 1775, y - 275, z + 3000 } } ).Mine
            end
        end
    end
    -- Zündschnur zum Minenfeld
    for x = 1, 20 do
        mineField[x + 1000] = CreateMine( { Position = { x * 50 - 1280, 0, 3275 } } ).Mine
    end
    return mineField
end

-- Erzeugt eine runde Scheibe als Minenfeld (in Vorbereitung)
MissionLib.CreateMineFieldDisk = function( Coordinates, MineCount )
end

-- Erzeugt ein quadratisches Minenfeld (in Vorbereitung)
MissionLib.CreateMineFieldSquare = function( Coordinates, MineCount )
end

-- Erzeugt ein rechteckiges Minenfeld (in Vorbereitung)
MissionLib.CreateMineFieldRect = function( Coordinates, MineCount )
end

-- Erzeugt ein sternförmiges Minenfeld (in Vorbereitung)
MissionLib.CreateMineFieldStar = function( Coordinates, MineCount )
end

------------------------------[ Schiffe und Wings ]-----------------------------

-- Erzeugt ein Kreuzerwrack und liefert dessen Position zurück.
-- Der Parameter 'PosDescr' kann entweder eine absolute Positionsangabe {x,y,z}
-- oder eine parameterlose Positionsbeschreibung (POSDESCR_OFFSET,... usw.) sein.
-- POSDESCR_EXPLICIT und dynamische Eintrittspositionen dürfen nicht übergeben werden.
-- Existiert der Parameter 'Explode', dann explodiert der Kreuzer anstatt einfach durch sein
-- Wrack ersetzt zu werden. Dessen Handle kann im "StarshipDestroyed"-Event ermittelt werden.
MissionLib.CreateWreck = function( Type, Race, PosDescr )
    local position
    if lua.type( PosDescr ) == "table" then
        position = PosDescr
        PosDescr = POSDESCR_EXPLICIT
    end
    if Race == "Random" then
        Race = MissionLib.RandomInt0( 5 )
    end
    local cruiser = NWing.Create( {
        WingType = Type,
        Race     = Race,
        Number   = 1,
        PosType  = PosDescr,
        Position = position
    } ).Wing
    local ship = get( "Logic.Wings."..cruiser..".leader" )
    position = NObject.GetPosition( { Object = ship } ).Position
    if Explode then
        -- Liefert das Handle vom Wrack im Event "StarshipDestroyed"
        set( "Logic.StarShips."..ship..".hullCondition", 0.0 )
    else
        -- Liefert kein Handle, die Rückgabetabelle ist immer leer
        NShip.CreateWreck( { Ship = ship } )
    end
    return position
end

-- Erzeugt einen Wing aus S'kaadrohnen. Nur der Leader ist in der Targetliste sichtbar und hat
-- eine Markierung im Raum. Ist nur eine Drohne im Wing, ist sie in der Targetliste unsichtbar.
-- Sie kann zwar mit RadarMapColor in der Targetliste sichtbar gemacht werden, hat aber immer
-- noch keine Zielmarkierung im Raum, was sich auch mit SetHidden nicht ändern lässt.
-- Die Parametertabelle 'Data' ist ähnlich der von NWing.Define, jedoch darf weder 'WingType'
-- noch wird 'Ships' übergegeben, sondern die Anzahl der Schiffe im Parameter 'Number'.
-- Die Angabe von 'Level' oder 'LevelOffset' ist optional. Parametertabelle:
-- { Number, Level|LevelOffset, Names, PosType, Position|Object & Distance, FrontDir, UpDir }
MissionLib.CreateSkaaDrones = function( Data )
    local shiplist = {}
    local skaaship = { ObjType = ST_SKAADRONE, ObjIndex = 0 }    -- ObjIndex ist egal
    if Data.Level then
        skaaship.Level = Data.Level
    elseif Data.LevelOffset then
        skaaship.LevelOffset = Data.LevelOffset
    end
    for i = 1, Data.Number do
        shiplist[i] = skaaship
    end
    Data.Ships = shiplist
    return NWing.Define( Data ).Wing
end

-- Erzeugt ein S’kaa-Mutterschiff des Wingtyps WINGTYPE_CRUISER1
-- TODO: Begleitschutz aus S’kaa-Schwärmen
MissionLib.CreateSkaaCruiser1 = function( PosDescr, Front )
    local position
    if lua.type( PosDescr ) == "table" then
        position = PosDescr
        PosDescr = POSDESCR_EXPLICIT
    end
    if not Front then
        Front = SYSTEM_CENTER
    end
    return NWing.Define( {
        Ships = { { ObjType = ST_CRUISER, ObjIndex = 13 } },
        PosType = PosDescr,
        Position = position,
        FrontDir = Front
    } ).Wing
end

-- Das Schiff wirft eine Mine hinter sich ab. Wird in 'Target' ein Zielhandle
-- übergeben, erzeugt die Funktion eine feuernde Drohne mit dem Ziel 'Target'.
MissionLib.ShipDropMine = function( Ship, Target )
    if Ship and NShip.IsInSpace( { Ship = Ship } ).InSpace == 1 then
        local pos = { Position = MissionLib.PosBehindShip( Ship, 40 ) }
        if Target then
            pos.AimShip = Target
            pos.Shooter = 1
        end
        return NObject.CreateMine( pos ).Mine
    end
end

-- Der Spieler wirft eine Mine hinter sich ab. Wird in 'Target' ein Zielhandle
-- übergeben, erzeugt die Funktion eine feuernde Drohne mit dem Ziel 'Target'.
MissionLib.PlayerDropMine = function( Target )
    local pos = { Position = MissionLib.PosBehindPlayer( 40 ) }
    if Target then
        pos.AimShip = Target
        pos.Shooter = 1
    end
    local mine = NObject.CreateMine( pos ).Mine
    NObject.RadarMapColor( { Object = mine, Color = RADARMAP_WHITE_HIDDEN } )
    return mine
end

--============================[ Gameplay Einstellungen ]========================

-- Liefert den im Optionsmenü des Spiels eingestellten Schwierigkeitsgrad ( 0..4 )
MissionLib.GameplayLevel = function()
    return get( "Startwerte.Application.Difficulty", 0 )
end
MissionLibEx.lua Quellcode Ende


GetStarClusterId

GetStarClusterId( SystemId )

Liefert die ClusterID eines Systems.
Ist der Parameter 'SystemId' nicht vorhanden oder ungültig, wird die ClusterId des aktuellen Systems geliefert.

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
SystemId | unsigned int | 0..402 | Id des Systems

Rückgabewert
Beschreibung | Datentyp | Wertebereich | Kommentar
ClusterId | unsigned int | 0..29 | Id des Clusters

Beispiel

-- Cluster vom Sol-System
V.AlphaCentauri = MissionLib.GetStarClusterId( 29 )

-- Wo bin ich gerade?
local myCluster = MissionLib.GetStarClusterId()


GetIllegalGoods

GetIllegalGoods( SystemId )

Ermittelt die verbotenen Spezialwaren eines Systems.
Fehlt der Parameter 'SystemId', wird die Id des aktuellen Systems verwendet.

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
SystemId | unsigned int | 0..402 | Id des Systems

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
n/a | table[1..2] : enum | 20..24 (Handelswaren) | Tabelle mit den verbotenen Waren, 24 = alles ist erlaubt

Beispiel

-- Sol-System abfragen
local forbidden = MissionLib.GetIllegalGoods( 29 )

if forbidden[1] == GOODS_NONE then
    V.Legal = "all"
else
    -- Androiden und Drogen sind hier verboten
    V.Illegal1 = forbidden[1]	-- GOODS_ANDROIDS
    V.Illegal2 = forbidden[2]	-- GOODS_DRUGS
end


Pow

Pow( x, n )

Liefert die Potenz xn (nur positive Zahlen für 'x', negativer Exponent 'n' funktioniert).
Diese Funktion ist leider etwas ungenau und auch nur eingeschränkt nutzbar. Geht aber nicht anders, denn es wurden weder die LUA-Funktion "math.pow(x,y)" noch der Operator "^" im Moddingtool integriert.

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
x | float | >= 0.0 | Basis
n | float | n/a | Exponent

Rückgabewert
Beschreibung | Datentyp | Wertebereich | Kommentar
Ergebnis | float | n/a | Wert der Potenz

Beispiel

-- 1024 = 210
local result = MissionLib.Pow( 2, 10 )

-- 0.0625 = 2-4
local result = MissionLib.Pow( 2, -4 )


Root

Root( n, x )

Liefert die Wurzel n√x (nur positive Zahlen für 'x', negative Wurzel 'n' funktioniert).
Diese Funktion ist leider etwas ungenau und auch nur eingeschränkt nutzbar. Geht aber nicht anders, denn es wurden weder die LUA-Funktion "math.pow(x,y)" noch der Operator "^" im Moddingtool integriert, mit denen man auch Wurzeln höherer Ordnung als nur Quadratwurzeln ziehen könnte (z.B.: 3√x = x1/3).

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
n | float | n/a | Wurzelexponent
x | float | >= 0.0 | Wurzelbasis (Radikand)

Rückgabewert
Beschreibung | Datentyp | Wertebereich | Kommentar
Ergebnis | float | n/a | Wurzel

Beispiel

-- 4 = 3√64
local result = MissionLib.Root( 3, 64 )


IsMissionAchieved

IsMissionAchieved( pMission )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


CreateMineFieldGlobe

CreateMineFieldGlobe( Coordinates, MineCount )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


IsObject

IsObject( Object )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


GetOrbiterPos

GetOrbiterPos( OrbiterId )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


IsOrbiter

IsOrbiter( Object )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


GetPlayerHull()

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


RandomBool()

Liefert einen boolschen Zufallswert.

Parameter
Leer

Rückgabewert
Boolean

Beispiel

if MissionLib.RandomBool() == true then
    NGUI.ShowInfoText( { Text = "ID_TRUE" } )
else
    NGUI.ShowInfoText( { Text = "ID_FALSE" } )
end


IsShip

IsShip( Object ) : { IsShip, ShipType }

Liefert true und den Schiffstyp, wenn das Objekt ein Schiff ist.

Parameter
Parameter | Datentyp | Wertebereich | Kommentar
Object | unsigned int | CObjectHandle | Handle eines Space-Objekts

Rückgabetabelle
Feldbezeichner | Datentyp | Wertebereich | Kommentar
IsShip | bool | false/true | true, wenn das Objekt ein Schiff ist, ansonsten false
ShipType | unsigned int | ShipType | Liefert den Schiffstyp, wenn das Objekt ein Schiff ist

Beispiel

-- Wenn das selektierte Ziel ein Kreuzer ist, Landung erlauben.
-- Hat bei kleinen Kreuzern keine Auswirkung, da sie keinen Hangar haben.
{    2, nil, "TargetSelect", function( V, Data )
    local object = MissionLib.IsShip( Data.Target )
    if object.IsShip and ( object.ShipType == ST_CRUISER ) then
    NObject.PlayerLanding( { Object = Data.Target, Accept = 1 } )
    end
end },


GetStarSystemNation

GetStarSystemNation( SystemId )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


IsTable

IsTable( Item )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


AddVector

AddVector( Vector1, Vector2 )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


SetWingCloaked

SetWingCloaked( WingId, Switch )

Text

Parameter
Leer

Parametertabelle
Keine

Rückgabewert

Rückgabetabelle
Keine

Beispiel


Tabellen

Häufig benötigte Listen der Bezeichner für die in den Skripts verwendeten Konstanten.

Inhalt

  1. Ausrüstung
  2. Container
  3. Erzeugungsbereiche
  4. Handelswaren
  5. Kommunikation
  6. Kameras
  7. Kreuzer und Superfrachter
  8. Missionen
    • Missionslisten
    • Fortschritt der Story
    • Die globale Missionstabelle MISSION_TABLE
    • Die globale Skripttabelle SCRIPT_TABLE
  9. Missionstypen
  10. Munition
  11. Objekte und Orbiter
  12. Piratengangs
  13. Plasmawerfer
  14. PlayerShip
  15. Radarfarben
  16. Rassen
  17. Regierung und Fraktion
  18. StarShips
  19. StarSystems
  20. String-IDs
  21. Wings
  22. Wirtschaft und Wohlstand


Equipment

Ausrüstung

Die im Spiel verfügbaren Ausrüstungsgegenstände
Konstante | Kommentar | Wert
EQUIPMENT_SHIELD_GENERATOR | Schildgenerator | 0
EQUIPMENT_AFTERBURNER | Nachbrenner | 1
EQUIPMENT_HYPERDRIVE | Feldantrieb | 2
EQUIPMENT_SCANNER | Frachtscanner | 3
EQUIPMENT_SCANNER_JAMMER | Jammer, stört die Polizei-Frachtscanner | 4
EQUIPMENT_GENERATOR | Generator, lädt Schildgenerator und Waffenkondensator auf | 5
EQUIPMENT_CAPACITOR | Kondensator, puffert Waffen- und Schildenergie | 6
EQUIPMENT_CARGO_COMPUTER | Frachtcomputer mit Frachtdrohnen | 7
EQUIPMENT_ORE_COLLECTOR | Erzsammler, ermöglicht den Abbau von Rohstoffen in Meteoritenfeldern | 8
EQUIPMENT_ENERGY_COLLECTOR | Energiesammler, regeneriert die Energie für den Sprungantrieb schneller | 9
EQUIPMENT_ENERGYFLUX | Energieflux, ermöglicht Energietransfer zwischen hinterem und vorderem Schild | 10
EQUIPMENT_SHIELDFLUX | Schildflux, ermöglicht Energietransfer zwischen Waffen und Schilden | 11
EQUIPMENT_LANDING_COMPUTER | Landecomputer, für automatische Landungen auf Handelsstationen | 12
EQUIPMENT_TRADE_COMPUTER | Handelscomputer, zeigt alle Warenbestände bereits auf der Navigationskarte an (deaktiviert, da ohne Funktion) | 13
EQUIPMENT_REPAIRBOT | Reparaturbot, repariert einmalig das Schiff | 14
EQUIPMENT_PLASMA_BOOSTER | Plasma-Booster, lädt einmalig den Plasmawerfer auf | 15
EQUIPMENT_SHIELD_BOOSTER | Schild-Booster, lädt einmalig die Schildenergie auf | 16
EQUIPMENT_AFTERBURNER_BOOSTER | Nachbrenner-Booster, erhöht einmalig die Nachbrennerlaufzeit | 17
EQUIPMENT_GRAVITON | Graviton-Schub, vervielfacht die Geschwindigkeit des Schiffs für einige Sekunden | 18
EQUIPMENT_ACTUATOR_REFILL | Aktuator-Refill, lädt einmalig den Sprungantrieb auf | 19
Rot: Konstante in der MissionLibEx.lua definiert.

Typen der Ausrüstungsgegenstände für die Benutzen-Taste
Konstante | Kommentar | Wert
ITEM_TYPE_REPAIRCONTROL | Reparaturbot | 0
ITEM_TYPE_PLASMABOOST | Plasma-Booster | 1
ITEM_TYPE_LANDINGCOMPUTER | Landecomputer | 2
ITEM_TYPE_GRAVITON | Graviton-Schub | 3
ITEM_TYPE_BURNERBOOST | Nachbrenner-Booster | 4
ITEM_TYPE_AKTUATOR | Aktuator-Refill | 5
ITEM_TYPE_SHIELDBOOST | Schild-Booster | 6
ITEM_TYPE_MISSION | Von einer Mission erzeugter Gegenstand | 7

Sternsysteme mit Tech-Level 10

Sternsysteme, die Ausrüstungsgegenstände Klasse 10 zum Kauf anbieten
Cluster | Volk | Klasse 10 Sternsysteme
Lalande | Terraner | Obas, Pachee
Tau Ceti | Terraner | Ote
Alpha Centauri | Terraner | Wini
Grotok | Mortok | Aranjar, Lular, Mandedulce, Matada
Stromok | Mortok | Haorta
Klatok | Mortok | Alquebayo, Avilmurcia, Fribeicon, Vielvietona
Humok | Mortok | Cadacala
Raptor Gamma | Raptor | Chernomen, Schel
Raptor Epsilon | Raptor | Beldets, Simpawlo
Prea'Chan | Oc'to | Dalmiga'vie, Kinloch'ore, Sana'chan
Hive-AC3 | Arrack | Haiken, Mingin, Natkyigon, Pyidaung
Hive-F17 | Arrack | Rankse
Hive-DC | Arrack | Mepok
Hive-G8 | Arrack | Gamnim

Manchmal ändert sich durch die Wirtschaftslage der Tech-Level eines Systems, was sich bei den Klasse 10 Systemen aber meistens wieder normalisiert. Das Sternsystem Mepok im Cluster Hive-DC wäre so ein Beispiel: Dem System geht es am Anfang einmal für kurze Zeit schlecht und es bietet nur noch Klasse 9 Ausrüstung an. Nach kurzer Zeit stabilisiert es sich wieder und bleibt dann dauerhaft auf dem Tech-Level 10. Es gibt auch noch ein paar Fälle, wo es umgekehrt ist. Vor allem bei den Oc'to gibt es einige Systeme, die beim ersten Sprung in einen ihrer Cluster den Tech-Level 10 haben, um dann nach kurzer Zeit für immer auf einen geringeren Level abzufallen.


Containertypen

Eine Aufzählung der vorhandenen Containertypen für NContainer.Create
Konstante | Kommentar | Wert
CONTAINER_SPACE | Container wird im angebenen Raumbereich erzeugt | 0
CONTAINER_ASTEROID | Container für Minenwaren in einem Asteroiden | 1
CONTAINER_SHIP | Container wird erzeugt und an das angegebene Schiff angedockt | 2
CONTAINER_POSITION | Container wird an der angebenen Raumkoordinate frei im Weltall erzeugt | 3

Eine Aufzählung der vorhandenen Containergrößen
Konstante | Kommentar | Wert
CONTAINER_SMALL | Container mit 50t Kapazität | 0
CONTAINER_MEDIUM | Container mit 100t Kapazität | 1
CONTAINER_LARGE | Container mit 200t Kapazität | 2
CONTAINER_SPECIAL | Geheimdienstwaffen-Container (nur 1t Kapazität, belegt ein 200t Frachterdock) | 3
CONTAINER_PASSENGER | Passagiercontainer an Shuttles (nur 1t Kapazität, belegt ein 100t Frachterdock) Hinweis: Kann auch von den 50t-Frachtdrohnen der DSO aufgenommen werden | 4
CONTAINER_ROCK | Container, wie er beim Sprengen eines Meteoriten erzeugt wird (50t Kapazität) | 5
CONTAINER_ARTEFACT | Artefakt-Container (keine Kapazität für Handelswaren, nur Missionswaren) | 6
CONTAINER_NONE | Kein Container gefunden, z.B. für "NContainer.GetType" | -1
Rot: Konstante in der MissionLibEx.lua definiert.

Eine Aufzählung der Containeraktionen für das Event "Container"
Konstante | Kommentar | Wert
CONTAINER_DESTROYED | Container wurde zerstört | 0
CONTAINER_DROPPED | Container wurde fallengelassen | 1
CONTAINER_TAKEN | Container wurde aufgenommen | 2
CONTAINER_METEROID | Ein Container wurde durch Meteoritenabschuss erzeugt | 3


Erzeugungsbereiche

Die Bereiche, in denen Wings erzeugt werden können
Konstante | Parameter | Kommentar | Wert
POSDESCR_PLAYERSHIP -/- Kugelschale um das Spielerschiff im Abstand von 2-4 Units. 0
POSDESCR_INTERCEPTION -/- Dreiviertel-Kugel mit einem Radius von 4 Units. Der Mittelpunkt liegt 4 Units vom Tor entfernt auf der Verbindungsachse Absprungtor – Handelsstation. Der fehlende Kugelabschnitt liegt oberhalb vom Zentrum in Richtung Handelsstation. Die Anzahl der möglichen Positionen ist unbegrenzt. 1
POSDESCR_OFFSET -/- Strahlenförmige Halbkugel mit einem Radius von 3 Units. Der Mittlelpunkt der Grundfläche liegt 3 Units vom Tor entfernt auf der Verbindungsachse Absprungtor - Handelsstation. Von der Handelsstation aus gesehen weist der Halbkugel-Nordpol im Winkel von 45° nach links oben. Es gibt genau 40 verschiedene Positionen. 2
POSDESCR_ASTEROID -/- Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Zentrum des Asteroiden entfernt, auf der zur Handelsstation abgewandten Seite. Hat ein System mehrere Asteroiden, so wird zufällig ein Asteroid gewählt. 3
POSDESCR_TRADESTATION1 -/- Kugel mit einem Radius 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Zentrum der Handelsstation entfernt, auf der zum Absprungtor abgewandten Seite. 4
POSDESCR_TRADESTATION2 -/-
Kugelschale um die Handelsstation im Abstand von 1-3 Units.
Wird der Wing dort erzeugt, ist er immer von der Handelsstation weg ausgerichtet.
 5
POSDESCR_RESEARCHSTATION
POSDESCR_RESEARCH
 -/- Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Zentrum der Forschungsstation entfernt, auf der zur Handelsstation abgewandten Seite. Hat ein System mehrere Forschungsstationen, so wird zufällig eine ausgewählt. 6
POSDESCR_WELCOME -/- Ein Ring mit einem Durchmesser von 0,3 Units, dessen Mittelpunkt 0,1 Units vor dem Hangartor der Handelsstation liegt (knapp 0,2 Units vor dem Systemzentrum). Auf diesem Ring werden die Positionen auf zwei Viertelkreisen erzeugt, die von der Handelsstation aus gesehen rechts oben und links unten liegen (Quadranten I und III). In den Quadranten II und IV des Rings werden keine Positionen erzeugt. 7
POSDESCR_METEROIDS -/- Der Mittelpunkt eines Meteoritenfeldes. Bei mehreren Feldern im System wird immer das erste ausgewählt. 8
POSDESCR_ESCORT -/- Ein senkrecht in der XY-Ebene stehender Torus mit einem Außenradius von 5 und einem Innenradius von 0,8 Units, dessen Zentrum genau zwischen Handelsstation und Hyperraumtor liegt. Auf der Z-Achse ist der Torus 4 Units dick. Es gibt genau 108 verschiedene Positionen in strahlenförmiger Anordnung. 9
POSDESCR_HANGAR | Object | Start von Jägern aus einem Objekt mit Hangar. Von großen Kreuzern können nur Militär- und Hunterwings starten, andere Wingtypen werden nicht erzeugt. | 10
POSDESCR_WINGDISTANCE
Object,
Distance
 In einem gegebenen Abstand neben einem Wing im Weltraum. Die Position wird zufällig bestimmt und der neue Wing auf den anderen ausgerichtet. 11
POSDESCR_EXPLICIT
Position,
FrontDir,
UpDir
 Eine absolute Position mit Ausrichtung. 12
POSDESCR_HYPERSPACE -/- Das System wird durch das Hyperraumtor betreten. Kreuzer und S'kaawings betreten das System ohne das Tor an einer freien Position. 13
POSDESCR_HYPERSPACE_CRUISER -/- Kreuzer und S'kaawings betreten das System ohne das Tor an einer freien Position. Alle anderen Wings kommen aus dem Hyperraumtor. 14
POSDESCR_FIRST_PLANET -/- Position 5 Units über der Oberfläche des Planeten hinter der Handelsstation, auf der zur Handelsstation abgewandten Seite. Es muss sich dabei nicht immer um den nächststehenden Planeten im System handeln. 15
POSDESCR_ACTIONTURRET | Position | Position ist eine Position relativ zu dem ActionTurret. | 16
POSDESCR_CRUISER_ENTRY
Position,
FrontDir,
UpDir
Kann mit allen Wings wie POSDESCR_EXPLICIT verwendet werden. Die Schiffe werden nicht nur einfach an der Position erzeugt, sondern betreten das System mit einem Hyperraumfenster und bremsen dann ab. Einige Befehle, wie z.B. NPlayer.SelectTarget, müssen etwas verzögert werden, damit sie für diesen Wing funktionieren. Das Event WING_ENTER_SYSTEM wird ausgelöst. 17
POSDESCR_ANOMALIE Anomalie
Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit von der Anomalie entfernt, auf der zur Handelsstation abgewandten Seite.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosAnomalie, denen das Handle der Anomalie übergeben werden muss.
 18
POSDESCR_METEORID Meteorid
Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit von dem Zentrum des Meteoritenfelds entfernt, auf der zur Handelsstation abgewandten Seite.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosMeteorid, denen das Handle des Meteoritenfelds übergeben werden muss.
 19
POSDESCR_PLANET Planet
Position 5 Units über der Oberfläche des angegebenen Planeten im System, auf der zur Handelsstation abgewandten Seite.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosPlanet, denen das Handle des Planeten übergeben werden muss.
 20
POSDESCR_BLACKHOLE Blackhole
Kugel mit einem Radius von 2 Units. Der Mittelpunkt liegt 3 Units von dem schwarzen Loch entfernt, auf der der Handelsstation zugewandten Seite.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosBlackhole, denen das Handle des schwarzen Lochs übergeben werden muss.
 21
POSDESCR_HYPERGATE Hypergate
Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit von dem Hyperraumtor entfernt, auf der der Handelsstation zugewandten Seite.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosHypergate, denen optional das Handle des Hyperraumtors übergeben werden kann. Ohne Handle wird die Standardposition des Tors verwendet.
 22
POSDESCR_WELCOME2 -/-
Ein Ring mit einem Durchmesser von 0,3 Units, dessen Mittelpunkt 0,1 Units vor dem Hangartor der Handelsstation liegt (genau 0,2 Units vor dem Systemzentrum). Es wird der komplette Ring für die Positionserzeugung genutzt (alle 4 Quadranten).
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosWelcome.
 23
POSDESCR_ASTEROID2 Asteroid
Kugelschale um einen Asteroiden im Abstand von 1-3 Units.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosAsteroid2, denen das Handle des Asteroiden übergeben werden muss.
 24
POSDESCR_RESEARCH2
POSDESCR_RESEARCHSTATION2
 Station Kugelschale um eine Forschungsstation im Abstand von 1-3 Units. Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosResearchStation2, denen das Handle der Forschungsstation übergeben werden muss. 25
POSDESCR_ANOMALIE2 Anomalie
Kugel mit einem Radius von 2 Units um eine Anomalie.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosAnomalie2, denen das Handle der Anomalie übergeben werden muss.
 26
POSDESCR_METEORID2 Meteorid
Kugelschale um das Zentrum eines Meteoritenfelds im Abstand von 0,5-2 Units.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosMeteorid2, denen das Handle des Meteoritenfelds übergeben werden muss.
 27
POSDESCR_PLANET2 Planet
Kugelschale um einen Planeten im Abstand von 3-6 Units von der Oberfläche.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosPlanet2, denen das Handle des Planeten übergeben werden muss.
 28
POSDESCR_BLACKHOLE2 Blackhole
Kugelschale um ein schwarzes Loch im Abstand von 2-6 Units.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosBlackhole2, denen das Handle des schwarzen Lochs übergeben werden muss.
 29
POSDESCR_HYPERGATE2 Hypergate
Kugelschale um ein Hyperraumtor im Abstand von 0,5-2 Units.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosHypergate2, denen das Handle des Hyperraumtors übergeben werden kann. Ohne Handle wird die Standardposition des Tors verwendet.
 30
POSDESCR_OBJECT
Object,
MaxDistance
Kugelschale um ein beliebiges Objekt im Abstand von 0 bis 'MaxDistance' Units von dessen Hüllkugel.
Nur für die Funktionen MissionLib.GetPos und MissionLib.GetPosObject, denen das Handle des Objekts übergeben werden muss.
Die Entfernung 'MaxDistance' wird in der Funktion MissionLib.GetPos nicht verwendet und ist dort auf 3 Units festgeleget. Dagegen muss sie der Funktion MissionLib.GetPosObject zusätzlich übergeben werden und ist nicht begrenzt.
 31
Rot: Konstante in der MissionLibEx.lua definiert.

Bei mehreren Forschungsstationen oder Asteroiden wird zufällig ausgewählt, wo erzeugt wird. Das sollte sich steuern lassen. Wenn man sonst drei Wellen Jäger vom Asteroiden losschicken möchte, geht das nicht zuverlässig. Einfach einen Parameter Explicit 1) einfügen, bei dem die Nummer/ID des Objekts übergeben werden kann.
1) Eine Angabe im ursprünglichen Modding Guide, die aber leider nicht (mehr) zutrifft. Der Parameter Explicit scheint nicht zu existieren, jedenfalls wird die zufällige Auswahl damit nicht unterbunden. Dafür existieren jetzt einige neue Funktionen in der MissionLibEx.lua im Abschnitt Erzeugungsbereiche, die das als Ersatz für die Funktion NVector.GetPos bewirken (GetPos, GetPosAsteroid und GetPosResearchStation).


Missionen

In Darkstar One vorhandene Missionen und ihre von NScript.Register registrierte Namen.

  • Missionslisten
    • Piraten-Missionen
    • Ascarong-Mission
    • Bar-Missionen (Sidequests)
    • Flak-Missionen
    • Terminal-Missionen
    • Zufällige Missionen, die im All starten
    • Hintergrundaktivitäten im All
    • Story-Missionen
    • Tunnel-Missionen
  • Fortschritt der Story
  • Die globale Missionstabelle (MISSION_TABLE)
  • Die globale Skripttabelle (SCRIPT_TABLE)

Wichtiger Hinweis: Schreibt man selbst Missions-Skripts, sollte man darauf achten, keine der bereits im Spiel vorhandenen Namen zu verwenden. Die internen Missionen starten dann nicht mehr, da die eigenen Skripts einer Mod Vorrang haben. Andererseits kann das natürlich auch genutzt werden, um ein bestehendes Originalskript durch ein verbessertes und/oder erweitertes Skript zu ersetzen.
Die Namen beziehen sich dabei auf die mit "NScript.Register" eingetragenen Namen und nicht auf die Dateinamen, letztere können beliebig gewählt werden. Im Beispiel hier unten darf also keine dritte Null an den zu registrierenden Namen angehängt werden, sonst laufen keine Missionen mit den Piratenverstecken mehr (Geheimdienstwaffen!). Auch hier gilt, dass die Groß- und Kleinschreibung der NScript-Namen berücksichtigt wird. "ALWAYS_001" ist nicht gleich "Always_001", sondern ein ganz anderes Skript.

NScript.Register( {
    Name  = "ALWAYS_00",
    Group = 0,
    Type  = MTYPE_ALWAYS,
    Transitions = {

Alle im Spiel vorhandenen Missionen

Piraten-Missionen
NScript-Name | Cluster | System | Titel
ALWAYS_000 | Fast alle | Gangsysteme: In manchen Systemen mit Meteoritenfeld versteckt sich am Mittelpunkt eine Piratengang. Kommt der Spieler dem Mittelpunkt des Feldes zu nahe, so wird eine Gang und ein Bossgegner erzeugt, die den Spieler angreifen. Besiegt der Spieler die Gang, erhält er außer den üblichen Credits noch eine Geheimdienstwaffe als Belohnung. | n/a
Always_001 | Fast alle | Ein System ist von Piraten besetzt. Diese Systeme sind auf der Karte mit Totenköpfen gekennzeichnet. Wenn der Spieler alle Piraten vernichtet, bekommt er eine dicke Belohnung in Form von Credits und einem Artefakt. Das System hat nach der Befreiung wieder die ursprüngliche Regierungsform. | n/a

Ascarong-Mission
NScript-Name | Cluster | System | Titel | Hinweise
ASCARONG | Hive-AC3 | Ascarong | "Die Ascarong-Gang" | Das System ist mit dem normalen Sprungantrieb nicht erreichbar, da es ca. 10 Lichtjahre vom nächsten System entfernt liegt.

Bar-Missionen (Sidequests)
NScript-Name | Cluster | System | Titel | Hinweise
BAR_000 | Lalande | - | zur freien Verwendung |
BAR_001 | Barnard | Tanee | "Piraten des besetzten Ta-Systems" | Wird nicht im System Tanee angeboten
BAR_002 | Tau Ceti | - | zur freien Verwendung |
BAR_003 | Alpha Centauri | Pani | "Die Tochter des Ratspräsidenten" | Wird nicht in Rebellensystemen angeboten
BAR_004 | Grotok | Naro | "Die Spionagesatelliten der Raptoren" |
BAR_005 | Pertok | Alaniz | "Einem Konzernboss wird gekündigt" |
BAR_006 | Stromok | Risafes | "Schutz für die Keoma IV" | Nur im System Cabracoy erhältlich
BAR_007 | Klatok | Camrracin | "Die Waffenschmuggler" | Nur im System Mostorga erhältlich
BAR_008 | Humok | - | zur freien Verwendung |
BAR_009 | Raptor-Alpha | Zhusomol | "Wirtschftsförderung im Zhusomol-System." | Nur im System Zhusomol erhältlich
BAR_010 | Raptor-Nova | Zareck | "Die Handelsblockade im Zareck-System" |
BAR_011 | Raptor-Gamma | Nakhod | "Geleitschutz für einen Konvoi" | Wird nur in GU-Systemen angeboten
BAR_012 | Raptor-Delta | Koro | "Die Rache des Mynok-Konzerns" | Wird nur in GU-Systemen angeboten
BAR_013 | Raptor-Epsilon | Nizpul | "Religiöse Fanatiker" | Wird in allen Systemen außer Nizpul angeboten
BAR_014 | Sion'nach | Coill'ore | "Belagerung durch religiöse Fanatiker" | Nur im System Kil'ore erhältlich
BAR_015 | Sirius | Yaha | "Unterstützung für einen Kreuzer" | Nur in Patu, Ponniseh, Wenee und Zute erhältlich
BAR_016 | Madra'mor | C'atlodge | "Angriff auf einen Piraten-Kreuzer" | Nur in den Systemen 220 bis 230 erhältlich
BAR_017 | Prea'chan | - | zur freien Verwendung |
BAR_018 | Ross 128 | - | zur freien Verwendung |
BAR_019 | Bear'mor | - | zur freien Verwendung |
BAR_020 | Gab'har | Badic'aul | "Wir sind N.O.M.A.D." | Nur im System Bin'dal erhältlich
BAR_021 | Hive-AC3 | Gaungbwa | "Schutz für die Akshat II" | Nur im System Tinmaung erhältlich
BAR_022 | Hive-F17 | - | zur freien Verwendung |
BAR_023 | Hive-CU7 | Molin | "Die Belagerung des Molin-Systems" | Wird nur in GU-Systemen angeboten
BAR_024 | Hive-B52 | Maleindon | "Zwei verrückte Terraner" | Nur im System Shanzeik erhältlich
BAR_025 | Hive-DC | Pegin | "Flüssiger Sprengstoff" | Wird nicht in Rebellensystemen angeboten
BAR_026 | Hive-ET9 | Kamaing | "Vergeltungsschlag" | Nur in Chondrha und Katpanbok erhältlich
BAR_027 | Hive-G8 | - | zur freien Verwendung |
BAR_028 | Communa | Ormiscaig | "Raumkoller auf der Niatuin" | Nicht in Rebellen- und Anarchiesystemen erhältlich
BAR_029 | Hyma | Clayock | "Die Manndroiden" | Nur in Dalchalm und Dorusduain erhältlich

Bar-Missionen (Sidequests) in der Modifikation "Versteckte Cluster"
NScript-Name | Cluster | System | Titel | Hinweise
BAR_00 | Lalande | Systeme mit Meteoritenfeld | "Schiffbruch" | Erste und sehr einfache Sidequest im Spiel, wird in allen Systemen im Cluster Lalande und nur im Schiffslevel 0 angeboten.
BAR_000 | Lalande | Cloosa | "Gestohlene Androiden" | Schaltet nach Erfüllung den Cluster Tau Ceti frei.
BAR_002 | Tau Ceti | Oma | "Der Transmitter / Die Odyssee" | Mehrteilige Mini-Kampagne für längeren Spielspaß.
BAR_008 | Humok | Fresgar | "Das Selbstmordkommando der Raptoren" | Bombenangriff auf einen Industrieplaneten der Mortok. Ist nur im System Canniozar erhältlich.
BAR_017 | Prea'chan | - | in Vorbereitung |
BAR_018 | Ross 128 | - | in Planung |
BAR_019 | Bear'mor | - | in Vorbereitung |
BAR_022 | Hive-F17 | - | in Vorbereitung |
BAR_027 | Hive-G8 | - | in Vorbereitung |

Flak-Missionen
NScript-Name | Cluster | System | Titel
FLAK_01 | Sion'nach | Kil'ore | "Flakabwehr (1)"
FLAK_02 | Hive-DC | Segin | "Flakabwehr (2)"

Terminal-Missionen
NScript-Name | Cluster | System | Titel
Global_000 | Lalande | Pencah | "Training 1: Grundlagen"
Global_001 | Lalande | Pencah | "Training 2: Fortgeschrittener Kampf"
GLOBAL_002 | Lalande | Pencah | "Training 3: Frachttransport"
GLOBAL_005 | n/a | n/a | "Sabotage" (Einem Konzern einen Denkzettel verpassen: 2 Frachter aus dem Verkehr ziehen)
GLOBAL_006 | n/a | n/a | "Bergung" (Ein Container ist in der Nähe eines Asteroiden verlorengegangen)
GLOBAL_007 | n/a | n/a | "Kopfgeldjagd" (Dringender Auftrag: Finde und vernichte den Piraten)
GLOBAL_009 | n/a | n/a | "Transport" (Waffen in ein Rebellensystem transportieren, Übergabe durch Geheimdienst)
GLOBAL_010 | n/a | n/a | "Kopfgeldjagd" (Treffen der Rebellen)
GLOBAL_011 | n/a | n/a | "Gestohlene Güter" (Container gestohlen, Übergabe am Asteroiden platzen lassen)
GLOBAL_016 | n/a | n/a | "Sabotage" (Einen Rebellensatelliten zerstören)
GLOBAL_017 | n/a | n/a | "Wenn zwei sich streiten, freut sich der Dritte" (Container aus anderem System zurückbringen)
GLOBAL_018 | n/a | n/a | "Konferenz „mit Ohren” " (Geheime Konferenz in Forschungsstation mitschneiden)
GLOBAL_019 | n/a | n/a | "Space-Kalender-Shooting" (Jährlicher Weltallkalender: mindestens 3 Fotos schießen)
GLOBAL_021 | n/a | n/a | "Kopfgeldjäger zum Abschuss freigegeben" (Gewissenlosen Verbrecher zur Strecke bringen)
GLOBAL_022 | n/a | n/a | "Manchmal kommt alles anders als beauftragt" (Kapitän eines Frachters hat dem Konzern geschadet) Frachter beschützen und dann warten, bis er die Station erreicht: Ergibt gleiche Belohnung, obwohl die Mission fehlschlägt.
GLOBAL_023 | n/a | n/a | "Rebellen und Politik" (Information über Aufenthalt einer gesuchten Person) Frachter beschützen und eskortieren, bis er die Station erreicht: Kann doppelte Belohnung geben, obwohl die Mission fehlschlägt.
GLOBAL_024 | n/a | n/a | "Satelliten-Sabotage" (Kommunikationsnetz umprogrammieren)
GLOBAL_025 | n/a | n/a | "Wichtiger Transportauftrag" (Labortechnik zu einer Forschungsstation liefern)
GLOBAL_030 | n/a | n/a | "Ärger mit den Kriminellen" (Lange gesuchter Verbrecher wurde registriert)
GLOBAL_031* | n/a | n/a | "Container muss weg." (Infos über einen Container mit neuartigen Computerchip-Prototypen besorgen) *
GLOBAL_032 | n/a | n/a | "Frachter-Unterstützung" (Überfall auf Konzernfrachter, als Verstärkung dem Frachter helfen)
GLOBAL_034* | n/a | n/a | "Piratenangriff auf Konvoi" (Den Handelskonvoi eines großen Konzerns überfallen) *
GLOBAL_035 | n/a | n/a | "Routinepatrouille?" (Patrouillenflug: Nach versteckten Piraten suchen)
GLOBAL_037 | n/a | n/a | "Gauner ausrauben" (Einer Piratenbande die Beute abnehmen)
GLOBAL_038 | n/a | n/a | "Frachter braucht Unterstützung bei Containersuche." (Container von System A nach B liefern)
GLOBAL_039 | n/a | n/a | "Container vergessen" (Container einem Frachter nachliefern)
GLOBAL_041* | n/a | n/a | "Satellitenstart" (Für Forschungsarbeiten sollen zwei Satelliten ausgesetzt werden) *
GLOBAL_042 | n/a | n/a | "Lieferdienst" (Container in anderes System bringen, Übergabe durch Jäger am Asteroid)
GLOBAL_043 | n/a | n/a | "Berüchtigter Pirat" (Ehemaligen Kopfgeldjäger vernichten)
GLOBAL_044 | n/a | n/a | "Kopfgeldjäger" (Zwei brutale Boss-Hunter killen)
* Nicht vorhanden, wurde von Ascaron nie realisiert.
* Wurde von Ascaron nie realisiert. Ist jetzt in der Mod "Versteckte Cluster" vorhanden.

Zufällige Missionen, die im All starten (teilweise mit Belohnung)
NScript-Name | Cluster | System | Titel
GLOBALSPACE_002 | Barnard | Metharon | Im System Metharon hat ein Militärkreuzer einen Piratenkonvoi gestellt. Im Gegensatz zu den anderen Globalspace-Missionen ist dies eine Storymission, welche beim ersten Sprung nach Metharon und auch nur einmal startet. Der Spieler kann die Herausforderung, die Militärgruppe gegen die Piraten zu unterstützen, freiwillig annehmen oder auch nicht.
GLOBALSPACE_005 | n/a | n/a | Hunter fliegen zu einer Piratengruppe und fragen den Spieler nach Teilnahme.
GLOBALSPACE_009 | n/a | n/a | Hunter wird von Piraten angegriffen und fragt den Spieler, ob er ihm helfen kann.
GLOBALSPACE_013 | n/a | n/a | Der Spieler wird zu einem Rennen aufgefordert, das aber eine Falle von Piraten ist.
GLOBALSPACE_014* | n/a | n/a | Der Spieler soll für einen Piraten einen Minenwaren-Container aus einem Asteroiden klauen. *
GLOBALSPACE_016 | n/a | n/a | Der Spieler soll 2 Huntern bei der Beseitigung eines Minenfelds helfen.
GLOBALSPACE_017 | n/a | n/a | Der Spieler soll die Wachen ablenken, damit ein Pirat einen Container klauen kann.
GLOBALSPACE_019 | n/a | n/a | Auftrag einer Forschungsstation, die Sabotage ihres Satelliten zu verhindern.
GLOBALSPACE_020 | n/a | n/a | Der Spieler bekommt von einem Kurier Credits überwiesen. Die Mafia will die aber wieder haben.
GLOBALSPACE_035 | n/a | n/a | Piraten verfolgen den Spieler und und fordern ihn auf, ihnen seine Fracht zu übergeben. Greifen nach 20 Sekunden an, wenn der Spieler sie nicht fallen lässt.
GLOBALSPACE_036 | n/a | n/a | Militärische Schergen des System-Diktators wollen deine Waren beschlagnahmen.
GLOBALSPACE_037 | n/a | n/a | Gefangenen Eskorte. Ein Hunter wird vom Militär zur Station gebracht. Der Spieler kann ihn befreien, wenn er will.
* Wurde von Ascaron nie realisiert. Ist jetzt in der Mod "Versteckte Cluster" vorhanden.

Hintergrundaktivitäten im All (keine eigentlichen Missionen, auch keine Belohnung)
NScript-Name | Cluster | System | Titel
PASSIVE_001 | n/a | n/a | Schießübungen des Militärs in GU-Systemen.
PASSIV_004 | n/a | n/a | Drei Kommunikationssatelliten werden gewartet.
PASSIVE_005 | n/a | n/a | Der Spieler kann einen Container mit zufälliger Handelsware bergen.
PASSIVE_009 | n/a | n/a | 1-5 Jäger fliegen als Touristen eine ganze Weile gemütlich im System spazieren und verlassen es dann.
PASSIV_014 | n/a | n/a | Zwei terranische Frachterwings fliegen in Richtung Hypergate und springen dahinter in den Hyperraum.
PASSIVE_015 | n/a | n/a | Ein Schiff kommt dem Spieler entgegen, weicht aus und funkt ihn an: "Das war aber knapp."
PASSIVE_016 | n/a | n/a | Ein Frachter verliert seine Container und sammelt sie wieder auf.
PASSIVE_017 | n/a | n/a | Der Spieler kommt an einer Ansammlung von Containern mit Handelswaren vorbei, die von einem Hunterwing bewacht werden. Versucht der Spieler einen Container anzudocken, wird der Hunterwing feindlich.
PASSIVE_018 | n/a | n/a | Zwei Frachter unterhalten sich und springen dann aus dem System.
PASSIVE_019 | n/a | n/a | Der Spieler hört ein Gespräch von 2 Huntern, die im Abfangbereich warten. Wenn der Spieler den Wegpunkt erreicht, hört man folgendes: "Ist das das Schiff das wir suchen?" "Nein, der kommt bestimmt gleich." Nach einiger Zeit springt ein weiterer Hunter in das System und fliegt zu Hunter 1. Anschließend fliegen alle Hunter zur Handelsstation.
PASSIV_020 | n/a | n/a | Zwei Hunter führen am Hypergate eine Wartung durch und scannen dieses.
PASSIV_021 | n/a | n/a | Eine Horde Piraten greift einen Frachterwing an, um die Container zu rauben.
PASSIV_022 | n/a | n/a | ADAC im Weltraum, ein Hunter gibt einem anderen Starthilfe.
PASSIVE_023 | n/a | n/a | Zwei Hunter bestaunen die DarkStar One: "Was ist das für ein Schiff?" "Das sieht ja heiß aus..."
PASSIV_024 | n/a | n/a | Zwei Militärwings mit je 8 Jägern patrouillieren im System.
PASSIV_025 | n/a | n/a | Ein Frachter unterhält sich mit seiner Eskorte über Thuldrohnen.
PASSIV_028 | n/a | n/a | Drei Piratenwings kämpfen mit einem Hunterwing.

Story-Missionen
NScript-Name | Cluster | System | Titel
STORY_000 |  |  | evtl. frei
STORY_001 |  |  | evtl. frei
STORY_002 | Lalande | Hu | "Die verschollenen Artefakte"
STORY_003 | Alpha Centauri | Yankwalla | "Treffen mit Delano im Sol-System"
STORY_004 | Alpha Centauri | Shoma | "Das Ende der Aponi-Gang"
STORY_005 | Grotok | Mandedulce | "Angriff der Drohnen abwehren (1.x)"
STORY_006 | Pertok | Rulote | "Auftrag für Ramirez"
STORY_007 | Stromok | Cabracoy, Alsavia, Lorbeisua, Pinzar | "Eonas Rettung"
STORY_008 | Klatok | Mostorga | "Anflug auf Kabros Versteck"
STORY_009 | Klatok | Mostorga | "Showdown mit Kabro"
STORY_010 | Raptor-Nova | Kosrod | "Mitris Schmuggelmission"
STORY_011 | Raptor-Gamma | Sakaterin, Twerkano, Schel, Bogozan, Chernomen | "Die Wolodja-Forschungsstation"
STORY_012 | Raptor-Gamma | Goronezh | "Nicolais Rettung"
STORY_013 | Raptor-Epsilon | Permnaja | "Vertrauensbeweis für die Raptoren"
STORY_014 | Sion'nach | Kil'ore | "Das Gastgeschenk"
STORY_015 | Madra'mor | Ach'air | "Beschütze Hornblower"
STORY_016 | Madra'mor | Lyn'chat | "Mit Hornblower zu den Arrack"
STORY_017 | Hive-AC3 | Tinmaung | "Angriff der Drohnen abwehren (2)" & "Treffen mit Jiju"
STORY_018 | Hive-AC3 | Tinmaung, Sinkwe, Gaungbwa | "Mission für Jiju" (Satellitenmission)
STORY_019 | Hive-AC3 | Tinmaung, Haiken | "Die Kristalllieferung"
STORY_020A | Hive-B52 | Tinmaung, Kajudeng | "Die Suche nach den Thul (1.0 - 1.1)"
STORY_020B | Hive-B52 | Kajudeng | "Die Suche nach den Thul (1.2)"
STORY_021 | Gab'har | Tinmaung, Achand'unie, Inch'ore, Sc'atwell | "Der Tarnfeldscanner der Arrack (1.1 - 3.2)"
STORY_022 | Hive-B52 | Kajudeng | "Angriff auf den getarnten Thul-Kreuzer"
STORY_023 | Hive-B52 | Metojang | "Die Suche nach Jack geht weiter"
STORY_024 | Hive-DC | Segin | "Angriff der Drohnen abwehren (3)"
STORY_025 | Hive-DC | Segin, Yama, Beinn | "Dr.Zarkovs Einkaufsliste"
STORY_026 | Gab'har | Tom'atin | "Angriff der Drohnen abwehren (4.x)"
STORY_027 | Gab'har | Sona'chan, Tar'vie | "Finde Jowson"
STORY_028 | Gab'har | Bad'aul, Bin'dal | "Jowson als Vermittler"
STORY_029 | Communa | Clachtoll | "Beschütze den ThulKreuzer"
STORY_030 | Raptor-Delta | Archangelsk, Koro | "Der Schlüssel zum Skaa-System"
STORY_031A | Raptor-Delta | Permakin | "Das Mutterschiff der Skaa (1)"
STORY_031B | Raptor-Delta | Permakin | "Das Mutterschiff der Skaa (2)"
STORY_031C | Raptor-Delta | Permakin | "Das Mutterschiff der Skaa (3)"
STORY_031D | Raptor-Delta | Permakin | "Das Mutterschiff der Skaa (4)"
STORY_032 | Raptor-Delta | Permakin | "Vernichtung der Skaa"

Tunnel-Missionen
NScript-Name | Cluster | System | Titel
TUNNEL_000 | Klatok | Mostorga | "Eonas Befreiung" (die Canyon-Mission)
TUNNEL_001 | Raptor-Delta | Toggrad | "Bronis Waffenfabrik"
TUNNEL_002 | Raptor-Delta | Permakin | "Zerstörung des S'kaa-Mutterschiffs" (im S'kaa-Kreuzer)

Fortschritt der Story

Diese Tabelle zeigt den Fortschritt der Story anhand des aktuellen Kapitels und Unterkapitels.
Die von NStory.Progress gelieferte Tabelle { Chapter, Subchapter } ist hier als float-Wert unter 'Kapitel' dargestellt.
Kapitel | Beschreibung
0.0 | Einführungsvideo und Unterhaltung mit Robert
0.06 | In der Bar "Ein neues Schiff"
0.08 | START des Spiels nach Bestätigung des ersten Story-Dialogs
0.09 | Pencah, erster Start von der Station, "Prolog"
0.13 | Hu, "Die verschollenen Artefakte" abgeschlossen
0.16 | Hu, Abflug in ein anderes System
0.18 | Pencah, Info von Robert, wer für den Tod von Kayrons Vater verantwortlich ist, 3 Lj-Antrieb erhältlich
0.21 | Pencah, Info Storymission bestätigt
0.22 | Pencah, nach sofortigem Kauf des Feldantriebs
0.24 | Pencah, Info Storymission bestätigt, Nachricht von Robert
0.27 | Pencah, nach Start von Station und Erhalt der Systemschlüssel für Metharon und Anomi von Robert
1.0 | Metharon/Barnard, nach Abwehr des Piratenangriffs auf Kreuzer
1.02 | Metharon, nach Danksagung des Kreuzerkommandanten
1.03 | Anomi, Kontakt mit Eona
1.05 | Anomi, Info Storymission bestätigt
1.06 | Anomi, erster Abflug mit Eona
1.08 | Anomi, neue Nachricht von Eona
1.10 | Anomi, Schlüssel für Yankwalla/Alpha Centauri von Eona erhalten
1.15 | Sol/Alpha Centauri, erste Landung
1.23 | Shoma, Verlassen des Systems nach Mission mit Delano, 4 Lj-Antrieb erhältlich
1.24 | Alegenla/Grotok, Ankunft im System
1.25 | Mandedulce, Kontakt mit Forschungsstation
1.26 | Mandedulce, Drohnenangriff auf die Forschungsstation
1.31 | Mandedulce, nach Gespräch mit dem Stationsdirektor
1.35 | Mandedulce, Info Storymission "Zarkovs Station" bestätigt
1.38 | Mandedulce, Start von Forschungsstation, Systemschlüssel Arotorracin/Pertok von Eona erhalten
1.39 | Biarnar, nach der Entführung Eonas
1.42 | Biarnar, Info Storymission "Auftrag für Ramirez" bestätigt
1.46 | Cabracoy, nach Treffen mit Ramirez, ersten von 3 Aufträgen von Ramirez erhalten
1.47 | Cabracoy, Annahme der Schmuggelmission nach Alsavia
1.48 | Lorbeisua-Pinzar, "Eonas Rettung (1.1 / 2.1 / 3.1 / 4.1)"
1.51 | Pinzar, Bombenfrachter-Mission erfüllt, Ende "Eonas Rettung (4.2)"
1.52 | Cabracoy, nach Treffen mit Ramirez in der Bar
1.57 | Cabracoy, Annahme der Storymission nach Mostorga, 5 Lj-Antrieb erhältlich
1.59 | Mostorga, "Anflug auf Kabros Versteck"
1.61 | Mostorga, Startposition im Canyon
1.62 | Mostorga, zurück im All, "Showdown mit Kabro"
1.65 | Mostorga, Eona ist wieder an Bord
1.66 | Mostorga, Info Storymission bestätigt
2.0 | Mostorga, Info Storymission "Hilfe von Ramirez" bestätigt, 6 Lj-Antrieb, Schlüssel Kosrod erhalten
2.01 | Ankunft Zhusomol, "Mitris Schmuggelmission" Kosrod
2.05 | Ankunft Zareck/Raptor-Nova, "Die Wolodja-Forschungsstation" Sakaterin
2.06 | Kosrod, Mitris Schmuggelmission erfüllt, auf der Forschungsstation
2.08 | Kosrod, Forschungsstation, Info Storymission "Zarkov wurde von Jack entführt" bestätigt
2.12 | Kosrod, Abflug von der Forschungsstation, Liste über 4 Forschungsstationen und Schlüssel Yarosny + Sakaterin erhalten
2.15 | Nach Abflug aus Kosrod
2.16 | Sakaterin, Ankunft
2.21 | Sakaterin, nach Ablieferung des Plasma-Resonanz-Kollektors, Schlüssel Goronezh erhalten
2.23 | Goronezh, nach "Nicolais Rettung" und Landung auf der Toscha Forschungsstation
2.27 | Goronezh, Info Storymission "Die 3. Forschungsstation", Schlüssel Petrokau/Raptor-Epsilon erhalten
2.29 | Goronezh, Abflug aus dem System
2.38 | Toggrad, Bronis Waffenfabrik ist zerstört, 7 Lj-Antrieb erhältlich
2.43 | Kil'ore, "Das Gastgeschenk" beginnt
2.50 | Kil'ore, "Das Gastgeschenk" ist abgeschlossen
2.52 | Abflug von Kil'ore nach der ersten Flakmission
2.54 | Ankunft Ad'vie/Madra'mor
3.0 | Ach'air/Madra'mor, "Beschütze Hornblower" erfolgreich abgeschlossen
3.02 | Ankunft Lyn'chat/Madra'mor, "Mit Hornblower zu den Arrack (1.1)"
3.04 | Ankunft Tinmaung/Hive-AC3, Drohnenangriff auf den Asteroiden Mahendra
3.07 | Tinmaung, Drohnen abgewehrt, Landung auf Asteroid Mahendra
3.09 | Nach Missionsannahme "Mission für Jiju (1.1)" und Öffnen der NavKarte
3.11 | Rückkehr nach Tinmaung, Start der Mission "Die Kristalllieferung"
3.15 | Rückkehr von Haiken nach Tinmaung, Ende der "Kristalllieferung", Start "Die Suche nach den Thul (1.1)"
3.17 | Ankunft Kajudeng, Start "Die Suche nach den Thul (1.2)"
3.18 | Tinmaung, Landung auf Jijus Asteroiden nach Hornblowers Tod
3.20 | Auftragsannahme "Der Tarnfeldscanner"
3.23 | Sc'atwell, Tarnfeldscanner aufgenommen
3.27 | Tinmaung, Auftrag "Der getarnte Thulkreuzer" erhalten
3.29 | Kajudeng, der Thul-Kreuzer ist zerstört
3.34 | E-Mail-Nachricht von Robert erhalten
3.35 | Verbindungsaufnahme mit Robert
4.0 | Gespräch mit Robert beendet, Schlüssel Metojang erhalten
4.01 | Abflug aus Hangar nach Gespräch
4.03 | Unterhaltung mit Eona über Schmugglerstation, Metojang als Missionsziel markiert
4.07 | Metojang, "Die Suche nach Jack geht weiter (2)", nach Drohnenabwehr und Gespräch mit Jack
4.09 | Ankunft Kandaya/Hive-CU7
4.10 | Abflug von Kandaya
4.12 | Segin, Beginn der zweiten Flak-Mission
4.13 | Segin, Ende der zweiten Flak-Mission
4.15 | Segin, Annahme der Mission "Dr. Zarkovs Einkaufsliste" in der Forschungsstation
4.17 | Segin, Abflug von der Forschungsstation, "Dr. Zarkovs Einkaufsliste (1)" automatisch gespeichert
4.19 | Segin, Rückkehr von Beinn und Abgabe der Quamstrahl-Isotope
4.23 | Segin, nach Gespräch mit Zarkov und seiner Bitte, den Geologen Jow'hal aufzusuchen
4.25 | Ankunft im Cluster Gab'har für das Treffen mit Jow'hal
4.26 | Tom'atin, nach Gespräch mit Jow'hal auf dem Asteroid
4.27 | Tom'atin, Annahme der Mission "Die Suche nach Jow'son"
4.31 | Tom'atin, nach Start vom Asteroid und Erhalt des Systemschlüssels für Sona'chan
4.34 | Ankunft in Bad'aul mit Jow'son, Kopfgeldjägerangriff
4.39 | Bin'dal, Landung auf Station oder Kreuzer
4.42 | Segin, Systemschlüssel Binga/Hive-ET9 von Zarkov erhalten
4.46 | Ankunft Binga, Systemschlüssel Pitcalnie/Communa erhalten, 9Lj-Antrieb erhältlich
4.47 | Nach Sprung ins nächste System
4.51 | Clachtoll, nach Drohnenabwehr und erster Landung auf der Eoghane, vor Missionsannahme
4.53 | Clachtoll, Eoghane, nach Missionsannahme "Ein Schlüssel für das S'kaa-System"
4.57 | Clachtoll, Start vom Kreuzer, neues Missionsziel Archangelsk, Schlüssel Dalchalm/Hyma erhalten
5.0 | Koro, Schlüssel zum Permakin-System durch Kreuzerwrack-Scan erhalten
5.01 | Koro, nach dem Start von der Handelsstation, falls gelandet
5.03 | Permakin, Angriff auf das Mutterschiff nach Rückkehr vom Waldplaneten
5.04 | Permakin, Kreuzer Eoghane und Freunde treffen zur Unterstützung ein
5.06 | Permakin, E-Mail-Infos von Robert vom Mutterschiff aus, Scan abgeschlossen, Drohnen ziehen sich zurück
5.09 | Permakin, nach Landung auf der Eoghane
5.11 | Permakin, Eoghane, nach Annahme der Mission "Die Zerstörung des S'kaa-Mutterschiffs"
5.12 | Permakin, Startposition im S'kaa-Mutterschiff
5.15 | Permakin, das Mutterschiff ist zerstört, wieder im All nach Abschiedsvideo, Eonas Stimme im Computer
6.0 | Abenteuer beendet.

Die globale Variable MISSION_TABLE

Es gibt eine bisher undokumentierte Möglichkeit, Variablen in der V-Tabelle von anderen gerade aktiven Missionen abzufragen und eventuell auch zu verändern oder hinzuzufügen. Dies kann über die globale Variable MISSION_TABLE bewerkstelligt werden, welche die V-Tabellen aller aktuell laufenden Missionsskripts enthält. Allerdings sollte dies mit größter Vorsicht und nur in Ausnahmefällen gemacht werden, da eine einzige Änderung in diesen Tabellen zu unvorhersehbaren Zuständen führen kann. Auch muss man sehr darauf achten, wenn man die Namen von V-Variablen in einem Skript ändert, ob sie von anderen Skripts über die MISSION_TABLE abgefragt werden. In diesem Fall müssen sie in den betreffenden Skripts natürlich ebenfalls angepasst werden. Es ist eine gute Idee, solche Fälle in den Skripts ausreichend mit Querverweisen zu den anderen betroffenen Skripts zu dokumentieren. Damit spart man sich später eine unnötige Fehlersuche, wenn mal etwas nicht klappt, obwohl alles scheinbar vollkommen korrekt erscheint (z.B. die Syntax).

Schematischer Aufbau der Tabelle, die fünf ersten groß geschriebenen Einträge der V-Tabelle sind immer von Anfang an da, weitere können dynamisch nach dem Missionsstart vom Skript erzeugt werden:

MISSION_TABLE = {			-- table (Tabelle der aktiven Missionen)
    [Handle_1] = {			-- table (V-Tabelle, Index ist das Handle der Mission)
        SCRIPT  = <Skriptname>,		-- string
        STATE   = <Missionsstatus>,	-- enum (Zustand der Mission)
        ID      = <Handle>,		-- CMissionHandle (idR der gleiche Wert wie der Index)
        OWNER   = 196607,		-- number
        VERSION = 103,			-- number
        Step    = <n>,			-- float (Fortschritt der Mission)
        Variablen der Mission		-- Alle im Skript definierten V-Variablen (dynamisch)
    },
    [Handle_2] = { V-Tabelle der nächsten aktiven Mission },
    ͻ
    [Handle_n] = { V-Tabelle der letzten aktiven Mission }
}

Im folgenden Beispiel wird vom aktuellen Skript geprüft, ob die Mission mit den Piratengangs aktiv ist und der Geheimdienstwaffencontainer durch Abschuss des Piratenbosses schon im All schwebt. Das Containerhandle wird dann ins aktuelle Skript übernommen:

-- Handle vom Geheimdienstwaffencontainer holen:
for handle, vtable in MISSION_TABLE do
    if vtable.SCRIPT == "ALWAYS_000" then
        if vtable.Container then
            V.SecretWeapon = vtable.Container
        end
        break
    end
end

Die globale Variable SCRIPT_TABLE

Eine weitere bisher undokumentierte globale Variable ist die Hash-Tabelle SCRIPT_TABLE, welche alle registrierten Skripts und deren Definitionen enthält. Die Reihenfolge der eingetragenen Skripts ist undefiniert.
Wichtig: Auf diese Tabelle darf nur lesend zugegriffen werden und man darf auf gar keinen Fall irgendwelche Änderungen darin vornehmen!

Schematischer Aufbau der Tabelle:

SCRIPT_TABLE = {		-- table (Tabelle aller registrierten Skripts)
    ["Skriptname_1"] = {	-- table (Bezeichner ist der in NScript.Register eingetragene Name)
        FORMAT	= "STATES",	-- string
        GROUP	= 0,		-- number (immer 0)
        TYPE	= <Missionstyp>,-- enum (z.B. MTYPE_BAR)
        STATES	= {		-- table[n] (Tabelle mit den Transitions)
            {			-- table[2..4] (Transition 1)
                minStep,	-- number | float | nil: Zustandsbereich, in dem sich V.Step befinden muss,
                maxStep,	-- number | float | nil: … damit die Transition ausgeführt wird.
                "Init",		-- Event-Filter
                function	-- Funktionsblock
            },
            {			-- table[2..4] (Transition 2)
                minStep,	-- wenn nil, wird die Transition unabhängig vom Wert in V.Step ausgeführt,
                maxStep,	-- … immer wenn das Event triggert.
                "Create",	-- Event-Filter
                function	-- Funktionsblock
            },
            { 1.0, nil, "Failed", function( V, Data ) <Block> end },	-- (Beispiel Transition 3)
            { 1.0, 1.0, "System", function( V, Data ) <Block> end },	-- (Beispiel Transition 4)
            ͻ
            { letzte Transition n }
        },
        NAME	= <Skriptname>,	-- string (idR der gleiche Eintrag wie beim Index)
        M_COUNT	= 1,		-- number (immer 1?)
        T_COUNT	= 0,		-- number (immer 0?)
        I_COUNT	= 0|1		-- number, 0 = inaktiv, 1 = angeboten, aktiv oder für immer beendet
    },
    ["Skriptname_2"] = { Tabelleneinträge wie oben },
    ["Skriptname_3"] = { Tabelleneinträge wie oben },
    ͻ
    ["Skriptname_n"] = { Tabelleneinträge wie oben }
}

Im folgenden Beispiel erstellen wir uns eine einfache Liste mit den Skriptnamen aller im Spiel vorhandenen Terminalmissionen:

local index = 0
V.TerminalMissions = {}
for scriptname, table in SCRIPT_TABLE do
    if table.TYPE == MTYPE_TERMINAL or table.TYPE == MTYPE_USER_TERMINAL then
        index = index + 1
        V.TerminalMissions[index] = scriptname
        -- oder so, ist das Gleiche, nur etwas langsamer:
        -- V.TerminalMissions[index] = table.NAME
    end
end
V.MissionCount = index


Handelswaren

Alle von der Wirtschaftssimulation verwendeten Handelswaren
Konstante | Kommentar | Wert
GOODS_COALHYDRATES | Kohlenhydrate | 0
GOODS_PROTEINS | Proteine | 1
GOODS_LIFEFORMS | Lebensformen | 2
GOODS_VEGFIBERS | Pflanzenfasern | 3
GOODS_METALS | Metalle | 4
GOODS_PRECMETALS | Edelmetalle | 5
GOODS_CRYSTALS | Kristalle | 6
GOODS_ALLOYS | Legierungen | 7
GOODS_MACHINERY | Maschinen | 8
GOODS_ELECTRONICS | Elekronik | 9
GOODS_COMPUTERS | Computer | 10
GOODS_SHIPTECHS | Schiffstechnik | 11
GOODS_MEDICINE | Medizin | 12
GOODS_CHEMICALS | Chemikalien | 13
GOODS_LIQUOR | Spirituosen | 14
GOODS_FERTILIZER | Dünger | 15
GOODS_ENERGYCELLS | Energiezellen | 16
GOODS_FUELRODS | Brennstäbe | 17
GOODS_ISOTOPES | Isotope | 18
GOODS_SUPERCONDUCTORS | Supraleiter | 19
GOODS_VIDEOGAMES | Videospiele | 20
GOODS_LUXURIES | Luxusartikel | 21
GOODS_ANDROIDS | Androiden | 22
GOODS_DRUGS | Drogen | 23
GOODS_NONE | Keine Waren | 24
GOODS_MISSIONOBJECT | Missionswaren | 25
GOODS_WEAPON | Geheimdienstwaffe | 26
Rot: Konstante in der MissionLibEx.lua definiert.


Kameras

Filter der Funktion NCamera.AddFilter für die Kameras
Konstante | Kommentar | Wert
CAMERA_FILTER_BLACK | Bild bleibt eine halbe Sekunde schwarz | 1
CAMERA_FILTER_WHITE_IN | Blendet von weiß ein | 2
CAMERA_FILTER_BLACK_IN | Blendet von schwarz ein | 3
CAMERA_FILTER_SHAKE | Kamera wackelt | 4
CAMERA_FILTER_BLUR | Weichzeichner bzw. Unschärfe | 5
-/- |  | 6
CAMERA_FILTER_WHITE_OUT | Blendet nach weiß aus | 7
CAMERA_FILTER_BLACK_OUT | Blendet nach schwarz aus | 8
CAMERA_FILTER_FLASH | Blendet zuerst nach weiß ein und geht dann wieder auf die normalen Werte zurück | 9
CAMERA_FILTER_FOV | Ändert kontinuierlich den Kamerawinkel | 10


Kommunikation

Ereignisse im Zusammenhang mit Standarddialogen
Konstante | Kommentar | Wert
COMMTYPE_LANDING_FORBIDDEN | Landung wurde verboten | 0
COMMTYPE_LANDING_DENIED | Landeerlaubnis wurde verweigert | 1
COMMTYPE_LANDING_GRANTED | Landeerlaubnis wurde erteilt | 2
COMMTYPE_LANDING_CLEARED | Landung wurde freigegeben | 3
COMMTYPE_DLG_START | Dialog wurde gestartet | 4
COMMTYPE_DLG_END | Dialog wurde beendet | 5


Kreuzer

Kreuzer und Superfrachter

Kreuzerverteilung beim Spielstart (Konzept.ini), ändert sich im Laufe des Spiels
Index | Kreuzername | Größe | SystemId | System | Cluster
0 | Nahimana | groß | 1 | Cloosa | Lalande
1 | Keoma | klein | 16 | Metharon | Barnard
2 | Tallahassee | groß | 25 | Zuoria | Tau Ceti
3 | Topeka | klein | 38 | Ete | Alpha Centauri
4 | Wakanda | groß | 37 | Yankton | Alpha Centauri
5 | Durango | klein | 50 | Lucia | Grotok
6 | Heroica | groß | 51 | Alegenla | Grotok
7 | Bermudo | klein | 63 | Arotorracin | Pertok
8 | Mauregato | groß | 70 | Arber | Stromok
9 | Possidonio | klein | 71 | Cabracoy | Stromok
10 | Nuevo Grandes | groß | 100 | Siedillo | Klatok
11 | Entronque | klein | 101 | Cuendo | Klatok
12 | Hidalgo | groß | 120 | Canniozar | Humok
13 | Michoacan | klein | 121 | Antetaber | Humok
14 | Maximuschka | groß | 128 | Zhusomol | Raptor Alpha
15 | Gennadi | klein | 140 | Zareck | Raptor Nova
16 | Petruscha | groß | 141 | Nizbin | Raptor Nova
17 | Wanjuscha | klein | 150 | Malopul | Raptor Gamma
18 | Kolenka | groß | 151 | Suzga | Raptor Gamma
19 | Lucknov | klein | 153 | Kostrono | Raptor Gamma
20 | Krasnogul | groß | 174 | Chanschat | Raptor Delta
21 | Archangelsk | klein | 180 | Kaschi | Raptor Epsilon
22 | Turuchansk | groß | 181 | Penol | Raptor Epsilon
23 | Clash'ore | klein | 200 | Abria'chan | Sion'nach
24 | Kinloch'ore | groß | 201 | Ann'at | Sion'nach
25 | Macawicha | klein | 207 | Ozurim | Sirius
26 | Karmigaho | groß | 208 | Wama | Sirius
27 | Gahojacy | klein | 212 | Ponniseh | Sirius
28 | Tuwazulu | groß | 213 | Wallawalla | Sirius
29 | Lochcar'ron | klein | 220 | Lochcar'ron | Madra'mor
30 | Ormsaig'nie | groß | 221 | Am'atn'atua | Madra'mor
31 | Sliga'chan | klein | 223 | Ad'vie | Madra'mor
32 | Lathe'ron | groß | 225 | Sliga'chan | Madra'mor
33 | Skullo'ron | klein | 250 | Garb'at | Prea'chan
34 | Drum'unie | groß | 251 | Dalmiga'vie | Prea'chan
35 | Bo'athvic | klein | 252 | Sana'chan | Prea'chan
36 | MS Steinhammer | groß | 258 | Shovis | Ross 128
37 | MS Stahlwerk | klein | 259 | Yate | Ross 128
38 | MS Eisenfaust | groß | 260 | Penchi | Ross 128
39 | MS Steinfaust | klein | 261 | Eosa | Ross 128
40 | Bad'aul | groß | 265 | Ardul'lie | Bear'mor
41 | Leirin'vie | klein | 270 | Lairg'uie | Gab'har
42 | Linside'ore | groß | 271 | Tar'vie | Gab'har
43 | Tour'oreton | klein | 272 | Sona'chan | Gab'har
44 | Lakshman-fu | groß | 300 | Hulaung | Hive-AC3
45 | Narendra-ko | klein | 301 | Mingin | Hive-AC3
46 | Manindra-ne | groß | 302 | Tamaung | Hive-AC3
47 | Yogendra-ne | klein | 313 | Uyin | Hive-F17
48 | Matsendra-ai | groß | 314 | Lakai | Hive-F17
49 | Sudhakar-ne | klein | 315 | Yagyat | Hive-F17
50 | Prakash-ai | groß | 330 | Ringhku | Hive-CU7
51 | Vidyadhar-ko | klein | 331 | Molin | Hive-CU7
52 | Jinendra-ne | groß | 340 | Ngakin | Hive-B52
53 | Akshat-ne | klein | 350 | Segin | Hive-DC
54 | Makarand-ai | groß | 351 | Sibingwe | Hive-DC
55 | Hemendra-ko | klein | 354 | Mepok | Hive-DC
56 | Devendra-ne | groß | 364 | Chondrha | Hive-ET9
57 | Tarak-fu | klein | 370 | Daingnat * | Hive-G8
58 | Kaushik-ko | groß | 371 | Lethagon | Hive-G8
59 | Galadriel | klein | 388 | Pitcalnie | Communa
60 | Eoghane | groß | 383 | Ramasaig | Communa
61 | Aonghusa | klein | 384 | Faebait | Communa
62 | Conchubhar | groß | 398 | Clayock | Hyma
* Die SystemId ist in der Original-Datei "inifiles\Infos\konzept.ini" fälschlicherweise als 270 eingetragen.

Es gibt 3 verschiedene Superfrachter im Spiel:
Volk | Größe | Container
Terraner | 9000t | 45 á 200t (15 längs * 3 um die Achse)
Arrack | 8400t | 42 á 200t (5 längs * 8 um die Achse + 2 vorne)
Raptor | 8000t | 40 á 200t (8 längs * 4 um die Achse)

Die standardmäßig in der StarShip.ini definierten Superfrachter sind allerdings welche mit Geheimdienstwaffen-Containern:
Volk | Größe | Container
Terraner | CONTAINER_SPECIAL | 45 á 0-100 Geheimdienstwaffen (15 * 3)
Arrack | CONTAINER_SPECIAL | 42 á 0-100 Geheimdienstwaffen (5 * 8 + 2)
Raptor | CONTAINER_SPECIAL | 40 á 0-100 Geheimdienstwaffen (8 * 4)

Um nun auch Frachter mit normalen Containern mittels "NWing.Define" in den Skripts erzeugen zu können, habe ich die StarShip.ini entsprechend ergänzt. Dabei wurden auch gleich Definitionen für Superfrachter zum Transport der kleineren Container hinzugefügt:
Volk | Größe | Container
Terraner | 4500t | 45 á 100t (15 * 3)
Arrack | 4200t | 42 á 100t (5 * 8 + 2)
Raptor | 4000t | 40 á 100t (8 * 4)
Terraner | 2250t | 45 á 50t (15 * 3)
Arrack | 2100t | 42 á 50t (5 * 8 + 2)
Raptor | 2000t | 40 á 50t (8 * 4)

Somit stehen jetzt insgesamt 12 verschiedene Superfrachter in der StarShip.ini zur Verfügung.


Missionstypen

Skript Missionstypen (CMissionHandle) für NScript.Register
Konstante | Kommentar | Wert
MTYPE_ALWAYS | Mission wird immer ausgeführt | 1
MTYPE_SPACE | Mission startet im Weltraum, das Programm bestimmt den Startzeitpunkt per Zufall | 2
MTYPE_TERMINAL | Mission wird im Terminal angeboten. Die Startbedingungen werden bei jeder Landung auf einer Handelsstation erneut geprüft und der Auftrag bei Nichterfüllung dort auch nicht angeboten. Nach der Annahme eines Auftrags kann kein zweiter mehr angenommen werden, auch kein Geleitschutzauftrag. | 3
MTYPE_BAR | Mission wird in der Bar angeboten (Sidequest oder Kontaktperson) | 4
MTYPE_CHAPTER | Unterkapitel von Missionen | 5
MTYPE_TUNNEL | Mission startet im Canyon, im S'kaatunnel oder der Waffenfabrik | 6
MTYPE_STORY | Story-Mission | 7
MTYPE_STORY_TERMINAL | Story-Mission, die im Terminal angeboten wird | 8
MTYPE_STORY_CHAPTER | Unterkapitel von Story-Missionen | 9
MTYPE_STORY_BAR | Story-Mission, die in der Bar angeboten wird (Kontaktperson) | 10
MTYPE_MENU | Kamera für das Hauptmenü, Planeten und Aktionen (Video) | 11
MTYPE_USER_TERMINAL
Wie MTYPE_TERMINAL, mit höherer Priorität. Im Gegensatz zu MTYPE_TERMINAL kann nach der Annahme des Auftrags noch ein weiterer angenommen werden.
Achtung: Nach der Erzeugung eines Auftrags werden die Startbedingungen bei der nächsten Landung auf einer Handelsstation nicht nochmal im "Init"-Event geprüft und in "Create" neu erzeugt. Somit wird der Auftrag selbst dann wieder angeboten, wenn die Bedingungen in einem anderen System nicht erfüllt werden. Er wartet also ständig auf seine Annahme und wird bis dahin nicht wieder zerstört und neu erzeugt. Dies führt oft zum Absturz, wenn man versucht, den Auftrag dort auszuführen, wo die Startbedingungen nicht erfüllt sind!
 12
MTYPE_USER_SPACE | Wie MTYPE_SPACE, mit höherer Priorität. | 13
MTYPE_GLOBAL | dokumentiert, ist jedoch undefiniert | nil
MTYPE_VIDEO | dokumentiert, ist jedoch undefiniert | nil
MTYPE_NONE | Keine Mission | nil

Skript Missionsstatus für NMission.GetState, NMission.SetState und die Variable V.STATE
Konstante | Kommentar | Wert
MSTATE_NONE MISSION_NONE | Mission ist nicht vorhanden | 0
MSTATE_OFFERING MISSION_OFFERING | Mission steht im Terminal zur Verfügung | 1
MSTATE_RUNNING MISSION_RUNNING | Mission ist aktiv | 2
MSTATE_ACHIEVED MISSION_ACHIEVED | Mission wurde erfolgreich abgeschlossen | 3
MSTATE_FAILED MISSION_FAILED | Mission ist fehlgeschlagen | 4
MSTATE_ENDED MISSION_ENDED | Mission ist zu Ende | 5
MSTATE_IDLE | Mission wurde beendet und erhält keine Events mehr | 6

Subtypen von Missionen, bestimmt das Bild von Aufträgen im Terminal
Konstante | Kommentar | Wert
SUBTYPE_TRANSPORT | Transportauftrag | 1
SUBTYPE_HEADHUNT | Kopfgeldjagd | 2
SUBTYPE_PIRATES | Piratenjagd | 3
SUBTYPE_SABOTAGE | Sabotageauftrag (ausführen oder verhindern) | 4
SUBTYPE_PROTECT | Missionsziel beschützen | 5
SUBTYPE_RESCUE | Bergungs- oder Rettungsauftrag | 6
SUBTYPE_POLITICAL | Politischer Auftrag | 7

Grafiken im Terminal
SUBTYPE_TRANSPORT | SUBTYPE_HEADHUNT | SUBTYPE_PIRATES
Transportauftrag | Kopfgeldjagd | Piratenjagd
SUBTYPE_SABOTAGE | SUBTYPE_PROTECT | SUBTYPE_RESCUE
Sabotageauftrag | Missionsziel beschützen | Bergung / Rettung
SUBTYPE_POLITICAL |  |
Politischer Auftrag |  |


Munitionssorten

Die im Spiel verwendeten Munitionsarten
Konstante | Kommentar | Wert
AMMO_TYPE_LASER | Standardwaffe der Menschen | 0
AMMO_TYPE_RAILGUN | Standardwaffe der Mortok | 1
AMMO_TYPE_PHASER | Standardwaffe der Raptor | 2
AMMO_TYPE_SONIC | Standardwaffe der Oc'to | 3
AMMO_TYPE_ENERGY | Standardwaffe der Arrack | 4
AMMO_TYPE_PHOTON | Standardwaffe der Thul | 5
AMMO_TYPE_SKAADRILL | Standardwaffe der S'kaa | 6
AMMO_TYPE_SWARM | Schwarm-Rakete | 7
AMMO_TYPE_HELLFIRE | Hellfire-Rakete | 8
AMMO_TYPE_BIGBANG | Raumtorpedo | 9
AMMO_TYPE_RAPTOR * | Raptorwaffe | 10
AMMO_TYPE_MINE * | Mine | 11
AMMO_TYPE_SHOOTER * | Selbstfeuernde Mine | 12
AMMO_TYPE_RAPTORBOSS * | Raptor Boss, ein ganzes Bündel Schwarmraketen | 13
AMMO_TYPE_TURRETMISSILE | Geschützturm als Raketenlafette | 14
AMMO_TYPE_MINE_BRONIS | Selbstfeuernde Mine in der Waffenfabrik | 15
AMMO_TYPE_LIGHT | Explosionseffekt im Heck von Raptorschiffen | 16
AMMO_TYPE_KIHOMING | Hellfire-Rakete der KI (normale Hellfire) | 17
AMMO_TYPE_MORTOKBOSS | Mortok Boss, eine leichte Hellfire | 18
AMMO_TYPE_NONE | Keine Munition | -1
AMMO_TYPE_DUMMY0 |  | -
AMMO_TYPE_DUMMY1 |  | -
AMMO_TYPE_DUMMY2 |  | -
AMMO_TYPE_DUMMY3 |  | -
AMMO_TYPE_EMP | EMP | -
AMMO_TYPE_ENEMY | Waffenboost? | -
AMMO_TYPE_HYPERSPACE | Plasmaschild? | -
AMMO_TYPE_MODULATION | Schildboost? | -
AMMO_TYPE_OVERLOAD | Overload | -
AMMO_TYPE_SLEEPER | Timeshock | -
Rot: Konstante in der MissionLibEx.lua definiert.
* Konstante in der MissionLibEx.lua neu definiert, ist zwar in Darkstar vorhanden, hat aber keinen Wert.

Auswirkung der speziellen Projektile mit der Funktion NShip.UseMissiles bei normalen Jägern
 | Rassen
Munitionstyp | Terraner | Raptor | Oc'to | Arrack | Thul
AMMO_TYPE_KIHOMING | Fehlalarm | Fehlalarm | Drohne, Fehlalarm | Fehlalarm | Fehlalarm
AMMO_TYPE_LIGHT | Fehlalarm | Explosion, Fehlalarm | Drohne | Fehlalarm | Fehlalarm
AMMO_TYPE_MINE | Fehlalarm | Fehlalarm | Mine | Fehlalarm | Fehlalarm
AMMO_TYPE_MINE_BRONIS | Fehlalarm | Drohne-Ex, Fehlalarm | Drohne-Ex, Fehlalarm | Fehlalarm | Fehlalarm
AMMO_TYPE_MORTOKBOSS | Fehlalarm | Schwarm | Drohne, Fehlalarm | Fehlalarm | Fehlalarm
AMMO_TYPE_RAPTOR | Fehlalarm | D-Rakete | Drohne | Fehlalarm | Fehlalarm
AMMO_TYPE_RAPTORBOSS | Stinger | L-Hellfire | Stinger, Drohne | Stinger | Stinger
AMMO_TYPE_SHOOTER | Fehlalarm | Shooter, Fehlalarm | Drohne | Fehlalarm | Fehlalarm
AMMO_TYPE_TURRETMISSILE | Fehlalarm | L-Swarm | Drohne | Fehlalarm | Fehlalarm

Mortok und S'kaa sind nicht mit in der Tabelle aufgeführt, da die Bestückung mit diesen Munitionssorten bei deren normalen Jägern keine Auswirkung hat. Es werden auch keine Fehlalarme erzeugt, wenn man es dennoch versucht.

Legende:

  • D-Rakete: Ein Raketenwerfer zum Abfeuern von zwei Raketen gleichzeitig.
  • Drohne: Eine einzelne selbstfeuernde Drohne. Die nächste Drohne wird erst abgeworfen, wenn die vorherige explodiert ist.
  • Drohne-Ex: Eine einzelne Drohne, die sofort nach dem Abwurf explodiert.
  • Explosion: Eine Explosion mit geringer Schadenswirkung im eigenen Triebwerk.
  • L-Hellfire: Eine leichte Hellfire mit der halben Schadenswirkung normaler Hellfires.
  • L-Swarm: Eine leichte Swarm-Rakete mit relativ geringer Schadenswirkung.
  • Mine: Eine einzelne Mine.
  • Schwarm: Ein dickes Bündel Schwarmraketen mit geringem Streuwinkel und hoher Schadenswirkung. Sehr gefährlich!
  • Shooter: Selbstfeuernde Drohnen, die bei Verfolgung abgeworfen werden.
  • Stinger: Stinger-Raketen mit hoher Feuerrate und langer Lebensdauer, die sich sofort auf das Ziel aufschalten und anders als bei den Hellfires und BigBangs keine Zeit dafür benötigen. Sie haben keine Reichweitenbeschränkung und werden bereits aus großer Entfernung in sehr kurzer Folge abgefeuert. Obwohl die Schadenswirkung einer einzelnen Rakete nicht höher als die einer Swarm-Rakete ist, sind sie durch die schnelle Abschussfolge, der großen Reichweite und der langen Lebensdauer extrem gefährlich!
  • Fehlalarm: Das Schiff lässt sich nicht mit dieser Munitionssorte bestücken. Jedoch werden im HUD Fehlalarme über angeblich aufgeschaltete Raketen angezeigt.

  • Raptorjäger werfen außer bei den Munitionssorten Drohne-Ex und Shooter noch zusätzlich Minen ab, wenn sie verfolgt werden.


Objekte

Objekte und Orbiter

Eine Aufzählung aller Objekte und ihrer Typen

Orbiter
Konstante | Kommentar | Wert
OBJTYPE_BASE OBJTYPE_TRADESTATION | Handelsstation | 0
OBJTYPE_SUN | Sonne | 1
OBJTYPE_PLANETTC OBJTYPE_PLANET_TECH | Technikplanet | 2
OBJTYPE_PLANETBG OBJTYPE_PLANET_BLUE | Agrarplanet | 3
OBJTYPE_PLANETGR OBJTYPE_PLANET_GAS | Gasriese | 4
OBJTYPE_ASTEROID | Bergbau-Asteroid | 5
OBJTYPE_MOON | Mond | 6
OBJTYPE_STATION OBJTYPE_RESEARCH_STATION | Forschungsstation | 7
OBJTYPE_GATE | Hypergate | 8
OBJTYPE_KOMET OBJTYPE_COMET | Komet | 9
OBJTYPE_METEOR | Meteoritenfeld | 10
OBJTYPE_DECORATION | Schiffs- und Stationswracks | 11
ORBITART_ANOMALIE OBJTYPE_ANOMALIE | Anomalie | 12
OBJTYPE_DISPLAY | Werbetafel | 13
OBJTYPE_BLACKHOLE | Schwarzes Loch; nur im Cluster Raptor Alpha, dort in allen Systemen | 14
OBJTYPE_BASESHIP | Piratenbasis | 15

SPACE-Objekte, Indicés für INI-Dateien
Konstante | Kommentar | Wert
SPACE_SUN | Sonne, Index für Suns.ini ? | 0
SPACE_PLANET | Planeten und Monde (ohne Lavaplaneten und Planetenringe) | 1
SPACE_SHIP | Spielerschiff, Index für StarShip.ini | 2
SPACE_STATION | Handelsstation, Index für StarShip.ini | 3
SPACE_TAXI | Taxi, Index für StarShip.ini | 4
SPACE_TRANSPORTER | Frachter, Index für StarShip.ini | 5
SPACE_CARGO | Index für Drones.ini ? | 6
SPACE_ROCKET | Index für Projectiles.ini ? | 7
SPACE_PIRATE | Piratenjäger, Index für StarShip.ini | 8
SPACE_MINE | Index für Projectiles.ini ? | 9
SPACE_POLICE | Polizeijäger, Index für StarShip.ini | 10
SPACE_PROJECTILE | Index für Projectiles.ini ? | 11
SPACE_WARPGATE | Hyperraumtor | 12
SPACE_CRUISER | Kreuzer, Index für StarShip.ini | 13
SPACE_EXPLOSION | Index für Explosion.ini ? | 14
SPACE_MILITARY | Militärjäger, Index für StarShip.ini | 15
SPACE_HUNTER | Geleitschutz- und Kopfgeldjäger, Index für StarShip.ini | 16
SPACE_SKAADRONE SPACE_SPECIALPLANET | Einzelne S'kaadrohne, nur in Afterburners.ini eingetragen Lavaplaneten (Crack- und Feuer-Planeten) und Planetenringe | 17
SPACE_ASTEROID |  | 18
SPACE_METEROID |  | 19
SPACE_RING |  | 20
SPACE_CANYON |  | 21
SPACE_CAMERA | Index für ActionCams.ini ? | 22
SPACE_SPELL | Plasma-Effekte | 23
SPACE_DEBRIS | Trümmer | 24
SPACE_CARGODRONE | Frachtdrohne der Jäger, Index für StarShip.ini | 25
SPACE_TURRET | Index für Projectiles.ini ? | 26
SPACE_WEAPONBASE | Waffenplattform, Index für StarShip.ini | 27
SPACE_SCAT | Schrott | 28
SPACE_WARPEFFECT | Hypersprung-Effekt | 29
SPACE_DECORATION | Wracks | 30
SPACE_PIRATE_FREIGHTER | Piratenfrachter, Index für StarShip.ini | 31
SPACE_SKAASWARM | S'kaaschwarm, Index für StarShip.ini | 32
SPACE_COMMSAT | Kommunikationssatellit, Index für StarShip.ini | 33
SPACE_? |  | 34
SPACE_SHIELDGEN | Schildgenerator, Index für StarShip.ini | 35
SPACE_? |  | 36
SPACE_? |  | 37
SPACE_? |  | 38
SPACE_? |  | 39
SPACE_PLAYERTURRET | Playerturret, Index für StarShip.ini | 40
SPACE_? |  | 41
SPACE_? |  | 42
SPACE_? |  | 43
SPACE_HIDEOUT | Piratenbasis, Index für StarShip.ini | 44
SPACE_ABERRATION | Anomalie | nil
SPACE_ADVERTISMENT | Werbetafel | nil
SPACE_ASTEROIDAUFBAUTEN |  | nil
SPACE_ASTEROIDINNERE | Zentrum von Asteroiden | nil
SPACE_COLLIDER |  | nil
SPACE_FORCEFIELD | Kraftfeld | nil
SPACE_HOVERTANK |  | nil
SPACE_SKAATUNNEL | S’kaa Mutterschiff | nil
SPACE_SUBSTATION |  | nil
SPACE_WEAPONFACTORY | Waffenfabrik | nil

Rot: Konstante in der MissionLibEx.lua definiert.

Handelsstationen

Die Bezeichnung "Model n" entpricht dem jeweiligen Eintrag in der Datei Planets.ini über dem Eintrag Orbitart = Basis.
Terraner Model 0 | Terraner Model 1 | Terraner Model 2
Terraner 0 | Terraner 1 | Terraner 2
Mortok Model 0 | Mortok Model 1 | Mortok Model 2
Mortok 0 | Mortok 1 | Mortok 2
Raptor Model 0 | Raptor Model 1 | Raptor Model 2
Raptor 0 | Raptor 1 | Raptor 2
Oc'to Model 0 | Oc'to Model 1 | Oc'to Model 2
Oc'to 0 | Oc'to 1 | Oc'to 2
Arrack Model 0 | Arrack Model 1 | Arrack Model 2
Arrack 0 | Arrack 1 | Arrack 2
Thul Model 0 | Thul Model 1 | Thul Model 2
Thul 0 | Thul 1 | Thul 2

Forschungsstationen

Die Bezeichnung "Model n" entpricht dem jeweiligen Eintrag in der Datei Planets.ini über dem Eintrag Orbitart = Forschung.
Terraner Model 0 | Terraner Model 1 | Terraner Model 2
Terraner 0 | Terraner 1 | Terraner 2
Mortok Model 0 | Mortok Model 1 | Mortok Model 2
Mortok 0 | Mortok 1 | Mortok 2
Raptor Model 0 | Raptor Model 1 | Raptor Model 2
Raptor 0 | Raptor 1 | Raptor 2
Oc'to Model 0 | Oc'to Model 1 | Oc'to Model 2
Oc'to 0 | Oc'to 1 | Oc'to 2
Arrack Model 0 | Arrack Model 1 | Arrack Model 2
Arrack 0 | Arrack 1 | Arrack 2
Thul Model 0 | Thul Model 1 | Thul Model 2
Thul 0 | Thul 1 | Thul 2

Kreuzer- und Stationswracks

"Model" entspricht dem jeweiligen Eintrag in der Datei Planets.ini über dem Eintrag Orbitart = Dekoration.
Model | Objekt
0 | kleines Kreuzerwrack der Terraner
1 | kleines Kreuzerwrack der Mortok
2 | großes Kreuzerwrack der Raptor
3 | kleines Kreuzerwrack der Oc'to
4 | kleines Kreuzerwrack der Arrack
5 | kleines Kreuzerwrack der Thul
6 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
7 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
8 | großes Kreuzerwrack der Terraner
9 | großes Kreuzerwrack der Mortok
10 | kleines Kreuzerwrack der Raptor
11 | großes Kreuzerwrack der Oc'to
12 | großes Kreuzerwrack der Arrack
13 | großes Kreuzerwrack der Thul
14 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
15 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
16 | Stationswrack, Fenster ist Vorderseite (Hangarposition ist an 45° gegen den Uhrzeigersinn)


Piratengangs

Eine Aufzählung aller Piratengangs und ihrer beheimateten Systeme
GangId | Gangname | SystemId | System | Cluster | Volk | Orbiter
0 | Karmiti-Gang | 4 | Obas | Lalande | Terraner | Schiffswrack
1 | Akim-Gang | 11 | Pachee | Lalande | Terraner | Schiffswrack
2 | Elsu-Gang | 18 | Anomi | Barnard | Terraner | Piratenbasis
3 | Taini-Gang | 26 | Echee | Alpha Centauri | Terraner | Anomalie
4 | Aponi-Gang | 34 | Shoma | Alpha Centauri | Terraner | Schiffswrack
5 | Fortun-Gang | 42 | Baylona | Grotok | Mortok | Schiffswrack
6 | Ordonho-Gang | 43 | Albadiz | Grotok | Mortok | Piratenbasis
7 | Ramiro-Gang | 46 | Neplocruz | Grotok | Mortok | Piratenbasis
8 | Vasco-Gang | 48 | Arrosloca | Grotok | Mortok | Schiffswrack
9 | Boaventura-Gang * | 64 | Rulote | Pertok | Mortok | Piratenbasis
10 | Alvito-Gang | 57 | Lular | Grotok | Mortok | Anomalie
11 | Mendo-Gang | 58 | Alfabalas | Grotok | Mortok | Piratenbasis
12 | Galindo-Gang | 75 | Lucero | Stromok | Mortok | Anomalie
13 | Gil-Gang | 80 | Telbeigro | Stromok | Mortok | Piratenbasis
14 | Tiago-Gang | 90 | Sarbrejar | Klatok | Mortok | Piratenbasis
15 | Marjo-Gang | 95 | Aychena | Klatok | Mortok | Anomalie
16 | Helder-Gang | 110 | Avilmurcia | Klatok | Mortok | Anomalie
17 | Armengol-Gang | 112 | Tero | Klatok | Mortok | Piratenbasis
18 | Boris-Gang | 135 | Goro | Raptor Nova | Raptor | Piratenbasis
19 | Sergej-Gang | 138 | Vidal | Raptor Nova | Raptor | Piratenbasis
20 | Igor-Gang | 141 | Nizbin | Raptor Nova | Raptor | Schiffswrack
21 | Jurij-Gang | 155 | Desno | Raptor Gamma | Raptor | Piratenbasis
22 | Wladislaw-Gang | 157 | Twerkano | Raptor Gamma | Raptor | Piratenbasis
23 | Sascha-Gang | 171 | Archangelsk | Raptor Delta | Raptor | Piratenbasis
24 | Danilo-Gang | 172 | Nakhodlu | Raptor Delta | Raptor | Piratenbasis
25 | Andrei-Gang | 179 | Amkovo | Raptor Epsilon | Raptor | Schiffswrack
26 | Jorg-Gang | 184 | Charodpul | Raptor Epsilon | Raptor | Piratenbasis
27 | Let'han-Gang | 194 | Gans'clie | Sion'nach | Oc'to | Piratenbasis
28 | Gor'ogh-Gang | 197 | Kil'ore | Sion'nach | Oc'to | Anomalie
29 | Mascha-Gang | 211 | Wica | Sirius | Terraner | Piratenbasis
30 | Macawi-Gang | 217 | Cloma | Sirius | Terraner | Piratenbasis
31 | Tor'hal-Gang | 231 | D'ores | Madra'mor | Oc'to | Schiffswrack
32 | Mar'ghal-Gang | 274 | Lone'ron | Gab'har | Oc'to | Anomalie
33 | Sav'ghal-Gang | 284 | Achnas'aul | Gab'har | Oc'to | Schiffswrack
34 | Shakunt-fu-Gang | 295 | Pyidaung | Hive-AC3 | Arrack | Anomalie
35 | Dakshe-ne-Gang | 297 | Laikuku | Hive-AC3 | Arrack | Piratenbasis
36 | Jitendra-ko-Gang | 301 | Mingin | Hive-AC3 | Arrack | Piratenbasis
37 | Janath-ai-Gang | 326 | Sainolin | Hive-CU7 | Arrack | Schiffswrack
38 | Eknath-ko-Gang | 332 | Kindaung | Hive-CU7 | Arrack | Anomalie
39 | Al'ogh-Gang | 339 | Kinmin | Hive-CU7 | Arrack | Anomalie
40 | Tarak-fu-Gang | 345 | Chaing | Hive-DC | Arrack | Piratenbasis
41 | Uday-ne-Gang | 346 | Thidaya | Hive-DC | Arrack | Schiffswrack
42 | Alok-ne-Gang | 348 | Tegyigon | Hive-DC | Arrack | Piratenbasis
43 | Domhnall-Gang | 385 | Aberloch | Communa | Thul | Piratenbasis
44 | Laoghaire-Gang | 392 | Keodale | Communa | Thul | Piratenbasis
45 | Lennox-Gang | 393 | Ardarroch | Communa | Thul | Piratenbasis
46 | Mathuin-Gang | 395 | Todhair | Communa | Thul | Piratenbasis
-/- | Raz'koyr-Bull * | 276 | Sc'atwell | Gab'har | Oc'to | Piratenbasis
-/- | X'Snider'Hips * | 286 | Insh'ore | Gab'har | Oc'to | Piratenbasis

* Die Boaventura-Gang ist standardmäßig deaktiviert (SystemId=500, Absicht oder nur ein Schreibfehler in der "Systemeigenschaften.ini"?), ansonsten wäre die Gang wahrscheinlich im System Lucia (SystemId=50) des Clusters Grotok angesiedelt. Man kann die Gang auch in ein anderes System ohne Piratengang stecken, es muss aber in einem Cluster der Mortok liegen, sonst wird kein Piraten-Wing erzeugt. Ich habe sie in den Cluster Pertok gesteckt, da dort noch keine Gang existiert und Grotok bereits 6 davon hat. Der versteckte Cluster Humok wäre ebenfalls gut geeignet, wenn man dessen Systeme in den INI-Dateien freischaltet.

Um die Gang zu aktivieren, müssen die folgenden 3 Dateien im Mod-Verzeichnis geändert werden:

  1. inifiles\Planets.ini
    Meteoritenfeld und Piratenbasis, Schiffswrack oder Anomalie hinzufügen, unter [Globals] die Planetenanzahl um 2 erhöhen
  2. inifiles\StarSystem.ini
    Index "9" der Piratengang im entsprechenden System eintragen
  3. inifiles\Infos\Systemeigenschaften.ini
    SystemId des gewählten Sternensystems der Piratengang beim Index "9" eintragen

* Diese beiden Gangs sind nur der Vollständigkeit halber mit aufgeführt. Sie werden vom Programm in einer Storymission erzeugt, sind nicht in den INI-Dateien definiert und haben somit auch keine GangId. Nach Erfüllung der Tarnfeldscanner-Mission sind sie im Gegensatz zu den fest definierten Piratengangs wieder endgültig weg.


Plasmawerfer

Die Effekte des Plasmawerfers (definiert in WeaponEffects.ini)
Konstante | Kommentar | Farbe | Sound | Wert
EFFECT_WEAPON_BOOST | Waffenboost | Weiß | Nein | 0
EFFECT_OVERLOAD | Overload | Grün | Schusssound mit Nachhall 1 | 1
EFFECT_EMP | Elektromagnetischer Puls | Weiß | Schusssound mit Nachhall 2 | 2
EFFECT_SHIELD_BOOST | Schildboost | Weiß | Nein | 3
EFFECT_PLASMA_SHIELD | Plasmaschild | Weiß | Nein | 4
EFFECT_TIME_SHOCK | Timeshock | Weiß | Langanhaltender hohler Windeffekt | 5

Der Waffenstrahl ist transparent, somit hängt seine Farbe auch vom Hintergrund des Alls ab.


PlayerShip

Die Schiffsstufen mit den zugehörigen Energie-, Waffen- und Ausrüstungsklassen
Upgradestufen
Schiff | Energie | Waffen | Ausrüstung | Erhältliche Ausrüstung
0 | 1 | 1 | 1 | Aktuator-Refill, Energieflux, Energiesammler X-20, Handelscomputer X-50 (nur "Versteckte Cluster" Mod), Jammer X-30, Landecomputer X-1, Laser, Nachbrenner 150%, Nachbrenner-Booster, Raketenwerfer, Reparaturbot X-60 (nur "Versteckte Cluster" Mod), Schildflux, Swarm
1 | 1 | 2 | 1 | Hellfire
2 | 2 | 2 | 1 | Frachtcomputer X-100, Frachtscanner X-2, Nachbrenner 160% (nur "Versteckte Cluster" Mod)
3 | 2 | 3 | 2 | BigBang, Energiesammler X-30, Graviton-Schub, Handelscomputer X-100 (nur "Versteckte Cluster" Mod), Jammer X-40, Landecomputer X-2, Reparaturbot X-80
4 | 3 | 3 | 2 | Frachtcomputer X-200, Nachbrenner 180% (nur "Versteckte Cluster" Mod)
5 | 3 | 3 | 3 | Energiesammler X-40, Erzsammler, Jammer X-50, Landecomputer X-3, Reparaturbot X-100
6 | 3 | 4 | 3 |
7 | 4 | 4 | 3 | Frachtcomputer X-300, Frachtscanner X-3, Nachbrenner 200% (nur "Versteckte Cluster" Mod), Frühestmöglicher Ausbau der ersten Stufe vom Timeshock
8 | 4 | 4 | 4 | Energiesammler X-50, Jammer X-60, Landecomputer X-4 (nur "Versteckte Cluster" Mod), Frühestmöglicher Ausbau der ersten Stufe vom Plasmaschild
9 | 4 | 5 | 4 |
10 | 5 | 5 | 4 | Frachtcomputer X-600, Frachtscanner X-4, Nachbrenner 250% (nur "Versteckte Cluster" Mod)
11 | 5 | 5 | 5 | Jammer X-70, Landecomputer X-5, Frühestmöglicher Maximalausbau des Timeshocks
12 | 5 | 6 | 5 | Frühestmöglicher Maximalausbau des Plasmaschildes
13 | 6 | 6 | 5 | Frachtscanner X-5, Nachbrenner 300% (nur "Versteckte Cluster" Mod)
14 | 6 | 6 | 6 | Jammer X-80 (nur "Versteckte Cluster" Mod)
15 | 6 | 7 | 6 |
16 | 7 | 7 | 7 | Frachtscanner X-Elite 10u, Nachbrenner 350% (nur "Versteckte Cluster" Mod)
17 | 7 | 7 | 7 | Jammer X-90
18 | 7 | 8 | 7 |
19 | 8 | 8 | 8 | Frachtscanner X-Elite 15u, Nachbrenner 400% (nur "Versteckte Cluster" Mod)
20 | 8 | 8 | 8 |
21 | 8 | 9 | 8 |
22 | 9 | 9 | 9 | Frachtscanner X-Elite 20u, Nachbrenner 450% (nur "Versteckte Cluster" Mod)
23 | 9 | 9 | 9 |
24 | 9 | 9 | 9 |
25 | 10 | 10 | 10 | Nachbrenner 500% (nur "Versteckte Cluster" Mod)
26 | 10 | 10 | 10 |
27 | 10 | 10 | 10 |
28 | 10 | 10 | 10 |
29 | 10 | 10 | 10 |
30 | 10 | 10 | 10 |


RadarMap Colors

Die auf der Radarmap verwendeten Farben.
Die Farben haben keinen Einfluss auf das Verhalten.
Konstante | Kommentar | Wert
RADARMAP_INVISIBLE | Objekt wird nicht angezeigt | 0
RADARMAP_SHIP_FRIEND | Freundliches Objekt | 1
RADARMAP_SHIP_FRIEND_WING | Freundliches Objekt | 2
RADARMAP_SHIP_HOSTILE | Feindliches Objekt | 3
RADARMAP_SHIP_HOSTILE_WING | Feindliches Objekt | 4
RADARMAP_SHIP_OFFICIAL | Patrouillen- und Militärschiffe | 5
RADARMAP_SHIP_OFFICIAL_WING | Patrouillen- und Militärschiffe | 6
RADARMAP_SHIP_NEUTRAL RADARMAP_SHIP_STANDARD RADARMAP_SHIP_THREAT | Neutrales Objekt Standardobjekt Bedrohung | 9
RADARMAP_SHIP_NEUTRAL_WING RADARMAP_SHIP_STANDARD_WING RADARMAP_SHIP_THREAT_WING | Neutraler Wing Standardwing Bedrohender Wing | 10
RADARMAP_SHIP_TAXI | Taxis und Shuttles | 11
RADARMAP_CARGO | Container | 12
RADARMAP_BASE | Handelsstation | 13
RADARMAP_STATION | Forschungsstation | 14
RADARMAP_WAYPOINT | Wegpunkt | 15
RADARMAP_INVALID | Geänderte Zuweisungen werden wieder auf Standardfarben zurückgesetzt | 18

In der MissionLibEx.lua definierte Konstanten für die auf der Radarmap und den Markierungen im Weltraum verwendeten Farben.
Format der Namen: RADARMAP_<Farbe>_<Spalte in der Targetliste>.
In der rechten Spalte "Offiziell" (blau) der Targetliste sind ORBITER immer oben und SHIP unten gelistet.
Konstante | Kommentar | Wert
RADARMAP_NONE_HIDDEN | Objekt wird nicht angezeigt und hat auch keine Markierung im Weltraum | 0
RADARMAP_GREEN_FRIEND | Freundliches Objekt | 1
RADARMAP_GREEN_FRIEND2 | Freundliches Objekt | 2
RADARMAP_RED_ENEMY | Feindliches Objekt | 3
RADARMAP_RED_ENEMY2 | Feindliches Objekt | 4
RADARMAP_BLUE_SHIP | Offizielles dynamisches Objekt, dunkelblau in der Targetliste, mittelblau im Raum | 5
RADARMAP_BLUE_SHIP2 | Offizielles dynamisches Objekt, dunkelblau in der Targetliste, mittelblau im Raum | 6
RADARMAP_BLUE_SHIP3 | Offizielles dynamisches Objekt, dunkelblau in der Targetliste, mittelblau im Raum | 7
RADARMAP_BLUE_SHIP4 | Offizielles dynamisches Objekt, dunkelblau in der Targetliste, mittelblau im Raum | 8
RADARMAP_GREEN_FRIEND3 | Freundliches Objekt | 9
RADARMAP_GREEN_FRIEND4 | Freundliches Objekt | 10
RADARMAP_WHITE_HIDDEN | Neutral, wird in der Targetliste nicht angezeigt | 11
RADARMAP_WHITE_SHIP | Neutral, offizielles dynamisches Objekt in der Targetliste | 12
RADARMAP_BLUE_ORBITER | Offizielles statisches Objekt, mittelblau in der Targetliste, dunkelblau im Raum | 13
RADARMAP_BLUE_ORBITER2 | Offizielles statisches Objekt, mittelblau in der Targetliste, dunkelblau im Raum | 14
RADARMAP_WHITE_FRIEND | Neutral, freundliches Objekt in der Targetliste | 15
RADARMAP_WHITE_FRIEND2 | Neutral, freundliches Objekt in der Targetliste | 16
RADARMAP_WHITE_HIDDEN2 | Neutral, wird in der Targetliste nicht angezeigt | 17
RADARMAP_STANDARD | Farbe ist vom Objekt abhängig, Änderungen werden zurückgesetzt | 18


Rassen

Eine Aufzählung aller vorhandenen Völker
Konstante | Kommentar | Wert
RACE_HUMAN | Terraner | 0
RACE_MORTOK RACE_MORLOK | Mortok | 1
RACE_RAPTOR | Raptor | 2
RACE_OCTO | Oc'to | 3
RACE_ARRACK RACE_WASP | Arrack | 4
RACE_THUL | Thul | 5
RACE_SKAA | S'kaa | 6
RACE_1704 | 1704 (nicht vorhanden) * | 7
RACE_RANDOM | Automatische Rassenverteilung des aktuellen Clusters wird verwendet | 8
RACE_CLUSTER | Automatische Rassenverteilung des aktuellen Clusters wird verwendet | -1
Rot: Konstante in der MissionLibEx.lua definiert.

* Schaltet man den versteckten Terraner-Cluster "Ross 128" (ClusterId=18) frei, wird man feststellen, dass die Raumstationen der Sternsysteme zwar in der Targetliste erscheinen, aber im Weltraum grafisch nicht sichtbar sind. Eine manuelle Landung auf den Stationen ist somit praktisch kaum möglich, da auch die Anflugbefeuerung nicht angezeigt wird, nachdem man die Landeerlaubnis erhalten hat. Während man bei den Handelsstationen ja noch den Landecomputer zu Hilfe nehmen kann, funktioniert das bei den Forschungsstationen nicht.

Der Fehler liegt in der Datei "inifiles\StarCluster.ini" im Sektor "[Cluster18]" begraben. Dort hatte Ascaron mit dem Eintrag "Rasse = 1704" diese nicht existierende Rasse eingetragen. Einfach in "Rasse = Menschen" ändern, und schon sind die Stationen wieder sichtbar.


Regierung

Eine Aufzählung aller Regierungsformen
Konstante | Kommentar | Wert
GOVERN_DEMOCRACY | Demokratie | 0
GOVERN_DICTATORSHIP | Diktatur | 1
GOVERN_FEDERATION | Staatenbund | 2
GOVERN_ANARCHY | Anarchie | 3
GOVERN_CONCERN | Konzernführung | 4
GOVERN_MONARCHY | Monarchie | 5

Fraktionen
Konstante | Kommentar | Wert
FACTION_FEDERATION | GU (Galaktische Union) | 0
FACTION_REBELS | Rebellen | 1
FACTION_INDEPENDENT | Neutral | 2


StarShip-Typen

und StarShip-Modelle

Eine Aufzählung aller Schiffsklassen (ShipType), für 'ObjType' in der Funktion "NWing.Define"
Konstante | Kommentar | Wert | SPACE-Objekttyp | Wert
ST_PLAYERSHIP * | Das Schiff des Spielers | 0 | SPACE_SHIP | 2
ST_TRADERSHIP | Handelsfrachter | 1 | SPACE_TRANSPORTER | 5
ST_SHUTTLE * | Shuttle für die Container zwischen Frachtern und Station | 2 | SPACE_TAXI | 4
ST_CONSUMPTION_SHUTTLE * | Transportshuttle von Handelsstation zu anderen Orbitern | 3 | SPACE_TAXI | 4
ST_PRODUCTION_SHUTTLE * | Transportshuttle von den Orbitern zur Handelsstation | 4 | SPACE_TAXI | 4
ST_POLICE | Polizeijäger | 5 | SPACE_POLICE | 10
ST_PIRATESHIP | Piratenjäger | 6 | SPACE_PIRATE | 8
ST_WINGMAN | Begleitjäger oder Schiff der Kopfgeldjäger | 7 | SPACE_HUNTER | 16
ST_CRUISER | Großer oder kleiner Kreuzer | 8 | SPACE_CRUISER | 13
ST_SKAADRONE | Kampfdrohne der S’kaa, bleibt immer in einer Formation | 9 | SPACE_SKAADRONE | 17
ST_MILITARYFIGHTER | Militärjäger | 10 | SPACE_MILITARY | 15
ST_CARGODRONE * | Frachtdrohne der Jäger (auch vom Spielerschiff) | 11 | SPACE_CARGODRONE | 25
ST_WEAPONBASE | Unbewegliche Waffenplattform | 12 | SPACE_WEAPONBASE | 27
ST_PIRATEFREIGHTER | Frachter der Piraten | 13 | SPACE_PIRATE_FREIGHTER | 31
ST_SKAASWARM | Zentrum der S’kaadrohnen-Formation, kein Schiff | 14 | SPACE_SKAASWARM | 32
ST_CANYONSHIP * | Schiff, welches in Canyons auf festen Bahnen fliegt | 15 | Abhängig vom Modelltyp (Look) |
ST_COMMSAT * | Kommunikations-Satellit als Waffenplattform | 16 | SPACE_COMMSAT | 33
ST_TRADERDRONE * | Frachtdrohne der Frachter | 17 |  |
ST_COLLECTOR_SHUTTLE * | Shuttle, sammelt frei im All schwebende Container ein? | 18 | SPACE_TAXI | 4
ST_SHIELDGEN * | Missionsobjekt, das im Canyon zerstört werden soll | 19 | SPACE_SHIELDGEN | 35
ST_... ? | Frei? Ist jedenfalls kein Schiff (getestet mit NWing.Define) | 20 |
ST_PASSENGER_SHUTTLE * | Transportshuttle mit Passagiermodul (Taxi) | 21 | SPACE_TAXI | 4
ST_BASESHIP | Piratenbasis | 22 | SPACE_HIDEOUT | 44
ST_SUPERFREIGHTER | Superfrachter, trägt je nach Rasse 40, 42 o. 45 Container | 23 | SPACE_TRANSPORTER | 5
Rot: Konstante in der MissionLibEx.lua definiert.
* Diese Schiffstypen lassen sich nicht mit "NWing.Define" erzeugen.

Generatoren, für 'ObjIndex' in der Funktion "NWing.Define"
Konstante | Kommentar | Wert
GENERATOR_KABRO | Der Generator in der ersten Tunnelmission (Kabro) | 0
GENERATOR_BRONIS_0 | Ein blauer Generator in der Waffenfabrik | 1
GENERATOR_BRONIS_1 | Ein roter Generator in der Waffenfabrik | 2
GENERATOR_BRONIS_2 | Ein grüner Generator in der Waffenfabrik | 3
GENERATOR_SKAA | Ein Generator im S’kaatunnel | 4
GENERATOR_SKAA_CORE | Der Hauptreaktor des S’kaamutterschiffs | 5

Schiffszustand im StarShips-Event "StarShip"
Wert | Beschreibung | Wert
SHIP_SHIELD_50 | Der Schildzustand des Schiffes ist unter 50% gesunken. | 0
SHIP_SHIELD_25 | Der Schildzustand des Schiffes ist unter 25% gesunken. | 1
SHIP_SHIELD_0 | Der Schildzustand des Schiffes ist auf 0% gesunken. | 2
SHIP_HULL_75 | Der Hüllenzustand des Schiffes ist unter 75% gesunken. | 3
SHIP_HULL_50 | Der Hüllenzustand des Schiffes ist unter 50% gesunken. | 4
SHIP_HULL_25 | Der Hüllenzustand des Schiffes ist unter 25% gesunken. | 5
SHIP_HULL_10 | Der Hüllenzustand des Schiffes ist unter 10% gesunken. | 6
SHIP_LANDED | Das Schiff ist gelandet ( und wird danach zerstört ) | 7

Schildzustand im StarShips-Event "Shield"
Konstante | Kommentar | Wert
SHIELD_DOWN | Der Schutzschild ist weg | 0
SHIELD_HALF | Der Schutzschild ist zur Hälfte runter | 1
SHIELD_FRONT | Vorderer Schild ist betroffen | 0
SHIELD_BACK | Hinterer Schild ist betroffen | 1
SHIELD_BOTH | Beide Schilde sind betroffen | 2

StarShip-Modelle

Eine Aufzählung aller StarShip-Modelle, für 'ObjIndex' in der Funktion "NWing.Define"

Wer sich seine Wings mit der Funktion "NWing.Define" erzeugen möchte, muss bei dem Parameter 'Ships' auch einen Objektindex für das gewünschte Modell angeben. Bisher ging dafür immer die große Suche in der StarShip.ini los, da es im Modding-Tool fast keine Konstanten dafür gibt. Um das zu vereinfachen, wurden in der MissionLibEx.lua entsprechende Konstanten für alle in der StarShip.ini vorhandenen Modelle definiert.

Ein Beispiel am Eintrag [StarShip005_000] in der StarShip.ini:
Die erste Zahl "005" entspricht der Konstante eines SPACE-Objekts (vgl. Objekte und Orbiter), nicht zu verwechseln mit der ST_-Konstante für StarShip-Typen. Hier ist es also ein Handelsfrachter SPACE_TRANSPORTER und kein Jäger ST_POLICE.
Die zweite Zahl "000" ist eine laufende Nummer für das definierte Modell und entspricht den hier in den Tabellen eingetragenen Werten.
Somit erhält man in diesem Beispiel einen terranischen Handelsfrachter, der 4 Container á 50t transportieren kann.

Übersicht:
  • Frachtdrohne
  • Frachter - Handelsfrachter
  • Frachter - Spezialfrachter
  • Frachter - Piratenfrachter
  • Jäger - Geleitschutz- und Kopfgeldjäger
  • Jäger - Militärjäger
  • Jäger - Piratenjäger
  • Jäger - Polizeijäger
  • Kreuzer
  • Piratenbasis
  • Playerturrets
  • Satelliten
  • Schildgeneratoren
  • S’kaaschwarm
  • Stationen - Handelsstationen
  • Taxi (Shuttles)
  • Waffenplattformen
zurück zu den StarShip-Typen

Frachtdrohne SPACE_CARGODRONE
Konstante | Kommentar | Wert
SI_CARGODRONE | Frachtdrohne, die für Jäger die Container trägt | 0
zur Übersicht

Handelsfrachter SPACE_TRANSPORTER
Konstante | Kommentar | Wert
SI_TRADER_4X50T_HUMAN | Terraner-Frachter 200 Tonnen, für 4 Container á 50t | 0
SI_TRADER_2X100T_HUMAN | Terraner-Frachter 200 Tonnen, für 2 Container á 100t | 1
SI_TRADER_8X50T_HUMAN | Terraner-Frachter 400 Tonnen, für 8 Container á 50t | 2
SI_TRADER_4X100T_HUMAN | Terraner-Frachter 400 Tonnen, für 4 Container á 100t | 3
SI_TRADER_6X100T_HUMAN | Terraner-Frachter 600 Tonnen, für 6 Container á 100t | 4
SI_TRADER_3X200T_HUMAN | Terraner-Frachter 600 Tonnen, für 3 Container á 200t | 5
SI_TRADER_4X50T_MORTOK | Mortok-Frachter 200 Tonnen, für 4 Container á 50t | 6
SI_TRADER_2X100T_MORTOK | Mortok-Frachter 200 Tonnen, für 2 Container á 100t | 7
SI_TRADER_8X50T_MORTOK | Mortok-Frachter 400 Tonnen, für 8 Container á 50t | 8
SI_TRADER_4X100T_MORTOK | Mortok-Frachter 400 Tonnen, für 4 Container á 100t | 9
SI_TRADER_6X100T_MORTOK | Mortok-Frachter 600 Tonnen, für 6 Container á 100t | 10
SI_TRADER_3X200T_MORTOK | Mortok-Frachter 600 Tonnen, für 3 Container á 200t | 11
SI_TRADER_4X50T_RAPTOR | Raptor-Frachter 200 Tonnen, für 4 Container á 50t | 13*
SI_TRADER_4X100T_RAPTOR | Raptor-Frachter 400 Tonnen, für 4 Container á 100t | 14*
SI_TRADER_3X200T_RAPTOR | Raptor-Frachter 600 Tonnen, für 3 Container á 200t | 15*
SI_TRADER_4X50T_OCTO | Oc’to-Frachter 200 Tonnen, für 4 Container á 50t | 12*
SI_TRADER_4X100T_OCTO | Oc’to-Frachter 400 Tonnen, für 4 Container á 100t | 16
SI_TRADER_3X200T_OCTO | Oc’to-Frachter 600 Tonnen, für 3 Container á 200t | 17
SI_TRADER_4X50T_ARRACK | Arrack-Frachter 200 Tonnen, für 4 Container á 50t | 18
SI_TRADER_4X100T_ARRACK | Arrack-Frachter 400 Tonnen, für 4 Container á 100t | 19
SI_TRADER_3X200T_ARRACK | Arrack-Frachter 600 Tonnen, für 3 Container á 200t | 20
SI_TRADER_4X50T_THUL | Thul-Frachter 200 Tonnen, für 4 Container á 50t | 21
SI_TRADER_4X100T_THUL | Thul-Frachter 400 Tonnen, für 4 Container á 100t | 22
SI_TRADER_3X200T_THUL | Thul-Frachter 600 Tonnen, für 3 Container á 200t | 23
SI_SUPERTRADER_S_HUMAN | Superfrachter 2250 Tonnen, für 45 Container á 50t * | 24
SI_SUPERTRADER_M_HUMAN | Superfrachter 4500 Tonnen, für 45 Container á 100t * | 25
SI_SUPERTRADER_L_HUMAN | Superfrachter 9000 Tonnen, für 45 Container á 200t * | 26
SI_SUPERTRADER_S_ARRACK | Superfrachter 2100 Tonnen, für 42 Container á 50t * | 27
SI_SUPERTRADER_M_ARRACK | Superfrachter 4200 Tonnen, für 42 Container á 100t * | 28
SI_SUPERTRADER_L_ARRACK | Superfrachter 8400 Tonnen, für 42 Container á 200t * | 29
SI_SUPERTRADER_S_RAPTOR | Superfrachter 2000 Tonnen, für 40 Container á 50t * | 30
SI_SUPERTRADER_M_RAPTOR | Superfrachter 4000 Tonnen, für 40 Container á 100t * | 31
SI_SUPERTRADER_L_RAPTOR | Superfrachter 8000 Tonnen, für 40 Container á 200t * | 32
* Der StarShip.ini neu hinzugefügt.
* Kein Schreibfehler, die Reihenfolge stimmt hier tatsächlich nicht.
zur Übersicht

Spezialfrachter SPACE_TRANSPORTER
Konstante | Kommentar | Wert
SI_BOMBER_B2_HUMAN | Terraner-Frachter 400 Tonnen, für 2 Geheimdienstwaffen-Container * | 33
SI_BOMBER_B3_HUMAN | Terraner-Frachter 600 Tonnen, für 3 Geheimdienstwaffen-Container * | 34
SI_BOMBER_B4_HUMAN | Terraner-Frachter 800 Tonnen, für 4 Geheimdienstwaffen-Container * | 35
SI_BOMBER_B6_HUMAN | Terraner-Frachter 1200 Tonnen, für 6 Geheimdienstwaffen-Container * | 36
SI_BOMBER_B8_HUMAN | Terraner-Frachter 1600 Tonnen, für 8 Geheimdienstwaffen-Container * | 37
SI_BOMBER_B2_MORTOK | Mortok-Frachter 400 Tonnen, für 2 Geheimdienstwaffen-Container * | 38
SI_BOMBER_B3_MORTOK | Mortok-Frachter 600 Tonnen, für 3 Geheimdienstwaffen-Container * | 39
SI_BOMBER_B4_MORTOK | Mortok-Frachter 800 Tonnen, für 4 Geheimdienstwaffen-Container * | 40
SI_BOMBER_B6_MORTOK | Mortok-Frachter 1200 Tonnen, für 6 Geheimdienstwaffen-Container * | 41
SI_BOMBER_B8_MORTOK | Mortok-Frachter 1600 Tonnen, für 8 Geheimdienstwaffen-Container * | 42
SI_BOMBER_B3_RAPTOR | Raptor-Frachter 600 Tonnen, für 3 Geheimdienstwaffen-Container * | 43
SI_BOMBER_B4_RAPTOR | Raptor-Frachter 800 Tonnen, für 4 Geheimdienstwaffen-Container * | 44
SI_BOMBER_B3_OCTO | Oc’to-Frachter 600 Tonnen, für 3 Geheimdienstwaffen-Container * | 45
SI_BOMBER_B4_OCTO | Oc’to-Frachter 800 Tonnen, für 4 Geheimdienstwaffen-Container * | 46
SI_BOMBER_B3_ARRACK | Arrack-Frachter 600 Tonnen, für 3 Geheimdienstwaffen-Container * | 47
SI_BOMBER_B4_ARRACK | Arrack-Frachter 800 Tonnen, für 4 Geheimdienstwaffen-Container * | 48
SI_BOMBER_B3_THUL | Thul-Frachter 600 Tonnen, für 3 Geheimdienstwaffen-Container * | 49
SI_BOMBER_B4_THUL | Thul-Frachter 800 Tonnen, für 4 Geheimdienstwaffen-Container * | 50
SI_SUPERBOMBER_HUMAN | Superfrachter 9000 Tonnen, für 45 Geheimdienstwaffen-Container | 51
SI_SUPERBOMBER_ARRACK | Superfrachter 8400 Tonnen, für 42 Geheimdienstwaffen-Container | 52
SI_SUPERBOMBER_RAPTOR | Superfrachter 8000 Tonnen, für 40 Geheimdienstwaffen-Container | 53
* Der StarShip.ini neu hinzugefügt.

Hinweis: Die letzten drei Superfrachter-Einträge müssen aus technischen Gründen immer am Ende der Handelsfrachter-Definitionen in der StarShip.ini stehen. Deshalb haben sich die Werte hier gegenüber der originalen INI-Datei geändert. Für die originale StarShip.ini müssen wieder die ursprünglichen Werte für die Superfrachter verwendet werden und sind daher in der MissionLibEx.lua nochmal mit anderen Bezeichnungen der Konstanten definiert:
Konstante | Kommentar | Wert
SI_SUPERTRADER_W_HUMAN | Superfrachter 9000 Tonnen, für 45 Geheimdienstwaffen-Container | 24
SI_SUPERTRADER_W_ARRACK | Superfrachter 8400 Tonnen, für 42 Geheimdienstwaffen-Container | 25
SI_SUPERTRADER_W_RAPTOR | Superfrachter 8000 Tonnen, für 40 Geheimdienstwaffen-Container | 26
zur Übersicht

Piratenfrachter SPACE_PIRATE_FREIGHTER
Konstante | Kommentar | Wert
SI_PIRATE_4X50T_HUMAN | Terraner-Piratenfrachter 200 Tonnen, für 4 Container á 50t | 0
SI_PIRATE_2X100T_HUMAN | Terraner-Piratenfrachter 200 Tonnen, für 2 Container á 100t | 1
SI_PIRATE_8X50T_HUMAN | Terraner-Piratenfrachter 400 Tonnen, für 8 Container á 50t | 2
SI_PIRATE_4X100T_HUMAN | Terraner-Piratenfrachter 400 Tonnen, für 4 Container á 100t | 3
SI_PIRATE_6X100T_HUMAN | Terraner-Piratenfrachter 600 Tonnen, für 6 Container á 100t | 4
SI_PIRATE_3X200T_HUMAN | Terraner-Piratenfrachter 600 Tonnen, für 3 Container á 200t | 5
SI_PIRATE_4X50T_MORTOK | Mortok-Piratenfrachter 200 Tonnen, für 4 Container á 50t | 6
SI_PIRATE_2X100T_MORTOK | Mortok-Piratenfrachter 200 Tonnen, für 2 Container á 100t | 7
SI_PIRATE_8X50T_MORTOK | Mortok-Piratenfrachter 400 Tonnen, für 8 Container á 50t | 8
SI_PIRATE_4X100T_MORTOK | Mortok-Piratenfrachter 400 Tonnen, für 4 Container á 100t | 9
SI_PIRATE_6X100T_MORTOK | Mortok-Piratenfrachter 600 Tonnen, für 6 Container á 100t | 10
SI_PIRATE_3X200T_MORTOK | Mortok-Piratenfrachter 600 Tonnen, für 3 Container á 200t | 11
SI_PIRATE_4X50T_RAPTOR | Raptor-Piratenfrachter 200 Tonnen, für 4 Container á 50t | 12
SI_PIRATE_4X100T_RAPTOR | Raptor-Piratenfrachter 400 Tonnen, für 4 Container á 100t | 13
SI_PIRATE_3X200T_RAPTOR | Raptor-Piratenfrachter 600 Tonnen, für 3 Container á 200t | 14
SI_PIRATE_4X50T_OCTO | Oc’to-Piratenfrachter 200 Tonnen, für 4 Container á 50t | 15
SI_PIRATE_4X100T_OCTO | Oc’to-Piratenfrachter 400 Tonnen, für 4 Container á 100t | 16
SI_PIRATE_3X200T_OCTO | Oc’to-Piratenfrachter 600 Tonnen, für 3 Container á 200t | 17
SI_PIRATE_4X50T_ARRACK | Arrack-Piratenfrachter 200 Tonnen, für 4 Container á 50t | 18
SI_PIRATE_4X100T_ARRACK | Arrack-Piratenfrachter 400 Tonnen, für 4 Container á 100t | 19
SI_PIRATE_3X200T_ARRACK | Arrack-Piratenfrachter 600 Tonnen, für 3 Container á 200t | 20
SI_PIRATE_4X50T_THUL | Thul-Piratenfrachter 200 Tonnen, für 4 Container á 50t | 21
SI_PIRATE_4X100T_THUL | Thul-Piratenfrachter 400 Tonnen, für 4 Container á 100t | 22
SI_PIRATE_3X200T_THUL | Thul-Piratenfrachter 600 Tonnen, für 3 Container á 200t | 23

Der StarShip.ini neu hinzugefügte Piratenfrachter SPACE_PIRATE_FREIGHTER
Konstante | Kommentar | Wert
SI_PIRATE_2X50T_HUMAN | Terraner-Piratenfrachter 100 Tonnen, für 2 Container á 50t | 24
SI_PIRATE_3X50T_HUMAN | Terraner-Piratenfrachter 150 Tonnen, für 3 Container á 50t | 25
SI_PIRATE_6X50T_HUMAN | Terraner-Piratenfrachter 300 Tonnen, für 6 Container á 50t | 26
SI_PIRATE_3X100T_HUMAN | Terraner-Piratenfrachter 300 Tonnen, für 3 Container á 100t | 27
SI_PIRATE_2X200T_HUMAN | Terraner-Piratenfrachter 400 Tonnen, für 2 Container á 200t | 28
SI_PIRATE_8X100T_HUMAN | Terraner-Piratenfrachter 800 Tonnen, für 8 Container á 100t | 29
SI_PIRATE_4X200T_HUMAN | Terraner-Piratenfrachter 800 Tonnen, für 4 Container á 200t | 30
SI_PIRATE_6X200T_HUMAN | Terraner-Piratenfrachter 1200 Tonnen, für 6 Container á 200t | 31
SI_PIRATE_8X200T_HUMAN | Terraner-Piratenfrachter 1600 Tonnen, für 8 Container á 200t | 32
SI_PIRATE_2X50T_MORTOK | Mortok-Piratenfrachter 100 Tonnen, für 2 Container á 50t | 33
SI_PIRATE_3X50T_MORTOK | Mortok-Piratenfrachter 150 Tonnen, für 3 Container á 50t | 34
SI_PIRATE_6X50T_MORTOK | Mortok-Piratenfrachter 300 Tonnen, für 6 Container á 50t | 35
SI_PIRATE_3X100T_MORTOK | Mortok-Piratenfrachter 300 Tonnen, für 3 Container á 100t | 36
SI_PIRATE_2X200T_MORTOK | Mortok-Piratenfrachter 400 Tonnen, für 2 Container á 200t | 37
SI_PIRATE_8X100T_MORTOK | Mortok-Piratenfrachter 800 Tonnen, für 8 Container á 100t | 38
SI_PIRATE_4X200T_MORTOK | Mortok-Piratenfrachter 800 Tonnen, für 4 Container á 200t | 39
SI_PIRATE_6X200T_MORTOK | Mortok-Piratenfrachter 1200 Tonnen, für 6 Container á 200t | 40
SI_PIRATE_8X200T_MORTOK | Mortok-Piratenfrachter 1600 Tonnen, für 8 Container á 200t | 41
SI_PIRATE_3X50T_RAPTOR | Raptor-Piratenfrachter 150 Tonnen, für 3 Container á 50t | 42
SI_PIRATE_3X100T_RAPTOR | Raptor-Piratenfrachter 300 Tonnen, für 3 Container á 100t | 43
SI_PIRATE_4X200T_RAPTOR | Raptor-Piratenfrachter 800 Tonnen, für 4 Container á 200t | 44
SI_PIRATE_3X50T_OCTO | Oc’to-Piratenfrachter 150 Tonnen, für 3 Container á 50t | 45
SI_PIRATE_3X100T_OCTO | Oc’to-Piratenfrachter 300 Tonnen, für 3 Container á 100t | 46
SI_PIRATE_4X200T_OCTO | Oc’to-Piratenfrachter 800 Tonnen, für 4 Container á 200t | 47
SI_PIRATE_3X50T_ARRACK | Arrack-Piratenfrachter 150 Tonnen, für 3 Container á 50t | 48
SI_PIRATE_3X100T_ARRACK | Arrack-Piratenfrachter 300 Tonnen, für 3 Container á 100t | 49
SI_PIRATE_4X200T_ARRACK | Arrack-Piratenfrachter 800 Tonnen, für 4 Container á 200t | 50
SI_PIRATE_3X50T_THUL | Thul-Piratenfrachter 150 Tonnen, für 3 Container á 50t | 51
SI_PIRATE_3X100T_THUL | Thul-Piratenfrachter 300 Tonnen, für 3 Container á 100t | 52
SI_PIRATE_4X200T_THUL | Thul-Piratenfrachter 800 Tonnen, für 4 Container á 200t | 53
zur Übersicht

Geleitschutz- und Kopfgeldjäger SPACE_HUNTER
Konstante | Kommentar | Wert
SI_HUNTER_HUMAN | Geleitschutzjäger der Terraner, Typ 1 mit einem Triebwerk | 0
SI_HUNTER_MORTOK | Geleitschutzjäger der Mortok | 1
SI_HUNTER_RAPTOR | Geleitschutzjäger der Raptor | 2
SI_HUNTER_OCTO | Geleitschutzjäger der Oc’to | 3
SI_HUNTER_ARRACK | Geleitschutzjäger der Arrack | 4
SI_HUNTER_THUL | Geleitschutzjäger der Thul | 5
SI_HUNTER2_HUMAN | Geleitschutzjäger der Terraner, Typ 2 mit zwei Triebwerken | 6
SI_HUNTER_SKAA | S’kaadrohne | 7
SI_HUNTER_1704 | Wie HUNTER_HUMAN, doppelte Hitpoints und Schildstärke * | 8
SI_HUNTER2_1704 | Wie HUNTER2_HUMAN, doppelte Hitpoints und Schildstärke * | 9
* Der StarShip.ini neu hinzugefügt.
zur Übersicht

Militärjäger SPACE_MILITARY
Konstante | Kommentar | Wert
SI_MILITARY_HUMAN | Militärjäger der Terraner | 0
SI_MILITARY_MORTOK | Militärjäger der Mortok | 1
SI_MILITARY_RAPTOR | Militärjäger der Raptor | 2
SI_MILITARY_OCTO | Militärjäger der Oc’to | 3
SI_MILITARY_ARRACK | Militärjäger der Arrack | 4
SI_MILITARY_THUL | Militärjäger der Thul | 5
zur Übersicht

Piratenjäger SPACE_PIRATE
Konstante | Kommentar | Wert
SI_PIRATE_HUMAN | Piratenjäger der Terraner, Typ 1 mit einem Triebwerk | 0
SI_PIRATE_MORTOK | Piratenjäger der Mortok | 1
SI_PIRATE_RAPTOR | Piratenjäger der Raptor | 2
SI_PIRATE_OCTO | Piratenjäger der Oc’to | 3
SI_PIRATE_ARRACK | Piratenjäger der Arrack | 4
SI_PIRATE_THUL | Piratenjäger der Thul | 5
SI_PIRATE2_HUMAN | Piratenjäger der Terraner, Typ 2 mit zwei Triebwerken | 6
zur Übersicht

Polizeijäger SPACE_POLICE
Konstante | Kommentar | Wert
SI_POLICE_HUMAN | Polizeijäger der Terraner | 0
SI_POLICE_MORTOK | Polizeijäger der Mortok | 1
SI_POLICE_RAPTOR | Polizeijäger der Raptor | 2
SI_POLICE_OCTO | Polizeijäger der Oc’to | 3
SI_POLICE_ARRACK | Polizeijäger der Arrack | 4
SI_POLICE_THUL | Polizeijäger der Thul | 5
zur Übersicht

Kreuzer SPACE_CRUISER
Konstante | Kommentar | Wert
SI_CRUISER2_HUMAN | Kleiner Kreuzer der Terraner | 0
SI_CRUISER1_HUMAN | Großer Kreuzer der Terraner | 1
SI_CRUISER2_MORTOK | Kleiner Kreuzer der Mortok | 2
SI_CRUISER1_MORTOK | Großer Kreuzer der Mortok | 3
SI_CRUISER1_RAPTOR | Großer Kreuzer der Raptor | 4
SI_CRUISER2_RAPTOR | Kleiner Kreuzer der Raptor | 5
SI_CRUISER2_OCTO | Kleiner Kreuzer der Oc’to | 6
SI_CRUISER1_OCTO | Großer Kreuzer der Oc’to | 7
SI_CRUISER2_ARRACK | Kleiner Kreuzer der Arrack | 8
SI_CRUISER1_ARRACK | Großer Kreuzer der Arrack | 9
SI_CRUISER2_THUL | Kleiner Kreuzer der Thul | 10
SI_CRUISER1_THUL | Großer Kreuzer der Thul | 11
SI_CRUISER2_SKAA | Kleiner Kreuzer der S’kaa (Mutterschiff) | 12
SI_CRUISER1_SKAA | Großer Kreuzer der S’kaa* | 13
* Der StarShip.ini mit dem doppelten Rumpfwert HitpointFactor = 48 neu hinzugefügt.
Der Wert NationObjectId = 0 darf aber nicht wie bei den anderen großen Kreuzern auf 1 gesetzt werden, sonst Absturz!
zur Übersicht

Piratenbasis mit 12 Geschütztürmen SPACE_HIDEOUT
Konstante | Kommentar | Wert
SI_PIRATEBASE_HUMAN | Piratenbasis (Versteck) der Terraner | 0
SI_PIRATEBASE_MORTOK | Piratenbasis (Versteck) der Mortok | 1
SI_PIRATEBASE_RAPTOR | Piratenbasis (Versteck) der Raptor | 2
SI_PIRATEBASE_OCTO | Piratenbasis (Versteck) der Oc’to | 3
SI_PIRATEBASE_ARRACK | Piratenbasis (Versteck) der Arrack | 4
SI_PIRATEBASE_THUL | Piratenbasis (Versteck) der Thul | 5
SI_PIRATEBASE_SKAA | Piratenbasis (Versteck) der S’kaa, S’kaadrill, 4-fache Stabilität * | 6
SI_PIRATEBASE_1704 | Piratenbasis (Versteck) der 1704, Laser, doppelte Stabilität * | 7
zur Übersicht

Playerturrets (Flak) SPACE_PLAYERTURRET
Konstante | Kommentar | Wert
SI_TURRET_HUMAN | Playerturret der Terraner | 0
SI_TURRET_MORTOK | Playerturret der Mortok | 1
SI_TURRET_RAPTOR | Playerturret der Raptor | 2
SI_TURRET_OCTO | Playerturret der Oc’to | 3
SI_TURRET_ARRACK | Playerturret der Arrack | 4
SI_TURRET_THUL | Playerturret der Thul | 5
zur Übersicht

Kommunikations-Satelliten SPACE_COMMSAT
Konstante | Kommentar | Wert
SI_SAT_HUMAN | Satellit der Terraner, bestückt mit zwei Laser-Geschütztürmen | 0
SI_SAT_MORTOK | Satellit der Mortok, bestückt mit zwei Railgun-Geschütztürmen | 1
SI_SAT_RAPTOR | Satellit der Raptor, bestückt mit zwei Ionenkanonen-Geschütztürmen | 2
SI_SAT_OCTO | Satellit der Oc’to, bestückt mit zwei Schallkanonen-Geschütztürmen | 3
SI_SAT_ARRACK | Satellit der Arrack, bestückt mit zwei Sporenkanonen-Geschütztürmen | 4
SI_SAT_THUL | Satellit der Thul, bestückt mit zwei Photonenkanonen-Geschütztürmen | 5
SI_SAT_SKAA | Satellit der S’kaa, bestückt mit zwei unsichtbaren S’kaadrills * | 6
SI_SAT_1704 | Satellit der 1704, bestückt mit zwei Laser-Geschütztürmen * | 7
Satelliten können mit "NWing.Define" nicht erzeugt werden.
zur Übersicht

Schildgeneratoren SPACE_SHIELDGEN
Konstante | Kommentar | Wert
SI_GEN_CANYON | Der Generator im Canyon (Kabro, erste Tunnelmission) | 0
SI_GEN_BLUE | Blauer Generator in der Waffenfabrik | 1
SI_GEN_RED | Roter Generator in der Waffenfabrik | 2
SI_GEN_GREEN | Grüner Generator in der Waffenfabrik | 3
SI_GEN_SKAA | Ein Generator im S’kaa-Tunnel | 4
SI_GEN_SKAACORE | Der Hauptreaktor des S’kaa-Mutterschiffs | 5
zur Übersicht

S’kaa-Schwarm SPACE_SKAASWARM
Konstante | Kommentar | Wert
SI_SKAA | Die S’kaadrohnen-Formation | 0
zur Übersicht

Handelsstationen SPACE_STATION
Konstante | Kommentar | Wert
SI_STATION_3DOCKS | Station mit 3 Frachterdocks | 0
SI_STATION_4DOCKS | Station mit 4 Frachterdocks | 1
zur Übersicht

Taxi (Shuttles) SPACE_TAXI
Konstante | Kommentar | Wert
SI_TAXI_HUMAN | Transport-Shuttle der Terraner | 0
SI_TAXI_MORTOK | Transport-Shuttle der Mortok | 1
SI_TAXI_RAPTOR | Transport-Shuttle der Raptor | 2
SI_TAXI_OCTO | Transport-Shuttle der Oc’to | 3
SI_TAXI_ARRACK | Transport-Shuttle der Arrack | 4
SI_TAXI_THUL | Transport-Shuttle der Thul | 5
zur Übersicht

Waffenplattformen SPACE_WEAPONBASE
Konstante | Kommentar | Wert
SI_WEAPONBASE1_HUMAN | Waffenplattform der Terraner mit einem Laser-Geschützturm | 0
SI_WEAPONBASE2_HUMAN | Waffenplattform der Terraner mit zwei Laser-Geschütztürmen | 1
SI_WEAPONBASE1_MORTOK | Waffenplattform der Mortok mit einem Railgun-Geschützturm | 2
SI_WEAPONBASE2_MORTOK | Waffenplattform der Mortok mit zwei Railgun-Geschütztürmen | 3
SI_WEAPONBASE1_RAPTOR | Waffenplattform der Raptor mit einem Phaser-Geschützturm | 4
SI_WEAPONBASE2_RAPTOR | Waffenplattform der Raptor mit zwei Phaser-Geschütztürmen | 5
SI_WEAPONBASE1_OCTO | Waffenplattform der Oc’to mit einem Graviton-Geschützturm | 6
SI_WEAPONBASE2_OCTO | Waffenplattform der Oc’to mit zwei Graviton-Geschütztürmen | 7
SI_WEAPONBASE1_ARRACK | Waffenplattform der Arrack mit einem Energieprojektil-Geschützturm | 8
SI_WEAPONBASE2_ARRACK | Waffenplattform der Arrack mit zwei Energieprojektil-Geschütztürmen | 9
SI_WEAPONBASE1_THUL | Waffenplattform der Thul mit einem Photonen-Geschützturm | 10
SI_WEAPONBASE2_THUL | Waffenplattform der Thul mit zwei Photonen-Geschütztürmen | 11
SI_WEAPONBASE1_SKAA | Waffenplattform der S’kaa mit einem unsichtbaren S’kaadrill * | 12
SI_WEAPONBASE2_SKAA | Waffenplattform der S’kaa mit zwei unsichtbaren S’kaadrills * | 13
SI_WEAPONBASE1_1704 | Waffenplattform der 1704 mit einem Laser-Geschützturm * | 14
SI_WEAPONBASE2_1704 | Waffenplattform der 1704 mit zwei Laser-Geschütztürmen * | 15
* Der StarShip.ini mit dem doppelten bzw. vierfachen Rumpfwert neu hinzugefügt.
zur Übersicht


StarSystems

Sternsysteme und Cluster

Gehe zum ersten System mit: A B C D E F G H I J K L M N O P R S T U V W Y Z (rechte Liste)

  • Namen und IDs der Cluster
  • Sichtbarkeitsklassen
  • Sternsysteme mit Tech-Level 10

Sternsysteme

Eine Liste mit den Namen und System-IDs aller 403 Sternsysteme in Darkstar One
====== Sortiert nach System-Id ====== ===== Sortiert nach Systemname =====
SystemId | Systemname | Cluster
0 | Witon | Lalande
1 | Cloosa | Lalande
2 | Weca | Lalande
3 | Pecola | Lalande
4 | Obas | Lalande
5 | Hu | Lalande
6 | Yankni | Lalande
7 | Natshorim | Lalande
8 | Pencah | Lalande
9 | Athasho | Lalande
10 | Yarie | Lalande
11 | Pachee | Lalande
12 | Patorwalla | Barnard
13 | Kalima | Barnard
14 | Zuos | Barnard
15 | Tanee | Barnard
16 | Metharon | Barnard
17 | Mesehkane | Barnard
18 | Anomi | Barnard
19 | Ta | Barnard
20 | Oma | Tau Ceti
21 | Tasakane | Tau Ceti
22 | Patiak | Tau Ceti
23 | Ote | Tau Ceti
24 | Taba | Tau Ceti
25 | Zuoria | Tau Ceti
26 | Echee | Alpha Centauri
27 | Page | Alpha Centauri
28 | Yankwalla | Alpha Centauri
29 | Sol | Alpha Centauri
30 | Spocheewalla | Alpha Centauri
31 | Pani | Alpha Centauri
32 | Keoshotu | Alpha Centauri
33 | Waba | Alpha Centauri
34 | Shoma | Alpha Centauri
35 | Parim | Alpha Centauri
36 | Wini | Alpha Centauri
37 | Yankton | Alpha Centauri
38 | Ete | Alpha Centauri
39 | Witha | Alpha Centauri
40 | Teha | Alpha Centauri
41 | Sassudia | Grotok
42 | Baylona | Grotok
43 | Albadiz | Grotok
44 | Masba | Grotok
45 | Alarluz | Grotok
46 | Neplocruz | Grotok
47 | Lugoferra | Grotok
48 | Arroscola | Grotok
49 | Albola | Grotok
50 | Lucia | Grotok
51 | Alegenla | Grotok
52 | Matada | Grotok
53 | Aranjar | Grotok
54 | Rubiro | Grotok
55 | Camvilje | Grotok
56 | Mandedulce | Grotok
57 | Lular | Grotok
58 | Alfabalas | Grotok
59 | Bramurcia | Grotok
60 | Martotacon | Grotok
61 | Naro | Grotok
62 | Eicete | Pertok
63 | Arotorracin | Pertok
64 | Rulote | Pertok
65 | Rocete | Pertok
66 | Alaniz | Pertok
67 | Cavcala | Pertok
68 | Biarnar | Pertok
69 | Sarzar | Stromok
70 | Arber | Stromok
71 | Cabracoy | Stromok
72 | Capella | Stromok
73 | Alsavia | Stromok
74 | Majarin | Stromok
75 | Lucero | Stromok
76 | Adeviegar | Stromok
77 | Rusiefes | Stromok
78 | Manorciras | Stromok
79 | Haorta | Stromok
80 | Telbeigro | Stromok
81 | Anmansa | Stromok
82 | Arromazan | Stromok
83 | Risafes | Stromok
84 | Pinzar | Stromok
85 | Lorbeisua | Stromok
86 | Sorfulla | Stromok
87 | Cenposta | Stromok
88 | Odia | Stromok
89 | Biardorra | Klatok
90 | Sarbrejar | Klatok
91 | Ferreriquera | Klatok
92 | Petevegua | Klatok
93 | Grajuez | Klatok
94 | Argozazu | Klatok
95 | Aychena | Klatok
96 | Albocos | Klatok
97 | Miganda | Klatok
98 | Vielvietona | Klatok
99 | Aguamaniz | Klatok
100 | Siedillo | Klatok
101 | Cuendo | Klatok
102 | Horcruz | Klatok
103 | Cazviecife | Klatok
104 | Fuenxadas | Klatok
105 | Alquebayo | Klatok
106 | Ubeties | Klatok
107 | Mostorga | Klatok
108 | Bielturias | Klatok
109 | Altazaarfe | Klatok
110 | Avilmurcia | Klatok
111 | Fribeicon | Klatok
112 | Tero | Klatok
113 | Fuenbocete | Klatok
114 | Camrracin | Klatok
115 | Agualote | Humok
116 | Rodia | Humok
117 | Zaniz | Humok
118 | Cadacala | Humok
119 | Eitanar | Humok
120 | Canniozar | Humok
121 | Antetaber | Humok
122 | Vipacoy | Humok
123 | Cesella | Humok
124 | Manzahuvia | Humok
125 | Arnelajarin | Humok
126 | Alsaro | Humok
127 | Fresgar | Humok
128 | Zhusomol | Raptor Alpha
129 | Nostromo | Raptor Alpha
130 | Teirov | Raptor Alpha
131 | Tamburg | Raptor Alpha
132 | Lysmir | Raptor Alpha
133 | Borriev | Raptor Nova
134 | Zapul | Raptor Nova
135 | Goro | Raptor Nova
136 | Brakann | Raptor Nova
137 | Mynok | Raptor Nova
138 | Vidal | Raptor Nova
139 | Komkannmir | Raptor Nova
140 | Zareck | Raptor Nova
141 | Nizbin | Raptor Nova
142 | Eletsmir | Raptor Nova
143 | Khimzan | Raptor Nova
144 | Bogojol | Raptor Nova
145 | Kosrod | Raptor Nova
146 | Bogozan | Raptor Gamma
147 | Schel | Raptor Gamma
148 | Chernomen | Raptor Gamma
149 | Mana | Raptor Gamma
150 | Malopul | Raptor Gamma
151 | Suzga | Raptor Gamma
152 | Eletssk | Raptor Gamma
153 | Kostrono | Raptor Gamma
154 | Balasom | Raptor Gamma
155 | Desno | Raptor Gamma
156 | Goronezh | Raptor Gamma
157 | Twerkano | Raptor Gamma
158 | Simcow | Raptor Gamma
159 | Nakhod | Raptor Gamma
160 | Murnij | Raptor Gamma
161 | Vidlukau | Raptor Gamma
162 | Celna | Raptor Gamma
163 | Yarosny | Raptor Gamma
164 | Zelenonezh | Raptor Gamma
165 | Mornamur | Raptor Gamma
166 | Tjuma | Raptor Gamma
167 | Sakaterin | Raptor Gamma
168 | Chakin | Raptor Gamma
169 | Abariev | Raptor Gamma
170 | Oren | Raptor Gamma
171 | Archangelsk | Raptor Delta
172 | Nakhodlu | Raptor Delta
173 | Koro | Raptor Delta
174 | Chanschat | Raptor Delta
175 | Saraschat | Raptor Delta
176 | Jegutna | Raptor Delta
177 | Morkann | Raptor Delta
178 | Toggrad | Raptor Delta
179 | Amkovo | Raptor Epsilon
180 | Kaschi | Raptor Epsilon
181 | Penol | Raptor Epsilon
182 | Nizpul | Raptor Epsilon
183 | Simpawlo | Raptor Epsilon
184 | Charodpul | Raptor Epsilon
185 | Abanaul | Raptor Epsilon
186 | Beldets | Raptor Epsilon
187 | Perekin | Raptor Epsilon
188 | Khimtishy | Raptor Epsilon
189 | Petrokau | Raptor Epsilon
190 | Permnaja | Raptor Epsilon
191 | Desnodal | Raptor Epsilon
192 | Ken'ore | Sion'nach
193 | Rhilo'chan | Sion'nach
194 | Gans'clie | Sion'nach
195 | Li'atrie | Sion'nach
196 | Ca'ore | Sion'nach
197 | Kil'ore | Sion'nach
198 | Gallt'air | Sion'nach
199 | Lon'ore | Sion'nach
200 | Abria'chan | Sion'nach
201 | Ann'at | Sion'nach
202 | Kill'ate | Sion'nach
203 | L'air | Sion'nach
204 | Coill'ore | Sion'nach
205 | Mechez | Sirius
206 | Wichita | Sirius
207 | Ozurim | Sirius
208 | Wama | Sirius
209 | Tezutiak | Sirius
210 | Witeni | Sirius
211 | Wica | Sirius
212 | Ponniseh | Sirius
213 | Wallawalla | Sirius
214 | Patu | Sirius
215 | Yaha | Sirius
216 | Wenee | Sirius
217 | Cloma | Sirius
218 | Zute | Sirius
219 | Pazuspell | Sirius
220 | Lochcar'ron | Madra'mor
221 | Am'atn'atua | Madra'mor
222 | Ach'air | Madra'mor
223 | Ad'vie | Madra'mor
224 | B'rochel | Madra'mor
225 | Sliga'chan | Madra'mor
226 | Dochgar'roch | Madra'mor
227 | Bena'vie | Madra'mor
228 | Boath'vic | Madra'mor
229 | Bara'ore | Madra'mor
230 | Lyn'ore | Madra'mor
231 | D'ores | Madra'mor
232 | A'chill | Madra'mor
233 | Loth'ore | Madra'mor
234 | Drum'unie | Madra'mor
235 | Ardmo'lich | Madra'mor
236 | Ardar'roch | Madra'mor
237 | Skullo'mie | Madra'mor
238 | Achnab'at | Madra'mor
239 | Garty'ore | Madra'mor
240 | Lyn'chat | Madra'mor
241 | C'atlodge | Madra'mor
242 | Tor'ore | Prea'chan
243 | Tul'lich | Prea'chan
244 | Ach'ore | Prea'chan
245 | Bal'ore | Prea'chan
246 | Kinloch'ore | Prea'chan
247 | Led'ore | Prea'chan
248 | Ormsaig'nie | Prea'chan
249 | Lyne'ore | Prea'chan
250 | Garb'at | Prea'chan
251 | Dalmiga'vie | Prea'chan
252 | Sana'chan | Prea'chan
253 | Achvaras'dal | Prea'chan
254 | Slie'ore | Prea'chan
255 | Olgrin'nie | Prea'chan
256 | Arpafee'lie | Prea'chan
257 | Sh'oreton | Prea'chan
258 | Shovis | Ross 128
259 | Yate | Ross 128
260 | Penchi | Ross 128
261 | Eosa | Ross 128
262 | Pontiac | Ross 128
263 | Tenatori | Ross 128
264 | Omatu | Ross 128
265 | Ardul'lie | Bear'mor
266 | D'unie | Bear'mor
267 | Sc'atraig | Bear'mor
268 | Al'vie | Bear'mor
269 | Glen'ore | Bear'mor
270 | Sona'chan | Gab'har
271 | Tar'vie | Gab'har
272 | Lairg'uie | Gab'har
273 | Newton'ore | Gab'har
274 | Lone'ron | Gab'har
275 | Lairin'vie | Gab'har
276 | Sc'atwell | Gab'har
277 | Sort'at | Gab'har
278 | Linside'ore | Gab'har
279 | Tom'atin | Gab'har
280 | Archrea'mie | Gab'har
281 | Bad'aul | Gab'har
282 | Clash'ore | Gab'har
283 | L'athe'ron | Gab'har
284 | Achnas'aul | Gab'har
285 | Rhe'ore | Gab'har
286 | Insh'ore | Gab'har
287 | Bin'dal | Gab'har
288 | Dunb'ath | Gab'har
289 | Altand'uin | Gab'har
290 | Dalna'vie | Gab'har
291 | Achand'unie | Gab'har
292 | Ard'ore | Gab'har
293 | Badic'aul | Gab'har
294 | Pachaung | Hive-AC3
295 | Pyidaung | Hive-AC3
296 | Gaungbwa | Hive-AC3
297 | Laikuku | Hive-AC3
298 | Zajatpyu | Hive-AC3
299 | Aingya | Hive-AC3
300 | Hulaung | Hive-AC3
301 | Mingin | Hive-AC3
302 | Tamaung | Hive-AC3
303 | Inwaing | Hive-AC3
304 | Sinkwe | Hive-AC3
305 | Honnaing | Hive-AC3
306 | Shwege | Hive-AC3
307 | Tinmaung | Hive-AC3
308 | Kinzan | Hive-AC3
309 | Haiken | Hive-AC3
310 | Natkyigon | Hive-AC3
311 | Ascarong | Hive-AC3
312 | Wakkai | Hive-AC3
313 | Uyin | Hive-F17
314 | Lakai | Hive-F17
315 | Yagyat | Hive-F17
316 | Sinbyuchi | Hive-F17
317 | Zanabok | Hive-F17
318 | Kujung | Hive-F17
319 | Kindat | Hive-F17
320 | Wegyaung | Hive-F17
321 | Songon | Hive-F17
322 | Yalagaung | Hive-F17
323 | Rankse | Hive-F17
324 | Changrang | Hive-F17
325 | Ngobin | Hive-F17
326 | Sainolin | Hive-CU7
327 | Wetluaing | Hive-CU7
328 | Kandaya | Hive-CU7
329 | Myaunggon | Hive-CU7
330 | Ringhku | Hive-CU7
331 | Molin | Hive-CU7
332 | Kindaung | Hive-CU7
333 | Ingynbin | Hive-CU7
334 | Wadan | Hive-CU7
335 | Mayinlon | Hive-CU7
336 | Lewingon | Hive-CU7
337 | Kindaw | Hive-CU7
338 | Aingdama | Hive-CU7
339 | Kinmin | Hive-CU7
340 | Ngakin | Hive-B52
341 | Shanzeik | Hive-B52
342 | Maleindon | Hive-B52
343 | Minshwe | Hive-B52
344 | Chanthagon | Hive-DC
345 | Chaing | Hive-DC
346 | Thidaya | Hive-DC
347 | Pindon | Hive-DC
348 | Tegyigon | Hive-DC
349 | Pegin | Hive-DC
350 | Segin | Hive-DC
351 | Sibingwe | Hive-DC
352 | Atet | Hive-DC
353 | Ekyigon | Hive-DC
354 | Mepok | Hive-DC
355 | Sagon | Hive-DC
356 | Beinn | Hive-DC
357 | Magyibok | Hive-DC
358 | Sagagon | Hive-DC
359 | Yama | Hive-DC
360 | Nepaling | Hive-ET9
361 | Letpan | Hive-ET9
362 | Kamaing | Hive-ET9
363 | Bonchaung | Hive-ET9
364 | Chondrha | Hive-ET9
365 | Khopyin | Hive-ET9
366 | Katpanbok | Hive-ET9
367 | Binga | Hive-ET9
368 | Pantok | Hive-G8
369 | Pagandi | Hive-G8
370 | Daingnat | Hive-G8
371 | Lethagon | Hive-G8
372 | Gamnim | Hive-G8
373 | Shwebangon | Hive-G8
374 | Bao | Hive-G8
375 | Obingon | Hive-G8
376 | Thabyedaw | Hive-G8
377 | Yedaw | Hive-G8
378 | Bailebeag | Communa
379 | Achintraid | Communa
380 | Clachtoll | Communa
381 | Inchlaggan | Communa
382 | Dalmigavie | Communa
383 | Ramasaig | Communa
384 | Faebait | Communa
385 | Aberloch | Communa
386 | Eilanreach | Communa
387 | Aberchald | Communa
388 | Pitcalnie | Communa
389 | Ormiscaig | Communa
390 | Glaschoil | Communa
391 | Cuidrach | Communa
392 | Keodale | Communa
393 | Ardarroch | Communa
394 | Fearnbeg | Communa
395 | Todhair | Communa
396 | Laggan | Hyma
397 | Dalchalm | Hyma
398 | Clayock | Hyma
399 | Dorusduain | Hyma
400 | Kajudeng | Hive-B52
401 | Metojang | Hive-B52
402 | Permakin | Raptor Delta

SystemId | Systemname | Cluster
185 | Abanaul | Raptor Epsilon
169 | Abariev | Raptor Gamma
387 | Aberchald | Communa
385 | Aberloch | Communa
200 | Abria'chan | Sion'nach
222 | Ach'air | Madra'mor
291 | Achand'unie | Gab'har
232 | A'chill | Madra'mor
379 | Achintraid | Communa
238 | Achnab'at | Madra'mor
284 | Achnas'aul | Gab'har
244 | Ach'ore | Prea'chan
253 | Achvaras'dal | Prea'chan
76 | Adeviegar | Stromok
223 | Ad'vie | Madra'mor
115 | Agualote | Humok
99 | Aguamaniz | Klatok
338 | Aingdama | Hive-CU7
299 | Aingya | Hive-AC3
66 | Alaniz | Pertok
45 | Alarluz | Grotok
43 | Albadiz | Grotok
96 | Albocos | Klatok
49 | Albola | Grotok
51 | Alegenla | Grotok
58 | Alfabalas | Grotok
105 | Alquebayo | Klatok
126 | Alsaro | Humok
73 | Alsavia | Stromok
289 | Altand'uin | Gab'har
109 | Altazaarfe | Klatok
268 | Al'vie | Bear'mor
221 | Am'atn'atua | Madra'mor
179 | Amkovo | Raptor Epsilon
81 | Anmansa | Stromok
201 | Ann'at | Sion'nach
18 | Anomi | Barnard
121 | Antetaber | Humok
53 | Aranjar | Grotok
70 | Arber | Stromok
171 | Archangelsk | Raptor Delta
280 | Archrea'mie | Gab'har
393 | Ardarroch | Communa
236 | Ardar'roch | Madra'mor
235 | Ardmo'lich | Madra'mor
292 | Ard'ore | Gab'har
265 | Ardul'lie | Bear'mor
94 | Argozazu | Klatok
125 | Arnelajarin | Humok
63 | Arotorracin | Pertok
256 | Arpafee'lie | Prea'chan
82 | Arromazan | Stromok
48 | Arroscola | Grotok
311 | Ascarong | Hive-AC3
352 | Atet | Hive-DC
9 | Athasho | Lalande
110 | Avilmurcia | Klatok
95 | Aychena | Klatok
281 | Bad'aul | Gab'har
293 | Badic'aul | Gab'har
378 | Bailebeag | Communa
154 | Balasom | Raptor Gamma
245 | Bal'ore | Prea'chan
374 | Bao | Hive-G8
229 | Bara'ore | Madra'mor
42 | Baylona | Grotok
356 | Beinn | Hive-DC
186 | Beldets | Raptor Epsilon
227 | Bena'vie | Madra'mor
89 | Biardorra | Klatok
68 | Biarnar | Pertok
108 | Bielturias | Klatok
287 | Bin'dal | Gab'har
367 | Binga | Hive-ET9
228 | Boath'vic | Madra'mor
144 | Bogojol | Raptor Nova
146 | Bogozan | Raptor Gamma
363 | Bonchaung | Hive-ET9
133 | Borriev | Raptor Nova
136 | Brakann | Raptor Nova
59 | Bramurcia | Grotok
224 | B'rochel | Madra'mor
71 | Cabracoy | Stromok
118 | Cadacala | Humok
114 | Camrracin | Klatok
55 | Camvilje | Grotok
120 | Canniozar | Humok
196 | Ca'ore | Sion'nach
72 | Capella | Stromok
241 | C'atlodge | Madra'mor
67 | Cavcala | Pertok
103 | Cazviecife | Klatok
162 | Celna | Raptor Gamma
87 | Cenposta | Stromok
123 | Cesella | Humok
345 | Chaing | Hive-DC
168 | Chakin | Raptor Gamma
324 | Changrang | Hive-F17
174 | Chanschat | Raptor Delta
344 | Chanthagon | Hive-DC
184 | Charodpul | Raptor Epsilon
148 | Chernomen | Raptor Gamma
364 | Chondrha | Hive-ET9
380 | Clachtoll | Communa
282 | Clash'ore | Gab'har
398 | Clayock | Hyma
217 | Cloma | Sirius
1 | Cloosa | Lalande
204 | Coill'ore | Sion'nach
101 | Cuendo | Klatok
391 | Cuidrach | Communa
370 | Daingnat | Hive-G8
397 | Dalchalm | Hyma
382 | Dalmigavie | Communa
251 | Dalmiga'vie | Prea'chan
290 | Dalna'vie | Gab'har
155 | Desno | Raptor Gamma
191 | Desnodal | Raptor Epsilon
226 | Dochgar'roch | Madra'mor
231 | D'ores | Madra'mor
399 | Dorusduain | Hyma
234 | Drum'unie | Madra'mor
288 | Dunb'ath | Gab'har
266 | D'unie | Bear'mor
26 | Echee | Alpha Centauri
62 | Eicete | Pertok
386 | Eilanreach | Communa
119 | Eitanar | Humok
353 | Ekyigon | Hive-DC
142 | Eletsmir | Raptor Nova
152 | Eletssk | Raptor Gamma
261 | Eosa | Ross 128
38 | Ete | Alpha Centauri
384 | Faebait | Communa
394 | Fearnbeg | Communa
91 | Ferreriquera | Klatok
127 | Fresgar | Humok
111 | Fribeicon | Klatok
113 | Fuenbocete | Klatok
104 | Fuenxadas | Klatok
198 | Gallt'air | Sion'nach
372 | Gamnim | Hive-G8
194 | Gans'clie | Sion'nach
250 | Garb'at | Prea'chan
239 | Garty'ore | Madra'mor
296 | Gaungbwa | Hive-AC3
390 | Glaschoil | Communa
269 | Glen'ore | Bear'mor
135 | Goro | Raptor Nova
156 | Goronezh | Raptor Gamma
93 | Grajuez | Klatok
309 | Haiken | Hive-AC3
79 | Haorta | Stromok
305 | Honnaing | Hive-AC3
102 | Horcruz | Klatok
5 | Hu | Lalande
300 | Hulaung | Hive-AC3
381 | Inchlaggan | Communa
333 | Ingynbin | Hive-CU7
286 | Insh'ore | Gab'har
303 | Inwaing | Hive-AC3
176 | Jegutna | Raptor Delta
400 | Kajudeng | Hive-B52
13 | Kalima | Barnard
362 | Kamaing | Hive-ET9
328 | Kandaya | Hive-CU7
180 | Kaschi | Raptor Epsilon
366 | Katpanbok | Hive-ET9
192 | Ken'ore | Sion'nach
392 | Keodale | Communa
32 | Keoshotu | Alpha Centauri
188 | Khimtishy | Raptor Epsilon
143 | Khimzan | Raptor Nova
365 | Khopyin | Hive-ET9
202 | Kill'ate | Sion'nach
197 | Kil'ore | Sion'nach
319 | Kindat | Hive-F17
332 | Kindaung | Hive-CU7
337 | Kindaw | Hive-CU7
246 | Kinloch'ore | Prea'chan
339 | Kinmin | Hive-CU7
308 | Kinzan | Hive-AC3
139 | Komkannmir | Raptor Nova
173 | Koro | Raptor Delta
145 | Kosrod | Raptor Nova
153 | Kostrono | Raptor Gamma
318 | Kujung | Hive-F17
396 | Laggan | Hyma
297 | Laikuku | Hive-AC3
203 | L'air | Sion'nach
272 | Lairg'uie | Gab'har
275 | Lairin'vie | Gab'har
314 | Lakai | Hive-F17
283 | L'athe'ron | Gab'har
247 | Led'ore | Prea'chan
371 | Lethagon | Hive-G8
361 | Letpan | Hive-ET9
336 | Lewingon | Hive-CU7
195 | Li'atrie | Sion'nach
278 | Linside'ore | Gab'har
220 | Lochcar'ron | Madra'mor
274 | Lone'ron | Gab'har
199 | Lon'ore | Sion'nach
85 | Lorbeisua | Stromok
233 | Loth'ore | Madra'mor
75 | Lucero | Stromok
50 | Lucia | Grotok
47 | Lugoferra | Grotok
57 | Lular | Grotok
240 | Lyn'chat | Madra'mor
249 | Lyne'ore | Prea'chan
230 | Lyn'ore | Madra'mor
132 | Lysmir | Raptor Alpha
357 | Magyibok | Hive-DC
74 | Majarin | Stromok
342 | Maleindon | Hive-B52
150 | Malopul | Raptor Gamma
149 | Mana | Raptor Gamma
56 | Mandedulce | Grotok
78 | Manorciras | Stromok
124 | Manzahuvia | Humok
60 | Martotacon | Grotok
44 | Masba | Grotok
52 | Matada | Grotok
335 | Mayinlon | Hive-CU7
205 | Mechez | Sirius
354 | Mepok | Hive-DC
17 | Mesehkane | Barnard
16 | Metharon | Barnard
401 | Metojang | Hive-B52
97 | Miganda | Klatok
301 | Mingin | Hive-AC3
343 | Minshwe | Hive-B52
331 | Molin | Hive-CU7
177 | Morkann | Raptor Delta
165 | Mornamur | Raptor Gamma
107 | Mostorga | Klatok
160 | Murnij | Raptor Gamma
329 | Myaunggon | Hive-CU7
137 | Mynok | Raptor Nova
159 | Nakhod | Raptor Gamma
172 | Nakhodlu | Raptor Delta
61 | Naro | Grotok
310 | Natkyigon | Hive-AC3
7 | Natshorim | Lalande
360 | Nepaling | Hive-ET9
46 | Neplocruz | Grotok
273 | Newton'ore | Gab'har
340 | Ngakin | Hive-B52
325 | Ngobin | Hive-F17
141 | Nizbin | Raptor Nova
182 | Nizpul | Raptor Epsilon
129 | Nostromo | Raptor Alpha
4 | Obas | Lalande
375 | Obingon | Hive-G8
88 | Odia | Stromok
255 | Olgrin'nie | Prea'chan
20 | Oma | Tau Ceti
264 | Omatu | Ross 128
170 | Oren | Raptor Gamma
389 | Ormiscaig | Communa
248 | Ormsaig'nie | Prea'chan
23 | Ote | Tau Ceti
207 | Ozurim | Sirius
294 | Pachaung | Hive-AC3
11 | Pachee | Lalande
369 | Pagandi | Hive-G8
27 | Page | Alpha Centauri
31 | Pani | Alpha Centauri
368 | Pantok | Hive-G8
35 | Parim | Alpha Centauri
22 | Patiak | Tau Ceti
12 | Patorwalla | Barnard
214 | Patu | Sirius
219 | Pazuspell | Sirius
3 | Pecola | Lalande
349 | Pegin | Hive-DC
8 | Pencah | Lalande
260 | Penchi | Ross 128
181 | Penol | Raptor Epsilon
187 | Perekin | Raptor Epsilon
402 | Permakin | Raptor Delta
190 | Permnaja | Raptor Epsilon
92 | Petevegua | Klatok
189 | Petrokau | Raptor Epsilon
347 | Pindon | Hive-DC
84 | Pinzar | Stromok
388 | Pitcalnie | Communa
212 | Ponniseh | Sirius
262 | Pontiac | Ross 128
295 | Pyidaung | Hive-AC3
383 | Ramasaig | Communa
323 | Rankse | Hive-F17
285 | Rhe'ore | Gab'har
193 | Rhilo'chan | Sion'nach
330 | Ringhku | Hive-CU7
83 | Risafes | Stromok
65 | Rocete | Pertok
116 | Rodia | Humok
54 | Rubiro | Grotok
64 | Rulote | Pertok
77 | Rusiefes | Stromok
358 | Sagagon | Hive-DC
355 | Sagon | Hive-DC
326 | Sainolin | Hive-CU7
167 | Sakaterin | Raptor Gamma
252 | Sana'chan | Prea'chan
175 | Saraschat | Raptor Delta
90 | Sarbrejar | Klatok
69 | Sarzar | Stromok
41 | Sassudia | Grotok
267 | Sc'atraig | Bear'mor
276 | Sc'atwell | Gab'har
147 | Schel | Raptor Gamma
350 | Segin | Hive-DC
341 | Shanzeik | Hive-B52
34 | Shoma | Alpha Centauri
257 | Sh'oreton | Prea'chan
258 | Shovis | Ross 128
373 | Shwebangon | Hive-G8
306 | Shwege | Hive-AC3
351 | Sibingwe | Hive-DC
100 | Siedillo | Klatok
158 | Simcow | Raptor Gamma
183 | Simpawlo | Raptor Epsilon
316 | Sinbyuchi | Hive-F17
304 | Sinkwe | Hive-AC3
237 | Skullo'mie | Madra'mor
254 | Slie'ore | Prea'chan
225 | Sliga'chan | Madra'mor
29 | Sol | Alpha Centauri
270 | Sona'chan | Gab'har
321 | Songon | Hive-F17
86 | Sorfulla | Stromok
277 | Sort'at | Gab'har
30 | Spocheewalla | Alpha Centauri
151 | Suzga | Raptor Gamma
19 | Ta | Barnard
24 | Taba | Tau Ceti
302 | Tamaung | Hive-AC3
131 | Tamburg | Raptor Alpha
15 | Tanee | Barnard
271 | Tar'vie | Gab'har
21 | Tasakane | Tau Ceti
348 | Tegyigon | Hive-DC
40 | Teha | Alpha Centauri
130 | Teirov | Raptor Alpha
80 | Telbeigro | Stromok
263 | Tenatori | Ross 128
112 | Tero | Klatok
209 | Tezutiak | Sirius
376 | Thabyedaw | Hive-G8
346 | Thidaya | Hive-DC
307 | Tinmaung | Hive-AC3
166 | Tjuma | Raptor Gamma
395 | Todhair | Communa
178 | Toggrad | Raptor Delta
279 | Tom'atin | Gab'har
242 | Tor'ore | Prea'chan
243 | Tul'lich | Prea'chan
157 | Twerkano | Raptor Gamma
106 | Ubeties | Klatok
313 | Uyin | Hive-F17
138 | Vidal | Raptor Nova
161 | Vidlukau | Raptor Gamma
98 | Vielvietona | Klatok
122 | Vipacoy | Humok
33 | Waba | Alpha Centauri
334 | Wadan | Hive-CU7
312 | Wakkai | Hive-AC3
213 | Wallawalla | Sirius
208 | Wama | Sirius
2 | Weca | Lalande
320 | Wegyaung | Hive-F17
216 | Wenee | Sirius
327 | Wetluaing | Hive-CU7
211 | Wica | Sirius
206 | Wichita | Sirius
36 | Wini | Alpha Centauri
210 | Witeni | Sirius
39 | Witha | Alpha Centauri
0 | Witon | Lalande
315 | Yagyat | Hive-F17
215 | Yaha | Sirius
322 | Yalagaung | Hive-F17
359 | Yama | Hive-DC
6 | Yankni | Lalande
37 | Yankton | Alpha Centauri
28 | Yankwalla | Alpha Centauri
10 | Yarie | Lalande
163 | Yarosny | Raptor Gamma
259 | Yate | Ross 128
377 | Yedaw | Hive-G8
298 | Zajatpyu | Hive-AC3
317 | Zanabok | Hive-F17
117 | Zaniz | Humok
134 | Zapul | Raptor Nova
140 | Zareck | Raptor Nova
164 | Zelenonezh | Raptor Gamma
128 | Zhusomol | Raptor Alpha
25 | Zuoria | Tau Ceti
14 | Zuos | Barnard
218 | Zute | Sirius

Aufzug

Cluster

Liste mit den Namen und Cluster-IDs der 30 Cluster in Darkstar One
==== Sortiert nach Cluster-Id ==== === Sortiert nach Clustername ===
ClusterId | Clustername
0 | Lalande (Terraner)
1 | Barnard (Terraner)
2 | Tau Ceti (Terraner)
3 | Alpha Centauri (Terraner)
4 | Grotok (Mortok)
5 | Pertok (Mortok)
6 | Stromok (Mortok)
7 | Klatok (Mortok)
8 | Humok (Mortok)
9 | Raptor Alpha (Raptor)
10 | Raptor Nova (Raptor)
11 | Raptor Gamma (Raptor)
12 | Raptor Delta (Raptor)
13 | Raptor Epsilon (Raptor)
14 | Sion'nach (Oc'to)
15 | Sirius (Terraner)
16 | Madra'mor (Oc'to)
17 | Prea'chan (Oc'to)
18 | Ross 128 (Terraner)
19 | Bear'mor (Oc'to)
20 | Gab'har (Oc'to)
21 | Hive-AC3 (Arrack)
22 | Hive-F17 (Arrack)
23 | Hive-CU7 (Arrack)
24 | Hive-B52 (Arrack)
25 | Hive-DC (Arrack)
26 | Hive-ET9 (Arrack)
27 | Hive-G8 (Arrack)
28 | Communa (Thul)
29 | Hyma (Thul)

ClusterId | Clustername
3 | Alpha Centauri (Terraner)
1 | Barnard (Terraner)
19 | Bear'mor (Oc'to)
28 | Communa (Thul)
20 | Gab'har (Oc'to)
4 | Grotok (Mortok)
21 | Hive-AC3 (Arrack)
24 | Hive-B52 (Arrack)
23 | Hive-CU7 (Arrack)
25 | Hive-DC (Arrack)
26 | Hive-ET9 (Arrack)
22 | Hive-F17 (Arrack)
27 | Hive-G8 (Arrack)
8 | Humok (Mortok)
29 | Hyma (Thul)
7 | Klatok (Mortok)
0 | Lalande (Terraner)
16 | Madra'mor (Oc'to)
5 | Pertok (Mortok)
17 | Prea'chan (Oc'to)
9 | Raptor Alpha (Raptor)
12 | Raptor Delta (Raptor)
13 | Raptor Epsilon (Raptor)
11 | Raptor Gamma (Raptor)
10 | Raptor Nova (Raptor)
18 | Ross 128 (Terraner)
14 | Sion'nach (Oc'to)
15 | Sirius (Terraner)
6 | Stromok (Mortok)
2 | Tau Ceti (Terraner)

Aufzug

Sichtbarkeit

Sichtbarkeitsklassen (für den StarFinder)
Konstante | Kommentar | Wert
STAR_UNLOCKED | Das System ist sichtbar und kann betreten werden | 0
STAR_MISSION | Missions-System | 1
STAR_SYSTEMKEY | Für das System darf ein Systemschlüssel vergeben werden | 2
STAR_GANGSYSTEM | Im System befindet sich eine Piratengang | 3

Aufzug

Sternsysteme mit Tech-Level 10

Sternsysteme, die Ausrüstungsgegenstände Klasse 10 zum Kauf anbieten
Cluster | Volk | Klasse 10 Sternsysteme
Lalande | Terraner | Obas, Pachee
Tau Ceti | Terraner | Ote
Alpha Centauri | Terraner | Wini
Grotok | Mortok | Aranjar, Lular, Mandedulce, Matada
Stromok | Mortok | Haorta
Klatok | Mortok | Alquebayo, Avilmurcia, Fribeicon, Vielvietona
Humok | Mortok | Cadacala
Raptor Gamma | Raptor | Chernomen, Schel
Raptor Epsilon | Raptor | Beldets, Simpawlo
Prea'Chan | Oc'to | Dalmiga'vie, Kinloch'ore, Sana'chan
Hive-AC3 | Arrack | Haiken, Mingin, Natkyigon, Pyidaung
Hive-F17 | Arrack | Rankse
Hive-DC | Arrack | Mepok
Hive-G8 | Arrack | Gamnim

Manchmal ändert sich durch die Wirtschaftslage der Tech-Level eines Systems, was sich bei den Klasse 10 Systemen aber meistens wieder normalisiert. Das Sternsystem Mepok im Cluster Hive-DC wäre so ein Beispiel: Dem System geht es am Anfang einmal für kurze Zeit schlecht und es bietet nur noch Klasse 9 Ausrüstung an. Nach kurzer Zeit stabilisiert es sich wieder und bleibt dann dauerhaft auf dem Tech-Level 10. Es gibt auch noch ein paar Fälle, wo es umgekehrt ist. Vor allem bei den Oc'to gibt es einige Systeme, die beim ersten Sprung in einen ihrer Cluster den Tech-Level 10 haben, um dann nach kurzer Zeit für immer auf einen geringeren Level abzufallen.


String-IDs

Liste der bisher bekannten String-IDs in der "global.res"
StringId | Angezeigter Text | Kommentar
ID_ABBR_TONS | %1t | %1 = StringID für Replace
ID_AUTOSAVE | Automatisches Speichern |
ID_BASE | Basis | Handelsstation
ID_CLUSTER_<ID> | Alpha Centauri...Tau Ceti | <ID> = ClusterID (0..29)
ID_DARKSTAR | Darkstar |
ID_GANGBOSS_<ID> | Akim-Boss...Wladislaw-Boss | <ID> = GangID (0..46)
ID_ECONOMY | Wirtschaft |
ID_ECO_TYPE_<ID> | Minenkolonie, etc. | <ID> = Wirtschaftsindex
ID_FACTION_<ID> | GU, Rebellen, Neutral | <ID> = Fraktionsindex
ID_GANGGUARD_<ID> | Akim-Leibwächter...Wladislaw-Leibwächter | <ID> = GangID (0..46)
ID_GANGNAME_<ID> | Akim-Gang...Wladislaw-Gang | <ID> = GangID (0..46)
ID_GANGPIRATE_<ID> | Akim-Pirat...Wladislaw-Pirat | <ID> = GangID (0..46)
ID_GOVERNMENT | Regierung |
ID_HJ_INFO_GOVERNMENT | %1,(%2) | %1 %2 = StringIDs für Replace
ID_HJ_INFO_WEALTH | %1, %2 | %1 %2 = StringIDs für Replace
ID_HYPERJUMPINFO_ENTRY | %1 %2 | Text ist in weißer Farbe
ID_HYPERJUMPINFO_ENTRY_ILLEGAL | %1 %2 | Text ist in roter Farbe
ID_POPULATION | Mrd. Einwohner |
ID_WEALTH_TYPE_<ID> | arm, wohlhabend, reich | <ID> = Wohlstandsindex
ID_STATION | Station | Forschungsstation
ID_SYSTEMNAME_<ID> | Abanaul...Zute | <ID> = SystemID (0..402)
ID_WAYPOINT | Wegpunkt |
ID_CRUISER_0 | Nahimana | großer Kreuzer, Lalande
ID_CRUISER_1 | Keoma | kleiner Kreuzer, Barnard
ID_CRUISER_2 | Tallahassee | großer Kreuzer, Tau Ceti
ID_CRUISER_3 | Topeka | kleiner Kreuzer, Alpha Centauri
ID_CRUISER_4 | Wakanda | großer Kreuzer, Alpha Centauri
ID_CRUISER_5 | Durango | kleiner Kreuzer, Grotok
ID_CRUISER_6 | Heroica | großer Kreuzer, Grotok
ID_CRUISER_7 | Bermudo | kleiner Kreuzer, Pertok
ID_CRUISER_8 | Mauregato | großer Kreuzer, Stromok
ID_CRUISER_9 | Possidonio | kleiner Kreuzer, Stromok
ID_CRUISER_10 | Nuevo Grandes | großer Kreuzer, Klatok
ID_CRUISER_11 | Entronque | kleiner Kreuzer, Klatok
ID_CRUISER_12 | Hidalgo | großer Kreuzer, Humok
ID_CRUISER_13 | Michoacan | kleiner Kreuzer, Humok
ID_CRUISER_14 | Maximuschka | großer Kreuzer, Raptor Alpha
ID_CRUISER_15 | Gennadi | kleiner Kreuzer, Raptor Nova
ID_CRUISER_16 | Petruscha | großer Kreuzer, Raptor Nova
ID_CRUISER_17 | Wanjuscha | kleiner Kreuzer, Raptor Gamma
ID_CRUISER_18 | Kolenka | großer Kreuzer, Raptor Gamma
ID_CRUISER_19 | Lucknov | kleiner Kreuzer, Raptor Gamma
ID_CRUISER_20 | Krasnogul | großer Kreuzer, Raptor Delta
ID_CRUISER_21 | Archangelsk | kleiner Kreuzer, Raptor Epsilon
ID_CRUISER_22 | Turuchansk | großer Kreuzer, Raptor Epsilon
ID_CRUISER_23 | Clash'ore | kleiner Kreuzer, Sion'nach
ID_CRUISER_24 | Kinloch'ore | großer Kreuzer, Sion'nach
ID_CRUISER_25 | Macawicha | kleiner Kreuzer, Sirius
ID_CRUISER_26 | Karmigaho | großer Kreuzer, Sirius
ID_CRUISER_27 | Gahojacy | kleiner Kreuzer, Sirius
ID_CRUISER_28 | Tuwazulu | großer Kreuzer, Sirius
ID_CRUISER_29 | Lochcar'ron | kleiner Kreuzer, Madra'mor
ID_CRUISER_30 | Ormsaig'nie | großer Kreuzer, Madra'mor
ID_CRUISER_31 | Sliga'chan | kleiner Kreuzer, Madra'mor
ID_CRUISER_32 | Lathe'ron | großer Kreuzer, Madra'mor
ID_CRUISER_33 | Skullo'ron | kleiner Kreuzer, Prea'chan
ID_CRUISER_34 | Drum'unie | großer Kreuzer, Prea'chan
ID_CRUISER_35 | Bo'athvic | kleiner Kreuzer, Prea'chan
ID_CRUISER_36 | MS Steinhammer | großer Kreuzer, Ross 128
ID_CRUISER_37 | MS Stahlwerk | kleiner Kreuzer, Ross 128
ID_CRUISER_38 | MS Eisenfaust | großer Kreuzer, Ross 128
ID_CRUISER_39 | MS Steinfaust | kleiner Kreuzer, Ross 128
ID_CRUISER_40 | Bad'aul | großer Kreuzer, Bear'mor
ID_CRUISER_41 | Leirin'vie | kleiner Kreuzer, Gab'har
ID_CRUISER_42 | Linside'ore | großer Kreuzer, Gab'har
ID_CRUISER_43 | Tour'oreton | kleiner Kreuzer, Gab'har
ID_CRUISER_44 | Lakshman-fu | großer Kreuzer, Hive-AC3
ID_CRUISER_45 | Narendra-ko | kleiner Kreuzer, Hive-AC3
ID_CRUISER_46 | Manindra-ne | großer Kreuzer, Hive-AC3
ID_CRUISER_47 | Yogendra-ne | kleiner Kreuzer, Hive-F17
ID_CRUISER_48 | Matsendra-ai | großer Kreuzer, Hive-F17
ID_CRUISER_49 | Sudhakar-ne | kleiner Kreuzer, Hive-F17
ID_CRUISER_50 | Prakash-ai | großer Kreuzer, Hive-CU7
ID_CRUISER_51 | Vidyadhar-ko | kleiner Kreuzer, Hive-CU7
ID_CRUISER_52 | Jinendra-ne | großer Kreuzer, Hive-B52
ID_CRUISER_53 | Akshat-ne | kleiner Kreuzer, Hive-DC
ID_CRUISER_54 | Makarand-ai | großer Kreuzer, Hive-DC
ID_CRUISER_55 | Hemendra-ko | kleiner Kreuzer, Hive-DC
ID_CRUISER_56 | Devendra-ne | großer Kreuzer, Hive-ET9
ID_CRUISER_57 | Tarak-fu | kleiner Kreuzer, Hive-G8
ID_CRUISER_58 | Kaushik-ko | großer Kreuzer, Hive-G8
ID_CRUISER_59 | Galadriel | kleiner Kreuzer, Communa
ID_CRUISER_60 | Eoghane | großer Kreuzer, Communa
ID_CRUISER_61 | Aonghusa | kleiner Kreuzer, Communa
ID_CRUISER_62 | Conchubhar | großer Kreuzer, Hyma
ID_CRUISER_63 | Samudra II | kleiner Kreuzer, Hive-G8
ID_CRUISER_64 | Samudra III | großer Kreuzer, Hive-F17
ID_CRUISER_65 | Eowýn | kleiner Kreuzer, Hyma
ID_CRUISER_66 | Arwén | großer Kreuzer, Communa
ID_CRUISER_67 | Kailua-Kona | kleiner Kreuzer, Tau Ceti
ID_NAME_"Rasse"_<ID> | Piratenname der Rasse: | <ID> = laufende Nummer der StringId
ID_NAME_HUMAN_0..59 ID_NAME_MORTOK_0..59 ID_NAME_RAPTOR_0..59 ID_NAME_OCTO_0..59 ID_NAME_ARRACK_0..59 ID_NAME_THUL_0..59 | Piratenname | StringId kann per Zufall von NObject.GetName geliefert werden.
ID_RUF_0 | Unbekannt |
ID_RUF_1 | Harmlos |
ID_RUF_2 | Ungefährlich |
ID_RUF_3 | Bekannt |
ID_RUF_4 | Gefährlich |
ID_RUF_5 | Sehr gefährlich |
ID_RUF_6 | Extrem gefährlich |
ID_RUF_7 | Tödlich |
ID_RUF_8 | Sehr tödlich |
ID_RUF_9 | Extrem tödlich |
ID_RUF_10 | Legendär |
ID_SHOP_ROCKET | Raketen |
ID_SHOP_SHIELD | Energiesysteme |
ID_SHOP_TECH | Ausrüstung |
ID_SHOP_TURRETS | Geschütztürme |
ID_SHOP_WEAPONS | Waffensysteme |
ID_SPACEOBJ_ABERRATION | Anomalie |
ID_SPACEOBJ_ADVERTISMENT | Werbetafel |
ID_SPACEOBJ_ARTEFACT | Artefakt |
ID_SPACEOBJ_ASTEROID | Asteroid |
ID_SPACEOBJ_ASTEROIDAUFBAUTEN | Landeplattform |
ID_SPACEOBJ_ASTEROIDINNERE | Asteroidenzentrum |
ID_SPACEOBJ_CAMERA | Wegpunkt |
ID_SPACEOBJ_CANYON | Canyon |
ID_SPACEOBJ_CARGO | Container |
ID_SPACEOBJ_CARGODRONE | Frachtdrohne |
ID_SPACEOBJ_COLLIDER | Collider |
ID_SPACEOBJ_COMMSAT | Kom-Sat |
ID_SPACEOBJ_CONTAINER50 | Container 50t |
ID_SPACEOBJ_CONTAINER100 | Container 100t |
ID_SPACEOBJ_CONTAINER200 | Container 200t |
ID_SPACEOBJ_CONTAINERCRYSTAL | Kristalle (%1t) |
ID_SPACEOBJ_CONTAINERMETAL | Edelmetalle (%1t) | %1 = StringID für Replace
ID_SPACEOBJ_CONTAINERORE | Erzklumpen (%1t) | %1 = StringID für Replace
ID_SPACEOBJ_CONTAINERPASSENGER | Passagiermodul |
ID_SPACEOBJ_CONTAINER_SPECIAL | Spezialcontainer |
ID_SPACEOBJ_CRUISER | Kreuzer |
ID_SPACEOBJ_DECORATION | Schiffswrack |
ID_SPACEOBJ_DECOSTATION | Stationswrack |
ID_SPACEOBJ_DEBRIS | Weltraumschrott |
ID_SPACEOBJ_DRONE | Drohne |
ID_SPACEOBJ_EXPLOSION | Explosion |
ID_SPACEOBJ_FORCEFIELD | Kraftfeld |
ID_SPACEOBJ_HIDEOUT | Piratenversteck |
ID_SPACEOBJ_HOVERTANK | Geschütz |
ID_SPACEOBJ_HUNTER | Jäger |
ID_SPACEOBJ_METEROID | Meteroit |
ID_SPACEOBJ_MILITARY | Militär |
ID_SPACEOBJ_MINE | Mine |
ID_SPACEOBJ_PIRATE | Pirat |
ID_SPACEOBJ_PIRATE_FREIGHTER | Piratenfrachter |
ID_SPACEOBJ_PLANET | Planet |
ID_SPACEOBJ_PLAYERTURRET | Flak-Abwehr |
ID_SPACEOBJ_POLICE | Polizei |
ID_SPACEOBJ_PROJECTILE | Projektil |
ID_SPACEOBJ_RING | Ring |
ID_SPACEOBJ_ROCKET | Rakete |
ID_SPACEOBJ_SCAT | Schrott |
ID_SPACEOBJ_SCHIFF | Schiff |
ID_SPACEOBJ_SHIELDGEN | Schildgenerator |
ID_SPACEOBJ_SKAADROHNE | S'kaa-Drohne |
ID_SPACEOBJ_SKAASWARM | Schwarm |
ID_SPACEOBJ_SONNE | Sonne |
ID_SPACEOBJ_SPELL | Spell |
ID_SPACEOBJ_STATION | Handelsstation |
ID_SPACEOBJ_SUBSTATION | Stationsmodul |
ID_SPACEOBJ_TAXI | Taxi |
ID_SPACEOBJ_TURRET | Geschützturm |
ID_SPACEOBJ_TRANSPORTER | Frachter |
ID_SPACEOBJ_WARPEFFECT | Warpeffekt |
ID_SPACEOBJ_WARPGATE | Sprungtor |
ID_SPACEOBJ_WEAPONBASE | Waffenplattform |
ID_SPACEOBJ_WEAPONFACTORY | Waffenfabrik |
ID_TERMINAL_REWARD | Belohnung: %1 |
ID_TTIP_AKT_KLASSE | Aktuelle Klasse |
ID_TTIP_INGAME_RADAR_UMSCHALTEN | Radarreichweite auf %1 umschalten |
ID_TTIP_UPGRADE_DARKSTAR | Darkstar-Ugradesystem |
ID_TTIP_... | Noch 151 weitere "ID_TTIP_"-StringIDs vorhanden |
ID_TYPE_FIRERATE | Feuerrate |
ID_TYPE_FIRERATE_VALUE | %1 / s | %1 = StringID für Replace
ID_TYPE_HITPOINTS | Schaden |
ID_TYPE_HITPOINTS_JOULE | %1 MJ | %1 = StringID für Replace
ID_UPGRADE_INFO_00 | 100% Bonus auf die Einsatzdauer des Nachbrenners | Diverse Upgradeinfos, Start
ID_UPGRADE_INFO_01 | 50% Bonus auf die Einsatzdauer des Nachbrenners |
ID_UPGRADE_INFO_02 | Verbessertes Feuerleitsystem. Geschütztürme +10% Schaden. |
ID_UPGRADE_INFO_03 | Verbessertes Feuerleitsystem. Geschütztürme +20% Schaden. |
ID_UPGRADE_INFO_04 | Verbessertes Feuerleitsystem. Alle Bugwaffen +10% Schaden. |
ID_UPGRADE_INFO_05 | Verbessertes Feuerleitsystem. Alle Bugwaffen +20% Schaden. |
ID_UPGRADE_INFO_06 | Flügel |
ID_UPGRADE_INFO_07 | Bugwaffen |
ID_UPGRADE_INFO_08 | Wendigkeit |
ID_UPGRADE_INFO_09 | Rumpf |
ID_UPGRADE_INFO_10 | Geschütztürme |
ID_UPGRADE_INFO_11 | Stabilität |
ID_UPGRADE_INFO_12 | Triebwerk |
ID_UPGRADE_INFO_13 | Aufladung |
ID_UPGRADE_INFO_14 | Trägheit |
ID_UPGRADE_INFO_15 | Ausstattung |
ID_UPGRADEONLY | -- nur Ersetzen möglich -- | Diverse Upgradeinfos, Ende
ID_WERFT_CLASS_0 | MK 2 |
ID_WERFT_CLASS_1 | MK 3 |
ID_WERFT_CLASS_2 | Military |
ID_WERFT_CLASS_3 | Military MK 2 |
ID_WERFT_CLASS_4 | Military MK 3 |
ID_WERFT_CLASS_5 | Elite |
ID_WERFT_CLASS_6 | Elite MK 2 |
ID_WERFT_CLASS_7 | Elite MK 3 |
ID_WERFT_CLASS_8 | Elite MK 4 |
ID_WERFT_CLASS_ABBRV | Kl. %1 | %1 = StringID für Replace
ID_WERFT_CLASS_ENERGY | Energieklasse |
ID_WERFT_CLASS_EQUIPMENT | Ausrüstungsklasse |
ID_WERFT_CLASS_MILITARY | Werferklasse |
ID_WERFT_CLASS_WEAPON | Waffenklasse |
ID_WERFT_ITEM_<ID> | Name des Ausrüstungsgegenstands in der Werft: | <ID> = erste Id in Items.ini
ID_WERFT_ITEM_0 | Feldantrieb 2,5 Lj |
ID_WERFT_ITEM_1 | Feldantrieb 3 Lj |
ID_WERFT_ITEM_2 | Feldantrieb 4 Lj |
ID_WERFT_ITEM_3 | Feldantrieb 5 Lj |
ID_WERFT_ITEM_4 | Feldantrieb 6 Lj |
ID_WERFT_ITEM_5 | Feldantrieb 7 Lj |
ID_WERFT_ITEM_6 | Feldantrieb 8 Lj |
ID_WERFT_ITEM_7 | Feldantrieb 9 Lj |
ID_WERFT_ITEM_8 | Feldantrieb 10 Lj |
ID_WERFT_ITEM_9 | Frachtcomputer X-50 | für 1 Container 50t
ID_WERFT_ITEM_10 | Frachtcomputer X-100 | für 2 Container 50t
ID_WERFT_ITEM_11 | Frachtcomputer X-200 | für 2 Container 100t
ID_WERFT_ITEM_12 | Frachtcomputer X-300 | für 3 Container 100t
ID_WERFT_ITEM_13 | Frachtcomputer X-600 | für 3 Container 200t
ID_WERFT_ITEM_14 | Generator I |
ID_WERFT_ITEM_15 | Generator II |
ID_WERFT_ITEM_16 | Generator III |
ID_WERFT_ITEM_17 | Generator IV |
ID_WERFT_ITEM_18 | Generator V |
ID_WERFT_ITEM_19 | Generator VI |
ID_WERFT_ITEM_20 | Generator VII |
ID_WERFT_ITEM_21 | Generator VIII |
ID_WERFT_ITEM_22 | Generator IX |
ID_WERFT_ITEM_23 | Generator X |
ID_WERFT_ITEM_24 | Frachtscanner X-1 |
ID_WERFT_ITEM_25 | Frachtscanner X-2 |
ID_WERFT_ITEM_26 | Frachtscanner X-3 |
ID_WERFT_ITEM_27 | Frachtscanner X-4 |
ID_WERFT_ITEM_28 | Frachtscanner X-Elite |
ID_WERFT_ITEM_29 | Energieschild I |
ID_WERFT_ITEM_30 | Energieschild II |
ID_WERFT_ITEM_31 | Energieschild III |
ID_WERFT_ITEM_32 | Energieschild IV |
ID_WERFT_ITEM_33 | Energieschild V |
ID_WERFT_ITEM_34 | Energieschild VI |
ID_WERFT_ITEM_35 | Energieschild VII |
ID_WERFT_ITEM_36 | Energieschild VIII |
ID_WERFT_ITEM_37 | Energieschild IX |
ID_WERFT_ITEM_38 | Energieschild X |
ID_WERFT_ITEM_39 | Kondensator I |
ID_WERFT_ITEM_40 | Kondensator II |
ID_WERFT_ITEM_41 | Kondensator III |
ID_WERFT_ITEM_42 | Kondensator IV |
ID_WERFT_ITEM_43 | Kondensator V |
ID_WERFT_ITEM_44 | Kondensator VI |
ID_WERFT_ITEM_45 | Kondensator VII |
ID_WERFT_ITEM_46 | Kondensator VIII |
ID_WERFT_ITEM_47 | Kondensator IX |
ID_WERFT_ITEM_48 | Kondensator X |
ID_WERFT_ITEM_49 | Nachbrenner I |
ID_WERFT_ITEM_50 | Nachbrenner II |
ID_WERFT_ITEM_51 | Nachbrenner III |
ID_WERFT_ITEM_52 | Nachbrenner IV |
ID_WERFT_ITEM_53 | Nachbrenner V |
ID_WERFT_ITEM_54 | Nachbrenner VI |
ID_WERFT_ITEM_55 | Nachbrenner VII |
ID_WERFT_ITEM_56 | Nachbrenner VIII |
ID_WERFT_ITEM_57 | Nachbrenner IX |
ID_WERFT_ITEM_58 | Nachbrenner X |
ID_WERFT_ITEM_59 | Frachtscanner X-5 |
ID_WERFT_ITEM_60..99 | -/- | frei
ID_WERFT_ITEM_100 | Raketenwerfer ST | der "Raketenwerfer"
ID_WERFT_ITEM_101 | Raketenwerfer ST-2 | der "Raketenwerfer MK 2"
ID_WERFT_ITEM_102 | Raketenwerfer ST-3 | der "Raketenwerfer MK 3"
ID_WERFT_ITEM_103 | Raketenwerfer MI | der "Raketenwerfer Military"
ID_WERFT_ITEM_104 | Raketenwerfer MI-2 | der "Raketenwerfer Military MK 2"
ID_WERFT_ITEM_105 | Raketenwerfer MI-3 | der "Raketenwerfer Military MK 3"
ID_WERFT_ITEM_106 | Raketenwerfer EL | der "Raketenwerfer Elite"
ID_WERFT_ITEM_107 | Raketenwerfer EL-2 | der "Raketenwerfer Elite MK 2"
ID_WERFT_ITEM_108 | Raketenwerfer EL-3 | der "Raketenwerfer Elite MK 3"
ID_WERFT_ITEM_109 | Raketenwerfer EL-4 | der "Raketenwerfer Elite MK 4"
ID_WERFT_ITEM_110 | Laser |
ID_WERFT_ITEM_111 | Railgun |
ID_WERFT_ITEM_112 | Ion Pulse |
ID_WERFT_ITEM_113 | Graviton Gun |
ID_WERFT_ITEM_114 | Spore Cannon |
ID_WERFT_ITEM_115 | Photon Gun |
ID_WERFT_ITEM_116 | Laser |
ID_WERFT_ITEM_117 | Railgun |
ID_WERFT_ITEM_118 | Ion Pulse |
ID_WERFT_ITEM_119 | Graviton Gun |
ID_WERFT_ITEM_120 | Spore Cannon |
ID_WERFT_ITEM_121 | Photon Gun |
ID_WERFT_ITEM_122..149 | -/- | frei
ID_WERFT_ITEM_150 | Swarm |
ID_WERFT_ITEM_151 | Hellfire |
ID_WERFT_ITEM_152 | Big Bang |
ID_WERFT_ITEM_153..199 | -/- | frei
ID_WERFT_ITEM_200 | Jammer X-30 |
ID_WERFT_ITEM_201 | Jammer X-40 |
ID_WERFT_ITEM_202 | Jammer X-50 |
ID_WERFT_ITEM_203 | Jammer X-60 |
ID_WERFT_ITEM_204 | Jammer X-70 |
ID_WERFT_ITEM_205 | Jammer X-Elite |
ID_WERFT_ITEM_206 | Handelscomputer X-50 |
ID_WERFT_ITEM_207 | Handelscomputer X-100 |
ID_WERFT_ITEM_208 | Landecomputer X-1 |
ID_WERFT_ITEM_209 | Landecomputer X-2 |
ID_WERFT_ITEM_210 | Landecomputer X-3 |
ID_WERFT_ITEM_211 | Landecomputer X-5 |
ID_WERFT_ITEM_212 | Reparaturbot X-60 |
ID_WERFT_ITEM_213 | Reparaturbot X-80 |
ID_WERFT_ITEM_214 | Reparaturbot X-100 |
ID_WERFT_ITEM_215 | Schildflux |
ID_WERFT_ITEM_216 | Energieflux |
ID_WERFT_ITEM_217 | Energiesammler X-20 |
ID_WERFT_ITEM_218 | Energiesammler X-30 |
ID_WERFT_ITEM_219 | Energiesammler X-40 |
ID_WERFT_ITEM_220 | Energiesammler X-50 |
ID_WERFT_ITEM_221 | Erzsammler |
ID_WERFT_ITEM_222 | Plasma-Booster |
ID_WERFT_ITEM_223 | Schild-Booster |
ID_WERFT_ITEM_224 | Nachbrenner-Booster |
ID_WERFT_ITEM_225 | Graviton-Schub |
ID_WERFT_ITEM_226 | Aktuator-Refill |
ID_WERFT_ITEM_227 | Jammer X-80 |
ID_WERFT_ITEM_228 | Landecomputer X-4 |
ID_WERFT_ITEM_229 | Energiesammler X-60 |
ID_WERFT_ITEM_230 | Energiesammler X-Elite |
ID_WERFT_ITEM_231..99999 | -/- | frei
ID_WERFT_ITEM_100000..599999 | -/- | 4 Texte in diesem Bereich
ID_WERFT_ITEM_600000..656269 | -/- | frei
ID_WERFT_ITEM_656270 | Rettungsmodul |
ID_WERFT_ITEM_656271..999999 | -/- | frei
ID_WERFT_ITEMCLASS_ROCKET | Werferklasse %1 |
ID_WERFT_ITEMDETAILS_<ID> | Beschreibung im Infofenster der Werft | <ID> = zweite Id in Items.ini
ID_WERFT_ITEMDETAILS_0..6 | Beschreibungen für Energiesysteme |
ID_WERFT_ITEMDETAILS_7..99 | -/- | frei
ID_WERFT_ITEMDETAILS_100..112 | Beschreibungen für Waffen |
ID_WERFT_ITEMDETAILS_113..149 | -/- | frei
ID_WERFT_ITEMDETAILS_150..152 | Beschreibungen für Raketen |
ID_WERFT_ITEMDETAILS_153..199 | -/- | frei
ID_WERFT_ITEMDETAILS_200..212 | Beschreibungen für Ausrüstung |
ID_WERFT_ITEMDETAILS_213 | Neue Beschreibung für den Handelscomputer | im Original frei
ID_WERFT_ITEMDETAILS_214 | Neue Beschreibung mit Zweitverwendung für den Aktuator-Refill | im Original frei
ID_WERFT_ITEMDETAILS_215..999 | -/- | frei
ID_WERFT_ITEMDETAILS_1000..99999 | -/- | 1 Text in diesem Bereich
ID_WERFT_ITEMSTRING_0 | Anzahl Drohnen | Texte für "items.ini", Start
ID_WERFT_ITEMSTRING_1 | Max. Größe |
ID_WERFT_ITEMSTRING_2 | Gesamt |
ID_WERFT_ITEMSTRING_3 | Reichweite |
ID_WERFT_ITEMSTRING_4 | Scanvorgang erfolgt durch |
ID_WERFT_ITEMSTRING_5 | Umschalten der Targetview |
ID_WERFT_ITEMSTRING_6 | Erfolg |
ID_WERFT_ITEMSTRING_7 | Wird bei Bedarf |
ID_WERFT_ITEMSTRING_8 | automatisch aktiviert |
ID_WERFT_ITEMSTRING_9 | Max. Raketenzahl |
ID_WERFT_ITEMSTRING_10 | Feuert alle Raketentypen |
ID_WERFT_ITEMSTRING_11 | der Klasse 1 ab |
ID_WERFT_ITEMSTRING_12 | der Klasse 2 ab |
ID_WERFT_ITEMSTRING_13 | der Klasse 3 ab |
ID_WERFT_ITEMSTRING_14 | der Klasse 4 ab |
ID_WERFT_ITEMSTRING_15 | der Klasse 5 ab |
ID_WERFT_ITEMSTRING_16 | der Klasse 6 ab |
ID_WERFT_ITEMSTRING_17 | der Klasse 7 ab |
ID_WERFT_ITEMSTRING_18 | der Klasse 8 ab |
ID_WERFT_ITEMSTRING_19 | der Klasse 9 ab |
ID_WERFT_ITEMSTRING_20 | der Klasse 10 ab |
ID_WERFT_ITEMSTRING_21 | Einsatzdauer |
ID_WERFT_ITEMSTRING_22 | Geschwindigkeit |
ID_WERFT_ITEMSTRING_23 | Zeigt einige Warenbestände |
ID_WERFT_ITEMSTRING_24 | bereits auf der |
ID_WERFT_ITEMSTRING_25 | Navigationskarte an. |
ID_WERFT_ITEMSTRING_26 | Zeigt alle Warenbestände |
ID_WERFT_ITEMSTRING_27 | Abstand von Station |
ID_WERFT_ITEMSTRING_28 | Ermöglicht das Abbauen |
ID_WERFT_ITEMSTRING_29 | von Rohstoffen |
ID_WERFT_ITEMSTRING_30 | in Meteoritenfeldern. |
ID_WERFT_ITEMSTRING_31 | Schaden |
ID_WERFT_ITEMSTRING_32 | Flugdauer |
ID_WERFT_ITEMSTRING_33 | Sprengköpfe |
ID_WERFT_ITEMSTRING_34 | Wendigkeit |
ID_WERFT_ITEMSTRING_35 | Automatische Landung |
ID_WERFT_ITEMSTRING_36 | nach Landefreigabe |
ID_WERFT_ITEMSTRING_37 | Stellt den Rumpfzustand |
ID_WERFT_ITEMSTRING_38 | wieder her. |
ID_WERFT_ITEMSTRING_39 | Verbesserung |
ID_WERFT_ITEMSTRING_40 | Ermöglicht Energietransfer |
ID_WERFT_ITEMSTRING_41 | vom Bugschild |
ID_WERFT_ITEMSTRING_42 | zum Heckschild. |
ID_WERFT_ITEMSTRING_43 | Ermöglicht Transfer |
ID_WERFT_ITEMSTRING_44 | von Waffenenergie |
ID_WERFT_ITEMSTRING_45 | auf Schilde. |
ID_WERFT_ITEMSTRING_46 | Erhöht die Aufladerate |
ID_WERFT_ITEMSTRING_47 | des Hyperraumantriebs. |
ID_WERFT_ITEMSTRING_48 | Verbesserung |
ID_WERFT_ITEMSTRING_49 | Ermöglicht den Abbau |
ID_WERFT_ITEMSTRING_50 | von Rohstoffen |
ID_WERFT_ITEMSTRING_51 | in Meteoritenfeldern. |
ID_WERFT_ITEMSTRING_52 | Regeneriert einmalig |
ID_WERFT_ITEMSTRING_53 | die Energie des |
ID_WERFT_ITEMSTRING_54 | Plasmawerfers. |
ID_WERFT_ITEMSTRING_55 | die Schildenergie. |
ID_WERFT_ITEMSTRING_56 | Erhöht einmalig die Energie |
ID_WERFT_ITEMSTRING_57 | des Nachbrenners auf 200% |
ID_WERFT_ITEMSTRING_58 | Gibt dem Schiff für 10 s |
ID_WERFT_ITEMSTRING_59 | einen deutlichen Geschwindigkeitsschub |
ID_WERFT_ITEMSTRING_60 |  | leer
ID_WERFT_ITEMSTRING_61 | Füllt einmalig die Energie |
ID_WERFT_ITEMSTRING_62 | des Hyperraum-Aktuators |
ID_WERFT_ITEMSTRING_63 | wieder auf. | ab 64 im Original frei
ID_WERFT_ITEMSTRING_64 | Gibt dem Schiff für 10 Sekunden |
ID_WERFT_ITEMSTRING_65 | Gibt dem Schiff für 12 Sekunden |
ID_WERFT_ITEMSTRING_66 | Gibt dem Schiff für 14 Sekunden |
ID_WERFT_ITEMSTRING_67 | Gibt dem Schiff für 16 Sekunden |
ID_WERFT_ITEMSTRING_68 | Gibt dem Schiff für 18 Sekunden |
ID_WERFT_ITEMSTRING_69 | Gibt dem Schiff für 20 Sekunden |
ID_WERFT_ITEMSTRING_70 | Gibt dem Schiff für 25 Sekunden |
ID_WERFT_ITEMSTRING_71 | Gibt dem Schiff für 30 Sekunden |
ID_WERFT_ITEMSTRING_72 | Gibt dem Schiff für 40 Sekunden |
ID_WERFT_ITEMSTRING_73 | Gibt dem Schiff für 50 Sekunden |
ID_WERFT_ITEMSTRING_74 | Gibt dem Schiff für 1 Minute |
ID_WERFT_ITEMSTRING_75 | Zeigt eine der beiden illegale Waren |
ID_WERFT_ITEMSTRING_76 | Zeigt die beiden illegalen Waren |
ID_WERFT_ITEMSTRING_77 | der von Piraten besetzten Systeme nach |
ID_WERFT_ITEMSTRING_78 | dem Schließen der Navigationskarte an. |
ID_WERFT_PERCENTAGE_10 | 10% |
ID_WERFT_PERCENTAGE_20 | 20% |
ID_WERFT_PERCENTAGE_30 | 30% |
ID_WERFT_PERCENTAGE_40 | 40% |
ID_WERFT_PERCENTAGE_50 | 50% |
ID_WERFT_PERCENTAGE_60 | 60% |
ID_WERFT_PERCENTAGE_70 | 70% |
ID_WERFT_PERCENTAGE_80 | 80% |
ID_WERFT_PERCENTAGE_90 | 90% |
ID_WERFT_PERCENTAGE_100 | 100% |
ID_WERFT_PERCENTAGE_150 | 150% |
ID_WERFT_PERCENTAGE_160 | 160% |
ID_WERFT_PERCENTAGE_180 | 180% |
ID_WERFT_PERCENTAGE_200 | 200% |
ID_WERFT_PERCENTAGE_250 | 250% |
ID_WERFT_PERCENTAGE_300 | 300% |
ID_WERFT_PERCENTAGE_350 | 350% |
ID_WERFT_PERCENTAGE_400 | 400% |
ID_WERFT_PERCENTAGE_500 | 500% |
ID_WERFT_PERCENTAGE_600 | 600% |
ID_WERFT_PERCENTAGE_700 | 700% |
ID_WERFT_PERCENTAGE_800 | 800% |
ID_WERFT_PERCENTAGE_900 | 900% |
ID_WERFT_PERCENTAGE_1000 | 1000% |
ID_WERFT_SEK_8 | 8 s | 0-7 und alle Lücken frei
ID_WERFT_SEK_9 | 9 s |
ID_WERFT_SEK_10 | 10 s |
ID_WERFT_SEK_12 | 12 s |
ID_WERFT_SEK_14 | 14 s |
ID_WERFT_SEK_15 | 15 s |
ID_WERFT_SEK_16 | 16 s |
ID_WERFT_SEK_18 | 18 s |
ID_WERFT_SEK_20 | 20 s |
ID_WERFT_SEK_21 | 21 s |
ID_WERFT_SEK_22 | 22 s |
ID_WERFT_SEK_24 | 24 s |
ID_WERFT_SEK_25 | 25 s |
ID_WERFT_SEK_28 | 28 s |
ID_WERFT_SEK_30 | 30 s |
ID_WERFT_SEK_32 | 32 s |
ID_WERFT_SEK_36 | 36 s |
ID_WERFT_SEK_40 | 40 s |
ID_WERFT_SEK_44 | 44 s |
ID_WERFT_SEK_50 | 50 s |
ID_WERFT_SEK_60 | 60 s |
ID_WERFT_SIMPLE_1 | 1 | Zahl, kein String
ID_WERFT_SIMPLE_2 | 2 | Zahl, kein String
ID_WERFT_SIMPLE_3 | 3 | Zahl, kein String
ID_WERFT_SLOTS | Freie Plätze |
ID_WERFT_TONS_50 | 50t |
ID_WERFT_TONS_100 | 100t |
ID_WERFT_TONS_200 | 200t |
ID_WERFT_TONS_300 | 300t |
ID_WERFT_TONS_600 | 600t |
ID_WERFT_TURRET_NAME_0 | Laser Turret |
ID_WERFT_TURRET_NAME_1 | Rail Turret |
ID_WERFT_TURRET_NAME_2 | Ion Turret |
ID_WERFT_TURRET_NAME_3 | Graviton Turret |
ID_WERFT_TURRET_NAME_4 | Spore Turret |
ID_WERFT_TURRET_NAME_5 | Photon Turret |
ID_WERFT_U_1 | 1 u |
ID_WERFT_U_2 | 2 u |
ID_WERFT_U_3 | 3 u |
ID_WERFT_U_4 | 4 u |
ID_WERFT_U_5 | 5 u |
ID_WERFT_U_10 | 10 u |
ID_WERFT_U_15 | 15 u |
ID_WERFT_U_20 | 20 u |
ID_WERFT_WEAPON_NAME_0 | Laser |
ID_WERFT_WEAPON_NAME_1 | Railgun |
ID_WERFT_WEAPON_NAME_2 | Ion Pulse |
ID_WERFT_WEAPON_NAME_3 | Graviton Gun |
ID_WERFT_WEAPON_NAME_4 | Spore Cannon |
ID_WERFT_WEAPON_NAME_5 | Photon Gun |
ID_WERFT_WEAPON_NAME_6 | Launcher | Texte für "items.ini", Ende
IDL_EQUIPMENT_00 | Schildgenerator |
IDL_EQUIPMENT_01 | Nachbrenner |
IDL_EQUIPMENT_02 | Feldantrieb |
IDL_EQUIPMENT_03 | Frachtscanner |
IDL_EQUIPMENT_04 | Frachtschild | der "Scanner-Jammer"
IDL_EQUIPMENT_05 | Generator |
IDL_EQUIPMENT_06 | Energiespeicher | der "Kondensator"
IDL_EQUIPMENT_07 | Frachtcomputer |
IDL_EQUIPMENT_08 | Erzsammler |
IDL_EQUIPMENT_09 | Energiesammler |
IDL_EQUIPMENT_10 | Energieflux |
IDL_EQUIPMENT_11 | Schildflux |
IDL_EQUIPMENT_12 | Landecomputer |
IDL_EQUIPMENT_13 | Handelscomputer |
IDL_EQUIPMENT_14 | Reparaturbot |
IDL_WEAPON_01 | Raketenwerfer |
IDL_WEAPON_02 | Plasmawerfer |
IDL_WEAPON_03 | Minenwerfer |
IDL_WEAPON_04 | Geheimdienstwaffe |
IDL_WEAPON_05 | Geheimdienstturm |
IDL_GOODS_<ID> | Handelswaren (ID immer zweistellig!) | <ID> = Handelswaren (00..23)
IDL_GOVERN_00 | Demokratie |
IDL_GOVERN_01 | Diktatur |
IDL_GOVERN_02 | Staatenbund |
IDL_GOVERN_03 | Anarchie |
IDL_GOVERN_04 | Konzernführung |
IDL_GOVERN_05 | Monarchie |
IDL_ASTEROID_BAIKOV | Asteroid Baikov |
IDL_ASTEROID_MAHENDRA | Asteroid Mahendra |
IDL_ASTEROID_NOMAD | Asteroid N.O.M.A.D. |
IDL_CERN_STATION | CERN-Forschungsstation |
IDL_GU_TRADESTATION | Handelsstation des GU-Rats |
IDL_MUIGAHL_STATION | Mui'ghal-Forschungsstation |
IDL_MAX_PLANCK_STATION | Max-Planck-Forschungsstation |
IDL_NINDORIA_STATION | Nindoria-Forschungsstation |
IDL_POLTAVA_STATION | Poltava-Forschungsstation |
IDL_PROTWINO_STATION | Protwino-Forschungsstation |
IDL_RESEARCH_PERMNAJA | Kolenka-Forschungsstation | Im Original = "Kolenka-Station"
IDL_RESEARCH_STATION | Forschungsstation |
IDL_TARTU_STATION | Tartu-Forschungsstation |
IDL_TOSCHA_STATION | Toscha-Forschungsstation |
IDL_TRADE_STATION | Handelsstation |
IDL_TSCHERENKOW_STATION | Tscherenkow-Forschungsstation |
IDL_VULCAN_STATION | Vul'can-Forschungsstation |
IDL_WOLODJA_STATION | Wolodja-Forschungsstation |
IDL_BOUNTY_HUNTER | Kopfgeldjäger |
IDM_ALWAYS_000_HINWEIS_01 | "ID_GANGNAME_<GangId>" vernichtet |
IDM_ALWAYS_001_ACHIEVED | Gratulation! System befreit! |
IDM_ALWAYS_001_INFO_01 | Besetztes System. Vernichte alle Piraten. |
IDM_ALWAYS_001_NAME | Piratenpatrouille |
IDM_ASCARONG_CONTAINER | Sprengstoffcontainer |
IDM_ASCARONG_CONTAINERCONTENT | Sprengstoff |
IDM_ASCARONG_GUI1 | Ascarong-Gang entdeckt |
IDM_ASCARONG_GUI2 | Glückwunsch! Du hast die gefürchtete Ascarong-Gang vernichtet! |
IDM_ASCARONG_HDR | Die Ascarong-Gang |
IDM_CLANNAME_CLUSTER_<ID> | Alexej-Clan...Wakanda-Clan | <ID> = ClusterID (0..29)
IDM_NPC_NAME_ARIM | Arim |
IDM_NPC_NAME_BASILIUS | Basilius |
IDM_STORY_011_SHIPNAME_BASILIUS | Basilius |
IDM_STORY_011_SHIPNAME_BRONIS | Bronis |
IDM_NPC_NAME_DELANO | Delano |
IDM_NPC_NAME_EONA | Eona |
IDM_NPC_NAME_FERVATH | Fervath |
IDM_NPC_NAME_HARTOK | Hartok |
IDM_NPC_NAME_HORNBLOWER | Cpt. Hornblower |
IDM_NPC_NAME_HUNHAN | Professor Hun'han |
IDM_NPC_NAME_JACK | Jack |
IDM_NPC_NAME_JIJU | Jiju |
IDM_NPC_NAME_JOWHAL | Jow'hal |
IDM_NPC_NAME_JOWSON | Jow'son |
IDM_NPC_NAME_KABRO | Kabro |
IDM_NPC_NAME_KAYRON | Kayron |
IDM_NPC_NAME_KORNIUS | Kornius |
IDM_NPC_NAME_MENDO | Mendo |
IDM_STORY_011_MENDO_NAME | Mendo |
IDM_NPC_NAME_MITRI | Mitri |
IDM_STORY_010_MITRI_NAME | Mitri |
IDM_NPC_NAME_NAARA | Naara |
IDM_NPC_NAME_NICOLAI | Nicolai |
IDM_NPC_NAME_RAMIREZ | Ramirez |
IDM_NPC_NAME_ROBERT | Robert |
IDM_NPC_NAME_ROBOT | Automat |
IDM_NPC_NAME_SHURIK | Shurik |
IDM_NPC_NAME_SKAABOSS | S'kaa |
IDM_NPC_NAME_TANALE | Tan'ale |
IDM_NPC_NAME_VIMARO | Vimaro |
IDM_NPC_NAME_ZARKOV | Zarkov |
IDM_STORY_021_PIRATENAME_BASE1 | X'Snider'Hips-Basis |
IDM_STORY_021_PIRATENAME_BASE2 | Raz'koyr-Bull-Basis |
IDM_STORY_TEXT_032_HDR | Abenteuer beendet |
IDM_STORY_TEXT_032 | Du hast die Galaxis vor den S'kaa gerettet. Keine weitere Story-Mission vorhanden. |
IDM_MISSION_ACHIEVED | Mission erfüllt |
IDM_MISSION_FAILED | Mission gescheitert |
IDM_MISSION_UPDATE | Neues Missionsziel |
IDM_TASK_ACHIEVED | Auftrag erfüllt |
IDM_TASK_CANCEL | Auftrag abgebrochen! |
IDM_TASK_FAILED | Auftrag gescheitert |
IDM_TASK_NEW | Auftrag erhalten |
IDM_TASK_UPDATE | Neues Auftragsziel |
IDM_NEW_EMAIL | Neue Nachricht erhalten |
IDM_NEW_ENERGYCLASS |  |
IDM_NEW_MISSILE_1 |  |
IDM_NEW_MISSILE_2 |  |
IDM_NEW_LOGENTRY | Neuer Tagebucheintrag |
IDM_NEW_SMUGGLING |  |
IDM_NEW_WEAPONCLASS |  |
IDM_ARTEFACT | Artefakt aufgenommen |
IDM_ARTEFACT2 | Upgrade möglich |
IDM_ARTEFACT3 | Noch %1 bis zum nächsten Upgrade | %1 = StringID für Replace
IDM_ALL_ARTEFACTS | Alle 100 Artefakte gesammelt! Zwischenweltantrieb freigeschaltet! |
IDM_ATMOSPHERE | Planet zu nah |
IDM_CREDITS | %1 erhalten | %1 = StringIDs für Replace
IDM_CRIME_LVL1 | Strafenregister: Vorbestraft |
IDM_CRIME_LVL2 | Strafenregister: Gesucht |
IDM_CRIME_LVL3 | Strafenregister: Verbrecher |
IDM_CRIME_LVL4 | Strafenregister: Schwerverbrecher |
IDM_CRIME_LVL5 | Strafenregister: Top-Terrorist |
IDM_CRIMELEVEL_HIGH |  |
IDM_ESCORT_FAILED | Geleitschutz gescheitert! |
IDM_ESCORT_SUCCESS | Geleitschutz erfüllt! |
IDM_GLOBAL_024_HEADER | Satelliten-Sabotage |
IDM_GLOBAL_024_HUNTER | Wartungsservice |
IDM_GLOBAL_024_ITEM | Portscanner |
IDM_GLOBAL_024_USE | Manipulation erfolgreich |
IDM_GLOBAL_WEAPON | Geheimdienstwaffe erhalten |
IDM_NEW_HYPERDRIVE | %1-Lj-Antrieb erhältlich |
IDM_PIRATE_KILL | %1 Kopfgeld erhalten |
IDM_THREAT_LVLUP | Neue Einstufung: %1 | %1 = StringID für Replace

Liste mit allgemeinen String-IDs in der "global.res"
Allgemeine z.T. noch nicht ermittelte StringIDs
Angezeigter Text | StringId | Kommentar
Abhörposition | IDM_GLOBAL_018_WAYPOINTNAME |
Alkoholische Getränke | IDM_STORY_016_CONTAINER1 |
Ärger mit den Kriminellen | IDM_GLOBAL_030_HEADER |
Artefakt erhalten | ? |
Aufnahme läuft. | IDM_GLOBAL_018_GUI |
Bergung | IDM_GLOBAL_006_HEADER |
Berüchtigter Pirat | IDM_GLOBAL_043_HEADER |
Chip-Prototypen | IDM_GLOBAL_031_GOODS |
Computerteile | IDM_GLOBAL_002_CONTAINER_CONTENT |
Container vergessen | IDM_GLOBAL_039_HEADER |
Container wird angedockt | ? |
Diebesgut | IDM_GLOBAL_011_GOODS |
Ersatzteile | IDM_GLOBAL_042_CONTAINER |
Forschungsausrüstung | IDM_GLOBAL_025_CONTAINER |
Frachter braucht Unterstützung bei Containersuche. | IDM_GLOBAL_038_HEADER |
Frachter-Unterstützung | IDM_GLOBAL_032_HEADER |
Gauner ausrauben | IDM_GLOBAL_037_HEADER |
Gemischte Blumen | IDM_GLOBAL_009_CONTAINER |
Gestohlene Güter | IDM_GLOBAL_011_HEADER |
GU-Strafenregister gelöscht | ? |
Helfer | IDM_GLOBAL_043_WINGNAME_1 |
Konferenz "mit Ohren" | IDM_GLOBAL_018_HEADER |
Kopfgeldjagd | IDM_GLOBAL_010_HEADER |
Kopfgeldjäger | IDM_STORY_003_WINGNAME |
Laser-Mikrofon | IDM_GLOBAL_018_USEITEM |
Leibgarde | IDM_GLOBAL_043_WINGNAME_2 |
Lieferdienst | IDM_GLOBAL_042_HEADER |
Manchmal kommt alles anders als beauftragt | IDM_GLOBAL_022_HEADER |
Piratenbasis | IDM_STORY_016_PIRATEBASE |
Plasma-Resonanz-Kollektor | IDM_STORY_011_CONTAINER5 |
Polizeischiff nähert sich zum Scannen. | ? |
Raptor-Waffen | IDM_BAR_007_CARGO |
Routinepatrouille? | IDM_GLOBAL_035_HEADER |
Sabotage | IDM_GLOBAL_005_HEADER |
Scanvorgang wurde erfolgreich gestört | ? |
Spielstand gespeichert | ? |
Terrorist | ? |
Transport | ? |
Verbrecher | ? |
Vorbestraft | ? |
Wenn zwei sich streiten, freut sich der Dritte | ? |
? | ID_EXIT |
? | ID_NEWGAME |
? | ID_OPTION_TAB_GAMEPLAY |
? | ID_OPTION_TAB_GFX |
? | ID_OPTION_TAB_SOUND |
? | ID_OPTION_TAB_STEUERUNG |

Rot: StringId in der "user_strings.res" definiert.


Wingtypen

Die Wingtypen, die erzeugt werden können
Konstante | Kommentar | Wert
WINGTYPE_HUNTER | Ein Wing mit normalen Jägern (Kopfgeldjäger bzw. Geleitschiffe). | 0
WINGTYPE_FREIGHTER50T
Ein Wing mit einem Frachter (200/400t), der 4 oder 8 Container á 50t transportieren kann.
Die Anzahl der Containerplätze wird zufällig erzeugt. Alle weiteren Schiffe des Wings sind Hunter.
1
WINGTYPE_FREIGHTER100T
Ein Wing mit einem Frachter (200/400/600t), der 2, 4 oder 6 Container á 100t transportieren kann.
Die Anzahl der Containerplätze wird zufällig erzeugt. Alle weiteren Schiffe des Wings sind Hunter.
2
WINGTYPE_FREIGHTER200T
Ein Wing mit einem Frachter (600t), der 3 Container á 200t transportieren kann.
Die Anzahl der Containerplätze ist immer 3. Alle weiteren Schiffe des Wings sind Hunter.
3
WINGTYPE_POLICE | Ein Polizei-Wing. | 4
WINGTYPE_MILITARY | Ein Wing mit Militärjägern. | 5
WINGTYPE_CRUISER1 | Ein Wing aus großen Kreuzern mit Hangar. Geleitschiffe werden nicht erzeugt. | 6
WINGTYPE_CRUISER2 | Ein Wing aus kleinen Kreuzern ohne Hangar. Geleitschiffe werden nicht erzeugt. | 7
WINGTYPE_WEAPONBASE | Ein Wing aus Waffenplattformen mit je einem Laser-Geschützturm. | 8
WINGTYPE_PIRATES | Ein normaler Piratenwing für den Angriff auf Schiffe. | 9
WINGTYPE_RAIDERS | Ein Piratenwing mit besonderer Logik für den Raub von Containern. | 10
WINGTYPE_PIRATEFREIGHTER
Ein Wing nur aus Piratenfrachtern ohne Geleitschiffe.
Anzahl der Containerplätze und Containergröße werden zufällig erzeugt.
11
WINGTYPE_SKAA | Der Wing ist ein S'kaa-Schwarm. | 12
WINGTYPE_PIRATEFREIGHTER50T
Ein Wing mit einem Piratenfrachter, der 50t-Container transportieren kann.
Die Anzahl der Containerplätze wird zufällig erzeugt. Alle weiteren Schiffe sind Hunter, keine Piraten!
13
WINGTYPE_PIRATEFREIGHTER100T
Ein Wing mit einem Piratenfrachter, der 100t-Container transportieren kann.
Die Anzahl der Containerplätze wird zufällig erzeugt. Alle weiteren Schiffe sind Hunter, keine Piraten!
14
WINGTYPE_PIRATEFREIGHTER200T
Ein Wing mit einem Piratenfrachter, der 200t-Container transportieren kann.
Die Anzahl der Containerplätze ist immer 3. Alle weiteren Schiffe sind Hunter, keine Piraten!
15
WINGTYPE_FREIGHTER200CAP | Ein Wing mit einem Frachter, der Kapazität für 200t Ladung hat. Es können 2 Container á 100t oder 4 Container á 50t angedockt werden. Alle weiteren Schiffe des Wings sind Hunter. | 16
WINGTYPE_FREIGHTER400CAP | Ein Wing mit einem Frachter, der Kapazität für 400t Ladung hat. Es können 4 Container á 100t oder 8 Container á 50t angedockt werden. Alle weiteren Schiffe des Wings sind Hunter. | 17
WINGTYPE_FREIGHTER600CAP | Ein Wing mit einem Frachter, der Kapazität für 600t Ladung hat. Es können 3 Container á 200t oder 6 Container á 100t angedockt werden. Alle weiteren Schiffe des Wings sind Hunter. | 18
WINGTYPE_BASESHIP | Eine einzelne Piratenbasis. | 19
WINGTYPE_WEAPONBASE2 | Ein Wing aus Waffenplattformen mit je zwei Laser-Geschütztürmen. | 20
WINGTYPE_SUPERFREIGHTER * | Ein Wing mit einem Superfrachter (Raptor: 8000t; Arrack: 8400t; Terraner: 9000t), der 40, 42 oder 45 Container á 200t oder Spezialcontainer transportieren kann.** | 21
* Konstante in der MissionLibEx.lua definiert.
** Seitens des Programms von Darkstar One gibt es keine Konstante für die Erzeugung eines Superfrachter-Wings. Tests mit Zahlen von 21 bis 1.000.000 brachten keinen Erfolg. Superfrachter lassen sich aber mit der Funktion NWing.Define() und Verwendung des passenden StarShip-Typs, wie z.B. mit ST_TRADERSHIP, erzeugen. Nähere Erklärungen und Beispiele dazu sind der Beschreibung von NWing.Define als "Special: Superfrachterwings" beigefügt.

Wingaktionen (1)

Die Aktionen von Wings, die mit NWing.AddAction definiert werden können
Konstante | Kommentar | Wert
AI_ACTION_INAKTIV AI_ACTION_INACTIVE | Wing ist völlig regungslos und reagiert auch nicht auf Angriffe. | 0
AI_ACTION_STATISCH AI_ACTION_STATIC | Wing ist regungslos, führt aber eine Gegnerliste und feuert auf Gegner in Schussweite. | 1
AI_ACTION_WARTEN AI_ACTION_WAIT | Wing ist regungslos, bis seine Gegnerliste einen Eintrag erhält. | 2
AI_ACTION_ANGRIFF AI_ACTION_ATTACK | Wing greift alle Gegner seiner Gegnerliste sofort an. | 3
AI_ACTION_CONTANGRIFF AI_ACTION_CONTATTACK | Wie Angriff, jedoch sucht sich der Wing automatisch einen neuen Gegnerwing aus der Gruppen-KI. | 4
AI_ACTION_POSITION1 | Wing wird zu einer neuen absoluten Position geschickt. Gegner werden mit den Geschütztürmen beschossen, die Schiffe ändern aber nicht ihren Kurs. | 5
AI_ACTION_POSITION2 | Wing wird zu einer neuen absoluten Position geschickt. Gegner werden angegriffen, wobei der Anflug auf die Position unterbrochen wird. | 6
AI_ACTION_OBJECT1 | Wing wird zu einem SpaceObject geschickt. Gegner werden nicht angegriffen. | 7
AI_ACTION_OBJECT2 | Wing wird zu einem SpaceObject geschickt. Gegner werden angegriffen. | 8
AI_ACTION_LANDEN AI_ACTION_LAND | Wing landet auf dem angegebenen Objekt (Hangar), wenn keine Gegner in der Nähe sind. | 9
AI_ACTION_KREISEN AI_ACTION_CIRCLE | Wie Warten, jedoch kreist der Wing um die aktuelle Position. Hat der Wing Gegner, wird das Kreisen beendet und der Gegner angegriffen. | 10
AI_ACTION_PATROUILLE AI_ACTION_PATROL | Wing fliegt von einer Position zur nächsten. Hier können bis zu 4 Positionsangaben und mehr folgen. | 11
AI_ACTION_BESCHUETZEN AI_ACTION_PROTECT | Wing soll einen anderen Wing beschützen. Er folgt diesem in einem Standard-Abstand. Funktioniert mit Militär- und Kreuzer-Wings nur sehr eingeschränkt. | 12
AI_ACTION_BEWACHEN AI_ACTION_GUARD | Wing soll einen Container bewachen. | 13
AI_ACTION_BERGEN AI_ACTION_PICKUP | Wing soll einen Container bergen. | 14
AI_ACTION_ABWERFEN AI_ACTION_DROP | Bezeichnet das Handle einen Container, wird nur dieser abgeworfen. Sonst werfen alle Schiffe des Wings alle ihre Container ab. | 15
AI_ACTION_HYPERRAUM AI_ACTION_HYPERJUMP | Wing soll in den Hyperraum. Ist der Spieler im Wing, springt dieser zusammen mit dem Wing in das angegebene System (inklusive Kamera). Ein Missions-Wing der nur aus KI-Schiffen besteht, wird beim Verlassen des Systems gelöscht und es wird ein WING_DESTROYED Event ausgelöst. | 16
AI_ACTION_BOSSKREISEN AI_ACTION_BOSSCIRCLE | Wing kreist um die aktuelle Position. Speed wird als Radius interpretiert. Der Status endet nicht, wenn Gegner eingetragen werden. | 17
AI_ACTION_EINTRITT AI_ACTION_ENTRY | Wing kämpft gegen Gegner in seiner Nähe. Ist der angegebene Wing bzw. Schiff im System angekommen, wird eine neue Aktion gestartet. | 18
AI_ACTION_DESTROYOBJ | Wing stellt sich vor das Objekt und beschießt es mit seinen Frontwaffen. | 19
? |  | 20
AI_ACTION_ESKORTE AI_ACTION_ESCORT | Wing fliegt zu einer Position. Kleine Schiffe (auch als Leader) dürfen die Formation verlassen, um Gegner anzugreifen. | 21
AI_ACTION_FOLGESCHIFF AI_ACTION_FOLLOWSHIP | Handle bezeichnet ein Schiff eines anderen Wings, dem gefolgt werden soll. Position bestimmt die Richtung vom Wing zum Leader des zu folgenden Wings. | 22
AI_ACTION_POSANGRIFF AI_ACTION_POSATTACK | Die gegebene 3D-Position wird angeflogen und beschossen. | 23
AI_ACTION_ACTIONTURRET | Der ActionTurret wird angegriffen. | 24
AI_ACTION_SOFORTSPRUNG AI_ACTION_HYPERJUMPNOW | Wie AI_ACTION_HYPERRAUM. Allerdings werden die Schiffe der Gegnerliste nicht angegriffen. | 25
AI_ACTION_SOFORTLANDEN AI_ACTION_LANDNOW | Wing landet auf dem angegebenen Objekt (Hangar), auch wenn Gegner in der Nähe sind. | 26
? | -/- | 27
? | -/- | 28
? | -/- | 29
? | -/- | 30
? | -/- | 31
? | wie AI_ACTION_STATISCH | 32
AI_ACTION_GETLIST | Eine neue Aktion aus der Aktionsliste soll gestartet werden, funktioniert jedoch nicht für bereits aktive Listen. Kann aber für vorbereitete Listen zum Löschen eines Eintrags verwendet werden, da mit nil die nächste Aktion sonst nicht gestartet wird. | 33
AI_ACTION_STANDARD | Die Standard-Ai des Wings wird gestartet. | 34
AI_ACTION_SKAA_ATTACK | Der S'kaa-Wing greift das Schiff an. Dieser Befehl funktioniert nur mit Wings, die als WINGTYPE_SKAA erzeugt wurden! | 35
AI_ACTION_SKAA_ACTIONTURRET | Ist der CActionTurret aktiv, wird dessen Zielschiff angegriffen. Andere Ziele werden nicht beachtet. Dieser Befehl funktioniert nur mit Wings, die als WINGTYPE_SKAA erzeugt wurden! | 36
? | wie entweder AI_ACTION_STANDARD, AI_ACTION_HYPERRAUM oder AI_ACTION_SOFORTSPRUNG | 37
? | wie entweder AI_ACTION_STANDARD, AI_ACTION_HYPERRAUM oder AI_ACTION_SOFORTSPRUNG | 38
AI_ACTION_POLICESCAN | Der Wing fliegt zur Position. Das Spielerschiff wird gescannt, wenn es in die Nähe kommt. Bei Position {0,0,0} probiert der Wing einen Scan an der aktuellen Position, wenn kein Spieler in Reichweite ist, ignorieren sie die Aktion. Dieser Befehl funktioniert nur mit Wings, die als WINGTYPE_POLICE erzeugt wurden! | 39

Wingaktionen (2)

Die Aktionslisten, die von NWing.AddAction bei besonderen Situationen aktiviert werden
Konstante | Kommentar | Wert
LIST_ACTIVE | Liste, die zur Zeit abgearbeitet wird | 0
LIST_SHIELD | Wird aktiviert, wenn ein Schiff seinen Schild verloren hat | 1
LIST_FIRST_SHIP | Wird aktiviert, wenn das erste Schiff des Wings zerstört wurde | 2
LIST_HALF | Wird aktiviert, wenn die Hälfte der Schiffe des Wings zerstört wurden | 3
LIST_LAST_SHIP | Wird aktiviert, wenn der Wing nur noch ein Schiff hat | 4
LIST_NO_ENEMY | Wird aktiviert, wenn der Wing keinen Gegner mehr hat | 5
LIST_PLAYER | Wird aktiviert, wenn der Wing ein Gegner des Spielers wird | 6

Wingstatus

Ereignisse, die im "Wing"-Event abgefragt werden können
Konstante | Kommentar | Wert
WING_NO_TARGET | Der Wing hat kein Ziel zum Angreifen mehr | 1
WING_DESTROYED | Das letzte Schiff des Wings wurde zerstört und der Wing wird unmittelbar im Anschluß gelöscht | 2
WING_TARGET_REACHED | Der Wing hat eine vorher festgelegte Raumkoordinate erreicht | 3
WING_ENTER_SYSTEM | Alle Schiffe des Wings haben das aktive System betreten | 4
WING_LEAVE_SYSTEM | Alle Schiffe des Wings verlassen gleich das aktive System | 5
WING_SHIP_SHIELDDOWN | Ein Schiff hat im Kampf seinen Schild verloren | 6
WING_SHIP_DESTROYED_1 | Der Wing hat das erste Schiff im Kampf verloren | 7
WING_SHIP_DESTROYED_2 | Der Wing hat die Hälfte seiner Schiffe im Kampf verloren | 8
WING_SHIP_DESTROYED_3 | Der Wing hat nur noch ein Schiff | 9
WING_SHIPS_LANDED | Das letzte Schiff des Wings ist in einem Hangar gelandet | 10
WING_FIRST_ENEMY | Die Gegnerliste des Wings war leer, enthält jetzt aber wieder einen Gegner | 11
WING_CARGO_GRABBED | Der Wing hat seinen Auftrag, einen Container aufzunehmen beendet. Der Container muß nicht aufgenommen worden sein | 12
WING_ACTIONLIST_EMPTY | Die Aktionsliste des Wings ist leer | 13

Wingverhalten

Aktionen, wofür?
Konstante | Kommentar | Wert
PATROUILLE |  | 0
KILLER |  | 1
PIRATE |  | 2
JUMP |  | 3
DOCK |  | 4
PLAYERKILLER |  | 5

Wingformationen *

Alle in der WingInfo.ini standardmäßig vorhandenen Wingformationen
Die Werte entsprechen dem Index der jeweiligen Formation in der WingInfo.ini
Konstante | Kommentar | Wert
FORMATION_DELTA | Jägerwings | 0
FORMATION_DELTA_2 | Jägerwings | 1
FORMATION_V_SHAPE | Jägerwings | 2
FORMATION_ESCORT | Frachtergeleitschutz | 3
FORMATION_CHAIN | Jägerwings | 4
FORMATION_SKAA | "Alte" S’kaa-Formation | 5
FORMATION_LINE_RIGHT | Jägerwings | 6
FORMATION_PLAYER_WING | Spielerwing | 7
FORMATION_SKAA_10 | S’kaa-Wings mit 10 Schiffen | 8
FORMATION_SKAA_9 | S’kaa-Wings mit 9 Schiffen | 9
FORMATION_SKAA_8 | S’kaa-Wings mit 8 Schiffen | 10
FORMATION_SKAA_7 | S’kaa-Wings mit 7 Schiffen | 11
FORMATION_SKAA_6 | S’kaa-Wings mit 6 Schiffen | 12
FORMATION_SKAA_5 | S’kaa-Wings mit 5 Schiffen | 13
FORMATION_SKAA_4 | S’kaa-Wings mit 4 Schiffen | 14
FORMATION_SKAA_3 | S’kaa-Wings mit 3 Schiffen | 15
FORMATION_SKAA_2 | S’kaa-Wings mit 2 Schiffen | 16
FORMATION_SKAA_1 | S’kaa-Wings mit 1 Schiff | 17
FORMATION_CRUISER | Kreuzerwings | 18
FORMATION_WEAPONBASE | Waffenplattformen | 19
FORMATION_CLUSTER_GROUP | Clustergruppe | 20
FORMATION_PLAYER_NPC | Missionswing mit Spielerschiff | 21
FORMATION_SUPERFRACHTER | Geleitschutz für Superfrachter | 22
Eigene Formationen der WingInfo.ini hinzugefügt
FORMATION_DELTA_INV | Wie DELTA, aber invertiert. Boss fliegt hinten. | 23
FORMATION_ARROW_10 | Pfeil | 24
FORMATION_ARROW_2_10 | Doppelter Pfeil (die beste Formation) | 25
FORMATION_ARROW_3D_10 | 3D-Pfeil | 26
FORMATION_DIAMOND_10 | Raute | 27
FORMATION_CIRCLE_8 | Kreis, Boss fliegt im Zentrum | 28
FORMATION_PYRAMID | Pyramide | 29
FORMATION_LINE_CENTER | Gerade Linie auf der X-Achse, Boss im Zentrum | 30
FORMATION_CRUISER_ESCORT | Flankenschutz für Kreuzer | 31
* Konstanten in der MissionLibEx.lua definiert.


Wirtschaft

Wirtschaft und Wohlstand

Eine Aufzählung aller Wirtschaftsformen
Konstante | Kommentar | Wert
SYSTEM_AGRICULTURE | Agrarsystem | 0
SYSTEM_MINING | Minenkolonie | 1
SYSTEM_INDUSTRY | Industriesystem | 2
SYSTEM_PHARMACEUTICS | Pharmakolonie | 3
SYSTEM_RESEARCH | Forschungskolonie | 4
SYSTEM_SERVICE | Dienstleistungen | 5

Wohlstand (Lebensstandard) der Systeme
Konstante | Kommentar | Wert
WEALTH_POOR | Armes System - niedrige Preise für Einkauf, hoher Erlös für Verkauf | 0
WEALTH_WEALTHY | Wohlhabendes System - normale Preise | 1
WEALTH_RICH | Reiches System - hohe Preise für Einkauf, niedriger Erlös für Verkauf | 2

Tipp: Kaufe nach Möglichkeit die Handelswaren hauptsächlich in armen Sternsystemen ein und verkaufe sie auch wieder in den armen Systemen. So ist die Gewinnspanne meistens am höchsten. Nur wenn in reichen Systemen die Menge der Exportwaren sehr hoch ist, kann sich auch dort der Einkauf lohnen. Eine Ausnahme ist der Verkauf von Geheimdienstwaffen, für die gibt es Festpreise, welche in reichen Systemen am höchsten sind. Bei den Schmuggelwaren ist es dagegen genau umgekehrt und es gilt dasselbe wie für die normalen Handelswaren.


INI-Dateien

Für Modifikationen benötigte INI-Dateien in den Verzeichnissen "inifiles\" und "inifiles\Infos\"

Inhalt

  1. Afterburners.ini
  2. Cluster.ini *
  3. Equipment.ini
  4. Explosion.ini
  5. HitPoint.ini
  6. Items.ini
  7. Planets.ini
  8. Projectiles.ini
  9. StarCluster.ini
  10. StarShip.ini
  11. StarSystem.ini
  12. Systemeigenschaften.ini *
  13. Upgrades.ini
  14. WeaponEffects.ini
  15. WingInfo.ini

* Dateien, die sich im Modding-Ordner "inifiles\Infos\" befinden.
Alle anderen Dateien befinden sich im Modding-Ordner "inifiles\".

Allgemeine Hinweise zu den INI-Dateien

Die in Darkstar One verwendeten INI-Dateien folgen der allgemein üblichen Syntax dieses Dateityps:

[Sektion] ; Kommentar
Name1 = Wert
Name2 = Wert ; Kommentar

Wie in den Beispielen hier und da zu sehen ist, wurden in einigen Fällen zusätzliche Infos hinzugefügt (in der StarSystem.ini z.B. die System- und Clusternamen zum schnelleren Auffinden eines gesuchten Systems). Alles, was in einer Zeile hinter einem Semikolon folgt, wird vom Programm als Kommentar behandelt und nicht ausgewertet. Somit ist es auch möglich, bei Wertänderungen eine ganze Zeile zu kopieren und eine mit einem Semikolon am Anfang komplett auszukommentieren, während die andere geändert wird. Somit kann man jederzeit wieder auf die ursprünglichen Einstellungen zurückgreifen, wenn mal etwas nicht so klappt wie gewünscht:

[System020] ; Oma {Tau Ceti}
...
PosX = 2.300000 ; geänderte x-Position auf der Karte
;PosX = 1.800000 ; x-Position auf der Karte
PosY = 5.930000 ; geänderte y-Position auf der Karte
;PosY = 0.930000 ; y-Position auf der Karte
...

Wichtig: Wie schon im ModdingGuide erwähnt, bitte nicht vergessen, nach jeder Änderung an den INI-Dateien die Datei "ini_file.bin" vor dem Programmstart zu löschen, damit sie beim nächsten Start vom Programm neu erzeugt wird und somit die Änderungen auch beinhaltet. Lief das Programm noch im Hintergrund während der Änderung (Taskwechsel), muss es zunächst beendet und wieder neu gestartet werden.


Aberrations.ini

Aberrations.ini (Anomalie-Effekte)

Änderungen und Erweiterungen in der Datei inifiles\Aberrations.ini

Beispiel:


ActionCams.ini

ActionCams.ini (Kameras)

Änderungen und Erweiterungen in der Datei inifiles\ActionCams.ini

Beispiel:


Afterburners.ini

Afterburners.ini (Nachbrenner)

Änderungen und Erweiterungen in der Datei inifiles\Afterburners.ini

Beispiel:

Nachbrenner-Geschwindigkeiten der DSO erhöhen

Um die Geschwindigkeiten des Nachbrenners in den einzelnen Energieleveln der DSO zu erhöhen, muss in den folgenden Sektionen der Wert für 'SpeedMax' entsprechend geändert werden (Standard = 1.5 für 150% Maximalgeschwindigkeit). Zur korrekten Anzeige der geänderten Werte können noch in der "user_strings.res" die fehlenden StringIds definiert und in der Datei Items.ini eingetragen werden.
Nützliche Nebeneffekte dieser Änderung: Spätestens ab dem Energielevel 3 werden Graviton-Schub und Nachbrenner-Booster überflüssig. Die erhöhten Geschwindigkeiten sind genauso wie bisher zeitlich dem erreichten Energielevel entsprechend begrenzt und stehen nach der Aufladung des Nachbrenners immer wieder zur Verfügung.
Ein kleiner Nachteil kann es eventuell sein, dass auch die Startgeschwindigkeiten aus den Hangars der Stationen, Asteroiden und Kreuzer höher sind und man weiter herauskatapultiert wird. Übertreibt man es mit dem Wert, findet man sich z.B. nach dem Start aus der Handelsstation plötzlich hinter dem Hyperraumtor wieder. Außerdem sind Kollisionen bei zu hohen Werten absolut tödlich.

Tipp: Setze diesen Wert möglichst nicht über ca. 6.0 bis 10.0 (600% - 1000%), sonst kann es zu ziemlich unschönen Grafikfehlern kommen, die auch nach dem Abschalten des Nachbrenners bestehen bleiben können. Dies kann auch mit dem Befehl NPlayer.SetMultipliers per Skript getestet werden, bevor man die Afterburners.ini ändert. Die hier eingetragenen Werte haben sich im Spiel gut bewährt.

[afterburner016] ; SPACE_SHIP
DriveTime = 250 ; Brenndauer des Afterburners in Zeitschritten
Level = 1 ; Level
Name = ab_player_level_1 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 1.600000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner017] ; SPACE_SHIP
DriveTime = 300 ; Brenndauer des Afterburners in Zeitschritten
Level = 2 ; Level
Name = ab_player_level_2 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 1.800000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner018] ; SPACE_SHIP
DriveTime = 350 ; Brenndauer des Afterburners in Zeitschritten
Level = 3 ; Level
Name = ab_player_level_3 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 2.000000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner019] ; SPACE_SHIP
DriveTime = 400 ; Brenndauer des Afterburners in Zeitschritten
Level = 4 ; Level
Name = ab_player_level_4 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 2.500000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner020] ; SPACE_SHIP
DriveTime = 450 ; Brenndauer des Afterburners in Zeitschritten
Level = 5 ; Level
Name = ab_player_level_5 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 3.000000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner021] ; SPACE_SHIP
DriveTime = 500 ; Brenndauer des Afterburners in Zeitschritten
Level = 6 ; Level
Name = ab_player_level_6 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 3.500000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner022] ; SPACE_SHIP
DriveTime = 550 ; Brenndauer des Afterburners in Zeitschritten
Level = 7 ; Level
Name = ab_player_level_7 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 4.000000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner023] ; SPACE_SHIP
DriveTime = 625 ; Brenndauer des Afterburners in Zeitschritten
Level = 8 ; Level
Name = ab_player_level_8 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 4.500000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )

[afterburner024] ; SPACE_SHIP
DriveTime = 750 ; Brenndauer des Afterburners in Zeitschritten
Level = 9 ; Level
Name = ab_player_level_9 ; Namensalias für Referenz in anderen Konfigurationsdateien ( MUSS eindeutig sein )
ObjectType = 2 ; SPACE_SHIP
RechargeTime = 0.000000 ; Faktor für die Aufladedauer in Zeitschritten ( in Bezug auf DriveTime )
SpeedMax = 5.000000 ; Faktor für maximale Geschwindigkeit ( siehe StarFlight.ini )


Cluster.ini

Cluster.ini (Sterncluster)

Änderungen in der Datei inifiles\Infos\Cluster.ini

Diese Datei beinhaltet die Sektionen [Cluster0] bis [Cluster29] für die in Darkstar vorhandenen 30 Sternencluster mit den Positionsdaten der Sterne auf der Navigationskarte. Der Aufbau der einzelnen Sektionen ist für alle Cluster der gleiche und wird im folgenden anhand von Lalande kurz beschrieben:

[Cluster0] ; Lalande
Sterne = 12	     ; Anzahl der Systeme in diesem Cluster
Mitte = 7.35, 15.55  ; X- und Y-Koordinate vom Mittelpunkt des Clusters
Stern0 = 4.5, 17.8   ; X- und Y-Koordinate des Systems mit der SystemId 0  (Witon)
Stern1 = 5.4, 12     ; X- und Y-Koordinate des Systems mit der SystemId 1  (Cloosa)
...
Stern11 = 7.5, 17.5  ; X- und Y-Koordinate des Systems mit der SystemId 11 (Pachee)
Beispiel:

Terraner-Cluster Tau Ceti verschieben

Wird der versteckte Cluster Tau Ceti in den beiden Dateien StarSystem.ini und Systemeigenschaften.ini freigeschaltet, stellt man fest, dass er ziemlich weit oben links in der Ecke der Karte liegt. Viel zu weit weg, um ihn mit dem anfangs auf nur 2,5 - 3 Lichtjahre Reichweite begrenzten Sprungantrieb von Lalande aus erreichen zu können. Daher verschieben wir einfach den ganzen Cluster durch eine Erhöhung der Y-Werte in den 6 Sternensystemen und der 'Mitte' um 5 Lichtjahre nach unten (alle Y-Werte um 5.0 erhöhen).

Mit der Originaleinstellung der X-Werte ist das System Patiak (Stern22) auf der Karte gar nicht und das System Tasakane (Stern21) nur bei genauem Hinsehen zu erkennen, da sie zu weit links am Rand liegen. Das kann gleich mit geändert werden, indem der X-Wert um 0.5 erhöht wird. Damit verschieben sich die beiden Sterne um ein halbes Lichtjahr nach rechts und werden deutlich sichtbar. Möchte man die ursprüngliche Geometrie des Clusters beibehalten, kann man dasselbe noch mit den anderen 4 Systemen und der 'Mitte' machen.

[Cluster2] ; Tau Ceti
Sterne = 6
Mitte = 3.55, 8.385
Stern20 = 2.3, 5.93
Stern21 = 1.68, 7.6
Stern22 = 1.5, 9.3
Stern23 = 4.1, 8.3
Stern24 = 3.32, 10.84
Stern25 = 5.6, 9.36

Die Positionsänderungen müssen ebenfalls noch in der Datei StarSystem.ini in den Werten für 'PosX' und 'PosY' eingetragen werden, und die Änderung der 'Mitte' in der Datei StarCluster.ini beim gleichnamigen Wert.

Sollten mal ein oder mehrere Sternensysteme von einem Cluster in einen anderen verschoben und auch dem neuen Cluster zugeordnet werden, muss nicht nur hier die Anzahl 'Sterne' angepasst werden, sondern auch in der Datei StarCluster.ini. Weiterhin muss man in der StarSystem.ini außer den X/Y-Koordinaten noch die ClusterId vom Eintrag 'Cluster' im jeweiligen System anpassen.
Andererseits könnte man dies auch sein lassen. Das hätte dann zu Folge, dass beim Verschieben z.B. eines Mortok-Systems in den Cluster Lalande schon zu Beginn des Spiels die Railguns der Mortok zur Verfügung stünden, sobald man dieses System betreten hat.


DanielsUpgrades.ini

DanielsUpgrades.ini (Aufrüstung)

Änderungen und Erweiterungen in der Datei inifiles\DanielsUpgrades.ini

Beispiel:


DroneController.ini

DroneController.ini (Fracht-Computer)

Änderungen und Erweiterungen in der Datei inifiles\DroneController.ini

Beispiel:


Drones.ini

Drones.ini (Fracht-Drohnen)

Änderungen und Erweiterungen in der Datei inifiles\Drones.ini

Beispiel:


Engines.ini

Engines.ini (Antriebe)

Änderungen und Erweiterungen in der Datei inifiles\Engines.ini

Beispiel:


Equipment.ini

Equipment.ini (Ausrüstung)

Änderungen und Erweiterungen in der Datei inifiles\Equipment.ini

Beispiel:

Scanner-Jammer nachrüsten

Nachrüstung von je einem Polizeiscanner-Jammer mit 40% und 80% Erfolgswahrscheinlichkeit durch Änderung der Werte 'Range01" und 'Range05'. Zur korrekten Anzeige in der Werft kann dazu für den Jammer mit 80% in der "user_strings.res" die StringId ID_WERFT_PERCENTAGE_80 mit dem Text "80%" definiert werden. Für den 40%-Scanner existiert der Wert schon in der "global.res". Beide StringIds dann noch in die Items.ini eintragen.

[ScannerJammer] ; Wahrscheinlichkeit der Scannerstörung
Range00 = 0.300000 ; Wahrscheinlichkeit im Level 0
Range01 = 0.400000 ; Wahrscheinlichkeit im Level 1
Range02 = 0.500000 ; Wahrscheinlichkeit im Level 2
Range03 = 0.600000 ; Wahrscheinlichkeit im Level 3
Range04 = 0.700000 ; Wahrscheinlichkeit im Level 4
Range05 = 0.800000 ; Wahrscheinlichkeit im Level 5
Range06 = 0.900000 ; Wahrscheinlichkeit im Level 6
Range07 = -1.000000 ; Wahrscheinlichkeit im Level 7
Range08 = -1.000000 ; Wahrscheinlichkeit im Level 8
Range09 = -1.000000 ; Wahrscheinlichkeit im Level 9


Explosion.ini

Explosion.ini (Explosions-Effekte)

Änderungen und Erweiterungen in der Datei inifiles\Explosion.ini

Die Sektionsnamen in der Datei sind gleich den Bezeichnern als String für die Explosionstypen, die von der Funktion NObject.CreateExplosion für den Parameter 'Type' verwendet werden.

Explosionstypen

Bezeichner | Beschreibung | Typ in ExplosionDef.ini
EXPLOSION_PLASMA_OVERLOAD | Blitzentladungen | Explosion000
EXPLOSION_PLASMA_EMP | Schneeschauer Im-/Explosion | Explosion001
EXPLOSION_PLASMA_TIMESHOCK | Grüner Ring | Explosion002
EXPLOSION_PLASMA_WEAPON | Schneeschauer Im-/Explosion | Explosion003
EXPLOSION_PLASMA_SHIELD | Schneeschauer Im-/Explosion | Explosion004
EXPLOSION_PLASMA_INVUL | Schneeschauer Im-/Explosion | Explosion037
EXPLOSION_DEBRIS_A | Trümmer, Terraner | Explosion005
EXPLOSION_DEBRIS_C | Trümmer, Mortok | Explosion006
EXPLOSION_DEBRIS_B | Trümmer, Raptor | Explosion007
EXPLOSION_DEBRIS_F | Trümmer, Oc’to | Explosion008
EXPLOSION_DEBRIS_D | Trümmer, Arrack | Explosion009
EXPLOSION_DEBRIS_E | Trümmer, Thul | Explosion010
EXPLOSION_DEBRIS_G | Trümmer, S’kaa | Explosion011
EXPLOSION_FIGHTER_A | Jäger A, Terraner | Explosion012
EXPLOSION_FIGHTER_C | Jäger C, Mortok | Explosion013
EXPLOSION_FIGHTER_B | Jäger B, Raptor | Explosion014
EXPLOSION_FIGHTER_F | Jäger F, Oc’to | Explosion015
EXPLOSION_FIGHTER_D | Jäger D, Arrack | Explosion016
EXPLOSION_FIGHTER_E | Jäger E, Thul | Explosion017
EXPLOSION_FIGHTER_G | Jäger G, S’kaa | Explosion018
EXPLOSION_FREIGHTER_A | Frachter A, Terraner | Explosion019
EXPLOSION_FREIGHTER_C | Frachter C, Mortok | Explosion020
EXPLOSION_FREIGHTER_B | Frachter B, Raptor | Explosion021
EXPLOSION_FREIGHTER_F | Frachter F, Oc’to | Explosion022
EXPLOSION_FREIGHTER_D | Frachter D, Arrack | Explosion023
EXPLOSION_FREIGHTER_E | Frachter E, Thul | Explosion024
EXPLOSION_FREIGHTER_G | Frachter G, S’kaa | Explosion025
EXPLOSION_CRUISER_A_0 | Großer Kreuzer A, Terraner | Explosion026
EXPLOSION_CRUISER_C_0 | Großer Kreuzer C, Mortok | Explosion027
EXPLOSION_CRUISER_B_0 | Großer Kreuzer B, Raptor | Explosion028
EXPLOSION_CRUISER_F_0 | Großer Kreuzer F, Oc’to | Explosion029
EXPLOSION_CRUISER_D_0 | Großer Kreuzer D, Arrack | Explosion030
EXPLOSION_CRUISER_E_0 | Großer Kreuzer E, Thul | Explosion031
EXPLOSION_CRUISER_G_0 | Großer Kreuzer G, S’kaa | Explosion032
EXPLOSION_CRUISER_A_1 | Kleiner Kreuzer A, Terraner | Explosion038
EXPLOSION_CRUISER_C_1 | Kleiner Kreuzer C, Mortok | Explosion039
EXPLOSION_CRUISER_B_1 | Kleiner Kreuzer B, Raptor | Explosion040
EXPLOSION_CRUISER_F_1 | Kleiner Kreuzer F, Oc’to | Explosion041
EXPLOSION_CRUISER_D_1 | Kleiner Kreuzer D, Arrack | Explosion042
EXPLOSION_CRUISER_E_1 | Kleiner Kreuzer E, Thul | Explosion043
EXPLOSION_MISSILE_SWARM | Schwarm-Rakete | Explosion033
EXPLOSION_MISSILE_HELLFIRE | Hellfire-Rakete | Explosion034
EXPLOSION_MISSILE_BIGBANG | Raumtorpedo (BigBang) | Explosion035
EXPLOSION_MISSILE_BIGBANG_CENTER | Raumtorpedo (BigBang) mit Zentrumblitz | Explosion036
EXPLOSION_HIDEOUT | Piratenbasis | Explosion045
EXPLOSION_METEROID1 | Meteorit aus Stein | Explosion044
EXPLOSION_METEROID_0 | Stein 25m | Explosion049
EXPLOSION_METEROID_1 | Stein 50m | Explosion050
EXPLOSION_METEROID_5 | Stein 75m | Explosion051
EXPLOSION_METEROID_2 | Stein 100m | Explosion052
EXPLOSION_METEROID_3 | Stein 150m | Explosion053
EXPLOSION_METEROID_4 | Stein 750m | Explosion054
EXPLOSION_MET_DEBRIS1 | Meteorit aus Metall | Explosion048
EXPLOSION_MET_DEBRIS_0 | Trümmerteile 10m | Explosion055
EXPLOSION_MET_DEBRIS_1 | Trümmerteile 25m | Explosion056
EXPLOSION_MET_DEBRIS_2 | Trümmerteile 30m | Explosion057
EXPLOSION_MET_DEBRIS_3 | Trümmerteile 50m | Explosion058
EXPLOSION_MET_DEBRIS_4 | Trümmerteile 75m | Explosion059
EXPLOSION_MET_DEBRIS_5 | Trümmerteile 100m | Explosion060
EXPLOSION_MET_DEBRIS_6 | Trümmerteile 130m | Explosion061
EXPLOSION_MET_ICE1 | Meteorit aus Eis | Explosion046
EXPLOSION_MET_ICE_0 | Eis 50m | Explosion062
EXPLOSION_MET_ICE_1 | Eis 100m | Explosion063
EXPLOSION_MET_ICE_2 | Eis 150m | Explosion064
EXPLOSION_MET_CRYSTAL1 | Meteorit aus Kristall | Explosion047
EXPLOSION_MET_CRYSTAL_0 | Kristall 30m | Explosion065
EXPLOSION_MET_CRYSTAL_1 | Kristall 50m | Explosion066
EXPLOSION_MET_CRYSTAL_2 | Kristall 75m | Explosion067
EXPLOSION_MET_CRYSTAL_3 | Kristall 100m | Explosion068
EXPLOSION_MET_CRYSTAL_4 | Kristall 130m | Explosion069
EXPLOSION_PLASMA_EMP_FLASH | Schneeschauer Im-/Explosion mit Zentrumblitz | Explosion070
EXPLOSION_MISSILE_SWARM_2 | Schwarm-Rakete mit dumpfem Knall | Explosion071

Beispiel:


ExplosionDef.ini

ExplosionDef.ini (Explosions-Definitionen)

Änderungen und Erweiterungen in der Datei inifiles\ExplosionDef.ini

Beispiel:


Galaxy.ini

Galaxy.ini (Galaxie)

Änderungen und Erweiterungen in der Datei inifiles\Galaxy.ini

Beispiel:


Globals.ini

Globals.ini (Grunddaten und Preise)

Änderungen und Erweiterungen in der Datei inifiles\Globals.ini

Beispiel:


Goods.ini

Goods.ini (Handelswaren)

Änderungen und Erweiterungen in der Datei inifiles\Goods.ini

Beispiel:


HitPoint.ini

HitPoint.ini (Schadensfaktoren)

Änderungen und Erweiterungen in der Datei inifiles\HitPoint.ini

Beispiel:

Lagerkapazität des Raketenwerfers erhöhen

Möchte man mehr Raketen zur Verfügung haben, muss hier nur die gewünschte Anzahl für jeden Waffenlevel geändert werden. Die Anzeige in der Werft wird dabei automatisch aktualisiert, es sind dafür keine weiteren Änderungen in anderen INI-Dateien notwendig.

[Missiles] ; Lagerkapazität für Raketen
Number00 = 5  ; org=5  ; wenn ein Raketenwerfer Level 0 eingebaut ist
Number01 = 8  ; org=8  ; wenn ein Raketenwerfer Level 1 eingebaut ist
Number02 = 12 ; org=10 ; wenn ein Raketenwerfer Level 2 eingebaut ist
Number03 = 15 ; org=12 ; wenn ein Raketenwerfer Level 3 eingebaut ist
Number04 = 20 ; org=15 ; wenn ein Raketenwerfer Level 4 eingebaut ist
Number05 = 25 ; org=18 ; wenn ein Raketenwerfer Level 5 eingebaut ist
Number06 = 30 ; org=20 ; wenn ein Raketenwerfer Level 6 eingebaut ist
Number07 = 35 ; org=25 ; wenn ein Raketenwerfer Level 7 eingebaut ist
Number08 = 40 ; org=30 ; wenn ein Raketenwerfer Level 8 eingebaut ist
Number09 = 50 ; org=40 ; wenn ein Raketenwerfer Level 9 eingebaut ist


InputControl.ini

InputControl.ini (Steuerung)

Änderungen und Erweiterungen in der Datei inifiles\InputControl.ini

Beispiel:


Items.ini

Items.ini (Texte für die Ausrüstung)

Ausrüstungsgegenstände in der Werft und im Schiffsinventar.

Aufbau der Einträge am Beispiel des Landecomputers X-3 im Level 3:
2 = 210,202,ID_WERFT_ITEMSTRING_3,ID_WERFT_U_3,ID_WERFT_ITEMSTRING_35,-1,ID_WERFT_ITEMSTRING_36,-1

2 = 			Ausrüstungslevel (intern, angezeigt wird Level 3)
210,			"ID_WERFT_ITEM_210" - Id vom Ausrüstungsname in der Werft und dem Inventar
202,			"ID_WERFT_ITEMDETAILS_202" - Id der Beschreibung unter dem "i"-Symbol
ID_WERFT_ITEMSTRING_3,	StringId der Kurzbeschreibung 1. Zeile: z.B. "Anzahl Drohnen", "Reichweite",...
ID_WERFT_U_3,		StringId der Daten 1. Zeile: z.B. die Reichweite
ID_WERFT_ITEMSTRING_35,	StringId der Kurzbeschreibung 2. Zeile: z.B. "Max. Größe", "Automatische Landung",...
-1,			StringId der Daten 2. Zeile: z.B. die maximale Containergröße (-1 ≡ nichts)
ID_WERFT_ITEMSTRING_36,	StringId der Kurzbeschreibung 3. Zeile: z.B. "Gesamt, "nach Landefreigabe",...
-1			StringId der Daten 3. Zeile: z.B. die Gesamtkapazität geschleppter Container

Werte von "-1" bedeuten, dass nichts angezeigt wird.

Änderungen und Erweiterungen in der Datei inifiles\Items.ini:

Beispiel:

Scanner-Jammer - modifizierte Werte korrekt anzeigen

Nachrüstung von je einem Polizeiscanner-Jammer mit 40% und 80% Erfolgswahrscheinlichkeit. Zur korrekten Anzeige des Jammers mit 80% muss dazu noch in der "user_strings.res" die StringId ID_WERFT_PERCENTAGE_80 mit dem Text "80%" definiert werden. Für den 40%-Scanner existiert der Wert schon in der "global.res". Die entsprechenden Werte müssen dann noch in der Equipment.ini geändert werden.

[Jammer]
0 = 200,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_30,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
1 = 201,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_40,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
2 = 202,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_50,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
3 = 203,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_60,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
4 = 204,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_70,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
5 = 205,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_80,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
6 = 205,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_90,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
7 = 205,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_90,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
8 = 205,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_90,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1
9 = 205,200,ID_WERFT_ITEMSTRING_6,ID_WERFT_PERCENTAGE_90,ID_WERFT_ITEMSTRING_7,-1,ID_WERFT_ITEMSTRING_8,-1

Nachbrenner - modifizierte Werte korrekt anzeigen

Zunächst die in der "global.res" fehlenden StringIds (rot) in der "user_strings.res" für erhöhte Geschwindigkeiten des Nachbrenners definieren und hier eintragen. In der Werft wird die Erhöhung um n% und nicht die Maximalgeschwindigkeit angezeigt (Verbesserung 150% = 250% Endgeschwindigkeit). Die Geschwindigkeitsfaktoren selbst müssen in der Datei Afterburners.ini mit dem Eintrag 'SpeedMax' angepasst werden.

[Nachbrenner]
0 = 49,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_8,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_50,-1,-1
1 = 50,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_10,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_60,-1,-1
2 = 51,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_12,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_80,-1,-1
3 = 52,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_14,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_100,-1,-1
4 = 53,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_16,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_150,-1,-1
5 = 54,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_18,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_200,-1,-1
6 = 55,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_20,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_250,-1,-1
7 = 56,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_22,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_300,-1,-1
8 = 57,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_25,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_350,-1,-1
9 = 58,6,ID_WERFT_ITEMSTRING_21,ID_WERFT_SEK_30,ID_WERFT_ITEMSTRING_22,ID_WERFT_PERCENTAGE_400,-1,-1


Messages.ini

Messages.ini (Funknachrichten)

Änderungen und Erweiterungen in der Datei inifiles\Messages.ini

Beispiel:


Meteorids.ini

Meteorids.ini (Meteoriten)

Änderungen und Erweiterungen in der Datei inifiles\Meteorids.ini

Beispiel:


OrbiterNames.ini

OrbiterNames.ini (Orbiternamen)

Änderungen und Erweiterungen in der Datei inifiles\OrbiterNames.ini

Beispiel:


Planets.ini

Planets.ini (Orbiter der Sternsysteme)

Änderungen und Erweiterungen in der Datei inifiles\Planets.ini

Änderungen in der Planets.ini sollten normalerweise vor dem Start eines neuen Spiels vorgenommen werden. Es funktioniert aber auch in einem laufenden Spiel, allerdings kann es in einzelnen Fällen zum Absturz kommen, wenn man den Spielstand wieder lädt. In diesem Fall sollte man sich im später zu ladenden Spielstand nicht in demjenigen Sternsystem des Clusters aufhalten, wo die Änderungen vorgenommen werden.

Die Sektion [Globals]

Beim Hinzufügen von Sektionen muss auch die 'Planetenanzahl' (Anzahl aller statischen Objekte bzw. Anzahl der Sektionen) in der Sektion [Globals] entsprechend erhöht werden. Der Wert entspricht der Summe aller Sektionen von [Planet000_000] bis [Planet402_nnn] und muss immer mindestens der tatsächlichen Anzahl der hier definierten Orbiter entsprechen. Höhere Werte sind zwar unproblematisch, sollten aber der Übersicht halber beim Entfernen von Sektionen angepasst werden. Die 'Sternenanzahl' sollte immer auf dem Wert 403 bleiben. Eine Erhöhung von diesen Wert ist sowieso sinnlos, da keine weiteren Sternenysteme hinzugefügt werden können.

[Globals] ;
Planetenanzahl = 5971 ; Die Anzahl der Planetendaten in dieser Ini-Datei
Sternenanzahl = 403 ; Die Anzahl der Sternsysteme, für die in dieser Ini-Datei Planeten gespeichert sind

Die Sektionen [Planetnnn_mmm]

Die erste Zahl nnn entspricht der System-ID, die zweite Zahl mmm ist eine fortlaufende Nummer des eingetragenen Orbiters. Die Nummerierung beginnt in beiden Fällen immer mit 0 und es dürfen keine Lücken darin vorhanden sein, sonst werden alle folgenden Daten ignoriert.

Objekte der Orbitart "Dekoration"

Model | Objekt
0 | kleines Kreuzerwrack der Terraner
1 | kleines Kreuzerwrack der Mortok
2 | großes Kreuzerwrack der Raptor
3 | kleines Kreuzerwrack der Oc'to
4 | kleines Kreuzerwrack der Arrack
5 | kleines Kreuzerwrack der Thul
6 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
7 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
8 | großes Kreuzerwrack der Terraner
9 | großes Kreuzerwrack der Mortok
10 | kleines Kreuzerwrack der Raptor
11 | großes Kreuzerwrack der Oc'to
12 | großes Kreuzerwrack der Arrack
13 | großes Kreuzerwrack der Thul
14 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
15 | kleines Kreuzerwrack der Terraner (evtl. undefiniert, kommt in keiner INI-Datei vor)
16 | Stationswrack, Fenster ist Vorderseite (Hangarposition ist an 45° entgegen dem Uhrzeigersinn)

Beispiele:

Erweiterung für die Boaventura-Gang

In diesem Beispiel wird ein Meteoritenfeld und ein Piratenversteck dem System Rulote im Mortok-Cluster Pertok hinzugefügt. Dieses soll später die Heimatbasis für die standardmäßig deaktivierte Boaventura-Piratengang werden. Da diese beiden Sektionen hier direkt hinter dem Sprungtor ( [Planet064_002] ) eingefügt wurden, müssen die darauf folgenden Indices nnn von [Planet064_nnn] natürlich auch um 2 erhöht werden ( [Planet064_005], usw. ). Nicht vergessen, die 'Planetenanzahl' unter [Globals] anzupassen.

[Planet064_003] ; Daniels Feld
Model = 27 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Meteoritenfeld ; Name der Art dieses Orbiters
Position = 0.000000 / 5900.000000 / 5900.000000 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 5538.475586 ; Radius in Metern
RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 64 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet064_004] ;
Model = 0 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Piratenversteck ; Name der Art dieses Orbiters
Position = 0.000000 / 5900.000000 / 5900.000000 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 0.000000 ; Radius in Metern
RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 64 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter geh0rt
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet064_005] ; Bergbaufeld
Model = 119 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Meteoritenfeld ; Name der Art dieses Orbiters
...

Um die Gang endgültig zu aktivieren, müssen noch 2 weitere Dateien geändert werden:
1.) In der Datei StarSystem.ini unter [System064] den Wert vom Eintrag "Piratengang" von 65535 auf 9 ändern.
2.) In der Datei Systemeigenschaften.ini unter [Gangsysteme] den Wert vom Eintrag "9" von 500 auf 64 ändern.

Forschungsstation im System Thabyedaw, Cluster Hive-G8

Wird der versteckte Arrack-Cluster Hive-G8 freigeschaltet und man bereist das Sternensystem Thabyedaw, dann stellt man fest, dass die dortige Forschungsstation fast komplett innerhalb eines Asteroiden versteckt liegt. Dieser Fehler lässt sich durch eine kleine Änderung beheben: Einfach z.B. die Z-Koordinate vom ursprünglichen Positions-Wert 5212 um 1500 auf 6712 erhöhen. Damit wird die Station um 1,5 Units in Richtung Hypergate verschoben und liegt somit komplett außerhalb des Asteroiden.

[Planet376_007] ;
Model = 2 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Forschung ; Name der Art dieses Orbiters
Position = 0.000911 / -53.000000 / 6712.130371 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 100.000000 ; Radius in Metern
RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 376 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

Position der Sonne im Sol-System

Das die Sonnen in den meisten Systemen die Nordhalbkugel der Planeten anstrahlen, geht ja an der Realität ganz schön weit vorbei. Das korrigieren wir hiermit zumindest mal für das Sol-System, so dass der Einstrahlwinkel vom Licht halbwegs stimmt. Eine Korrektur der Drehrichtung der Erde wird dagegen wohl leider nicht möglich sein. Nun ja, dann geht die Sonne halt weiter im Westen auf ;-)

[Planet029_000] ; Sol-System
Model = 0 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Sonne ; Name der Art dieses Orbiters
Position = -1493490.625000 / 566113.281250 / 979931.625000 ; neue X-, Y- und Z-Koordinaten in Metern
;Position = 466113.281250 / 1593490.625000 / 479931.625000 ; die X-, Y- und Z-Koordinaten in Metern
RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

Uranus und Neptun im Sol-System nachrüsten

Eine simple Aufgabe, es müssen nur ein paar Sektionen am Ende von [Planet029_nnn] angehängt werden. Etwas schwieriger ist es lediglich, einigermaßen passende Modelle zu finden und passable Positionsdaten zu ermitteln.

[Planet029_022] ; Uranus
Model = 616 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Gasriese ; Name der Art dieses Orbiters
Position = 638833.386719 / -32453.722656 / -551707.171875 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 25559.000000 ; Radius in Metern
RotationSteps = 64000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_023] ; Uranus-Mond Miranda
Model = 20 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Mond ; Name der Art dieses Orbiters
Position = 25779.417969 / 811.107802 / 15343.451172 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 235.800000 ; Radius in Metern
RotationSteps = 15000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 43680 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_024] ; Uranus-Mond Ariel
Model = 48 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Mond ; Name der Art dieses Orbiters
Position = 34372.554687 / 1014.810403 / 20457.935547 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 579.000000 ; Radius in Metern
RotationSteps = 15000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 65520 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_025] ; Uranus-Mond Umbriel
Model = 47 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Mond ; Name der Art dieses Orbiters
Position = -38028.5625 / -1115.112669 / -12402.753906 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 584.700000 ; Radius in Metern
RotationSteps = 15000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 65520 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_026] ; Uranus-Mond Titania
Model = 42 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Mond ; Name der Art dieses Orbiters
Position = 26536.863281 / 1315.633500 / 29929.830078 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 788.900000 ; Radius in Metern
RotationSteps = 15000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 65520 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_027] ; Uranus-Mond Oberon
Model = 44 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Mond ; Name der Art dieses Orbiters
Position = 14450.682617 / -1416.012400 / -37298.492187 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 761.400000 ; Radius in Metern
RotationSteps = 15000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 65520 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_028] ; Uranus-Ring
Model = 65530 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Gasriese ; Name der Art dieses Orbiters
Position = 638833.386719 / -32453.722656 / -551707.171875 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 25559.000000 ; Radius in Metern
RotationSteps = 64000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_029] ; Neptun
Model = 532 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Gasriese ; Name der Art dieses Orbiters
Position = 538833.386719 / 82453.722656 / -821707.171875 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 24764.000000 ; Radius in Metern
RotationSteps = 30000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_030] ; Neptun-Mond Triton
Model = 42 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Mond ; Name der Art dieses Orbiters
Position = 27536.863281 / -15.633500 / 31929.830078 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 788.900000 ; Radius in Metern
RotationSteps = 15000 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 65520 ; Zeitschritte für die Umkreisung des zentralen Orbiters

[Planet029_031] ; aufgegebene Station
Model = 16 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Dekoration ; Name der Art dieses Orbiters
Position = 500000.000000 / 82453.000000 / -821500.000000 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 100.000000 ; Radius in Metern
RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 29 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters

Zum Abschluß dann wieder die 'Planetenanzahl' unter [Globals] entsprechend erhöhen. Eventuell kann auch in der StarSystem.ini noch die Anzahl der Planeten im System erhöht werden, ist aber nicht notwendig.

Drehen von Objekten

X-Winkel = 0 ; Rotation in Grad um die X-Achse (Polarwinkel, bzw. Neigung)
Y-Winkel = 0 ; Rotation in Grad um die Y-Achse (Azimutwinkel, bzw. Richtung in der X/Z-Ebene)

Die Neigungsrichtung +X geht von der Handelsstation {0,0,0} aus gesehen nach vorne unten, positives Y dreht das Objekt im Uhrzeigersinn. Die Werte beziehen sich auf das relative Koordinatensystem des Objekts. Negative Werte sind erlaubt. Beim Wrack der Handelsstation geht die Z-Achse nicht durch den Hangar, sondern durch das große Aussichtsfenster. Der Hangar liegt also etwa an Y = -45° (bzw. +315°).

Funktioniert für Schiffs- und Stationswracks (Dekorationen). Funktioniert nicht für normale Handelsstationen, Forschungsstationen, Asteroiden*, Sprungtore und Werbetafeln. Diese Objekte sind immer parallel zur Z-Achse ausgerichtet, außer den Forschungsstationen, die mit ihrem Hangar in Blickrichtung zur Handelsstation positioniert sind.
* Muss noch getestet werden.

Hier wird im System Permakin beim Waldplaneten eine zerstörte Handelsstation hinzugefügt, deren Hangar ungefähr auf das Hyperraumtor ausgerichtet ist:

[Planet402_001] ; Defekte Station
Model = 16 ; Id des 3D-Modells, mit dem dieser Orbiter dargestellt wird
Orbitart = Dekoration ; Name der Art dieses Orbiters
Position = -37000.000000 / -9000.000000 / -30000.000000 ; die X-, Y- und Z-Koordinaten in Metern
Radius = 0.000000 ; Radius in Metern
RotationSteps = 0 ; Zeitschritte für die Rotation um die eigene Achse
SystemId = 402 ; fortlaufende Nummer des Sonnensystems, zu dem dieser Orbiter gehört
UmlaufSteps = 0 ; Zeitschritte für die Umkreisung des zentralen Orbiters
X-Winkel = 0 ; Rotation in Grad um die X-Achse
Y-Winkel = 90 ; Rotation in Grad um die Y-Achse

Sternsysteme mit mehreren Sonnen:
Nur die erste Sonne dient als Beleuchtungsquelle, die anderen haben leider keine Auswirkung.

Sternsysteme ohne Sonne:
Planeten und Monde sind abgedunkelt, es herrscht aber eine allgemeine diffuse Beleuchtung.

Monde:
Anders als bei den Planeten und sonstigen Orbitern sind die Positionsdaten keine absoluten Raumkoordinaten, sondern beziehen sich relativ zu dem von ihnen umkreisten Planeten. Dies ist immer der zuletzt über dem jeweiligen Mond eingetragene Planet, was bei einer Modifikation der Koordinaten nicht unbedingt dem nächststehenden Planet entsprechen muss. Koordinatenursprung ist das Zentrum des Planeten, der Planetenradius muss also mit berücksichtigt werden, sonst kann der Mond innerhalb des Planeten stehen. Durch die Umkreisung des Planeten ändern sich die Mond-Koordinaten natürlich ständig, daher sind die eingetragenen Positionen nur als Startwerte zu sehen.

Schwarze Löcher:
Die schwarzen Löcher werden immer in einer exakten Entfernung von 100 Units vom Systemzentrum positioniert. Die Positionsangaben sind daher keine absoluten Raumkoordinaten, sondern Richtungsvektoren. Die Singularitäten sind unsichtbar und verfügen über keinerlei besondere Eigenschaften, wie es beispielsweise bei einigen Anomalien der Fall ist.


PlanetTypes.ini

PlanetTypes.ini (Planeten-Optik)

Änderungen und Erweiterungen in der Datei inifiles\PlanetTypes.ini

Beispiel:


Prices.ini

Prices.ini (Grundpreise)

Änderungen und Erweiterungen in der Datei inifiles\Prices.ini

Beispiel:


Projectiles.ini

Projectiles.ini (Munitionsarten)

Änderungen in der Datei inifiles\Projectiles.ini

Beispiel eines Eintrags:
[projectile000] ; Swarm 1, AMMO_TYPE_SWARM
Aliens = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
AmmoLook = 0 ; Projektilindex für Boris
AmmoName = Swarm ; Swarm
CollRadius = 0.000000 ; Radius des Geschosses
ConeAngle = 0.000000 ; Der Öffnungswinkel des Kegels, in dem das Ziel verfolgt werden kann
Explosion = EXPLOSION_MISSILE_SWARM ;
ExplosionRadius = 50.000000 ; Explosionsradius bei Treffer oder Selbstzerstörung
HullDmg = 20 ; Rumpfschaden
LaunchSfx = FX.Missile.Swarm.Fire ;
Level = 0 ; Level der Waffe
LifeTime = 1.240000 ; Lebenszeit in Sekunden
LockAngle = 0.000000 ; Aufschaltwinkel bei zielsuchenden Geschossen
LockSteps = 65535 ; Aufschaltdauer in Zeitschritten bei zielsuchenden Geschossen
Multiple = 5 ; zusätzliche Projektile in einer Salve
Range = 496.000000 ; Reichweite in Metern
ShldDmg = 20 ; Schildschaden
Speed = 16.000000 ; Geschossgeschwindigkeit in Metern/Zeitschritt
TurnRate = 79.999992 ; Wendigkeit bei zielsuchenden Geschossen ( Grad pro Sekunde )
Kurzübersicht der definierten Einträge:
Index | Munitionstyp und Level | Konstante
000 | Swarm 1 | AMMO_TYPE_SWARM
001 | Swarm 2 | AMMO_TYPE_SWARM
002 | Swarm 3 | AMMO_TYPE_SWARM
003 | Swarm 4 | AMMO_TYPE_SWARM
004 | Swarm 5 | AMMO_TYPE_SWARM
005 | Swarm 6 | AMMO_TYPE_SWARM
006 | Hellfire 2 | AMMO_TYPE_HELLFIRE
007 | Hellfire 3 | AMMO_TYPE_HELLFIRE
008 | Hellfire 4 | AMMO_TYPE_HELLFIRE
009 | Hellfire 5 | AMMO_TYPE_HELLFIRE
010 | Hellfire 6 | AMMO_TYPE_HELLFIRE
011 | Big Bang 3 | AMMO_TYPE_BIGBANG
012 | Big Bang 4 | AMMO_TYPE_BIGBANG
013 | Big Bang 5 | AMMO_TYPE_BIGBANG
014 | Big Bang 6 | AMMO_TYPE_BIGBANG
015 | Mine 1 | AMMO_TYPE_MINE *
016 | Mine 2 | AMMO_TYPE_MINE *
017 | Mine 3 | AMMO_TYPE_MINE *
018 | Mine 4 | AMMO_TYPE_MINE *
019 | Mine 5 | AMMO_TYPE_MINE *
020 | Mine 6 | AMMO_TYPE_MINE *
021 | Turret Missile 1 | AMMO_TYPE_TURRETMISSILE *
022 | Turret Missile 2 | AMMO_TYPE_TURRETMISSILE *
023 | Turret Missile 3 | AMMO_TYPE_TURRETMISSILE *
024 | Turret Missile 4 | AMMO_TYPE_TURRETMISSILE *
025 | Turret Missile 5 | AMMO_TYPE_TURRETMISSILE *
026 | selbstfeuernde Mine 1 | AMMO_TYPE_SHOOTER *
027 | Raptor 1 | AMMO_TYPE_RAPTOR *
028 | Raptor 2 | AMMO_TYPE_RAPTOR *
029 | Raptor 3 | AMMO_TYPE_RAPTOR *
030 | Raptor 4 | AMMO_TYPE_RAPTOR *
031 | Raptor 5 | AMMO_TYPE_RAPTOR *
032 | Raptor 6 | AMMO_TYPE_RAPTOR *
033 | Raptor 7 | AMMO_TYPE_RAPTOR *
034 | Raptor 8 | AMMO_TYPE_RAPTOR *
035 | Raptor 9 | AMMO_TYPE_RAPTOR *
036 | Raptor 10 | AMMO_TYPE_RAPTOR *
037 | Turret Missile 6 | AMMO_TYPE_TURRETMISSILE *
038 | Turret Missile 7 | AMMO_TYPE_TURRETMISSILE *
039 | Turret Missile 8 | AMMO_TYPE_TURRETMISSILE *
040 | Turret Missile 9 | AMMO_TYPE_TURRETMISSILE *
041 | Turret Missile 10 | AMMO_TYPE_TURRETMISSILE *
042 | Light 1 | AMMO_TYPE_LIGHT *
043 | Light 2 | AMMO_TYPE_LIGHT *
044 | Light 3 | AMMO_TYPE_LIGHT *
045 | Light 4 | AMMO_TYPE_LIGHT *
046 | Light 5 | AMMO_TYPE_LIGHT *
047 | Light 6 | AMMO_TYPE_LIGHT *
048 | Light 7 | AMMO_TYPE_LIGHT *
049 | Light 8 | AMMO_TYPE_LIGHT *
050 | Light 9 | AMMO_TYPE_LIGHT *
051 | Light 10 | AMMO_TYPE_LIGHT *
052 | selbstfeuernde Mine in der Waffenfabrik 1 | AMMO_TYPE_MINE_BRONIS *
053 | selbstfeuernde Mine in der Waffenfabrik 2 | AMMO_TYPE_MINE_BRONIS *
054 | selbstfeuernde Mine in der Waffenfabrik 3 | AMMO_TYPE_MINE_BRONIS *
055 | RaptorBoss 1 | AMMO_TYPE_RAPTORBOSS *
056 | RaptorBoss 2 | AMMO_TYPE_RAPTORBOSS *
057 | RaptorBoss 3 | AMMO_TYPE_RAPTORBOSS *
058 | RaptorBoss 4 | AMMO_TYPE_RAPTORBOSS *
059 | RaptorBoss 5 | AMMO_TYPE_RAPTORBOSS *
060 | RaptorBoss 6 | AMMO_TYPE_RAPTORBOSS *
061 | RaptorBoss 7 | AMMO_TYPE_RAPTORBOSS *
062 | RaptorBoss 8 | AMMO_TYPE_RAPTORBOSS *
063 | RaptorBoss 9 | AMMO_TYPE_RAPTORBOSS *
064 | RaptorBoss 10 | AMMO_TYPE_RAPTORBOSS *
065 | selbstfeuernde Mine 2 | AMMO_TYPE_SHOOTER *
066 | selbstfeuernde Mine 3 | AMMO_TYPE_SHOOTER *
067 | selbstfeuernde Mine 4 | AMMO_TYPE_SHOOTER *
068 | selbstfeuernde Mine 5 | AMMO_TYPE_SHOOTER *
069 | selbstfeuernde Mine 6 | AMMO_TYPE_SHOOTER *
070 | selbstfeuernde Mine 7 | AMMO_TYPE_SHOOTER *
071 | selbstfeuernde Mine 8 | AMMO_TYPE_SHOOTER *
072 | selbstfeuernde Mine 9 | AMMO_TYPE_SHOOTER *
073 | selbstfeuernde Mine 10 | AMMO_TYPE_SHOOTER *
074 | Mine 7 | AMMO_TYPE_MINE *
075 | Mine 8 | AMMO_TYPE_MINE *
076 | Mine 9 | AMMO_TYPE_MINE *
077 | Mine 10 | AMMO_TYPE_MINE *
078 | Hellfire 7 | AMMO_TYPE_HELLFIRE
079 | Hellfire 8 | AMMO_TYPE_HELLFIRE
080 | Hellfire 9 | AMMO_TYPE_HELLFIRE
081 | Hellfire 10 | AMMO_TYPE_HELLFIRE
082 | Swarm 7 | AMMO_TYPE_SWARM
083 | Swarm 8 | AMMO_TYPE_SWARM
084 | Swarm 9 | AMMO_TYPE_SWARM
085 | Swarm 10 | AMMO_TYPE_SWARM
086 | Big Bang 7 | AMMO_TYPE_BIGBANG
087 | Big Bang 8 | AMMO_TYPE_BIGBANG
088 | Big Bang 9 | AMMO_TYPE_BIGBANG
089 | Big Bang 10 | AMMO_TYPE_BIGBANG
090 | Hellfire der KI 2 | AMMO_TYPE_KIHOMING *
091 | Hellfire der KI 3 | AMMO_TYPE_KIHOMING *
092 | Hellfire der KI 4 | AMMO_TYPE_KIHOMING *
093 | Hellfire der KI 5 | AMMO_TYPE_KIHOMING *
094 | Hellfire der KI 6 | AMMO_TYPE_KIHOMING *
095 | Hellfire der KI 7 | AMMO_TYPE_KIHOMING *
096 | Hellfire der KI 8 | AMMO_TYPE_KIHOMING *
097 | Hellfire der KI 9 | AMMO_TYPE_KIHOMING *
098 | Hellfire der KI 10 | AMMO_TYPE_KIHOMING *
099 | MortokBoss 1 | AMMO_TYPE_MORTOKBOSS *
100 | MortokBoss 2 | AMMO_TYPE_MORTOKBOSS *
101 | MortokBoss 3 | AMMO_TYPE_MORTOKBOSS *
102 | MortokBoss 4 | AMMO_TYPE_MORTOKBOSS *
103 | MortokBoss 5 | AMMO_TYPE_MORTOKBOSS *
104 | MortokBoss 6 | AMMO_TYPE_MORTOKBOSS *
105 | MortokBoss 7 | AMMO_TYPE_MORTOKBOSS *
106 | MortokBoss 8 | AMMO_TYPE_MORTOKBOSS *
107 | MortokBoss 9 | AMMO_TYPE_MORTOKBOSS *
108 | MortokBoss 10 | AMMO_TYPE_MORTOKBOSS *
* Konstante in der MissionLibEx.lua definiert.


SkyBox.ini

SkyBox.ini (Nav-Karte?)

Änderungen und Erweiterungen in der Datei inifiles\SkyBox.ini

Beispiel:


Sound.ini

Sound.ini (Klangeffekte)

Änderungen und Erweiterungen in der Datei inifiles\Sound.ini

Beispiel:


Space.ini

Space.ini (Orbiterdaten)

Änderungen und Erweiterungen in der Datei inifiles\Space.ini

Beispiel:


StarCluster.ini

StarCluster.ini (Sterncluster)

Änderungen in der Datei inifiles\StarCluster.ini

Die folgenden Einträge der StarCluster.ini sind in der Datei "inifiles\Infos\Konzept.ini" unter [Kreuzer_Spielstart] definiert:
(Siehe hierzu auch die Tabelle Kreuzer und Superfrachter)

  • CruiserIndex0 - CruiserIndex3
  • CruiserSize0 - CruiserSize3
  • CruiserStart0 - CruiserStart3

Beispiel:

Terraner-Cluster Ross 128

Schaltet man den versteckten Terraner-Cluster "Ross 128" frei, wird man feststellen, dass die Raumstationen der Sternensysteme zwar in der Targetliste erscheinen, aber im Weltraum grafisch nicht sichtbar sind. Eine manuelle Landung auf den Stationen ist somit praktisch kaum möglich, da auch die Anflugbefeuerung nicht angezeigt wird, nachdem man die Landeerlaubnis erhalten hat. Während man bei den Handelsstationen ja noch den Landecomputer zu Hilfe nehmen kann, geht das bei den Forschungsstationen bekanntlich nicht.

Der Fehler liegt hier im Sektor [Cluster18] begraben. Dort wurde mit dem Eintrag "Rasse = 1704" diese nicht existierende Rasse eingetragen. Einfach in "Rasse = Menschen" ändern, und schon sind die Stationen wieder sichtbar.

[Cluster18] ; 1704
CruiserIndex0 = 36 ; Namensindex des Kreuzers
CruiserIndex1 = 37 ; Namensindex des Kreuzers
CruiserIndex2 = 38 ; Namensindex des Kreuzers
CruiserIndex3 = 39 ; Namensindex des Kreuzers
CruiserSize0 = 1 ; != 0, wenn der Kreuzer groß ist
CruiserSize1 = 0 ; != 0, wenn der Kreuzer groß ist
CruiserSize2 = 1 ; != 0, wenn der Kreuzer groß ist
CruiserSize3 = 0 ; != 0, wenn der Kreuzer groß ist
CruiserStart0 = 258 ; Startsystem des Kreuzers
CruiserStart1 = 259 ; Startsystem des Kreuzers
CruiserStart2 = 260 ; Startsystem des Kreuzers
CruiserStart3 = 261 ; Startsystem des Kreuzers
FrachterWkeit = 0.000000 ; Wkeit für Frachter der zweiten Rasse
Frachterrasse = Menschen ; die Rasse, die ein paar Frachter stellt
Info1 =  ; die minimale Reichweite, mit der alle Systeme erreicht werden können, ist 0.0000
Info2 =  ; der maximale Abstand eines Sternes zum Zentrum des Sternenhaufens ist 3.9579
Mitte = 3.15, 32.55 ; Mittelpunkt des Clusters
Rasse = Menschen ; die Rasse, die diesen Cluster bewohnt
Sterne = 7 ; Anzahl der Sterne im Cluster
Wkeit_1704 = 0 ; Wahrscheinlichkeit für 1704-Schiffe
Wkeit_Menschen = 40 ; Wahrscheinlichkeit für Menschen-Schiffe
Wkeit_Morlok = 0 ; Wahrscheinlichkeit für Morlok-Schiffe
Wkeit_Octo = 20 ; Wahrscheinlichkeit für Octo-Schiffe
Wkeit_Raptor = 20 ; Wahrscheinlichkeit für Raptor-Schiffe
Wkeit_S’kaa = 0 ; Wahrscheinlichkeit für S’kaa-Schiffe
Wkeit_Thul = 0 ; Wahrscheinlichkeit für Thul-Schiffe
Wkeit_Wasp = 20 ; Wahrscheinlichkeit für Wasp-Schiffe


StarFlight.ini

StarFlight.ini (Schiffsdaten)

Änderungen und Erweiterungen in der Datei inifiles\StarFlight.ini

Beispiel:


StarLight.ini

StarLight.ini (Lichteinstellungen der Sternsysteme)

Änderungen und Erweiterungen in der Datei inifiles\StarLight.ini

Beispiel:


StarShip.ini

StarShip.ini (Schiffe und Satelliten)

Änderungen und Erweiterungen in der Datei inifiles\StarShip.ini

Beispiel:

Superfrachter

Die ersten 3 Einträge [StarShip005_024] bis [StarShip005_026] in diesem Auszug aus der Datei StarShip.ini sind Superfrachter mit Geheimdienstwaffen-Containern, welche schon standardmäßig definiert sind. Im Spiel tauchen jedoch hier und da nur Superfrachter auf, die mit ganz normalen 200t-Frachtcontainern beladen sind. Die zugehörigen Definitionen fehlten hier bislang und wurden von mir entsprechend ergänzt. Dabei habe ich mich nicht auf die Frachter mit 200t-Containern beschränkt, sondern auch gleich welche für 50t- und 100t-Container hinzugefügt.

Superfrachter gibt es nur für die 3 Rassen Terraner, Raptoren und Arrack. Wahrscheinlich existieren keine 3D-Objekte für die anderen Völker, sodass für sie keine Superfrachter erzeugt werden können.

Wie man selbst diese Superfrachter im Skript erzeugen kann, wird in der Beschreibung der Funktion NWing.Define inklusive praktischen Beispielen erläutert.

[StarShip005_024] ; SPACE_TRANSPORTER - Superfrachter für Geheimdienstwaffen-Container
Aliens = Menschen ; Alienrassen, die dieses Schiff verwenden
BayNum = 45 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 3 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_A ; Explosionstyp
HitpointFactor = 24.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_025] ; SPACE_TRANSPORTER - Superfrachter für Geheimdienstwaffen-Container
Aliens = Wasp ; Alienrassen, die dieses Schiff verwenden
BayNum = 45 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 3 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_D ; Explosionstyp
HitpointFactor = 24.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_026] ; SPACE_TRANSPORTER - Superfrachter für Geheimdienstwaffen-Container
Aliens = Raptor ; Alienrassen, die dieses Schiff verwenden
BayNum = 45 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 3 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_B ; Explosionstyp
HitpointFactor = 24.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_027] ; SPACE_TRANSPORTER - wie 024, Superfrachter für 50t-Container
Aliens = Menschen ; Alienrassen, die dieses Schiff verwenden
BayNum = 45 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 0 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_A ; Explosionstyp
HitpointFactor = 16.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_028] ; SPACE_TRANSPORTER - wie 024, Superfrachter für 100t-Container
Aliens = Menschen ; Alienrassen, die dieses Schiff verwenden
BayNum = 45 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 1 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_A ; Explosionstyp
HitpointFactor = 20.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_029] ; SPACE_TRANSPORTER - wie 024, Superfrachter für 200t-Container
Aliens = Menschen ; Alienrassen, die dieses Schiff verwenden
BayNum = 45 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 2 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_A ; Explosionstyp
HitpointFactor = 24.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_030] ; SPACE_TRANSPORTER - wie 025, Superfrachter für 50t-Container
Aliens = Wasp ; Alienrassen, die dieses Schiff verwenden
BayNum = 42 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 0 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_D ; Explosionstyp
HitpointFactor = 16.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_031] ; SPACE_TRANSPORTER - wie 025, Superfrachter für 100t-Container
Aliens = Wasp ; Alienrassen, die dieses Schiff verwenden
BayNum = 42 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 1 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_D ; Explosionstyp
HitpointFactor = 20.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_032] ; SPACE_TRANSPORTER - wie 025, Superfrachter für 200t-Container
Aliens = Wasp ; Alienrassen, die dieses Schiff verwenden
BayNum = 42 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 2 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_D ; Explosionstyp
HitpointFactor = 24.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_033] ; SPACE_TRANSPORTER - wie 026, Superfrachter für 50t-Container
Aliens = Raptor ; Alienrassen, die dieses Schiff verwenden
BayNum = 40 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 0 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_B ; Explosionstyp
HitpointFactor = 16.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_034] ; SPACE_TRANSPORTER - wie 026, Superfrachter für 100t-Container
Aliens = Raptor ; Alienrassen, die dieses Schiff verwenden
BayNum = 40 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 1 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_B ; Explosionstyp
HitpointFactor = 20.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

[StarShip005_035] ; SPACE_TRANSPORTER - wie 026, Superfrachter für 200t-Container
Aliens = Raptor ; Alienrassen, die dieses Schiff verwenden
BayNum = 40 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.000000 ; Skalierungsfaktor für den Schild
ContainerSize = 2 ; Größe der Container
DoorNum = 0 ; Anzahl der Landebuchten
Explosion = EXPLOSION_FREIGHTER_B ; Explosionstyp
HitpointFactor = 24.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 8 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.474487 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 10 ; Anzahl der Geschütztürme

Großen S'kaa-Kreuzer nachrüsten

Bisher ließ sich kein S'kaa-Kreuzer vom Typ WINGTYPE_CRUISER1 erzeugen, was sich mit diesem Eintrag ändert. Allerdings ändert sich damit nichts an der Optik des Schiffs ('NationObjectId = 1' geht nicht). Die Werte für 'DoorNum' und 'TurretNum' sind zwar auch nur Makulatur, da weder ein Hangar noch Geschütztürme erzeugt werden, aber zur Unterscheidung zur existierenden S'kaa-Kreuzerdefinition notwendig.

[StarShip013_013] ; SPACE_CRUISER - S'kaa Mutterschiff, großer Kreuzer
Aliens = S’kaa ; Alienrassen, die dieses Schiff verwenden
BayNum = 0 ; Anzahl der Halterungen für Frachtcontainer
CameraDist = -1.000000 ; Abstand der Kamera zum Schiff
CollScale = 1.500000 ; Skalierungsfaktor für den Schild
ContainerSize = 2 ; Größe der Container
DoorNum = 1 ; Anzahl der Landebuchten
Explosion = EXPLOSION_CRUISER_E_1 ; Explosionstyp
HitpointFactor = 48.000000 ; Abweichung vom normalen Rumpfwert
NationObjectId = 0 ; Id des Schiffes: eindeutig für Nation und Schiffstyp
Radius = 131.146515 ; Radius der Hüllkugel
SlotNum = 0 ; Anzahl der Aufhänger für starre Waffen
TurretNum = 90 ; Anzahl der Geschütztürme


StarSystem.ini

StarSystem.ini (Sternsysteme)

Änderungen in der Datei inifiles\StarSystem.ini

Beispiel:

Aktivierung der Boaventura-Gang

Um die Boaventura-Gang zu aktivieren, sind ein paar Änderungen in 3 INI-Dateien notwendig. In der StarSystem.ini muss dazu nur der eine Index 'Piratengang = 65535' im gewünschten System (hier: Rulote im Mortok-Cluster Pertok) geändert werden:

[System064] ; Rulote
Artefakt = 0 ; > 0, wenn ein Artefakt im System ist
Bedroht = 0 ; > 0: Piratenbedrohung
Bürger = 1.680000 ; Bevölkerung in Milliarden
Cluster = 5 ; Nummer des Clusters, zu dem der Stern gehört
EnergyLevel = 0 ; legt die Weltraumteilchen fest
Faction = 0 ; Handelsföderation
Function_X1 = 4 ; X1-Wert
Function_X2 = 7 ; X2-Wert
Function_X3 = 9 ; X3-Wert
Function_Y = 4 ; Minimallevel
NachbarRegel = 63 - 63 ; System wird sichtbar, wenn eines dieser Systeme betreten wird
Piratengang = 9 ; Index der Piratengang
Planeten = 1 ; Anzahl der Planeten im System
PosX = 40.099998 ; x-Position auf der Karte
PosY = 8.500000 ; y-Position auf der Karte
Produktion1 = 0 ; Kohlenhydrate
Produktion2 = 2 ; Lebensformen
Produktion3 = 3 ; Pflanzenfasern
Produktion4 = 5 ; Edelmetalle
Produktion5 = 21 ; Luxusartikel
Produktionsfaktor = 0.760000 ;
Regierung = 2 ; Staatenbund
Sichtbarkeitstyp = 2 ; das System wird von Nachbarsystemen betretbar geschaltet
StarLightId = 2 ; Föderation
UniqueItem = 0 ; > 0, wenn ein Unique Item im System ist

Um die Gang endgültig zu aktivieren, müssen noch 2 weitere Dateien geändert werden:
1.) In der Datei Planets.ini je ein Meteoritenfeld und Piratenversteck (wahlweise auch Anomalie oder Schiffswrack) hinzufügen.
2.) In der Datei Systemeigenschaften.ini unter [Gangsysteme] den Wert vom Eintrag "9" von 500 auf 64 ändern.

Terraner-Cluster Tau Ceti betretbar machen☺

Um diesen versteckten Cluster betreten zu können, sind ein paar Änderungen an verschiedenen INI-Dateien notwendig. Dafür müssen hier in der StarSystem.ini 2 Einträge bearbeitet werden, der 'Sichtbarkeitstyp' und die 'NachbarRegel':

  1. Sichtbarkeitstyp = 6: Allen Systemen im Cluster einen der folgenden gültigen Werte zuweisen:
    • 0 : das System kann bei Spielstart betreten werden
    • 2 : das System wird von Nachbarsystemen betretbar geschaltet (weißes Fragezeichen)
    • 4 : das System wird von der Story freigeschaltet (weißes Fragezeichen)
    • 6 : das System wird niemals freigeschaltet (das wollen wir ja ändern)
    • 7 : das System ist versteckt und wird durch eine Mission freigeschaltet (graues Fragezeichen)
  2. NachbarRegel = 65535 - 0: SystemID von - bis; Einzelnes System oder ein Bereich von Sternsystemen zuweisen:
    • 24 - 24 : System wird sichtbar, wenn eines dieser Systeme betreten wird

Sinnvolle Werte für den Sichtbarkeitstyp wären also 0, 2 und 7. In diesem Beispiel wird zunächst das System Taba (System024) durch das Betreten von Cloosa (System001) freigeschaltet. Das System Ote (System023) wird dann sichtbar, sobald man nach Taba springt. Wird nun wie im Fall von Ote die Nachbarregel der anderen Sterne in Tau Ceti ebenfalls auf 24 - 24 gesetzt, dann werden sie beim Sprung nach Taba alle gleichzeitig sichtbar.

Hinweis:
Änderungen des Sichtbarkeitstyps und der Nachbarregel müssen ebenfalls noch in der Datei "Systemeigenschaften.ini" eingetragen werden.

Sonstige Änderungen gegenüber der originalen StarSystem.ini (dunkelblau gekennzeichnet):

1.) Der Cluster Tau Ceti liegt ziemlich weit oben links in der Ecke der Karte. Viel zu weit weg, um ihn mit dem anfangs auf nur 2,5 - 3 Lichtjahre Reichweite begrenzten Sprungantrieb von Lalande aus erreichen zu können. Daher verschieben wir einfach den ganzen Cluster durch eine Erhöhung des Wertes 'PosY' in den 6 Sternensystemen um 5 Lichtjahre nach unten ('PosY' um 5.0 erhöhen).

2.) Mit der Originaleinstellung von 'PosX' ist das System Patiak (System022) gar nicht und das System Tasakane (System021) nur bei genauem Hinsehen zu erkennen, da sie zu weit links am Rand liegen. Das kann gleich mit geändert werden, indem der Wert 'PosX' um 0.5 erhöht wird. Damit verschieben sich die beiden Sterne um ein halbes Lichtjahr nach rechts und werden deutlich sichtbar. Möchte man die ursprüngliche Geometrie des Clusters erhalten, kann man dasselbe noch mit den anderen 4 Systemen machen.

3.) Wie so nebenbei zu sehen ist, liegt in Ote ein Artefakt (Artefakt = 1) verborgen, das in der ursprünglichen StarSystem.ini nicht vorhanden war. Damit das auch funktioniert, muss im System mindestens 1 Asteroid vorhanden sein, da Artefakte immer nur dort vom Programm eingebaut werden. Ob ein Asteroid da ist, sieht man ganz einfach in der Planets.ini (oder baut sich dort selber einen ein).

Hinweis:
Positionsänderungen von Sternsystemen wie in 1. und 2. müssen ebenfalls noch in der Datei "Cluster.ini" eingetragen werden, und das Ändern und Hinzufügen von Artefakten wie in 3. muss man auch in der Datei "Systemeigenschaften.ini" anpassen.

[System023] ; Ote
Artefakt = 1 ; > 0, wenn ein Artefakt im System ist
Bedroht = 0 ; > 0: Piratenbedrohung
Bürger = 3.840000 ; Bevölkerung in Milliarden
Cluster = 2 ; Nummer des Clusters, zu dem der Stern gehört
EnergyLevel = 0 ; legt die Weltraumteilchen fest
Faction = 0 ; Handelsföderation
Function_X1 = 1 ; X1-Wert
Function_X2 = 4 ; X2-Wert
Function_X3 = 6 ; X3-Wert
Function_Y = 1 ; Minimallevel
NachbarRegel = 24 - 24 ; System wird sichtbar, wenn eines dieser Systeme betreten wird
Piratengang = 65535 ; Index der Piratengang
Planeten = 2 ; Anzahl der Planeten im System
PosX = 4.100000 ; x-Position auf der Karte
PosY = 8.300000 ; y-Position auf der Karte
Produktion1 = 6 ; Kristalle
Produktion2 = 7 ; Legierungen
Produktion3 = 8 ; Maschinen
Produktion4 = 9 ; Elektronik
Produktion5 = 11 ; Schiffstechnik
Produktionsfaktor = 0.800000 ;
Regierung = 4 ; Konzernführung
Sichtbarkeitstyp = 2 ; das System wird von Nachbarsystemen betretbar geschaltet
StarLightId = 4 ; Konzern
UniqueItem = 0 ; > 0, wenn ein Unique Item im System ist

[System024] ; Taba
Artefakt = 0 ; > 0, wenn ein Artefakt im System ist
Bedroht = 0 ; > 0: Piratenbedrohung
Bürger = 5.920000 ; Bevölkerung in Milliarden
Cluster = 2 ; Nummer des Clusters, zu dem der Stern gehört
EnergyLevel = 0 ; legt die Weltraumteilchen fest
Faction = 1 ; Piratensystem
Function_X1 = 1 ; X1-Wert
Function_X2 = 4 ; X2-Wert
Function_X3 = 6 ; X3-Wert
Function_Y = 1 ; Minimallevel
NachbarRegel = 1 - 1 ; System wird sichtbar, wenn eines dieser Systeme betreten wird
Piratengang = 65535 ; Index der Piratengang
Planeten = 3 ; Anzahl der Planeten im System
PosX = 3.320000 ; x-Position auf der Karte
PosY = 10.840000 ; y-Position auf der Karte
Produktion1 = 0 ; Kohlenhydrate
Produktion2 = 2 ; Lebensformen
Produktion3 = 3 ; Pflanzenfasern
Produktion4 = 10 ; Computer
Produktion5 = 20 ; Videospiele
Produktionsfaktor = 0.800000 ;
Regierung = 5 ; Monarchie
Sichtbarkeitstyp = 2 ; das System wird von Nachbarsystemen betretbar geschaltet
StarLightId = 5 ; Monarchie
UniqueItem = 0 ; > 0, wenn ein Unique Item im System ist

Das gleiche muss nun noch mit den restlichen Sternensystemen von [System020] bis [System025] gemacht werden.

Dies alleine genügt jedoch noch nicht, um nach Tau Ceti gelangen zu können. Dazu sind, wie oben schon erwähnt, weitere Änderungen an den folgenden Dateien nötig und werden hier in den entsprechenden Menüeinträgen behandelt:
  • inifiles\Infos\Systemeigenschaften.ini
  • inifiles\Infos\Cluster.ini (optional)

Tipp: Lalande ist der einzige der nicht versteckten Cluster, in dem keine Sidequest angeboten wird. Wäre doch gleich mal eine Möglichkeit, den Sichtbarkeitstyp von Taba auf 7 anstatt auf 2 zu setzen und sich z.B. eine Bar-Mission zu schreiben, bei deren Erfüllung man für Taba den Systemschlüssel erhält. Als weitere Anregung könnten dann noch zusätzlich eingebaute Artefakte in Tau Ceti winken.


Suns.ini

Suns.ini (Farbfaktoren der Sonnen)

Änderungen und Erweiterungen in der Datei inifiles\Suns.ini

Beispiel:


Systemeigenschaften.ini

Systemeigenschaften.ini (Sternsysteme)

Änderungen und Erweiterungen in der Datei inifiles\Infos\Systemeigenschaften.ini

Diese Datei beinhaltet 6 Sektionen:

  1. [Gangsysteme]
    Heimatsysteme der Piratengangs im Format:
    GangId = SystemId
    (Nicht zu verwechseln mit "von Piraten besetzte Systeme")

  2. [Artefakte]
    Verteilung der Artefakte im Format:
    Laufende Nummer = SystemId
    Die lfd. Nummern scheinen egal zu sein, sie dürfen nur nicht doppelt vorkommen. Um zusätzlich eingebaute Artefakte leichter von den standardmäßig vorhandenen in der INI-Datei zu unterscheiden, kann man für sie z.B. mit der Nummer 101 beginnen. Manch einer wundert sich vielleicht, dass hier nur 60 und keine 100 Artefakte gelistet sind. Dies sind nur die in Asteroiden eingebauten Artefakte. Die restlichen 40 sind mit 37 Stück auf die von Piraten besetzten Systeme und dem Erhalt von jenen 3 Stück am Spielende aufgeteilt.

  3. [Besetzt]
    Von Piraten besetzte Systeme im Format:
    Laufende Nummer = SystemId
    (Diese Systeme sind auf der Karte mit Totenköpfen gekennzeichnet)

  4. [Sichtbarkeit]
    Die Art der Freischaltung der Systeme im Format:
    Freizuschaltende SystemId = Sichtbarkeitstyp, SystemId "von", SystemId "bis"
    Die Nachbarregel "SystemId von/bis" ist nur für den Sichtbarkeitstyp "Nachbarschlüssel" relevant.
    Mögliche Werte für den Sichtbarkeitstyp:
    • Spielstart : System kann bei Spielstart betreten werden
    • Nachbarschlüssel : System wird von Nachbarsystemen betretbar geschaltet
    • Story : System wird von der Story freigeschaltet
    • Unbenutzt : System wird niemals freigeschaltet
    • Versteckt : System ist versteckt und wird von einer Mission (Sidequest) freigeschaltet
    Beispiele:
    • 0 = Nachbarschlüssel, 10, 10
    Witon (Id=0) wird durch das Betreten von Yarie (Id=10) freigeschaltet
    (vorher sieht man nur ein weißes Fragezeichen und kann das System nicht anwählen)
    • 10 = Spielstart
    Yarie (10) kann bereits bei Spielbeginn betreten werden
    • 16 = Story
    Metharon (16) wird sichtbar und freigeschaltet, sobald Kayron den Systemschlüssel von Robert erhält
    • 17 = Nachbarschlüssel, 12, 15
    Mesehkane (17) wird freigeschaltet, wenn eines der Systeme mit den IDs von 12-15 betreten wird:
    Das wären hier Patorwalla (12), Kalima (13), Zuos (14) oder Tanee (15)
    • 19 = Versteckt
    Ta (19) kann erst nach der Erfüllung der Sidequest "Piraten des besetzten Ta-Systems" betreten werden
    (vorher sieht man nur ein graues Fragezeichen und kann das System nicht anwählen)
    • 20 = Unbenutzt
    Oma (20) im Cluster Tau Ceti bleibt immer unsichtbar

  5. [Politik]
    Die Fraktionen GU, Rebellen und Neutral der Systeme in Reihenfolge der SystemIDs (0-402)

  6. [Meteoriten]
    Keine Einträge

Beispiele:

Aktivierung der Boaventura-Gang

Um die Boaventura-Gang (GangId=9) zu aktivieren, sind ein paar Änderungen in 3 INI-Dateien notwendig. In der Systemeigenschaften.ini muss dazu bei der GangId "9" nur die SystemId von "500" auf das gewünschte System (hier: "64" = Rulote) geändert werden:

[Gangsysteme]
0 = 4
.
.
9 = 64
10 = 57
.
.

Um die Gang endgültig zu aktivieren, müssen noch 2 weitere Dateien geändert werden:
1.) In der Datei Planets.ini je ein Meteoritenfeld und Piratenversteck (wahlweise auch Anomalie oder Schiffswrack) hinzufügen.
2.) In der Datei StarSystem.ini unter [System064] den Wert vom Eintrag "Piratengang" von 65535 auf 9 ändern.

Terraner-Cluster Tau Ceti betretbar machen☺

Um diesen versteckten Cluster betreten zu können, sind ein paar Änderungen an verschiedenen INI-Dateien notwendig. Dafür müssen hier in der Datei Systemeigenschaften.ini die Sichtbarkeitstypen für die im Cluster vorhandenen Sternensysteme von "Unbenutzt" auf die gewünschten Typen geändert werden. Sinnvolle Werte für den Sichtbarkeitstyp wären "Spielstart", "Nachbarschlüssel" und "Versteckt". In diesem Beispiel machen wir es uns einfach und wenden die Nachbarregel an. Zunächst wird das System Taba (SystemId = 24) durch das Betreten von Cloosa (SystemId = 1) freigeschaltet (rot markiert). Die anderen 5 Systeme werden dann beim Sprung nach Taba alle gleichzeitig freigeschaltet.

[Sichtbarkeit]
.
.
20 = Nachbarschlüssel, 24, 24
21 = Nachbarschlüssel, 24, 24
22 = Nachbarschlüssel, 24, 24
23 = Nachbarschlüssel, 24, 24
24 = Nachbarschlüssel, 1, 1
25 = Nachbarschlüssel, 24, 24
.
.

Die Änderungen des Sichtbarkeitstyps und der Nachbarregel müssen ebenfalls noch in der Datei StarSystem.ini eingetragen werden.

Wer sich mit der Skriptprogrammierung schon auskennt, kann die Sache ja noch etwas interessanter gestalten, indem er zunächst hier die Sichtbarkeit von Taba auf "Versteckt" setzt: 24 = Versteckt. Bei Erfüllung der selbstgeschriebenen Mission schaltet dann das Skript mit NStarSystem.Unlock( { System = 24 } ) das System Taba frei.

Zusätzliche Artefakte

Wurde mit obigem Tipp der Cluster Tau Ceti freigeschaltet, so ist ja dort außer gelegentlichen Piratenüberfällen und den üblichen Aufträgen am Teminal noch lange nichts los, es sei denn, man schreibt sich selbst ein paar Missionen für Tau Ceti. Aber auch ohne Programmierkenntnisse kann man durch den einfachen Einbau von Artefakten einen Anreiz für das Bereisen des Clusters schaffen.
Damit das auch funktioniert, muss in dem jeweiligen System ein Asteroid vorhanden sein, was in der Datei Planets.ini ermittelt werden kann. Im folgenden Beispiel wird in den 3 Systemen Oma (Id = 20), Tasakane (Id = 21) und Ote (Id = 23), in denen bereits Asteroiden existieren, je 1 Artefakt eingebaut. Dazu einfach am Ende der Liste neue lfd. Nummern eintragen und ihnen die SystemIDs zuweisen:

[Artefakte]
0 = 5
.
.
59 = 396
101 = 20
102 = 21
103 = 23

Dann noch in der Datei StarSystem.ini bei diesen 3 Systemen den Wert "Artefakt = 1" setzen, fertig.


Thrusters.ini

Thrusters.ini (Antriebsdaten)

Änderungen und Erweiterungen in der Datei inifiles\Thrusters.ini

Beispiel:


Time.ini

Time.ini (Zeitfaktoren)

Änderungen und Erweiterungen in der Datei inifiles\Time.ini

Beispiel:


TradeStation.ini

TradeStation.ini (Handelsstationen)

Änderungen und Erweiterungen in der Datei inifiles\TradeStation.ini

Beispiel:


Upgrades.ini

Upgrades.ini (Aufrüstung)

Änderungen in der Datei inifiles\Upgrades.ini

Beispiele:

Schiffsstufe 30 mit 100 Artefakten

In diesem Beispiel wurde die Anzahl der für den jeweils nächsthöheren Schiffslevel benötigten Artefakte so geändert, dass man mit den standardmäßig vorhandenen 100 Artefakten die Schiffsstufe 30 erreichen kann. Im Kommentar hinter dem Semikolon wird die Anzahl der zu sammelnden Artefakte für diesen Level angezeigt, danach der damit erreichte Energie-, Waffen- und Ausrüstungslevel.

[ArtefactsNeeded] ; Benötigte Artefakte für einen Upgrade
Upgrade01 = 1 ;   +1 Artefakt	1-2-1 -> Energie-, Waffen-, Ausrüstungslevel
Upgrade02 = 2 ;   +1	-"-	2-2-1
Upgrade03 = 3 ;   +1	-"-	2-3-2
Upgrade04 = 4 ;   +1	-"-	3-3-2
Upgrade05 = 6 ;   +2 Artefakte	3-3-3
Upgrade06 = 8 ;   +2	-"-	3-4-3
Upgrade07 = 10 ;  +2	-"-	4-4-3
Upgrade08 = 13 ;  +3	-"-	4-4-4
Upgrade09 = 16 ;  +3	-"-	4-5-4
Upgrade10 = 19 ;  +3	-"-	5-5-4
Upgrade11 = 23 ;  +4	-"-	5-5-5
Upgrade12 = 27 ;  +4	-"-	5-6-5
Upgrade13 = 31 ;  +4	-"-	6-6-5
Upgrade14 = 35 ;  +4	-"-	6-6-6
Upgrade15 = 39 ;  +4	-"-	6-7-6
Upgrade16 = 43 ;  +4	-"-	7-7-7
Upgrade17 = 47 ;  +4	-"-	7-7-7
Upgrade18 = 51 ;  +4	-"-	7-8-7
Upgrade19 = 55 ;  +4	-"-	8-8-8
Upgrade20 = 59 ;  +4	-"-	8-8-8
Upgrade21 = 63 ;  +4	-"-	8-9-8
Upgrade22 = 67 ;  +4	-"-	9-9-9
Upgrade23 = 71 ;  +4	-"-	9-9-9
Upgrade24 = 75 ;  +4	-"-	9-9-9
Upgrade25 = 79 ;  +4	-"-	10-10-10
Upgrade26 = 83 ;  +4	-"-	10-10-10
Upgrade27 = 87 ;  +4	-"-	10-10-10
Upgrade28 = 91 ;  +4	-"-	10-10-10
Upgrade29 = 95 ;  +4	-"-	10-10-10
Upgrade30 = 100 ; +5	-"-	10-10-10


Video.ini

Video.ini (Videos)

Änderungen und Erweiterungen in der Datei inifiles\Video.ini

Beispiel:


WeaponEffects.ini

WeaponEffects.ini (Plasmawaffe)

Änderungen in der Datei inifiles\WeaponEffects.ini

Beispiel:


WingInfo.ini

WingInfo.ini (Wing-Formationen)

Änderungen und Erweiterungen in der Datei inifiles\WingInfo.ini

Die WingInfo.ini enthält die Positionsdaten (Offsets) und die Abstände zwischen den Schiffen von allen in Darkstar One vorkommenden Wing-Formationen. Alle Positionswerte sind relative Koordinaten, die sich auf den Wingleader beziehen. Dieser hat immer eine relative Raumkoordinate von { 0,0,0 } und ist daher nicht mit in den Listen eingetragen. Da in einem Wing maximal 11 Schiffe erzeugt werden können (1 Boss + 10 Flügelmänner), sind die Positionsdaten auch auf maximal 10 Dreiergruppen beschränkt:

[WingNonnn]
AiState = ...
Interdist = ...
Nations = ...
Position00X = ...  ; Wingmember 1
Position00Y = ...  ;
Position00Z = ...  ;
...
Position09X = ...  ; Wingmember 10
Position09Y = ...  ;
Position09Z = ...  ;

Alle Offsetwerte werden mit dem Abstandsfaktor 'Interdist' multipliziert und ergeben damit die endgültigen relativen Koordinaten in tausenstel Units. Das gibt einem die einfache Möglichkeit, eine Formation unter Beibehaltung der Form auseinander zu ziehen oder zusammen zu rücken, ohne dass jeder einzelne Positionswert bearbeitet werden muss. Einfach nur den Faktor 'Interdist' ändern und evtl. als neue Formation in die WingInfo.ini eintragen, Bingo.

Die laufende Nummer nnn in [WingNonnn] ist der Index, der von der Funktion "NWing.SetFormation( { Wing, Formation } )" im Parameter 'Formation' verwendet wird.
Hinweis: Es können maximal 32 Formationen definiert werden, weitere führen zu Problemen.

Beispiele:

Superfrachter-Formation ergänzen

Hier hatte noch die Position für das 10. Begleitschiff gefehlt (Position09X/Y/Z).
[WingNo022] ; Superfrachterwing, Konstante = FORMATION_SUPERFRACHTER
AiState = Superfrachter ; Wingtyp, der das Maneuver anwendet
Interdist = -10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X =   60.000000 ; X-Offset	vorne rechts
Position00Y =  -10.000000 ; Y-Offset
Position00Z =   50.000000 ; Z-Offset
Position01X =  -60.000000 ; X-Offset	vorne links
Position01Y =  -10.000000 ; Y-Offset
Position01Z =   50.000000 ; Z-Offset
Position02X =    0.000000 ; X-Offset	vorne oben
Position02Y =   60.000000 ; Y-Offset
Position02Z =   50.000000 ; Z-Offset
Position03X =   60.000000 ; X-Offset	mitte rechts
Position03Y =   10.000000 ; Y-Offset
Position03Z =  -50.000000 ; Z-Offset
Position04X =  -60.000000 ; X-Offset	mitte links
Position04Y =   10.000000 ; Y-Offset
Position04Z =  -50.000000 ; Z-Offset
Position05X =    0.000000 ; X-Offset	mitte unten
Position05Y =  -60.000000 ; Y-Offset
Position05Z =  -50.000000 ; Z-Offset
Position06X =   60.000000 ; X-Offset	hinten rechts
Position06Y =   10.000000 ; Y-Offset
Position06Z = -150.000000 ; Z-Offset
Position07X =  -60.000000 ; X-Offset	hinten links
Position07Y =   10.000000 ; Y-Offset
Position07Z = -150.000000 ; Z-Offset
Position08X =    0.000000 ; X-Offset	hinten unten
Position08Y =  -60.000000 ; Y-Offset
Position08Z = -150.000000 ; Z-Offset
Position09X =    0.000000 ; X-Offset	hinten oben
Position09Y =   60.000000 ; Y-Offset
Position09Z = -150.000000 ; Z-Offset

Zusätzlich eingetragene neue Formationen

[WingNo023] ; DELTA_INVERS, wie DELTA, Boss fliegt aber hinten. Konstante = FORMATION_DELTA_INV
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X =  -2.500000 ; X-Offset
Position00Y =   0.000000 ; Y-Offset
Position00Z =   2.500000 ; Z-Offset
Position01X =   2.500000 ; X-Offset
Position01Y =   0.000000 ; Y-Offset
Position01Z =   2.500000 ; Z-Offset
Position02X =  -5.000000 ; X-Offset
Position02Y =   0.000000 ; Y-Offset
Position02Z =   5.000000 ; Z-Offset
Position03X =   5.000000 ; X-Offset
Position03Y =   0.000000 ; Y-Offset
Position03Z =   5.000000 ; Z-Offset
Position04X =  -7.500000 ; X-Offset
Position04Y =   0.000000 ; Y-Offset
Position04Z =   7.500000 ; Z-Offset
Position05X =   7.500000 ; X-Offset
Position05Y =   0.000000 ; Y-Offset
Position05Z =   7.500000 ; Z-Offset
Position06X = -10.000000 ; X-Offset
Position06Y =   0.000000 ; Y-Offset
Position06Z =  10.000000 ; Z-Offset
Position07X =  10.000000 ; X-Offset
Position07Y =   0.000000 ; Y-Offset
Position07Z =  10.000000 ; Z-Offset
Position08X = -12.500000 ; X-Offset
Position08Y =   0.000000 ; Y-Offset
Position08Z =  12.500000 ; Z-Offset
Position09X =  12.500000 ; X-Offset
Position09Y =   0.000000 ; Y-Offset
Position09Z =  12.500000 ; Z-Offset

----- Darstellung der Formation -----
↑	°                   °	 12.5
|	  °               °  	 10.0
|	    °           °    	  7.5
Z-Offset      °       °      	  5.0
|	        °   °        	  2.5
|	          ▲          	  0.0
---     -10  -5   0   5   10  --→ X-Offset
---	  ▲ = Wingleader      ---

[WingNo024] ; ARROW_10, Pfeil. Konstante = FORMATION_ARROW_10
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X =  -2.500000 ; X-Offset
Position00Y =   0.000000 ; Y-Offset
Position00Z =  -2.500000 ; Z-Offset
Position01X =   2.500000 ; X-Offset
Position01Y =   0.000000 ; Y-Offset
Position01Z =  -2.500000 ; Z-Offset
Position02X =  -5.000000 ; X-Offset
Position02Y =   0.000000 ; Y-Offset
Position02Z =  -5.000000 ; Z-Offset
Position03X =   5.000000 ; X-Offset
Position03Y =   0.000000 ; Y-Offset
Position03Z =  -5.000000 ; Z-Offset
Position04X =   0.000000 ; X-Offset
Position04Y =   0.000000 ; Y-Offset
Position04Z =  -5.000000 ; Z-Offset
Position05X =  -7.500000 ; X-Offset
Position05Y =   0.000000 ; Y-Offset
Position05Z =  -7.500000 ; Z-Offset
Position06X =   7.500000 ; X-Offset
Position06Y =   0.000000 ; Y-Offset
Position06Z =  -7.500000 ; Z-Offset
Position07X =   0.000000 ; X-Offset
Position07Y =   0.000000 ; Y-Offset
Position07Z =  -7.500000 ; Z-Offset
Position08X =   0.000000 ; X-Offset
Position08Y =   0.000000 ; Y-Offset
Position08Z = -10.000000 ; Z-Offset
Position09X =   0.000000 ; X-Offset
Position09Y =   0.000000 ; Y-Offset
Position09Z = -12.500000 ; Z-Offset

          ▲      	  0.0
        °   °    	 -2.5
      °   °   °  	 -5.0
    °     °     °	 -7.5
          °      	-10.0
          °      	-12.5

[WingNo025] ; ARROW_2_10, Doppelpfeil. Konstante = FORMATION_ARROW_2_10
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X =  -2.500000 ; X-Offset
Position00Y =   0.000000 ; Y-Offset
Position00Z =  -2.500000 ; Z-Offset
Position01X =   2.500000 ; X-Offset
Position01Y =   0.000000 ; Y-Offset
Position01Z =  -2.500000 ; Z-Offset
Position02X =  -5.000000 ; X-Offset
Position02Y =   0.000000 ; Y-Offset
Position02Z =  -5.000000 ; Z-Offset
Position03X =   5.000000 ; X-Offset
Position03Y =   0.000000 ; Y-Offset
Position03Z =  -5.000000 ; Z-Offset
Position04X =   0.000000 ; X-Offset
Position04Y =   0.000000 ; Y-Offset
Position04Z =  -5.000000 ; Z-Offset
Position05X =  -7.500000 ; X-Offset
Position05Y =   0.000000 ; Y-Offset
Position05Z =  -7.500000 ; Z-Offset
Position06X =   7.500000 ; X-Offset
Position06Y =   0.000000 ; Y-Offset
Position06Z =  -7.500000 ; Z-Offset
Position07X =   0.000000 ; X-Offset
Position07Y =   0.000000 ; Y-Offset
Position07Z =  -7.500000 ; Z-Offset
Position08X =  -2.500000 ; X-Offset
Position08Y =   0.000000 ; Y-Offset
Position08Z = -10.000000 ; Z-Offset
Position09X =   2.500000 ; X-Offset
Position09Y =   0.000000 ; Y-Offset
Position09Z = -10.000000 ; Z-Offset

          ▲      	  0.0
        °   °    	 -2.5
      °   °   °  	 -5.0
    °     °     °	 -7.5
        °   °    	-10.0

[WingNo026] ; ARROW_3D_10, 3D-Pfeil. Konstante = FORMATION_ARROW_3D_10
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position09X =  0.000000 ; X-Offset
Position09Y =  0.000000 ; Y-Offset
Position09Z = -2.500000 ; Z-Offset
Position00X = -2.500000 ; X-Offset
Position00Y =  0.000000 ; Y-Offset
Position00Z = -2.500000 ; Z-Offset
Position01X =  2.500000 ; X-Offset
Position01Y =  0.000000 ; Y-Offset
Position01Z = -2.500000 ; Z-Offset
Position07X =  0.000000 ; X-Offset
Position07Y = -2.500000 ; Y-Offset
Position07Z = -2.500000 ; Z-Offset
Position08X =  0.000000 ; X-Offset
Position08Y =  2.500000 ; Y-Offset
Position08Z = -2.500000 ; Z-Offset
Position02X = -5.000000 ; X-Offset
Position02Y =  0.000000 ; Y-Offset
Position02Z = -5.000000 ; Z-Offset
Position03X =  5.000000 ; X-Offset
Position03Y =  0.000000 ; Y-Offset
Position03Z = -5.000000 ; Z-Offset
Position04X =  0.000000 ; X-Offset
Position04Y = -5.000000 ; Y-Offset
Position04Z = -5.000000 ; Z-Offset
Position05X =  0.000000 ; X-Offset
Position05Y =  5.000000 ; Y-Offset
Position05Z = -5.000000 ; Z-Offset
Position06X =  0.000000 ; X-Offset
Position06Y =  0.000000 ; Y-Offset
Position06Z = -5.000000 ; Z-Offset

[WingNo027] ; DIAMOND_10, Raute. Konstante = FORMATION_DIAMOND_10
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X =  0.000000 ; X-Offset
Position00Y =  0.000000 ; Y-Offset
Position00Z =  5.000000 ; Z-Offset
Position01X = -2.500000 ; X-Offset
Position01Y =  0.000000 ; Y-Offset
Position01Z =  2.500000 ; Z-Offset
Position02X =  2.500000 ; X-Offset
Position02Y =  0.000000 ; Y-Offset
Position02Z =  2.500000 ; Z-Offset
Position03X = -5.000000 ; X-Offset
Position03Y =  0.000000 ; Y-Offset
Position03Z =  0.000000 ; Z-Offset
Position04X =  5.000000 ; X-Offset
Position04Y =  0.000000 ; Y-Offset
Position04Z =  0.000000 ; Z-Offset
Position05X = -2.500000 ; X-Offset
Position05Y =  0.000000 ; Y-Offset
Position05Z = -2.500000 ; Z-Offset
Position06X =  2.500000 ; X-Offset
Position06Y =  0.000000 ; Y-Offset
Position06Z = -2.500000 ; Z-Offset
Position07X =  0.000000 ; X-Offset
Position07Y =  0.000000 ; Y-Offset
Position07Z = -5.000000 ; Z-Offset
Position08X =  0.000000 ; X-Offset
Position08Y =  2.500000 ; Y-Offset
Position08Z =  0.000000 ; Z-Offset
Position09X =  0.000000 ; X-Offset
Position09Y = -2.500000 ; Y-Offset
Position09Z =  0.000000 ; Z-Offset

        °    	  5.0
      °   °  	  2.5
    °   ▲   °	  0.0	Y1 = -2.5;  Y2 = 2.5;  je 1 Jäger
      °   °  	 -2.5
        °    	 -5.0

[WingNo028] ; CIRCLE_8, Kreis, Boss fliegt im Zentrum. Konstante = FORMATION_CIRCLE_8
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 100.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X = -2.000000 ; X-Offset
Position00Y =  0.000000 ; Y-Offset
Position00Z =  0.000000 ; Z-Offset
Position01X = -1.410000 ; X-Offset
Position01Y =  1.410000 ; Y-Offset
Position01Z =  0.000000 ; Z-Offset
Position02X =  0.000000 ; X-Offset
Position02Y =  2.000000 ; Y-Offset
Position02Z =  0.000000 ; Z-Offset
Position03X =  1.410000 ; X-Offset
Position03Y =  1.410000 ; Y-Offset
Position03Z =  0.000000 ; Z-Offset
Position04X =  2.000000 ; X-Offset
Position04Y =  0.000000 ; Y-Offset
Position04Z =  0.000000 ; Z-Offset
Position05X =  1.410000 ; X-Offset
Position05Y = -1.410000 ; Y-Offset
Position05Z =  0.000000 ; Z-Offset
Position06X =  0.000000 ; X-Offset
Position06Y = -2.000000 ; Y-Offset
Position06Z =  0.000000 ; Z-Offset
Position07X = -1.410000 ; X-Offset
Position07Y = -1.410000 ; Y-Offset
Position07Z =  0.000000 ; Z-Offset

        °    	  2.00
      °   °  	  1.41
    °   ▲   °	  0.00
      °   °  	 -1.41
        °    	 -2.00
        ↑
;) Soll ein Kreis sein ;)

[WingNo031] ; KREUZER_ESKORTE, Flankenschutz, Konstante = FORMATION_CRUISER_ESCORT
AiState = Jäger ; Wingtyp, der das Maneuver anwendet
Interdist = 10.000000 ; Abstand zwischen den Positionen
Nations = Menschen,Morlok,Raptor,Octo,Wasp,Thul,S’kaa,1704 ; Set der anwendenden Nationen
Position00X =  10.000000 ; X-Offset
Position00Y =  -1.000000 ; Y-Offset
Position00Z =  -5.000000 ; Z-Offset
Position01X = -10.000000 ; X-Offset
Position01Y =  -1.000000 ; Y-Offset
Position01Z =  -5.000000 ; Z-Offset
Position02X =  10.000000 ; X-Offset
Position02Y =  -1.000000 ; Y-Offset
Position02Z = -10.000000 ; Z-Offset
Position03X = -10.000000 ; X-Offset
Position03Y =  -1.000000 ; Y-Offset
Position03Z = -10.000000 ; Z-Offset
Position04X =  10.000000 ; X-Offset
Position04Y =  -1.000000 ; Y-Offset
Position04Z = -15.000000 ; Z-Offset
Position05X = -10.000000 ; X-Offset
Position05Y =  -1.000000 ; Y-Offset
Position05Z = -15.000000 ; Z-Offset

          ▲      	  0.0
       °     °    	 -5.0	Y = -1
       °     °  	 -10.0	Y = -1
       °     °	 -15.0	Y = -1
---      -10  0  10    --→ X-Offset


Vorlagen

Skriptvorlagen

Vorlagen für Skripts der verschiedenen Missionstypen.

Inhalt

  1. Missionstyp MTYPE_ALWAYS
  2. Missionstyp MTYPE_BAR
  3. Missionstyp MTYPE_SPACE
  4. Missionstyp MTYPE_TERMINAL
  5. Missionstyp MTYPE_USER_SPACE
  6. Missionstyp MTYPE_USER_TERMINAL


Skriptvorlage MTYPE_ALWAYS

Vorlage für Missionsskripte ALWAYS_nn.lua
------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]----------------------------------------
-- Author:  [SNF]Norbert
-- Version: 1.0
------------------------------[ Description ]---------------------------------
-- Vorlage
------------------------------[ Notes ]---------------------------------------
--
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"  -- Verschiedene Hilfsfunktionen
------------------------------[ Register ]------------------------------------

NScript.Register( {
    Name  = "ALWAYS_00",
    Group = 0,
    Type  = MTYPE_ALWAYS,
    Transitions = {

------------------------------[ Transitions ]---------------------------------
------------------------------[ Initialization / Destruction ]----------------

{	-- Missionsstart prüfen
    nil, nil, "Init", function( V, Data )
    return { Ready = false }
end },

{	-- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    V.Step = 1
end },

{	-- Mission wird zerstört
    nil, nil, "Destroy", function( V, Data )
end },

------------------------------[ Mandatory callbacks ]-------------------------

{	-- Keinen Missionstext liefern
    nil, nil, "Text", function( V, Data )
    return { Text = "", Replace = {} }
end },

{	-- Mission startet bei jedem Sprung in ein System
    nil, nil, "MissionStart", function( V, Data )
end },

------------------------------[ Mission success / failure ]-------------------

{	-- Mission erfolgreich
    1, nil, "Achieved", function( V, Data )
    return { Timeout = 0 }
end },

{	-- Mission wird zerstört
    1, nil, "Failed", function( V, Data )
    return { Timeout = 0 }
end },

------------------------------[ Custom mission steps ]------------------------

{	-- Spieler betritt ein System
    1, 1, "System", function( V, Data )
end },

}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


Skriptvorlage MTYPE_BAR

Vorlage für Missionsskripte BAR_nnn.lua
------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]----------------------------------------
-- Author:  [SNF]Norbert
-- Version: 1.0
------------------------------[ Description ]---------------------------------
-- Vorlage
------------------------------[ Notes ]---------------------------------------
--
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"  -- Verschiedene Hilfsfunktionen
------------------------------[ Register ]------------------------------------

NScript.Register( {
    Name  = "BAR_000",
    Group = 0,
    Type  = MTYPE_BAR,
    Transitions = {

------------------------------[ Transitions ]---------------------------------
------------------------------[ Initialization / Destruction ]----------------

{	-- Missionsstart prüfen
    nil, nil, "Init", function( V, Data )
    if not MissionLib.IsMissionDone( "BAR_000" ) then
        local systemId = MissionLib.GetStarSystemId()
        if ( systemId <= 11 ) and ( systemId ~= 1 ) then
            return { Ready = true }
        end
    end
    return { Ready = false }
end },

{	-- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    local name = NObject.GetName( { Race = RACE_HUMAN } ).Name
    V.NPC = NNPC.Create( { Model = "Ratsmitglied2", Location = "01", Name = name } ).NPC
    V.TargetSystemId = 1  -- Cloosa
    V.Reward = NPlayer.StandardReward( { Factor = 1.5 } ).Credits
end },

{	-- Mission wird zerstört
    nil, nil, "Destroy", function( V, Data )
    if V.NPC then
        NNPC.Destroy( { NPC = V.NPC } )
        V.NPC = nil
    end
end },

------------------------------[ Mandatory callbacks ]-------------------------

{	-- Subtype festlegen
    nil, nil, "Subtype", function( V, Data )
    return { Subtype = SUBTYPE_HEADHUNT }
--	return { Subtype = SUBTYPE_PIRATES }
--	return { Subtype = SUBTYPE_POLITICAL }
--	return { Subtype = SUBTYPE_PROTECT }
--	return { Subtype = SUBTYPE_RESCUE }
--	return { Subtype = SUBTYPE_SABOTAGE }
--	return { Subtype = SUBTYPE_TRANSPORT }
end },

{	-- Mission startet
    nil, nil, "MissionStart", function( V, Data )
    NStarSystem.SetAsMissionTarget( { System = V.TargetSystemId, Set = true } )
    MissionLib.LogUpdateStory()
    -- nicht im Event "Create" einsetzen, sonst kein NPC!
    if V.NPC then
        NNPC.Destroy( { NPC = V.NPC } )
        V.NPC = nil
    end
    V.Step = 1
end },

------------------------------[ Mission success / failure ]-------------------

{	-- Mission erfolgreich
    1, nil, "Achieved", function( V, Data )
    NStarSystem.RemoveStoryLock( { System = 1 } )
    MissionLib.SetMissionDone("BAR_000")
    return { Credits = V.Reward, Keys = { 24 }, Timeout = -1 }
end },

{	-- Mission ist fehlgeschlagen
    1, nil, "Failed", function( V, Data )
    return { Timeout = 10 }
end },

------------------------------[ Custom mission steps ]------------------------

{	-- Missionsbeschreibung im NPC-Fenster
    nil, 2, "Text", function( V, Data )
    return {
        Header  = "IDM_BAR_000_BAR_HDR",
        Client  = "IDM_BAR_000_BAR_CLIENT",
        Text    = "IDM_BAR_000_BAR_TEXT",
        Replace = { "ID_SYSTEMNAME_"..V.TargetSystemId },
        Credits = V.Reward
    }
end },

{	-- Kurzbeschreibung der Mission als ersten Eintrag im Logbuch
    1, nil, "Text", function( V, Data )
    return {
        Header  = "IDM_BAR_000_BAR_HDR",
        Client  = "IDM_BAR_000_BAR_CLIENT",
        Text    = "IDM_BAR_000_LOG_TEXT",
        Replace = { "ID_SYSTEMNAME_"..V.TargetSystemId }
    }
end },

{	-- Beim Betreten des Systems alle Objekte erzeugen
    1, 1, "System", function( V, Data )
    if ( MissionLib.GetStarSystemId() == V.TargetSystemId ) and ( Data.State == ENTER_PRECAM ) then
        V.Step = 2
    end
end },

{	-- Mission fehlgeschlagen, wenn der Spieler hier das System verlässt
    2, nil, "System", function( V, Data )
    if Data.State == LEAVE_SYSTEM then
        NMission.SetState( { State = MSTATE_FAILED } )
        V.Step = 0
    end
end },

}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


Skriptvorlage MTYPE_SPACE

Vorlage für Missionsskripte SPACE_nnn.lua
------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]----------------------------------------
-- Author:  [SNF]Norbert
-- Version: 1.0
------------------------------[ Description ]---------------------------------
-- Vorlage
------------------------------[ Notes ]---------------------------------------
-- Space-Missionen starten immer im All zu einem zufälligen Zeitpunkt
-- den das Programm bestimmt und nicht vom Skript festgelegt werden kann.
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"  -- Verschiedene Hilfsfunktionen
------------------------------[ Register ]------------------------------------

NScript.Register( {
    Name  = "SPACE_000",
    Group = 0,
    Type  = MTYPE_SPACE,
    Transitions = {

------------------------------[ Transitions ]---------------------------------
------------------------------[ Initialization / Destruction ]----------------

{	-- Missionsstart prüfen
    nil, nil, "Init", function( V, Data )
    return { Ready = true }
end },

{	-- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    V.Step = 1
end },

{	-- Mission wird zerstört
    nil, nil, "Destroy", function( V, Data )
end },

------------------------------[ Mandatory callbacks ]-------------------------

{	-- Subtype festlegen
    nil, nil, "Subtype", function( V, Data )
    return { Subtype = SUBTYPE_HEADHUNT }
--	return { Subtype = SUBTYPE_PIRATES }
--	return { Subtype = SUBTYPE_POLITICAL }
--	return { Subtype = SUBTYPE_PROTECT }
--	return { Subtype = SUBTYPE_RESCUE }
--	return { Subtype = SUBTYPE_SABOTAGE }
--	return { Subtype = SUBTYPE_TRANSPORT }
end },

{	-- Keinen Missionstext liefern
    nil, nil, "Text", function( V, Data )
    return { Text = "", Replace = {} }
end },

{	-- Mission startet
    nil, nil, "MissionStart", function( V, Data )
end },

------------------------------[ Mission success / failure ]-------------------

{	-- Mission war erfolgreich
    1, nil, "Achieved", function( V, Data )
    return { Timeout = 0, Text = "" }
end },

{	-- Mission ist fehlgeschlagen
    1, nil, "Failed", function( V, Data )
    return { Timeout = 0, Text = "" }
end },

------------------------------[ Custom mission steps ]------------------------

{	-- Spieler betritt ein System
    1, 1, "System", function( V, Data )
end },

{	-- Spieler verlässt das System
    1, nil, "System", function( V, Data )
    if Data.State == LEAVE_SYSTEM then
        NMission.SetState( { State = MSTATE_FAILED } )
    end
end },

}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


Skriptvorlage MTYPE_TERMINAL

Vorlage für Missionsskripte TERMINAL_nnn.lua
------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]----------------------------------------
-- Author:  [SNF]Norbert
-- Version: 1.0
------------------------------[ Description ]---------------------------------
-- Vorlage
--------------------------------[ Notes ]-------------------------------------
--
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"  -- Verschiedene Hilfsfunktionen
------------------------------[ Register ]------------------------------------

NScript.Register( {
    Name  = "TERMINAL_000",
    Group = 0,
    Type  = MTYPE_TERMINAL,
    Transitions = {

------------------------------[ Transitions ]---------------------------------
------------------------------[ Initialization / Destruction ]----------------

{	-- Missionsstart prüfen
    nil, nil, "Init", function( V, Data )
    return { Ready = true }
end },

{	-- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    V.Reward = 0
end },

{	-- Mission wird zerstört
    nil, nil, "Destroy", function( V, Data )
end },

------------------------------[ Mandatory callbacks ]-------------------------

{	-- Subtype festlegen
    nil, nil, "Subtype", function( V, Data )
    return { Subtype = SUBTYPE_HEADHUNT }
--	return { Subtype = SUBTYPE_PIRATES }
--	return { Subtype = SUBTYPE_POLITICAL }
--	return { Subtype = SUBTYPE_PROTECT }
--	return { Subtype = SUBTYPE_RESCUE }
--	return { Subtype = SUBTYPE_SABOTAGE }
--	return { Subtype = SUBTYPE_TRANSPORT }
end },

{	-- Missionstext liefern
    nil, nil, "Text", function( V, Data )
    return { Text = "", Replace = {} }
end },

{	-- Mission startet
    nil, nil, "MissionStart", function( V, Data )
    V.Step = 1
end },

------------------------------[ Mission success / failure ]-------------------

{	-- Mission war erfolgreich
    1, nil, "Achieved", function( V, Data )
    return { Credits = 0, Timeout = 0 }
end },

{	-- Mission ist fehlgeschlagen
    1, nil, "Failed", function( V, Data )
    return { Credits = 0, Timeout = 0 }
end },

------------------------------[ Custom mission steps ]------------------------

{	-- Spieler verlässt die Station
    1, 1, "Station", function( V, Data )
end },

{	-- Spieler hat das Zielsystem erreicht
    1, 1, "System", function( V, Data )
end },

}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


Skriptvorlage MTYPE_USER_SPACE

Vorlage für Missionsskripte USER_SPACE_nnn.lua
------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]----------------------------------------
-- Author:  [SNF]Norbert
-- Version: 1.0
------------------------------[ Description ]---------------------------------
-- Vorlage
------------------------------[ Notes ]---------------------------------------
-- Space-Missionen starten immer im All zu einem zufälligen Zeitpunkt
-- den das Programm bestimmt und nicht vom Skript festgelegt werden kann.
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"  -- Verschiedene Hilfsfunktionen
------------------------------[ Register ]------------------------------------

NScript.Register( {
    Name  = "USER_SPACE_000",
    Group = 0,
    Type  = MTYPE_USER_SPACE,
    Transitions = {

------------------------------[ Transitions ]---------------------------------
------------------------------[ Initialization / Destruction ]----------------

{	-- Missionsstart prüfen
    nil, nil, "Init", function( V, Data )
    return { Ready = true }
end },

{	-- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    V.Step = 1
end },

{	-- Mission wird zerstört
    nil, nil, "Destroy", function( V, Data )
end },

------------------------------[ Mandatory callbacks ]-------------------------

{	-- Subtype festlegen
    nil, nil, "Subtype", function( V, Data )
    return { Subtype = SUBTYPE_HEADHUNT }
--	return { Subtype = SUBTYPE_PIRATES }
--	return { Subtype = SUBTYPE_POLITICAL }
--	return { Subtype = SUBTYPE_PROTECT }
--	return { Subtype = SUBTYPE_RESCUE }
--	return { Subtype = SUBTYPE_SABOTAGE }
--	return { Subtype = SUBTYPE_TRANSPORT }
end },

{	-- Keinen Missionstext liefern
    nil, nil, "Text", function( V, Data )
    return { Text = "", Replace = {} }
end },

{	-- Mission startet
    nil, nil, "MissionStart", function( V, Data )
end },

------------------------------[ Mission success / failure ]-------------------

{	-- Mission war erfolgreich
    1, nil, "Achieved", function( V, Data )
    return { Timeout = 0, Text = "" }
end },

{	-- Mission ist fehlgeschlagen
    1, nil, "Failed", function( V, Data )
    return { Timeout = 0, Text = "" }
end },

------------------------------[ Custom mission steps ]------------------------

{	-- Spieler betritt ein System
    1, 1, "System", function( V, Data )
end },

{	-- Spieler verlässt das System
    1, nil, "System", function( V, Data )
    if Data.State == LEAVE_SYSTEM then
        NMission.SetState( { State = MSTATE_FAILED } )
    end
end },

}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


Skriptvorlage MTYPE_USER_TERMINAL

Vorlage für Missionsskripte USER_TERMINAL_nnn.lua
------------------------------------------------------------------------------
-- Dark Star One (TM) - Mission Script
-- Copyright (C) [SNF]Norbert
-- All Rights Reserved.
------------------------------[ Info ]----------------------------------------
-- Author:  [SNF]Norbert
-- Version: 1.0
------------------------------[ Description ]---------------------------------
-- Vorlage
--------------------------------[ Notes ]-------------------------------------
--
------------------------------[ Import ]--------------------------------------
source "lua/mission/MissionLib.lua"  -- Verschiedene Hilfsfunktionen
------------------------------[ Register ]------------------------------------

NScript.Register( {
    Name  = "USER_TERMINAL_000",
    Group = 0,
    Type  = MTYPE_USER_TERMINAL,
    Transitions = {

------------------------------[ Transitions ]---------------------------------
------------------------------[ Initialization / Destruction ]----------------

{	-- Missionsstart prüfen
    nil, nil, "Init", function( V, Data )
    return { Ready = true }
end },

{	-- Mission erzeugen
    nil, nil, "Create", function( V, Data )
    V.Reward = 0
end },

{	-- Mission wird zerstört
    nil, nil, "Destroy", function( V, Data )
end },

------------------------------[ Mandatory callbacks ]-------------------------

{	-- Subtype festlegen
    nil, nil, "Subtype", function( V, Data )
    return { Subtype = SUBTYPE_HEADHUNT }
--	return { Subtype = SUBTYPE_PIRATES }
--	return { Subtype = SUBTYPE_POLITICAL }
--	return { Subtype = SUBTYPE_PROTECT }
--	return { Subtype = SUBTYPE_RESCUE }
--	return { Subtype = SUBTYPE_SABOTAGE }
--	return { Subtype = SUBTYPE_TRANSPORT }
end },

{	-- Missionstext liefern
    nil, nil, "Text", function( V, Data )
    return { Text = "", Replace = {} }
end },

{	-- Mission startet
    nil, nil, "MissionStart", function( V, Data )
    V.Step = 1
end },

------------------------------[ Mission success / failure ]-------------------

{	-- Mission war erfolgreich
    1, nil, "Achieved", function( V, Data )
    return { Credits = 0, Timeout = 0 }
end },

{	-- Mission ist fehlgeschlagen
    1, nil, "Failed", function( V, Data )
    return { Credits = 0, Timeout = 0 }
end },

------------------------------[ Custom mission steps ]------------------------

{	-- Spieler verlässt die Station
    1, 1, "Station", function( V, Data )
end },

{	-- Spieler hat das Zielsystem erreicht
    1, 1, "System", function( V, Data )
end },

}  -- close transition table
}  -- close parameter table of NScript.Register()
)  -- close function call to NScript.Register()


Scripting Konstanten

ScriptingEvents : Konstanten

Diese Liste ist nicht vollständig und beinhaltet nur eine Übersicht der aus der ursprünglichen Dokumentation zusammengesuchten Konstanten. Genauere Listen mit Beschreibungen und den numerischen Werten der Konstanten sind unter den Tabellen zu finden.

GUI

  • GUI_NAVMAP
  • GUI_TARGETVIEW
  • GUI_HYPERJUMP

Canyon

  • CST_ENTER
  • CST_ENTER_REVERSE
  • CST_HOVER
  • CST_HOVER_REVERSE
  • CST_ON_SPLINE
  • CST_ON_SPLINE_REVERSE
  • CST_LANDING
  • SPEED_DYNAMIC
  • SPEED_FIXED
  • SPLINE_PLAYER
  • SPLINE_AI_0
  • SPLINE_AI_1
  • SPLINE_AI_2
  • SPLINE_AI_3
  • SPLINE_OVERTURN
  • SPLINE_ENTER

Wingtypen

  • WINGTYPE_HUNTER
  • WINGTYPE_FREIGHTER100T
  • WINGTYPE_FREIGHTER200T
  • WINGTYPE_POLICE
  • WINGTYPE_MILITARY
  • WINGTYPE_CRUISER1
  • WINGTYPE_CRUISER2
  • WINGTYPE_WEAPONBASE
  • WINGTYPE_PIRATES
  • WINGTYPE_RAIDERS
  • WINGTYPE_PIRATEFREIGHTER

Wingstatus

  • WING_NO_TARGET
  • WING_DESTROYED
  • WING_TARGET_REACHED
  • WING_ENTER_SYSTEM

Comm

  • COMMTYPE_LANDING_CLEARED
  • COMMTYPE_LANDING_DENIED

Shield

  • SHIELD_BACK
  • SHIELD_FRONT
  • SHIELD_BOTH

Dialog

  • DIALOG_TYPE_1
  • DIALOG_TYPE_EIGHT
  • DIALOG_TYPE_TURN

Startpositionen

  • HYPERSPACE
  • HYPERNEAR
  • TRADESTATION
  • HANGAR
  • POSITION
  • FIGHTING
  • WINGDEST

Wingverhalten

  • PATROUILLE
  • KILLER
  • PIRATE
  • JUMP
  • DOCK
  • PLAYERKILLER

Schiffstypen

  • ST_PLAYERSHIP
  • ST_TRADERSHIP
  • ST_CONSUMPTION_SHUTTLE
  • ST_PRODUCTION_SHUTTLE
  • ST_POLICE
  • ST_PIRATESHIP
  • ST_WINGMAN
  • ST_CRUISER
  • ST_SKAADRONE
  • ST_MILITARYFIGHTER
  • ST_CARGODRONE
  • ST_WEAPONBASE
  • ST_PIRATEFREIGHTER
  • ST_SKAASWARM
  • ST_CANYONSHIP
  • ST_COMMSAT
  • ST_TRADERDRONE
  • ST_COLLECTOR_SHUTTLE
  • ST_SHIELDGEN

Objekttypen

  • OBJTYPE_ASTEROID
  • OBJTYPE_BASE
  • OBJTYPE_GATE
  • OBJTYPE_KOMET
  • OBJTYPE_METEOR
  • OBJTYPE_MOON
  • OBJTYPE_PLANETBG
  • OBJTYPE_PLANETGR
  • OBJTYPE_PLANETTC
  • OBJTYPE_SUN
  • OBJTYPE_STATION
  • SPACE_SUN
  • SPACE_PLANET
  • SPACE_SHIP
  • SPACE_STATION
  • SPACE_TAXI
  • SPACE_TRANSPORTER
  • SPACE_CARGO
  • SPACE_ROCKET
  • SPACE_PIRATE
  • SPACE_MINE
  • SPACE_POLICE
  • SPACE_PROJECTILE
  • SPACE_WARPGATE
  • SPACE_CRUISER
  • SPACE_EXPLOSION
  • SPACE_MILITARY
  • SPACE_HUNTER
  • SPACE_SKAADRONE
  • SPACE_ASTEROID
  • SPACE_METEROID
  • SPACE_RING
  • SPACE_CANYON
  • SPACE_CAMERA
  • SPACE_SPELL
  • SPACE_DEBRIS
  • SPACE_CARGODRONE
  • SPACE_TURRET
  • SPACE_WEAPONBASE
  • SPACE_SCAT
  • SPACE_WARPEFFECT
  • SPACE_DECORATION
  • SPACE_PIRATE_FREIGHTER
  • SPACE_SKAASWARM
  • SPACE_COMMSAT

Tutorial

  • TUTORIAL_ONCLICK_NAVMAP
  • TUTORIAL_ONCLICK_TARGETMAP
  • TUTORIAL_ONCLICK_HYPERJUMP
  • TUTORIAL_ONCLICK_CLUSTERMAP
  • TUTORIAL_ONCLICK_PLAYERCRUISER
  • TUTORIAL_ONCLOSE_NAVMAP
  • TUTORIAL_ONCLOSE_TARGETMAP
  • TUTORIAL_ONCLOSE_CLUSTERMAP
  • TUTORIAL_ONCLOSE_PLAYERCRUISER
  • BLINK_BTN_NAVMAP
  • BLINK_BTN_TARGETMAP
  • BLINK_BTN_COMMUNICATION
  • BLINK_BTN_LOGBUCH
  • BLINK_BTN_OPTIONS
  • BLINK_BTN_ROCKETS
  • BLINK_BTN_SPELLWEAPON
  • BLINK_BTN_SHIP

Artefaktstatus

  • ARTEFACT_RECEIVED

Positionstypen

Konstante | Parameter | Kommentar
POSDESCR_PLAYERSHIP | -/- | Kugelschale um das Spielerschiff im Abstand von 2-4 Units (u).
POSDESCR_INTERCEPTION | -/- | Kugelschale im Abstand von 2-4 Units vom Mittelpunkt. Der Mittelpunkt liegt auf der Verbindungsachse Absprungtor - Handelsstation im Abstand von 4 Units vom Ring.
POSDESCR_OFFSET | -/- | Kugel mit einem Radius von 3 Units. Der Mittelpunkt liegt 3 Units von der 3-Unit-Marke der Verbindungsachse Absprungtor - Handelsstation entfernt.
POSDESCR_ASTEROID | -/- | Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Mittelpunkt des Asteroiden entfernt, auf der zur Handelsstation abgewandten Seite. Hat ein System mehrere Asteroiden, so wird zufällig ein Asteroid gewählt.
POSDESCR_TRADESTATION1 | -/- | Kugel mit einem Radius 0,5 Units. Der Mittelpunkt liegt 1 Unit vom Mittelpunkt der Handelsstation entfernt, auf der zum Absprungtor abgewandten Seite.
POSDESCR_TRADESTATION2 | -/- | Kugelschale um die Handelsstation im Abstand von 1-3 Units.
POSDESCR_RESEARCHSTATION | -/- | Kugel mit einem Radius von 0,5 Units. Der Mittelpunkt liegt 1u vom Mittelpunkt der Forschungsstation entfernt, auf der zur Handelsstation abgewandten Seite. Hat ein System mehrere Forschungsstationen, so wird zufällig eine Forschungsstation gewählt.
POSDESCR_WELCOME | -/- | Ein Ring mit einem Durchmesser von 0,1 Units, dessen Mittelpunkt 0,1 Units vor dem Tor der Handelsstation liegt.
POSDESCR_METEROIDS | -/- | Der Mittelpunkt eines Meteoritenfeldes. ( jedes System kann nur ein Feld haben )
POSDESCR_ESCORT | -/- | Ein Torus, dessen Mittelpunkt genau zwischen Handelsstation und Hyperraumtor liegt.
POSDESCR_HANGAR | Object | Start aus einem Objekt mit Hangar.
POSDESCR_WINGDISTANCE | Object und Distance | In einem gegebenen Abstand neben einem Wing im Weltraum.
POSDESCR_EXPLICIT | Position, FrontDir, UpDir | Eine absolute Position mit Ausrichtung.
POSDESCR_HYPERSPACE | -/- | Das System wird durch das Hyperraumtor betreten.
POSDESCR_HYPERSPACE_CRUISER | -/- | Kreuzer betreten das System ohne das Tor an einer freien Position.
POSDESCR_FIRST_PLANET | -/- | Position über dem ersten Planeten hinter der Handelsstation.
POSDESCR_ACTIONTURRET | Position | Position ist eine Position relativ zu dem ActionTurret.
POSDESCR_CRUISER_ENTRY | Position, FrontDir, UpDir | Kann mit S'kaa- und Kreuzerwings wie POSDESCR_EXPLICIT verwendet werden. Die Schiffe werden nur nicht einfach erzeugt, sondern betreten das System mit einem Hyperraumfenster und bremsen dann ab.

Containertypen

  • CONTAINER_ASTEROID
  • CONTAINER_SHIP
  • CONTAINER_SPACE
  • CONTAINER_POSITION

Containergrößen

  • CONTAINER_SMALL
  • CONTAINER_MEDIUM
  • CONTAINER_LARGE
  • CONTAINER_SPECIAL
  • CONTAINER_PASSENGER
  • CONTAINER_ROCK
  • CONTAINER_ARTEFACT

Containerwaren

  • GOODS_COALHYDRATES
  • GOODS_PROTEINS
  • GOODS_LIFEFORMS
  • GOODS_VEGFIBERS
  • GOODS_METALS
  • GOODS_PRECMETALS
  • GOODS_CRYSTALS
  • GOODS_ALLOYS
  • GOODS_MACHINERY
  • GOODS_ELECTRONICS
  • GOODS_COMPUTERS
  • GOODS_SHIPTECHS
  • GOODS_MEDICINE
  • GOODS_CHEMICALS
  • GOODS_LIQUOR
  • GOODS_FERTILIZER
  • GOODS_ENERGYCELLS
  • GOODS_FUELRODS
  • GOODS_ISOTOPES
  • GOODS_SUPERCONDUCTORS
  • GOODS_VIDEOGAMES
  • GOODS_LUXURIES
  • GOODS_ANDROIDS
  • GOODS_DRUGS
  • GOODS_MISSIONOBJECT

Sichtbarkeitsklassen

  • STAR_UNLOCKED - Ein System, das der Spieler betreten kann
  • STAR_MISSION - Ein System, das für Missionen gesperrt ist und mit dem im aktuellen System eine Mission gebildet werden kann
  • STAR_SYSTEMKEY - Ein System, das sichtbar ist und für das in dem aktuellen System der Schlüssel vergeben werden darf
  • STAR_GANGSYSTEM - Ein System, das sichtbar ist und eine Piratengang enthält

Nationen / Race

  • RACE_HUMAN
  • RACE_MORLOK
  • RACE_RAPTOR
  • RACE_OCTO
  • RACE_WASP
  • RACE_THUL
  • RACE_SKAA

Regierung / Government

  • GOVERN_ANARCHY
  • GOVERN_DICTATORSHIP
  • GOVERN_FEDERATION
  • GOVERN_DEMOCRACY
  • GOVERN_CONCERN
  • GOVERN_MONARCHY

Fraktion / Faction

  • FACTION_FEDERATION
  • FACTION_REBELS
  • FACTION_INDEPENDENT

System Wirtschaft / System economy

  • SYSTEM_AGRICULTURE
  • SYSTEM_INDUSTRY
  • SYSTEM_MINING
  • SYSTEM_PHARMACEUTICS
  • SYSTEM_RESEARCH
  • SYSTEM_SERVICE

System Wohlstand / System wealth

  • WEALTH_POOR
  • WEALTH_RICH
  • WEALTH_WEALTHY

Missionsstatus

  • MISSION_ACHIEVED
  • MISSION_ENDED
  • MISSION_FAILED
  • MISSION_NONE
  • MISSION_OFFERING
  • MISSION_RUNNING

Missionstypen

  • SUBTYPE_HEADHUNT
  • SUBTYPE_TRANSPORT
  • SUBTYPE_PIRATES
  • SUBTYPE_SABOTAGE
  • SUBTYPE_PROTECT
  • SUBTYPE_RESCUE
  • SUBTYPE_POLITICAL

Orbitertypen

  • OBJTYPE_ASTEROID
  • OBJTYPE_BASE (Handelsstation)
  • OBJTYPE_GATE (Hypergate)
  • OBJTYPE_KOMET
  • OBJTYPE_METEOR (Meteoritenfeld)
  • OBJTYPE_MOON
  • OBJTYPE_PLANETBG (Agrarplanet)
  • OBJTYPE_PLANETGR (Gasriese)
  • OBJTYPE_PLANETTC (Technikplanet)
  • OBJTYPE_SUN
  • OBJTYPE_STATION (Forschungsstation)
  • ORBITART_ANOMALIE


Lua 5.1 Reference Manual - contents

Lua

Lua 5.1 Reference Manual

The reference manual is the official definition of the Lua language.

Start · Contents · Function-Index
Copyright © 2006-2008 Lua.org, PUC-Rio. Freely available under the terms of the Lua license.

Contents

  • 1 - Introduction

  • 2 - The Language
    • 2.1 - Lexical Conventions
    • 2.2 - Values and Types
      • 2.2.1 - Coercion
    • 2.3 - Variables
    • 2.4 - Statements
      • 2.4.1 - Chunks
      • 2.4.2 - Blocks
      • 2.4.3 - Assignment
      • 2.4.4 - Control Structures
      • 2.4.5 - For Statement
      • 2.4.6 - Function Calls as Statements
      • 2.4.7 - Local Declarations
    • 2.5 - Expressions
      • 2.5.1 - Arithmetic Operators
      • 2.5.2 - Relational Operators
      • 2.5.3 - Logical Operators
      • 2.5.4 - Concatenation
      • 2.5.5 - The Length Operator
      • 2.5.6 - Precedence
      • 2.5.7 - Table Constructors
      • 2.5.8 - Function Calls
      • 2.5.9 - Function Definitions
    • 2.6 - Visibility Rules
    • 2.7 - Error Handling
    • 2.8 - Metatables
    • 2.9 - Environments
    • 2.10 - Garbage Collection
      • 2.10.1 - Garbage-Collection Metamethods
      • 2.10.2 - Weak Tables
    • 2.11 - Coroutines

  • 3 - The Application Program Interface
    • 3.1 - The Stack
    • 3.2 - Stack Size
    • 3.3 - Pseudo-Indices
    • 3.4 - C Closures
    • 3.5 - Registry
    • 3.6 - Error Handling in C
    • 3.7 - Functions and Types
    • 3.8 - The Debug Interface

  • 4 - The Auxiliary Library
    • 4.1 - Functions and Types

  • 5 - Standard Libraries
    • 5.1 - Basic Functions
    • 5.2 - Coroutine Manipulation
    • 5.3 - Modules
    • 5.4 - String Manipulation
      • 5.4.1 - Patterns
    • 5.5 - Table Manipulation
    • 5.6 - Mathematical Functions
    • 5.7 - Input and Output Facilities
    • 5.8 - Operating System Facilities
    • 5.9 - The Debug Library

  • 6 - Lua Stand-alone

  • 7 - Incompatibilities with the Previous Version
    • 7.1 - Changes in the Language
    • 7.2 - Changes in the Libraries
    • 7.3 - Changes in the API

  • 8 - The Complete Syntax of Lua

Index

Lua functions

_G
_VERSION
assert
collectgarbage
dofile
error
getfenv
getmetatable
ipairs
load
loadfile
loadstring
module
next
pairs
pcall
print
rawequal
rawget
rawset
require
select
setfenv
setmetatable
tonumber
tostring
type
unpack
xpcall

coroutine.create
coroutine.resume
coroutine.running
coroutine.status
coroutine.wrap
coroutine.yield

debug.debug
debug.getfenv
debug.gethook
debug.getinfo
debug.getlocal
debug.getmetatable
debug.getregistry
debug.getupvalue
debug.setfenv
debug.sethook
debug.setlocal
debug.setmetatable
debug.setupvalue
debug.traceback

file:close
file:flush
file:lines
file:read
file:seek
file:setvbuf
file:write

io.close
io.flush
io.input
io.lines
io.open
io.output
io.popen
io.read
io.stderr
io.stdin
io.stdout
io.tmpfile
io.type
io.write

math.abs
math.acos
math.asin
math.atan
math.atan2
math.ceil
math.cos
math.cosh
math.deg
math.exp
math.floor
math.fmod
math.frexp
math.huge
math.ldexp
math.log
math.log10
math.max
math.min
math.modf
math.pi
math.pow
math.rad
math.random
math.randomseed
math.sin
math.sinh
math.sqrt
math.tan
math.tanh

os.clock
os.date
os.difftime
os.execute
os.exit
os.getenv
os.remove
os.rename
os.setlocale
os.time
os.tmpname

package.cpath
package.loaded
package.loaders
package.loadlib
package.path
package.preload
package.seeall

string.byte
string.char
string.dump
string.find
string.format
string.gmatch
string.gsub
string.len
string.lower
string.match
string.rep
string.reverse
string.sub
string.upper

table.concat
table.insert
table.maxn
table.remove
table.sort

C API

lua_Alloc
lua_CFunction
lua_Debug
lua_Hook
lua_Integer
lua_Number
lua_Reader
lua_State
lua_Writer

lua_atpanic
lua_call
lua_checkstack
lua_close
lua_concat
lua_cpcall
lua_createtable
lua_dump
lua_equal
lua_error
lua_gc
lua_getallocf
lua_getfenv
lua_getfield
lua_getglobal
lua_gethook
lua_gethookcount
lua_gethookmask
lua_getinfo
lua_getlocal
lua_getmetatable
lua_getstack
lua_gettable
lua_gettop
lua_getupvalue
lua_insert
lua_isboolean
lua_iscfunction
lua_isfunction
lua_islightuserdata
lua_isnil
lua_isnone
lua_isnoneornil
lua_isnumber
lua_isstring
lua_istable
lua_isthread
lua_isuserdata
lua_lessthan
lua_load
lua_newstate
lua_newtable
lua_newthread
lua_newuserdata
lua_next
lua_objlen
lua_pcall
lua_pop
lua_pushboolean
lua_pushcclosure
lua_pushcfunction
lua_pushfstring
lua_pushinteger
lua_pushlightuserdata
lua_pushliteral
lua_pushlstring
lua_pushnil
lua_pushnumber
lua_pushstring
lua_pushthread
lua_pushvalue
lua_pushvfstring
lua_rawequal
lua_rawget
lua_rawgeti
lua_rawset
lua_rawseti
lua_register
lua_remove
lua_replace
lua_resume
lua_setallocf
lua_setfenv
lua_setfield
lua_setglobal
lua_sethook
lua_setlocal
lua_setmetatable
lua_settable
lua_settop
lua_setupvalue
lua_status
lua_toboolean
lua_tocfunction
lua_tointeger
lua_tolstring
lua_tonumber
lua_topointer
lua_tostring
lua_tothread
lua_touserdata
lua_type
lua_typename
lua_upvalueindex
lua_xmove
lua_yield

auxiliary library

luaL_Buffer
luaL_Reg

luaL_addchar
luaL_addlstring
luaL_addsize
luaL_addstring
luaL_addvalue
luaL_argcheck
luaL_argerror
luaL_buffinit
luaL_callmeta
luaL_checkany
luaL_checkint
luaL_checkinteger
luaL_checklong
luaL_checklstring
luaL_checknumber
luaL_checkoption
luaL_checkstack
luaL_checkstring
luaL_checktype
luaL_checkudata
luaL_dofile
luaL_dostring
luaL_error
luaL_getmetafield
luaL_getmetatable
luaL_gsub
luaL_loadbuffer
luaL_loadfile
luaL_loadstring
luaL_newmetatable
luaL_newstate
luaL_openlibs
luaL_optint
luaL_optinteger
luaL_optlong
luaL_optlstring
luaL_optnumber
luaL_optstring
luaL_prepbuffer
luaL_pushresult
luaL_ref
luaL_register
luaL_typename
luaL_typerror
luaL_unref
luaL_where

Last update: Tue Jul 28 15:41:24 BRT 2009


License

Lizenzbestimmungen und Copyright

Dekompilierung und Programmänderungen

(1) Die Rückübersetzung des im Computerspiel enthaltenen Programmcodes in andere Codeformen (Dekompilierung) sowie sonstige Arten der Rückerschließung der verschiedenen Herstellungsstufen des Programms (Reverse-Engineering) sind unzulässig.

(2) Die Entfernung des Kopierschutzes ist unzulässig. Nur wenn der Kopierschutz die störungsfreie Spielnutzung beeinträchtigt oder verhindert und bzw. Ascaron Entertainment trotz einer entsprechenden Mitteilung des Kunden unter genauer Beschreibung der aufgetretenen Störung die Störung nicht innerhalb von vier Wochen beseitigen kann oder will, darf der Kopierschutz zur Sicherstellung der Funktionsfähigkeit des Computerspiels entfernt werden. Für die Beeinträchtigung oder Verhinderung störungsfreier Benutzbarkeit durch den Kopierschutz trägt der Kunde die Beweislast. Die besondere Informationspflicht des Kunden nach § 11 der vorliegenden Lizenz- und Garantiebedingungen ist zu beachten.

(3) Andere als die in Abs. 2 geregelten Programmänderungen zum Zwecke der sonstigen Fehlerbeseitigung sind nur zulässig, wenn das geänderte Programm allein im Rahmen des eigenen Gebrauchs eingesetzt wird. Zum eigenen Gebrauch im Sinne dieser Regelung zählt insbesondere der private Gebrauch des Kunden. Daneben zählt zum eigenen Gebrauch aber auch der zu beruflichen oder erwerbswirtschaftlichen Zwecken dienende Gebrauch, sofern er sich auf die eigene Verwendung durch den Kunden beschränkt und nicht nach außen hin in irgendeiner Art und Weise gewerblich verwertet werden soll.

(5) Urhebervermerke, Seriennummern sowie sonstige der Computerspielidentifikation dienende Merkmale dürfen auf keinen Fall entfernt oder verändert werden.

Spieländerungen

(1) Es ist dem Kunden gestattet, unter Verwendung des Computerspiels, des Benutzerhandbuchs und des sonstigen Begleitmaterials, insbesondere unter Verwendung des Level Editor, neue Levels, "Add-on"-Pakete oder andere, auf dem Computerspiel beruhende Produkte (gemeinsam "Spieländerungen" genannt) herzustellen und zu verbreiten, wenn er dabei folgende Bedingungen beachtet:

(a) die Spieländerungen müssen, um spielfähig zu sein, einer legal erworbenen Originalversion des Computerspiels bedürfen;

(b) sie dürfen keine in irgendeiner Weise geänderte Spielausführungsdatei enthalten;

(c) sie dürfen weder die Rechte Dritter (z.B. Urheber-, Persönlichkeits- oder Kennzeichenrechte) noch gesetzliche Bestimmungen (z.B. Jugendschutzgesetze) verletzen;

(d) die Nutzung und Vertrieb der Spieländerungen muss unentgeltlich erfolgen, d.h. weder der Kunde noch ein Dritter darf in irgendeiner Weise von der Nutzung oder dem Vertrieb der Spieländerungen finanziell profitieren;

Nicht gestattete Nutzungshandlungen

(1) Sofern dies durch diese Lizenz- und Garantiebedingungen nicht ausdrücklich gestattet ist, ist der Kunde nicht berechtigt, das Computerspiel, das Benutzerhandbuch sowie das sonstige Begleitmaterial oder Teile (z.B. Charaktere, Figuren, Dialoge oder sonstige Elemente) hieraus zu vervielfältigen, zu verändern, zu verbreiten (insbesondere zu vermieten oder zu verleihen) oder öffentlich wiederzugeben. Insbesondere ist es dem Kunden nicht gestattet, das Computerspiel, das Benutzerhandbuch sowie das sonstige Begleitmaterial oder Teile hieraus über das Internet oder ein vergleichbares Netz zum Abruf zugänglich zu machen oder an eine andere Person (z.B. über E-mail oder über einen Internet-Dateidienst wie FTP oder Peer-to-Peer) zu übertragen.

(2) Grundsätzlich stellt jede nicht nach diesen Lizenz- und Garantiebedingungen gestattete Vervielfältigung, Verbreitung (insbesondere über das Internet oder vergleichbare Netze) oder öffentliche Wiedergabe des Computerspiels, des Benutzerhandbuchs oder des sonstigen Begleitmaterials ein Urheberrechtsverletzung dar, die von Ascaron Entertainment zivil- und gegebenenfalls auch strafrechtlich verfolgt wird.


Lua: License

Lua is free software: it can be used for any purpose, including commercial purposes, at absolutely no cost. No paperwork, no royalties, no GNU-like "copyleft" restrictions, either. Just download it and use it. Lua is certified Open Source software. Its licenses are compatible with GPL. Lua is not in the public domain and PUC-Rio keeps its copyright. The legal details are below.

[osi certified] | License for Lua 5.0 and later versions: Since Lua 5.0, Lua is licensed under the terms of the MIT license reproduced below.
[open source] | License for Lua 4.0 and earlier versions: Until Lua 4.0, Lua used its own license, which was very close to the zlib license and others, but not quite the same.

The spirit of both licenses is that you are free to use Lua for any purpose at no cost without having to ask us. The only requirement is that if you do use Lua, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation. A nice, but optional, way to give us further credit is to include a Lua logo and a link to our site in a web page for your product.

The Lua language is entirely designed, implemented, and maintained by a team at PUC-Rio in Brazil. The implementation is not derived from licensed software.

License for Lua 5.0 and later versions

Copyright © 1994-2008 Lua.org, PUC-Rio.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

License for Lua 4.0 and earlier versions

Copyright © 1994-2002 Tecgraf, PUC-Rio.

Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, translate, and distribute this software and its documentation (hereby called the "package") for any purpose, including commercial applications, subject to the following conditions:

  • The above copyright notice and this permission notice shall appear in all copies or substantial portions of this package.
  • The origin of this package must not be misrepresented; you must not claim that you wrote the original package. If you use this package in a product, an acknowledgment in the product documentation would be greatly appreciated (but it is not required).
  • Altered source versions must be plainly marked as such, and must not be misrepresented as being the original package.
The authors specifically disclaim any warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The package provided hereunder is on an "as is" basis, and the authors have no obligation to provide maintenance, support, updates, enhancements, or modifications. In no event shall Tecgraf, PUC-Rio, or the authors be held liable to any party for direct, indirect, special, incidental, or consequential damages arising out of the use of this package and its documentation.

Last update: Mon Aug 4 07:59:38 BRT 2008


Lua 5.1 Reference Manual

by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes

Copyright © 2006-2008 Lua.org, PUC-Rio. Freely available under the terms of the Lua license.
Contents online · Index online

Contents · Function-Index

1 - Introduction

Lua is an extension programming language designed to support general procedural programming with data description facilities. It also offers good support for object-oriented programming, functional programming, and data-driven programming. Lua is intended to be used as a powerful, light-weight scripting language for any program that needs one. Lua is implemented as a library, written in clean C (that is, in the common subset of ANSI C and C++).

Being an extension language, Lua has no notion of a "main" program: it only works embedded in a host client, called the embedding program or simply the host. This host program can invoke functions to execute a piece of Lua code, can write and read Lua variables, and can register C functions to be called by Lua code. Through the use of C functions, Lua can be augmented to cope with a wide range of different domains, thus creating customized programming languages sharing a syntactical framework. The Lua distribution includes a sample host program called lua, which uses the Lua library to offer a complete, stand-alone Lua interpreter.

Lua is free software, and is provided as usual with no guarantees, as stated in its license. The implementation described in this manual is available at Lua's official web site, www.lua.org.

Like any other reference manual, this document is dry in places. For a discussion of the decisions behind the design of Lua, see the technical papers available at Lua's web site. For a detailed introduction to programming in Lua, see Roberto's book, Programming in Lua (Second Edition).

2 - The Language

This section describes the lexis, the syntax, and the semantics of Lua. In other words, this section describes which tokens are valid, how they can be combined, and what their combinations mean.

The language constructs will be explained using the usual extended BNF notation, in which {a} means 0 or more a's, and [a] means an optional a. Non-terminals are shown like non-terminal, keywords are shown like kword, and other terminal symbols are shown like `=´. The complete syntax of Lua can be found in §8 at the end of this manual.

2.1 - Lexical Conventions

Names (also called identifiers) in Lua can be any string of letters, digits, and underscores, not beginning with a digit. This coincides with the definition of names in most languages. (The definition of letter depends on the current locale: any character considered alphabetic by the current locale can be used in an identifier.) Identifiers are used to name variables and table fields.

The following keywords are reserved and cannot be used as names:

     and       break     do        else      elseif
     end       false     for       function  if
     in        local     nil       not       or
     repeat    return    then      true      until     while

Lua is a case-sensitive language: and is a reserved word, but And and AND are two different, valid names. As a convention, names starting with an underscore followed by uppercase letters (such as _VERSION) are reserved for internal global variables used by Lua.

The following strings denote other tokens:

     +     -     *     /     %     ^     #
     ==    ~=    <=    >=    <     >     =
     (     )     {     }     [     ]
     ;     :     ,     .     ..    ...

Literal strings can be delimited by matching single or double quotes, and can contain the following C-like escape sequences: '\a' (bell), '\b' (backspace), '\f' (form feed), '\n' (newline), '\r' (carriage return), '\t' (horizontal tab), '\v' (vertical tab), '\\' (backslash), '\"' (quotation mark [double quote]), and '\'' (apostrophe [single quote]). Moreover, a backslash followed by a real newline results in a newline in the string. A character in a string can also be specified by its numerical value using the escape sequence \ddd, where ddd is a sequence of up to three decimal digits. (Note that if a numerical escape is to be followed by a digit, it must be expressed using exactly three digits.) Strings in Lua can contain any 8-bit value, including embedded zeros, which can be specified as '\0'.

Literal strings can also be defined using a long format enclosed by long brackets. We define an opening long bracket of level n as an opening square bracket followed by n equal signs followed by another opening square bracket. So, an opening long bracket of level 0 is written as [[, an opening long bracket of level 1 is written as [=[, and so on. A closing long bracket is defined similarly; for instance, a closing long bracket of level 4 is written as ]====]. A long string starts with an opening long bracket of any level and ends at the first closing long bracket of the same level. Literals in this bracketed form can run for several lines, do not interpret any escape sequences, and ignore long brackets of any other level. They can contain anything except a closing bracket of the proper level.

For convenience, when the opening long bracket is immediately followed by a newline, the newline is not included in the string. As an example, in a system using ASCII (in which 'a' is coded as 97, newline is coded as 10, and '1' is coded as 49), the five literal strings below denote the same string:

     a = 'alo\n123"'
     a = "alo\n123\""
     a = '\97lo\10\04923"'
     a = [[alo
     123"]]
     a = [==[
     alo
     123"]==]

A numerical constant can be written with an optional decimal part and an optional decimal exponent. Lua also accepts integer hexadecimal constants, by prefixing them with 0x. Examples of valid numerical constants are

     3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56

A comment starts with a double hyphen (--) anywhere outside a string. If the text immediately after -- is not an opening long bracket, the comment is a short comment, which runs until the end of the line. Otherwise, it is a long comment, which runs until the corresponding closing long bracket. Long comments are frequently used to disable code temporarily.

2.2 - Values and Types

Lua is a dynamically typed language. This means that variables do not have types; only values do. There are no type definitions in the language. All values carry their own type.

All values in Lua are first-class values. This means that all values can be stored in variables, passed as arguments to other functions, and returned as results.

There are eight basic types in Lua: nil, boolean, number, string, function, userdata, thread, and table. Nil is the type of the value nil, whose main property is to be different from any other value; it usually represents the absence of a useful value. Boolean is the type of the values false and true. Both nil and false make a condition false; any other value makes it true. Number represents real (double-precision floating-point) numbers. (It is easy to build Lua interpreters that use other internal representations for numbers, such as single-precision float or long integers; see file luaconf.h.) String represents arrays of characters. Lua is 8-bit clean: strings can contain any 8-bit character, including embedded zeros ('\0') (see §2.1).

Lua can call (and manipulate) functions written in Lua and functions written in C (see §2.5.8).

The type userdata is provided to allow arbitrary C data to be stored in Lua variables. This type corresponds to a block of raw memory and has no pre-defined operations in Lua, except assignment and identity test. However, by using metatables, the programmer can define operations for userdata values (see §2.8). Userdata values cannot be created or modified in Lua, only through the C API. This guarantees the integrity of data owned by the host program.

The type thread represents independent threads of execution and it is used to implement coroutines (see §2.11). Do not confuse Lua threads with operating-system threads. Lua supports coroutines on all systems, even those that do not support threads.

The type table implements associative arrays, that is, arrays that can be indexed not only with numbers, but with any value (except nil). Tables can be heterogeneous; that is, they can contain values of all types (except nil). Tables are the sole data structuring mechanism in Lua; they can be used to represent ordinary arrays, symbol tables, sets, records, graphs, trees, etc. To represent records, Lua uses the field name as an index. The language supports this representation by providing a.name as syntactic sugar for a["name"]. There are several convenient ways to create tables in Lua (see §2.5.7).

Like indices, the value of a table field can be of any type (except nil). In particular, because functions are first-class values, table fields can contain functions. Thus tables can also carry methods (see §2.5.9).

Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.

The library function type returns a string describing the type of a given value.

2.2.1 - Coercion

Lua provides automatic conversion between string and number values at run time. Any arithmetic operation applied to a string tries to convert this string to a number, following the usual conversion rules. Conversely, whenever a number is used where a string is expected, the number is converted to a string, in a reasonable format. For complete control over how numbers are converted to strings, use the format function from the string library (see string.format).

2.3 - Variables

Variables are places that store values. There are three kinds of variables in Lua: global variables, local variables, and table fields.

A single name can denote a global variable or a local variable (or a function's formal parameter, which is a particular kind of local variable):

    var ::= Name

Name denotes identifiers, as defined in §2.1.

Any variable is assumed to be global unless explicitly declared as a local (see §2.4.7). Local variables are lexically scoped: local variables can be freely accessed by functions defined inside their scope (see §2.6).

Before the first assignment to a variable, its value is nil.

Square brackets are used to index a table:

    var ::= prefixexp `[´ exp `]´

The meaning of accesses to global variables and table fields can be changed via metatables. An access to an indexed variable t[i] is equivalent to a call gettable_event(t,i). (See §2.8 for a complete description of the gettable_event function. This function is not defined or callable in Lua. We use it here only for explanatory purposes.)

The syntax var.Name is just syntactic sugar for var["Name"]:

    var ::= prefixexp `.´ Name

All global variables live as fields in ordinary Lua tables, called environment tables or simply environments (see §2.9). Each function has its own reference to an environment, so that all global variables in this function will refer to this environment table. When a function is created, it inherits the environment from the function that created it. To get the environment table of a Lua function, you call getfenv. To replace it, you call setfenv. (You can only manipulate the environment of C functions through the debug library; (see §5.9).)

An access to a global variable x is equivalent to _env.x, which in turn is equivalent to

     gettable_event(_env, "x")

where _env is the environment of the running function. (See §2.8 for a complete description of the gettable_event function. This function is not defined or callable in Lua. Similarly, the _env variable is not defined in Lua. We use them here only for explanatory purposes.)

2.4 - Statements

Lua supports an almost conventional set of statements, similar to those in Pascal or C. This set includes assignments, control structures, function calls, and variable declarations.

2.4.1 - Chunks

The unit of execution of Lua is called a chunk. A chunk is simply a sequence of statements, which are executed sequentially. Each statement can be optionally followed by a semicolon:

    chunk ::= {stat [`;´]}

There are no empty statements and thus ';;' is not legal.

Lua handles a chunk as the body of an anonymous function with a variable number of arguments (see §2.5.9). As such, chunks can define local variables, receive arguments, and return values.

A chunk can be stored in a file or in a string inside the host program. To execute a chunk, Lua first pre-compiles the chunk into instructions for a virtual machine, and then it executes the compiled code with an interpreter for the virtual machine.

Chunks can also be pre-compiled into binary form; see program luac for details. Programs in source and compiled forms are interchangeable; Lua automatically detects the file type and acts accordingly.

2.4.2 - Blocks

A block is a list of statements; syntactically, a block is the same as a chunk:

    block ::= chunk

A block can be explicitly delimited to produce a single statement:

    stat ::= do block end

Explicit blocks are useful to control the scope of variable declarations. Explicit blocks are also sometimes used to add a return or break statement in the middle of another block (see §2.4.4).

2.4.3 - Assignment

Lua allows multiple assignments. Therefore, the syntax for assignment defines a list of variables on the left side and a list of expressions on the right side. The elements in both lists are separated by commas:

    stat ::= varlist `=´ explist
    varlist ::= var {`,´ var}
    explist ::= exp {`,´ exp}

Expressions are discussed in §2.5.

Before the assignment, the list of values is adjusted to the length of the list of variables. If there are more values than needed, the excess values are thrown away. If there are fewer values than needed, the list is extended with as many nil's as needed. If the list of expressions ends with a function call, then all values returned by that call enter the list of values, before the adjustment (except when the call is enclosed in parentheses; see §2.5).

The assignment statement first evaluates all its expressions and only then are the assignments performed. Thus the code

     i = 3
     i, a[i] = i+1, 20

sets a[3] to 20, without affecting a[4] because the i in a[i] is evaluated (to 3) before it is assigned 4. Similarly, the line

     x, y = y, x

exchanges the values of x and y, and

     x, y, z = y, z, x

cyclically permutes the values of x, y, and z.

The meaning of assignments to global variables and table fields can be changed via metatables. An assignment to an indexed variable t[i] = val is equivalent to settable_event(t,i,val). (See §2.8 for a complete description of the settable_event function. This function is not defined or callable in Lua. We use it here only for explanatory purposes.)

An assignment to a global variable x = val is equivalent to the assignment _env.x = val, which in turn is equivalent to

     settable_event(_env, "x", val)

where _env is the environment of the running function. (The _env variable is not defined in Lua. We use it here only for explanatory purposes.)

2.4.4 - Control Structures

The control structures if, while, and repeat have the usual meaning and familiar syntax:

    stat ::= while exp do block end
    stat ::= repeat block until exp
    stat ::= if exp then block {elseif exp then block} [else block] end

Lua also has a for statement, in two flavors (see §2.4.5).

The condition expression of a control structure can return any value. Both false and nil are considered false. All values different from nil and false are considered true (in particular, the number 0 and the empty string are also true).

In the repeat–until loop, the inner block does not end at the until keyword, but only after the condition. So, the condition can refer to local variables declared inside the loop block.

The return statement is used to return values from a function or a chunk (which is just a function). Functions and chunks can return more than one value, and so the syntax for the return statement is

    stat ::= return [explist]

The break statement is used to terminate the execution of a while, repeat, or for loop, skipping to the next statement after the loop:

    stat ::= break

A break ends the innermost enclosing loop.

The return and break statements can only be written as the last statement of a block. If it is really necessary to return or break in the middle of a block, then an explicit inner block can be used, as in the idioms do return end and do break end, because now return and break are the last statements in their (inner) blocks.

2.4.5 - For Statement

The for statement has two forms: one numeric and one generic.

The numeric for loop repeats a block of code while a control variable runs through an arithmetic progression. It has the following syntax:

    stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end

The block is repeated for name starting at the value of the first exp, until it passes the second exp by steps of the third exp. More precisely, a for statement like

     for v = e1, e2, e3 do block end

is equivalent to the code:

     do
       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
       if not (var and limit and step) then error() end
       while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
         local v = var
         block
         var = var + step
       end
     end

Note the following:

  • All three control expressions are evaluated only once, before the loop starts. They must all result in numbers.
  • var, limit, and step are invisible variables. The names shown here are for explanatory purposes only.
  • If the third expression (the step) is absent, then a step of 1 is used.
  • You can use break to exit a for loop.
  • The loop variable v is local to the loop; you cannot use its value after the for ends or is broken. If you need this value, assign it to another variable before breaking or exiting the loop.

The generic for statement works over functions, called iterators. On each iteration, the iterator function is called to produce a new value, stopping when this new value is nil. The generic for loop has the following syntax:

    stat ::= for namelist in explist do block end
    namelist ::= Name {`,´ Name}

A for statement like

     for var_1, ···, var_n in explist do block end

is equivalent to the code:

     do
       local f, s, var = explist
       while true do
         local var_1, ···, var_n = f(s, var)
         var = var_1
         if var == nil then break end
         block
       end
     end

Note the following:

  • explist is evaluated only once. Its results are an iterator function, a state, and an initial value for the first iterator variable.
  • f, s, and var are invisible variables. The names are here for explanatory purposes only.
  • You can use break to exit a for loop.
  • The loop variables var_i are local to the loop; you cannot use their values after the for ends. If you need these values, then assign them to other variables before breaking or exiting the loop.

2.4.6 - Function Calls as Statements

To allow possible side-effects, function calls can be executed as statements:

    stat ::= functioncall

In this case, all returned values are thrown away. Function calls are explained in §2.5.8.

2.4.7 - Local Declarations

Local variables can be declared anywhere inside a block. The declaration can include an initial assignment:

    stat ::= local namelist [`=´ explist]

If present, an initial assignment has the same semantics of a multiple assignment (see §2.4.3). Otherwise, all variables are initialized with nil.

A chunk is also a block (see §2.4.1), and so local variables can be declared in a chunk outside any explicit block. The scope of such local variables extends until the end of the chunk.

The visibility rules for local variables are explained in §2.6.

2.5 - Expressions

The basic expressions in Lua are the following:

    exp ::= prefixexp
    exp ::= nil | false | true
    exp ::= Number
    exp ::= String
    exp ::= function
    exp ::= tableconstructor
    exp ::= `...´
    exp ::= exp binop exp
    exp ::= unop exp
    prefixexp ::= var | functioncall | `(´ exp `)´

Numbers and literal strings are explained in §2.1; variables are explained in §2.3; function definitions are explained in §2.5.9; function calls are explained in §2.5.8; table constructors are explained in §2.5.7. Vararg expressions, denoted by three dots ('...'), can only be used when directly inside a vararg function; they are explained in §2.5.9.

Binary operators comprise arithmetic operators (see §2.5.1), relational operators (see §2.5.2), logical operators (see §2.5.3), and the concatenation operator (see §2.5.4). Unary operators comprise the unary minus (see §2.5.1), the unary not (see §2.5.3), and the unary length operator (see §2.5.5).

Both function calls and vararg expressions can result in multiple values. If an expression is used as a statement (only possible for function calls (see §2.4.6)), then its return list is adjusted to zero elements, thus discarding all returned values. If an expression is used as the last (or the only) element of a list of expressions, then no adjustment is made (unless the call is enclosed in parentheses). In all other contexts, Lua adjusts the result list to one element, discarding all values except the first one.

Here are some examples:

     f()                -- adjusted to 0 results
     g(f(), x)          -- f() is adjusted to 1 result
     g(x, f())          -- g gets x plus all results from f()
     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)
     a,b = ...          -- a gets the first vararg parameter, b gets
                        -- the second (both a and b can get nil if there
                        -- is no corresponding vararg parameter)

     a,b,c = x, f()     -- f() is adjusted to 2 results
     a,b,c = f()        -- f() is adjusted to 3 results
     return f()         -- returns all results from f()
     return ...         -- returns all received vararg parameters
     return x,y,f()     -- returns x, y, and all results from f()
     {f()}              -- creates a list with all results from f()
     {...}              -- creates a list with all vararg parameters
     {f(), nil}         -- f() is adjusted to 1 result

Any expression enclosed in parentheses always results in only one value. Thus, (f(x,y,z)) is always a single value, even if f returns several values. (The value of (f(x,y,z)) is the first value returned by f or nil if f does not return any values.)

2.5.1 - Arithmetic Operators

Lua supports the usual arithmetic operators: the binary + (addition), - (subtraction), * (multiplication), / (division), % (modulo), and ^ (exponentiation); and unary - (negation). If the operands are numbers, or strings that can be converted to numbers (see §2.2.1), then all operations have the usual meaning. Exponentiation works for any exponent. For instance, x^(-0.5) computes the inverse of the square root of x. Modulo is defined as

     a % b == a - math.floor(a/b)*b

That is, it is the remainder of a division that rounds the quotient towards minus infinity.

2.5.2 - Relational Operators

The relational operators in Lua are

     ==    ~=    <     >     <=    >=

These operators always result in false or true.

Equality (==) first compares the type of its operands. If the types are different, then the result is false. Otherwise, the values of the operands are compared. Numbers and strings are compared in the usual way. Objects (tables, userdata, threads, and functions) are compared by reference: two objects are considered equal only if they are the same object. Every time you create a new object (a table, userdata, thread, or function), this new object is different from any previously existing object.

You can change the way that Lua compares tables and userdata by using the "eq" metamethod (see §2.8).

The conversion rules of §2.2.1 do not apply to equality comparisons. Thus, "0"==0 evaluates to false, and t[0] and t["0"] denote different entries in a table.

The operator ~= is exactly the negation of equality (==).

The order operators work as follows. If both arguments are numbers, then they are compared as such. Otherwise, if both arguments are strings, then their values are compared according to the current locale. Otherwise, Lua tries to call the "lt" or the "le" metamethod (see §2.8). A comparison a > b is translated to b < a and a >= b is translated to b <= a.

2.5.3 - Logical Operators

The logical operators in Lua are and, or, and not. Like the control structures (see §2.4.4), all logical operators consider both false and nil as false and anything else as true.

The negation operator not always returns false or true. The conjunction operator and returns its first argument if this value is false or nil; otherwise, and returns its second argument. The disjunction operator or returns its first argument if this value is different from nil and false; otherwise, or returns its second argument. Both and and or use short-cut evaluation; that is, the second operand is evaluated only if necessary. Here are some examples:

     10 or 20            --> 10
     10 or error()       --> 10
     nil or "a"          --> "a"
     nil and 10          --> nil
     false and error()   --> false
     false and nil       --> false
     false or nil        --> nil
     10 and 20           --> 20

(In this manual, --> indicates the result of the preceding expression.)

2.5.4 - Concatenation

The string concatenation operator in Lua is denoted by two dots ('..'). If both operands are strings or numbers, then they are converted to strings according to the rules mentioned in §2.2.1. Otherwise, the "concat" metamethod is called (see §2.8).

2.5.5 - The Length Operator

The length operator is denoted by the unary operator #. The length of a string is its number of bytes (that is, the usual meaning of string length when each character is one byte).

The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).

2.5.6 - Precedence

Operator precedence in Lua follows the table below, from lower to higher priority:

     or
     and
     <     >     <=    >=    ~=    ==
     ..
     +     -
     *     /     %
     not   #     - (unary)
     ^

As usual, you can use parentheses to change the precedences of an expression. The concatenation ('..') and exponentiation ('^') operators are right associative. All other binary operators are left associative.

2.5.7 - Table Constructors

Table constructors are expressions that create tables. Every time a constructor is evaluated, a new table is created. A constructor can be used to create an empty table or to create a table and initialize some of its fields. The general syntax for constructors is

    tableconstructor ::= `{´ [fieldlist] `}´
    fieldlist ::= field {fieldsep field} [fieldsep]
    field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
    fieldsep ::= `,´ | `;´

Each field of the form [exp1] = exp2 adds to the new table an entry with key exp1 and value exp2. A field of the form name = exp is equivalent to ["name"] = exp. Finally, fields of the form exp are equivalent to [i] = exp, where i are consecutive numerical integers, starting with 1. Fields in the other formats do not affect this counting. For example,

     a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

is equivalent to

     do
       local t = {}
       t[f(1)] = g
       t[1] = "x"         -- 1st exp
       t[2] = "y"         -- 2nd exp
       t.x = 1            -- t["x"] = 1
       t[3] = f(x)        -- 3rd exp
       t[30] = 23
       t[4] = 45          -- 4th exp
       a = t
     end

If the last field in the list has the form exp and the expression is a function call or a vararg expression, then all values returned by this expression enter the list consecutively (see §2.5.8). To avoid this, enclose the function call or the vararg expression in parentheses (see §2.5).

The field list can have an optional trailing separator, as a convenience for machine-generated code.

2.5.8 - Function Calls

A function call in Lua has the following syntax:

    functioncall ::= prefixexp args

In a function call, first prefixexp and args are evaluated. If the value of prefixexp has type function, then this function is called with the given arguments. Otherwise, the prefixexp "call" metamethod is called, having as first parameter the value of prefixexp, followed by the original call arguments (see §2.8).

The form

    functioncall ::= prefixexp `:´ Name args

can be used to call "methods". A call v:name(args) is syntactic sugar for v.name(v,args), except that v is evaluated only once.

Arguments have the following syntax:

    args ::= `(´ [explist] `)´
    args ::= tableconstructor
    args ::= String

All argument expressions are evaluated before the call. A call of the form f{fields} is syntactic sugar for f({fields}); that is, the argument list is a single new table. A call of the form f'string' (or f"string" or f[[string]]) is syntactic sugar for f('string'); that is, the argument list is a single literal string.

As an exception to the free-format syntax of Lua, you cannot put a line break before the '(' in a function call. This restriction avoids some ambiguities in the language. If you write

     a = f
     (g).x(a)

Lua would see that as a single statement, a = f(g).x(a). So, if you want two statements, you must add a semi-colon between them. If you actually want to call f, you must remove the line break before (g).

A call of the form return functioncall is called a tail call. Lua implements proper tail calls (or proper tail recursion): in a tail call, the called function reuses the stack entry of the calling function. Therefore, there is no limit on the number of nested tail calls that a program can execute. However, a tail call erases any debug information about the calling function. Note that a tail call only happens with a particular syntax, where the return has one single function call as argument; this syntax makes the calling function return exactly the returns of the called function. So, none of the following examples are tail calls:

     return (f(x))        -- results adjusted to 1
     return 2 * f(x)
     return x, f(x)       -- additional results
     f(x); return         -- results discarded
     return x or f(x)     -- results adjusted to 1

2.5.9 - Function Definitions

The syntax for function definition is

    function ::= function funcbody
    funcbody ::= `(´ [parlist] `)´ block end

The following syntactic sugar simplifies function definitions:

    stat ::= function funcname funcbody
    stat ::= local function Name funcbody
    funcname ::= Name {`.´ Name} [`:´ Name]

The statement

     function f () body end

translates to

     f = function () body end

The statement

     function t.a.b.c.f () body end

translates to

     t.a.b.c.f = function () body end

The statement

     local function f () body end

translates to

     local f; f = function () body end

not to

     local f = function () body end

(This only makes a difference when the body of the function contains references to f.)

A function definition is an executable expression, whose value has type function. When Lua pre-compiles a chunk, all its function bodies are pre-compiled too. Then, whenever Lua executes the function definition, the function is instantiated (or closed). This function instance (or closure) is the final value of the expression. Different instances of the same function can refer to different external local variables and can have different environment tables.

Parameters act as local variables that are initialized with the argument values:

    parlist ::= namelist [`,´ `...´] | `...´

When a function is called, the list of arguments is adjusted to the length of the list of parameters, unless the function is a variadic or vararg function, which is indicated by three dots ('...') at the end of its parameter list. A vararg function does not adjust its argument list; instead, it collects all extra arguments and supplies them to the function through a vararg expression, which is also written as three dots. The value of this expression is a list of all actual extra arguments, similar to a function with multiple results. If a vararg expression is used inside another expression or in the middle of a list of expressions, then its return list is adjusted to one element. If the expression is used as the last element of a list of expressions, then no adjustment is made (unless that last expression is enclosed in parentheses).

As an example, consider the following definitions:

     function f(a, b) end
     function g(a, b, ...) end
     function r() return 1,2,3 end

Then, we have the following mapping from arguments to parameters and to the vararg expression:

     CALL            PARAMETERS

     f(3)             a=3, b=nil
     f(3, 4)          a=3, b=4
     f(3, 4, 5)       a=3, b=4
     f(r(), 10)       a=1, b=10
     f(r())           a=1, b=2

     g(3)             a=3, b=nil, ... -->  (nothing)
     g(3, 4)          a=3, b=4,   ... -->  (nothing)
     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
     g(5, r())        a=5, b=1,   ... -->  2  3

Results are returned using the return statement (see §2.4.4). If control reaches the end of a function without encountering a return statement, then the function returns with no results.

The colon syntax is used for defining methods, that is, functions that have an implicit extra parameter self. Thus, the statement

     function t.a.b.c:f (params) body end

is syntactic sugar for

     t.a.b.c.f = function (self, params) body end

2.6 - Visibility Rules

Lua is a lexically scoped language. The scope of variables begins at the first statement after their declaration and lasts until the end of the innermost block that includes the declaration. Consider the following example:

     x = 10                -- global variable
     do                    -- new block
       local x = x         -- new 'x', with value 10
       print(x)            --> 10
       x = x+1
       do                  -- another block
         local x = x+1     -- another 'x'
         print(x)          --> 12
       end
       print(x)            --> 11
     end
     print(x)              --> 10  (the global one)

Notice that, in a declaration like local x = x, the new x being declared is not in scope yet, and so the second x refers to the outside variable.

Because of the lexical scoping rules, local variables can be freely accessed by functions defined inside their scope. A local variable used by an inner function is called an upvalue, or external local variable, inside the inner function.

Notice that each execution of a local statement defines new local variables. Consider the following example:

     a = {}
     local x = 20
     for i=1,10 do
       local y = 0
       a[i] = function () y=y+1; return x+y end
     end

The loop creates ten closures (that is, ten instances of the anonymous function). Each of these closures uses a different y variable, while all of them share the same x.

2.7 - Error Handling

Because Lua is an embedded extension language, all Lua actions start from C code in the host program calling a function from the Lua library (see lua_pcall). Whenever an error occurs during Lua compilation or execution, control returns to C, which can take appropriate measures (such as printing an error message).

Lua code can explicitly generate an error by calling the error function. If you need to catch errors in Lua, you can use the pcall function.

2.8 - Metatables

Every value in Lua can have a metatable. This metatable is an ordinary Lua table that defines the behavior of the original value under certain special operations. You can change several aspects of the behavior of operations over a value by setting specific fields in its metatable. For instance, when a non-numeric value is the operand of an addition, Lua checks for a function in the field "__add" in its metatable. If it finds one, Lua calls this function to perform the addition.

We call the keys in a metatable events and the values metamethods. In the previous example, the event is "add" and the metamethod is the function that performs the addition.

You can query the metatable of any value through the getmetatable function.

You can replace the metatable of tables through the setmetatable function. You cannot change the metatable of other types from Lua (except by using the debug library); you must use the C API for that.

Tables and full userdata have individual metatables (although multiple tables and userdata can share their metatables). Values of all other types share one single metatable per type; that is, there is one single metatable for all numbers, one for all strings, etc.

A metatable controls how an object behaves in arithmetic operations, order comparisons, concatenation, length operation, and indexing. A metatable also can define a function to be called when a userdata is garbage collected. For each of these operations Lua associates a specific key called an event. When Lua performs one of these operations over a value, it checks whether this value has a metatable with the corresponding event. If so, the value associated with that key (the metamethod) controls how Lua will perform the operation.

Metatables control the operations listed next. Each operation is identified by its corresponding name. The key for each operation is a string with its name prefixed by two underscores, '__'; for instance, the key for operation "add" is the string "__add". The semantics of these operations is better explained by a Lua function describing how the interpreter executes the operation.

The code shown here in Lua is only illustrative; the real behavior is hard coded in the interpreter and it is much more efficient than this simulation. All functions used in these descriptions (rawget, tonumber, etc.) are described in §5.1. In particular, to retrieve the metamethod of a given object, we use the expression

     metatable(obj)[event]

This should be read as

     rawget(getmetatable(obj) or {}, event)

That is, the access to a metamethod does not invoke other metamethods, and the access to objects with no metatables does not fail (it simply results in nil).

  • "add": the + operation.

    The function getbinhandler below defines how Lua chooses a handler for a binary operation. First, Lua tries the first operand. If its type does not define a handler for the operation, then Lua tries the second operand.

         function getbinhandler (op1, op2, event)
       return metatable(op1)[event] or metatable(op2)[event]
     end

    By using this function, the behavior of the op1 + op2 is

         function add_event (op1, op2)
       local o1, o2 = tonumber(op1), tonumber(op2)
       if o1 and o2 then  -- both operands are numeric?
         return o1 + o2   -- '+' here is the primitive 'add'
       else  -- at least one of the operands is not numeric
         local h = getbinhandler(op1, op2, "__add")
         if h then
           -- call the handler with both operands
           return (h(op1, op2))
         else  -- no handler available: default behavior
           error(···)
         end
       end
     end

  • "sub": the - operation. Behavior similar to the "add" operation.
  • "mul": the * operation. Behavior similar to the "add" operation.
  • "div": the / operation. Behavior similar to the "add" operation.
  • "mod": the % operation. Behavior similar to the "add" operation, with the operation o1 - floor(o1/o2)*o2 as the primitive operation.
  • "pow": the ^ (exponentiation) operation. Behavior similar to the "add" operation, with the function pow (from the C math library) as the primitive operation.
  • "unm": the unary - operation.
         function unm_event (op)
       local o = tonumber(op)
       if o then  -- operand is numeric?
         return -o  -- '-' here is the primitive 'unm'
       else  -- the operand is not numeric.
         -- Try to get a handler from the operand
         local h = metatable(op).__unm
         if h then
           -- call the handler with the operand
           return (h(op))
         else  -- no handler available: default behavior
           error(···)
         end
       end
     end

  • "concat": the .. (concatenation) operation.
         function concat_event (op1, op2)
       if (type(op1) == "string" or type(op1) == "number") and
          (type(op2) == "string" or type(op2) == "number") then
         return op1 .. op2  -- primitive string concatenation
       else
         local h = getbinhandler(op1, op2, "__concat")
         if h then
           return (h(op1, op2))
         else
           error(···)
         end
       end
     end

  • "len": the # operation.
         function len_event (op)
       if type(op) == "string" then
         return strlen(op)         -- primitive string length
       elseif type(op) == "table" then
         return #op                -- primitive table length
       else
         local h = metatable(op).__len
         if h then
           -- call the handler with the operand
           return (h(op))
         else  -- no handler available: default behavior
           error(···)
         end
       end
     end

    See §2.5.5 for a description of the length of a table.

  • "eq": the == operation. The function getcomphandler defines how Lua chooses a metamethod for comparison operators. A metamethod only is selected when both objects being compared have the same type and the same metamethod for the selected operation.
         function getcomphandler (op1, op2, event)
       if type(op1) ~= type(op2) then return nil end
       local mm1 = metatable(op1)[event]
       local mm2 = metatable(op2)[event]
       if mm1 == mm2 then return mm1 else return nil end
     end

    The "eq" event is defined as follows:

         function eq_event (op1, op2)
       if type(op1) ~= type(op2) then  -- different types?
         return false   -- different objects
       end
       if op1 == op2 then   -- primitive equal?
         return true   -- objects are equal
       end
       -- try metamethod
       local h = getcomphandler(op1, op2, "__eq")
       if h then
         return (h(op1, op2))
       else
         return false
       end
     end

    a ~= b is equivalent to not (a == b).

  • "lt": the < operation.
         function lt_event (op1, op2)
       if type(op1) == "number" and type(op2) == "number" then
         return op1 < op2   -- numeric comparison
       elseif type(op1) == "string" and type(op2) == "string" then
         return op1 < op2   -- lexicographic comparison
       else
         local h = getcomphandler(op1, op2, "__lt")
         if h then
           return (h(op1, op2))
         else
           error(···)
         end
       end
     end

    a > b is equivalent to b < a.

  • "le": the <= operation.
         function le_event (op1, op2)
       if type(op1) == "number" and type(op2) == "number" then
         return op1 <= op2   -- numeric comparison
       elseif type(op1) == "string" and type(op2) == "string" then
         return op1 <= op2   -- lexicographic comparison
       else
         local h = getcomphandler(op1, op2, "__le")
         if h then
           return (h(op1, op2))
         else
           h = getcomphandler(op1, op2, "__lt")
           if h then
             return not h(op2, op1)
           else
             error(···)
           end
         end
       end
     end

    a >= b is equivalent to b <= a. Note that, in the absence of a "le" metamethod, Lua tries the "lt", assuming that a <= b is equivalent to not (b < a).

  • "index": The indexing access table[key].
         function gettable_event (table, key)
       local h
       if type(table) == "table" then
         local v = rawget(table, key)
         if v ~= nil then return v end
         h = metatable(table).__index
         if h == nil then return nil end
       else
         h = metatable(table).__index
         if h == nil then
           error(···)
         end
       end
       if type(h) == "function" then
         return (h(table, key))     -- call the handler
       else return h[key]           -- or repeat operation on it
       end
     end

  • "newindex": The indexing assignment table[key] = value.
         function settable_event (table, key, value)
       local h
       if type(table) == "table" then
         local v = rawget(table, key)
         if v ~= nil then rawset(table, key, value); return end
         h = metatable(table).__newindex
         if h == nil then rawset(table, key, value); return end
       else
         h = metatable(table).__newindex
         if h == nil then
           error(···)
         end
       end
       if type(h) == "function" then
         h(table, key,value)           -- call the handler
       else h[key] = value             -- or repeat operation on it
       end
     end

  • "call": called when Lua calls a value.
         function function_event (func, ...)
       if type(func) == "function" then
         return func(...)   -- primitive call
       else
         local h = metatable(func).__call
         if h then
           return h(func, ...)
         else
           error(···)
         end
       end
     end

2.9 - Environments

Besides metatables, objects of types thread, function, and userdata have another table associated with them, called their environment. Like metatables, environments are regular tables and multiple objects can share the same environment.

Threads are created sharing the environment of the creating thread. Userdata and C functions are created sharing the environment of the creating C function. Non-nested Lua functions (created by loadfile, loadstring or load) are created sharing the environment of the creating thread. Nested Lua functions are created sharing the environment of the creating Lua function.

Environments associated with userdata have no meaning for Lua. It is only a convenience feature for programmers to associate a table to a userdata.

Environments associated with threads are called global environments. They are used as the default environment for threads and non-nested Lua functions created by the thread and can be directly accessed by C code (see §3.3).

The environment associated with a C function can be directly accessed by C code (see §3.3). It is used as the default environment for other C functions and userdata created by the function.

Environments associated with Lua functions are used to resolve all accesses to global variables within the function (see §2.3). They are used as the default environment for nested Lua functions created by the function.

You can change the environment of a Lua function or the running thread by calling setfenv. You can get the environment of a Lua function or the running thread by calling getfenv. To manipulate the environment of other objects (userdata, C functions, other threads) you must use the C API.

2.10 - Garbage Collection

Lua performs automatic memory management. This means that you have to worry neither about allocating memory for new objects nor about freeing it when the objects are no longer needed. Lua manages memory automatically by running a garbage collector from time to time to collect all dead objects (that is, objects that are no longer accessible from Lua). All memory used by Lua is subject to automatic management: tables, userdata, functions, threads, strings, etc.

Lua implements an incremental mark-and-sweep collector. It uses two numbers to control its garbage-collection cycles: the garbage-collector pause and the garbage-collector step multiplier. Both use percentage points as units (so that a value of 100 means an internal value of 1).

The garbage-collector pause controls how long the collector waits before starting a new cycle. Larger values make the collector less aggressive. Values smaller than 100 mean the collector will not wait to start a new cycle. A value of 200 means that the collector waits for the total memory in use to double before starting a new cycle.

The step multiplier controls the relative speed of the collector relative to memory allocation. Larger values make the collector more aggressive but also increase the size of each incremental step. Values smaller than 100 make the collector too slow and can result in the collector never finishing a cycle. The default, 200, means that the collector runs at "twice" the speed of memory allocation.

You can change these numbers by calling lua_gc in C or collectgarbage in Lua. With these functions you can also control the collector directly (e.g., stop and restart it).

2.10.1 - Garbage-Collection Metamethods

Using the C API, you can set garbage-collector metamethods for userdata (see §2.8). These metamethods are also called finalizers. Finalizers allow you to coordinate Lua's garbage collection with external resource management (such as closing files, network or database connections, or freeing your own memory).

Garbage userdata with a field __gc in their metatables are not collected immediately by the garbage collector. Instead, Lua puts them in a list. After the collection, Lua does the equivalent of the following function for each userdata in that list:

     function gc_event (udata)
       local h = metatable(udata).__gc
       if h then
         h(udata)
       end
     end

At the end of each garbage-collection cycle, the finalizers for userdata are called in reverse order of their creation, among those collected in that cycle. That is, the first finalizer to be called is the one associated with the userdata created last in the program. The userdata itself is freed only in the next garbage-collection cycle.

2.10.2 - Weak Tables

A weak table is a table whose elements are weak references. A weak reference is ignored by the garbage collector. In other words, if the only references to an object are weak references, then the garbage collector will collect this object.

A weak table can have weak keys, weak values, or both. A table with weak keys allows the collection of its keys, but prevents the collection of its values. A table with both weak keys and weak values allows the collection of both keys and values. In any case, if either the key or the value is collected, the whole pair is removed from the table. The weakness of a table is controlled by the __mode field of its metatable. If the __mode field is a string containing the character 'k', the keys in the table are weak. If __mode contains 'v', the values in the table are weak.

After you use a table as a metatable, you should not change the value of its __mode field. Otherwise, the weak behavior of the tables controlled by this metatable is undefined.

2.11 - Coroutines

Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends its execution by explicitly calling a yield function.

You create a coroutine with a call to coroutine.create. Its sole argument is a function that is the main function of the coroutine. The create function only creates a new coroutine and returns a handle to it (an object of type thread); it does not start the coroutine execution.

When you first call coroutine.resume, passing as its first argument a thread returned by coroutine.create, the coroutine starts its execution, at the first line of its main function. Extra arguments passed to coroutine.resume are passed on to the coroutine main function. After the coroutine starts running, it runs until it terminates or yields.

A coroutine can terminate its execution in two ways: normally, when its main function returns (explicitly or implicitly, after the last instruction); and abnormally, if there is an unprotected error. In the first case, coroutine.resume returns true, plus any values returned by the coroutine main function. In case of errors, coroutine.resume returns false plus an error message.

A coroutine yields by calling coroutine.yield. When a coroutine yields, the corresponding coroutine.resume returns immediately, even if the yield happens inside nested function calls (that is, not in the main function, but in a function directly or indirectly called by the main function). In the case of a yield, coroutine.resume also returns true, plus any values passed to coroutine.yield. The next time you resume the same coroutine, it continues its execution from the point where it yielded, with the call to coroutine.yield returning any extra arguments passed to coroutine.resume.

Like coroutine.create, the coroutine.wrap function also creates a coroutine, but instead of returning the coroutine itself, it returns a function that, when called, resumes the coroutine. Any arguments passed to this function go as extra arguments to coroutine.resume. coroutine.wrap returns all the values returned by coroutine.resume, except the first one (the boolean error code). Unlike coroutine.resume, coroutine.wrap does not catch errors; any error is propagated to the caller.

As an example, consider the following code:

     function foo (a)
       print("foo", a)
       return coroutine.yield(2*a)
     end

     co = coroutine.create(function (a,b)
           print("co-body", a, b)
           local r = foo(a+1)
           print("co-body", r)
           local r, s = coroutine.yield(a+b, a-b)
           print("co-body", r, s)
           return b, "end"
     end)

     print("main", coroutine.resume(co, 1, 10))
     print("main", coroutine.resume(co, "r"))
     print("main", coroutine.resume(co, "x", "y"))
     print("main", coroutine.resume(co, "x", "y"))

When you run it, it produces the following output:

     co-body 1       10
     foo     2

     main    true    4
     co-body r
     main    true    11      -9
     co-body x       y
     main    true    10      end
     main    false   cannot resume dead coroutine

3 - The Application Program Interface

This section describes the C API for Lua, that is, the set of C functions available to the host program to communicate with Lua. All API functions and related types and constants are declared in the header file lua.h.

Even when we use the term "function", any facility in the API may be provided as a macro instead. All such macros use each of their arguments exactly once (except for the first argument, which is always a Lua state), and so do not generate any hidden side-effects.

As in most C libraries, the Lua API functions do not check their arguments for validity or consistency. However, you can change this behavior by compiling Lua with a proper definition for the macro luai_apicheck, in file luaconf.h.

3.1 - The Stack

Lua uses a virtual stack to pass values to and from C. Each element in this stack represents a Lua value (nil, number, string, etc.).

Whenever Lua calls C, the called function gets a new stack, which is independent of previous stacks and of stacks of C functions that are still active. This stack initially contains any arguments to the C function and it is where the C function pushes its results to be returned to the caller (see lua_CFunction).

For convenience, most query operations in the API do not follow a strict stack discipline. Instead, they can refer to any element in the stack by using an index: A positive index represents an absolute stack position (starting at 1); a negative index represents an offset relative to the top of the stack. More specifically, if the stack has n elements, then index 1 represents the first element (that is, the element that was pushed onto the stack first) and index n represents the last element; index -1 also represents the last element (that is, the element at the top) and index -n represents the first element. We say that an index is valid if it lies between 1 and the stack top (that is, if 1 ‰¤ abs(index) ‰¤ top).

3.2 - Stack Size

When you interact with Lua API, you are responsible for ensuring consistency. In particular, you are responsible for controlling stack overflow. You can use the function lua_checkstack to grow the stack size.

Whenever Lua calls C, it ensures that at least LUA_MINSTACK stack positions are available. LUA_MINSTACK is defined as 20, so that usually you do not have to worry about stack space unless your code has loops pushing elements onto the stack.

Most query functions accept as indices any value inside the available stack space, that is, indices up to the maximum stack size you have set through lua_checkstack. Such indices are called acceptable indices. More formally, we define an acceptable index as follows:

     (index < 0 && abs(index) <= top) ||
     (index > 0 && index <= stackspace)

Note that 0 is never an acceptable index.

3.3 - Pseudo-Indices

Unless otherwise noted, any function that accepts valid indices can also be called with pseudo-indices, which represent some Lua values that are accessible to C code but which are not in the stack. Pseudo-indices are used to access the thread environment, the function environment, the registry, and the upvalues of a C function (see §3.4).

The thread environment (where global variables live) is always at pseudo-index LUA_GLOBALSINDEX. The environment of the running C function is always at pseudo-index LUA_ENVIRONINDEX.

To access and change the value of global variables, you can use regular table operations over an environment table. For instance, to access the value of a global variable, do

     lua_getfield(L, LUA_GLOBALSINDEX, varname);

3.4 - C Closures

When a C function is created, it is possible to associate some values with it, thus creating a C closure; these values are called upvalues and are accessible to the function whenever it is called (see lua_pushcclosure).

Whenever a C function is called, its upvalues are located at specific pseudo-indices. These pseudo-indices are produced by the macro lua_upvalueindex. The first value associated with a function is at position lua_upvalueindex(1), and so on. Any access to lua_upvalueindex(n), where n is greater than the number of upvalues of the current function (but not greater than 256), produces an acceptable (but invalid) index.

3.5 - Registry

Lua provides a registry, a pre-defined table that can be used by any C code to store whatever Lua value it needs to store. This table is always located at pseudo-index LUA_REGISTRYINDEX. Any C library can store data into this table, but it should take care to choose keys different from those used by other libraries, to avoid collisions. Typically, you should use as key a string containing your library name or a light userdata with the address of a C object in your code.

The integer keys in the registry are used by the reference mechanism, implemented by the auxiliary library, and therefore should not be used for other purposes.

3.6 - Error Handling in C

Internally, Lua uses the C longjmp facility to handle errors. (You can also choose to use exceptions if you use C++; see file luaconf.h.) When Lua faces any error (such as memory allocation errors, type errors, syntax errors, and runtime errors) it raises an error; that is, it does a long jump. A protected environment uses setjmp to set a recover point; any error jumps to the most recent active recover point.

Most functions in the API can throw an error, for instance due to a memory allocation error. The documentation for each function indicates whether it can throw errors.

Inside a C function you can throw an error by calling lua_error.

3.7 - Functions and Types

Here we list all functions and types from the C API in alphabetical order. Each function has an indicator like this: [-o, +p, x]

The first field, o, is how many elements the function pops from the stack. The second field, p, is how many elements the function pushes onto the stack. (Any function always pushes its results after popping its arguments.) A field in the form x|y means the function can push (or pop) x or y elements, depending on the situation; an interrogation mark '?' means that we cannot know how many elements the function pops/pushes by looking only at its arguments (e.g., they may depend on what is on the stack). The third field, x, tells whether the function may throw errors: '-' means the function never throws any error; 'm' means the function may throw an error only due to not enough memory; 'e' means the function may throw other kinds of errors; 'v' means the function may throw an error on purpose.

lua_Alloc

typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);

The type of the memory-allocation function used by Lua states. The allocator function must provide a functionality similar to realloc, but not exactly the same. Its arguments are ud, an opaque pointer passed to lua_newstate; ptr, a pointer to the block being allocated/reallocated/freed; osize, the original size of the block; nsize, the new size of the block. ptr is NULL if and only if osize is zero. When nsize is zero, the allocator must return NULL; if osize is not zero, it should free the block pointed to by ptr. When nsize is not zero, the allocator returns NULL if and only if it cannot fill the request. When nsize is not zero and osize is zero, the allocator should behave like malloc. When nsize and osize are not zero, the allocator behaves like realloc. Lua assumes that the allocator never fails when osize >= nsize.

Here is a simple implementation for the allocator function. It is used in the auxiliary library by luaL_newstate.

     static void *l_alloc (void *ud, void *ptr, size_t osize,
                                                size_t nsize) {
       (void)ud;  (void)osize;  /* not used */
       if (nsize == 0) {
         free(ptr);
         return NULL;
       }
       else
         return realloc(ptr, nsize);
     }

This code assumes that free(NULL) has no effect and that realloc(NULL, size) is equivalent to malloc(size). ANSI C ensures both behaviors.

lua_atpanic

[-0, +0, -]

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);

Sets a new panic function and returns the old one.

If an error happens outside any protected environment, Lua calls a panic function and then calls exit(EXIT_FAILURE), thus exiting the host application. Your panic function can avoid this exit by never returning (e.g., doing a long jump).

The panic function can access the error message at the top of the stack.

lua_call

[-(nargs + 1), +nresults, e]

void lua_call (lua_State *L, int nargs, int nresults);

Calls a function.

To call a function you must use the following protocol: first, the function to be called is pushed onto the stack; then, the arguments to the function are pushed in direct order; that is, the first argument is pushed first. Finally you call lua_call; nargs is the number of arguments that you pushed onto the stack. All arguments and the function value are popped from the stack when the function is called. The function results are pushed onto the stack when the function returns. The number of results is adjusted to nresults, unless nresults is LUA_MULTRET. In this case, all results from the function are pushed. Lua takes care that the returned values fit into the stack space. The function results are pushed onto the stack in direct order (the first result is pushed first), so that after the call the last result is on the top of the stack.

Any error inside the called function is propagated upwards (with a longjmp).

The following example shows how the host program can do the equivalent to this Lua code:

     a = f("how", t.x, 14)

Here it is in C:

     lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */
     lua_pushstring(L, "how");                        /* 1st argument */
     lua_getfield(L, LUA_GLOBALSINDEX, "t");   /* table to be indexed */
     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
     lua_remove(L, -2);                  /* remove 't' from the stack */
     lua_pushinteger(L, 14);                          /* 3rd argument */
     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
     lua_setfield(L, LUA_GLOBALSINDEX, "a");        /* set global 'a' */

Note that the code above is "balanced": at its end, the stack is back to its original configuration. This is considered good programming practice.

lua_CFunction

typedef int (*lua_CFunction) (lua_State *L);

Type for C functions.

In order to communicate properly with Lua, a C function must use the following protocol, which defines the way parameters and results are passed: a C function receives its arguments from Lua in its stack in direct order (the first argument is pushed first). So, when the function starts, lua_gettop(L) returns the number of arguments received by the function. The first argument (if any) is at index 1 and its last argument is at index lua_gettop(L). To return values to Lua, a C function just pushes them onto the stack, in direct order (the first result is pushed first), and returns the number of results. Any other value in the stack below the results will be properly discarded by Lua. Like a Lua function, a C function called by Lua can also return many results.

As an example, the following function receives a variable number of numerical arguments and returns their average and sum:

     static int foo (lua_State *L) {
       int n = lua_gettop(L);    /* number of arguments */
       lua_Number sum = 0;
       int i;
       for (i = 1; i <= n; i++) {
         if (!lua_isnumber(L, i)) {
           lua_pushstring(L, "incorrect argument");
           lua_error(L);
         }
         sum += lua_tonumber(L, i);
       }
       lua_pushnumber(L, sum/n);        /* first result */
       lua_pushnumber(L, sum);         /* second result */
       return 2;                   /* number of results */
     }

lua_checkstack

[-0, +0, m]

int lua_checkstack (lua_State *L, int extra);

Ensures that there are at least extra free stack slots in the stack. It returns false if it cannot grow the stack to that size. This function never shrinks the stack; if the stack is already larger than the new size, it is left unchanged.

lua_close

[-0, +0, -]

void lua_close (lua_State *L);

Destroys all objects in the given Lua state (calling the corresponding garbage-collection metamethods, if any) and frees all dynamic memory used by this state. On several platforms, you may not need to call this function, because all resources are naturally released when the host program ends. On the other hand, long-running programs, such as a daemon or a web server, might need to release states as soon as they are not needed, to avoid growing too large.

lua_concat

[-n, +1, e]

void lua_concat (lua_State *L, int n);

Concatenates the n values at the top of the stack, pops them, and leaves the result at the top. If n is 1, the result is the single value on the stack (that is, the function does nothing); if n is 0, the result is the empty string. Concatenation is performed following the usual semantics of Lua (see §2.5.4).

lua_cpcall

[-0, +(0|1), -]

int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);

Calls the C function func in protected mode. func starts with only one element in its stack, a light userdata containing ud. In case of errors, lua_cpcall returns the same error codes as lua_pcall, plus the error object on the top of the stack; otherwise, it returns zero, and does not change the stack. All values returned by func are discarded.

lua_createtable

[-0, +1, m]

void lua_createtable (lua_State *L, int narr, int nrec);

Creates a new empty table and pushes it onto the stack. The new table has space pre-allocated for narr array elements and nrec non-array elements. This pre-allocation is useful when you know exactly how many elements the table will have. Otherwise you can use the function lua_newtable.

lua_dump

[-0, +0, m]

int lua_dump (lua_State *L, lua_Writer writer, void *data);

Dumps a function as a binary chunk. Receives a Lua function on the top of the stack and produces a binary chunk that, if loaded again, results in a function equivalent to the one dumped. As it produces parts of the chunk, lua_dump calls function writer (see lua_Writer) with the given data to write them.

The value returned is the error code returned by the last call to the writer; 0 means no errors.

This function does not pop the Lua function from the stack.

lua_equal

[-0, +0, e]

int lua_equal (lua_State *L, int index1, int index2);

Returns 1 if the two values in acceptable indices index1 and index2 are equal, following the semantics of the Lua == operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid.

lua_error

[-1, +0, v]

int lua_error (lua_State *L);

Generates a Lua error. The error message (which can actually be a Lua value of any type) must be on the stack top. This function does a long jump, and therefore never returns. (see luaL_error).

lua_gc

[-0, +0, e]

int lua_gc (lua_State *L, int what, int data);

Controls the garbage collector.

This function performs several tasks, according to the value of the parameter what:

  • LUA_GCSTOP: stops the garbage collector.
  • LUA_GCRESTART: restarts the garbage collector.
  • LUA_GCCOLLECT: performs a full garbage-collection cycle.
  • LUA_GCCOUNT: returns the current amount of memory (in Kbytes) in use by Lua.
  • LUA_GCCOUNTB: returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024.
  • LUA_GCSTEP: performs an incremental step of garbage collection. The step "size" is controlled by data (larger values mean more steps) in a non-specified way. If you want to control the step size you must experimentally tune the value of data. The function returns 1 if the step finished a garbage-collection cycle.
  • LUA_GCSETPAUSE: sets data as the new value for the pause of the collector (see §2.10). The function returns the previous value of the pause.
  • LUA_GCSETSTEPMUL: sets data as the new value for the step multiplier of the collector (see §2.10). The function returns the previous value of the step multiplier.

lua_getallocf

[-0, +0, -]

lua_Alloc lua_getallocf (lua_State *L, void **ud);

Returns the memory-allocation function of a given state. If ud is not NULL, Lua stores in *ud the opaque pointer passed to lua_newstate.

lua_getfenv

[-0, +1, -]

void lua_getfenv (lua_State *L, int index);

Pushes onto the stack the environment table of the value at the given index.

lua_getfield

[-0, +1, e]

void lua_getfield (lua_State *L, int index, const char *k);

Pushes onto the stack the value t[k], where t is the value at the given valid index. As in Lua, this function may trigger a metamethod for the "index" event (see §2.8).

lua_getglobal

[-0, +1, e]

void lua_getglobal (lua_State *L, const char *name);

Pushes onto the stack the value of the global name. It is defined as a macro:

     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)

lua_getmetatable

[-0, +(0|1), -]

int lua_getmetatable (lua_State *L, int index);

Pushes onto the stack the metatable of the value at the given acceptable index. If the index is not valid, or if the value does not have a metatable, the function returns 0 and pushes nothing on the stack.

lua_gettable

[-1, +1, e]

void lua_gettable (lua_State *L, int index);

Pushes onto the stack the value t[k], where t is the value at the given valid index and k is the value at the top of the stack.

This function pops the key from the stack (putting the resulting value in its place). As in Lua, this function may trigger a metamethod for the "index" event (see §2.8).

lua_gettop

[-0, +0, -]

int lua_gettop (lua_State *L);

Returns the index of the top element in the stack. Because indices start at 1, this result is equal to the number of elements in the stack (and so 0 means an empty stack).

lua_insert

[-1, +1, -]

void lua_insert (lua_State *L, int index);

Moves the top element into the given valid index, shifting up the elements above this index to open space. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.

lua_Integer

typedef ptrdiff_t lua_Integer;

The type used by the Lua API to represent integral values.

By default it is a ptrdiff_t, which is usually the largest signed integral type the machine handles "comfortably".

lua_isboolean

[-0, +0, -]

int lua_isboolean (lua_State *L, int index);

Returns 1 if the value at the given acceptable index has type boolean, and 0 otherwise.

lua_iscfunction

[-0, +0, -]

int lua_iscfunction (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a C function, and 0 otherwise.

lua_isfunction

[-0, +0, -]

int lua_isfunction (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a function (either C or Lua), and 0 otherwise.

lua_islightuserdata

[-0, +0, -]

int lua_islightuserdata (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a light userdata, and 0 otherwise.

lua_isnil

[-0, +0, -]

int lua_isnil (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is nil, and 0 otherwise.

lua_isnone

[-0, +0, -]

int lua_isnone (lua_State *L, int index);

Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack), and 0 otherwise.

lua_isnoneornil

[-0, +0, -]

int lua_isnoneornil (lua_State *L, int index);

Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack) or if the value at this index is nil, and 0 otherwise.

lua_isnumber

[-0, +0, -]

int lua_isnumber (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a number or a string convertible to a number, and 0 otherwise.

lua_isstring

[-0, +0, -]

int lua_isstring (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a string or a number (which is always convertible to a string), and 0 otherwise.

lua_istable

[-0, +0, -]

int lua_istable (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a table, and 0 otherwise.

lua_isthread

[-0, +0, -]

int lua_isthread (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a thread, and 0 otherwise.

lua_isuserdata

[-0, +0, -]

int lua_isuserdata (lua_State *L, int index);

Returns 1 if the value at the given acceptable index is a userdata (either full or light), and 0 otherwise.

lua_lessthan

[-0, +0, e]

int lua_lessthan (lua_State *L, int index1, int index2);

Returns 1 if the value at acceptable index index1 is smaller than the value at acceptable index index2, following the semantics of the Lua < operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid.

lua_load

[-0, +1, -]

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname);

Loads a Lua chunk. If there are no errors, lua_load pushes the compiled chunk as a Lua function on top of the stack. Otherwise, it pushes an error message. The return values of lua_load are:

  • 0: no errors;
  • LUA_ERRSYNTAX: syntax error during pre-compilation;
  • LUA_ERRMEM: memory allocation error.

This function only loads a chunk; it does not run it.

lua_load automatically detects whether the chunk is text or binary, and loads it accordingly (see program luac).

The lua_load function uses a user-supplied reader function to read the chunk (see lua_Reader). The data argument is an opaque value passed to the reader function.

The chunkname argument gives a name to the chunk, which is used for error messages and in debug information (see §3.8).

lua_newstate

[-0, +0, -]

lua_State *lua_newstate (lua_Alloc f, void *ud);

Creates a new, independent state. Returns NULL if cannot create the state (due to lack of memory). The argument f is the allocator function; Lua does all memory allocation for this state through this function. The second argument, ud, is an opaque pointer that Lua simply passes to the allocator in every call.

lua_newtable

[-0, +1, m]

void lua_newtable (lua_State *L);

Creates a new empty table and pushes it onto the stack. It is equivalent to lua_createtable(L, 0, 0).

lua_newthread

[-0, +1, m]

lua_State *lua_newthread (lua_State *L);

Creates a new thread, pushes it on the stack, and returns a pointer to a lua_State that represents this new thread. The new state returned by this function shares with the original state all global objects (such as tables), but has an independent execution stack.

There is no explicit function to close or to destroy a thread. Threads are subject to garbage collection, like any Lua object.

lua_newuserdata

[-0, +1, m]

void *lua_newuserdata (lua_State *L, size_t size);

This function allocates a new block of memory with the given size, pushes onto the stack a new full userdata with the block address, and returns this address.

Userdata represent C values in Lua. A full userdata represents a block of memory. It is an object (like a table): you must create it, it can have its own metatable, and you can detect when it is being collected. A full userdata is only equal to itself (under raw equality).

When Lua collects a full userdata with a gc metamethod, Lua calls the metamethod and marks the userdata as finalized. When this userdata is collected again then Lua frees its corresponding memory.

lua_next

[-1, +(2|0), e]

int lua_next (lua_State *L, int index);

Pops a key from the stack, and pushes a key-value pair from the table at the given index (the "next" pair after the given key). If there are no more elements in the table, then lua_next returns 0 (and pushes nothing).

A typical traversal looks like this:

     /* table is in the stack at index 't' */
     lua_pushnil(L);  /* first key */
     while (lua_next(L, t) != 0) {
       /* uses 'key' (at index -2) and 'value' (at index -1) */
       printf("%s - %s\n",
              lua_typename(L, lua_type(L, -2)),
              lua_typename(L, lua_type(L, -1)));
       /* removes 'value'; keeps 'key' for next iteration */
       lua_pop(L, 1);
     }

While traversing a table, do not call lua_tolstring directly on a key, unless you know that the key is actually a string. Recall that lua_tolstring changes the value at the given index; this confuses the next call to lua_next.

lua_Number

typedef double lua_Number;

The type of numbers in Lua. By default, it is double, but that can be changed in luaconf.h.

Through the configuration file you can change Lua to operate with another type for numbers (e.g., float or long).

lua_objlen

[-0, +0, -]

size_t lua_objlen (lua_State *L, int index);

Returns the "length" of the value at the given acceptable index: for strings, this is the string length; for tables, this is the result of the length operator ('#'); for userdata, this is the size of the block of memory allocated for the userdata; for other values, it is 0.

lua_pcall

[-(nargs + 1), +(nresults|1), -]

int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);

Calls a function in protected mode.

Both nargs and nresults have the same meaning as in lua_call. If there are no errors during the call, lua_pcall behaves exactly like lua_call. However, if there is any error, lua_pcall catches it, pushes a single value on the stack (the error message), and returns an error code. Like lua_call, lua_pcall always removes the function and its arguments from the stack.

If errfunc is 0, then the error message returned on the stack is exactly the original error message. Otherwise, errfunc is the stack index of an error handler function. (In the current implementation, this index cannot be a pseudo-index.) In case of runtime errors, this function will be called with the error message and its return value will be the message returned on the stack by lua_pcall.

Typically, the error handler function is used to add more debug information to the error message, such as a stack traceback. Such information cannot be gathered after the return of lua_pcall, since by then the stack has unwound.

The lua_pcall function returns 0 in case of success or one of the following error codes (defined in lua.h):

  • LUA_ERRRUN: a runtime error.
  • LUA_ERRMEM: memory allocation error. For such errors, Lua does not call the error handler function.
  • LUA_ERRERR: error while running the error handler function.

lua_pop

[-n, +0, -]

void lua_pop (lua_State *L, int n);

Pops n elements from the stack.

lua_pushboolean

[-0, +1, -]

void lua_pushboolean (lua_State *L, int b);

Pushes a boolean value with value b onto the stack.

lua_pushcclosure

[-n, +1, m]

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);

Pushes a new C closure onto the stack.

When a C function is created, it is possible to associate some values with it, thus creating a C closure (see §3.4); these values are then accessible to the function whenever it is called. To associate values with a C function, first these values should be pushed onto the stack (when there are multiple values, the first value is pushed first). Then lua_pushcclosure is called to create and push the C function onto the stack, with the argument n telling how many values should be associated with the function. lua_pushcclosure also pops these values from the stack.

The maximum value for n is 255.

lua_pushcfunction

[-0, +1, m]

void lua_pushcfunction (lua_State *L, lua_CFunction f);

Pushes a C function onto the stack. This function receives a pointer to a C function and pushes onto the stack a Lua value of type function that, when called, invokes the corresponding C function.

Any function to be registered in Lua must follow the correct protocol to receive its parameters and return its results (see lua_CFunction).

lua_pushcfunction is defined as a macro:

     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)

lua_pushfstring

[-0, +1, m]

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

Pushes onto the stack a formatted string and returns a pointer to this string. It is similar to the C function sprintf, but has some important differences:

  • You do not have to allocate space for the result: the result is a Lua string and Lua takes care of memory allocation (and deallocation, through garbage collection).
  • The conversion specifiers are quite restricted. There are no flags, widths, or precisions. The conversion specifiers can only be '%%' (inserts a '%' in the string), '%s' (inserts a zero-terminated string, with no size restrictions), '%f' (inserts a lua_Number), '%p' (inserts a pointer as a hexadecimal numeral), '%d' (inserts an int), and '%c' (inserts an int as a character).

lua_pushinteger

[-0, +1, -]

void lua_pushinteger (lua_State *L, lua_Integer n);

Pushes a number with value n onto the stack.

lua_pushlightuserdata

[-0, +1, -]

void lua_pushlightuserdata (lua_State *L, void *p);

Pushes a light userdata onto the stack.

Userdata represent C values in Lua. A light userdata represents a pointer. It is a value (like a number): you do not create it, it has no individual metatable, and it is not collected (as it was never created). A light userdata is equal to "any" light userdata with the same C address.

lua_pushliteral

[-0, +1, m]

void lua_pushliteral (lua_State *L, const char *s);

This macro is equivalent to lua_pushlstring, but can be used only when s is a literal string. In these cases, it automatically provides the string length.

lua_pushlstring

[-0, +1, m]

void lua_pushlstring (lua_State *L, const char *s, size_t len);

Pushes the string pointed to by s with size len onto the stack. Lua makes (or reuses) an internal copy of the given string, so the memory at s can be freed or reused immediately after the function returns. The string can contain embedded zeros.

lua_pushnil

[-0, +1, -]

void lua_pushnil (lua_State *L);

Pushes a nil value onto the stack.

lua_pushnumber

[-0, +1, -]

void lua_pushnumber (lua_State *L, lua_Number n);

Pushes a number with value n onto the stack.

lua_pushstring

[-0, +1, m]

void lua_pushstring (lua_State *L, const char *s);

Pushes the zero-terminated string pointed to by s onto the stack. Lua makes (or reuses) an internal copy of the given string, so the memory at s can be freed or reused immediately after the function returns. The string cannot contain embedded zeros; it is assumed to end at the first zero.

lua_pushthread

[-0, +1, -]

int lua_pushthread (lua_State *L);

Pushes the thread represented by L onto the stack. Returns 1 if this thread is the main thread of its state.

lua_pushvalue

[-0, +1, -]

void lua_pushvalue (lua_State *L, int index);

Pushes a copy of the element at the given valid index onto the stack.

lua_pushvfstring

[-0, +1, m]

const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);

Equivalent to lua_pushfstring, except that it receives a va_list instead of a variable number of arguments.

lua_rawequal

[-0, +0, -]

int lua_rawequal (lua_State *L, int index1, int index2);

Returns 1 if the two values in acceptable indices index1 and index2 are primitively equal (that is, without calling metamethods). Otherwise returns 0. Also returns 0 if any of the indices are non valid.

lua_rawget

[-1, +1, -]

void lua_rawget (lua_State *L, int index);

Similar to lua_gettable, but does a raw access (i.e., without metamethods).

lua_rawgeti

[-0, +1, -]

void lua_rawgeti (lua_State *L, int index, int n);

Pushes onto the stack the value t[n], where t is the value at the given valid index. The access is raw; that is, it does not invoke metamethods.

lua_rawset

[-2, +0, m]

void lua_rawset (lua_State *L, int index);

Similar to lua_settable, but does a raw assignment (i.e., without metamethods).

lua_rawseti

[-1, +0, m]

void lua_rawseti (lua_State *L, int index, int n);

Does the equivalent of t[n] = v, where t is the value at the given valid index and v is the value at the top of the stack.

This function pops the value from the stack. The assignment is raw; that is, it does not invoke metamethods.

lua_Reader

typedef const char * (*lua_Reader) (lua_State *L,
                                    void *data,
                                    size_t *size);

The reader function used by lua_load. Every time it needs another piece of the chunk, lua_load calls the reader, passing along its data parameter. The reader must return a pointer to a block of memory with a new piece of the chunk and set size to the block size. The block must exist until the reader function is called again. To signal the end of the chunk, the reader must return NULL or set size to zero. The reader function may return pieces of any size greater than zero.

lua_register

[-0, +0, e]

void lua_register (lua_State *L,
                   const char *name,
                   lua_CFunction f);

Sets the C function f as the new value of global name. It is defined as a macro:

     #define lua_register(L,n,f) \
            (lua_pushcfunction(L, f), lua_setglobal(L, n))

lua_remove

[-1, +0, -]

void lua_remove (lua_State *L, int index);

Removes the element at the given valid index, shifting down the elements above this index to fill the gap. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.

lua_replace

[-1, +0, -]

void lua_replace (lua_State *L, int index);

Moves the top element into the given position (and pops it), without shifting any element (therefore replacing the value at the given position).

lua_resume

[-?, +?, -]

int lua_resume (lua_State *L, int narg);

Starts and resumes a coroutine in a given thread.

To start a coroutine, you first create a new thread (see lua_newthread); then you push onto its stack the main function plus any arguments; then you call lua_resume, with narg being the number of arguments. This call returns when the coroutine suspends or finishes its execution. When it returns, the stack contains all values passed to lua_yield, or all values returned by the body function. lua_resume returns LUA_YIELD if the coroutine yields, 0 if the coroutine finishes its execution without errors, or an error code in case of errors (see lua_pcall). In case of errors, the stack is not unwound, so you can use the debug API over it. The error message is on the top of the stack. To restart a coroutine, you put on its stack only the values to be passed as results from yield, and then call lua_resume.

lua_setallocf

[-0, +0, -]

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);

Changes the allocator function of a given state to f with user data ud.

lua_setfenv

[-1, +0, -]

int lua_setfenv (lua_State *L, int index);

Pops a table from the stack and sets it as the new environment for the value at the given index. If the value at the given index is neither a function nor a thread nor a userdata, lua_setfenv returns 0. Otherwise it returns 1.

lua_setfield

[-1, +0, e]

void lua_setfield (lua_State *L, int index, const char *k);

Does the equivalent to t[k] = v, where t is the value at the given valid index and v is the value at the top of the stack.

This function pops the value from the stack. As in Lua, this function may trigger a metamethod for the "newindex" event (see §2.8).

lua_setglobal

[-1, +0, e]

void lua_setglobal (lua_State *L, const char *name);

Pops a value from the stack and sets it as the new value of global name. It is defined as a macro:

     #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)

lua_setmetatable

[-1, +0, -]

int lua_setmetatable (lua_State *L, int index);

Pops a table from the stack and sets it as the new metatable for the value at the given acceptable index.

lua_settable

[-2, +0, e]

void lua_settable (lua_State *L, int index);

Does the equivalent to t[k] = v, where t is the value at the given valid index, v is the value at the top of the stack, and k is the value just below the top.

This function pops both the key and the value from the stack. As in Lua, this function may trigger a metamethod for the "newindex" event (see §2.8).

lua_settop

[-?, +?, -]

void lua_settop (lua_State *L, int index);

Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed.

lua_State

typedef struct lua_State lua_State;

Opaque structure that keeps the whole state of a Lua interpreter. The Lua library is fully reentrant: it has no global variables. All information about a state is kept in this structure.

A pointer to this state must be passed as the first argument to every function in the library, except to lua_newstate, which creates a Lua state from scratch.

lua_status

[-0, +0, -]

int lua_status (lua_State *L);

Returns the status of the thread L.

The status can be 0 for a normal thread, an error code if the thread finished its execution with an error, or LUA_YIELD if the thread is suspended.

lua_toboolean

[-0, +0, -]

int lua_toboolean (lua_State *L, int index);

Converts the Lua value at the given acceptable index to a C boolean value (0 or 1). Like all tests in Lua, lua_toboolean returns 1 for any Lua value different from false and nil; otherwise it returns 0. It also returns 0 when called with a non-valid index. (If you want to accept only actual boolean values, use lua_isboolean to test the value's type.)

lua_tocfunction

[-0, +0, -]

lua_CFunction lua_tocfunction (lua_State *L, int index);

Converts a value at the given acceptable index to a C function. That value must be a C function; otherwise, returns NULL.

lua_tointeger

[-0, +0, -]

lua_Integer lua_tointeger (lua_State *L, int index);

Converts the Lua value at the given acceptable index to the signed integral type lua_Integer. The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tointeger returns 0.

If the number is not an integer, it is truncated in some non-specified way.

lua_tolstring

[-0, +0, m]

const char *lua_tolstring (lua_State *L, int index, size_t *len);

Converts the Lua value at the given acceptable index to a C string. If len is not NULL, it also sets *len with the string length. The Lua value must be a string or a number; otherwise, the function returns NULL. If the value is a number, then lua_tolstring also changes the actual value in the stack to a string. (This change confuses lua_next when lua_tolstring is applied to keys during a table traversal.)

lua_tolstring returns a fully aligned pointer to a string inside the Lua state. This string always has a zero ('\0') after its last character (as in C), but can contain other zeros in its body. Because Lua has garbage collection, there is no guarantee that the pointer returned by lua_tolstring will be valid after the corresponding value is removed from the stack.

lua_tonumber

[-0, +0, -]

lua_Number lua_tonumber (lua_State *L, int index);

Converts the Lua value at the given acceptable index to the C type lua_Number (see lua_Number). The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tonumber returns 0.

lua_topointer

[-0, +0, -]

const void *lua_topointer (lua_State *L, int index);

Converts the value at the given acceptable index to a generic C pointer (void*). The value can be a userdata, a table, a thread, or a function; otherwise, lua_topointer returns NULL. Different objects will give different pointers. There is no way to convert the pointer back to its original value.

Typically this function is used only for debug information.

lua_tostring

[-0, +0, m]

const char *lua_tostring (lua_State *L, int index);

Equivalent to lua_tolstring with len equal to NULL.

lua_tothread

[-0, +0, -]

lua_State *lua_tothread (lua_State *L, int index);

Converts the value at the given acceptable index to a Lua thread (represented as lua_State*). This value must be a thread; otherwise, the function returns NULL.

lua_touserdata

[-0, +0, -]

void *lua_touserdata (lua_State *L, int index);

If the value at the given acceptable index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. Otherwise, returns NULL.

lua_type

[-0, +0, -]

int lua_type (lua_State *L, int index);

Returns the type of the value in the given acceptable index, or LUA_TNONE for a non-valid index (that is, an index to an "empty" stack position). The types returned by lua_type are coded by the following constants defined in lua.h: LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA.

lua_typename

[-0, +0, -]

const char *lua_typename  (lua_State *L, int tp);

Returns the name of the type encoded by the value tp, which must be one the values returned by lua_type.

lua_Writer

typedef int (*lua_Writer) (lua_State *L,
                           const void* p,
                           size_t sz,
                           void* ud);

The type of the writer function used by lua_dump. Every time it produces another piece of chunk, lua_dump calls the writer, passing along the buffer to be written (p), its size (sz), and the data parameter supplied to lua_dump.

The writer returns an error code: 0 means no errors; any other value means an error and stops lua_dump from calling the writer again.

lua_xmove

[-?, +?, -]

void lua_xmove (lua_State *from, lua_State *to, int n);

Exchange values between different threads of the same global state.

This function pops n values from the stack from, and pushes them onto the stack to.

lua_yield

[-?, +?, -]

int lua_yield  (lua_State *L, int nresults);

Yields a coroutine.

This function should only be called as the return expression of a C function, as follows:

     return lua_yield (L, nresults);

When a C function calls lua_yield in that way, the running coroutine suspends its execution, and the call to lua_resume that started this coroutine returns. The parameter nresults is the number of values from the stack that are passed as results to lua_resume.

3.8 - The Debug Interface

Lua has no built-in debugging facilities. Instead, it offers a special interface by means of functions and hooks. This interface allows the construction of different kinds of debuggers, profilers, and other tools that need "inside information" from the interpreter.

lua_Debug

typedef struct lua_Debug {
  int event;
  const char *name;           /* (n) */
  const char *namewhat;       /* (n) */
  const char *what;           /* (S) */
  const char *source;         /* (S) */
  int currentline;            /* (l) */
  int nups;                   /* (u) number of upvalues */
  int linedefined;            /* (S) */
  int lastlinedefined;        /* (S) */
  char short_src[LUA_IDSIZE]; /* (S) */
  /* private part */
  other fields
} lua_Debug;

A structure used to carry different pieces of information about an active function. lua_getstack fills only the private part of this structure, for later use. To fill the other fields of lua_Debug with useful information, call lua_getinfo.

The fields of lua_Debug have the following meaning:

  • source: If the function was defined in a string, then source is that string. If the function was defined in a file, then source starts with a '@' followed by the file name.
  • short_src: a "printable" version of source, to be used in error messages.
  • linedefined: the line number where the definition of the function starts.
  • lastlinedefined: the line number where the definition of the function ends.
  • what: the string "Lua" if the function is a Lua function, "C" if it is a C function, "main" if it is the main part of a chunk, and "tail" if it was a function that did a tail call. In the latter case, Lua has no other information about the function.
  • currentline: the current line where the given function is executing. When no line information is available, currentline is set to -1.
  • name: a reasonable name for the given function. Because functions in Lua are first-class values, they do not have a fixed name: some functions can be the value of multiple global variables, while others can be stored only in a table field. The lua_getinfo function checks how the function was called to find a suitable name. If it cannot find a name, then name is set to NULL.
  • namewhat: explains the name field. The value of namewhat can be "global", "local", "method", "field", "upvalue", or "" (the empty string), according to how the function was called. (Lua uses the empty string when no other option seems to apply.)
  • nups: the number of upvalues of the function.

lua_gethook

[-0, +0, -]

lua_Hook lua_gethook (lua_State *L);

Returns the current hook function.

lua_gethookcount

[-0, +0, -]

int lua_gethookcount (lua_State *L);

Returns the current hook count.

lua_gethookmask

[-0, +0, -]

int lua_gethookmask (lua_State *L);

Returns the current hook mask.

lua_getinfo

[-(0|1), +(0|1|2), m]

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

Returns information about a specific function or function invocation.

To get information about a function invocation, the parameter ar must be a valid activation record that was filled by a previous call to lua_getstack or given as argument to a hook (see lua_Hook).

To get information about a function you push it onto the stack and start the what string with the character '>'. (In that case, lua_getinfo pops the function in the top of the stack.) For instance, to know in which line a function f was defined, you can write the following code:

     lua_Debug ar;
     lua_getfield(L, LUA_GLOBALSINDEX, "f");  /* get global 'f' */
     lua_getinfo(L, ">S", &ar);
     printf("%d\n", ar.linedefined);

Each character in the string what selects some fields of the structure ar to be filled or a value to be pushed on the stack:

  • 'n': fills in the field name and namewhat;
  • 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
  • 'l': fills in the field currentline;
  • 'u': fills in the field nups;
  • 'f': pushes onto the stack the function that is running at the given level;
  • 'L': pushes onto the stack a table whose indices are the numbers of the lines that are valid on the function. (A valid line is a line with some associated code, that is, a line where you can put a break point. Non-valid lines include empty lines and comments.)

This function returns 0 on error (for instance, an invalid option in what).

lua_getlocal

[-0, +(0|1), -]

const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);

Gets information about a local variable of a given activation record. The parameter ar must be a valid activation record that was filled by a previous call to lua_getstack or given as argument to a hook (see lua_Hook). The index n selects which local variable to inspect (1 is the first parameter or active local variable, and so on, until the last active local variable). lua_getlocal pushes the variable's value onto the stack and returns its name.

Variable names starting with '(' (open parentheses) represent internal variables (loop control variables, temporaries, and C function locals).

Returns NULL (and pushes nothing) when the index is greater than the number of active local variables.

lua_getstack

[-0, +0, -]

int lua_getstack (lua_State *L, int level, lua_Debug *ar);

Get information about the interpreter runtime stack.

This function fills parts of a lua_Debug structure with an identification of the activation record of the function executing at a given level. Level 0 is the current running function, whereas level n+1 is the function that has called level n. When there are no errors, lua_getstack returns 1; when called with a level greater than the stack depth, it returns 0.

lua_getupvalue

[-0, +(0|1), -]

const char *lua_getupvalue (lua_State *L, int funcindex, int n);

Gets information about a closure's upvalue. (For Lua functions, upvalues are the external local variables that the function uses, and that are consequently included in its closure.) lua_getupvalue gets the index n of an upvalue, pushes the upvalue's value onto the stack, and returns its name. funcindex points to the closure in the stack. (Upvalues have no particular order, as they are active through the whole function. So, they are numbered in an arbitrary order.)

Returns NULL (and pushes nothing) when the index is greater than the number of upvalues. For C functions, this function uses the empty string "" as a name for all upvalues.

lua_Hook

typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);

Type for debugging hook functions.

Whenever a hook is called, its ar argument has its field event set to the specific event that triggered the hook. Lua identifies these events with the following constants: LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILRET, LUA_HOOKLINE, and LUA_HOOKCOUNT. Moreover, for line events, the field currentline is also set. To get the value of any other field in ar, the hook must call lua_getinfo. For return events, event can be LUA_HOOKRET, the normal value, or LUA_HOOKTAILRET. In the latter case, Lua is simulating a return from a function that did a tail call; in this case, it is useless to call lua_getinfo.

While Lua is running a hook, it disables other calls to hooks. Therefore, if a hook calls back Lua to execute a function or a chunk, this execution occurs without any calls to hooks.

lua_sethook

[-0, +0, -]

int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

Sets the debugging hook function.

Argument f is the hook function. mask specifies on which events the hook will be called: it is formed by a bitwise or of the constants LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, and LUA_MASKCOUNT. The count argument is only meaningful when the mask includes LUA_MASKCOUNT. For each event, the hook is called as explained below:

  • The call hook: is called when the interpreter calls a function. The hook is called just after Lua enters the new function, before the function gets its arguments.
  • The return hook: is called when the interpreter returns from a function. The hook is called just before Lua leaves the function. You have no access to the values to be returned by the function.
  • The line hook: is called when the interpreter is about to start the execution of a new line of code, or when it jumps back in the code (even to the same line). (This event only happens while Lua is executing a Lua function.)
  • The count hook: is called after the interpreter executes every count instructions. (This event only happens while Lua is executing a Lua function.)

A hook is disabled by setting mask to zero.

lua_setlocal

[-(0|1), +0, -]

const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);

Sets the value of a local variable of a given activation record. Parameters ar and n are as in lua_getlocal (see lua_getlocal). lua_setlocal assigns the value at the top of the stack to the variable and returns its name. It also pops the value from the stack.

Returns NULL (and pops nothing) when the index is greater than the number of active local variables.

lua_setupvalue

[-(0|1), +0, -]

const char *lua_setupvalue (lua_State *L, int funcindex, int n);

Sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops the value from the stack. Parameters funcindex and n are as in the lua_getupvalue (see lua_getupvalue).

Returns NULL (and pops nothing) when the index is greater than the number of upvalues.

4 - The Auxiliary Library

The auxiliary library provides several convenient functions to interface C with Lua. While the basic API provides the primitive functions for all interactions between C and Lua, the auxiliary library provides higher-level functions for some common tasks.

All functions from the auxiliary library are defined in header file lauxlib.h and have a prefix luaL_.

All functions in the auxiliary library are built on top of the basic API, and so they provide nothing that cannot be done with this API.

Several functions in the auxiliary library are used to check C function arguments. Their names are always luaL_check* or luaL_opt*. All of these functions throw an error if the check is not satisfied. Because the error message is formatted for arguments (e.g., "bad argument #1"), you should not use these functions for other stack values.

4.1 - Functions and Types

Here we list all functions and types from the auxiliary library in alphabetical order.

luaL_addchar

[-0, +0, m]

void luaL_addchar (luaL_Buffer *B, char c);

Adds the character c to the buffer B (see luaL_Buffer).

luaL_addlstring

[-0, +0, m]

void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);

Adds the string pointed to by s with length l to the buffer B (see luaL_Buffer). The string may contain embedded zeros.

luaL_addsize

[-0, +0, m]

void luaL_addsize (luaL_Buffer *B, size_t n);

Adds to the buffer B (see luaL_Buffer) a string of length n previously copied to the buffer area (see luaL_prepbuffer).

luaL_addstring

[-0, +0, m]

void luaL_addstring (luaL_Buffer *B, const char *s);

Adds the zero-terminated string pointed to by s to the buffer B (see luaL_Buffer). The string may not contain embedded zeros.

luaL_addvalue

[-1, +0, m]

void luaL_addvalue (luaL_Buffer *B);

Adds the value at the top of the stack to the buffer B (see luaL_Buffer). Pops the value.

This is the only function on string buffers that can (and must) be called with an extra element on the stack, which is the value to be added to the buffer.

luaL_argcheck

[-0, +0, v]

void luaL_argcheck (lua_State *L,
                    int cond,
                    int narg,
                    const char *extramsg);

Checks whether cond is true. If not, raises an error with the following message, where func is retrieved from the call stack:

     bad argument #<narg> to <func> (<extramsg>)

luaL_argerror

[-0, +0, v]

int luaL_argerror (lua_State *L, int narg, const char *extramsg);

Raises an error with the following message, where func is retrieved from the call stack:

     bad argument #<narg> to <func> (<extramsg>)

This function never returns, but it is an idiom to use it in C functions as return luaL_argerror(args).

luaL_Buffer

typedef struct luaL_Buffer luaL_Buffer;

Type for a string buffer.

A string buffer allows C code to build Lua strings piecemeal. Its pattern of use is as follows:

  • First you declare a variable b of type luaL_Buffer.
  • Then you initialize it with a call luaL_buffinit(L, &b).
  • Then you add string pieces to the buffer calling any of the luaL_add* functions.
  • You finish by calling luaL_pushresult(&b). This call leaves the final string on the top of the stack.

During its normal operation, a string buffer uses a variable number of stack slots. So, while using a buffer, you cannot assume that you know where the top of the stack is. You can use the stack between successive calls to buffer operations as long as that use is balanced; that is, when you call a buffer operation, the stack is at the same level it was immediately after the previous buffer operation. (The only exception to this rule is luaL_addvalue.) After calling luaL_pushresult the stack is back to its level when the buffer was initialized, plus the final string on its top.

luaL_buffinit

[-0, +0, -]

void luaL_buffinit (lua_State *L, luaL_Buffer *B);

Initializes a buffer B. This function does not allocate any space; the buffer must be declared as a variable (see luaL_Buffer).

luaL_callmeta

[-0, +(0|1), e]

int luaL_callmeta (lua_State *L, int obj, const char *e);

Calls a metamethod.

If the object at index obj has a metatable and this metatable has a field e, this function calls this field and passes the object as its only argument. In this case this function returns 1 and pushes onto the stack the value returned by the call. If there is no metatable or no metamethod, this function returns 0 (without pushing any value on the stack).

luaL_checkany

[-0, +0, v]

void luaL_checkany (lua_State *L, int narg);

Checks whether the function has an argument of any type (including nil) at position narg.

luaL_checkint

[-0, +0, v]

int luaL_checkint (lua_State *L, int narg);

Checks whether the function argument narg is a number and returns this number cast to an int.

luaL_checkinteger

[-0, +0, v]

lua_Integer luaL_checkinteger (lua_State *L, int narg);

Checks whether the function argument narg is a number and returns this number cast to a lua_Integer.

luaL_checklong

[-0, +0, v]

long luaL_checklong (lua_State *L, int narg);

Checks whether the function argument narg is a number and returns this number cast to a long.

luaL_checklstring

[-0, +0, v]

const char *luaL_checklstring (lua_State *L, int narg, size_t *l);

Checks whether the function argument narg is a string and returns this string; if l is not NULL fills *l with the string's length.

This function uses lua_tolstring to get its result, so all conversions and caveats of that function apply here.

luaL_checknumber

[-0, +0, v]

lua_Number luaL_checknumber (lua_State *L, int narg);

Checks whether the function argument narg is a number and returns this number.

luaL_checkoption

[-0, +0, v]

int luaL_checkoption (lua_State *L,
                      int narg,
                      const char *def,
                      const char *const lst[]);

Checks whether the function argument narg is a string and searches for this string in the array lst (which must be NULL-terminated). Returns the index in the array where the string was found. Raises an error if the argument is not a string or if the string cannot be found.

If def is not NULL, the function uses def as a default value when there is no argument narg or if this argument is nil.

This is a useful function for mapping strings to C enums. (The usual convention in Lua libraries is to use strings instead of numbers to select options.)

luaL_checkstack

[-0, +0, v]

void luaL_checkstack (lua_State *L, int sz, const char *msg);

Grows the stack size to top + sz elements, raising an error if the stack cannot grow to that size. msg is an additional text to go into the error message.

luaL_checkstring

[-0, +0, v]

const char *luaL_checkstring (lua_State *L, int narg);

Checks whether the function argument narg is a string and returns this string.

This function uses lua_tolstring to get its result, so all conversions and caveats of that function apply here.

luaL_checktype

[-0, +0, v]

void luaL_checktype (lua_State *L, int narg, int t);

Checks whether the function argument narg has type t. See lua_type for the encoding of types for t.

luaL_checkudata

[-0, +0, v]

void *luaL_checkudata (lua_State *L, int narg, const char *tname);

Checks whether the function argument narg is a userdata of the type tname (see luaL_newmetatable).

luaL_dofile

[-0, +?, m]

int luaL_dofile (lua_State *L, const char *filename);

Loads and runs the given file. It is defined as the following macro:

     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))

It returns 0 if there are no errors or 1 in case of errors.

luaL_dostring

[-0, +?, m]

int luaL_dostring (lua_State *L, const char *str);

Loads and runs the given string. It is defined as the following macro:

     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))

It returns 0 if there are no errors or 1 in case of errors.

luaL_error

[-0, +0, v]

int luaL_error (lua_State *L, const char *fmt, ...);

Raises an error. The error message format is given by fmt plus any extra arguments, following the same rules of lua_pushfstring. It also adds at the beginning of the message the file name and the line number where the error occurred, if this information is available.

This function never returns, but it is an idiom to use it in C functions as return luaL_error(args).

luaL_getmetafield

[-0, +(0|1), m]

int luaL_getmetafield (lua_State *L, int obj, const char *e);

Pushes onto the stack the field e from the metatable of the object at index obj. If the object does not have a metatable, or if the metatable does not have this field, returns 0 and pushes nothing.

luaL_getmetatable

[-0, +1, -]

void luaL_getmetatable (lua_State *L, const char *tname);

Pushes onto the stack the metatable associated with name tname in the registry (see luaL_newmetatable).

luaL_gsub

[-0, +1, m]

const char *luaL_gsub (lua_State *L,
                       const char *s,
                       const char *p,
                       const char *r);

Creates a copy of string s by replacing any occurrence of the string p with the string r. Pushes the resulting string on the stack and returns it.

luaL_loadbuffer

[-0, +1, m]

int luaL_loadbuffer (lua_State *L,
                     const char *buff,
                     size_t sz,
                     const char *name);

Loads a buffer as a Lua chunk. This function uses lua_load to load the chunk in the buffer pointed to by buff with size sz.

This function returns the same results as lua_load. name is the chunk name, used for debug information and error messages.

luaL_loadfile

[-0, +1, m]

int luaL_loadfile (lua_State *L, const char *filename);

Loads a file as a Lua chunk. This function uses lua_load to load the chunk in the file named filename. If filename is NULL, then it loads from the standard input. The first line in the file is ignored if it starts with a #.

This function returns the same results as lua_load, but it has an extra error code LUA_ERRFILE if it cannot open/read the file.

As lua_load, this function only loads the chunk; it does not run it.

luaL_loadstring

[-0, +1, m]

int luaL_loadstring (lua_State *L, const char *s);

Loads a string as a Lua chunk. This function uses lua_load to load the chunk in the zero-terminated string s.

This function returns the same results as lua_load.

Also as lua_load, this function only loads the chunk; it does not run it.

luaL_newmetatable

[-0, +1, m]

int luaL_newmetatable (lua_State *L, const char *tname);

If the registry already has the key tname, returns 0. Otherwise, creates a new table to be used as a metatable for userdata, adds it to the registry with key tname, and returns 1.

In both cases pushes onto the stack the final value associated with tname in the registry.

luaL_newstate

[-0, +0, -]

lua_State *luaL_newstate (void);

Creates a new Lua state. It calls lua_newstate with an allocator based on the standard C realloc function and then sets a panic function (see lua_atpanic) that prints an error message to the standard error output in case of fatal errors.

Returns the new state, or NULL if there is a memory allocation error.

luaL_openlibs

[-0, +0, m]

void luaL_openlibs (lua_State *L);

Opens all standard Lua libraries into the given state.

luaL_optint

[-0, +0, v]

int luaL_optint (lua_State *L, int narg, int d);

If the function argument narg is a number, returns this number cast to an int. If this argument is absent or is nil, returns d. Otherwise, raises an error.

luaL_optinteger

[-0, +0, v]

lua_Integer luaL_optinteger (lua_State *L,
                             int narg,
                             lua_Integer d);

If the function argument narg is a number, returns this number cast to a lua_Integer. If this argument is absent or is nil, returns d. Otherwise, raises an error.

luaL_optlong

[-0, +0, v]

long luaL_optlong (lua_State *L, int narg, long d);

If the function argument narg is a number, returns this number cast to a long. If this argument is absent or is nil, returns d. Otherwise, raises an error.

luaL_optlstring

[-0, +0, v]

const char *luaL_optlstring (lua_State *L,
                             int narg,
                             const char *d,
                             size_t *l);

If the function argument narg is a string, returns this string. If this argument is absent or is nil, returns d. Otherwise, raises an error.

If l is not NULL, fills the position *l with the results's length.

luaL_optnumber

[-0, +0, v]

lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);

If the function argument narg is a number, returns this number. If this argument is absent or is nil, returns d. Otherwise, raises an error.

luaL_optstring

[-0, +0, v]

const char *luaL_optstring (lua_State *L,
                            int narg,
                            const char *d);

If the function argument narg is a string, returns this string. If this argument is absent or is nil, returns d. Otherwise, raises an error.

luaL_prepbuffer

[-0, +0, -]

char *luaL_prepbuffer (luaL_Buffer *B);

Returns an address to a space of size LUAL_BUFFERSIZE where you can copy a string to be added to buffer B (see luaL_Buffer). After copying the string into this space you must call luaL_addsize with the size of the string to actually add it to the buffer.

luaL_pushresult

[-?, +1, m]

void luaL_pushresult (luaL_Buffer *B);

Finishes the use of buffer B leaving the final string on the top of the stack.

luaL_ref

[-1, +0, m]

int luaL_ref (lua_State *L, int t);

Creates and returns a reference, in the table at index t, for the object at the top of the stack (and pops the object).

A reference is a unique integer key. As long as you do not manually add integer keys into table t, luaL_ref ensures the uniqueness of the key it returns. You can retrieve an object referred by reference r by calling lua_rawgeti(L, t, r). Function luaL_unref frees a reference and its associated object.

If the object at the top of the stack is nil, luaL_ref returns the constant LUA_REFNIL. The constant LUA_NOREF is guaranteed to be different from any reference returned by luaL_ref.

luaL_Reg

typedef struct luaL_Reg {
  const char *name;
  lua_CFunction func;
} luaL_Reg;

Type for arrays of functions to be registered by luaL_register. name is the function name and func is a pointer to the function. Any array of luaL_Reg must end with an sentinel entry in which both name and func are NULL.

luaL_register

[-(0|1), +1, m]

void luaL_register (lua_State *L,
                    const char *libname,
                    const luaL_Reg *l);

Opens a library.

When called with libname equal to NULL, it simply registers all functions in the list l (see luaL_Reg) into the table on the top of the stack.

When called with a non-null libname, luaL_register creates a new table t, sets it as the value of the global variable libname, sets it as the value of package.loaded[libname], and registers on it all functions in the list l. If there is a table in package.loaded[libname] or in variable libname, reuses this table instead of creating a new one.

In any case the function leaves the table on the top of the stack.

luaL_typename

[-0, +0, -]

const char *luaL_typename (lua_State *L, int index);

Returns the name of the type of the value at the given index.

luaL_typerror

[-0, +0, v]

int luaL_typerror (lua_State *L, int narg, const char *tname);

Generates an error with a message like the following:

     location: bad argument narg to 'func' (tname expected, got rt)

where location is produced by luaL_where, func is the name of the current function, and rt is the type name of the actual argument.

luaL_unref

[-0, +0, -]

void luaL_unref (lua_State *L, int t, int ref);

Releases reference ref from the table at index t (see luaL_ref). The entry is removed from the table, so that the referred object can be collected. The reference ref is also freed to be used again.

If ref is LUA_NOREF or LUA_REFNIL, luaL_unref does nothing.

luaL_where

[-0, +1, m]

void luaL_where (lua_State *L, int lvl);

Pushes onto the stack a string identifying the current position of the control at level lvl in the call stack. Typically this string has the following format:

     chunkname:currentline:

Level 0 is the running function, level 1 is the function that called the running function, etc.

This function is used to build a prefix for error messages.

5 - Standard Libraries

The standard Lua libraries provide useful functions that are implemented directly through the C API. Some of these functions provide essential services to the language (e.g., type and getmetatable); others provide access to "outside" services (e.g., I/O); and others could be implemented in Lua itself, but are quite useful or have critical performance requirements that deserve an implementation in C (e.g., table.sort).

All libraries are implemented through the official C API and are provided as separate C modules. Currently, Lua has the following standard libraries:

  • basic library, which includes the coroutine sub-library;
  • package library;
  • string manipulation;
  • table manipulation;
  • mathematical functions (sin, log, etc.);
  • input and output;
  • operating system facilities;
  • debug facilities.

Except for the basic and package libraries, each library provides all its functions as fields of a global table or as methods of its objects.

To have access to these libraries, the C host program should call the luaL_openlibs function, which opens all standard libraries. Alternatively, it can open them individually by calling luaopen_base (for the basic library), luaopen_package (for the package library), luaopen_string (for the string library), luaopen_table (for the table library), luaopen_math (for the mathematical library), luaopen_io (for the I/O library), luaopen_os (for the Operating System library), and luaopen_debug (for the debug library). These functions are declared in lualib.h and should not be called directly: you must call them like any other Lua C function, e.g., by using lua_call.

5.1 - Basic Functions

The basic library provides some core functions to Lua. If you do not include this library in your application, you should check carefully whether you need to provide implementations for some of its facilities.

assert (v [, message])

Issues an error when the value of its argument v is false (i.e., nil or false); otherwise, returns all its arguments. message is an error message; when absent, it defaults to "assertion failed!"

collectgarbage (opt [, arg])

This function is a generic interface to the garbage collector. It performs different functions according to its first argument, opt:

  • "stop": stops the garbage collector.
  • "restart": restarts the garbage collector.
  • "collect": performs a full garbage-collection cycle.
  • "count": returns the total memory in use by Lua (in Kbytes).
  • "step": performs a garbage-collection step. The step "size" is controlled by arg (larger values mean more steps) in a non-specified way. If you want to control the step size you must experimentally tune the value of arg. Returns true if the step finished a collection cycle.
  • "setpause": sets arg as the new value for the pause of the collector (see §2.10). Returns the previous value for pause.
  • "setstepmul": sets arg as the new value for the step multiplier of the collector (see §2.10). Returns the previous value for step.

dofile (filename)

Opens the named file and executes its contents as a Lua chunk. When called without arguments, dofile executes the contents of the standard input (stdin). Returns all values returned by the chunk. In case of errors, dofile propagates the error to its caller (that is, dofile does not run in protected mode).

error (message [, level])

Terminates the last protected function called and returns message as the error message. Function error never returns.

Usually, error adds some information about the error position at the beginning of the message. The level argument specifies how to get the error position. With level 1 (the default), the error position is where the error function was called. Level 2 points the error to where the function that called error was called; and so on. Passing a level 0 avoids the addition of error position information to the message.

_G

A global variable (not a function) that holds the global environment (that is, _G._G = _G). Lua itself does not use this variable; changing its value does not affect any environment, nor vice-versa. (Use setfenv to change environments.)

getfenv ([f])

Returns the current environment in use by the function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling getfenv. If the given function is not a Lua function, or if f is 0, getfenv returns the global environment. The default for f is 1.

getmetatable (object)

If object does not have a metatable, returns nil. Otherwise, if the object's metatable has a "__metatable" field, returns the associated value. Otherwise, returns the metatable of the given object.

ipairs (t)

Returns three values: an iterator function, the table t, and 0, so that the construction

     for i,v in ipairs(t) do body end

will iterate over the pairs (1,t[1]), (2,t[2]), ···, up to the first integer key absent from the table.

load (func [, chunkname])

Loads a chunk using function func to get its pieces. Each call to func must return a string that concatenates with previous results. A return of an empty string, nil, or no value signals the end of the chunk.

If there are no errors, returns the compiled chunk as a function; otherwise, returns nil plus the error message. The environment of the returned function is the global environment.

chunkname is used as the chunk name for error messages and debug information. When absent, it defaults to "=(load)".

loadfile ([filename])

Similar to load, but gets the chunk from file filename or from the standard input, if no file name is given.

loadstring (string [, chunkname])

Similar to load, but gets the chunk from the given string.

To load and run a given string, use the idiom

     assert(loadstring(s))()

When absent, chunkname defaults to the given string.

next (table [, index])

Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table. next returns the next index of the table and its associated value. When called with nil as its second argument, next returns an initial index and its associated value. When called with the last index, or with nil in an empty table, next returns nil. If the second argument is absent, then it is interpreted as nil. In particular, you can use next(t) to check whether a table is empty.

The order in which the indices are enumerated is not specified, even for numeric indices. (To traverse a table in numeric order, use a numerical for or the ipairs function.)

The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields.

pairs (t)

Returns three values: the next function, the table t, and nil, so that the construction

     for k,v in pairs(t) do body end

will iterate over all key-value pairs of table t.

See function next for the caveats of modifying the table during its traversal.

pcall (f, arg1, ···)

Calls function f with the given arguments in protected mode. This means that any error inside f is not propagated; instead, pcall catches the error and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In such case, pcall also returns all results from the call, after this first result. In case of any error, pcall returns false plus the error message.

print (···)

Receives any number of arguments, and prints their values to stdout, using the tostring function to convert them to strings. print is not intended for formatted output, but only as a quick way to show a value, typically for debugging. For formatted output, use string.format.

rawequal (v1, v2)

Checks whether v1 is equal to v2, without invoking any metamethod. Returns a boolean.

rawget (table, index)

Gets the real value of table[index], without invoking any metamethod. table must be a table; index may be any value.

rawset (table, index, value)

Sets the real value of table[index] to value, without invoking any metamethod. table must be a table, index any value different from nil, and value any Lua value.

This function returns table.

select (index, ···)

If index is a number, returns all arguments after argument number index. Otherwise, index must be the string "#", and select returns the total number of extra arguments it received.

setfenv (f, table)

Sets the environment to be used by the given function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling setfenv. setfenv returns the given function.

As a special case, when f is 0 setfenv changes the environment of the running thread. In this case, setfenv returns no values.

setmetatable (table, metatable)

Sets the metatable for the given table. (You cannot change the metatable of other types from Lua, only from C.) If metatable is nil, removes the metatable of the given table. If the original metatable has a "__metatable" field, raises an error.

This function returns table.

tonumber (e [, base])

Tries to convert its argument to a number. If the argument is already a number or a string convertible to a number, then tonumber returns this number; otherwise, it returns nil.

An optional argument specifies the base to interpret the numeral. The base may be any integer between 2 and 36, inclusive. In bases above 10, the letter 'A' (in either upper or lower case) represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. In base 10 (the default), the number can have a decimal part, as well as an optional exponent part (see §2.1). In other bases, only unsigned integers are accepted.

tostring (e)

Receives an argument of any type and converts it to a string in a reasonable format. For complete control of how numbers are converted, use string.format.

If the metatable of e has a "__tostring" field, then tostring calls the corresponding value with e as argument, and uses the result of the call as its result.

type (v)

Returns the type of its only argument, coded as a string. The possible results of this function are "nil" (a string, not the value nil), "number", "string", "boolean", "table", "function", "thread", and "userdata".

unpack (list [, i [, j]])

Returns the elements from the given table. This function is equivalent to
     return list[i], list[i+1], ···, list[j]

except that the above code can be written only for a fixed number of elements. By default, i is 1 and j is the length of the list, as defined by the length operator (see §2.5.5).

_VERSION

A global variable (not a function) that holds a string containing the current interpreter version. The current contents of this variable is "Lua 5.1".

xpcall (f, err)

This function is similar to pcall, except that you can set a new error handler.

xpcall calls function f in protected mode, using err as the error handler. Any error inside f is not propagated; instead, xpcall catches the error, calls the err function with the original error object, and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In this case, xpcall also returns all results from the call, after this first result. In case of any error, xpcall returns false plus the result from err.

5.2 - Coroutine Manipulation

The operations related to coroutines comprise a sub-library of the basic library and come inside the table coroutine. See §2.11 for a general description of coroutines.

coroutine.create (f)

Creates a new coroutine, with body f. f must be a Lua function. Returns this new coroutine, an object with type "thread".

coroutine.resume (co [, val1, ···])

Starts or continues the execution of coroutine co. The first time you resume a coroutine, it starts running its body. The values val1, ··· are passed as the arguments to the body function. If the coroutine has yielded, resume restarts it; the values val1, ··· are passed as the results from the yield.

If the coroutine runs without any errors, resume returns true plus any values passed to yield (if the coroutine yields) or any values returned by the body function (if the coroutine terminates). If there is any error, resume returns false plus the error message.

coroutine.running ()

Returns the running coroutine, or nil when called by the main thread.

coroutine.status (co)

Returns the status of coroutine co, as a string: "running", if the coroutine is running (that is, it called status); "suspended", if the coroutine is suspended in a call to yield, or if it has not started running yet; "normal" if the coroutine is active but not running (that is, it has resumed another coroutine); and "dead" if the coroutine has finished its body function, or if it has stopped with an error.

coroutine.wrap (f)

Creates a new coroutine, with body f. f must be a Lua function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to resume. Returns the same values returned by resume, except the first boolean. In case of error, propagates the error.

coroutine.yield (···)

Suspends the execution of the calling coroutine. The coroutine cannot be running a C function, a metamethod, or an iterator. Any arguments to yield are passed as extra results to resume.

5.3 - Modules

The package library provides basic facilities for loading and building modules in Lua. It exports two of its functions directly in the global environment: require and module. Everything else is exported in a table package.

module (name [, ···])

Creates a module. If there is a table in package.loaded[name], this table is the module. Otherwise, if there is a global table t with the given name, this table is the module. Otherwise creates a new table t and sets it as the value of the global name and the value of package.loaded[name]. This function also initializes t._NAME with the given name, t._M with the module (t itself), and t._PACKAGE with the package name (the full module name minus last component; see below). Finally, module sets t as the new environment of the current function and the new value of package.loaded[name], so that require returns t.

If name is a compound name (that is, one with components separated by dots), module creates (or reuses, if they already exist) tables for each component. For instance, if name is a.b.c, then module stores the module table in field c of field b of global a.

This function can receive optional options after the module name, where each option is a function to be applied over the module.

require (modname)

Loads the given module. The function starts by looking into the package.loaded table to determine whether modname is already loaded. If it is, then require returns the value stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module.

To find a loader, require is guided by the package.loaders array. By changing this array, we can change how require looks for a module. The following explanation is based on the default configuration for package.loaders.

First require queries package.preload[modname]. If it has a value, this value (which should be a function) is the loader. Otherwise require searches for a Lua loader using the path stored in package.path. If that also fails, it searches for a C loader using the path stored in package.cpath. If that also fails, it tries an all-in-one loader (see package.loaders).

Once a loader is found, require calls the loader with a single argument, modname. If the loader returns any value, require assigns the returned value to package.loaded[modname]. If the loader returns no value and has not assigned any value to package.loaded[modname], then require assigns true to this entry. In any case, require returns the final value of package.loaded[modname].

If there is any error loading or running the module, or if it cannot find any loader for the module, then require signals an error.

package.cpath

The path used by require to search for a C loader.

Lua initializes the C path package.cpath in the same way it initializes the Lua path package.path, using the environment variable LUA_CPATH or a default path defined in luaconf.h.

package.loaded

A table used by require to control which modules are already loaded. When you require a module modname and package.loaded[modname] is not false, require simply returns the value stored there.

package.loaders

A table used by require to control how to load modules.

Each entry in this table is a searcher function. When looking for a module, require calls each of these searchers in ascending order, with the module name (the argument given to require) as its sole parameter. The function can return another function (the module loader) or a string explaining why it did not find that module (or nil if it has nothing to say). Lua initializes this table with four functions.

The first searcher simply looks for a loader in the package.preload table.

The second searcher looks for a loader as a Lua library, using the path stored at package.path. A path is a sequence of templates separated by semicolons. For each template, the searcher will change each interrogation mark in the template by filename, which is the module name with each dot replaced by a "directory separator" (such as "/" in Unix); then it will try to open the resulting file name. So, for instance, if the Lua path is the string

     "./?.lua;./?.lc;/usr/local/?/init.lua"

the search for a Lua file for module foo will try to open the files ./foo.lua, ./foo.lc, and /usr/local/foo/init.lua, in that order.

The third searcher looks for a loader as a C library, using the path given by the variable package.cpath. For instance, if the C path is the string

     "./?.so;./?.dll;/usr/local/?/init.so"

the searcher for module foo will try to open the files ./foo.so, ./foo.dll, and /usr/local/foo/init.so, in that order. Once it finds a C library, this searcher first uses a dynamic link facility to link the application with the library. Then it tries to find a C function inside the library to be used as the loader. The name of this C function is the string "luaopen_" concatenated with a copy of the module name where each dot is replaced by an underscore. Moreover, if the module name has a hyphen, its prefix up to (and including) the first hyphen is removed. For instance, if the module name is a.v1-b.c, the function name will be luaopen_b_c.

The fourth searcher tries an all-in-one loader. It searches the C path for a library for the root name of the given module. For instance, when requiring a.b.c, it will search for a C library for a. If found, it looks into it for an open function for the submodule; in our example, that would be luaopen_a_b_c. With this facility, a package can pack several C submodules into one single library, with each submodule keeping its original open function.

package.loadlib (libname, funcname)

Dynamically links the host program with the C library libname. Inside this library, looks for a function funcname and returns this function as a C function. (So, funcname must follow the protocol (see lua_CFunction)).

This is a low-level function. It completely bypasses the package and module system. Unlike require, it does not perform any path searching and does not automatically adds extensions. libname must be the complete file name of the C library, including if necessary a path and extension. funcname must be the exact name exported by the C library (which may depend on the C compiler and linker used).

This function is not supported by ANSI C. As such, it is only available on some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix systems that support the dlfcn standard).

package.path

The path used by require to search for a Lua loader.

At start-up, Lua initializes this variable with the value of the environment variable LUA_PATH or with a default path defined in luaconf.h, if the environment variable is not defined. Any ";;" in the value of the environment variable is replaced by the default path.

package.preload

A table to store loaders for specific modules (see require).

package.seeall (module)

Sets a metatable for module with its __index field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function module.

5.4 - String Manipulation

This library provides generic functions for string manipulation, such as finding and extracting substrings, and pattern matching. When indexing a string in Lua, the first character is at position 1 (not at 0, as in C). Indices are allowed to be negative and are interpreted as indexing backwards, from the end of the string. Thus, the last character is at position -1, and so on.

The string library provides all its functions inside the table string. It also sets a metatable for strings where the __index field points to the string table. Therefore, you can use the string functions in object-oriented style. For instance, string.byte(s, i) can be written as s:byte(i).

The string library assumes one-byte character encodings.

string.byte (s [, i [, j]])

Returns the internal numerical codes of the characters s[i], s[i+1], ···, s[j]. The default value for i is 1; the default value for j is i.

Note that numerical codes are not necessarily portable across platforms.

string.char (···)

Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument.

Note that numerical codes are not necessarily portable across platforms.

string.dump (function)

Returns a string containing a binary representation of the given function, so that a later loadstring on this string returns a copy of the function. function must be a Lua function without upvalues.

string.find (s, pattern [, init [, plain]])

Looks for the first match of pattern in the string s. If it finds a match, then find returns the indices of s where this occurrence starts and ends; otherwise, it returns nil. A third, optional numerical argument init specifies where to start the search; its default value is 1 and can be negative. A value of true as a fourth, optional argument plain turns off the pattern matching facilities, so the function does a plain "find substring" operation, with no characters in pattern being considered "magic". Note that if plain is given, then init must be given as well.

If the pattern has captures, then in a successful match the captured values are also returned, after the two indices.

string.format (formatstring, ···)

Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the printf family of standard C functions. The only differences are that the options/modifiers *, l, L, n, p, and h are not supported and that there is an extra option, q. The q option formats a string in a form suitable to be safely read back by the Lua interpreter: the string is written between double quotes, and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly escaped when written. For instance, the call
     string.format('%q', 'a string with "quotes" and \n new line')

will produce the string:

     "a string with \"quotes\" and \
      new line"

The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, whereas q and s expect a string.

This function does not accept string values containing embedded zeros, except as arguments to the q option.

string.gmatch (s, pattern)

Returns an iterator function that, each time it is called, returns the next captures from pattern over string s. If pattern specifies no captures, then the whole match is produced in each call.

As an example, the following loop

     s = "hello world from Lua"
     for w in string.gmatch(s, "%a+") do
       print(w)
     end

will iterate over all the words from string s, printing one per line. The next example collects all pairs key=value from the given string into a table:

     t = {}
     s = "from=world, to=Lua"
     for k, v in string.gmatch(s, "(%w+)=(%w+)") do
       t[k] = v
     end

For this function, a '^' at the start of a pattern does not work as an anchor, as this would prevent the iteration.

string.gsub (s, pattern, repl [, n])

Returns a copy of s in which all (or the first n, if given) occurrences of the pattern have been replaced by a replacement string specified by repl, which can be a string, a table, or a function. gsub also returns, as its second value, the total number of matches that occurred.

If repl is a string, then its value is used for replacement. The character % works as an escape character: any sequence in repl of the form %n, with n between 1 and 9, stands for the value of the n-th captured substring (see below). The sequence %0 stands for the whole match. The sequence %% stands for a single %.

If repl is a table, then the table is queried for every match, using the first capture as the key; if the pattern specifies no captures, then the whole match is used as the key.

If repl is a function, then this function is called every time a match occurs, with all captured substrings passed as arguments, in order; if the pattern specifies no captures, then the whole match is passed as a sole argument.

If the value returned by the table query or by the function call is a string or a number, then it is used as the replacement string; otherwise, if it is false or nil, then there is no replacement (that is, the original match is kept in the string).

Here are some examples:

     x = string.gsub("hello world", "(%w+)", "%1 %1")
     --> x="hello hello world world"

     x = string.gsub("hello world", "%w+", "%0 %0", 1)
     --> x="hello hello world"

     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
     --> x="world hello Lua from"

     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
     --> x="home = /home/roberto, user = roberto"

     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
           return loadstring(s)()
         end)
     --> x="4+5 = 9"

     local t = {name="lua", version="5.1"}
     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
     --> x="lua-5.1.tar.gz"

string.len (s)

Receives a string and returns its length. The empty string "" has length 0. Embedded zeros are counted, so "a\000bc\000" has length 5.

string.lower (s)

Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale.

string.match (s, pattern [, init])

Looks for the first match of pattern in the string s. If it finds one, then match returns the captures from the pattern; otherwise it returns nil. If pattern specifies no captures, then the whole match is returned. A third, optional numerical argument init specifies where to start the search; its default value is 1 and can be negative.

string.rep (s, n)

Returns a string that is the concatenation of n copies of the string s.

string.reverse (s)

Returns a string that is the string s reversed.

string.sub (s, i [, j])

Returns the substring of s that starts at i and continues until j; i and j can be negative. If j is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s, -i) returns a suffix of s with length i.

string.upper (s)

Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale.

5.4.1 - Patterns

Character Class:

A character class is used to represent a set of characters. The following combinations are allowed in describing a character class:

  • x: (where x is not one of the magic characters ^$()%.[]*+-?) represents the character x itself.
  • .: (a dot) represents all characters.
  • %a: represents all letters.
  • %c: represents all control characters.
  • %d: represents all digits.
  • %l: represents all lowercase letters.
  • %p: represents all punctuation characters.
  • %s: represents all space characters.
  • %u: represents all uppercase letters.
  • %w: represents all alphanumeric characters.
  • %x: represents all hexadecimal digits.
  • %z: represents the character with representation 0.
  • %x: (where x is any non-alphanumeric character) represents the character x. This is the standard way to escape the magic characters. Any punctuation character (even the non magic) can be preceded by a '%' when used to represent itself in a pattern.
  • [set]: represents the class which is the union of all characters in set. A range of characters can be specified by separating the end characters of the range with a '-'. All classes %x described above can also be used as components in set. All other characters in set represent themselves. For example, [%w_] (or [_%w]) represents all alphanumeric characters plus the underscore, [0-7] represents the octal digits, and [0-7%l%-] represents the octal digits plus the lowercase letters plus the '-' character.

    The interaction between ranges and classes is not defined. Therefore, patterns like [%a-z] or [a-%%] have no meaning.

  • [^set]: represents the complement of set, where set is interpreted as above.

For all classes represented by single letters (%a, %c, etc.), the corresponding uppercase letter represents the complement of the class. For instance, %S represents all non-space characters.

The definitions of letter, space, and other character groups depend on the current locale. In particular, the class [a-z] may not be equivalent to %l.

Pattern Item:

A pattern item can be

  • a single character class, which matches any single character in the class;
  • a single character class followed by '*', which matches 0 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence;
  • a single character class followed by '+', which matches 1 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence;
  • a single character class followed by '-', which also matches 0 or more repetitions of characters in the class. Unlike '*', these repetition items will always match the shortest possible sequence;
  • a single character class followed by '?', which matches 0 or 1 occurrence of a character in the class;
  • %n, for n between 1 and 9; such item matches a substring equal to the n-th captured string (see below);
  • %bxy, where x and y are two distinct characters; such item matches strings that start with x, end with y, and where the x and y are balanced. This means that, if one reads the string from left to right, counting +1 for an x and -1 for a y, the ending y is the first y where the count reaches 0. For instance, the item %b() matches expressions with balanced parentheses.

Pattern:

A pattern is a sequence of pattern items. A '^' at the beginning of a pattern anchors the match at the beginning of the subject string. A '$' at the end of a pattern anchors the match at the end of the subject string. At other positions, '^' and '$' have no special meaning and represent themselves.

Captures:

A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the substrings of the subject string that match captures are stored (captured) for future use. Captures are numbered according to their left parentheses. For instance, in the pattern "(a*(.)%w(%s*))", the part of the string matching "a*(.)%w(%s*)" is stored as the first capture (and therefore has number 1); the character matching "." is captured with number 2, and the part matching "%s*" has number 3.

As a special case, the empty capture () captures the current string position (a number). For instance, if we apply the pattern "()aa()" on the string "flaaap", there will be two captures: 3 and 5.

A pattern cannot contain embedded zeros. Use %z instead.

5.5 - Table Manipulation

This library provides generic functions for table manipulation. It provides all its functions inside the table table.

Most functions in the table library assume that the table represents an array or a list. For these functions, when we talk about the "length" of a table we mean the result of the length operator.

table.concat (table [, sep [, i [, j]]])

Given an array where all elements are strings or numbers, returns table[i]..sep..table[i+1] ··· sep..table[j]. The default value for sep is the empty string, the default for i is 1, and the default for j is the length of the table. If i is greater than j, returns the empty string.

table.insert (table, [pos,] value)

Inserts element value at position pos in table, shifting up other elements to open space, if necessary. The default value for pos is n+1, where n is the length of the table (see §2.5.5), so that a call table.insert(t,x) inserts x at the end of table t.

table.maxn (table)

Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.)

table.remove (table [, pos])

Removes from table the element at position pos, shifting down other elements to close the space, if necessary. Returns the value of the removed element. The default value for pos is n, where n is the length of the table, so that a call table.remove(t) removes the last element of table t.

table.sort (table [, comp])

Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the length of the table. If comp is given, then it must be a function that receives two table elements, and returns true when the first is less than the second (so that not comp(a[i+1],a[i]) will be true after the sort). If comp is not given, then the standard Lua operator < is used instead.

The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.

5.6 - Mathematical Functions

This library is an interface to the standard C math library. It provides all its functions inside the table math.

math.abs (x)

Returns the absolute value of x.

math.acos (x)

Returns the arc cosine of x (in radians).

math.asin (x)

Returns the arc sine of x (in radians).

math.atan (x)

Returns the arc tangent of x (in radians).

math.atan2 (y, x)

Returns the arc tangent of y/x (in radians), but uses the signs of both parameters to find the quadrant of the result. (It also handles correctly the case of x being zero.)

math.ceil (x)

Returns the smallest integer larger than or equal to x.

math.cos (x)

Returns the cosine of x (assumed to be in radians).

math.cosh (x)

Returns the hyperbolic cosine of x.

math.deg (x)

Returns the angle x (given in radians) in degrees.

math.exp (x)

Returns the value ex.

math.floor (x)

Returns the largest integer smaller than or equal to x.

math.fmod (x, y)

Returns the remainder of the division of x by y that rounds the quotient towards zero.

math.frexp (x)

Returns m and e such that x = m2e, e is an integer and the absolute value of m is in the range [0.5, 1) (or zero when x is zero).

math.huge

The value HUGE_VAL, a value larger than or equal to any other numerical value.

math.ldexp (m, e)

Returns m2e (e should be an integer).

math.log (x)

Returns the natural logarithm of x.

math.log10 (x)

Returns the base-10 logarithm of x.

math.max (x, ···)

Returns the maximum value among its arguments.

math.min (x, ···)

Returns the minimum value among its arguments.

math.modf (x)

Returns two numbers, the integral part of x and the fractional part of x.

math.pi

The value of pi.

math.pow (x, y)

Returns xy. (You can also use the expression x^y to compute this value.)

math.rad (x)

Returns the angle x (given in degrees) in radians.

math.random ([m [, n]])

This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.)

When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].

math.randomseed (x)

Sets x as the "seed" for the pseudo-random generator: equal seeds produce equal sequences of numbers.

math.sin (x)

Returns the sine of x (assumed to be in radians).

math.sinh (x)

Returns the hyperbolic sine of x.

math.sqrt (x)

Returns the square root of x. (You can also use the expression x^0.5 to compute this value.)

math.tan (x)

Returns the tangent of x (assumed to be in radians).

math.tanh (x)

Returns the hyperbolic tangent of x.

5.7 - Input and Output Facilities

The I/O library provides two different styles for file manipulation. The first one uses implicit file descriptors; that is, there are operations to set a default input file and a default output file, and all input/output operations are over these default files. The second style uses explicit file descriptors.

When using implicit file descriptors, all operations are supplied by table io. When using explicit file descriptors, the operation io.open returns a file descriptor and then all operations are supplied as methods of the file descriptor.

The table io also provides three predefined file descriptors with their usual meanings from C: io.stdin, io.stdout, and io.stderr. The I/O library never closes these files.

Unless otherwise stated, all I/O functions return nil on failure (plus an error message as a second result and a system-dependent error code as a third result) and some value different from nil on success.

io.close ([file])

Equivalent to file:close(). Without a file, closes the default output file.

io.flush ()

Equivalent to file:flush over the default output file.

io.input ([file])

When called with a file name, it opens the named file (in text mode), and sets its handle as the default input file. When called with a file handle, it simply sets this file handle as the default input file. When called without parameters, it returns the current default input file.

In case of errors this function raises the error, instead of returning an error code.

io.lines ([filename])

Opens the given file name in read mode and returns an iterator function that, each time it is called, returns a new line from the file. Therefore, the construction

     for line in io.lines(filename) do body end

will iterate over all lines of the file. When the iterator function detects the end of file, it returns nil (to finish the loop) and automatically closes the file.

The call io.lines() (with no file name) is equivalent to io.input():lines(); that is, it iterates over the lines of the default input file. In this case it does not close the file when the loop ends.

io.open (filename [, mode])

This function opens a file, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message.

The mode string can be any of the following:

  • "r": read mode (the default);
  • "w": write mode;
  • "a": append mode;
  • "r+": update mode, all previous data is preserved;
  • "w+": update mode, all previous data is erased;
  • "a+": append update mode, previous data is preserved, writing is only allowed at the end of file.

The mode string can also have a 'b' at the end, which is needed in some systems to open the file in binary mode. This string is exactly what is used in the standard C function fopen.

io.output ([file])

Similar to io.input, but operates over the default output file.

io.popen (prog [, mode])

Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w").

This function is system dependent and is not available on all platforms.

io.read (···)

Equivalent to io.input():read.

io.tmpfile ()

Returns a handle for a temporary file. This file is opened in update mode and it is automatically removed when the program ends.

io.type (obj)

Checks whether obj is a valid file handle. Returns the string "file" if obj is an open file handle, "closed file" if obj is a closed file handle, or nil if obj is not a file handle.

io.write (···)

Equivalent to io.output():write.

file:close ()

Closes file. Note that files are automatically closed when their handles are garbage collected, but that takes an unpredictable amount of time to happen.

file:flush ()

Saves any written data to file.

file:lines ()

Returns an iterator function that, each time it is called, returns a new line from the file. Therefore, the construction

     for line in file:lines() do body end

will iterate over all lines of the file. (Unlike io.lines, this function does not close the file when the loop ends.)

file:read (···)

Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).

The available formats are

  • "*n": reads a number; this is the only format that returns a number instead of a string.
  • "*a": reads the whole file, starting at the current position. On end of file, it returns the empty string.
  • "*l": reads the next line (skipping the end of line), returning nil on end of file. This is the default format.
  • number: reads a string with up to this number of characters, returning nil on end of file. If number is zero, it reads nothing and returns an empty string, or nil on end of file.

file:seek ([whence] [, offset])

Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence, as follows:

  • "set": base is position 0 (beginning of the file);
  • "cur": base is current position;
  • "end": base is end of file;

In case of success, function seek returns the final file position, measured in bytes from the beginning of the file. If this function fails, it returns nil, plus a string describing the error.

The default value for whence is "cur", and for offset is 0. Therefore, the call file:seek() returns the current file position, without changing it; the call file:seek("set") sets the position to the beginning of the file (and returns 0); and the call file:seek("end") sets the position to the end of the file, and returns its size.

file:setvbuf (mode [, size])

Sets the buffering mode for an output file. There are three available modes:

  • "no": no buffering; the result of any output operation appears immediately.
  • "full": full buffering; output operation is performed only when the buffer is full (or when you explicitly flush the file (see io.flush)).
  • "line": line buffering; output is buffered until a newline is output or there is any input from some special files (such as a terminal device).

For the last two cases, size specifies the size of the buffer, in bytes. The default is an appropriate size.

file:write (···)

Writes the value of each of its arguments to the file. The arguments must be strings or numbers. To write other values, use tostring or string.format before write.

5.8 - Operating System Facilities

This library is implemented through table os.

os.clock ()

Returns an approximation of the amount in seconds of CPU time used by the program.

os.date ([format [, time]])

Returns a string or a table containing date and time, formatted according to the given string format.

If the time argument is present, this is the time to be formatted (see the os.time function for a description of this value). Otherwise, date formats the current time.

If format starts with '!', then the date is formatted in Coordinated Universal Time. After this optional character, if format is the string "*t", then date returns a table with the following fields: year (four digits), month (1--12), day (1--31), hour (0--23), min (0--59), sec (0--61), wday (weekday, Sunday is 1), yday (day of the year), and isdst (daylight saving flag, a boolean).

If format is not "*t", then date returns the date as a string, formatted according to the same rules as the C function strftime.

When called without arguments, date returns a reasonable date and time representation that depends on the host system and on the current locale (that is, os.date() is equivalent to os.date("%c")).

os.difftime (t2, t1)

Returns the number of seconds from time t1 to time t2. In POSIX, Windows, and some other systems, this value is exactly t2-t1.

os.execute ([command])

This function is equivalent to the C function system. It passes command to be executed by an operating system shell. It returns a status code, which is system-dependent. If command is absent, then it returns nonzero if a shell is available and zero otherwise.

os.exit ([code])

Calls the C function exit, with an optional code, to terminate the host program. The default value for code is the success code.

os.getenv (varname)

Returns the value of the process environment variable varname, or nil if the variable is not defined.

os.remove (filename)

Deletes the file or directory with the given name. Directories must be empty to be removed. If this function fails, it returns nil, plus a string describing the error.

os.rename (oldname, newname)

Renames file or directory named oldname to newname. If this function fails, it returns nil, plus a string describing the error.

os.setlocale (locale [, category])

Sets the current locale of the program. locale is a string specifying a locale; category is an optional string describing which category to change: "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category is "all". The function returns the name of the new locale, or nil if the request cannot be honored.

If locale is the empty string, the current locale is set to an implementation-defined native locale. If locale is the string "C", the current locale is set to the standard C locale.

When called with nil as the first argument, this function only returns the name of the current locale for the given category.

os.time ([table])

Returns the current time when called without arguments, or a time representing the date and time specified by the given table. This table must have fields year, month, and day, and may have fields hour, min, sec, and isdst (for a description of these fields, see the os.date function).

The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the number of seconds since some given start time (the "epoch"). In other systems, the meaning is not specified, and the number returned by time can be used only as an argument to date and difftime.

os.tmpname ()

Returns a string with a file name that can be used for a temporary file. The file must be explicitly opened before its use and explicitly removed when no longer needed.

On some systems (POSIX), this function also creates a file with that name, to avoid security risks. (Someone else might create the file with wrong permissions in the time between getting the name and creating the file.) You still have to open the file to use it and to remove it (even if you do not use it).

When possible, you may prefer to use io.tmpfile, which automatically removes the file when the program ends.

5.9 - The Debug Library

This library provides the functionality of the debug interface to Lua programs. You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of these functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.

All functions in this library are provided inside the debug table. All functions that operate over a thread have an optional first argument which is the thread to operate over. The default is always the current thread.

debug.debug ()

Enters an interactive mode with the user, running each string that the user enters. Using simple commands and other debug facilities, the user can inspect global and local variables, change their values, evaluate expressions, and so on. A line containing only the word cont finishes this function, so that the caller continues its execution.

Note that commands for debug.debug are not lexically nested within any function, and so have no direct access to local variables.

debug.getfenv (o)

Returns the environment of object o.

debug.gethook ([thread])

Returns the current hook settings of the thread, as three values: the current hook function, the current hook mask, and the current hook count (as set by the debug.sethook function).

debug.getinfo ([thread,] function [, what])

Returns a table with information about a function. You can give the function directly, or you can give a number as the value of function, which means the function running at level function of the call stack of the given thread: level 0 is the current function (getinfo itself); level 1 is the function that called getinfo; and so on. If function is a number larger than the number of active functions, then getinfo returns nil.

The returned table can contain all the fields returned by lua_getinfo, with the string what describing which fields to fill in. The default for what is to get all information available, except the table of valid lines. If present, the option 'f' adds a field named func with the function itself. If present, the option 'L' adds a field named activelines with the table of valid lines.

For instance, the expression debug.getinfo(1,"n").name returns a table with a name for the current function, if a reasonable name can be found, and the expression debug.getinfo(print) returns a table with all available information about the print function.

debug.getlocal ([thread,] level, local)

This function returns the name and the value of the local variable with index local of the function at level level of the stack. (The first parameter or local variable has index 1, and so on, until the last active local variable.) The function returns nil if there is no local variable with the given index, and raises an error when called with a level out of range. (You can call debug.getinfo to check whether the level is valid.)

Variable names starting with '(' (open parentheses) represent internal variables (loop control variables, temporaries, and C function locals).

debug.getmetatable (object)

Returns the metatable of the given object or nil if it does not have a metatable.

debug.getregistry ()

Returns the registry table (see §3.5).

debug.getupvalue (func, up)

This function returns the name and the value of the upvalue with index up of the function func. The function returns nil if there is no upvalue with the given index.

debug.setfenv (object, table)

Sets the environment of the given object to the given table. Returns object.

debug.sethook ([thread,] hook, mask [, count])

Sets the given function as a hook. The string mask and the number count describe when the hook will be called. The string mask may have the following characters, with the given meaning:

  • "c": the hook is called every time Lua calls a function;
  • "r": the hook is called every time Lua returns from a function;
  • "l": the hook is called every time Lua enters a new line of code.

With a count different from zero, the hook is called after every count instructions.

When called without arguments, debug.sethook turns off the hook.

When the hook is called, its first parameter is a string describing the event that has triggered its call: "call", "return" (or "tail return", when simulating a return from a tail call), "line", and "count". For line events, the hook also gets the new line number as its second parameter. Inside a hook, you can call getinfo with level 2 to get more information about the running function (level 0 is the getinfo function, and level 1 is the hook function), unless the event is "tail return". In this case, Lua is only simulating the return, and a call to getinfo will return invalid data.

debug.setlocal ([thread,] level, local, value)

This function assigns the value value to the local variable with index local of the function at level level of the stack. The function returns nil if there is no local variable with the given index, and raises an error when called with a level out of range. (You can call getinfo to check whether the level is valid.) Otherwise, it returns the name of the local variable.

debug.setmetatable (object, table)

Sets the metatable for the given object to the given table (which can be nil).

debug.setupvalue (func, up, value)

This function assigns the value value to the upvalue with index up of the function func. The function returns nil if there is no upvalue with the given index. Otherwise, it returns the name of the upvalue.

debug.traceback ([thread,] [message] [, level])

Returns a string with a traceback of the call stack. An optional message string is appended at the beginning of the traceback. An optional level number tells at which level to start the traceback (default is 1, the function calling traceback).

6 - Lua Stand-alone

Although Lua has been designed as an extension language, to be embedded in a host C program, it is also frequently used as a stand-alone language. An interpreter for Lua as a stand-alone language, called simply lua, is provided with the standard distribution. The stand-alone interpreter includes all standard libraries, including the debug library. Its usage is:

     lua [options] [script [args]]

The options are:

  • -e stat: executes string stat;
  • -l mod: "requires" mod;
  • -i: enters interactive mode after running script;
  • -v: prints version information;
  • --: stops handling options;
  • -: executes stdin as a file and stops handling options.

After handling its options, lua runs the given script, passing to it the given args as string arguments. When called without arguments, lua behaves as lua -v -i when the standard input (stdin) is a terminal, and as lua - otherwise.

Before running any argument, the interpreter checks for an environment variable LUA_INIT. If its format is @filename, then lua executes the file. Otherwise, lua executes the string itself.

All options are handled in order, except -i. For instance, an invocation like

     $ lua -e'a=1' -e 'print(a)' script.lua

will first set a to 1, then print the value of a (which is '1'), and finally run the file script.lua with no arguments. (Here $ is the shell prompt. Your prompt may be different.)

Before starting to run the script, lua collects all arguments in the command line in a global table called arg. The script name is stored at index 0, the first argument after the script name goes to index 1, and so on. Any arguments before the script name (that is, the interpreter name plus the options) go to negative indices. For instance, in the call

     $ lua -la b.lua t1 t2

the interpreter first runs the file a.lua, then creates a table

     arg = { [-2] = "lua", [-1] = "-la",
             [0] = "b.lua",
             [1] = "t1", [2] = "t2" }

and finally runs the file b.lua. The script is called with arg[1], arg[2], ··· as arguments; it can also access these arguments with the vararg expression '...'.

In interactive mode, if you write an incomplete statement, the interpreter waits for its completion by issuing a different prompt.

If the global variable _PROMPT contains a string, then its value is used as the prompt. Similarly, if the global variable _PROMPT2 contains a string, its value is used as the secondary prompt (issued during incomplete statements). Therefore, both prompts can be changed directly on the command line or in any Lua programs by assigning to _PROMPT. See the next example:

     $ lua -e"_PROMPT='myprompt> '" -i

(The outer pair of quotes is for the shell, the inner pair is for Lua.) Note the use of -i to enter interactive mode; otherwise, the program would just end silently right after the assignment to _PROMPT.

To allow the use of Lua as a script interpreter in Unix systems, the stand-alone interpreter skips the first line of a chunk if it starts with #. Therefore, Lua scripts can be made into executable programs by using chmod +x and the #! form, as in

     #!/usr/local/bin/lua

(Of course, the location of the Lua interpreter may be different in your machine. If lua is in your PATH, then

     #!/usr/bin/env lua

is a more portable solution.)

7 - Incompatibilities with the Previous Version

Here we list the incompatibilities that you may find when moving a program from Lua 5.0 to Lua 5.1. You can avoid most of the incompatibilities compiling Lua with appropriate options (see file luaconf.h). However, all these compatibility options will be removed in the next version of Lua.

7.1 - Changes in the Language

  • The vararg system changed from the pseudo-argument arg with a table with the extra arguments to the vararg expression. (See compile-time option LUA_COMPAT_VARARG in luaconf.h.)
  • There was a subtle change in the scope of the implicit variables of the for statement and for the repeat statement.
  • The long string/long comment syntax ([[string]]) does not allow nesting. You can use the new syntax ([=[string]=]) in these cases. (See compile-time option LUA_COMPAT_LSTR in luaconf.h.)

7.2 - Changes in the Libraries

  • Function string.gfind was renamed string.gmatch. (See compile-time option LUA_COMPAT_GFIND in luaconf.h.)
  • When string.gsub is called with a function as its third argument, whenever this function returns nil or false the replacement string is the whole match, instead of the empty string.
  • Function table.setn was deprecated. Function table.getn corresponds to the new length operator (#); use the operator instead of the function. (See compile-time option LUA_COMPAT_GETN in luaconf.h.)
  • Function loadlib was renamed package.loadlib. (See compile-time option LUA_COMPAT_LOADLIB in luaconf.h.)
  • Function math.mod was renamed math.fmod. (See compile-time option LUA_COMPAT_MOD in luaconf.h.)
  • Functions table.foreach and table.foreachi are deprecated. You can use a for loop with pairs or ipairs instead.
  • There were substantial changes in function require due to the new module system. However, the new behavior is mostly compatible with the old, but require gets the path from package.path instead of from LUA_PATH.
  • Function collectgarbage has different arguments. Function gcinfo is deprecated; use collectgarbage("count") instead.

7.3 - Changes in the API

  • The luaopen_* functions (to open libraries) cannot be called directly, like a regular C function. They must be called through Lua, like a Lua function.
  • Function lua_open was replaced by lua_newstate to allow the user to set a memory-allocation function. You can use luaL_newstate from the standard library to create a state with a standard allocation function (based on realloc).
  • Functions luaL_getn and luaL_setn (from the auxiliary library) are deprecated. Use lua_objlen instead of luaL_getn and nothing instead of luaL_setn.
  • Function luaL_openlib was replaced by luaL_register.
  • Function luaL_checkudata now throws an error when the given value is not a userdata of the expected type. (In Lua 5.0 it returned NULL.)

8 - The Complete Syntax of Lua

Here is the complete syntax of Lua in extended BNF. (It does not describe operator precedences.)

    chunk ::= {stat [`;´]} [laststat [`;´]]

    block ::= chunk

    stat ::=  varlist `=´ explist |
         functioncall |
         do block end |
         while exp do block end |
         repeat block until exp |
         if exp then block {elseif exp then block} [else block] end |
         for Name `=´ exp `,´ exp [`,´ exp] do block end |
         for namelist in explist do block end |
         function funcname funcbody |
         local function Name funcbody |
         local namelist [`=´ explist]

    laststat ::= return [explist] | break

    funcname ::= Name {`.´ Name} [`:´ Name]

    varlist ::= var {`,´ var}

    var ::=  Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name

    namelist ::= Name {`,´ Name}

    explist ::= {exp `,´} exp

    exp ::=  nil | false | true | Number | String | `...´ | function |
         prefixexp | tableconstructor | exp binop exp | unop exp

    prefixexp ::= var | functioncall | `(´ exp `)´

    functioncall ::=  prefixexp args | prefixexp `:´ Name args

    args ::=  `(´ [explist] `)´ | tableconstructor | String

    function ::= function funcbody

    funcbody ::= `(´ [parlist] `)´ block end

    parlist ::= namelist [`,´ `...´] | `...´

    tableconstructor ::= `{´ [fieldlist] `}´

    fieldlist ::= field {fieldsep field} [fieldsep]

    field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp

    fieldsep ::= `,´ | `;´

    binop ::= `+´ | `-´ | `*´ | `/´ | `^´ | `%´ | `..´ |
         `<´ | `<=´ | `>´ | `>=´ | `==´ | `~=´ |
         and | or

    unop ::= `-´ | not | `#´

Last update: Wed Sep 10 09:22:34 BRT 2008