summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rail_cmd.cpp46
1 files changed, 42 insertions, 4 deletions
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index 024fd620d..f88090ad2 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -78,6 +78,44 @@ const byte _track_sloped_sprites[14] = {
* 11uuuudd => rail depot
*/
+/** Struct used in EnsureNoTrainOnTrack() */
+struct TrainOnTrackData {
+ TileIndex tile; ///< tile to check
+ uint z; ///< tile max Z
+ TrackBits rail_bits; ///< trackbits of interest
+};
+
+static void *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
+{
+ const TrainOnTrackData *info = (const TrainOnTrackData *)data;
+
+ if (v->tile != info->tile || v->type != VEH_TRAIN) return NULL;
+ if (v->z_pos > info->z) return NULL;
+
+ if ((v->u.rail.track != info->rail_bits) && !TracksOverlap(v->u.rail.track | info->rail_bits)) return NULL;
+
+ _error_message = VehicleInTheWayErrMsg(v);
+ return v;
+}
+
+/**
+ * Tests if a vehicle interacts with the specified track.
+ * All track bits interact except parallel TRACK_BIT_HORZ or TRACK_BIT_VERT.
+ *
+ * @param tile The tile.
+ * @param track The track.
+ */
+static bool EnsureNoTrainOnTrack(TileIndex tile, Track track)
+{
+ TrainOnTrackData info;
+
+ info.tile = tile;
+ info.z = GetTileMaxZ(tile);
+ info.rail_bits = TrackToTrackBits(track);
+
+ return VehicleFromPos(tile, &info, EnsureNoTrainOnTrackProc) == NULL;
+}
+
static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
{
TrackBits current; // The current track layout
@@ -239,7 +277,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p
switch (GetTileType(tile)) {
case MP_RAILWAY:
if (!CheckTrackCombination(tile, trackbit, flags) ||
- !EnsureNoVehicleOnGround(tile)) {
+ !EnsureNoTrainOnTrack(tile, track)) {
return CMD_ERROR;
}
if (!IsTileOwner(tile, _current_player) ||
@@ -374,7 +412,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32
if (!IsPlainRailTile(tile) ||
(_current_player != OWNER_WATER && !CheckTileOwnership(tile)) ||
- !EnsureNoVehicleOnGround(tile)) {
+ !EnsureNoTrainOnTrack(tile, track)) {
return CMD_ERROR;
}
@@ -647,7 +685,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32
SignalVariant sigvar = (pre_signal ^ HASBIT(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC;
CommandCost cost;
- if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoVehicleOnGround(tile))
+ if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track))
return CMD_ERROR;
/* Protect against invalid signal copying */
@@ -935,7 +973,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint3
if (!ValParamTrackOrientation(track) ||
!IsTileType(tile, MP_RAILWAY) ||
- !EnsureNoVehicleOnGround(tile) ||
+ !EnsureNoTrainOnTrack(tile, track) ||
!HasSignalOnTrack(tile, track)) {
return CMD_ERROR;
}