Add signal safety control override, restructure control system
parent
8f8f009425
commit
33c839b40d
|
@ -20,10 +20,11 @@ end
|
|||
--contents: {command="...", arrowconn=0-15 where arrow points}
|
||||
|
||||
--general
|
||||
function atc.train_set_command(train_id, command, arrow)
|
||||
atc.train_reset_command(train_id)
|
||||
advtrains.trains[train_id].atc_arrow = arrow
|
||||
advtrains.trains[train_id].atc_command = command
|
||||
function atc.train_set_command(train, command, arrow)
|
||||
atc.train_reset_command(train)
|
||||
train.atc_delay = 0
|
||||
train.atc_arrow = arrow
|
||||
train.atc_command = command
|
||||
end
|
||||
|
||||
function atc.send_command(pos, par_tid)
|
||||
|
@ -49,7 +50,7 @@ function atc.send_command(pos, par_tid)
|
|||
atwarn("ATC rail at", pos, ": Rail not on train's path! Can't determine arrow direction. Assuming +!")
|
||||
end
|
||||
|
||||
atc.train_set_command(train_id, atc.controllers[pts].command, iconnid==1)
|
||||
atc.train_set_command(train, atc.controllers[pts].command, iconnid==1)
|
||||
atprint("Sending ATC Command to", train_id, ":", atc.controllers[pts].command, "iconnid=",iconnid)
|
||||
return true
|
||||
|
||||
|
@ -66,12 +67,13 @@ function atc.send_command(pos, par_tid)
|
|||
return false
|
||||
end
|
||||
|
||||
function atc.train_reset_command(train_id)
|
||||
advtrains.trains[train_id].atc_command=nil
|
||||
advtrains.trains[train_id].atc_delay=0
|
||||
advtrains.trains[train_id].atc_brake_target=nil
|
||||
advtrains.trains[train_id].atc_wait_finish=nil
|
||||
advtrains.trains[train_id].atc_arrow=nil
|
||||
function atc.train_reset_command(train)
|
||||
train.atc_command=nil
|
||||
train.atc_delay=nil
|
||||
train.atc_brake_target=nil
|
||||
train.atc_wait_finish=nil
|
||||
train.atc_arrow=nil
|
||||
train.tarvelocity=nil
|
||||
end
|
||||
|
||||
--nodes
|
||||
|
@ -179,7 +181,7 @@ local matchptn={
|
|||
train.tarvelocity = 0
|
||||
elseif train.velocity>tonumber(match) then
|
||||
train.atc_brake_target=tonumber(match)
|
||||
if train.tarvelocity>train.atc_brake_target then
|
||||
if not train.tarvelocity or train.tarvelocity>train.atc_brake_target then
|
||||
train.tarvelocity=train.atc_brake_target
|
||||
end
|
||||
end
|
||||
|
@ -258,7 +260,7 @@ function atc.execute_atc_command(id, train)
|
|||
while nest>=0 do
|
||||
if pos>#rest then
|
||||
atwarn(sid(id), attrans("ATC command syntax error: I statement not closed: @1",command))
|
||||
atc.train_reset_command(id)
|
||||
atc.train_reset_command(train)
|
||||
return
|
||||
end
|
||||
local char=string.sub(rest, pos, pos)
|
||||
|
@ -301,7 +303,7 @@ function atc.execute_atc_command(id, train)
|
|||
end
|
||||
end
|
||||
atwarn(sid(id), attrans("ATC command parse error: Unknown command: @1", command))
|
||||
atc.train_reset_command(id)
|
||||
atc.train_reset_command(train)
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ function advtrains.pcall(fun)
|
|||
atwarn(debug.traceback())
|
||||
if advtrains.atprint_context_tid then
|
||||
advtrains.path_print(advtrains.trains[advtrains.atprint_context_tid], atdebug)
|
||||
atwarn(advtrains.trains[advtrains.atprint_context_tid].debug)
|
||||
end
|
||||
end)
|
||||
if not succ then
|
||||
|
|
|
@ -260,7 +260,7 @@ function advtrains.path_get_index_by_offset(train, index, offset)
|
|||
--atdebug("pibo: 2 off=",off,"idx=",idx)
|
||||
-- then walk the path forward until we would overshoot
|
||||
while off - train.path_dist[idx] >= 0 do
|
||||
idx = idx - 1
|
||||
idx = idx + 1
|
||||
advtrains.path_get_adjacent(train, idx)
|
||||
if not train.path_dist[idx] then
|
||||
for i=-5,5 do
|
||||
|
|
|
@ -44,19 +44,19 @@ function advtrains.on_control_change(pc, train, flip)
|
|||
else
|
||||
local act=false
|
||||
if pc.up then
|
||||
train.lever=4
|
||||
train.ctrl.user=4
|
||||
act=true
|
||||
end
|
||||
if pc.jump then
|
||||
train.lever = 1
|
||||
train.ctrl.user = 1
|
||||
act=true
|
||||
end
|
||||
if pc.down then
|
||||
if train.velocity>0 then
|
||||
if pc.jump then
|
||||
train.lever = 0
|
||||
train.ctrl.user = 0
|
||||
else
|
||||
train.lever = 2
|
||||
train.ctrl.user = 2
|
||||
end
|
||||
act=true
|
||||
else
|
||||
|
@ -77,7 +77,9 @@ function advtrains.on_control_change(pc, train, flip)
|
|||
train.door_open = 1
|
||||
end
|
||||
end
|
||||
train.active_control = act
|
||||
if not act then
|
||||
train.ctrl.user = nil
|
||||
end
|
||||
if pc.aux1 then
|
||||
--horn
|
||||
end
|
||||
|
@ -161,9 +163,7 @@ function advtrains.hud_train_format(train, flip)
|
|||
|
||||
local max=train.max_speed or 10
|
||||
local vel=advtrains.abs_ceil(train.velocity)
|
||||
local tvel=advtrains.abs_ceil(train.tarvelocity)
|
||||
local vel_kmh=advtrains.abs_ceil(advtrains.ms_to_kmh(train.velocity))
|
||||
local tvel_kmh=advtrains.abs_ceil(advtrains.ms_to_kmh(train.tarvelocity))
|
||||
|
||||
local levers = "B - o +"
|
||||
local tlev=train.lever
|
||||
|
@ -174,11 +174,28 @@ function advtrains.hud_train_format(train, flip)
|
|||
if tlev == 3 then levers = "B - >o< +" end
|
||||
if tlev == 4 then levers = "B - o >+<" end
|
||||
|
||||
local topLine, firstLine, secondLine
|
||||
local topLine, firstLine
|
||||
|
||||
local secondLine
|
||||
if train.tarvelocity then
|
||||
local b=" "
|
||||
local tvel=advtrains.abs_ceil(train.tarvelocity)
|
||||
local tvel_kmh=advtrains.abs_ceil(advtrains.ms_to_kmh(train.tarvelocity))
|
||||
if train.atc_brake_target then
|
||||
b="-B-"
|
||||
end
|
||||
secondLine="ATC"..b..": |"..string.rep("+", tvel)..string.rep("_", max-tvel).."> "..tvel_kmh.." km/h"
|
||||
elseif train.atc_delay then
|
||||
secondLine = "ATC waiting "..advtrains.abs_ceil(train.atc_delay).."s"
|
||||
else
|
||||
secondLine = "Manual operation"
|
||||
end
|
||||
if train.ctrl.lzb then
|
||||
secondLine = "-!- Safety override -!-"
|
||||
end
|
||||
|
||||
topLine=" ["..mletter[fct].."] {"..levers.."} "..doorstr[(train.door_open or 0) * fct]
|
||||
firstLine=attrans("Speed:").." |"..string.rep("+", vel)..string.rep("_", max-vel).."> "..vel_kmh.." km/h"
|
||||
secondLine=attrans("Target:").." |"..string.rep("+", tvel)..string.rep("_", max-tvel).."> "..tvel_kmh.." km/h"
|
||||
|
||||
return topLine.."\n"..firstLine.."\n"..secondLine
|
||||
return (train.debug or "").."\n"..topLine.."\n"..firstLine.."\n"..secondLine
|
||||
end
|
||||
|
|
|
@ -181,6 +181,13 @@ local function assertdef(tbl, var, def)
|
|||
end
|
||||
end
|
||||
|
||||
function advtrains.get_acceleration(train, lever)
|
||||
local acc_all = t_accel_all[lever]
|
||||
local acc_eng = t_accel_eng[lever]
|
||||
local nwagons = #train.trainparts
|
||||
local acc = acc_all + (acc_eng*train.locomotives_in_train)/nwagons
|
||||
return acc
|
||||
end
|
||||
|
||||
-- Small local util function to recalculate train's end index
|
||||
local function recalc_end_index(train)
|
||||
|
@ -219,9 +226,10 @@ function advtrains.train_ensure_init(id, train)
|
|||
if train.no_step then return end
|
||||
|
||||
assertdef(train, "velocity", 0)
|
||||
assertdef(train, "tarvelocity", 0)
|
||||
--assertdef(train, "tarvelocity", 0)
|
||||
assertdef(train, "acceleration", 0)
|
||||
assertdef(train, "id", id)
|
||||
assertdef(train, "ctrl", {})
|
||||
|
||||
|
||||
if not train.drives_on or not train.max_speed then
|
||||
|
@ -275,11 +283,10 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
|
||||
--- 3. handle velocity influences ---
|
||||
local train_moves=(train.velocity~=0)
|
||||
local tarvel_cap
|
||||
local tarvel_cap = train.speed_restriction
|
||||
|
||||
if train.recently_collided_with_env then
|
||||
tarvel_cap=0
|
||||
train.active_control=false
|
||||
if not train_moves then
|
||||
train.recently_collided_with_env=nil--reset status when stopped
|
||||
end
|
||||
|
@ -307,11 +314,24 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
tarvel_cap=1
|
||||
end
|
||||
|
||||
-- Driving control rework:
|
||||
--[[
|
||||
Items are only defined when something is controlling them.
|
||||
In order of precedence.
|
||||
train.ctrl = {
|
||||
lzb = restrictive override from LZB
|
||||
user = User input from driverstand
|
||||
atc = ATC command override (determined here)
|
||||
}
|
||||
The code here determines the precedence and writes the final control into train.lever
|
||||
]]
|
||||
|
||||
--interpret ATC command and apply auto-lever control when not actively controlled
|
||||
local trainvelocity = train.velocity
|
||||
if not train.lever then train.lever=3 end
|
||||
if train.active_control then
|
||||
advtrains.atc.train_reset_command(id)
|
||||
|
||||
|
||||
if train.ctrl.user then
|
||||
advtrains.atc.train_reset_command(train)
|
||||
else
|
||||
local braketar = train.atc_brake_target
|
||||
local emerg = false -- atc_brake_target==-1 means emergency brake (BB command)
|
||||
|
@ -323,8 +343,11 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
train.atc_brake_target=nil
|
||||
braketar = nil
|
||||
end
|
||||
if train.tarvelocity and train.velocity==train.tarvelocity then
|
||||
train.tarvelocity = nil
|
||||
end
|
||||
if train.atc_wait_finish then
|
||||
if not train.atc_brake_target and train.velocity==train.tarvelocity then
|
||||
if not train.atc_brake_target and not train.tarvelocity then
|
||||
train.atc_wait_finish=nil
|
||||
end
|
||||
end
|
||||
|
@ -334,42 +357,62 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
else
|
||||
train.atc_delay=train.atc_delay-dtime
|
||||
end
|
||||
elseif train.atc_delay then
|
||||
train.atc_delay = nil
|
||||
end
|
||||
|
||||
train.lever = 3
|
||||
if train.tarvelocity>trainvelocity then train.lever=4 end
|
||||
if train.tarvelocity<trainvelocity then
|
||||
train.ctrl.atc = nil
|
||||
if train.tarvelocity and train.tarvelocity>trainvelocity then
|
||||
train.ctrl.atc=4
|
||||
end
|
||||
if train.tarvelocity and train.tarvelocity<trainvelocity then
|
||||
if (braketar and braketar<trainvelocity) then
|
||||
if emerg then
|
||||
train.lever = 0
|
||||
train.ctrl.atc = 0
|
||||
else
|
||||
train.lever=1
|
||||
train.ctrl.atc=1
|
||||
end
|
||||
else
|
||||
train.lever=2
|
||||
train.ctrl.atc=2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if tarvel_cap and tarvel_cap<train.tarvelocity then
|
||||
if tarvel_cap and train.tarvelocity and tarvel_cap<train.tarvelocity then
|
||||
train.tarvelocity=tarvel_cap
|
||||
end
|
||||
local tmp_lever = train.lever
|
||||
|
||||
local tmp_lever
|
||||
|
||||
for _, lev in pairs(train.ctrl) do
|
||||
-- use the most restrictive of all control overrides
|
||||
tmp_lever = math.min(tmp_lever or 4, lev)
|
||||
end
|
||||
|
||||
if not tmp_lever then
|
||||
-- if there was no control at all, default to 3
|
||||
tmp_lever = 3
|
||||
end
|
||||
|
||||
if tarvel_cap and trainvelocity>tarvel_cap then
|
||||
tmp_lever = 0
|
||||
end
|
||||
|
||||
train.lever = tmp_lever
|
||||
|
||||
--- 3a. actually calculate new velocity ---
|
||||
if tmp_lever~=3 then
|
||||
local acc_all = t_accel_all[tmp_lever]
|
||||
local acc_eng = t_accel_eng[tmp_lever]
|
||||
local nwagons = #train.trainparts
|
||||
local accel = acc_all + (acc_eng*train.locomotives_in_train)/nwagons
|
||||
local accel = advtrains.get_acceleration(train, tmp_lever)
|
||||
local vdiff = accel*dtime
|
||||
if not train.active_control then
|
||||
|
||||
-- ATC control exception: don't cross tarvelocity if
|
||||
-- atc provided a target_vel
|
||||
if train.tarvelocity then
|
||||
local tvdiff = train.tarvelocity - trainvelocity
|
||||
if math.abs(vdiff) > math.abs(tvdiff) then
|
||||
if tvdiff~=0 and math.abs(vdiff) > math.abs(tvdiff) then
|
||||
--applying this change would cross tarvelocity
|
||||
--atdebug("In Tvdiff condition, clipping",vdiff,"to",tvdiff)
|
||||
--atdebug("vel=",trainvelocity,"tvel=",train.tarvelocity)
|
||||
vdiff=tvdiff
|
||||
end
|
||||
end
|
||||
|
@ -385,9 +428,9 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
end
|
||||
train.acceleration=vdiff
|
||||
train.velocity=train.velocity+vdiff
|
||||
if train.active_control then
|
||||
train.tarvelocity = train.velocity
|
||||
end
|
||||
--if train.ctrl.user then
|
||||
-- train.tarvelocity = train.velocity
|
||||
--end
|
||||
else
|
||||
train.acceleration = 0
|
||||
end
|
||||
|
@ -443,7 +486,7 @@ if train.no_step or train.wait_for_path then return end
|
|||
if not collided and advtrains.occ.check_collision(testpos, id) then
|
||||
--collides
|
||||
train.velocity = 0
|
||||
train.tarvelocity = 0
|
||||
advtrains.atc.train_reset_command(train)
|
||||
collided = true
|
||||
end
|
||||
--- 8b damage players ---
|
||||
|
@ -622,7 +665,7 @@ function advtrains.create_new_train_at(pos, connid, ioff, trainparts)
|
|||
t.last_connid=connid
|
||||
t.last_frac=ioff
|
||||
|
||||
t.tarvelocity=0
|
||||
--t.tarvelocity=0
|
||||
t.velocity=0
|
||||
t.trainparts=trainparts
|
||||
|
||||
|
|
|
@ -485,7 +485,7 @@ function ildb.get_ip_signal_asp(pts, connid)
|
|||
ildb.clear_ip_signal(pts, connid)
|
||||
return nil
|
||||
end
|
||||
return asp
|
||||
return asp, p
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
|
|
@ -8,9 +8,12 @@ local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELI
|
|||
dofile(modpath.."database.lua")
|
||||
dofile(modpath.."signal_api.lua")
|
||||
dofile(modpath.."demosignals.lua")
|
||||
dofile(modpath.."train_related.lua")
|
||||
dofile(modpath.."train_sections.lua")
|
||||
dofile(modpath.."route_prog.lua")
|
||||
dofile(modpath.."routesetting.lua")
|
||||
dofile(modpath.."tcb_ts_ui.lua")
|
||||
|
||||
dofile(modpath.."lzb.lua")
|
||||
|
||||
|
||||
minetest.register_privilege("interlocking", {description = "Can set up track sections, routes and signals.", give_to_singleplayer = true})
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
-- lzb.lua
|
||||
-- Enforced and/or automatic train override control, obeying signals
|
||||
|
||||
--[[
|
||||
Documentation of train.lzb table
|
||||
train.lzb = {
|
||||
trav = Current index that the traverser has advanced so far
|
||||
travsht = boolean indicating whether the train will be a shunt move at "trav"
|
||||
travspd = speed restriction at end of traverser
|
||||
travwspd = warning speed res.
|
||||
oncoming = table containing oncoming signals, in order of appearance on the path
|
||||
{
|
||||
pos = position of the signal (not the IP!)
|
||||
idx = where this is on the path
|
||||
spd = speed allowed to pass (determined dynamically)
|
||||
}
|
||||
}
|
||||
each step, for every item in "oncoming", we need to determine the location to start braking (+ some safety margin)
|
||||
and, if we passed this point for at least one of the items, initiate brake.
|
||||
When speed has dropped below, say 3, decrease the margin to zero, so that trains actually stop at the signal IP.
|
||||
The spd variable and travsht need to be updated on every aspect change. it's probably best to reset everything when any aspect changes
|
||||
|
||||
The traverser stops at signals that result in spd==0, because changes beyond there are likely.
|
||||
]]
|
||||
|
||||
local il = advtrains.interlocking
|
||||
|
||||
local BRAKE_SPACE = 10
|
||||
local AWARE_ZONE = 50
|
||||
|
||||
local ADD_STAND = 2
|
||||
local ADD_SLOW = 1
|
||||
local ADD_FAST = 10
|
||||
|
||||
local SHUNT_SPEED_MAX = 4
|
||||
|
||||
local function look_ahead(id, train)
|
||||
|
||||
local acc = advtrains.get_acceleration(train, 1)
|
||||
local vel = train.velocity
|
||||
local brakedst = -(vel*vel) / (2*acc)
|
||||
|
||||
local brake_i = advtrains.path_get_index_by_offset(train, train.index, brakedst + BRAKE_SPACE)
|
||||
--local aware_i = advtrains.path_get_index_by_offset(train, brake_i, AWARE_ZONE)
|
||||
|
||||
local lzb = train.lzb
|
||||
local trav = lzb.trav
|
||||
local travspd = lzb.travspd
|
||||
local travwspd = lzb.travwspd
|
||||
local lspd
|
||||
|
||||
train.debug = lspd
|
||||
|
||||
while trav <= brake_i and (not lspd or lspd>0) do
|
||||
trav = trav + 1
|
||||
local pos = advtrains.path_get(train, trav)
|
||||
local pts = advtrains.roundfloorpts(pos)
|
||||
local cn = train.path_cn[trav]
|
||||
-- check offtrack
|
||||
if trav > train.path_trk_f then
|
||||
lspd = 0
|
||||
table.insert(lzb.oncoming, {
|
||||
idx = trav-1,
|
||||
spd = 0,
|
||||
})
|
||||
else
|
||||
-- check for signal
|
||||
local asp, spos = il.db.get_ip_signal_asp(pts, cn)
|
||||
--atdebug("trav: ",pos, cn, asp, spos, "travsht=", lzb.travsht)
|
||||
if asp then
|
||||
local nspd = 0
|
||||
--interpreting aspect and determining speed to proceed
|
||||
if lzb.travsht then
|
||||
--shunt move
|
||||
if asp.shunt.free then
|
||||
nspd = SHUNT_SPEED_MAX
|
||||
elseif asp.shunt.proceed_as_main and asp.main.free then
|
||||
nspd = asp.main.speed
|
||||
lzb.travsht = false
|
||||
end
|
||||
else
|
||||
--train move
|
||||
if asp.main.free then
|
||||
nspd = asp.main.speed
|
||||
elseif asp.shunt.free then
|
||||
nspd = SHUNT_SPEED_MAX
|
||||
lzb.travsht = true
|
||||
end
|
||||
end
|
||||
-- nspd can now be: 1. !=0: new speed restriction, 2. =0: stop here or 3. nil: keep travspd
|
||||
if nspd then
|
||||
if nspd == -1 then
|
||||
travspd = nil
|
||||
else
|
||||
travspd = nspd
|
||||
end
|
||||
end
|
||||
|
||||
local nwspd = asp.info.w_speed
|
||||
if nwspd then
|
||||
if nwspd == -1 then
|
||||
travwspd = nil
|
||||
else
|
||||
travwspd = nwspd
|
||||
end
|
||||
end
|
||||
--atdebug("ns,wns,ts,wts", nspd, nwspd, travspd, travwspd)
|
||||
lspd = travspd
|
||||
if travwspd and (not lspd or lspd>travwspd) then
|
||||
lspd = travwspd
|
||||
end
|
||||
|
||||
table.insert(lzb.oncoming, {
|
||||
pos = spos,
|
||||
idx = trav,
|
||||
spd = lspd,
|
||||
})
|
||||
-- TODO register aspect change callback!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
lzb.trav = trav
|
||||
lzb.travspd = travspd
|
||||
lzb.travwspd = travwspd
|
||||
|
||||
end
|
||||
|
||||
--[[
|
||||
Distance needed to accelerate from v0 to v1 with constant acceleration a:
|
||||
|
||||
v1 - v0 a / v1 - v0 \ 2
|
||||
s = v0 * ------- + - * | ------- |
|
||||
a 2 \ a /
|
||||
]]
|
||||
|
||||
local function apply_control(id, train)
|
||||
local lzb = train.lzb
|
||||
|
||||
local i = 1
|
||||
while i<#lzb.oncoming do
|
||||
if lzb.oncoming[i].idx < train.index then
|
||||
train.speed_restriction = lzb.oncoming[i].spd
|
||||
table.remove(lzb.oncoming, i)
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
for i, it in ipairs(lzb.oncoming) do
|
||||
local a = advtrains.get_acceleration(train, 1) --should be negative
|
||||
local v0 = train.velocity
|
||||
local v1 = it.spd
|
||||
if v1 and v1 <= v0 then
|
||||
local f = (v1-v0) / a
|
||||
local s = v0*f + a*f*f/2
|
||||
|
||||
local st = s + ADD_SLOW
|
||||
if v0 > 3 then
|
||||
st = s + ADD_FAST
|
||||
end
|
||||
if v0<=0 then
|
||||
st = s + ADD_STAND
|
||||
end
|
||||
|
||||
local i = advtrains.path_get_index_by_offset(train, it.idx, -st)
|
||||
|
||||
--train.debug = dump({v0f=v0*f, aff=a*f*f,v0=v0, v1=v1, f=f, a=a, s=s, st=st, i=i, idx=train.index})
|
||||
if i <= train.index then
|
||||
-- Gotcha! Braking...
|
||||
train.ctrl.lzb = 1
|
||||
--train.debug = train.debug .. "BRAKE!!!"
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
train.ctrl.lzb = nil
|
||||
end
|
||||
|
||||
|
||||
advtrains.te_register_on_new_path(function(id, train)
|
||||
train.lzb = {
|
||||
trav = atfloor(train.index),
|
||||
travsht = train.is_shunt,
|
||||
oncoming = {}
|
||||
}
|
||||
train.ctrl.lzb = nil
|
||||
look_ahead(id, train)
|
||||
end)
|
||||
|
||||
advtrains.te_register_on_update(function(id, train)
|
||||
look_ahead(id, train)
|
||||
apply_control(id, train)
|
||||
end)
|
|
@ -50,9 +50,7 @@ function r.fire_event(pos, evtdata)
|
|||
atc_send = function(cmd)
|
||||
if not train_id then return false end
|
||||
assertt(cmd, "string")
|
||||
advtrains.atc.train_reset_command(train_id)
|
||||
train.atc_command=cmd
|
||||
train.atc_arrow=atc_arrow
|
||||
advtrains.atc.train_set_command(train, cmd, atc_arrow)
|
||||
return true
|
||||
end,
|
||||
set_line = function(line)
|
||||
|
@ -62,7 +60,7 @@ function r.fire_event(pos, evtdata)
|
|||
atc_reset = function(cmd)
|
||||
if not train_id then return false end
|
||||
assertt(cmd, "string")
|
||||
advtrains.atc.train_reset_command(train_id)
|
||||
advtrains.atc.train_reset_command(train)
|
||||
return true
|
||||
end,
|
||||
atc_arrow = atc_arrow,
|
||||
|
|
Loading…
Reference in New Issue