mirror of
https://github.com/OpenTTD/OpenTTD
synced 2026-01-22 19:54:06 +01:00
(svn r17160) [0.7] -Backport from trunk:
- Fix: A stuck train could free the reservation of another train if it was reversed or did crash (r17152) - Fix: A train entering a PBS section through a block signal could cause a train crash if another reservation ending at a safe tile was already present in the section [FS#3104] (r17151) - Fix: Update vehicle position cache when the vehicle sprite changes [FS#3060] (r17121) - Fix: News message about ordered refits failing was not very clear [FS#3091] (r17096)
This commit is contained in:
@@ -1533,13 +1533,6 @@ void Train::UpdateDeltaXY(Direction direction)
|
||||
this->z_extent = 6;
|
||||
}
|
||||
|
||||
static void UpdateVarsAfterSwap(Vehicle *v)
|
||||
{
|
||||
v->UpdateDeltaXY(v->direction);
|
||||
v->cur_image = v->GetImage(v->direction);
|
||||
VehicleMove(v, true);
|
||||
}
|
||||
|
||||
static inline void SetLastSpeed(Vehicle *v, int spd)
|
||||
{
|
||||
int old = v->u.rail.last_speed;
|
||||
@@ -1627,15 +1620,15 @@ static void ReverseTrainSwapVeh(Vehicle *v, int l, int r)
|
||||
SwapTrainFlags(&a->u.rail.flags, &b->u.rail.flags);
|
||||
|
||||
/* update other vars */
|
||||
UpdateVarsAfterSwap(a);
|
||||
UpdateVarsAfterSwap(b);
|
||||
a->UpdateViewport(true, true);
|
||||
b->UpdateViewport(true, true);
|
||||
|
||||
/* call the proper EnterTile function unless we are in a wormhole */
|
||||
if (a->u.rail.track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
|
||||
if (b->u.rail.track != TRACK_BIT_WORMHOLE) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
|
||||
} else {
|
||||
if (a->u.rail.track != TRACK_BIT_DEPOT) a->direction = ReverseDir(a->direction);
|
||||
UpdateVarsAfterSwap(a);
|
||||
a->UpdateViewport(true, true);
|
||||
|
||||
if (a->u.rail.track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
|
||||
}
|
||||
@@ -1828,8 +1821,8 @@ static void ReverseTrainDirection(Vehicle *v)
|
||||
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
|
||||
}
|
||||
|
||||
/* Clear path reservation in front. */
|
||||
FreeTrainTrackReservation(v);
|
||||
/* Clear path reservation in front if train is not stuck. */
|
||||
if (!HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v);
|
||||
|
||||
/* Check if we were approaching a rail/road-crossing */
|
||||
TileIndex crossing = TrainApproachingCrossingTile(v);
|
||||
@@ -1859,7 +1852,7 @@ static void ReverseTrainDirection(Vehicle *v)
|
||||
TrainConsistChanged(v, true);
|
||||
|
||||
/* update all images */
|
||||
for (Vehicle *u = v; u != NULL; u = u->Next()) u->cur_image = u->GetImage(u->direction);
|
||||
for (Vehicle *u = v; u != NULL; u = u->Next()) u->UpdateViewport(false, false);
|
||||
|
||||
/* update crossing we were approaching */
|
||||
if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
|
||||
@@ -3086,6 +3079,15 @@ bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay)
|
||||
|
||||
bool other_train = false;
|
||||
PBSTileInfo origin = FollowTrainReservation(v, &other_train);
|
||||
/* The path we are driving on is alread blocked by some other train.
|
||||
* This can only happen in certain situations when mixing path and
|
||||
* block signals or when changing tracks and/or signals.
|
||||
* Exit here as doing any further reservations will probably just
|
||||
* make matters worse. */
|
||||
if (other_train && v->tile != origin.tile) {
|
||||
if (mark_as_stuck) MarkTrainAsStuck(v);
|
||||
return false;
|
||||
}
|
||||
/* If we have a reserved path and the path ends at a safe tile, we are finished already. */
|
||||
if (origin.okay && (v->tile != origin.tile || first_tile_okay)) {
|
||||
/* Can't be stuck then. */
|
||||
@@ -3093,14 +3095,6 @@ bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay)
|
||||
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
|
||||
return true;
|
||||
}
|
||||
/* The path we are driving on is alread blocked by some other train.
|
||||
* This can only happen when tracks and signals are changed. A crash
|
||||
* is probably imminent, don't do any further reservation because
|
||||
* it might cause stale reservations. */
|
||||
if (other_train && v->tile != origin.tile) {
|
||||
if (mark_as_stuck) MarkTrainAsStuck(v);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we are in a depot, tentativly reserve the depot. */
|
||||
if (v->u.rail.track & TRACK_BIT_DEPOT) {
|
||||
@@ -3253,8 +3247,7 @@ void Train::MarkDirty()
|
||||
{
|
||||
Vehicle *v = this;
|
||||
do {
|
||||
v->cur_image = v->GetImage(v->direction);
|
||||
MarkSingleVehicleDirty(v);
|
||||
v->UpdateViewport(false, false);
|
||||
} while ((v = v->Next()) != NULL);
|
||||
|
||||
/* need to update acceleration and cached values since the goods on the train changed. */
|
||||
@@ -3478,11 +3471,10 @@ static void SetVehicleCrashed(Vehicle *v)
|
||||
{
|
||||
if (v->u.rail.crash_anim_pos != 0) return;
|
||||
|
||||
/* Free a possible path reservation and try to mark all tiles occupied by the train reserved. */
|
||||
if (IsFrontEngine(v)) {
|
||||
/* Remove all reservations, also the ones currently under the train
|
||||
* and any railway station paltform reservation. */
|
||||
FreeTrainTrackReservation(v);
|
||||
/* Remove the reserved path in front of the train if it is not stuck.
|
||||
* Also clear all reserved tracks the train is currently on. */
|
||||
if (!HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v);
|
||||
for (const Vehicle *u = v; u != NULL; u = u->Next()) {
|
||||
ClearPathReservation(u, u->tile, GetVehicleTrackdir(u));
|
||||
if (IsTileType(u->tile, MP_TUNNELBRIDGE)) {
|
||||
@@ -4369,9 +4361,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
|
||||
for (Vehicle *u = v; u != NULL; u = u->Next()) {
|
||||
if ((u->vehstatus & VS_HIDDEN) != 0) continue;
|
||||
|
||||
uint16 old_image = u->cur_image;
|
||||
u->cur_image = u->GetImage(u->direction);
|
||||
if (old_image != u->cur_image) VehicleMove(u, true);
|
||||
u->UpdateViewport(false, false);
|
||||
}
|
||||
|
||||
if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress
|
||||
|
||||
Reference in New Issue
Block a user