mirror of
https://github.com/OpenTTD/OpenTTD
synced 2026-01-23 04:04:09 +01:00
Change: Allow bridges over locks. (#14595)
The bridge must be at least 2 levels higher than the lock.
This commit is contained in:
@@ -5268,6 +5268,7 @@ STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge i
|
||||
STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is too low for buoy
|
||||
STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is too low for rail waypoint
|
||||
STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is too low for road waypoint
|
||||
STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is too low for lock
|
||||
|
||||
# Tunnel related errors
|
||||
STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here...
|
||||
|
||||
@@ -410,6 +410,7 @@ enum SaveLoadVersion : uint16_t {
|
||||
SLV_STATIONS_UNDER_BRIDGES, ///< 359 PR#14477 Allow stations under bridges.
|
||||
|
||||
SLV_DOCKS_UNDER_BRIDGES, ///< 360 PR#14594 Allow docks under bridges.
|
||||
SLV_LOCKS_UNDER_BRIDGES, ///< 361 PR#14595 Allow locks under bridges.
|
||||
|
||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||
};
|
||||
|
||||
@@ -55,64 +55,71 @@ static const DrawTileSpriteSpan _shipdepot_display_data[][DEPOT_PART_END] = {
|
||||
},
|
||||
};
|
||||
|
||||
static constexpr uint8_t LOCK_HEIGHT_LOWER_REAR = 6; ///< Sub-tile height of rear wall of lower part.
|
||||
static constexpr uint8_t LOCK_HEIGHT_LOWER_FRONT = 10; ///< Sub-tile height of front wall of lower part.
|
||||
static constexpr uint8_t LOCK_HEIGHT_MIDDLE_REAR = 6; ///< Sub-tile height of rear wall of middle part.
|
||||
static constexpr uint8_t LOCK_HEIGHT_MIDDLE_FRONT = 10; ///< Sub-tile height of front wall of middle part.
|
||||
static constexpr uint8_t LOCK_HEIGHT_UPPER_REAR = 6; ///< Sub-tile height of rear wall of upper part.
|
||||
static constexpr uint8_t LOCK_HEIGHT_UPPER_FRONT = 6; ///< Sub-tile height of front wall of upper part.
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_middle_ne_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x10, 1, 0x14, 0 + 1)
|
||||
TILE_SEQ_LINE( 0, 0xF, 0, 0x10, 1, 0x14, 4 + 1)
|
||||
TILE_SEQ_LINE(0, 0, 0, TILE_SIZE, 1, LOCK_HEIGHT_MIDDLE_REAR, 0 + 1)
|
||||
TILE_SEQ_LINE(0, 15, 0, TILE_SIZE, 1, LOCK_HEIGHT_MIDDLE_FRONT, 4 + 1)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_middle_se_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, 0x10, 0x14, 0)
|
||||
TILE_SEQ_LINE( 0xF, 0, 0, 1, 0x10, 0x14, 4)
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_MIDDLE_REAR, 0)
|
||||
TILE_SEQ_LINE(15, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_MIDDLE_FRONT, 4)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_middle_sw_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x10, 1, 0x14, 0 + 2)
|
||||
TILE_SEQ_LINE( 0, 0xF, 0, 0x10, 1, 0x14, 4 + 2)
|
||||
TILE_SEQ_LINE(0, 0, 0, TILE_SIZE, 1, LOCK_HEIGHT_MIDDLE_REAR, 0 + 2)
|
||||
TILE_SEQ_LINE(0, 15, 0, TILE_SIZE, 1, LOCK_HEIGHT_MIDDLE_FRONT, 4 + 2)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_middle_nw_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, 0x10, 0x14, 0 + 3)
|
||||
TILE_SEQ_LINE( 0xF, 0, 0, 1, 0x10, 0x14, 4 + 3)
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_MIDDLE_REAR, 0 + 3)
|
||||
TILE_SEQ_LINE(15, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_MIDDLE_FRONT, 4 + 3)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_lower_ne_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x10, 1, 0x14, 8 + 1)
|
||||
TILE_SEQ_LINE( 0, 0xF, 0, 0x10, 1, 0x14, 12 + 1)
|
||||
TILE_SEQ_LINE(0, 0, 0, TILE_SIZE, 1, LOCK_HEIGHT_LOWER_REAR, 8 + 1)
|
||||
TILE_SEQ_LINE(0, 15, 0, TILE_SIZE, 1, LOCK_HEIGHT_LOWER_FRONT, 12 + 1)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_lower_se_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x1, 0x10, 0x14, 8)
|
||||
TILE_SEQ_LINE( 0xF, 0, 0, 0x1, 0x10, 0x14, 12)
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_LOWER_REAR, 8)
|
||||
TILE_SEQ_LINE(15, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_LOWER_FRONT, 12)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_lower_sw_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x10, 1, 0x14, 8 + 2)
|
||||
TILE_SEQ_LINE( 0, 0xF, 0, 0x10, 1, 0x14, 12 + 2)
|
||||
TILE_SEQ_LINE(0, 0, 0, TILE_SIZE, 1, LOCK_HEIGHT_LOWER_REAR, 8 + 2)
|
||||
TILE_SEQ_LINE(0, 15, 0, TILE_SIZE, 1, LOCK_HEIGHT_LOWER_FRONT, 12 + 2)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_lower_nw_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, 0x10, 0x14, 8 + 3)
|
||||
TILE_SEQ_LINE( 0xF, 0, 0, 1, 0x10, 0x14, 12 + 3)
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_LOWER_REAR, 8 + 3)
|
||||
TILE_SEQ_LINE(15, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_LOWER_FRONT, 12 + 3)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_upper_ne_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x10, 1, 0x14, 16 + 1)
|
||||
TILE_SEQ_LINE( 0, 0xF, 0, 0x10, 1, 0x14, 20 + 1)
|
||||
TILE_SEQ_LINE(0, 0, 0, TILE_SIZE, 1, LOCK_HEIGHT_UPPER_REAR, 16 + 1)
|
||||
TILE_SEQ_LINE(0, 15, 0, TILE_SIZE, 1, LOCK_HEIGHT_UPPER_FRONT, 20 + 1)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_upper_se_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x1, 0x10, 0x14, 16)
|
||||
TILE_SEQ_LINE( 0xF, 0, 0, 0x1, 0x10, 0x14, 20)
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_UPPER_REAR, 16)
|
||||
TILE_SEQ_LINE(15, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_UPPER_FRONT, 20)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_upper_sw_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 0x10, 1, 0x14, 16 + 2)
|
||||
TILE_SEQ_LINE( 0, 0xF, 0, 0x10, 1, 0x14, 20 + 2)
|
||||
TILE_SEQ_LINE(0, 0, 0, TILE_SIZE, 1, LOCK_HEIGHT_UPPER_REAR, 16 + 2)
|
||||
TILE_SEQ_LINE(0, 15, 0, TILE_SIZE, 1, LOCK_HEIGHT_UPPER_FRONT, 20 + 2)
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _lock_display_upper_nw_seq[] = {
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, 0x10, 0x14, 16 + 3)
|
||||
TILE_SEQ_LINE( 0xF, 0, 0, 1, 0x10, 0x14, 20 + 3)
|
||||
TILE_SEQ_LINE( 0, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_UPPER_REAR, 16 + 3)
|
||||
TILE_SEQ_LINE(15, 0, 0, 1, TILE_SIZE, LOCK_HEIGHT_UPPER_FRONT, 20 + 3)
|
||||
};
|
||||
|
||||
static const DrawTileSpriteSpan _lock_display_data[][DIAGDIR_END] = {
|
||||
|
||||
@@ -301,6 +301,21 @@ static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlags flags)
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_SHIP]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimal height required for a bridge above a lock part.
|
||||
* @param lock_part the lock part.
|
||||
* @return the minimal bridge height.
|
||||
*/
|
||||
static uint8_t GetLockPartMinimalBridgeHeight(LockPart lock_part)
|
||||
{
|
||||
static constexpr uint8_t MINIMAL_BRIDGE_HEIGHT[LOCK_PART_END] = {
|
||||
2, // LOCK_PART_MIDDLE
|
||||
3, // LOCK_PART_LOWER
|
||||
2, // LOCK_PART_UPPER
|
||||
};
|
||||
return MINIMAL_BRIDGE_HEIGHT[to_underlying(lock_part)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a lock.
|
||||
* @param tile Central tile of the lock.
|
||||
@@ -348,8 +363,11 @@ static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlags
|
||||
}
|
||||
WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
|
||||
|
||||
if (IsBridgeAbove(tile) || IsBridgeAbove(tile - delta) || IsBridgeAbove(tile + delta)) {
|
||||
return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||
for (LockPart lock_part = LOCK_PART_MIDDLE; TileIndex t : {tile, tile - delta, tile + delta}) {
|
||||
if (IsBridgeAbove(t) && GetBridgeHeight(GetSouthernBridgeEnd(t)) < GetTileMaxZ(t) + GetLockPartMinimalBridgeHeight(lock_part)) {
|
||||
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK);
|
||||
}
|
||||
++lock_part;
|
||||
}
|
||||
|
||||
if (flags.Test(DoCommandFlag::Execute)) {
|
||||
@@ -939,6 +957,9 @@ static void DrawTile_Water(TileInfo *ti)
|
||||
|
||||
case WATER_TILE_LOCK:
|
||||
DrawWaterLock(ti);
|
||||
DrawBridgeMiddle(ti, DiagDirToAxis(GetLockDirection(ti->tile)) == AXIS_X
|
||||
? BridgePillarFlags{BridgePillarFlag::EdgeNE, BridgePillarFlag::EdgeSW}
|
||||
: BridgePillarFlags{BridgePillarFlag::EdgeNW, BridgePillarFlag::EdgeSE});
|
||||
break;
|
||||
|
||||
case WATER_TILE_DEPOT:
|
||||
@@ -1412,9 +1433,13 @@ static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlags flags, int
|
||||
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
|
||||
}
|
||||
|
||||
static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, Axis, int)
|
||||
static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, Axis, int height)
|
||||
{
|
||||
if (IsWater(tile) || IsCoast(tile)) return CommandCost();
|
||||
if (IsLock(tile)) {
|
||||
if (GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) <= height) return CommandCost();
|
||||
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK);
|
||||
}
|
||||
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,9 @@ enum LockPart : uint8_t {
|
||||
LOCK_PART_MIDDLE = 0, ///< Middle part of a lock.
|
||||
LOCK_PART_LOWER = 1, ///< Lower part of a lock.
|
||||
LOCK_PART_UPPER = 2, ///< Upper part of a lock.
|
||||
LOCK_PART_END,
|
||||
};
|
||||
DECLARE_INCREMENT_DECREMENT_OPERATORS(LockPart);
|
||||
|
||||
bool IsPossibleDockingTile(Tile t);
|
||||
|
||||
@@ -323,10 +325,10 @@ inline DiagDirection GetLockDirection(Tile t)
|
||||
* @return The part.
|
||||
* @pre IsTileType(t, MP_WATER) && IsLock(t)
|
||||
*/
|
||||
inline uint8_t GetLockPart(Tile t)
|
||||
inline LockPart GetLockPart(Tile t)
|
||||
{
|
||||
assert(IsLock(t));
|
||||
return GB(t.m5(), WBL_LOCK_PART_BEGIN, WBL_LOCK_PART_COUNT);
|
||||
return static_cast<LockPart>(GB(t.m5(), WBL_LOCK_PART_BEGIN, WBL_LOCK_PART_COUNT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user