diff --git a/src/newgrf_roadstop.cpp b/src/newgrf_roadstop.cpp index da022d14f3..f093c0b2b4 100644 --- a/src/newgrf_roadstop.cpp +++ b/src/newgrf_roadstop.cpp @@ -561,20 +561,22 @@ const RoadStopSpec *GetRoadStopSpec(TileIndex t) /** * Allocate a RoadStopSpec to a Station. This is called once per build operation. - * @param statspec RoadStopSpec to allocate. + * @param spec RoadStopSpec to allocate. * @param st Station to allocate it to. - * @param exec Whether to actually allocate the spec. * @return Index within the Station's road stop spec list, or std::nullopt if the allocation failed. */ -std::optional AllocateSpecToRoadStop(const RoadStopSpec *statspec, BaseStation *st, bool exec) +std::optional AllocateSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st) { uint i; - if (statspec == nullptr || st == nullptr) return 0; + if (spec == nullptr) return 0; + + /* If station doesn't exist yet then the first slot is available. */ + if (st == nullptr) return 1; /* Try to find the same spec and return that one */ for (i = 1; i < st->roadstop_speclist.size() && i < NUM_ROADSTOPSPECS_PER_STATION; i++) { - if (st->roadstop_speclist[i].spec == statspec) return i; + if (st->roadstop_speclist[i].spec == spec) return i; } /* Try to find an unused spec slot */ @@ -587,18 +589,27 @@ std::optional AllocateSpecToRoadStop(const RoadStopSpec *statspec, Base return std::nullopt; } - if (exec) { - if (i >= st->roadstop_speclist.size()) st->roadstop_speclist.resize(i + 1); - st->roadstop_speclist[i].spec = statspec; - st->roadstop_speclist[i].grfid = statspec->grf_prop.grfid; - st->roadstop_speclist[i].localidx = statspec->grf_prop.local_id; - - RoadStopUpdateCachedTriggers(st); - } - return i; } +/** + * Assign a previously allocated RoadStopSpec specindex to a Station. + * @param spec RoadStopSpec to assign.. + * @param st Station to allocate it to. + * @param specindex Spec index of allocation. + */ +void AssignSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st, uint8_t specindex) +{ + if (specindex == 0) return; + if (specindex >= st->roadstop_speclist.size()) st->roadstop_speclist.resize(specindex + 1); + + st->roadstop_speclist[specindex].spec = spec; + st->roadstop_speclist[specindex].grfid = spec->grf_prop.grfid; + st->roadstop_speclist[specindex].localidx = spec->grf_prop.local_id; + + RoadStopUpdateCachedTriggers(st); +} + /** * Deallocate a RoadStopSpec from a Station. Called when removing a single roadstop tile. * @param st Station to work with. diff --git a/src/newgrf_roadstop.h b/src/newgrf_roadstop.h index 3f826aac43..73fa2e9db6 100644 --- a/src/newgrf_roadstop.h +++ b/src/newgrf_roadstop.h @@ -177,7 +177,8 @@ bool GetIfClassHasNewStopsByType(const RoadStopClass *roadstopclass, RoadStopTyp bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs, RoadType roadtype); const RoadStopSpec *GetRoadStopSpec(TileIndex t); -std::optional AllocateSpecToRoadStop(const RoadStopSpec *statspec, BaseStation *st, bool exec); +std::optional AllocateSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st); +void AssignSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st, uint8_t specindex); void DeallocateSpecFromRoadStop(BaseStation *st, uint8_t specindex); void RoadStopUpdateCachedTriggers(BaseStation *st); diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index d307e6dd9d..358f6505d5 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -692,16 +692,18 @@ CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_til /** * Allocate a StationSpec to a Station. This is called once per build operation. - * @param statspec StationSpec to allocate. + * @param spec StationSpec to allocate. * @param st Station to allocate it to. - * @param exec Whether to actually allocate the spec. * @return Index within the Station's station spec list, or std::nullopt if the allocation failed. */ -std::optional AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec) +std::optional AllocateSpecToStation(const StationSpec *spec, BaseStation *st) { uint i; - if (statspec == nullptr || st == nullptr) return 0; + if (spec == nullptr) return 0; + + /* If station doesn't exist yet then the first slot is available. */ + if (st == nullptr) return 1; for (i = 1; i < st->speclist.size() && i < NUM_STATIONSSPECS_PER_STATION; i++) { if (st->speclist[i].spec == nullptr && st->speclist[i].grfid == 0) break; @@ -714,24 +716,32 @@ std::optional AllocateSpecToStation(const StationSpec *statspec, BaseSt * but it's fairly unlikely that one reaches the limit anyways. */ for (i = 1; i < st->speclist.size() && i < NUM_STATIONSSPECS_PER_STATION; i++) { - if (st->speclist[i].spec == statspec) return i; + if (st->speclist[i].spec == spec) return i; } return std::nullopt; } - if (exec) { - if (i >= st->speclist.size()) st->speclist.resize(i + 1); - st->speclist[i].spec = statspec; - st->speclist[i].grfid = statspec->grf_prop.grfid; - st->speclist[i].localidx = statspec->grf_prop.local_id; - - StationUpdateCachedTriggers(st); - } - return i; } +/** + * Assign a previously allocated StationSpec specindex to a Station. + * @param spec StationSpec to assign.. + * @param st Station to allocate it to. + * @param specindex Spec index of allocation. + */ +void AssignSpecToStation(const StationSpec *spec, BaseStation *st, uint8_t specindex) +{ + if (specindex == 0) return; + if (specindex >= st->speclist.size()) st->speclist.resize(specindex + 1); + + st->speclist[specindex].spec = spec; + st->speclist[specindex].grfid = spec->grf_prop.grfid; + st->speclist[specindex].localidx = spec->grf_prop.local_id; + + StationUpdateCachedTriggers(st); +} /** * Deallocate a StationSpec from a Station. Called when removing a single station tile. diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 2537209fd8..990f0bc4a9 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -215,7 +215,8 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS uint16_t GetStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, std::span regs100 = {}); CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, uint8_t plat_len, uint8_t numtracks); -std::optional AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec); +std::optional AllocateSpecToStation(const StationSpec *spec, BaseStation *st); +void AssignSpecToStation(const StationSpec *spec, BaseStation *st, uint8_t specindex); void DeallocateSpecFromStation(BaseStation *st, uint8_t specindex); bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station); diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index 58d014a15d..57edac0323 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -136,7 +136,8 @@ void MoveWaypointsToBaseStations() SetRailStationReservation(tile, reserved); if (wp.spec != nullptr) { - auto specindex = AllocateSpecToStation(wp.spec, new_wp, true); + auto specindex = AllocateSpecToStation(wp.spec, new_wp); + if (specindex.has_value()) AssignSpecToStation(wp.spec, new_wp, *specindex); SetCustomStationSpecIndex(tile, specindex.value_or(0)); } new_wp->rect.BeforeAddTile(tile, StationRect::ADD_FORCE); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 2b5aadb8fe..ce85d755e2 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1491,7 +1491,7 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy } /* Check if we can allocate a custom stationspec to this station */ - auto specindex = AllocateSpecToStation(statspec, st, flags.Test(DoCommandFlag::Execute)); + auto specindex = AllocateSpecToStation(statspec, st); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (statspec != nullptr) { @@ -1514,6 +1514,7 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY); + if (specindex.has_value()) AssignSpecToStation(statspec, st, *specindex); if (statspec != nullptr) { /* Include this station spec's animation trigger bitmask * in the station's cached copy. */ @@ -2113,7 +2114,7 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width if (ret.Failed()) return ret; /* Check if we can allocate a custom stationspec to this station */ - auto specindex = AllocateSpecToRoadStop(roadstopspec, st, flags.Test(DoCommandFlag::Execute)); + auto specindex = AllocateSpecToRoadStop(roadstopspec, st); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (roadstopspec != nullptr) { @@ -2127,6 +2128,7 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width } if (flags.Test(DoCommandFlag::Execute)) { + if (specindex.has_value()) AssignSpecToRoadStop(roadstopspec, st, *specindex); /* Check every tile in the area. */ for (TileIndex cur_tile : roadstop_area) { /* Get existing road types and owners before any tile clearing */ diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 18a0540595..1a0dba435d 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -271,7 +271,8 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING); } - auto specindex = AllocateSpecToStation(spec, wp, flags.Test(DoCommandFlag::Execute)); + /* Check if we can allocate a custom spec to this waypoint. */ + auto specindex = AllocateSpecToStation(spec, wp); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (flags.Test(DoCommandFlag::Execute)) { @@ -284,6 +285,7 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi wp->owner = GetTileOwner(start_tile); wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY); + if (specindex.has_value()) AssignSpecToStation(spec, wp, *specindex); wp->delete_ctr = 0; wp->facilities.Set(StationFacility::Train); @@ -391,8 +393,8 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING); } - /* Check if we can allocate a custom roadstopspec to this station */ - auto specindex = AllocateSpecToRoadStop(roadstopspec, wp, flags.Test(DoCommandFlag::Execute)); + /* Check if we can allocate a custom spec to this waypoint. */ + auto specindex = AllocateSpecToRoadStop(roadstopspec, wp); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (flags.Test(DoCommandFlag::Execute)) { @@ -406,6 +408,7 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi wp->owner = _current_company; wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY); + if (specindex.has_value()) AssignSpecToRoadStop(roadstopspec, wp, *specindex); if (roadstopspec != nullptr) { /* Include this road stop spec's animation trigger bitmask