diff --git a/docs/newgrf-additions.html b/docs/newgrf-additions.html
index 518e522af5..0bbe06d22f 100644
--- a/docs/newgrf-additions.html
+++ b/docs/newgrf-additions.html
@@ -144,9 +144,35 @@
This is indicated by the feature name: action0_station_prop1B, version 1
+ Disallowed bridge pillars (mappable property: station_disallowed_bridge_pillars)
+ This property describes which bridge pillars are not allowed on the station tile.
+ It consists of 8 pillar flags, for each of the 8 station layouts.
+ Each set of flags is 1 byte, the total property length is 8 bytes.
+ Each set of flags has the format described in the bridge_pillar_flags property section, below.
+
+ This is indicated by the feature name: action0_station_disallowed_bridge_pillars, version 1
Menu icons (14, or mappable property: bridge_menu_icon)
This is indicated by the feature name: action0_bridge_prop14, version 1
+ Bridge pillars (mappable property: bridge_pillar_flags)
+ This property describes the pillars present for each bridge sprite table.
+ It consists of 6 pairs of pillar flags, for bridge sprite tables 0 - 5.
+ Each pair consists of: X direction flags, Y direction flags
+ Each set of flags is 1 byte, the total property length is 12 bytes.
+ Each set of flags has the format:
+
+ Bit | Value | Meaning |
+ 0 | 1 | Pillar is present in west corner |
+ 1 | 2 | Pillar is present in south corner |
+ 2 | 4 | Pillar is present in east corner |
+ 3 | 8 | Pillar is present in north corner |
+ 4 | 10 | Pillar is present along entire north-east edge |
+ 5 | 20 | Pillar is present along entire south-east edge |
+ 6 | 40 | Pillar is present along entire south-west edge |
+ 7 | 80 | Pillar is present along entire north-west edge |
+
+
+ This is indicated by the feature name: action0_bridge_pillar_flags, version 1
More bridges (16 instead of 13)
This is indicated by the feature name: more_bridge_types, version 1
diff --git a/src/bridge.h b/src/bridge.h
index 810744f204..5e4276c677 100644
--- a/src/bridge.h
+++ b/src/bridge.h
@@ -37,6 +37,27 @@ static const uint MAX_BRIDGES = 16; ///< Number of available bridge specs.
typedef uint BridgeType; ///< Bridge spec number.
+/**
+ * Actions that can be performed when the vehicle enters the depot.
+ */
+enum BridgePiecePillarFlags {
+ BPPF_CORNER_W = 1 << 0,
+ BPPF_CORNER_S = 1 << 1,
+ BPPF_CORNER_E = 1 << 2,
+ BPPF_CORNER_N = 1 << 3,
+ BPPF_ALL_CORNERS = 0xF,
+ BPPF_EDGE_NE = 1 << 4,
+ BPPF_EDGE_SE = 1 << 5,
+ BPPF_EDGE_SW = 1 << 6,
+ BPPF_EDGE_NW = 1 << 7,
+};
+DECLARE_ENUM_AS_BIT_SET(BridgePiecePillarFlags)
+
+enum BridgeSpecCtrlFlags {
+ BSCF_CUSTOM_PILLAR_FLAGS,
+ BSCF_INVALID_PILLAR_FLAGS,
+};
+
/**
* Struct containing information about a single bridge type
*/
@@ -52,6 +73,8 @@ struct BridgeSpec {
StringID transport_name[2]; ///< description of the bridge, when built for road or rail
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
byte flags; ///< bit 0 set: disable drawing of far pillars.
+ byte ctrl_flags; ///< control flags
+ byte pillar_flags[12]; ///< bridge pillar flags: 6 x pairs of x and y flags
};
extern BridgeSpec _bridge[MAX_BRIDGES];
@@ -74,6 +97,7 @@ void DrawBridgeMiddle(const TileInfo *ti);
CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags = DC_NONE);
int CalcBridgeLenCostFactor(int x);
+BridgePiecePillarFlags GetBridgeTilePillarFlags(TileIndex tile, TileIndex northern_bridge_end, TileIndex southern_bridge_end, BridgeType bridge_type, TransportType bridge_transport_type);
void ResetBridges();
diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp
index 6dea429dda..2459c88276 100644
--- a/src/bridge_gui.cpp
+++ b/src/bridge_gui.cpp
@@ -390,15 +390,19 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
return;
}
- /* only query bridge building possibility once, result is the same for all bridges!
+ /* only query bridge building possibility once, result is the same for all bridges,
+ * unless the result is bridge too low for station or pillars obstruct station, in which case it is bridge-type dependent.
* returns CMD_ERROR on failure, and price on success */
StringID errmsg = INVALID_STRING_ID;
CommandCost ret = DoCommand(end, start, type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE);
+ const bool query_per_bridge_type = ret.Failed() && (ret.GetErrorMessage() == STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION || ret.GetErrorMessage() == STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION);
+
GUIBridgeList *bl = NULL;
if (ret.Failed()) {
errmsg = ret.GetErrorMessage();
- } else {
+ }
+ if (ret.Succeeded() || query_per_bridge_type) {
/* check which bridges can be built */
const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2);
@@ -418,6 +422,8 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
/* loop for all bridgetypes */
for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
if (CheckBridgeAvailability(brd_type, bridge_len).Succeeded()) {
+ /* Re-check bridge building possibility is initial bridge builindg query indicated a bridge type dependent failure */
+ if (query_per_bridge_type && DoCommand(end, start, type | brd_type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE).Failed()) continue;
/* bridge is accepted, add to list */
BuildBridgeData *item = bl->Append();
item->index = brd_type;
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 0248a52797..5557e34d53 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -5259,6 +5259,8 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start an
STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ends of bridge must both be on land
STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... bridge too long
STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map
+STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is too low for station
+STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION :{WHITE}Bridge pillars obstruct station
# Tunnel related errors
STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here...
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 18100bd992..00104520a0 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2126,6 +2126,14 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons
}
break;
+ case A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS:
+ if (MappedPropertyLengthMismatch(buf, 8, mapping_entry)) break;
+ SetBit(statspec->internal_flags, SSIF_BRIDGE_DISALLOWED_PILLARS_SET);
+ for (uint i = 0; i < 8; i++) {
+ statspec->bridge_disallowed_pillars[i] = buf->ReadByte();
+ }
+ break;
+
default:
ret = HandleAction0PropertyDefault(buf, prop);
break;
@@ -2248,6 +2256,7 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
MapSpriteMappingRecolour(&bridge->sprite_table[tableid][sprite]);
}
}
+ if (!HasBit(bridge->ctrl_flags, BSCF_CUSTOM_PILLAR_FLAGS)) SetBit(bridge->ctrl_flags, BSCF_INVALID_PILLAR_FLAGS);
break;
}
@@ -2284,6 +2293,15 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
bridge->pal = buf->ReadWord();
break;
+ case A0RPI_BRIDGE_PILLAR_FLAGS:
+ if (MappedPropertyLengthMismatch(buf, 12, mapping_entry)) break;
+ for (uint i = 0; i < 12; i++) {
+ bridge->pillar_flags[i] = buf->ReadByte();
+ }
+ ClrBit(bridge->ctrl_flags, BSCF_INVALID_PILLAR_FLAGS);
+ SetBit(bridge->ctrl_flags, BSCF_CUSTOM_PILLAR_FLAGS);
+ break;
+
default:
ret = HandleAction0PropertyDefault(buf, prop);
break;
@@ -7962,9 +7980,11 @@ static const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("feature_test", 1),
GRFFeatureInfo("property_mapping", 1),
GRFFeatureInfo("action0_station_prop1B", 1),
+ GRFFeatureInfo("action0_station_disallowed_bridge_pillars", 1),
GRFFeatureInfo("varaction2_station_var42", 1),
GRFFeatureInfo("more_bridge_types", 1),
GRFFeatureInfo("action0_bridge_prop14", 1),
+ GRFFeatureInfo("action0_bridge_pillar_flags", 1),
GRFFeatureInfo(),
};
@@ -8077,7 +8097,9 @@ static bool HandleFeatureTestInfo(ByteReader *buf)
/** Action14 Action0 remappable property list */
static const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
GRFPropertyMapDefinition(GSF_STATIONS, A0RPI_STATION_MIN_BRIDGE_HEIGHT, "station_min_bridge_height"),
+ GRFPropertyMapDefinition(GSF_STATIONS, A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS, "station_disallowed_bridge_pillars"),
GRFPropertyMapDefinition(GSF_BRIDGES, A0RPI_BRIDGE_MENU_ICON, "bridge_menu_icon"),
+ GRFPropertyMapDefinition(GSF_BRIDGES, A0RPI_BRIDGE_PILLAR_FLAGS, "bridge_pillar_flags"),
GRFPropertyMapDefinition(),
};
diff --git a/src/newgrf.h b/src/newgrf.h
index cf11198a8f..9cb54d1fc3 100644
--- a/src/newgrf.h
+++ b/src/newgrf.h
@@ -109,7 +109,9 @@ enum Action0RemapPropertyIds {
A0RPI_UNKNOWN_ERROR,
A0RPI_STATION_MIN_BRIDGE_HEIGHT,
+ A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS,
A0RPI_BRIDGE_MENU_ICON,
+ A0RPI_BRIDGE_PILLAR_FLAGS,
};
enum Action0RemapFallbackMode {
diff --git a/src/newgrf_station.h b/src/newgrf_station.h
index fe5f4a5c2c..caeafb994e 100644
--- a/src/newgrf_station.h
+++ b/src/newgrf_station.h
@@ -114,6 +114,7 @@ enum StationRandomTrigger {
enum StationSpecIntlFlags {
SSIF_COPIED_LAYOUTS, ///< Copied StationLayout **layouts.
SSIF_BRIDGE_HEIGHTS_SET, ///< byte bridge_height[8] is set.
+ SSIF_BRIDGE_DISALLOWED_PILLARS_SET, ///< byte bridge_disallowed_pillars[8] is set.
};
/* Station layout for given dimensions - it is a two-dimensional array
@@ -170,6 +171,7 @@ struct StationSpec {
byte wires; ///< Bitmask of base tiles (0 - 7) which should contain elrail wires
byte blocked; ///< Bitmask of base tiles (0 - 7) which are blocked to trains
byte bridge_height[8]; ///< Minimum height for a bridge above, 0 for none
+ byte bridge_disallowed_pillars[8]; ///< Disallowed pillar flags for a bridge above
AnimationInfo animation;
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 7869c82f0e..8a277a3626 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -775,28 +775,56 @@ CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z
return cost;
}
-bool IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height)
+CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
+ BridgeType bridge_type, TransportType bridge_transport_type)
{
assert(layout < 8);
if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) {
- return (GetTileMaxZ(tile) + statspec->bridge_height[layout] <= bridge_height);
+ if (statspec->bridge_height[layout] == 0) return CommandCost(INVALID_STRING_ID);
+ if (GetTileMaxZ(tile) + statspec->bridge_height[layout] > bridge_height) {
+ return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
+ }
} else if (!statspec) {
// default stations/waypoints
const int height = layout < 4 ? 2 : 5;
- return (GetTileMaxZ(tile) + height <= bridge_height);
+ if (GetTileMaxZ(tile) + height > bridge_height) return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
+ } else {
+ if (!_settings_game.construction.allow_stations_under_bridges) return CommandCost(INVALID_STRING_ID);
+ }
+
+ BridgePiecePillarFlags disallowed_pillar_flags;
+ if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_DISALLOWED_PILLARS_SET)) {
+ // pillar flags set by NewGRF
+ disallowed_pillar_flags = (BridgePiecePillarFlags) statspec->bridge_height[layout];
+ } else if (!statspec) {
+ // default stations/waypoints
+ static const uint8 st_flags[8] = { 0x50, 0xA0, 0x50, 0xA0, 0x50 | 0x26, 0xA0 | 0x1C, 0x50 | 0x89, 0xA0 | 0x43 };
+ disallowed_pillar_flags = (BridgePiecePillarFlags) st_flags[layout];
+ } else if (HasBit(statspec->blocked, layout)) {
+ // non-track station tiles
+ disallowed_pillar_flags = (BridgePiecePillarFlags) 0;
} else {
- return _settings_game.construction.allow_stations_under_bridges;
+ // tracked station tiles
+ const Axis axis = HasBit(layout, 0) ? AXIS_Y : AXIS_X;
+ disallowed_pillar_flags = (BridgePiecePillarFlags) (axis == AXIS_X ? 0x50 : 0xA0);
+ }
+
+ if ((GetBridgeTilePillarFlags(tile, northern_bridge_end, southern_bridge_end, bridge_type, bridge_transport_type) & disallowed_pillar_flags) == 0) {
+ return CommandCost();
+ } else {
+ return CommandCost(STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION);
}
}
-bool IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout)
+CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout)
{
- if (!IsBridgeAbove(tile)) return true;
+ if (!IsBridgeAbove(tile)) return CommandCost();
TileIndex southern_bridge_end = GetSouthernBridgeEnd(tile);
TileIndex northern_bridge_end = GetNorthernBridgeEnd(tile);
- return IsRailStationBridgeAboveOk(tile, statspec, layout, northern_bridge_end, southern_bridge_end, GetBridgeHeight(southern_bridge_end));
+ return IsRailStationBridgeAboveOk(tile, statspec, layout, northern_bridge_end, southern_bridge_end, GetBridgeHeight(southern_bridge_end),
+ GetBridgeType(southern_bridge_end), GetTunnelBridgeTransportType(southern_bridge_end));
}
/**
@@ -1292,7 +1320,10 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
for (uint i = 0; i < numtracks; i++) {
TileIndex tile = tile_track;
for (uint j = 0; j < plat_len; j++) {
- if (!IsRailStationBridgeAboveOk(tile, statspec, *check_layout_ptr++)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
+ CommandCost ret = IsRailStationBridgeAboveOk(tile, statspec, *check_layout_ptr++);
+ if (ret.Failed()) {
+ return CommandCost::DualErrorMessage(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST, ret.GetErrorMessage());
+ }
tile += tile_delta;
}
tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
diff --git a/src/table/bridge_land.h b/src/table/bridge_land.h
index 44762e1b25..c4f0a8d2da 100644
--- a/src/table/bridge_land.h
+++ b/src/table/bridge_land.h
@@ -743,8 +743,12 @@ static const PalSpriteID * const * const _bridge_sprite_table[MAX_BRIDGES] = {
* @param nrl description of the rail bridge in query tool
* @param nrd description of the road bridge in query tool
*/
-#define MBR(y, mnl, mxl, p, mxs, spr, plt, dsc, nrl, nrd) \
- {y, mnl, mxl, p, mxs, spr, plt, dsc, { nrl, nrd }, NULL, 0}
+#define MBR(y, mnl, mxl, p, mxs, spr, plt, dsc, nrl, nrd, pillars) \
+ {y, mnl, mxl, p, mxs, spr, plt, dsc, { nrl, nrd }, NULL, 0, 0, pillars}
+
+#define ALL_PILLARS { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }
+#define SUSP_PILLARS { 0x03, 0x06, 0x0C, 0x09, 0x0C, 0x09, 0x03, 0x06, 0x0F, 0x0F, 0x00, 0x00 }
+#define CANT_PILLARS { 0x00, 0x00, 0x0C, 0x09, 0x0C, 0x09, 0x0C, 0x09, 0x0C, 0x09, 0x0C, 0x09 }
const BridgeSpec _orig_bridge[] = {
/*
@@ -758,49 +762,52 @@ const BridgeSpec _orig_bridge[] = {
string with description name on rail name on road
| | | | */
MBR( 0, 0, 0xFFFF, 80, 32, 0xA24, PAL_NONE,
- STR_BRIDGE_NAME_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_RAIL_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_ROAD_WOODEN),
+ STR_BRIDGE_NAME_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_RAIL_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_ROAD_WOODEN, ALL_PILLARS),
MBR( 0, 0, 2, 112, 48, 0xA26, PALETTE_TO_STRUCT_RED,
- STR_BRIDGE_NAME_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CONCRETE),
+ STR_BRIDGE_NAME_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CONCRETE, ALL_PILLARS),
MBR(1930, 0, 5, 144, 64, 0xA25, PAL_NONE,
- STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL),
+ STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL, ALL_PILLARS),
MBR( 0, 2, 10, 168, 80, 0xA22, PALETTE_TO_STRUCT_CONCRETE,
- STR_BRIDGE_NAME_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_CONCRETE),
+ STR_BRIDGE_NAME_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_CONCRETE, SUSP_PILLARS),
MBR(1930, 3, 0xFFFF, 185, 96, 0xA22, PAL_NONE,
- STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL),
+ STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL, SUSP_PILLARS),
MBR(1930, 3, 0xFFFF, 192, 112, 0xA22, PALETTE_TO_STRUCT_YELLOW,
- STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL),
+ STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL, SUSP_PILLARS),
MBR(1930, 3, 7, 224, 160, 0xA23, PAL_NONE,
- STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL),
+ STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL, CANT_PILLARS),
MBR(1930, 3, 8, 232, 208, 0xA23, PALETTE_TO_STRUCT_BROWN,
- STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL),
+ STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL, CANT_PILLARS),
MBR(1930, 3, 9, 248, 240, 0xA23, PALETTE_TO_STRUCT_RED,
- STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL),
+ STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL, CANT_PILLARS),
MBR(1930, 0, 2, 240, 256, 0xA27, PAL_NONE,
- STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL),
+ STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL, ALL_PILLARS),
MBR(1995, 2, 0xFFFF, 255, 320, 0xA28, PAL_NONE,
- STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL),
+ STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL, CANT_PILLARS),
MBR(2005, 2, 0xFFFF, 380, 512, 0xA28, PALETTE_TO_STRUCT_YELLOW,
- STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL),
+ STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL, CANT_PILLARS),
MBR(2010, 2, 0xFFFF, 510, 608, 0xA28, PALETTE_TO_STRUCT_CONCRETE,
- STR_BRIDGE_TUBULAR_SILICON, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL),
+ STR_BRIDGE_TUBULAR_SILICON, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL, CANT_PILLARS),
- MBR(MAX_YEAR + 1, 1, 0, 1, 0xFFFF, 0xA28, PALETTE_TO_STRUCT_CONCRETE, STR_EMPTY, STR_EMPTY, STR_EMPTY),
- MBR(MAX_YEAR + 1, 1, 0, 1, 0xFFFF, 0xA28, PALETTE_TO_STRUCT_CONCRETE, STR_EMPTY, STR_EMPTY, STR_EMPTY),
- MBR(MAX_YEAR + 1, 1, 0, 1, 0xFFFF, 0xA28, PALETTE_TO_STRUCT_CONCRETE, STR_EMPTY, STR_EMPTY, STR_EMPTY),
+ MBR(MAX_YEAR + 1, 1, 0, 1, 0xFFFF, 0xA28, PALETTE_TO_STRUCT_CONCRETE, STR_EMPTY, STR_EMPTY, STR_EMPTY, ALL_PILLARS),
+ MBR(MAX_YEAR + 1, 1, 0, 1, 0xFFFF, 0xA28, PALETTE_TO_STRUCT_CONCRETE, STR_EMPTY, STR_EMPTY, STR_EMPTY, ALL_PILLARS),
+ MBR(MAX_YEAR + 1, 1, 0, 1, 0xFFFF, 0xA28, PALETTE_TO_STRUCT_CONCRETE, STR_EMPTY, STR_EMPTY, STR_EMPTY, ALL_PILLARS),
};
+#undef CANT_PILLARS
+#undef SUSP_PILLARS
+#undef ALL_PILLARS
#undef MBR
#undef MN
#undef MR
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
index 395ad06d98..ee7d42093a 100644
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -65,7 +65,8 @@ extern void DrawTrackBits(TileInfo *ti, TrackBits track);
extern void DrawRoadBits(TileInfo *ti);
extern const RoadBits _invalid_tileh_slopes_road[2][15];
-extern bool IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height);
+extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
+ BridgeType bridge_type, TransportType bridge_transport_type);
/**
* Mark bridge tiles dirty.
@@ -499,7 +500,9 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
case STATION_RAIL:
case STATION_WAYPOINT: {
- if (!IsRailStationBridgeAboveOk(tile, GetStationSpec(tile), GetStationGfx(tile), tile_start, tile_end, z_start + 1)) {
+ CommandCost ret = IsRailStationBridgeAboveOk(tile, GetStationSpec(tile), GetStationGfx(tile), tile_start, tile_end, z_start + 1, bridge_type, transport_type);
+ if (ret.Failed()) {
+ if (ret.GetErrorMessage() != INVALID_STRING_ID) return ret;
goto not_valid_below;
}
break;
@@ -1801,6 +1804,34 @@ static BridgePieces CalcBridgePiece(uint north, uint south)
}
}
+BridgePiecePillarFlags GetBridgeTilePillarFlags(TileIndex tile, TileIndex northern_bridge_end, TileIndex southern_bridge_end, BridgeType bridge_type, TransportType bridge_transport_type)
+{
+ if (bridge_transport_type == TRANSPORT_WATER) return BPPF_ALL_CORNERS;
+
+ BridgePieces piece = CalcBridgePiece(
+ GetTunnelBridgeLength(tile, northern_bridge_end) + 1,
+ GetTunnelBridgeLength(tile, southern_bridge_end) + 1
+ );
+ assert(piece < BRIDGE_PIECE_HEAD);
+
+ const BridgeSpec *spec = GetBridgeSpec(bridge_type);
+ const Axis axis = TileX(northern_bridge_end) == TileX(southern_bridge_end) ? AXIS_Y : AXIS_X;
+ if (!HasBit(spec->ctrl_flags, BSCF_INVALID_PILLAR_FLAGS)) {
+ return (BridgePiecePillarFlags) spec->pillar_flags[piece * 2 + (axis == AXIS_Y ? 1 : 0)];
+ } else {
+ uint base_offset;
+ if (bridge_transport_type == TRANSPORT_RAIL) {
+ base_offset = GetRailTypeInfo(GetRailType(southern_bridge_end))->bridge_offset;
+ } else {
+ base_offset = 8;
+ }
+
+ const PalSpriteID *psid = base_offset + GetBridgeSpriteTable(bridge_type, piece);
+ if (axis == AXIS_Y) psid += 4;
+ return (BridgePiecePillarFlags) (psid[2].sprite != 0 ? BPPF_ALL_CORNERS : 0);
+ }
+}
+
/**
* Draw the middle bits of a bridge.
* @param ti Tile information of the tile to draw it on.
diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp
index 7c03e433bf..a170dc420a 100644
--- a/src/waypoint_cmd.cpp
+++ b/src/waypoint_cmd.cpp
@@ -139,7 +139,7 @@ static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *
extern void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec);
extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp);
extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis axis);
-extern bool IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout);
+extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout);
/**
* Convert existing rail to waypoint. Eg build a waypoint station over
@@ -205,7 +205,10 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
TileIndex tile = start_tile + i * offset;
CommandCost ret = IsValidTileForWaypoint(tile, axis, &est);
if (ret.Failed()) return ret;
- if (!IsRailStationBridgeAboveOk(tile, spec, layout_ptr[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
+ ret = IsRailStationBridgeAboveOk(tile, spec, layout_ptr[i]);
+ if (ret.Failed()) {
+ return CommandCost::DualErrorMessage(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST, ret.GetErrorMessage());
+ }
}
Waypoint *wp = NULL;