summaryrefslogtreecommitdiff
path: root/train_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'train_cmd.c')
-rw-r--r--train_cmd.c67
1 files changed, 64 insertions, 3 deletions
diff --git a/train_cmd.c b/train_cmd.c
index d473148c0..74dd5bf39 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "openttd.h"
+#include "debug.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
@@ -22,6 +23,7 @@
(is_custom_sprite(spritenum) ? IS_CUSTOM_FIRSTHEAD_SPRITE(spritenum) : _engine_sprite_add[spritenum] == 0)
static bool TrainCheckIfLineEnds(Vehicle *v);
+static void TrainController(Vehicle *v);
extern void ShowTrainViewWindow(Vehicle *v);
static const byte _vehicle_initial_x_fract[4] = {10,8,4,8};
@@ -81,6 +83,7 @@ void TrainConsistChanged(Vehicle *v) {
for (u = v; u != NULL; u = u->next) {
const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
+ uint16 veh_len;
// update the 'first engine'
u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine;
@@ -109,6 +112,16 @@ void TrainConsistChanged(Vehicle *v) {
// max speed is the minimum of the speed limits of all vehicles in the consist
if (rvi_u->max_speed != 0)
max_speed = min(rvi_u->max_speed, max_speed);
+
+ // check the vehicle length (callback)
+ veh_len = CALLBACK_FAILED;
+ if (HASBIT(rvi_u->callbackmask, CBM_VEH_LENGTH))
+ veh_len = GetCallBackResult(CBID_VEH_LENGTH, u->engine_type, u);
+ if (veh_len == CALLBACK_FAILED)
+ veh_len = rvi_u->shorten_factor;
+ assert(veh_len < 8);
+ u->u.rail.cached_veh_length = 8 - veh_len;
+
};
// store consist weight/max speed in cache
@@ -1257,6 +1270,52 @@ static void DisableTrainCrossing(TileIndex tile)
}
}
+/**
+ * Advances wagons for train reversing, needed for variable length wagons.
+ * Needs to be called once before the train is reversed, and once after it.
+ * @param v First vehicle in chain
+ * @param before Set to true for the call before reversing, false otherwise
+ */
+static void AdvanceWagons(Vehicle *v, bool before)
+{
+ Vehicle *base, *first, *last, *tempnext;
+ int i, length;
+ int differential;
+
+ base = v;
+ first = base->next;
+ length = CountVehiclesInChain(v);
+
+ while (length > 2) {
+ // find pairwise matching wagon
+ // start<>end, start+1<>end-1, ... */
+ last = first;
+ for (i = length - 3; i; i--) {
+ last = last->next;
+ }
+
+ differential = last->u.rail.cached_veh_length - base->u.rail.cached_veh_length;
+ if (before)
+ differential *= -1;
+
+ if (differential > 0) {
+ // disconnect last car to make sure only this subset moves
+ tempnext = last->next;
+ last->next = NULL;
+
+ for (i = 0; i < differential; i++) {
+ TrainController(first);
+ }
+
+ last->next = tempnext;
+ }
+
+ base = first;
+ first = first->next;
+ length -= 2;
+ }
+}
+
static void ReverseTrainDirection(Vehicle *v)
{
int l = 0, r = -1;
@@ -1285,11 +1344,15 @@ static void ReverseTrainDirection(Vehicle *v)
u = v;
do r++; while ( (u = u->next) != NULL );
+ AdvanceWagons(v, true);
+
/* swap start<>end, start+1<>end-1, ... */
do {
ReverseTrainSwapVeh(v, l++, r--);
} while (l <= r);
+ AdvanceWagons(v, false);
+
if (IsTileDepotType(v->tile, TRANSPORT_RAIL))
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
@@ -2723,8 +2786,6 @@ static void TrainController(Vehicle *v)
v->x_pos = gp.x;
v->y_pos = gp.y;
VehiclePositionChanged(v);
- if (prev == NULL)
- CheckTrainCollision(v);
continue;
}
common:;
@@ -2743,7 +2804,6 @@ common:;
if (prev == NULL) {
/* This is the first vehicle in the train */
AffectSpeedByZChange(v, old_z);
- CheckTrainCollision(v);
}
}
return;
@@ -3106,6 +3166,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
do {
TrainController(v);
+ CheckTrainCollision(v);
if (v->cur_speed <= 0x100)
break;
} while (--j != 0);