Extend station bridge above flags for more than 8 station gfx values

This commit is contained in:
Jonathan G Rennison 2024-08-22 14:55:02 +01:00
parent 84c6a917d8
commit f72d8d0b48
5 changed files with 72 additions and 29 deletions

View File

@ -201,18 +201,38 @@
<h3 id="a0stations"><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations">Action 0 - Stations</a></h3>
<h4 id="station_min_bridge_height"><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 property allows building bridges over stations.<br />
The bridge height property defines minimum clearances required for a bridge for each of the 8 station layouts (or 0 to not allow any bridge). Values are given in height level units (1 level == 8px).<br />
Each height value is 1 byte, the total property length is 8 bytes.
The bridge height property defines minimum clearances required for a bridge for each of the station layouts (or 0 to not allow any bridge). Values are given in height level units (1 level == 8px).<br />
</p>
<p>Fixed length of 8 values:<br />
Each height value is 1 byte, the number of values (one for each station layout) is 8, the total property length is 8 bytes.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_station_prop1B</font>, version 1</p>
<p>Variable length:<br />
Each height value is 1 byte, the number of values (one for each station layout) is variable, the total property length is variable.<br />
The mappable property must be used, not variable 1B. The number of values is determined from the length.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_station_min_bridge_height</font>, version 1</p>
<h4 id="station_disallowed_bridge_pillars">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 />
It consists of N pillar flags, for each of the N station layouts.<br />
Each set of flags is 1 byte.<br />
Each set of flags has the format described in the bridge_pillar_flags property section, below.
</p>
<p>Fixed length of 8 values:<br />
Each set of flags is 1 byte, the number of values (one for each station layout) is 8, the total property length is 8 bytes.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_station_disallowed_bridge_pillars</font>, version 1</p>
<p>Variable length:<br />
Each set of flags is 1 byte, the number of values (one for each station layout) is variable, the total property length is variable.<br />
The number of values is determined from the length.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_station_disallowed_bridge_pillars</font>, version 2</p>
<br />
The 8 station layouts are described below.
<table>

View File

@ -2148,23 +2148,33 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons
break;
}
case A0RPI_STATION_MIN_BRIDGE_HEIGHT:
if (MappedPropertyLengthMismatch(buf, 8, mapping_entry)) break;
[[fallthrough]];
case A0RPI_STATION_MIN_BRIDGE_HEIGHT: {
SetBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET);
size_t length = buf->ReadExtendedByte();
if (statspec->bridge_above_flags.size() < length) statspec->bridge_above_flags.resize(length);
for (size_t i = 0; i < length; i++) {
statspec->bridge_above_flags[i].height = buf->ReadByte();
}
break;
}
case 0x1B: // Minimum height for a bridge above
SetBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET);
if (statspec->bridge_above_flags.size() < 8) statspec->bridge_above_flags.resize(8);
for (uint i = 0; i < 8; i++) {
statspec->bridge_height[i] = buf->ReadByte();
statspec->bridge_above_flags[i].height = buf->ReadByte();
}
break;
case A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS:
if (MappedPropertyLengthMismatch(buf, 8, mapping_entry)) break;
case A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS: {
SetBit(statspec->internal_flags, SSIF_BRIDGE_DISALLOWED_PILLARS_SET);
for (uint i = 0; i < 8; i++) {
statspec->bridge_disallowed_pillars[i] = buf->ReadByte();
size_t length = buf->ReadExtendedByte();
if (statspec->bridge_above_flags.size() < length) statspec->bridge_above_flags.resize(length);
for (size_t i = 0; i < length; i++) {
statspec->bridge_above_flags[i].disallowed_pillars = buf->ReadByte();
}
break;
}
case 0x1C: // Station Name
AddStringForMapping(buf->ReadWord(), &statspec->name);

View File

@ -22,7 +22,8 @@ extern const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("feature_id_mapping", 2),
GRFFeatureInfo("action5_type_id_mapping", 2),
GRFFeatureInfo("action0_station_prop1B", 1),
GRFFeatureInfo("action0_station_disallowed_bridge_pillars", 1),
GRFFeatureInfo("action0_station_min_bridge_height", 1),
GRFFeatureInfo("action0_station_disallowed_bridge_pillars", 2),
GRFFeatureInfo("varaction2_station_var42", 1),
GRFFeatureInfo("varaction2_station_station_nearby_info_v2", 1),
GRFFeatureInfo("more_bridge_types", 1),

View File

@ -177,8 +177,11 @@ struct StationSpec : NewGRFSpecBase<StationClassID> {
uint8_t flags; ///< Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size
uint8_t bridge_height[8]; ///< Minimum height for a bridge above, 0 for none
uint8_t bridge_disallowed_pillars[8]; ///< Disallowed pillar flags for a bridge above
struct BridgeAboveFlags {
uint8_t height = UINT8_MAX; ///< Minimum height for a bridge above, 0 for none
uint8_t disallowed_pillars = 0; ///< Disallowed pillar flags for a bridge above
};
std::vector<BridgeAboveFlags> bridge_above_flags; ///< List of bridge above flags.
enum class TileFlags : uint8_t {
None = 0,
@ -194,6 +197,12 @@ struct StationSpec : NewGRFSpecBase<StationClassID> {
/** Custom platform layouts, keyed by platform and length combined. */
std::unordered_map<uint16_t, std::vector<uint8_t>> layouts;
BridgeAboveFlags GetBridgeAboveFlags(uint gfx) const
{
if (gfx < this->bridge_above_flags.size()) return this->bridge_above_flags[gfx];
return {};
}
};
DECLARE_ENUM_AS_BIT_SET(StationSpec::TileFlags);

View File

@ -924,15 +924,14 @@ CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z
CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, uint8_t 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)) {
if (statspec->bridge_height[layout] == 0) return CommandCost(INVALID_STRING_ID);
if (GetTileMaxZ(tile) + statspec->bridge_height[layout] > bridge_height) {
if (statspec != nullptr && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) {
int height_above = statspec->GetBridgeAboveFlags(layout).height;
if (height_above == 0) return CommandCost(INVALID_STRING_ID);
if (GetTileMaxZ(tile) + height_above > bridge_height) {
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
}
} else if (!statspec) {
// default stations/waypoints
/* Default stations/waypoints */
const int height = layout < 4 ? 2 : 5;
if (GetTileMaxZ(tile) + height > bridge_height) return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
} else {
@ -940,18 +939,22 @@ CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statsp
}
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_disallowed_pillars[layout];
if (statspec != nullptr && HasBit(statspec->internal_flags, SSIF_BRIDGE_DISALLOWED_PILLARS_SET)) {
/* Pillar flags set by NewGRF */
disallowed_pillar_flags = (BridgePiecePillarFlags) statspec->GetBridgeAboveFlags(layout).disallowed_pillars;
} else if (!statspec) {
// default stations/waypoints
/* Default stations/waypoints */
if (layout < 8) {
static const uint8_t st_flags[8] = { 0x50, 0xA0, 0x50, 0xA0, 0x50 | 0x26, 0xA0 | 0x1C, 0x50 | 0x89, 0xA0 | 0x43 };
disallowed_pillar_flags = (BridgePiecePillarFlags) st_flags[layout];
} else {
disallowed_pillar_flags = (BridgePiecePillarFlags) 0;
}
} else if ((GetStationTileFlags(layout, statspec) & StationSpec::TileFlags::Blocked) == StationSpec::TileFlags::Blocked) {
// non-track station tiles
/* Non-track station tiles */
disallowed_pillar_flags = (BridgePiecePillarFlags) 0;
} else {
// tracked station tiles
/* Tracked station tiles */
const Axis axis = HasBit(layout, 0) ? AXIS_Y : AXIS_X;
disallowed_pillar_flags = (BridgePiecePillarFlags) (axis == AXIS_X ? 0x50 : 0xA0);
}