Lua Scripting für Train SImulator/Debug Output und file format

Discord Einladung
Trete unserem Discord-Server bei (klicke hier zum Beitreten).
  • Liebe Community!


    Ich habe vor, mich ins Lua Scripting für den Train Sim einzuarbeiten. Programmiererfahrung habe ich bereits in Java und C#, also gilt es für Lua nur mit der neuen Syntax umzugehen. Ich habe mir bereits die zwei verfügbaren Tutorials zum Lua Scripting angesehen, die sind jedoch sehr allgemein und gehen nicht auf den Train Sim ein. Für den Anfang wollte ich das Script eines bereits funktionierten Fahrzeuges, dem RSSLO 4010, erneuern, da das Fahrzeug bereits existiert, der Funktionsumfang bisher recht einfach ist und grundsätzlich die Eigenschaften feststehen, es sind daher nur die .out files, also die verschlüsselten lua Scripte neu zu erstellen.


    Die originalen habe ich gesichert und dem ,;Create an Engine" Tutorial von den Developer Documents (Developer Documents) folgend, habe ich ein neues SimpleEngineScript.lua File erstellt in der Location vom alten, damit ich den Speicherort nicht in der bin ändern muss. Für den Anfang wollte ich einfachen Debug Output für LogMate haben, damit ich einfach und schnell sehen kann, was für Auswirkungen meine Änderungen haben. Die Struktur habe ich dafür aus genanntem Tutorial genommen und sieht folgendermaßen aus:


    Code
    function Setup ()
        Print("[DEBUG] Script initialized.")
    end
    function Update (interval)
        local speed = SysCall("GetSpeed") * 3.6 -- m/s to km/h
        Print("[Speed] Current speed: " .. tostring(speed) .. " km/h")
    end

    Gespeichert habe ich das mit Notepad++ als .lua file, ich nehme nicht an, dass ich das file auch als .out file verschlüsseln muss während des Development Prozesses. Dem Thread (Lua-Script Print-Funktion) folgend, habe ich auch die Startoption hinzugefügt, wie am Screenshot erkennbar, im Logfile von LogMate habe ich jedoch keinen Debug output von meinem Code. Was ist hierbei das Problem? Was habe ich vergessen? Muss man das File doch verschlüsseln?


    Durch trial and Error habe ich auch im Script folder das Script_OBB4010.out file durch ein eigenes .lua fil eersetzt mit folgendem, leicht abweichenden Code:

    Code
    function Initialise()
        Print("[Init] Locomotive script loaded. From OBB4010.lua")
    end
    
    function Update(time)
        local speed = SysCall("GetSpeed") * 3.6 -- m/s to km/h
        Print("[Speed] Current speed: " .. tostring(speed) .. " km/h")
    end

    Nun habe ich tatsächlich Debug output von diesem File. Das bringt mich aber zu weiteren Fragen. Was ist nun die Aufgabe der SimpleEngineSimulation.lua im Vergleich zu der Script.lua? Wieso haben die Methoden, zumindest die zur Initialisierung, andere Signaturen?

    Einmal editiert, zuletzt von Transalpin4010 () aus folgendem Grund: Ein Beitrag von Transalpin4010 mit diesem Beitrag zusammengefügt.

  • Ahja das macht Sinn, danke vielmals. Während meiner weiteren Recherche bin ich hier im Rail Sim Forum auf die Liste der möglichen Methoden gekommen, ist die vollständig? Ich habe leider nichts zu dem Togglen von Animationen gefunden. Laut dem .bin file wäre für den Fahrschalter zum Beispiel die default Position auf 0.5, was ,,Aus" entspricht. Mittels der SetControlValue habe ich versucht per Script den Fahrschalter auch auf die Position zu setzen, im Simulator steht der Fahrschalter im f4 hud auch auf der richtigen Position, nur das 3d Schaltrad steht auf 0. Gibt es da eine gute Möglichkeit, den Fahrschalter in der Initialisierung auch im 3d Modell auf die richtige Position zu stellen?


    Eine eher Pfusch Möglichkeit wäre, kurz nach der Initialisierung die Animation über einen Zeitraum in die Position laufen zu lassen und nachdem man tatsächlich sieht, wie sich das Rad dreht, wenn man die Standard Version des Scriptes hat, nehme ich an, dass RSSLO das auch so gemacht hat, aber ich bin mir auch da mit den möglichen Methoden nicht ganz sicher, wie das am besten geht.


    Dazu stellt sich mir auch die Frage, woher finde ich den Childname? In der .GeoPcDx gibt es zwar diverse <Child> tags, die über TransformIds mit Transforms verbunden sind, die passende Namen tragen würden und auch in der .bin finde ich zum Beispiel den ElementName Vleka für den VirtualThrottle, wenn ich aber zum Beispiel pos = Call("Vleka:getNearPosition") verwende um zu Debuggen, ob das das richtige Element ist bzw. Call("Vleka:SetTime", "Vleka", 0.5) um die Animation zu starten, passiert nichts, bzw. wenn ich pos printen will, bekomme ich nur einen Error, weil es wohl nil ist.

  • Die Developer Docs und die dortige Scripting Function Reference enthält die von Dir gesuchten Beschreibungen.


    Ansonsten guck Dir die Skripte vom Kuju-Rollmaterial an, die sind nicht verschlüsselt. Damit hast Du aber ein Grundangebot an Funktionen, die Du erweitern kannst.

    Es gibt auch ein paar andere unverschlüsselte Skripte, bei denen man ein Verständnis für diese spezielle Art von Skript entwickeln kann.


    Es gibt zB Funktionen des Rollmaterials, bei dem Du Dich an eine bestimmte Namensgebung halten musst um diese im TSC eingebaute Funktionen nutzen zu können.

    Bei anderen Ideen und Konzepten bewirkt das Zusammenspiel von Objekt, Animation und Script das gewünschte Verhalten.


    Die Verbindung zwischen Script und Child erfolgt über die dazugehörige Engine.xml. Dort findest Du die Namen der Childs und die Verknüpfung zum Modell im Bereich "ContainerComponent". Guck Dir dort unbedingt auch den Bereich "ControlContainerComponent" an, um das Zusammenspiel besser nachvollziehen zu können.


    Deine letzten beiden Beispiele könnten nur dann funktionieren, wenn es das Child "Vleka" geben würde. Um eine Animation ablaufen zu lassen, musst Du den Aufruf anders gestalten:


    Call("[Animationsobjekt]:AddTime", "[Animationsname]", time)


    Viel Erfolg *hi*


    PS und Update:

    Open NEC

    Hier gibt es ein Projekt für Updates zu Rollmaterial aus New York und dazugehörigen Strecken. Hier auf der Seite kannst Du lt. Beschreibung auch die Source-Dateien herunterladen und gucken, wie die Skripte aufgebaut sind.

    Hier der Link zum Projekt.

    Einmal editiert, zuletzt von SeKu () aus folgendem Grund: Update zum Projekt Open NEC

  • Bedenke auch dass der Fahrschalter oft per InputMapper über eine "VirtualThrottle" (Name frei wählbar) ControlValue gesteuert wird, die vom Skript verarbeitet wird und welches seinen Output an den eigentlichen Core "Regulator" ControlValue weitergibt der dann die Lok steuert. Wenn du jetzt per Skript aber den "Regulator" auf einen Wert setzt kriegt der virtuelle Regler den du siehst davon nix mit da der Core Regulator ja nur Eingabe kriegt aber selbst nicht zurückfunken kann, das gibt dann eine schlagartige Hebelbewegung wenn du ihn anrührst.


    Interessant sind Armstrong Powerhouse Skripte, die sind fast alle unverschlüsselt und eine gute Lernquelle. Wie man zum Beispiel Fliegen auf die Scheibe kriegt :D

  • Danke für die ganzen hilfreichen Antworten, mangels Autoabo vom Thread hab ich die jetzt erst sehr spät gesehen. Kuju Skripte habe ich mir bereits ein paar angeschaut und auch ein paar andere, unter anderem das vom RSSLO 4010er, das ich ja rekonstruieren, am besten verbessern, will und obwohl dabei zwar die Methodennamen verloren gehen, ist das auch sehr praktisch zum reverse Engineeren. Die Skripte von AP werde ich mir auf jeden Fall noch anschauen.

    Anschließend an meinen anderen Thread: Werden in den Skript files, nicht dem SimpleEngineScript, weil das ist zu 90% tatsächlich leer, alle 4 Basic Methoden, also die Initialise, Setup, Update und ControlValueChange aufgerufen theoretisch oder nur bestimmte bzw. gibt es Voraussetzungen dafür, dass eine Methode aufgerufen wird, also dass ich das Fahrzeug zb Bewegen muss oder so?



    Daran anschließend, kann man im Train Simulator statt lua jetzt auch TypeScript verwenden? Ich habe mir den Sourcecode heruntergeladen, die Scripte haben dort aber alle .ts Endung, das verwirrt mich etwas.

  • Transalpin4010,


    die letzte Frage zuerst beantwortet: kann ich Dir nicht sagen, aber die Umstellung im Projekt auf Typescript ist erst mit der Umstellung auf Version 2.0 erfolgt. Wie da die Einbindung erfolgt habe ich mir nicht angeguckt. Aber Du könntest Dir die Version 1.1.1 angucken, das ist die letzte Version in LUA. Ich vermute aber dass Du bei AP, wie von Spikee1975 beschrieben, fündig wirst.


    Ansonsten würde ich gerne vorschlagen, dass Du mit Deinen Fragen in einem Thread bleibst, damit andere Forumsmitglieder die Informationen nicht zusammensuchen müssen, wenn Sie vor ähnlichen Problemen stehen wie Du.


    Dein anderes Problem besteht, weil hier im WIKI die LUA Scriptreferenz fehlerhaft oder falsch beschrieben ist, es fehlt bei Dir in der Funktion "Initialise()" die Anweisung "Call( "BeginUpdate" )"

    Hier ist mal ein Beispiel für eine minimalistisch umgesetzte Engine.XML:

    2 Mal editiert, zuletzt von SeKu () aus folgendem Grund: kleine Anpassungen und Verbesserungen

  • Danke dir vielmals, das macht sehr viel Sinn. Eine Verständnisfrage noch zur onControlValueChange, wieso muss man nochmal SetControlValue mit dem gleichen Namen, index und value aufrufen? So wie ich das verstanden habe, passiert der Aufruf für die OnControlValueChange ja weil der value für das objekt mit dem Namen und dem index geändert wurde oder nicht?

  • Hier bin ich mir nicht ganz sicher, freue mich über eine Berichtigung, wenn es jemand besser oder richtig erklären kann.


    Ich vermute, habe aber nicht getestet, dass ohne die Übergabe über die Funktion OnControlValueChange() sich einfach nix an deinem Rollmaterial bewegt. Sprich die Funktion wird getriggert, weil sich überhaupt ein ControlValue verändert hat und die Übergabe an dieser Stelle ist notwendig um das gewünschte Verhalten am Rollmaterial tatsächlich umzusetzen. Hier sind einige Funktionen des Rollmaterials fest einprogrammiert und können durch den Einsatz von VirtualControls auch wieder verändert werden.

    Du kannst an dieser Stelle ansetzen und eigenes Verhalten einbauen. Zum Beispiel ein Ventilator, den Du in Blender erstellst, animierst und als Child einfügst, kannst Du hier an- und abschalten.