diff -r a4ad48192617 -r 7eb395287b3d src/rail_cmd.cpp --- 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 */ };