From c2a77280842b5d752ef6c744adab20d9d1b67857 Mon Sep 17 00:00:00 2001 From: PeterN Date: Thu, 14 Jun 2018 09:25:39 +0100 Subject: Fix: Prevent ships moving into docks after finishing (un)loading. (#6791) --- src/ship_cmd.cpp | 4 ++++ src/track_func.h | 21 +++++++++++++++++++++ src/train_cmd.cpp | 33 ++++++--------------------------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 967cd4e1d..0bdcf7041 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -537,6 +537,10 @@ static void ShipController(Ship *v) if (v->current_order.IsType(OT_LEAVESTATION)) { v->current_order.Free(); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); + /* Test if continuing forward would lead to a dead-end, moving into the dock. */ + DiagDirection exitdir = VehicleExitDir(v->direction, v->state); + TileIndex tile = TileAddByDiagDir(v->tile, exitdir); + if (TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) goto reverse_direction; } else if (v->dest_tile != 0) { /* We have a target, let's see if we reached it... */ if (v->current_order.IsType(OT_GOTO_WAYPOINT) && diff --git a/src/track_func.h b/src/track_func.h index 68de827ef..5e1585c08 100644 --- a/src/track_func.h +++ b/src/track_func.h @@ -692,4 +692,25 @@ static inline bool IsUphillTrackdir(Slope slope, Trackdir dir) return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir); } +/** + * Determine the side in which the vehicle will leave the tile + * + * @param direction vehicle direction + * @param track vehicle track bits + * @return side of tile the vehicle will leave + */ +static inline DiagDirection VehicleExitDir(Direction direction, TrackBits track) +{ + static const TrackBits state_dir_table[DIAGDIR_END] = { TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER }; + + DiagDirection diagdir = DirToDiagDir(direction); + + /* Determine the diagonal direction in which we will exit this tile */ + if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) { + diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT); + } + + return diagdir; +} + #endif /* TRACK_FUNC_H */ diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 9f4ecbea6..daebb9789 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -57,27 +57,6 @@ bool IsValidImageIndex(uint8 image_index) return image_index < lengthof(_engine_sprite_base); } -/** - * Determine the side in which the train will leave the tile - * - * @param direction vehicle direction - * @param track vehicle track bits - * @return side of tile the train will leave - */ -static inline DiagDirection TrainExitDir(Direction direction, TrackBits track) -{ - static const TrackBits state_dir_table[DIAGDIR_END] = { TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER }; - - DiagDirection diagdir = DirToDiagDir(direction); - - /* Determine the diagonal direction in which we will exit this tile */ - if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) { - diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT); - } - - return diagdir; -} - /** * Return the cargo weight multiplier to use for a rail vehicle @@ -1872,9 +1851,9 @@ void ReverseTrainDirection(Train *v) return; } - /* TrainExitDir does not always produce the desired dir for depots and + /* VehicleExitDir does not always produce the desired dir for depots and * tunnels/bridges that is needed for UpdateSignalsOnSegment. */ - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR; if (UpdateSignalsOnSegment(v->tile, dir, v->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) { @@ -3098,7 +3077,7 @@ static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data) /* not front engine of a train, inside wormhole or depot, crashed */ if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return NULL; - if (t->cur_speed > 5 || TrainExitDir(t->direction, t->track) != exitdir) return NULL; + if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return NULL; return t; } @@ -3681,7 +3660,7 @@ static TileIndex TrainApproachingCrossingTile(const Train *v) if (!TrainCanLeaveTile(v)) return INVALID_TILE; - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); TileIndex tile = v->tile + TileOffsByDiagDir(dir); /* not a crossing || wrong axis || unusable rail (wrong type or owner) */ @@ -3718,7 +3697,7 @@ static bool TrainCheckIfLineEnds(Train *v, bool reverse) if (!TrainCanLeaveTile(v)) return true; /* Determine the non-diagonal direction in which we will exit this tile */ - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); /* Calculate next tile */ TileIndex tile = v->tile + TileOffsByDiagDir(dir); @@ -3786,7 +3765,7 @@ static bool TrainLocoHandler(Train *v, bool mode) /* Try to reserve a path when leaving the station as we * might not be marked as wanting a reservation, e.g. * when an overlength train gets turned around in a station. */ - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR; if (UpdateSignalsOnSegment(v->tile, dir, v->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) { -- cgit v1.2.3-70-g09d2