Feature: Allow bridges over depots (#15836)

Depots are somewhat tall, so bridges must be at least 3 height levels above them.
This commit is contained in:
Peter Nelson
2026-07-09 18:26:13 +01:00
committed by GitHub
parent 44b51a94c5
commit 83ce49f6cb
6 changed files with 53 additions and 16 deletions
+3
View File
@@ -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 */
+3
View File
@@ -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...
+10 -4
View File
@@ -1006,7 +1006,10 @@ CommandCost CmdBuildTrainDepot(DoCommandFlags flags, TileIndex tile, RailType ra
cost.AddCost(Command<Commands::LandscapeClear>::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<Commands::LandscapeClear>::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. */
+10 -4
View File
@@ -1166,7 +1166,10 @@ CommandCost CmdBuildRoadDepot(DoCommandFlags flags, TileIndex tile, RoadType rt,
cost.AddCost(Command<Commands::LandscapeClear>::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<Commands::LandscapeClear>::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. */
+1
View File
@@ -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.
};
+26 -8
View File
@@ -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<Commands::LandscapeClear>::Do(flags, tile);
return CommandCost();
}
/** TileTypeProcs definitions for TileType::Water tiles. */