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> <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> <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 /> <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 /> 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 />
Each height value is 1 byte, the total property length is 8 bytes. </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>
<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>
<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> <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 /> <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 /> It consists of N pillar flags, for each of the N station layouts.<br />
Each set of flags is 1 byte, the total property length is 8 bytes.<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. Each set of flags has the format described in the bridge_pillar_flags property section, below.
</p> </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>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 /> <br />
The 8 station layouts are described below. The 8 station layouts are described below.
<table> <table>

View File

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

View File

@ -22,7 +22,8 @@ extern const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("feature_id_mapping", 2), GRFFeatureInfo("feature_id_mapping", 2),
GRFFeatureInfo("action5_type_id_mapping", 2), GRFFeatureInfo("action5_type_id_mapping", 2),
GRFFeatureInfo("action0_station_prop1B", 1), 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_var42", 1),
GRFFeatureInfo("varaction2_station_station_nearby_info_v2", 1), GRFFeatureInfo("varaction2_station_station_nearby_info_v2", 1),
GRFFeatureInfo("more_bridge_types", 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 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 struct BridgeAboveFlags {
uint8_t bridge_disallowed_pillars[8]; ///< Disallowed pillar flags for a bridge above 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 { enum class TileFlags : uint8_t {
None = 0, None = 0,
@ -194,6 +197,12 @@ struct StationSpec : NewGRFSpecBase<StationClassID> {
/** Custom platform layouts, keyed by platform and length combined. */ /** Custom platform layouts, keyed by platform and length combined. */
std::unordered_map<uint16_t, std::vector<uint8_t>> layouts; 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); 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, 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) BridgeType bridge_type, TransportType bridge_transport_type)
{ {
assert(layout < 8); if (statspec != nullptr && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) {
int height_above = statspec->GetBridgeAboveFlags(layout).height;
if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) { if (height_above == 0) return CommandCost(INVALID_STRING_ID);
if (statspec->bridge_height[layout] == 0) return CommandCost(INVALID_STRING_ID); if (GetTileMaxZ(tile) + height_above > bridge_height) {
if (GetTileMaxZ(tile) + statspec->bridge_height[layout] > bridge_height) {
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION); 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;
if (GetTileMaxZ(tile) + height > bridge_height) return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION); if (GetTileMaxZ(tile) + height > bridge_height) return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
} else { } else {
@ -940,18 +939,22 @@ CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statsp
} }
BridgePiecePillarFlags disallowed_pillar_flags; BridgePiecePillarFlags disallowed_pillar_flags;
if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_DISALLOWED_PILLARS_SET)) { if (statspec != nullptr && HasBit(statspec->internal_flags, SSIF_BRIDGE_DISALLOWED_PILLARS_SET)) {
// pillar flags set by NewGRF /* Pillar flags set by NewGRF */
disallowed_pillar_flags = (BridgePiecePillarFlags) statspec->bridge_disallowed_pillars[layout]; disallowed_pillar_flags = (BridgePiecePillarFlags) statspec->GetBridgeAboveFlags(layout).disallowed_pillars;
} else if (!statspec) { } else if (!statspec) {
// default stations/waypoints /* Default stations/waypoints */
static const uint8_t st_flags[8] = { 0x50, 0xA0, 0x50, 0xA0, 0x50 | 0x26, 0xA0 | 0x1C, 0x50 | 0x89, 0xA0 | 0x43 }; if (layout < 8) {
disallowed_pillar_flags = (BridgePiecePillarFlags) st_flags[layout]; 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) { } else if ((GetStationTileFlags(layout, statspec) & StationSpec::TileFlags::Blocked) == StationSpec::TileFlags::Blocked) {
// non-track station tiles /* Non-track station tiles */
disallowed_pillar_flags = (BridgePiecePillarFlags) 0; disallowed_pillar_flags = (BridgePiecePillarFlags) 0;
} else { } else {
// tracked station tiles /* Tracked station tiles */
const Axis axis = HasBit(layout, 0) ? AXIS_Y : AXIS_X; const Axis axis = HasBit(layout, 0) ? AXIS_Y : AXIS_X;
disallowed_pillar_flags = (BridgePiecePillarFlags) (axis == AXIS_X ? 0x50 : 0xA0); disallowed_pillar_flags = (BridgePiecePillarFlags) (axis == AXIS_X ? 0x50 : 0xA0);
} }