aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking
diff options
context:
space:
mode:
authororwell <orwell@bleipb.de>2025-06-24 22:30:00 +0200
committerorwell <orwell@bleipb.de>2025-06-24 22:30:00 +0200
commit570acb67c2aea20ce46251e67f394a1e6114dcfb (patch)
tree14f5574fb62e8aada9c34bcd032f97a50c0c3bfb /advtrains_interlocking
parentb99d89c07903ab0b4440004c66422f049435af34 (diff)
ARS: Add Train Length rule
Diffstat (limited to 'advtrains_interlocking')
-rw-r--r--advtrains_interlocking/ars.lua44
1 files changed, 42 insertions, 2 deletions
diff --git a/advtrains_interlocking/ars.lua b/advtrains_interlocking/ars.lua
index 5182cd3..393878a 100644
--- a/advtrains_interlocking/ars.lua
+++ b/advtrains_interlocking/ars.lua
@@ -7,7 +7,8 @@
ars = {
[n] = {
ln = "<line>" -- either line
- rc = "<routingcode>" -- or routingcode
+ rc = "<routingcode>" -- or routingcode
+ tl = {min=1, max=2} -- or train length in meters
n = true/false -- true = logical not (matches everything that does not have this line/rc)
conj = { -- and conjunction, optional. This must be true in addition to the main rule
ln=... / rc=... / n=... -- like toplevel
@@ -70,6 +71,26 @@
local il = advtrains.interlocking
+local function parse_trainlen(tlstr)
+ mins, maxs = string.match(tlstr, "^(%d*)%-(%d+)$")
+ if mins and maxs then
+ return {min=tonumber(mins), max=tonumber(maxs)}
+ end
+ return {min=tonumber(tlstr)}
+ -- if it's not parseable at all it will return an empty table which means invalid
+end
+local function trainlen_to_str(tl)
+ if tl.min and tl.max then
+ return tl.min.."-"..tl.max
+ elseif tl.min then
+ return tl.min
+ elseif tl.max then
+ return "0-"..tl.max
+ else
+ return "?"
+ end
+end
+
local function conj_to_text(conj, txt)
while conj do
@@ -81,6 +102,8 @@ local function conj_to_text(conj, txt)
txt[#txt+1] = "& "..n.."LN "..conj.ln
elseif conj.rc then
txt[#txt+1] = "& "..n.."RC "..conj.rc
+ elseif conj.tl then
+ txt[#txt+1] = "& "..n.."TL "..trainlen_to_str(conj.tl)
end
conj = conj.conj
end
@@ -107,6 +130,8 @@ function il.ars_to_text(arstab)
txt[#txt+1] = prio..n.."LN "..arsent.ln
elseif arsent.rc then
txt[#txt+1] = prio..n.."RC "..arsent.rc
+ elseif arsent.tl then
+ txt[#txt+1] = prio..n.."TL "..trainlen_to_str(arsent.tl)
elseif arsent.c then
txt[#txt+1] = "#"..arsent.c
end
@@ -125,11 +150,13 @@ function il.ars_to_text(arstab)
end
local function parse_ruleexp(line)
- local excl, key, val = string.match(line, "^%s*(!?)%s*([RL][CN])%s+(.+)%s*$")
+ local excl, key, val = string.match(line, "^%s*(!?)%s*([RLT][CNL])%s+(.+)%s*$")
if key == "RC" then
return {rc=val, n=(excl=="!")}
elseif key == "LN" then
return {ln=val, n=(excl=="!")}
+ elseif key == "TL" then
+ return {tl=parse_trainlen(val), n=(excl=="!")}
end
end
@@ -204,6 +231,19 @@ local function match_arsent(arsent, train)
local routingcode = train.routingcode
rule_matches = routingcode and string.find(" "..routingcode.." ", " "..arsent.rc.." ", nil, true)
if arsent.n then rule_matches = not rule_matches end
+ elseif arsent.tl then
+ local trainlen = train.trainlen
+ local lmin, lmax = arsent.tl.min, arsent.tl.max
+ if lmin and lmax then
+ rule_matches = (trainlen >= lmin) and (trainlen < lmax)
+ elseif lmin then
+ rule_matches = (trainlen >= lmin)
+ elseif lmax then
+ rule_matches = (trainlen < lmax)
+ else
+ -- errorneous entry never matches
+ end
+ if arsent.n then rule_matches = not rule_matches end
end
if rule_matches then
-- if the entry has a conjunction, go on checking
ss="hl ppc">#include "utility.h" #include <ICameraSceneNode.h> #include <IMeshCache.h> #include <IAnimatedMesh.h> class LocalPlayer; class MapDrawControl; class ExtrudedSpriteSceneNode; class IGameDef; /* Client camera class, manages the player and camera scene nodes, the viewing distance and performs view bobbing etc. It also displays the wielded tool in front of the first-person camera. */ class Camera { public: Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control); ~Camera(); // Get player scene node. // This node is positioned at the player's torso (without any view bobbing), // as given by Player::m_position. Yaw is applied but not pitch. inline scene::ISceneNode* getPlayerNode() const { return m_playernode; } // Get head scene node. // It has the eye transformation and pitch applied, // but no view bobbing. inline scene::ISceneNode* getHeadNode() const { return m_headnode; } // Get camera scene node. // It has the eye transformation, pitch and view bobbing applied. inline scene::ICameraSceneNode* getCameraNode() const { return m_cameranode; } // Get the camera position (in absolute scene coordinates). // This has view bobbing applied. inline v3f getPosition() const { return m_camera_position; } // Get the camera direction (in absolute camera coordinates). // This has view bobbing applied. inline v3f getDirection() const { return m_camera_direction; } // Horizontal field of view inline f32 getFovX() const { return m_fov_x; } // Vertical field of view inline f32 getFovY() const { return m_fov_y; } // Get maximum of getFovX() and getFovY() inline f32 getFovMax() const { return MYMAX(m_fov_x, m_fov_y); } // Checks if the constructor was able to create the scene nodes bool successfullyCreated(std::wstring& error_message);