From a03ddb3ccbff5db6b297614086862715358c6582 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 21 Apr 2024 15:44:26 +0100 Subject: [PATCH] Add: [NewGRF] Station property 1E, extended station tile flags. Properties 11, 14 and 15 to set pylons/nowires/blocked intrinsically only support 8 station tiles. Add new property to define all three flags for each station tile layout. --- src/newgrf.cpp | 46 ++++++++++++++++++++++++++++++++++++++------ src/newgrf_station.h | 14 ++++++++++---- src/station_cmd.cpp | 26 ++++++++++++++++--------- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 85ec3052e3..5b51d43528 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2075,9 +2075,18 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte statspec->cargo_threshold = buf.ReadWord(); break; - case 0x11: // Pylon placement - statspec->pylons = buf.ReadByte(); + case 0x11: { // Pylon placement + uint8_t pylons = buf.ReadByte(); + if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8); + for (int j = 0; j < 8; ++j) { + if (HasBit(pylons, j)) { + statspec->tileflags[j] |= StationSpec::TileFlags::Pylons; + } else { + statspec->tileflags[j] &= ~StationSpec::TileFlags::Pylons; + } + } break; + } case 0x12: // Cargo types for random triggers if (_cur.grffile->grf_version >= 7) { @@ -2091,13 +2100,31 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte statspec->flags = buf.ReadByte(); break; - case 0x14: // Overhead wire placement - statspec->wires = buf.ReadByte(); + case 0x14: { // Overhead wire placement + uint8_t wires = buf.ReadByte(); + if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8); + for (int j = 0; j < 8; ++j) { + if (HasBit(wires, j)) { + statspec->tileflags[j] |= StationSpec::TileFlags::NoWires; + } else { + statspec->tileflags[j] &= ~StationSpec::TileFlags::NoWires; + } + } break; + } - case 0x15: // Blocked tiles - statspec->blocked = buf.ReadByte(); + case 0x15: { // Blocked tiles + uint8_t blocked = buf.ReadByte(); + if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8); + for (int j = 0; j < 8; ++j) { + if (HasBit(blocked, j)) { + statspec->tileflags[j] |= StationSpec::TileFlags::Blocked; + } else { + statspec->tileflags[j] &= ~StationSpec::TileFlags::Blocked; + } + } break; + } case 0x16: // Animation info statspec->animation.frames = buf.ReadByte(); @@ -2149,6 +2176,13 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte AddStringForMapping(buf.ReadWord(), [statspec](StringID str) { StationClass::Get(statspec->class_index)->name = str; }); break; + case 0x1E: { // Extended tile flags (replaces prop 11, 14 and 15) + uint16_t tiles = buf.ReadExtendedByte(); + auto flags = reinterpret_cast(buf.ReadBytes(tiles)); + statspec->tileflags.assign(flags, flags + tiles); + break; + } + default: ret = CIR_UNKNOWN; break; diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 21a833227d..2a5c711707 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -10,6 +10,7 @@ #ifndef NEWGRF_STATION_H #define NEWGRF_STATION_H +#include "core/enum_type.hpp" #include "newgrf_animation_type.h" #include "newgrf_callbacks.h" #include "newgrf_class.h" @@ -115,7 +116,7 @@ struct StationSpec : NewGRFSpecBase { StationSpec() : name(0), disallowed_platforms(0), disallowed_lengths(0), cargo_threshold(0), cargo_triggers(0), - callback_mask(0), flags(0), pylons(0), wires(0), blocked(0), + callback_mask(0), flags(0), animation({0, 0, 0, 0}) {} /** * Properties related the the grf file. @@ -159,9 +160,13 @@ struct StationSpec : NewGRFSpecBase { uint8_t flags; ///< Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size - uint8_t pylons; ///< Bitmask of base tiles (0 - 7) which should contain elrail pylons - uint8_t wires; ///< Bitmask of base tiles (0 - 7) which should contain elrail wires - uint8_t blocked; ///< Bitmask of base tiles (0 - 7) which are blocked to trains + enum class TileFlags : uint8_t { + None = 0, + Pylons = 1U << 0, ///< Tile should contain catenary pylons. + NoWires = 1U << 1, ///< Tile should NOT contain catenary wires. + Blocked = 1U << 2, ///< Tile is blocked to vehicles. + }; + std::vector tileflags; ///< List of tile flags. AnimationInfo animation; @@ -175,6 +180,7 @@ struct StationSpec : NewGRFSpecBase { */ std::vector>> layouts; }; +DECLARE_ENUM_AS_BIT_SET(StationSpec::TileFlags); /** Class containing information relating to station classes. */ using StationClass = NewGRFClass; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index afad43768b..9b05e83d3b 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1305,6 +1305,19 @@ static CommandCost CalculateRailStationCost(TileArea tile_area, DoCommandFlag fl return cost; } +/** + * Get station tile flags for the given StationGfx. + * @param gfx StationGfx of station tile. + * @param statspec Station spec of station tile. + * @return Tile flags to apply. + */ +static StationSpec::TileFlags GetStationTileFlags(StationGfx gfx, const StationSpec *statspec) +{ + /* Default stations do not draw pylons under roofs (gfx >= 4) */ + if (statspec == nullptr || gfx >= statspec->tileflags.size()) return gfx < 4 ? StationSpec::TileFlags::Pylons : StationSpec::TileFlags::None; + return statspec->tileflags[gfx]; +} + /** * Set rail station tile flags for the given tile. * @param tile Tile to set flags on. @@ -1312,15 +1325,10 @@ static CommandCost CalculateRailStationCost(TileArea tile_area, DoCommandFlag fl */ void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec) { - const StationGfx gfx = GetStationGfx(tile); - bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx); - /* Default stations do not draw pylons under roofs (gfx >= 4) */ - bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4; - bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx); - - SetStationTileBlocked(tile, blocked); - SetStationTileHavePylons(tile, pylons); - SetStationTileHaveWires(tile, wires); + const auto flags = GetStationTileFlags(GetStationGfx(tile), statspec); + SetStationTileBlocked(tile, (flags & StationSpec::TileFlags::Blocked) == StationSpec::TileFlags::Blocked); + SetStationTileHavePylons(tile, (flags & StationSpec::TileFlags::Pylons) == StationSpec::TileFlags::Pylons); + SetStationTileHaveWires(tile, (flags & StationSpec::TileFlags::NoWires) != StationSpec::TileFlags::NoWires); } /**