diff --git a/src/autoslope.h b/src/autoslope.h index 5d4eeb35f2..e9bfa140f3 100644 --- a/src/autoslope.h +++ b/src/autoslope.h @@ -33,7 +33,7 @@ */ static inline bool AutoslopeCheckForEntranceEdge(TileIndex tile, uint z_new, Slope tileh_new, DiagDirection entrance) { - if (IsSteepSlope(tileh_new) || (GetTileMaxZ(tile) != z_new + GetSlopeMaxZ(tileh_new))) return false; + if (GetTileMaxZ(tile) != z_new + GetSlopeMaxZ(tileh_new)) return false; return ((tileh_new == SLOPE_FLAT) || CanBuildDepotByTileh(entrance, tileh_new)); } diff --git a/src/depot_func.h b/src/depot_func.h index c11901025b..cb48e3a4de 100644 --- a/src/depot_func.h +++ b/src/depot_func.h @@ -26,19 +26,14 @@ void DeleteDepotHighlightOfVehicle(const Vehicle *v); * @param direction The direction in which the depot's exit points * @param tileh The slope of the tile in question * @return true if the construction is possible - - * This is checked by the ugly 0x4C >> direction magic, which does the following: - * 0x4C is 0100 1100 and tileh has only bits 0..3 set (steep tiles are ruled out) - * So: for direction (only the significant bits are shown)

- * 00 (exit towards NE) we need either bit 2 or 3 set in tileh: 0x4C >> 0 = 1100

- * 01 (exit towards SE) we need either bit 1 or 2 set in tileh: 0x4C >> 1 = 0110

- * 02 (exit towards SW) we need either bit 0 or 1 set in tileh: 0x4C >> 2 = 0011

- * 03 (exit towards NW) we need either bit 0 or 4 set in tileh: 0x4C >> 3 = 1001

- * So ((0x4C >> direction) & tileh) determines whether the depot can be built on the current tileh */ static inline bool CanBuildDepotByTileh(DiagDirection direction, Slope tileh) { - return ((0x4C >> direction) & tileh) != 0; + assert(tileh != SLOPE_FLAT); + Slope entrance_corners = InclinedSlope(direction); + /* For steep slopes both entrance corners must be raised (i.e. neither of them is the lowest corner), + * For non-steep slopes at least one corner must be raised. */ + return IsSteepSlope(tileh) ? (tileh & entrance_corners) == entrance_corners : (tileh & entrance_corners) != 0; } #endif /* DEPOT_FUNC_H */ diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index c81b212b72..7ca5a5949a 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -168,7 +168,7 @@ void UpdateObjectColours(const Company *c) } } -extern CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool check_bridge); +extern CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool allow_steep, bool check_bridge); static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags); /** @@ -238,7 +238,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 } if (callback == CALLBACK_FAILED) { - cost.AddCost(CheckBuildableTile(t, 0, allowed_z, false)); + cost.AddCost(CheckBuildableTile(t, 0, allowed_z, false, false)); } else if (callback != 0) { /* The meaning of bit 10 is inverted in the result of this callback. */ return GetErrorMessageFromLocationCallbackResult(ToggleBit(callback, 10), spec->grf_prop.grffile->grfid, STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 95ff6440f8..35895c38a0 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -874,7 +874,6 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (tileh != SLOPE_FLAT && ( !_settings_game.construction.build_on_slopes || - IsSteepSlope(tileh) || !CanBuildDepotByTileh(dir, tileh) )) { return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); @@ -2338,15 +2337,15 @@ void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype) static uint GetSlopeZ_Track(TileIndex tile, uint x, uint y) { - uint z; - Slope tileh = GetTileSlope(tile, &z); - - if (tileh == SLOPE_FLAT) return z; if (IsPlainRail(tile)) { + uint z; + Slope tileh = GetTileSlope(tile, &z); + if (tileh == SLOPE_FLAT) return z; + z += ApplyFoundationToSlope(GetRailFoundation(tileh, GetTrackBits(tile)), &tileh); return z + GetPartialZ(x & 0xF, y & 0xF, tileh); } else { - return z + TILE_HEIGHT; + return GetTileMaxZ(tile); } } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 64e59640c2..e9276e8094 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -918,7 +918,6 @@ CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, ui Slope tileh = GetTileSlope(tile, NULL); if (tileh != SLOPE_FLAT && ( !_settings_game.construction.build_on_slopes || - IsSteepSlope(tileh) || !CanBuildDepotByTileh(dir, tileh) )) { return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); @@ -1343,16 +1342,17 @@ void UpdateNearestTownForRoadTiles(bool invalidate) static uint GetSlopeZ_Road(TileIndex tile, uint x, uint y) { - uint z; - Slope tileh = GetTileSlope(tile, &z); - if (tileh == SLOPE_FLAT) return z; if (IsNormalRoad(tile)) { + uint z; + Slope tileh = GetTileSlope(tile, &z); + if (tileh == SLOPE_FLAT) return z; + Foundation f = GetRoadFoundation(tileh, GetAllRoadBits(tile)); z += ApplyFoundationToSlope(f, &tileh); return z + GetPartialZ(x & 0xF, y & 0xF, tileh); } else { - return z + TILE_HEIGHT; + return GetTileMaxZ(tile); } } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 452dbe9da0..5f140365b3 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -672,10 +672,11 @@ CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags); * @param tile TileIndex to check. * @param invalid_dirs Prohibited directions for slopes (set of #DiagDirection). * @param allowed_z Height allowed for the tile. If allowed_z is negative, it will be set to the height of this tile. + * @param allow_steep Whether steep slopes are allowed. * @param check_bridge Check for the existance of a bridge. * @return The cost in case of success, or an error code if it failed. */ -CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool check_bridge = true) +CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool allow_steep, bool check_bridge = true) { if (check_bridge && MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) { return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); @@ -691,23 +692,21 @@ CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z * 1) The tile is "steep" (i.e. stretches two height levels). * 2) The tile is non-flat and the build_on_slopes switch is disabled. */ - if (IsSteepSlope(tileh) || + if ((!allow_steep && IsSteepSlope(tileh)) || ((!_settings_game.construction.build_on_slopes) && tileh != SLOPE_FLAT)) { return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); } CommandCost cost(EXPENSES_CONSTRUCTION); - int flat_z = z; + int flat_z = z + GetSlopeMaxZ(tileh); if (tileh != SLOPE_FLAT) { /* Forbid building if the tile faces a slope in a invalid direction. */ - if ((HasBit(invalid_dirs, DIAGDIR_NE) && !(tileh & SLOPE_NE)) || - (HasBit(invalid_dirs, DIAGDIR_SE) && !(tileh & SLOPE_SE)) || - (HasBit(invalid_dirs, DIAGDIR_SW) && !(tileh & SLOPE_SW)) || - (HasBit(invalid_dirs, DIAGDIR_NW) && !(tileh & SLOPE_NW))) { - return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); + for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) { + if (HasBit(invalid_dirs, dir) && !CanBuildDepotByTileh(dir, tileh)) { + return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); + } } cost.AddCost(_price[PR_BUILD_FOUNDATION]); - flat_z += TILE_HEIGHT; } /* The level of this tile must be equal to allowed_z. */ @@ -733,7 +732,7 @@ CommandCost CheckFlatLand(TileArea tile_area, DoCommandFlag flags) int allowed_z = -1; TILE_AREA_LOOP(tile_cur, tile_area) { - CommandCost ret = CheckBuildableTile(tile_cur, 0, allowed_z); + CommandCost ret = CheckBuildableTile(tile_cur, 0, allowed_z, true); if (ret.Failed()) return ret; cost.AddCost(ret); @@ -769,7 +768,7 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl bool slope_cb = statspec != NULL && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK); TILE_AREA_LOOP(tile_cur, tile_area) { - CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z); + CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false); if (ret.Failed()) return ret; cost.AddCost(ret); @@ -851,7 +850,7 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags int allowed_z = -1; TILE_AREA_LOOP(cur_tile, tile_area) { - CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z); + CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through); if (ret.Failed()) return ret; cost.AddCost(ret); @@ -3586,7 +3585,7 @@ static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, ui /* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here. * TTDP does not call it. */ - if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) { + if (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) { switch (GetStationType(tile)) { case STATION_WAYPOINT: case STATION_RAIL: {