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
This commit is contained in:
Jonathan G Rennison
2018-11-17 19:49:05 +00:00
parent d264d71d04
commit 8b37e5aac2
11 changed files with 188 additions and 32 deletions

View File

@@ -144,9 +144,35 @@
<h3><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations">Action 0 - Stations</a></h3> <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> <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> <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> <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> <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> <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> <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> <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> <h3><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations">Variational Action 2 - Stations</a></h3>

View File

@@ -37,6 +37,27 @@ static const uint MAX_BRIDGES = 16; ///< Number of available bridge specs.
typedef uint BridgeType; ///< Bridge spec number. 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 * 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 StringID transport_name[2]; ///< description of the bridge, when built for road or rail
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
byte flags; ///< bit 0 set: disable drawing of far pillars. 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]; 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); CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags = DC_NONE);
int CalcBridgeLenCostFactor(int x); 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(); void ResetBridges();

View File

@@ -390,15 +390,19 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
return; 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 */ * returns CMD_ERROR on failure, and price on success */
StringID errmsg = INVALID_STRING_ID; StringID errmsg = INVALID_STRING_ID;
CommandCost ret = DoCommand(end, start, type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE); 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; GUIBridgeList *bl = NULL;
if (ret.Failed()) { if (ret.Failed()) {
errmsg = ret.GetErrorMessage(); errmsg = ret.GetErrorMessage();
} else { }
if (ret.Succeeded() || query_per_bridge_type) {
/* check which bridges can be built */ /* check which bridges can be built */
const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2); 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 */ /* loop for all bridgetypes */
for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) { for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
if (CheckBridgeAvailability(brd_type, bridge_len).Succeeded()) { 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 */ /* bridge is accepted, add to list */
BuildBridgeData *item = bl->Append(); BuildBridgeData *item = bl->Append();
item->index = brd_type; item->index = brd_type;

View File

@@ -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_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_TOO_LONG :{WHITE}... bridge too long
STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map 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 # Tunnel related errors
STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here...

View File

@@ -2126,6 +2126,14 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons
} }
break; 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: default:
ret = HandleAction0PropertyDefault(buf, prop); ret = HandleAction0PropertyDefault(buf, prop);
break; break;
@@ -2248,6 +2256,7 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
MapSpriteMappingRecolour(&bridge->sprite_table[tableid][sprite]); MapSpriteMappingRecolour(&bridge->sprite_table[tableid][sprite]);
} }
} }
if (!HasBit(bridge->ctrl_flags, BSCF_CUSTOM_PILLAR_FLAGS)) SetBit(bridge->ctrl_flags, BSCF_INVALID_PILLAR_FLAGS);
break; break;
} }
@@ -2284,6 +2293,15 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
bridge->pal = buf->ReadWord(); bridge->pal = buf->ReadWord();
break; 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: default:
ret = HandleAction0PropertyDefault(buf, prop); ret = HandleAction0PropertyDefault(buf, prop);
break; break;
@@ -7962,9 +7980,11 @@ static const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("feature_test", 1), GRFFeatureInfo("feature_test", 1),
GRFFeatureInfo("property_mapping", 1), GRFFeatureInfo("property_mapping", 1),
GRFFeatureInfo("action0_station_prop1B", 1), GRFFeatureInfo("action0_station_prop1B", 1),
GRFFeatureInfo("action0_station_disallowed_bridge_pillars", 1),
GRFFeatureInfo("varaction2_station_var42", 1), GRFFeatureInfo("varaction2_station_var42", 1),
GRFFeatureInfo("more_bridge_types", 1), GRFFeatureInfo("more_bridge_types", 1),
GRFFeatureInfo("action0_bridge_prop14", 1), GRFFeatureInfo("action0_bridge_prop14", 1),
GRFFeatureInfo("action0_bridge_pillar_flags", 1),
GRFFeatureInfo(), GRFFeatureInfo(),
}; };
@@ -8077,7 +8097,9 @@ static bool HandleFeatureTestInfo(ByteReader *buf)
/** Action14 Action0 remappable property list */ /** Action14 Action0 remappable property list */
static const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = { static const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
GRFPropertyMapDefinition(GSF_STATIONS, A0RPI_STATION_MIN_BRIDGE_HEIGHT, "station_min_bridge_height"), 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_MENU_ICON, "bridge_menu_icon"),
GRFPropertyMapDefinition(GSF_BRIDGES, A0RPI_BRIDGE_PILLAR_FLAGS, "bridge_pillar_flags"),
GRFPropertyMapDefinition(), GRFPropertyMapDefinition(),
}; };

View File

@@ -109,7 +109,9 @@ enum Action0RemapPropertyIds {
A0RPI_UNKNOWN_ERROR, A0RPI_UNKNOWN_ERROR,
A0RPI_STATION_MIN_BRIDGE_HEIGHT, A0RPI_STATION_MIN_BRIDGE_HEIGHT,
A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS,
A0RPI_BRIDGE_MENU_ICON, A0RPI_BRIDGE_MENU_ICON,
A0RPI_BRIDGE_PILLAR_FLAGS,
}; };
enum Action0RemapFallbackMode { enum Action0RemapFallbackMode {

View File

@@ -114,6 +114,7 @@ enum StationRandomTrigger {
enum StationSpecIntlFlags { enum StationSpecIntlFlags {
SSIF_COPIED_LAYOUTS, ///< Copied StationLayout **layouts. SSIF_COPIED_LAYOUTS, ///< Copied StationLayout **layouts.
SSIF_BRIDGE_HEIGHTS_SET, ///< byte bridge_height[8] is set. 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 /* 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 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 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_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; AnimationInfo animation;

View File

@@ -775,28 +775,56 @@ CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z
return cost; 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); assert(layout < 8);
if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) { 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) { } else if (!statspec) {
// default stations/waypoints // default stations/waypoints
const int height = layout < 4 ? 2 : 5; 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 { } else {
return _settings_game.construction.allow_stations_under_bridges; 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 {
// 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 southern_bridge_end = GetSouthernBridgeEnd(tile);
TileIndex northern_bridge_end = GetNorthernBridgeEnd(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++) { for (uint i = 0; i < numtracks; i++) {
TileIndex tile = tile_track; TileIndex tile = tile_track;
for (uint j = 0; j < plat_len; j++) { 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 += tile_delta;
} }
tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta

View File

@@ -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 nrl description of the rail bridge in query tool
* @param nrd description of the road 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) \ #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} {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[] = { const BridgeSpec _orig_bridge[] = {
/* /*
@@ -758,49 +762,52 @@ const BridgeSpec _orig_bridge[] = {
string with description name on rail name on road string with description name on rail name on road
| | | | */ | | | | */
MBR( 0, 0, 0xFFFF, 80, 32, 0xA24, PAL_NONE, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, ALL_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, ALL_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, ALL_PILLARS),
}; };
#undef CANT_PILLARS
#undef SUSP_PILLARS
#undef ALL_PILLARS
#undef MBR #undef MBR
#undef MN #undef MN
#undef MR #undef MR

View File

@@ -65,7 +65,8 @@ extern void DrawTrackBits(TileInfo *ti, TrackBits track);
extern void DrawRoadBits(TileInfo *ti); extern void DrawRoadBits(TileInfo *ti);
extern const RoadBits _invalid_tileh_slopes_road[2][15]; 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. * Mark bridge tiles dirty.
@@ -499,7 +500,9 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
case STATION_RAIL: case STATION_RAIL:
case STATION_WAYPOINT: { 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; goto not_valid_below;
} }
break; 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. * Draw the middle bits of a bridge.
* @param ti Tile information of the tile to draw it on. * @param ti Tile information of the tile to draw it on.

View File

@@ -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 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 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 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 * 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; TileIndex tile = start_tile + i * offset;
CommandCost ret = IsValidTileForWaypoint(tile, axis, &est); CommandCost ret = IsValidTileForWaypoint(tile, axis, &est);
if (ret.Failed()) return ret; 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; Waypoint *wp = NULL;