summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2008-10-03 12:55:39 +0000
committerrubidium <rubidium@openttd.org>2008-10-03 12:55:39 +0000
commit3113cc17b97116bb3ab984f18dcd2695031b195c (patch)
treeb810177cfd0c47d6542f52656465768b2ecfb034 /src
parent3cff83c67e825087bef86b2524363819494a25bd (diff)
downloadopenttd-3113cc17b97116bb3ab984f18dcd2695031b195c.tar.xz
(svn r14436) -Fix [FS#1793]: (fast) trains would sometimes move one time too often/little when moving from diagonal<->non-diagonal tracks (iguannab)
Diffstat (limited to 'src')
-rw-r--r--src/train_cmd.cpp46
1 files changed, 35 insertions, 11 deletions
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 7b99dd0c8..69a56ab40 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -3227,6 +3227,16 @@ void Train::MarkDirty()
UpdateTrainAcceleration(this);
}
+/**
+ * This function looks at the vehicle and updates it's speed (cur_speed
+ * and subspeed) variables. Furthermore, it returns the distance that
+ * the train can drive this tick. This distance is expressed as 256 * n,
+ * where n is the number of straight (long) tracks the train can
+ * traverse. This means that moving along a straight track costs 256
+ * "speed" and a diagonal track costs 192 "speed".
+ * @param v The vehicle to update the speed of.
+ * @return distance to drive.
+ */
static int UpdateTrainSpeed(Vehicle *v)
{
uint accel;
@@ -3254,11 +3264,22 @@ static int UpdateTrainSpeed(Vehicle *v)
v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
}
- if (!(v->direction & 1)) spd = spd * 3 >> 2;
+ /* Scale speed by 3/4. Previously this was only done when the train was
+ * facing diagonally and would apply to however many moves the train made
+ * regardless the of direction actually moved in. Now it is always scaled,
+ * 256 spd is used to go straight and 192 is used to go diagonally
+ * (3/4 of 256). This results in the same effect, but without the error the
+ * previous method caused.
+ *
+ * The scaling is done in this direction and not by multiplying the amount
+ * to be subtracted by 4/3 so that the leftover speed can be saved in a
+ * byte in v->progress.
+ */
+ int scaled_spd = spd * 3 >> 2;
- spd += v->progress;
- v->progress = (byte)spd;
- return (spd >> 8);
+ scaled_spd += v->progress;
+ v->progress = 0; // set later in TrainLocoHandler or TrainController
+ return scaled_spd;
}
static void TrainEnterStation(Vehicle *v, StationID station)
@@ -4279,21 +4300,24 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
}
- if (j == 0) {
+ int adv_spd = (v->direction & 1) ? 192 : 256;
+ if (j < adv_spd) {
/* if the vehicle has speed 0, update the last_speed field. */
- if (v->cur_speed != 0) return;
+ if (v->cur_speed == 0) SetLastSpeed(v, v->cur_speed);
} else {
TrainCheckIfLineEnds(v);
-
+ /* Loop until the train has finished moving. */
do {
+ j -= adv_spd;
TrainController(v, NULL, true);
CheckTrainCollision(v);
- if (v->cur_speed <= 0x100)
- break;
- } while (--j != 0);
+ /* 192 spd used for going straight, 256 for going diagonally. */
+ adv_spd = (v->direction & 1) ? 192 : 256;
+ } while (j >= adv_spd);
+ SetLastSpeed(v, v->cur_speed);
}
- SetLastSpeed(v, v->cur_speed);
+ if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress
}