diff --git a/docs/landscape.html b/docs/landscape.html index 99243101e6..f592cd0f6a 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -989,8 +989,11 @@ +
  • m6 bit 7: rail station / waypoint may have catenary pylons
  • +
  • m6 bit 6: rail station / waypoint may have catenary wires
  • m6 bits 5..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint)
  • m6 bit 2: pbs reservation state for railway stations/waypoints
  • +
  • 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 e7e55aabf3..a0fa527a6b 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -188,7 +188,7 @@ the array so you can quickly see what is used and what is not. XXXX OOOO XXXX XXXX XXXX XXXX - OOXXX XOO + XXXXX XOX XXXX XXXX OOOO OOOO OOXX XXXX diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 5fb5ceb752..17f38d2cb8 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -840,46 +840,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_t GetAnimStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int) { diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 24ed09283b..714b0332c1 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -47,6 +47,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 "../core/backup_type.hpp" @@ -2856,6 +2857,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 (auto t : Map::Iterate()) { + 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 12c30a33b8..683b94e6cc 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1466,7 +1466,18 @@ CommandCost CmdBuildRailStation(DoCommandFlag flags, TileIndex tile_org, RailTyp 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 8e72a945f7..4268569316 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -43,12 +43,6 @@ void UpdateStationDockingTiles(Station *st); void RemoveDockingTile(TileIndex t); void ClearDockingTilesCheckingNeighbours(TileIndex tile); -/* 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 7eee619e02..ed21c71848 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -329,6 +329,78 @@ static inline bool IsHangarTile(Tile 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(Tile t) +{ + assert(HasStationRail(t)); + return HasBit(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(Tile t, bool b) +{ + assert(HasStationRail(t)); + SB(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(Tile t) +{ + assert(HasStationRail(t)); + return HasBit(t.m6(), 6); +} + +/** + * 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(Tile t, bool b) +{ + assert(HasStationRail(t)); + SB(t.m6(), 6, 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(Tile t) +{ + assert(HasStationRail(t)); + return HasBit(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(Tile t, bool b) +{ + assert(HasStationRail(t)); + SB(t.m6(), 7, 1, b ? 1 : 0); +} + /** * Get the rail direction of a rail station. * @param t Tile to query @@ -379,10 +451,10 @@ static inline TrackBits GetRailStationTrackBits(Tile t) static inline bool IsCompatibleTrainStationTile(Tile test_tile, Tile station_tile) { assert(IsRailStationTile(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 11da28b6dd..cfc5500230 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -277,6 +277,18 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlag flags, TileIndex start_tile, Axis HasStationReservation(tile); MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout_ptr[i], GetRailType(tile)); 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);