src/rail_cmd.cpp
branchNewGRF_ports
changeset 6868 7eb395287b3d
parent 6743 cabfaa4a0295
child 6870 ca3fd1fbe311
--- 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 */
 };