Implement custom bridge pillar flag support

Add bridge NewGRF property to set bridge pillars
Add station NewGRF property to disallow bridge pillars

Set values for default bridges and stations
pull/73/head
Jonathan G Rennison 6 years ago
parent d264d71d04
commit 8b37e5aac2

@ -144,9 +144,35 @@
<h3><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations">Action 0 - Stations</a></h3>
<h4><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations#Minimum_bridge_height_.281B.29">Minimum bridge height (1B, or mappable property: station_min_bridge_height)</a></h4>
<p>This is indicated by the feature name: <font face="monospace">action0_station_prop1B</font>, version 1</p>
<h4>Disallowed bridge pillars (mappable property: station_disallowed_bridge_pillars)</h4>
<p>This property describes which bridge pillars are not allowed on the station tile.<br />
It consists of 8 pillar flags, for each of the 8 station layouts.<br />
Each set of flags is 1 byte, the total property length is 8 bytes.<br />
Each set of flags has the format described in the bridge_pillar_flags property section, below.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_station_disallowed_bridge_pillars</font>, version 1</p>
<h3><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Bridges">Action 0 - Bridges</a></h3>
<h4>Menu icons (14, or mappable property: bridge_menu_icon)</h4>
<p>This is indicated by the feature name: <font face="monospace">action0_bridge_prop14</font>, version 1</p>
<h4>Bridge pillars (mappable property: bridge_pillar_flags)</h4>
<p>This property describes the pillars present for each bridge sprite table.<br />
It consists of 6 pairs of pillar flags, for bridge sprite tables 0 - 5.<br />
Each pair consists of: X direction flags, Y direction flags<br />
Each set of flags is 1 byte, the total property length is 12 bytes.<br />
Each set of flags has the format:
<table>
<tr><th>Bit</th><th>Value</th><th>Meaning</th></tr>
<tr><td>0</td><td>1</td><td>Pillar is present in west corner</td></tr>
<tr><td>1</td><td>2</td><td>Pillar is present in south corner</td></tr>
<tr><td>2</td><td>4</td><td>Pillar is present in east corner</td></tr>
<tr><td>3</td><td>8</td><td>Pillar is present in north corner</td></tr>
<tr><td>4</td><td>10</td><td>Pillar is present along entire north-east edge</td></tr>
<tr><td>5</td><td>20</td><td>Pillar is present along entire south-east edge</td></tr>
<tr><td>6</td><td>40</td><td>Pillar is present along entire south-west edge</td></tr>
<tr><td>7</td><td>80</td><td>Pillar is present along entire north-west edge</td></tr>
</table>
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_bridge_pillar_flags</font>, version 1</p>
<h4>More bridges (16 instead of 13)</h4>
<p>This is indicated by the feature name: <font face="monospace">more_bridge_types</font>, version 1</p>
<h3><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations">Variational Action 2 - Stations</a></h3>

@ -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();

@ -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;

@ -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...

@ -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(),
};

@ -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 {

@ -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;

@ -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

@ -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

@ -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.

@ -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;

Loading…
Cancel
Save