diff --git a/src/depot_type.h b/src/depot_type.h index fd46bf1418..8a9992f530 100644 --- a/src/depot_type.h +++ b/src/depot_type.h @@ -17,4 +17,7 @@ struct Depot; static const uint MAX_LENGTH_DEPOT_NAME_CHARS = 32; ///< The maximum length of a depot name in characters including '\0' +/** Minimal height for a bridge above any depot tile. */ +static constexpr uint8_t MINIMAL_DEPOT_BRIDGE_HEIGHT = 3; + #endif /* DEPOT_TYPE_H */ diff --git a/src/lang/english.txt b/src/lang/english.txt index 60f76932c6..295bf6d39b 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5361,6 +5361,9 @@ STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :bridge is {HEIG STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :bridge is {HEIGHT} too low for rail waypoint STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :bridge is {HEIGHT} too low for road waypoint STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :bridge is {HEIGHT} too low for lock +STR_ERROR_BRIDGE_TOO_LOW_FOR_TRAIN_DEPOT :bridge is {HEIGHT} too low for train depot +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADVEH_DEPOT :bridge is {HEIGHT} too low for road vehicle depot +STR_ERROR_BRIDGE_TOO_LOW_FOR_SHIP_DEPOT :bridge is {HEIGHT} too low for ship depot # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :Can't build tunnel here... diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 09131d531c..9cbc55922c 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1006,7 +1006,10 @@ CommandCost CmdBuildTrainDepot(DoCommandFlags flags, TileIndex tile, RailType ra cost.AddCost(Command::Do(flags, tile)); if (cost.Failed()) return cost; - if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + if (IsBridgeAbove(tile)) { + int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - GetBridgeHeight(GetSouthernBridgeEnd(tile)); + if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_TRAIN_DEPOT, height_diff * TILE_HEIGHT_STEP); + } if (!Depot::CanAllocateItem()) return CMD_ERROR; } @@ -2582,7 +2585,7 @@ static void DrawTile_Rail(TileInfo *ti) if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti); DrawRailTileSeq(ti, dts, TransparencyOption::Buildings, relocation, 0, pal); - /* Depots can't have bridges above so no blocked pillars. */ + blocked_pillars = BRIDGEPILLARFLAGS_ALL; } DrawBridgeMiddle(ti, blocked_pillars); } @@ -3172,10 +3175,13 @@ static CommandCost TerraformTile_Rail(TileIndex tile, DoCommandFlags flags, int } /** @copydoc CheckBuildAboveProc */ -static CommandCost CheckBuildAbove_Rail(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] Axis axis, [[maybe_unused]] int height) +static CommandCost CheckBuildAbove_Rail(TileIndex tile, [[maybe_unused]] DoCommandFlags flags, [[maybe_unused]] Axis axis, int height) { if (IsPlainRail(tile)) return CommandCost(); - return Command::Do(flags, tile); + + int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - height; + if (height_diff <= 0) return CommandCost(); + return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_TRAIN_DEPOT, height_diff * TILE_HEIGHT_STEP); } /** TileTypeProcs definitions for TileType::Rail tiles. */ diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 5574ef111a..fd6f5dc25c 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -1166,7 +1166,10 @@ CommandCost CmdBuildRoadDepot(DoCommandFlags flags, TileIndex tile, RoadType rt, cost.AddCost(Command::Do(flags, tile)); if (cost.Failed()) return cost; - if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + if (IsBridgeAbove(tile)) { + int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - GetBridgeHeight(GetSouthernBridgeEnd(tile)); + if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADVEH_DEPOT, height_diff * TILE_HEIGHT_STEP); + } if (!Depot::CanAllocateItem()) return CMD_ERROR; } @@ -1884,7 +1887,7 @@ static void DrawTile_Road(TileInfo *ti) } DrawRailTileSeq(ti, dts, TransparencyOption::Buildings, relocation, 0, palette); - /* Depots can't have bridges above so no blocked pillars. */ + blocked_pillars = BRIDGEPILLARFLAGS_ALL; break; } } @@ -2657,10 +2660,13 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ } /** @copydoc CheckBuildAboveProc */ -static CommandCost CheckBuildAbove_Road(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] Axis axis, [[maybe_unused]] int height) +static CommandCost CheckBuildAbove_Road(TileIndex tile, [[maybe_unused]] DoCommandFlags flags, [[maybe_unused]] Axis axis, int height) { if (!IsRoadDepot(tile)) return CommandCost(); - return Command::Do(flags, tile); + + int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - height; + if (height_diff <= 0) return CommandCost(); + return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADVEH_DEPOT, height_diff * TILE_HEIGHT_STEP); } /** TileTypeProcs definitions for TileType::Road tiles. */ diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 0049c418fc..6f60194d53 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -416,6 +416,7 @@ enum class SaveLoadVersion : uint16_t { BuoysAt0_0, ///< Saveload version: 364, GitHub pull request: 14983\n Allow to build buoys at (0x0). DriveBackwards, ///< Saveload version: 365, GitHub pull request: 15379\n Trains can drive backwards. + DepotsUnderBridges, ///< Saveload version: 366, GitHub pull request: 15836\n Allow depots under bridges. MaxVersion, ///< Highest possible saveload version. }; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 1b2dd3d48c..cc5fe21087 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -119,7 +119,12 @@ CommandCost CmdBuildShipDepot(DoCommandFlags flags, TileIndex tile, Axis axis) return CommandCost(STR_ERROR_MUST_BE_BUILT_ON_WATER); } - if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + for (Tile t : {tile, tile2}) { + if (IsBridgeAbove(t)) { + int height_diff = GetTileMaxZ(t) + MINIMAL_DEPOT_BRIDGE_HEIGHT - GetBridgeHeight(GetSouthernBridgeEnd(t)); + if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_SHIP_DEPOT, height_diff * TILE_HEIGHT_STEP); + } + } if (!IsTileFlat(tile) || !IsTileFlat(tile2)) { /* Prevent depots on rapids */ @@ -1000,6 +1005,7 @@ static void DrawTile_Water(TileInfo *ti) case WaterTileType::Depot: DrawWaterDepot(ti); + DrawBridgeMiddle(ti, BRIDGEPILLARFLAGS_ALL); break; } } @@ -1466,15 +1472,27 @@ static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlags flags, [[m } /** @copydoc CheckBuildAboveProc */ -static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] Axis axis, int height) +static CommandCost CheckBuildAbove_Water(TileIndex tile, [[maybe_unused]] DoCommandFlags flags, [[maybe_unused]] Axis axis, int height) { - if (IsWater(tile) || IsCoast(tile)) return CommandCost(); - if (IsLock(tile)) { - int height_diff = GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) - height; - if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff * TILE_HEIGHT_STEP); - return CommandCost{}; + switch (GetWaterTileType(tile)) { + case WaterTileType::Clear: + case WaterTileType::Coast: + break; + + case WaterTileType::Lock: { + int height_diff = GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) - height; + if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff * TILE_HEIGHT_STEP); + break; + } + + case WaterTileType::Depot: { + int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - height; + if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_SHIP_DEPOT, height_diff * TILE_HEIGHT_STEP); + break; + } } - return Command::Do(flags, tile); + + return CommandCost(); } /** TileTypeProcs definitions for TileType::Water tiles. */