aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--advtrains/atc.lua28
-rw-r--r--advtrains/couple.lua92
-rw-r--r--advtrains/init.lua2
-rw-r--r--advtrains/trainlogic.lua11
-rw-r--r--atc_command.txt4
5 files changed, 84 insertions, 53 deletions
diff --git a/advtrains/atc.lua b/advtrains/atc.lua
index 64cdcec..8cb3e8f 100644
--- a/advtrains/atc.lua
+++ b/advtrains/atc.lua
@@ -199,10 +199,16 @@ local matchptn={
return #match+1
end,
["B([0-9]+)"]=function(id, train, match)
- if train.velocity>tonumber(match) then
- train.atc_brake_target=tonumber(match)
- if not train.tarvelocity or train.tarvelocity>train.atc_brake_target then
- train.tarvelocity=train.atc_brake_target
+ local btar = tonumber(match)
+ if train.velocity>btar then
+ train.atc_brake_target=btar
+ if not train.tarvelocity or train.tarvelocity>btar then
+ train.tarvelocity=btar
+ end
+ else
+ -- independent of brake target, must make sure that tarvelocity is not greater than it
+ if train.tarvelocity and train.tarvelocity>btar then
+ train.tarvelocity=btar
end
end
return #match+1
@@ -267,6 +273,10 @@ local matchptn={
advtrains.interlocking.ars_set_disable(train, match=="0")
return 2
end,
+ ["Cpl"]=function(id, train)
+ train.atc_wait_autocouple=true
+ return 3
+ end,
}
eval_conditional = function(command, arrow, speed)
@@ -358,11 +368,13 @@ function atc.execute_atc_command(id, train)
local match=string.match(command, "^"..pattern)
if match then
local patlen=func(id, train, match)
-
- atprint("Executing: "..string.sub(command, 1, patlen))
-
+ --atdebug("Executing: "..string.sub(command, 1, patlen))
+ --atdebug("Train ATC State: tvel=",train.tarvelocity,"brktar=",train.atc_brake_target,"delay=",train.atc_delay,"wfinish=",train.atc_wait_finish,"wacpl=",train.atc_wait_autocouple)
+
train.atc_command=string.sub(command, patlen+1)
- if train.atc_delay<=0 and not train.atc_wait_finish then
+ if train.atc_delay<=0
+ and not train.atc_wait_finish
+ and not train.atc_wait_autocouple then
--continue (recursive, cmds shouldn't get too long, and it's a end-recursion.)
atc.execute_atc_command(id, train)
end
diff --git a/advtrains/couple.lua b/advtrains/couple.lua
index 336a6d4..149584b 100644
--- a/advtrains/couple.lua
+++ b/advtrains/couple.lua
@@ -11,14 +11,9 @@
-- When the initiating train has autocouple set, trains are immediately coupled
-- When not, a couple entity is spawned and coupling commences on click
-- Coupling MUST preserve the train ID of the initiating train, so it is done like this:
- -- initiating train is reversed
- -- stationary train is reversed if required, so that it points towards the initiating train
- -- do_connect_trains(initiating, stationary)
--- As a result, the coupled train is reversed in direction. Alternative way of doing things (might be considered later):
- -- stationary train is reversed if required, so that it points away from the initiating train
-- index of initiating train is set so that it matches the front pos of stationary train
- -- wagons of stationary train are inserted at the beginning of initiating train
-- remove stationary train
+ -- wagons of stationary train are inserted at the beginning of initiating train (considers direction of stat_train and inserts reverse if required)
-- train.couple_* contain references to ObjectRefs of couple objects, which contain all relevant information
-- These objectRefs will delete themselves once the couples no longer match (see below)
@@ -142,12 +137,16 @@ end
-- Called from train_step_b() when the current train (init_train) just stopped at one of the end indices of another train (stat_train)
-- Depending on autocouple, either couples immediately or spawns a couple entity
function advtrains.couple_initiate_with(init_train, stat_train, stat_is_front)
- --atdebug("Initiating couplign between init=",init_train.id,"stat=",stat_train.id,"backside=",stat_is_backside)
- if init_train.autocouple then
- advtrains.couple_trains(init_train, true, stat_train, stat_is_front)
+ --atdebug("Couple init autocouple=",init_train.autocouple,"atc_w_acpl=",init_train.atc_wait_autocouple)
+ if init_train.autocouple or init_train.atc_wait_autocouple then
+ advtrains.couple_trains(init_train, false, stat_train, stat_is_front)
+ -- clear atc couple waiting blocker
+ init_train.atc_wait_autocouple = nil
else
local pos = advtrains.path_get_interpolated(init_train, init_train.index)
create_couple_entity(pos, init_train, true, stat_train, stat_is_front)
+ -- clear ATC command on collision
+ advtrains.atc.train_reset_command(init_train)
end
end
@@ -177,50 +176,61 @@ function advtrains.safe_couple_trains(train1, t1_is_front, train2, t2_is_front,
wck_t2 = check_twagon_owner(train2, t2_is_front, pname)
end
if (wck_t1 or wck_t2) or not pname then
- advtrains.couple_trains(train1, t1_is_front, train2, t2_is_front)
+ advtrains.couple_trains(train1, not t1_is_front, train2, t2_is_front)
end
end
-- Actually performs the train coupling. Always retains train ID of train1
-function advtrains.couple_trains(train1, t1_is_front, train2, t2_is_front)
- --atdebug("Couple trains init=",init_train.id,"stat=",stat_train.id,"statreverse=",stat_must_reverse)
- -- see comment on top of file
- if t1_is_front then
- advtrains.invert_train(train1.id)
- end
- if not t2_is_front then
- advtrains.invert_train(train2.id)
- end
-
- advtrains.do_connect_trains(train1, train2)
-end
+function advtrains.couple_trains(init_train, invert_init_train, stat_train, stat_train_opposite)
+ --atdebug("Couple trains init=",init_train.id,"initinv=",invert_init_train,"stat=",stat_train.id,"statreverse=",stat_train_opposite)
--- Adds the wagons of first to second and deletes second_id afterwards
--- Assumes that second_id stands right behind first_id and both trains point to the same direction
-function advtrains.do_connect_trains(first, second)
-
- if not advtrains.train_ensure_init(first.id, first) then
- atwarn("Coupling: first train",first.id,"is not initialized! Operation aborted!")
+ if not advtrains.train_ensure_init(init_train.id, init_train) then
+ atwarn("Coupling: initiating train",init_train.id,"is not initialized! Operation aborted!")
return
end
- if not advtrains.train_ensure_init(second.id, second) then
- atwarn("Coupling: second train",second.id,"is not initialized! Operation aborted!")
+ if not advtrains.train_ensure_init(stat_train.id, stat_train) then
+ atwarn("Coupling: stationary train",stat_train.id,"is not initialized! Operation aborted!")
return
end
-
- local first_wagoncnt=#first.trainparts
- local second_wagoncnt=#second.trainparts
-
- for _,v in ipairs(second.trainparts) do
- table.insert(first.trainparts, v)
+
+ -- only used with the couple entity
+ if invert_init_train then
+ advtrains.invert_train(init_train.id)
end
-
- advtrains.remove_train(second.id)
- first.velocity = 0
+ local itp = init_train.trainparts
+ local init_wagoncnt = #itp
+ local stp = stat_train.trainparts
+ local stat_wagoncnt = #stp
+ local stat_trainlen = stat_train.trainlen -- save the train length of stat train, to be added to index
+
+ if stat_train_opposite then
+ -- insert wagons in inverse order and set their wagon_flipped state
+ for i=1,stat_wagoncnt do
+ table.insert(itp, 1, stp[i])
+ local wdata = advtrains.wagons[stp[i]]
+ if wdata then
+ wdata.wagon_flipped = not wdata.wagon_flipped
+ else
+ atwarn("While coupling, wagon",stp[i],"of stationary train",stat_train.id,"not found!")
+ end
+ end
+ else
+ --insert wagons in normal order
+ for i=stat_wagoncnt,1,-1 do
+ table.insert(itp, 1, stp[i])
+ end
+ end
+
+ -- TODO: migrate some of the properties from stat_train to init_train?
- advtrains.update_trainpart_properties(first.id)
- advtrains.couple_invalidate(first)
+ advtrains.remove_train(stat_train.id)
+
+ -- Set train index forward
+ init_train.index = advtrains.path_get_index_by_offset(init_train, init_train.index, stat_trainlen)
+
+ advtrains.update_trainpart_properties(init_train.id)
+ advtrains.couple_invalidate(init_train)
return true
end
diff --git a/advtrains/init.lua b/advtrains/init.lua
index 083281e..0882237 100644
--- a/advtrains/init.lua
+++ b/advtrains/init.lua
@@ -468,7 +468,7 @@ advtrains.avt_save = function(remove_players_from_wagons)
"atc_brake_target", "atc_wait_finish", "atc_command", "atc_delay", "door_open",
"text_outside", "text_inside", "line", "routingcode",
"il_sections", "speed_restriction", "is_shunt",
- "points_split", "autocouple", "ars_disable",
+ "points_split", "autocouple", "atc_wait_autocouple", "ars_disable",
})
--then save it
tmp_trains[id]=v
diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua
index 00c04bf..4650f9e 100644
--- a/advtrains/trainlogic.lua
+++ b/advtrains/trainlogic.lua
@@ -418,9 +418,11 @@ function advtrains.train_step_b(id, train, dtime)
ctrl_lever = userc
else
if train.atc_command then
- if (not train.atc_delay or train.atc_delay<=0) and not train.atc_wait_finish then
+ if (not train.atc_delay or train.atc_delay<=0)
+ and not train.atc_wait_finish
+ and not train.atc_wait_autocouple then
advtrains.atc.execute_atc_command(id, train)
- else
+ elseif train.atc_delay and train.atc_delay > 0 then
train.atc_delay=train.atc_delay-dtime
end
elseif train.atc_delay then
@@ -711,12 +713,15 @@ function advtrains.train_step_c(id, train, dtime)
if train.ontrack_collision_info then
train.velocity = 0
train.acceleration = 0
- advtrains.atc.train_reset_command(train)
+ --advtrains.atc.train_reset_command(train) will occur in couple_initiate_with if required
local otrn = advtrains.trains[train.ontrack_collision_info.otid]
if otrn.velocity == 0 then -- other train must be standing, else don't initiate coupling
advtrains.couple_initiate_with(train, otrn, not train.ontrack_collision_info.same_dir)
+ else
+ -- other collision - stop any ATC control
+ advtrains.atc.train_reset_command(train)
end
train.ontrack_collision_info = nil
diff --git a/atc_command.txt b/atc_command.txt
index 9f4eb50..5a1c8ff 100644
--- a/atc_command.txt
+++ b/atc_command.txt
@@ -51,6 +51,10 @@ Kick all passengers out of the trains
This command kicks all passengers (non-driving players) off the train. This command works only
if the train is stopped and its doors are open.
+Cpl
+Temporarily switch the train to "Autocouple" mode and wait for coupling.
+This command makes the train continue at its current speed until it hits another standing wagon or train. Then, it couples to this train and ATC command execution continues.
+
# conditional statements:
I<condition><code>;