diff --git a/docs/landscape.html b/docs/landscape.html index 78763f9d17..2aa9bbafc5 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -1050,8 +1050,11 @@ +
  • m6 bit 7: rail station / waypoint may have catenary pylons
  • m6 bits 6..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint, road waypoint)
  • m6 bit 2: pbs reservation state for railway stations/waypoints
  • +
  • m6 bit 1: rail station / waypoint may have catenary wires
  • +
  • m6 bit 0: rail station / waypoint is blocked
  • m7 bits 4..0: owner of road (road stops)
  • m7: animation frame (railway stations/waypoints, airports)
  • diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index f4b99e6139..79fa9696b2 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -194,7 +194,7 @@ the array so you can quickly see what is used and what is not. XXXX OOOO XXXX XXXX XXXX XXXX - OPXXX XOO + X PXXX XPX XXXX XXXX OOOO OOOO OOXX XXXX diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 4489e13326..09abffc604 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -872,46 +872,6 @@ const StationSpec *GetStationSpec(TileIndex t) return specindex < st->speclist.size() ? st->speclist[specindex].spec : nullptr; } - -/** - * Check whether a rail station tile is NOT traversable. - * @param tile %Tile to test. - * @return Station tile is blocked. - * @note This could be cached (during build) in the map array to save on all the dereferencing. - */ -bool IsStationTileBlocked(TileIndex tile) -{ - const StationSpec *statspec = GetStationSpec(tile); - - return statspec != nullptr && HasBit(statspec->blocked, GetStationGfx(tile)); -} - -/** - * Check if a rail station tile shall have pylons when electrified. - * @param tile %Tile to test. - * @return Tile shall have pylons. - * @note This could be cached (during build) in the map array to save on all the dereferencing. - */ -bool CanStationTileHavePylons(TileIndex tile) -{ - const StationSpec *statspec = GetStationSpec(tile); - uint gfx = GetStationGfx(tile); - /* Default stations do not draw pylons under roofs (gfx >= 4) */ - return statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4; -} - -/** - * Check if a rail station tile shall have wires when electrified. - * @param tile %Tile to test. - * @return Tile shall have wires. - * @note This could be cached (during build) in the map array to save on all the dereferencing. - */ -bool CanStationTileHaveWires(TileIndex tile) -{ - const StationSpec *statspec = GetStationSpec(tile); - return statspec == nullptr || !HasBit(statspec->wires, GetStationGfx(tile)); -} - /** Wrapper for animation control, see GetStationCallback. */ uint16 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int extra_data) { diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 07d0d4c199..cbed5a99b7 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -49,6 +49,7 @@ #include "../subsidy_base.h" #include "../subsidy_func.h" #include "../newgrf.h" +#include "../newgrf_station.h" #include "../engine_func.h" #include "../rail_gui.h" #include "../road_gui.h" @@ -3337,6 +3338,26 @@ bool AfterLoadGame() _settings_game.script.settings_profile = IsInsideMM(_old_diff_level, SP_BEGIN, SP_END) ? _old_diff_level : (uint)SP_MEDIUM; } + { + /* Station blocked, wires and pylon flags need to be stored in the map. This is effectively cached data, so no + * version check is necessary. This is done here as the SLV_182 check below needs the blocked status. */ + for (TileIndex t = 0; t < map_size; t++) { + if (HasStationTileRail(t)) { + StationGfx gfx = GetStationGfx(t); + const StationSpec *statspec = GetStationSpec(t); + + 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(t, blocked); + SetStationTileHavePylons(t, pylons); + SetStationTileHaveWires(t, wires); + } + } + } + if (IsSavegameVersionBefore(SLV_182)) { /* Aircraft acceleration variable was bonkers */ for (Aircraft *v : Aircraft::Iterate()) { diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 8823994bc2..7d9633d858 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1641,7 +1641,18 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 SetStationTileRandomBits(tile, GB(Random(), 0, 4)); SetAnimationFrame(tile, 0); - if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++; + /* Should be the same as layout but axis component could be wrong... */ + 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); + + if (!blocked) c->infrastructure.rail[rt]++; c->infrastructure.station++; if (statspec != nullptr) { diff --git a/src/station_func.h b/src/station_func.h index ad7a42f5e2..e2e867320b 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -42,12 +42,6 @@ void RemoveDockingTile(TileIndex t); void ClearDockingTilesCheckingNeighbours(TileIndex tile); bool IsValidDockingDirectionForDock(TileIndex t, DiagDirection d); -/* Check if a rail station tile is traversable. */ -bool IsStationTileBlocked(TileIndex tile); - -bool CanStationTileHavePylons(TileIndex tile); -bool CanStationTileHaveWires(TileIndex tile); - void UpdateAirportsNoise(); bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset); diff --git a/src/station_map.h b/src/station_map.h index 54da2fe14e..9807b62c92 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -438,6 +438,78 @@ static inline bool IsHangarTile(TileIndex t) return IsTileType(t, MP_STATION) && IsHangar(t); } +/** + * Is tile \a t a blocked tile? + * @pre HasStationRail(t) + * @param t Tile to check + * @return \c true if the tile is blocked + */ +static inline bool IsStationTileBlocked(TileIndex t) +{ + assert(HasStationRail(t)); + return HasBit(_me[t].m6, 0); +} + +/** + * Set the blocked state of the rail station + * @pre HasStationRail(t) + * @param t the station tile + * @param b the blocked state + */ +static inline void SetStationTileBlocked(TileIndex t, bool b) +{ + assert(HasStationRail(t)); + SB(_me[t].m6, 0, 1, b ? 1 : 0); +} + +/** + * Can tile \a t have catenary wires? + * @pre HasStationRail(t) + * @param t Tile to check + * @return \c true if the tile can have catenary wires + */ +static inline bool CanStationTileHaveWires(TileIndex t) +{ + assert(HasStationRail(t)); + return HasBit(_me[t].m6, 1); +} + +/** + * Set the catenary wires state of the rail station + * @pre HasStationRail(t) + * @param t the station tile + * @param b the catenary wires state + */ +static inline void SetStationTileHaveWires(TileIndex t, bool b) +{ + assert(HasStationRail(t)); + SB(_me[t].m6, 1, 1, b ? 1 : 0); +} + +/** + * Can tile \a t have catenary pylons? + * @pre HasStationRail(t) + * @param t Tile to check + * @return \c true if the tile can have catenary pylons + */ +static inline bool CanStationTileHavePylons(TileIndex t) +{ + assert(HasStationRail(t)); + return HasBit(_me[t].m6, 7); +} + +/** + * Set the catenary pylon state of the rail station + * @pre HasStationRail(t) + * @param t the station tile + * @param b the catenary pylons state + */ +static inline void SetStationTileHavePylons(TileIndex t, bool b) +{ + assert(HasStationRail(t)); + SB(_me[t].m6, 7, 1, b ? 1 : 0); +} + /** * Get the rail direction of a rail station. * @param t Tile to query @@ -488,10 +560,10 @@ static inline TrackBits GetRailStationTrackBits(TileIndex t) static inline bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex station_tile) { dbg_assert_tile(IsRailStationTile(station_tile), station_tile); - return IsRailStationTile(test_tile) && IsCompatibleRail(GetRailType(test_tile), GetRailType(station_tile)) && + return IsRailStationTile(test_tile) && !IsStationTileBlocked(test_tile) && + IsCompatibleRail(GetRailType(test_tile), GetRailType(station_tile)) && GetRailStationAxis(test_tile) == GetRailStationAxis(station_tile) && - GetStationIndex(test_tile) == GetStationIndex(station_tile) && - !IsStationTileBlocked(test_tile); + GetStationIndex(test_tile) == GetStationIndex(station_tile); } /** diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index f3bc17dad3..8c7130478e 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -317,6 +317,18 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout_ptr[i], GetRailType(tile)); if (old_specindex != map_spec_index) DeallocateSpecFromStation(wp, old_specindex); SetCustomStationSpecIndex(tile, map_spec_index); + + /* Should be the same as layout but axis component could be wrong... */ + StationGfx gfx = GetStationGfx(tile); + bool blocked = spec != nullptr && HasBit(spec->blocked, gfx); + /* Default stations do not draw pylons under roofs (gfx >= 4) */ + bool pylons = spec != nullptr ? HasBit(spec->pylons, gfx) : gfx < 4; + bool wires = spec == nullptr || !HasBit(spec->wires, gfx); + + SetStationTileBlocked(tile, blocked); + SetStationTileHavePylons(tile, pylons); + SetStationTileHaveWires(tile, wires); + SetRailStationReservation(tile, reserved); MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);