1
0
Fork 0

Add: Code dealing with extended rail depot platforms.

pull/8480/head
J0anJosep 2021-03-20 19:50:19 +01:00
parent 4854685bec
commit 7ab28f6045
8 changed files with 332 additions and 35 deletions

View File

@ -18,6 +18,7 @@
#include "command_func.h"
#include "vehicle_base.h"
#include "viewport_kdtree.h"
#include "platform_func.h"
#include "safeguards.h"
@ -212,6 +213,30 @@ void Depot::AfterAddRemove(TileArea ta, bool adding)
InvalidateWindowData(WC_SELECT_DEPOT, veh_type);
}
/**
* Check whether a tile is a destination tile, such as the starting tiles of
* rail platforms (and not the middle tiles of the platforms).
* @param dep The depot being checked
* @param tile The tile being checked
* @return Whether the tile is of the given depot.
*/
bool IsDepotDestTile(Depot *dep, TileIndex tile)
{
assert(IsDepotTile(tile));
assert(GetDepotIndex(tile) == dep->index);
switch (dep->veh_type) {
case VEH_TRAIN:
assert(IsRailDepotTile(tile));
return !IsExtendedRailDepot(tile) || IsAnyStartPlatformTile(tile);
case VEH_ROAD:
case VEH_SHIP:
case VEH_AIRCRAFT:
return true;
default: NOT_REACHED();
}
}
/**
* Rescan depot_tiles. Done after AfterAddRemove and SaveLoad.
* Updates the tiles of the depot and its railtypes/roadtypes...
@ -225,7 +250,7 @@ void Depot::RescanDepotTiles()
for (TileIndex tile : this->ta) {
if (!IsDepotTile(tile)) continue;
if (GetDepotIndex(tile) != this->index) continue;
this->depot_tiles.push_back(tile);
if (IsDepotDestTile(this, tile)) this->depot_tiles.push_back(tile);
switch (veh_type) {
case VEH_ROAD:
this->r_types.road_types |= GetPresentRoadTypes(tile);
@ -268,8 +293,12 @@ void UpdateExtendedDepotReservation(Vehicle *v, bool reserve)
SetDepotReservation(v->tile, res_type);
break;
case VEH_TRAIN:
case VEH_TRAIN: {
DiagDirection dir = GetRailDepotDirection(v->tile);
SetDepotReservation(GetPlatformExtremeTile(v->tile, dir), res_type);
SetDepotReservation(GetPlatformExtremeTile(v->tile, ReverseDiagDir(dir)), res_type);
break;
}
case VEH_AIRCRAFT:
break;

View File

@ -47,7 +47,8 @@ struct CFollowTrackT
bool m_is_tunnel; ///< last turn passed tunnel
bool m_is_bridge; ///< last turn passed bridge ramp
bool m_is_station; ///< last turn passed station
int m_tiles_skipped; ///< number of skipped tunnel or station tiles
bool m_is_extended_depot; ///< last turn passed depot
int m_tiles_skipped; ///< number of skipped tunnel, depot or station tiles
ErrorCode m_err;
RailTypes m_railtypes;
@ -81,7 +82,7 @@ struct CFollowTrackT
m_new_tile = INVALID_TILE;
m_new_td_bits = TRACKDIR_BIT_NONE;
m_exitdir = INVALID_DIAGDIR;
m_is_station = m_is_bridge = m_is_tunnel = false;
m_is_station = m_is_bridge = m_is_tunnel = m_is_extended_depot = false;
m_tiles_skipped = 0;
m_err = EC_NONE;
m_railtypes = railtype_override;
@ -171,11 +172,11 @@ struct CFollowTrackT
{
if (!DoTrackMasking()) return true;
if (m_is_station) {
/* Check skipped station tiles as well. */
if (m_is_station || m_is_extended_depot) {
/* Check skipped station and depot tiles as well. */
TileIndexDiff diff = TileOffsByDiagDir(m_exitdir);
for (TileIndex tile = m_new_tile - diff * m_tiles_skipped; tile != m_new_tile; tile += diff) {
if (HasStationReservation(tile)) {
if ((m_is_station && HasStationReservation(tile)) || (m_is_extended_depot && HasDepotReservation(tile))) {
m_new_td_bits = TRACKDIR_BIT_NONE;
m_err = EC_RESERVED;
return false;
@ -201,7 +202,7 @@ protected:
/** Follow the m_exitdir from m_old_tile and fill m_new_tile and m_tiles_skipped */
inline void FollowTileExit()
{
m_is_station = m_is_bridge = m_is_tunnel = false;
m_is_station = m_is_bridge = m_is_tunnel = m_is_extended_depot = false;
m_tiles_skipped = 0;
/* extra handling for tunnels and bridges in our direction */
@ -225,9 +226,13 @@ protected:
/* normal or station tile, do one step */
m_new_tile = TileAddByDiagDir(m_old_tile, m_exitdir);
/* special handling for stations */
if (IsRailTT() && HasStationTileRail(m_new_tile)) {
m_is_station = true;
/* special handling for stations and multi-tile depots */
if (IsRailTT()) {
if (HasStationTileRail(m_new_tile)) {
m_is_station = true;
} else if (IsExtendedRailDepotTile(m_new_tile)) {
m_is_extended_depot = true;
}
} else if (IsRoadTT() && IsStationRoadStopTile(m_new_tile)) {
m_is_station = true;
}
@ -369,13 +374,14 @@ protected:
}
}
/* special handling for rail stations - get to the end of platform */
if (IsRailTT() && m_is_station) {
/* special handling for rail platforms - get to the end of platform */
if (IsRailTT() && (m_is_station || m_is_extended_depot)) {
/* Entered a platform. */
assert(HasStationTileRail(m_new_tile));
assert(HasStationTileRail(m_new_tile) || IsExtendedRailDepotTile(m_new_tile));
/* How big step we must do to get to the last platform tile? */
m_tiles_skipped = GetPlatformLength(m_new_tile, TrackdirToExitdir(m_old_td)) - 1;
/* Move to the platform end. */
TileIndexDiff diff = TileOffsByDiagDir(m_exitdir);
diff *= m_tiles_skipped;
m_new_tile = TileAdd(m_new_tile, diff);
@ -390,14 +396,27 @@ protected:
{
/* rail and road depots cause reversing */
if (!IsWaterTT() && IsDepotTypeTile(m_old_tile, TT())) {
DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(m_old_tile) : GetRoadDepotDirection(m_old_tile);
DiagDirection exitdir;
switch (TT()) {
case TRANSPORT_AIR:
return false;
case TRANSPORT_RAIL:
if (IsExtendedRailDepot(m_old_tile)) return false;
exitdir = GetRailDepotDirection(m_old_tile);
break;
case TRANSPORT_ROAD:
exitdir = GetRoadDepotDirection(m_old_tile);
break;
default: NOT_REACHED();
}
if (exitdir != m_exitdir) {
/* reverse */
m_new_tile = m_old_tile;
m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(m_old_td));
m_exitdir = exitdir;
m_tiles_skipped = 0;
m_is_tunnel = m_is_bridge = m_is_station = false;
m_is_tunnel = m_is_bridge = m_is_station = m_is_extended_depot = false;
return true;
}
}

View File

@ -439,7 +439,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* Waypoint is also a good reason to finish. */
end_segment_reason |= ESRB_WAYPOINT;
} else if (tf->m_is_station) {
} else if (tf->m_is_station || tf->m_is_extended_depot) {
/* Station penalties. */
uint platform_length = tf->m_tiles_skipped + 1;
/* We don't know yet if the station is our target or not. Act like
@ -592,7 +592,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* Platform-length penalty. */
if ((end_segment_reason & ESRB_STATION) != ESRB_NONE) {
assert(HasStationTileRail(n.GetLastTile()));
assert(HasStationTileRail(n.GetLastTile()) || IsExtendedRailDepotTile(n.GetLastTile()));
uint platform_length = GetPlatformLength(n.GetLastTile(), ReverseDiagDir(TrackdirToExitdir(n.GetLastTrackdir())));
/* Reduce the extra cost caused by passing-platform penalty (each platform receives it in the segment cost). */
extra_cost -= Yapf().PfGetSettings().rail_station_penalty * platform_length;

View File

@ -12,6 +12,8 @@
#include "vehicle_func.h"
#include "newgrf_station.h"
#include "pathfinder/follow_track.hpp"
#include "platform_func.h"
#include "depot_map.h"
#include "safeguards.h"
@ -180,12 +182,12 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
/* No reservation --> path end found */
if (reserved == TRACKDIR_BIT_NONE) {
if (ft.m_is_station) {
if (ft.m_is_station || ft.m_is_extended_depot) {
/* Check skipped station tiles as well, maybe our reservation ends inside the station. */
TileIndexDiff diff = TileOffsByDiagDir(ft.m_exitdir);
while (ft.m_tiles_skipped-- > 0) {
ft.m_new_tile -= diff;
if (HasStationReservation(ft.m_new_tile)) {
if ((ft.m_is_station && HasStationReservation(ft.m_new_tile)) || (ft.m_is_extended_depot && HasDepotReservation(ft.m_new_tile))) {
tile = ft.m_new_tile;
trackdir = DiagDirToDiagTrackdir(ft.m_exitdir);
break;
@ -278,14 +280,14 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
if (train_on_res != nullptr) {
FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
if (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
if (*train_on_res == nullptr && IsRailStationTile(ftoti.res.tile)) {
/* The target tile is a rail station. The track follower
if (*train_on_res == nullptr && (IsRailStationTile(ftoti.res.tile) || IsExtendedRailDepotTile(ftoti.res.tile))) {
/* The target tile is a rail station or extended depot. The track follower
* has stopped on the last platform tile where we haven't
* found a train. Also check all previous platform tiles
* for a possible train. */
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
for (TileIndex st_tile = ftoti.res.tile + diff; *train_on_res == nullptr && IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
for (TileIndex pt_tile = ftoti.res.tile + diff; *train_on_res == nullptr && IsCompatiblePlatformTile(pt_tile, ftoti.res.tile); pt_tile += diff) {
FindVehicleOnPos(pt_tile, &ftoti, FindTrainOnTrackEnum);
if (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
}
}
@ -326,11 +328,11 @@ Train *GetTrainForReservation(TileIndex tile, Track track)
FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
if (ftoti.best != nullptr) return ftoti.best;
/* Special case for stations: check the whole platform for a vehicle. */
if (IsRailStationTile(ftoti.res.tile)) {
/* Special case for stations and extended depots: check the whole platform for a vehicle. */
if (IsRailStationTile(ftoti.res.tile) || IsExtendedRailDepotTile(ftoti.res.tile)) {
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
for (TileIndex pt_tile = ftoti.res.tile + diff; IsCompatiblePlatformTile(pt_tile, ftoti.res.tile); pt_tile += diff) {
FindVehicleOnPos(pt_tile, &ftoti, FindTrainOnTrackEnum);
if (ftoti.best != nullptr) return ftoti.best;
}
}

View File

@ -11,6 +11,9 @@
#include "station_map.h"
#include "platform_func.h"
#include "viewport_func.h"
#include "depot_base.h"
#include "vehicle_base.h"
#include "engine_base.h"
/**
* Set the reservation for a complete station platform.
@ -34,6 +37,29 @@ void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool
} while (IsCompatibleTrainStationTile(tile, start));
}
/**
* Set the reservation for a complete depot platform.
* @pre IsExtendedRailDepotTile(start)
* @param start starting tile of the platform
* @param dir the direction in which to follow the platform
* @param b the state the reservation should be set to
*/
void SetRailDepotPlatformReservation(TileIndex start, DiagDirection dir, bool b)
{
TileIndex tile = start;
TileIndexDiff diff = TileOffsByDiagDir(dir);
assert(IsExtendedRailDepotTile(start));
assert(GetRailDepotTrack(start) == DiagDirToDiagTrack(dir));
do {
SetDepotReservation(tile, b);
MarkTileDirtyByTile(tile);
tile = TileAdd(tile, diff);
} while (IsCompatibleTrainDepotTile(tile, start));
}
/**
* Set the reservation for a complete platform in a given direction.
* @param start starting tile of the platform
@ -49,6 +75,32 @@ void SetPlatformReservation(TileIndex start, DiagDirection dir, bool b)
case PT_RAIL_WAYPOINT:
SetRailStationReservation(start, b);
return;
case PT_RAIL_DEPOT:
SetRailDepotPlatformReservation(start, dir, b);
return;
default: NOT_REACHED();
}
}
/**
* Set the reservation for a complete platform.
* @param start A tile of the platform
* @param b the state the reservation should be set to
*/
void SetPlatformReservation(TileIndex start, bool b)
{
DiagDirection dir;
switch (GetPlatformType(start)) {
case PT_RAIL_STATION:
NOT_REACHED();
case PT_RAIL_WAYPOINT:
NOT_REACHED();
case PT_RAIL_DEPOT:
assert(IsExtendedRailDepotTile(start));
dir = GetRailDepotDirection(start);
SetRailDepotPlatformReservation(start, dir, b);
SetRailDepotPlatformReservation(start, ReverseDiagDir(dir), b);
return;
default: NOT_REACHED();
}
}
@ -103,6 +155,57 @@ uint GetRailStationPlatformLength(TileIndex tile, DiagDirection dir)
return length;
}
/**
* Get the length of a rail depot platform.
* @pre IsDepotTypeTile(tile, TRANSPORT_RAIL)
* @param tile Tile to check
* @return The length of the platform in tile length.
*/
uint GetRailDepotPlatformLength(TileIndex tile)
{
assert(IsExtendedRailDepotTile(tile));
TileIndexDiff delta = (GetRailDepotTrack(tile) == TRACK_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
TileIndex t = tile;
uint len = 0;
do {
t -= delta;
len++;
} while (IsCompatibleTrainDepotTile(t, tile));
t = tile;
do {
t += delta;
len++;
} while (IsCompatibleTrainDepotTile(t, tile));
return len - 1;
}
/**
* Get the length of a rail depot platform in a given direction.
* @pre IsRailDepotTile(tile)
* @param tile Tile to check
* @param dir Direction to check
* @return The length of the platform in tile length in the given direction.
*/
uint GetRailDepotPlatformLength(TileIndex tile, DiagDirection dir)
{
TileIndex start_tile = tile;
uint length = 0;
assert(IsExtendedRailDepotTile(tile));
assert(dir < DIAGDIR_END);
do {
length++;
tile += TileOffsByDiagDir(dir);
} while (IsCompatibleTrainDepotTile(tile, start_tile));
return length;
}
/**
* Get the length of a platform.
* @param tile Tile to check
@ -115,6 +218,8 @@ uint GetPlatformLength(TileIndex tile)
return GetRailStationPlatformLength(tile);
case PT_RAIL_WAYPOINT:
return 1;
case PT_RAIL_DEPOT:
return GetRailDepotPlatformLength(tile);
default: NOT_REACHED();
}
}
@ -133,6 +238,106 @@ uint GetPlatformLength(TileIndex tile, DiagDirection dir)
return GetRailStationPlatformLength(tile, dir);
case PT_RAIL_WAYPOINT:
return 1;
case PT_RAIL_DEPOT:
return GetRailDepotPlatformLength(tile, dir);
default: NOT_REACHED();
}
}
/**
* Get a tile where a rail station platform begins or ends.
* @pre IsRailStationTile(tile)
* @param tile Tile to check
* @param dir The diagonal direction to check
* @return The last tile of the platform seen from tile with direction dir.
*/
TileIndex GetRailStationExtreme(TileIndex tile, DiagDirection dir)
{
assert(IsRailStationTile(tile));
assert(GetRailStationAxis(tile) == DiagDirToAxis(dir));
TileIndexDiff delta = TileOffsByDiagDir(dir);
TileIndex t = tile;
do {
t -= delta;
} while (IsCompatibleTrainStationTile(t, tile));
return t + delta;
}
/**
* Get a tile where a depot platform begins or ends.
* @pre IsExtendedDepotTile(tile)
* @param tile Tile to check
* @param dir The diagonal direction to check
* @return The last tile of the platform seen from tile with direction dir.
*/
TileIndex GetRailDepotExtreme(TileIndex tile, DiagDirection dir)
{
assert(IsExtendedDepotTile(tile));
assert(GetRailDepotTrack(tile) == DiagDirToDiagTrack(dir));
TileIndexDiff delta = TileOffsByDiagDir(dir);
TileIndex t = tile;
do {
t -= delta;
} while (IsCompatibleTrainDepotTile(t, tile));
return t + delta;
}
/**
* Get a tile where a platform begins or ends.
* @param tile Tile to check
* @param dir Direction to check
* @return The last tile of the platform seen from tile with direction dir.
*/
TileIndex GetPlatformExtremeTile(TileIndex tile, DiagDirection dir)
{
switch (GetPlatformType(tile)) {
case PT_RAIL_STATION:
return GetRailStationExtreme(tile, dir);
case PT_RAIL_WAYPOINT:
return tile;
case PT_RAIL_DEPOT:
return GetRailDepotExtreme(tile, dir);
default: NOT_REACHED();
}
}
/**
* Get the tiles belonging to a platform.
* @param tile Tile of a platform
* @return the tile area of the platform
*/
TileArea GetPlatformTileArea(TileIndex tile)
{
switch (GetPlatformType(tile)) {
case PT_RAIL_STATION: {
assert(IsRailStationTile(tile));
DiagDirection dir = AxisToDiagDir(GetRailStationAxis(tile));
return TileArea(GetRailStationExtreme(tile, dir), GetRailStationExtreme(tile, ReverseDiagDir(dir)));
}
case PT_RAIL_WAYPOINT:
return TileArea(tile);
case PT_RAIL_DEPOT: {
assert(IsExtendedRailDepotTile(tile));
DiagDirection dir = GetRailDepotDirection(tile);
return TileArea(GetRailDepotExtreme(tile, dir), GetRailDepotExtreme(tile, ReverseDiagDir(dir)));
}
default: NOT_REACHED();
}
}
/**
* Check whether this tile is an extreme of a platform.
* @param tile Tile to check
* @return Whether the tile is the extreme of a platform.
*/
bool IsAnyStartPlatformTile(TileIndex tile)
{
assert(IsExtendedRailDepotTile(tile));
DiagDirection dir = GetRailDepotDirection(tile);
return tile == GetPlatformExtremeTile(tile, dir) || tile == GetPlatformExtremeTile(tile, ReverseDiagDir(dir));
}

View File

@ -11,6 +11,7 @@
#define PLATFORM_FUNC_H
#include "station_map.h"
#include "depot_map.h"
#include "platform_type.h"
/**
@ -35,6 +36,27 @@ static inline bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex s
GetStationIndex(test_tile) == GetStationIndex(station_tile);
}
/**
* Check if a tile is a valid continuation to an extended rail depot tile.
* The tile \a test_tile is a valid continuation to \a depot_tile, if all of the following are true:
* \li \a test_tile is an extended depot tile
* \li \a test_tile and \a depot_tile have the same rail type
* \li the tracks on \a test_tile and \a depot_tile are in the same direction
* \li both tiles belong to the same depot
* @param test_tile Tile to test
* @param depot_tile Depot tile to compare with
* @pre IsExtendedRailDepotTile(depot_tile)
* @return true if the two tiles are compatible
*/
static inline bool IsCompatibleTrainDepotTile(TileIndex test_tile, TileIndex depot_tile)
{
assert(IsExtendedRailDepotTile(depot_tile));
return IsExtendedRailDepotTile(test_tile) &&
GetRailType(test_tile) == GetRailType(depot_tile) &&
GetRailDepotTrack(test_tile) == GetRailDepotTrack(depot_tile) &&
GetDepotIndex(test_tile) == GetDepotIndex(depot_tile);
}
/**
* Returns the type of platform of a given tile.
* @param tile Tile to check
@ -47,6 +69,9 @@ static inline PlatformType GetPlatformType(TileIndex tile)
if (IsRailStation(tile)) return PT_RAIL_STATION;
if (IsRailWaypoint(tile)) return PT_RAIL_WAYPOINT;
break;
case MP_RAILWAY:
if (IsExtendedRailDepotTile(tile)) return PT_RAIL_DEPOT;
break;
default: break;
}
@ -74,6 +99,8 @@ static inline bool HasPlatformReservation(TileIndex tile)
case PT_RAIL_STATION:
case PT_RAIL_WAYPOINT:
return HasStationReservation(tile);
case PT_RAIL_DEPOT:
return HasDepotReservation(tile);
default: NOT_REACHED();
}
}
@ -92,13 +119,21 @@ static inline bool IsCompatiblePlatformTile(TileIndex test_tile, TileIndex orig_
return IsCompatibleTrainStationTile(test_tile, orig_tile);
case PT_RAIL_WAYPOINT:
return test_tile == orig_tile;
case PT_RAIL_DEPOT:
return IsCompatibleTrainDepotTile(test_tile, orig_tile);
default: NOT_REACHED();
}
}
void SetPlatformReservation(TileIndex start, DiagDirection dir, bool b);
void SetPlatformReservation(TileIndex start, bool b);
uint GetPlatformLength(TileIndex tile);
uint GetPlatformLength(TileIndex tile, DiagDirection dir);
TileIndex GetPlatformExtremeTile(TileIndex tile, DiagDirection dir);
TileArea GetPlatformTileArea(TileIndex tile);
bool IsAnyStartPlatformTile(TileIndex tile);
#endif /* PLATFORM_FUNC_H */

View File

@ -15,6 +15,7 @@
enum PlatformType {
PT_RAIL_STATION,
PT_RAIL_WAYPOINT,
PT_RAIL_DEPOT,
PT_END,
INVALID_PLATFORM_TYPE = PT_END,
};

View File

@ -40,6 +40,7 @@
#include "timer/timer_game_economy.h"
#include "depot_base.h"
#include "platform_func.h"
#include "depot_map.h"
#include "table/strings.h"
#include "table/train_sprites.h"
@ -2419,7 +2420,7 @@ static bool CheckTrainStayInDepot(Train *v)
{
/* bail out if not all wagons are in the same depot or not in a depot at all */
for (const Train *u = v; u != nullptr; u = u->Next()) {
if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
if (!u->IsInDepot() || u->tile != v->tile) return false;
}
/* if the train got no power, then keep it in the depot */
@ -2523,7 +2524,7 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_
}
}
}
} else if (IsRailStationTile(tile)) {
} else if (IsRailStationTile(tile) || IsExtendedRailDepotTile(tile)) {
TileIndex new_tile = TileAddByDiagDir(tile, dir);
/* If the new tile is not a further tile of the same station, we
* clear the reservation for the whole platform. */
@ -2546,8 +2547,9 @@ void FreeTrainTrackReservation(const Train *v)
TileIndex tile = v->tile;
Trackdir td = v->GetVehicleTrackdir();
bool free_tile = !(IsRailStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
bool free_tile = !(IsRailStationTile(v->tile) || IsExtendedRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
StationID station_id = IsRailStationTile(v->tile) ? GetStationIndex(v->tile) : INVALID_STATION;
DepotID depot_id = IsExtendedRailDepotTile(v->tile) ? GetDepotIndex(v->tile) : INVALID_DEPOT;
/* Can't be holding a reservation if we enter a depot. */
if (IsStandardRailDepotTile(tile) && TrackdirToExitdir(td) != GetRailDepotDirection(tile)) return;
@ -2590,7 +2592,7 @@ void FreeTrainTrackReservation(const Train *v)
}
/* Don't free first station/bridge/tunnel if we are on it. */
if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td);
if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !(ft.m_is_extended_depot && GetDepotIndex(ft.m_new_tile) == depot_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td);
free_tile = true;
}
@ -2649,7 +2651,7 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
}
/* Station, depot or waypoint are a possible target. */
bool target_seen = ft.m_is_station || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile));
bool target_seen = ft.m_is_station || ft.m_is_extended_depot || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile));
if (target_seen || KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
/* Choice found or possible target encountered.
* On finding a possible target, we need to stop and let the pathfinder handle the
@ -4358,9 +4360,13 @@ Trackdir Train::GetVehicleTrackdir() const
{
if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
if (this->track == TRACK_BIT_DEPOT) {
if (this->IsInDepot()) {
/* We'll assume the train is facing outwards */
return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot
if (this->track == TRACK_BIT_DEPOT)
return DiagDirToDiagTrackdir(DirToDiagDir(this->direction)); // Train in depot
Track track = FindFirstTrack(this->track & ~TRACK_BIT_DEPOT);
assert(IsValidTrack(track));
return TrackDirectionToTrackdir(track, this->direction);
}
if (this->track == TRACK_BIT_WORMHOLE) {