Immernoch kein Plan wos langgeht

This commit is contained in:
Nero 2022-06-21 22:27:51 +00:00
parent 203a7913a2
commit 43f1451de1

View File

@ -1,13 +1,59 @@
require("Prototype")
require("On")
-- Tabelle in einen String umwandeln, rekursiv
-- Funktionswerte werden ignoriert
function __tostring(self)
local t=type(self)
if t=="table" then
local r=""
-- load and sort table keys
local tkeys={}
for k in pairs(self) do table.insert(tkeys, k) end
table.sort(tkeys, function(a,b) return tostring(a)<tostring(b) end)
-- iterate over our table
for _,k in ipairs(tkeys) do
local v = __tostring(self[k])
-- ignore nil values, they unset the key anyways
if v~= nil and v ~= "nil" then
if r~="" then r=r.."," end
-- short format: foo="bar", saves bytes
if type(k)=="string" and k:match("^[%l%u_][%w_]*$") then
r=r..k.."="..v
-- long format: ["foo"]="bar", allows weird keys
else
r=r.."["..__tostring(k).."]="..v
end
end
end
return "{"..r.."}"
elseif t=="number" or t=="boolean" then
return tostring(self)
elseif t=="string" then
return ("%q"):format(self)
else
return "nil"
end
end
-- Da wir jetzt ohnehin Tabellen in Strings umwandeln koennen, patchen wir
-- print(...) damit diese von dieser Darstellung profitieren kann.
do
local oldprint=print
function print(...)
local args={...}
for i=1,#args do
if type(args[i]) == "table" then
args[i]=__tostring(args[i])
end
end
oldprint(table.unpack(args))
end
end
-- Tabelle in beliebigen Slot speichern
-- Im Slot steht dann eine Lua-Tabelle als String
-- Formatierungszeichen werden soweit URL-encoded,
-- dass EEP mit Formatierungszeichen keine Probleme mehr hat
-- Speziell hochkommas haben mir immer meine Daten abgeschnitten...
-- Formatierungszeichen werden URL-encoded, damit EEP mit ihren zurecht kommt
-- Speziell Hochkommas haben mir immer meine Daten abgeschnitten...
function speicherTabelle(Slotnummer, Tabelle)
local s=Prototype.__tostring(Tabelle):gsub("([%c%%\"])", function(c)
local s=__tostring(Tabelle):gsub("([%c%%\"])", function(c)
return string.format("%%%02X", string.byte(c))
end)
EEPSaveData(Slotnummer, s)
@ -26,380 +72,252 @@ function ladeTabelle(Slotnummer)
end))()
end
-- KsKit merkt sich, welche Zuege vor einem Signal stehen
-- Die Tabelle wird einmal beim Lua-Start gelesen
-- und nach Aenderungen wieder zurueck geschrieben
-- Slot 960 ist damit durch KsKit blockiert!
Zugmeldung_Slotnummer = 960
Zugmeldung = ladeTabelle(Zugmeldung_Slotnummer)
-- Hier werden Zuglenker je nach Fahrstrassen-Startsignal sortiert gesammelt
Zuglenkfunktionen = {}
-- Neuen Zuglenker installieren:
-- Zuglenker schalten unter bestimmten Bedingungen automatisch Fahrstrassen
function Zuglenkung(Tab)
local FS = Tab[1]
Tab[1]=nil
if Zuglenkfunktionen[FS] == nil then Zuglenkfunktionen[FS]={} end
table.insert(Zuglenkfunktionen[FS], function(Zugname, Ankunft)
local ziel = 2
if Tab.Ziele then
ziel = Tab.Ziele(math.random(#Tab.Ziele))
function AnimiereFahrzeugStromabnehmer(Fahrzeug, Richtung)
local Index, _ = Fahrzeug:gsub(";%d*$","")
local Angelegt = false
if Stromabnehmer[Index] then
local Achsen = Stromabnehmer[Index]
for i=1,#Achsen do
if (i == 1 and Richtung == -1) or (i == #Achsen and Richtung == 1) then
EEPRollingstockSetAxis(Fahrzeug, Achsen[i], 100)
Angelegt = true
else
EEPRollingstockSetAxis(Fahrzeug, Achsen[i], 0)
end
end
return ziel
end)
end
return Angelegt
end
-- EEPMain-Komponente der Zuglenkung
Main(function()
local FS = {}
-- Teste, ob an einem Signal Fahrstrassen und Zuglenkung existieren
-- Subfunktion, wird beim Sammeln der Fahrstrassen-Signale mehrfach aufgerufen
local VersucheAnSignal = function(Signal, Zugname, Ankunft)
if Signal == nil then return end
if Signale[Signal] == nil then return end
if Signale[Signal].FS == nil then return end
local FSignal = Signale[Signal].FS
if EEPGetSignal(FSignal) == 1 and Zuglenkfunktionen[FSignal] then
table.insert(FS, {FSignal, Zugname, Ankunft})
-- Richtung: -1, 0 oder 1
function AnimiereZugStromabnehmer(Zug, Richtung)
local AnzahlFahrzeuge = EEPGetRollingstockItemsCount(Zug)
local Startwert = 1
local Endwert = AnzahlFahrzeuge
local Schritt = 1
if Richtung > 0 then
Startwert = AnzahlFahrzeuge
Endwert = 1
Schritt = -1
end
for i=Startwert,Endwert,Schritt do
local Fahrzeug = EEPGetRollingstockItemName(Zug, i-1)
local ok, Vorwaerts = EEPRollingstockGetOrientation(Fahrzeug)
if ok and not Vorwaerts then
if AnimiereFahrzeugStromabnehmer(Fahrzeug, -1 * Richtung) then Richtung = 0 end
else
if AnimiereFahrzeugStromabnehmer(Fahrzeug, Richtung) then Richtung = 0 end
end
end
end
-- Sammle alle Fahrstrassen-Signale, die geschaltet werden koennen
-- Einmal die, wo direkt ein Zug in Anfahrt ist
-- Und einmal die, wo der Zug gerade das "Halt erwarten" am vorherigen Signal sieht
-- Zugname und Ankunftszeit merken
for k,v in pairs(Signale) do
if Zugmeldung[k] and v.FS then
local Begriff = v:Lese()
if Begriff[1] == HALT then
VersucheAnSignal(k, Zugmeldung[k][1], Zugmeldung[k][3])
elseif Begriff[1] == FAHRT and Begriff.H_erwarten and v.FF then
local Ziel = EEPGetSignal(v.FS) - 1
if v.FF[Ziel] then
VersucheAnSignal(v.FF[Ziel], Zugmeldung[k][1], Zugmeldung[k][3])
end
end
end
end
-- Zuglenker abarbeiten, moegliche Fahrstrassenstellungen sammeln
local FSStellungen = {}
for i=1,#FS do
local FSignal = FS[i][1]
local Zugname = FS[i][2]
local Ankunft = FS[i][3]
for j=1, #Zuglenkfunktionen[FSignal] do
local ziel = Zuglenkfunktionen[FSignal][j](Zugname,Ankunft)
if type(ziel) == "number" and ziel > 1 then
table.insert(FSStellungen,{FSignal,ziel})
end
end
end
-- Eine einzelne Fahrstrassenstellung mittels EEPSetSignal abarbeiten
-- Diese wird zufaellig ausgewaehlt, damit haben wir sowohl bei Verzweigungen und Zusammenfuehrungen
-- automatisch Abwechslung, soweit es die Zuglenker erlauben
-- Das wir nur eine Fahrstrasse schalten ist nicht schlimm, wir werden ja 5 mal pro Sekunde ausgefuehrt
-- Beim naechsten mal kann man dann aber via EEPGetSignal() sehen, was wir an Fahrstrassen nicht mehr zu schalten brauchen
if #FSStellungen >= 1 then
local FS, Ziel = table.unpack(FSStellungen[math.random(#FSStellungen)])
-- Wichtig: Callbacks aktivieren, damit Mehrabschnittssignale ueber ihren Nachfolger informiert werden
EEPSetSignal(FS, Ziel, 1)
end
end)
-- Basis-Prototyp fuer alle Signale
Signal=Prototype{}
-- Konstanten fuer Signalbegriffe
-- KsKit benutzt ein eigenes Format, um Signalbegriffe abzubilden
-- Dabei handelt es sich um eine Tabelle mit folgenden Schluesseln:
-- - 1: Grundsaetzlicher Typ von Begriffen, Fahrt ist 1, Halt ist 2
-- - V_max: nil oder number, Maximalgeschwindigkeit falls angezeigt
-- - H_erwarten: nil oder true, falls Begriff "Halt Erwarten" signalisiert
-- - V_erwarten: nil oder number, falls Begriff eine Geschwindigkeit vorsignalisiert
-- V_max und V_erwarten entsprechen absichtlich der Aufteilung der Zusatzanzeiger am Ks-Signal.
-- Gegen Ende der Datei sind extensiv Signalbegriffe als eigene Konstanten definiert
-- Grundsätzliche Typen von Signalbildern
FAHRT=1
HALT=2
RANGIERFAHRT=3
ERSATZFAHRT=4
AUS=5
-- Achtung: Keine Methode, Zugriff via einfachen Punkt, nicht Doppelpunkt
-- Wandelt einen Begriff in eine Textuelle Beschreibung um
-- Es lohnt sich, diesen Text im Signal-Tooltip anzuzeigen
-- Hl-Signale sind zwar huebsch, aber nicht immer einfach zu lesen
function Signal.BegriffZuText(Begriff)
if Begriff[1]==HALT then return "Halt" end
if Begriff[1]==RANGIERFAHRT then return "Rangierfahrt" end
if Begriff[1]==ERSATZFAHRT then return "Fahrt auf Ersatzsignal" end
if Begriff[1]==AUS then return "Signal ausgeschaltet" end
local txt = "Fahrt"
if Begriff.V_max then
txt = txt.." mit "..tostring(Begriff.V_max).." km/h"
function leseSignal(Signal)
if EEPGetSignal(Signal) == 1 then
return {FAHRT}
else
return {HALT}
end
if Begriff.H_erwarten ~= nil then
txt = txt..", Halt erwarten"
if Begriff.kurz ~= nil then
txt = txt.." im verkürzten Abstand"
end
local GefundeneSignale={}
local Zugaktionen={}
setmetatable(Zugaktionen, {
__index=function(table, key)
table[key]={}
return table[key]
end
})
function KsKitInit()
GefundeneSignale={}
Zugaktionen=ladeTabelle(1)
for Signal=1,1000 do
if EEPGetSignal(Signal) > 0 and EEPGetSignal(Signal+1000) > 0 then
table.insert(GefundeneSignale, Signal)
end
end
if Begriff.V_erwarten then
txt = txt..", "..tostring(Begriff.V_erwarten).." km/h erwarten"
end
return txt
end
-- Alle Signale vor EEP5 konnten nur diese beiden Begriffe
Signal.Begriffe={{FAHRT},{HALT}}
for i=1,#GefundeneSignale do
local Signal = GefundeneSignale[i]
EEPRegisterSignal(Signal)
_G["EEPOnSignal_"..tostring(Signal)]=function(Stellung)
-- Text fuer einen potentiellen Tooltip generieren
function Signal:TooltipText()
local Begriff = self:Lese()
local col=1
local bgcol = "255,0,0"
if Begriff[1]~=HALT then col=2 end
if Begriff[1]==FAHRT and Begriff.V_max == nil and not Begriff.H_erwarten then col=3 end
local fgcol={"255,255,255","0,0,0","0,0,0"}
local bgcol={"255,0,0","255,255,0","0,255,0"}
r="<c><b><bgrgb="..bgcol[col].."><fgrgb="..fgcol[col]..">"..self.BegriffZuText(Begriff).."<bgrgb=255,255,255></b>"
if Zugmeldung[self.ID] then
r=r.."\n<c>"..Zugmeldung[self.ID][1]
end
return r
end
-- Wird derzeit nicht genutzt, das war so gedacht, das im Tooltip dann "Rangiersignal" oder "Ausfahrsignal" steht
-- Hinterher war mir der Platz im Tooltip aber dann zu schade
-- Wenn hier vom User sowas wie "Einfahrsignal aus Richtung Nossen" eingetragen wird, ware das sicher nuetzlich
Signal.Beschreibung="Signal"
function Signal:set_Beschreibung(v)
self.Beschreibung=v
end
-- Neue Signale werden mit Signal{...} vom Prototyp abgeleitet
-- Die Optionen werden durch set_$schluessel Setter geleitet.
-- Gibt es einen Setter nicht, gibt es einen harten Fehler - hier vertippt sich keiner mehr, auch ich nicht.
function Signal:init(tab)
for k,v in pairs(tab) do
local setter = "set_"..tostring(k)
if type(self[setter]) == "function" then
self[setter](self, v)
else
error("Signaleigenschaft "..k.." hier nicht erlaubt")
end
EEPRegisterSignal(Signal+1000)
_G["EEPOnSignal_"..tostring(Signal+1000)]=function(FStellung)
if FStellung > 1 then
print("Fahrstrasse ",string.format("%04d-%02d", Signal+1000, FStellung-1)," geschalten")
end
end
end
end
-- Setter fuer Signal-ID. Die selbe ID, wie auch fur EEPGetSignal und EEPSetSignal genutzt wird.
-- Die steht ganz am Anfang in der Tabelle vom Init-Aufruf und hat keinen String als Schluessel.
-- Ab hier ist auch die exakte ID unseres Signales bekannt, deswegen werden Globale Funktionen mit der ID im Namen ebenfalls hier definiert.
-- Koennte man aber auch spaeter machen.
function Signal:set_1(id)
-- Globale Tabelle wo alle Signale drinnestehen
-- So merkt man besser wenn man eine ID zweimal vergibt
-- Die Signale-Tabelle wird auch benoetigt, damit Mehrabschnittssignale ueber die ID ihres Folgesignales den Begriff dessen lesen koennen.
if type(Signale) ~= "table" then Signale={} end
if Signale[id]~=nil then error("Signal ID "..id.." bereits verwendet") end
if type(id) ~= "number" then error("Signal ID muss eine Zahl sein") end
self.ID = id
Signale[id]=self
-- Anfahrtkontakt: Wir merken uns, das ein Zug an dieses Signal heranfaehrt.
-- Die Zuglenkung wertet diese Informationen aus
_G["Anfahrt_"..tostring(self.ID)]=function(Zugname)
local ok, Speed = EEPGetTrainSpeed(Zugname)
-- Derzeitige Fahrtrichtung ermitteln
local Richtung = 1
if Speed < 0 then Richtung = -1 end
-- Ankündigung an den User
--print(Zugname," an: ",self.Beschreibung," ",self.ID, ", V=",math.ceil(Speed))
-- Zuganmeldung speichern
Zugmeldung[self.ID]={Zugname, Richtung, EEPTime}
speicherTabelle(Zugmeldung_Slotnummer, Zugmeldung)
end
-- Wird ein Signal auf Halt gestellt, gehen wir davon aus, das der Zug, der bisher hier Stand, jetzt weg ist.
-- Damit kann durch einen Haltkontakt die Zugmeldung aufgeloest werden.
-- Liegengebliebende Zugmeldungen koennen damit auch durch Toggeln des Signales geloescht werden
OnSignal(self.ID, function(Stellung)
if self.Begriffe[Stellung][1] == HALT then
Zugmeldung[self.ID]=nil
speicherTabelle(Zugmeldung_Slotnummer, Zugmeldung)
end
end)
end
-- Der Konstruktor des jeweiligen Signaltypes fuettert die Stellungen des Signals hier rein
-- Das ist eine Liste von Begriffen im oben dokumentierten Tabellenformat
function Signal:set_Begriffe(Begriffe)
-- TODO: validieren das hier kein Mist reinkommt
self.Begriffe=Begriffe
end
-- Fahrstrassenstartsignal mit Signal verbinden
function Signal:set_FS(FS)
self.FS=FS
end
-- Folgesignale setzen
-- Der Wert ist eine Liste von Signal-IDs:
-- - Element 1 entspricht Folgesignal der ersten Fahrstrasse (Stellung 2)
-- - Element 2 entspricht dem Folgesignal der zweiten Fahrstrasse (Stellung 3)
-- - etc
-- Wird zum Vorsignalisieren genutzt
function Signal:set_FF(FF)
self.FF=FF
-- Callback fuer alle potentiellen Folgesignale eintragen
-- Wir mussen das ja hinterher ggf. vorsignalieren
for i=1,#FF do
if type(FF[i])=="number" and FF[i] > 0 then
OnSignal(FF[i], function()
self:UpdateVorsignalfunktion()
end)
function KsKitMain()
-- Signale abfragen, ob vielleicht ein Zug vor ihnen steht
for i=1,#GefundeneSignale do
local Signal = GefundeneSignale[i]
if EEPGetSignalTrainsCount(Signal) > 0 then
Zugname = EEPGetSignalTrainName(Signal, 1)
if not Zugaktionen[Zugname].S then
Zugaktionen[Zugname].S = Signal
end
end
end
end
-- Diese Funktion ist fuer Mehrabschnittssignale relevant
-- Ueber die FS und FF attribute koennen wir ableiten, welches Signal auf dieses folgt
-- Das lesen wir dann (geht nur, wenn es auch in KsKit eingetragen ist)
-- und basteln uns dann unsere eigenen Begriff zurecht
function Signal:UpdateVorsignalfunktion()
if self.FS == nil then return end -- Wir haben kein Fahrstrassensignal
if self.FF == nil then return end -- Wir haben keine Folgesignale
local FS_Ziel = EEPGetSignal(self.FS) - 1
if FS_Ziel < 1 then return end -- Fahrstrasse nicht geschaltet
local Folgesignal = self.FF[FS_Ziel]
local Begriff=self:Lese()
if Begriff[1] ~= FAHRT then return end
local Folgebegriff=Signale[Folgesignal]:Lese()
local NeuerBegriff = {FAHRT}
NeuerBegriff.V_max = Begriff.V_max
NeuerBegriff.V_erwarten = Folgebegriff.V_max
if Folgebegriff[1] == FAHRT then
NeuerBegriff.H_erwarten = nil
else
NeuerBegriff.H_erwarten = true
end
self:Zeige(NeuerBegriff)
end
-- Signalstellauftraege
local Schaltauftraege = {}
local SignalHaltegruende = {}
-- Signalbegriff lesen
-- Sehr trivial
function Signal:Lese()
return self.Begriffe[EEPGetSignal(self.ID)]
end
for Zugname, Data in pairs(Zugaktionen) do
local ok, V = EEPGetTrainSpeed(Zugname)
if ok then
local Haltegrund = "Kein Plan"
-- Signalbegriff setzen
-- Faktisch sortiert diese Funktion alle Begriffe je nachdem, wie gut sie der gesuchten Stellung entsprechen
-- Der erste (besten-passende) Begriff wird dann gesetzt
-- Die Funktion ist zwar saumaessig kompliziert, kann aber bei Geschwindigkeitsabstufungen auf gerigere Geschwindigkeiten zurueckfallen.
-- Speziell bei Hl-Signalen, die sich einen VS-Begriff fuer V40 und V60 teilen, ist das nuetzlich.
-- Bei Signalen mit einer sehr schlechten Auswahl an Begriffen kommt hier vielleicht Murks raus
-- Das sollte man vielleicht genauer testen
function Signal:Zeige(Stellung)
-- Achso, wir sortieren nicht die richtige Begriffstabelle, sondern eine Ersatztabelle mit den Indexen.
-- Ist performanter. Und wir zerschiessen uns nicht die Begriffstabelle, weil wir die ja per Referenz haben.
local order={}
for i=1,#self.Begriffe do
table.insert(order, i)
end
-- Sortieraufruf mit Sortierlabda
table.sort(order, function(a,b)
local StlgA = self.Begriffe[a]
local StlgB = self.Begriffe[b]
local props={1,"V_max","H_erwarten","V_erwarten"}
for i=1,#props do
-- Folgendes Muster: Wenn Stellung A und B sich in einem Merkmal unterscheiden
-- UND Stellung A in diesem Merkmal mit der Zielstellung uebereinstimmt,
-- DANN ist Stellung A besset geeignet, sonst nicht
-- Wir muessen das auch andersherum mit Stellung B machen
if StlgA[props[i]] ~= StlgB[props[i]] then
if StlgA[props[i]] == Stellung[props[i]] then return true end
if StlgB[props[i]] == Stellung[props[i]] then return false end
-- Muster: Geschwindigkeitsmerkmal ist vorhanden und kleiner als Ziel, aber der Vergleichsbegriff:
-- - zeigt das Merkmal gar nicht
-- - zeigt eine hohere Geschwindigkeit als gewollt
-- - zeigt eine noch kleinere Geschwindigkeit
-- Dann ist der Vergleichsbegriff schlechter geeignet
-- Und das dann jeweils in beide Richtungen
if i == 2 or i == 4 then -- 2 ist V_max, 4 ist V_erwarten
if StlgA[props[i]] and Stellung[props[i]] and StlgA[props[i]] < Stellung[props[i]] then
if StlgB[props[i]] == nil then return true end
if StlgB[props[i]] > Stellung[props[i]] then return true end
if StlgB[props[i]] < StlgA[props[i]] then return true end
-- Wenn wir stehen, merken wir uns unsere Ankunftszeit
if V > -5 and V < 5 then
if Zugaktionen[Zugname].A == nil then
Zugaktionen[Zugname].A = EEPTime
if Zugaktionen[Zugname].V then
EEPSetTrainSpeed(Zugname, 0)
if Zugaktionen[Zugname].R then
AnimiereZugStromabnehmer(Zugname, 0)
end
end
if StlgB[props[i]] and Stellung[props[i]] and StlgB[props[i]] < Stellung[props[i]] then
if StlgA[props[i]] == nil then return false end
if StlgA[props[i]] > Stellung[props[i]] then return false end
if StlgA[props[i]] < StlgB[props[i]] then return false end
end
-- Ankunftszeit loeschen falls wir unterwegs sind
elseif Zugaktionen[Zugname].A then
Zugaktionen[Zugname].A = nil
Zugaktionen[Zugname].S = nil
Zugaktionen[Zugname].R = nil
Zugaktionen[Zugname].V = nil
end
if Zugaktionen[Zugname].W then
Haltegrund = "Planhalt"
end
-- Wartezeit loeschen falls abgesessen
if Zugaktionen[Zugname].W and Zugaktionen[Zugname].A then
local Wartedauer = EEPTime - Zugaktionen[Zugname].A
if Wartedauer < 0 then
Wartedauer = Wartedauer + 24*60*60
end
if Wartedauer > Zugaktionen[Zugname].W then
Zugaktionen[Zugname].W = nil
end
end
-- Fahrstrasse schalten
if not Zugaktionen[Zugname].W and Zugaktionen[Zugname].S then
local ZSignal = Zugaktionen[Zugname].S
local FSignal = ZSignal + 1000
local Fahrstrassen = {}
if Zugaktionen[Zugname].FS then
Fahrstrassen = Zugaktionen[Zugname].FS
elseif Selbstblock_Default then
Fahrstrassen = {1}
end
if #Fahrstrassen > 0 then
if EEPGetSignal(FSignal) == 1 then
Schaltauftraege[FSignal] = 1+Fahrstrassen[math.random(#Fahrstrassen)]
end
Haltegrund = "FS angefordert"
end
end
-- Haltegrund merken, das wir ihn spaeter im Signal-Tooltip darstellen koennen
if Zugaktionen[Zugname].S then
SignalHaltegruende[Zugaktionen[Zugname].S] = Haltegrund
end
if Zugaktionen[Zugname].S then
local Begriff = leseSignal(Zugaktionen[Zugname].S)
if Begriff[1] ~= HALT then
if Zugaktionen[Zugname].V then
if Zugaktionen[Zugname].B and Zugaktionen[Zugname].B + 5 < EEPTime then
EEPSetTrainSpeed(Zugname, Zugaktionen[Zugname].V)
Zugaktionen[Zugname].V = nil
Zugaktionen[Zugname].B = nil
elseif not Zugaktionen[Zugname].B then
AnimiereZugStromabnehmer(Zugname, Zugaktionen[Zugname].V>0 and 1 or -1)
Zugaktionen[Zugname].B = EEPTime
Zugaktionen[Zugname].R = nil
end
else
Zugaktionen[Zugname].S = nil
end
end
end
else
-- Zug aus den Augen verloren...
Zugaktionen[Zugname]=nil
end
return false
end)
-- Begriff aktiv schalten... der Wert in unserer Indextabelle ist der Index in die Begriffstabelle
-- und damit auch genau der Wert, den EEP fuer die numerische Stellung braucht
EEPSetSignal(self.ID, order[1], 1)
return true
end
speicherTabelle(1, Zugaktionen)
EEPChangeInfoSignal(1, __tostring(Zugaktionen))
for k,v in pairs(Schaltauftraege) do
EEPSetSignal(k,v,1)
end
for i=1,#GefundeneSignale do
local Signal = GefundeneSignale[i]
if Aktiviere_Tooltips then
local name = string.format("%04d", Signal)
if Name and Name[Signal] then name=Name[Signal] end
local txt = "<c>Signal "..name
local Stellung = EEPGetSignal(Signal)
if Stellung == 1 then
txt = txt.."\n<c><b><fgrgb=0,0,0><bgrgb=0,255,0>Fahrt</b>"
else
txt = txt.."\n<c><b><fgrgb=255,255,255><bgrgb=255,0,0>Halt</b>"
end
txt = txt.."<fgrgb=0,0,0><bgrgb=255,255,255>"
local FStellung = EEPGetSignal(Signal+1000)
if FStellung > 1 then
txt = txt.."\n<c>".. string.format("FS #%02d", FStellung-1)
end
if SignalHaltegruende[Signal] then
txt = txt.."\n"..SignalHaltegruende[Signal]
end
EEPChangeInfoSignal(Signal, txt)
EEPShowInfoSignal(Signal, 1)
else
EEPShowInfoSignal(Signal, 0)
end
end
end
-- So, der Signal-Prototyp ist definiert! Jetzt definieren wir uns die ganzen Signalsysteme und jeweils ein paar Modelle dazu
function FS(...)
Zugaktionen[Zugname].FS = {...}
speicherTabelle(1, Zugaktionen)
end
-- Signalbilder OSJD/EZMG/Hl-Signale des Ostblocks
-- V_erwarten=60 wird durch V_erwarten=40 signalisiert
Hl1={FAHRT}
Hl2={FAHRT, V_max=100}
Hl3a={FAHRT, V_max=40}
Hl3b={FAHRT, V_max=60}
Hl4={FAHRT, V_erwarten=100}
Hl5={FAHRT, V_max=100, V_erwarten=100}
Hl6a={FAHRT, V_max=40, V_erwarten=100}
Hl6b={FAHRT, V_max=60, V_erwarten=100}
Hl7={FAHRT, V_erwarten=40}
Hl8={FAHRT, V_max=100, V_erwarten=40}
Hl9a={FAHRT, V_max=40, V_erwarten=40}
Hl9b={FAHRT, V_max=60, V_erwarten=40}
Hl10={FAHRT, H_erwarten=true}
Hl11={FAHRT, V_max=100, H_erwarten=true}
Hl12a={FAHRT, V_max=40, H_erwarten=true}
Hl12b={FAHRT, V_max=60, H_erwarten=true}
Hl13={HALT}
function W(Dauer)
Zugaktionen[Zugname].W = Dauer
speicherTabelle(1, Zugaktionen)
end
-- Zusatzsignale
Zs1={ERSATZFAHRT}
Ra10={HALT, Nur_Rangierfahrten=true} -- Rangierhalttafel
Ra11={HALT, Nur_Rangierfahrten=true} -- Wartezeichen
Sh1={RANGIERFAHRT} -- war Ra12 bei DR
function S(Signal)
Zugaktionen[Zugname].S = Signal
-- Geschwindigkeit fuer Weiterfahrt ermitteln
local _, V = EEPGetTrainSpeed(Zugname)
Zugaktionen[Zugname].V = math.floor(V)
speicherTabelle(1, Zugaktionen)
end
Rangierhalttafel=Signal{Begriffe={{FAHRT},Ra10},Beschreibung="Rangierhalttafel"}
-- V11NHK10024 HL-Signale der DR *V40* - Grundset
Hl_Signal_Ausfahrt_V40=Signal{Begriffe={Hl13,Hl1,Hl3a,Zs1,Sh1,Hl13},Beschreibung="Ausfahrsignal"}
Hl_Signal_Ausfahrt_Vmax=Signal{Begriffe={Hl13,Hl1,Zs1,Sh1,Hl13},Beschreibung="Ausfahrsignal"}
Hl_Signal_Block=Signal{Begriffe={Hl13,Hl1,Zs1,Hl13},Beschreibung="Blocksignal"}
Hl_Signal_Einfahrt_V40=Signal{Begriffe={Hl13,Hl1,Hl7,Hl10,Hl3a,Hl9a,Hl12a,Zs1,Hl13},Beschreibung="Einfahrsignal"}
Hl_Signal_Selbstblock=Signal{Begriffe={Hl13,Hl1,Hl10,Hl13},Beschreibung="Blocksignal"}
Hl_Signal_Vorsignal_V40=Signal{Begriffe={Hl10,Hl7,Hl1},Beschreibung="Vorsignal"}
Hl_Signal_Vorsignalwiederholer_V40=Signal{Begriffe={Hl10,Hl7,Hl1},Beschreibung="Vorsignalwdh"}
-- V11NHK10025 HL-Signale der DR *V60* - Erweiterungsset
Hl_Signal_Ausfahrt_V60=Signal{Begriffe={Hl13,Hl1,Hl3b,Hl3a,Zs1,Sh1,Hl13}, Beschreibung="Ausfahrsignal"}
Hl_Signal_Einfahrt_V60=Signal{Begriffe={Hl13,Hl1,Hl4,Hl7,Hl10,Hl3b,Hl6b,Hl9b,Hl12b,Hl3a,Hl6a,Hl9a,Hl12a,Zs1,Hl13}, Beschreibung="Einfahrsignal"}
-- V40 und V60 werden bei Hl gleich vorsignalisiert, keine Ahnung warum das ueberhaupt verschiedene Modelle hat
Hl_Signal_Vorsignal_V60=Hl_Signal_Vorsignal_V40
Hl_Signal_Vorsignalwiederholer_V60=Hl_Signal_Vorsignalwiederholer_V40
-- Bahnhofsset
Hl_Zwerg_Rangiersignal=Signal{Begriffe={Ra11,Sh1},Beschreibung="Rangierhaltsignal"}
-- Irgendein anderes set
Hl_Signal_AZ=Signal{Begriffe={Hl13,Hl1,Hl4,Hl7,Hl10,Hl3a,Hl9a,Hl6a,Hl12a,Sh1,Zs1,Hl13,{}}, Beschreibung="Ausfahrsignal"}
function R(Signal)
Zugaktionen[Zugname].S = Signal
-- Geschwindigkeit fuer Weiterfahrt ermitteln
local _, V = EEPGetTrainSpeed(Zugname)
Zugaktionen[Zugname].V = math.floor(-V)
-- Merken, das ein Richtungswechsel animiert werden soll
Zugaktionen[Zugname].R = 1
speicherTabelle(1, Zugaktionen)
end