--- a/src/rail_cmd.cpp Mon Aug 27 16:28:33 2007 +0000
+++ b/src/rail_cmd.cpp Sun Sep 02 11:58:58 2007 +0000
@@ -78,6 +78,44 @@
* 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 @@
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 @@
if (!IsPlainRailTile(tile) ||
(_current_player != OWNER_WATER && !CheckTileOwnership(tile)) ||
- !EnsureNoVehicleOnGround(tile)) {
+ !EnsureNoTrainOnTrack(tile, track)) {
return CMD_ERROR;
}
@@ -647,7 +685,7 @@
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 @@
if (!ValParamTrackOrientation(track) ||
!IsTileType(tile, MP_RAILWAY) ||
- !EnsureNoVehicleOnGround(tile) ||
+ !EnsureNoTrainOnTrack(tile, track) ||
!HasSignalOnTrack(tile, track)) {
return CMD_ERROR;
}
@@ -2118,7 +2156,7 @@
v->u.rail.track = TRACK_BIT_DEPOT,
v->vehstatus |= VS_HIDDEN; /* hide it */
v->direction = ReverseDir(v->direction);
- if (v->next == NULL) VehicleEnterDepot(v);
+ if (v->Next() == NULL) VehicleEnterDepot(v);
v->tile = tile;
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
@@ -2127,7 +2165,7 @@
} else if (fract_coord_leave == fract_coord) {
if (DiagDirToDir(dir) == v->direction) {
/* leave the depot? */
- if ((v = v->next) != NULL) {
+ if ((v = v->Next()) != NULL) {
v->vehstatus &= ~VS_HIDDEN;
v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
}
@@ -2137,6 +2175,73 @@
return VETSB_CONTINUE;
}
+static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
+{
+ if (IsPlainRailTile(tile)) {
+ uint z_old;
+ Slope tileh_old = GetTileSlope(tile, &z_old);
+ TrackBits rail_bits = GetTrackBits(tile);
+
+ _error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
+
+ /* When there is only a single horizontal/vertical track, one corner can be terraformed. */
+ Slope allowed_corner;
+ switch (rail_bits) {
+ case TRACK_BIT_RIGHT: allowed_corner = SLOPE_W; break;
+ case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
+ case TRACK_BIT_LEFT: allowed_corner = SLOPE_E; break;
+ case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
+ default: return CMD_ERROR;
+ }
+
+ Slope track_corners = ComplementSlope(allowed_corner);
+
+ Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
+ switch (f_old) {
+ case FOUNDATION_NONE:
+ /* Everything is valid, which only changes allowed_corner */
+
+ /* Compute height of track */
+ if (tileh_old == track_corners) z_old += TILE_HEIGHT;
+ if (tileh_new == track_corners) {
+ z_new += TILE_HEIGHT;
+ } else {
+ /* do not build a foundation */
+ if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return CMD_ERROR;
+ }
+
+ /* Track height must remain unchanged */
+ if (z_old != z_new) return CMD_ERROR;
+ break;
+
+ case FOUNDATION_LEVELED:
+ /* Is allowed_corner covered by the foundation? */
+ if ((tileh_old & allowed_corner) == 0) return CMD_ERROR;
+
+ /* allowed_corner may only be raised -> steep slope */
+ if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return CMD_ERROR;
+ break;
+
+ case FOUNDATION_STEEP_LOWER:
+ /* Only allow to lower highest corner */
+ if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return CMD_ERROR;
+ break;
+
+ case FOUNDATION_STEEP_HIGHER:
+ return CMD_ERROR;
+
+ default: NOT_REACHED();
+ }
+
+ /* Make the ground dirty */
+ if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
+
+ /* allow terraforming, no extra costs */
+ return CommandCost();
+ }
+ return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+}
+
extern const TileTypeProcs _tile_type_rail_procs = {
DrawTile_Track, /* draw_tile_proc */
@@ -2152,4 +2257,5 @@
NULL, /* get_produced_cargo_proc */
VehicleEnter_Track, /* vehicle_enter_tile_proc */
GetFoundation_Track, /* get_foundation_proc */
+ TerraformTile_Track, /* terraform_tile_proc */
};