* Perform all steps to upgrade from the old waypoints to the new version * that uses station. This includes some old saveload mechanics. */
| 66 | * that uses station. This includes some old saveload mechanics. |
| 67 | */ |
| 68 | void MoveWaypointsToBaseStations() |
| 69 | { |
| 70 | /* In version 17, ground type is moved from m2 to m4 for depots and |
| 71 | * waypoints to make way for storing the index in m2. The custom graphics |
| 72 | * id which was stored in m4 is now saved as a grf/id reference in the |
| 73 | * waypoint struct. */ |
| 74 | if (IsSavegameVersionBefore(SLV_17)) { |
| 75 | for (OldWaypoint &wp : _old_waypoints) { |
| 76 | if (wp.delete_ctr != 0) continue; // The waypoint was deleted |
| 77 | |
| 78 | /* Waypoint indices were not added to the map prior to this. */ |
| 79 | Tile tile = wp.xy; |
| 80 | tile.m2() = wp.index; |
| 81 | |
| 82 | if (HasBit(tile.m3(), 4)) { |
| 83 | wp.spec = StationClass::Get(STAT_CLASS_WAYP)->GetSpec(tile.m4() + 1); |
| 84 | } |
| 85 | } |
| 86 | } else { |
| 87 | /* As of version 17, we recalculate the custom graphic ID of waypoints |
| 88 | * from the GRF ID / station index. */ |
| 89 | for (OldWaypoint &wp : _old_waypoints) { |
| 90 | const auto specs = StationClass::Get(STAT_CLASS_WAYP)->Specs(); |
| 91 | auto found = std::ranges::find_if(specs, [&wp](const StationSpec *spec) { return spec != nullptr && spec->grf_prop.grfid == wp.grfid && spec->grf_prop.local_id == wp.localidx; }); |
| 92 | if (found != std::end(specs)) wp.spec = *found; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | if (!Waypoint::CanAllocateItem(_old_waypoints.size())) SlError(STR_ERROR_TOO_MANY_STATIONS_LOADING); |
| 97 | |
| 98 | /* All saveload conversions have been done. Create the new waypoints! */ |
| 99 | for (OldWaypoint &wp : _old_waypoints) { |
| 100 | TileIndex t = wp.xy; |
| 101 | /* Sometimes waypoint (sign) locations became disconnected from their actual location in |
| 102 | * the map array. If this is the case, try to locate the actual location in the map array */ |
| 103 | if (!IsTileType(t, MP_RAILWAY) || GetRailTileType(t) != RailTileType{2} /* RAIL_TILE_WAYPOINT */ || Tile(t).m2() != wp.index) { |
| 104 | Debug(sl, 0, "Found waypoint tile {} with invalid position", t); |
| 105 | t = INVALID_TILE; |
| 106 | for (auto tile : Map::Iterate()) { |
| 107 | if (IsTileType(tile, MP_RAILWAY) && GetRailTileType(tile) == RailTileType{2} /* RAIL_TILE_WAYPOINT */ && tile.m2() == wp.index) { |
| 108 | t = TileIndex(tile); |
| 109 | Debug(sl, 0, "Found actual waypoint position at {}", TileIndex(tile)); |
| 110 | break; |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | if (t == INVALID_TILE) { |
| 115 | SlErrorCorrupt("Waypoint with invalid tile"); |
| 116 | } |
| 117 | |
| 118 | Waypoint *new_wp = new Waypoint(t); |
| 119 | new_wp->town = wp.town; |
| 120 | new_wp->town_cn = wp.town_cn; |
| 121 | new_wp->name = wp.name; |
| 122 | new_wp->delete_ctr = 0; // Just reset delete counter for once. |
| 123 | new_wp->build_date = wp.build_date; |
| 124 | new_wp->owner = wp.owner; |
| 125 | new_wp->string_id = STR_SV_STNAME_WAYPOINT; |
no test coverage detected