This repository has been archived by the owner on Aug 10, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Misc.lua
146 lines (130 loc) · 4.46 KB
/
Misc.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
-- "Junk drawer" of Lua helper functions.
--
-- @include YoRyan/LibRailWorks/Iterator.lua
local P = {}
Misc = P
-- Speed at which a train is "stopped."
P.stopped_mps = 0.01
-- Flash an info (middle of screen) message.
function P.showinfo(title, msg)
if msg == nil then
SysCall("ScenarioManager:ShowMessage", "", tostring(title), 0)
else
SysCall("ScenarioManager:ShowMessage", title, tostring(msg), 0)
end
end
-- Flash an alert (top-right corner) message.
function P.showalert(title, msg)
if msg == nil then
SysCall("ScenarioManager:ShowMessage", tostring(title), "", 1)
else
SysCall("ScenarioManager:ShowMessage", title, tostring(msg), 1)
end
end
-- Run the provided function and arguments with pcall and report any errors
-- to the player.
function P.catcherrors(...)
local success, err = pcall(unpack(arg))
if not success then P.showinfo("Lua Error", err) end
end
-- Wrap the provided function with a pcall wrapper that reports any errors
-- to the player.
function P.wraperrors(fn)
return function(...) return P.catcherrors(fn, unpack(arg)) end
end
-- Allow other parts of the simulator to settle for a few seconds.
function P.isinitialized() return RailWorks.GetSimulationTime() > 3 end
-- Convert a boolean to an integer value that can be passed to system calls.
function P.intbool(b) return b and 1 or 0 end
local function negatedistance(distance_m, obj) return -distance_m, obj end
local function speedlimitsbydistance(direction, n, maxdistance_m)
local i = 0
local minsearch_m = 0
return function()
i = i + 1
if i > n then return nil, nil end
local type, speed_mps, distance_m
if maxdistance_m == nil then
type, speed_mps, distance_m = RailWorks.GetNextSpeedLimit(direction,
minsearch_m)
else
type, speed_mps, distance_m = RailWorks.GetNextSpeedLimit(direction,
minsearch_m,
maxdistance_m)
end
if type == 1 or type == 2 or type == 3 then
minsearch_m = distance_m + 0.01
return distance_m, {type = type, speed_mps = speed_mps}
else
return nil, nil
end
end, nil, nil
end
-- Iterate through up to n speed posts in both directions, with an optional
-- maximum lookahead/lookbehind distance. Speed limits are in the form of
-- {type=..., speed_mps=...} and the key is the distance in m.
function P.iterspeedlimits(n, maxdistance_m)
return Iterator.concat({
Iterator.map(negatedistance, speedlimitsbydistance(1, n, maxdistance_m))
}, {speedlimitsbydistance(0, n, maxdistance_m)})
end
local function restrictsignalsbydistance(direction, n, maxdistance_m)
local i = 0
local minsearch_m = 0
return function()
i = i + 1
if i > n then return nil, nil end
local found, basicstate, distance_m, prostate
if maxdistance_m == nil then
found, basicstate, distance_m, prostate =
RailWorks.GetNextRestrictiveSignal(direction, minsearch_m)
else
found, basicstate, distance_m, prostate =
RailWorks.GetNextRestrictiveSignal(direction, minsearch_m, maxdistance_m)
end
if found > 0 then
minsearch_m = distance_m + 0.01
return distance_m, {basicstate = basicstate, prostate = prostate}
else
return nil, nil
end
end, nil, nil
end
-- Iterate through up to n restrictive signals in both directions, with an
-- optional maximum lookahead/lookbehind distance. Signals are in the form
-- of {basicstate=..., prostate=...} and the key is the distance in m.
function P.iterrestrictsignals(n, maxdistance_m)
return Iterator.concat({
Iterator.map(negatedistance, restrictsignalsbydistance(1, n, maxdistance_m))
}, {restrictsignalsbydistance(0, n, maxdistance_m)})
end
-- Round a number.
function P.round(v)
if v > 0 then
return math.floor(v + 0.5)
else
return math.floor(v - 0.5)
end
end
-- Get the digit of the provided value in the 10^(place) place. If the digit
-- should not be shown because the value is too small, then return -1.
function P.getdigit(v, place)
v = math.abs(v)
local tens = math.pow(10, place)
if place > 0 and v < tens then
return -1
else
return math.floor(math.mod(v / tens, 10))
end
end
-- Get the number of places to offset a value to display it in a digital cab
-- control.
function P.getdigitguide(v)
v = math.abs(v)
if v < 10 then
return 0
else
return math.floor(math.log10(v))
end
end
return P