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

Action 0 - Stations

Minimum bridge height (1B, or mappable property: station_min_bridge_height)

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

Action 0 - Bridges

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: + + + + + + + + + + +
BitValueMeaning
01Pillar is present in west corner
12Pillar is present in south corner
24Pillar is present in east corner
38Pillar is present in north corner
410Pillar is present along entire north-east edge
520Pillar is present along entire south-east edge
640Pillar is present along entire south-west edge
780Pillar 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

Variational Action 2 - Stations

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;