1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-24 00:03:11 +01:00

Make Parkfile Pathfinding Deterministic (#16147)

* Rename path find functions and use sub function

* Modify leaving park logic to not use park entrance index

* Remove ChosenParkEntrance from peep struct

* Refactor GetNearestParkEntrance

Removed the index as its pointless. Fixed function to use CoordsXY

* Increment network version

* Update replays
This commit is contained in:
Duncan
2021-12-11 16:03:59 +00:00
committed by GitHub
parent 6dc1efde82
commit 56c4240d77
5 changed files with 32 additions and 47 deletions

View File

@@ -65,9 +65,9 @@ set(OBJECTS_VERSION "1.2.4")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip")
set(OBJECTS_SHA1 "c82605035f120188b7334a781a786ced9588e9af") set(OBJECTS_SHA1 "c82605035f120188b7334a781a786ced9588e9af")
set(REPLAYS_VERSION "0.0.60") set(REPLAYS_VERSION "0.0.61")
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip")
set(REPLAYS_SHA1 "1EB460BB3C71BD21CCBE778BEF1E8CD593241A18") set(REPLAYS_SHA1 "18BFAD02A453CE0D5926C13A856546ED825AD0F1")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests") option(WITH_TESTS "Build tests")

View File

@@ -48,8 +48,8 @@
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1> <TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.2.4/objects.zip</ObjectsUrl> <ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.2.4/objects.zip</ObjectsUrl>
<ObjectsSha1>c82605035f120188b7334a781a786ced9588e9af</ObjectsSha1> <ObjectsSha1>c82605035f120188b7334a781a786ced9588e9af</ObjectsSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.60/replays.zip</ReplaysUrl> <ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.61/replays.zip</ReplaysUrl>
<ReplaysSha1>1EB460BB3C71BD21CCBE778BEF1E8CD593241A18</ReplaysSha1> <ReplaysSha1>18BFAD02A453CE0D5926C13A856546ED825AD0F1</ReplaysSha1>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -331,11 +331,7 @@ struct Peep : EntityBase
uint8_t EnergyTarget; uint8_t EnergyTarget;
uint8_t Mass; uint8_t Mass;
uint8_t WindowInvalidateFlags; uint8_t WindowInvalidateFlags;
union ride_id_t CurrentRide;
{
ride_id_t CurrentRide;
ParkEntranceIndex ChosenParkEntrance;
};
StationIndex CurrentRideStation; StationIndex CurrentRideStation;
uint8_t CurrentTrain; uint8_t CurrentTrain;
union union

View File

@@ -40,7 +40,7 @@
// This string specifies which version of network stream current build uses. // This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within // It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version. // single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "4" #define NETWORK_STREAM_VERSION "5"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static Peep* _pickup_peep = nullptr; static Peep* _pickup_peep = nullptr;

View File

@@ -1631,20 +1631,18 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
* @param y y coordinate of location * @param y y coordinate of location
* @return Index of gParkEntrance (or 0xFF if no park entrances exist). * @return Index of gParkEntrance (or 0xFF if no park entrances exist).
*/ */
static uint8_t get_nearest_park_entrance_index(uint16_t x, uint16_t y) static std::optional<CoordsXYZ> GetNearestParkEntrance(const CoordsXY& loc)
{ {
uint8_t chosenEntrance = 0xFF; std::optional<CoordsXYZ> chosenEntrance = std::nullopt;
uint16_t nearestDist = 0xFFFF; uint16_t nearestDist = 0xFFFF;
uint8_t i = 0;
for (const auto& parkEntrance : gParkEntrances) for (const auto& parkEntrance : gParkEntrances)
{ {
auto dist = abs(parkEntrance.x - x) + abs(parkEntrance.y - y); auto dist = abs(parkEntrance.x - loc.x) + abs(parkEntrance.y - loc.y);
if (dist < nearestDist) if (dist < nearestDist)
{ {
nearestDist = dist; nearestDist = dist;
chosenEntrance = i; chosenEntrance = parkEntrance;
} }
i++;
} }
return chosenEntrance; return chosenEntrance;
} }
@@ -1653,16 +1651,16 @@ static uint8_t get_nearest_park_entrance_index(uint16_t x, uint16_t y)
* *
* rct2: 0x006952C0 * rct2: 0x006952C0
*/ */
static int32_t guest_path_find_entering_park(Peep* peep, uint8_t edges) static int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges)
{ {
// Send peeps to the nearest park entrance. // Send peeps to the nearest park entrance.
uint8_t chosenEntrance = get_nearest_park_entrance_index(peep->NextLoc.x, peep->NextLoc.y); auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc);
// If no defined park entrances are found, walk aimlessly. // If no defined park entrances are found, walk aimlessly.
if (chosenEntrance == 0xFF) if (!chosenEntrance.has_value())
return guest_path_find_aimless(peep, edges); return guest_path_find_aimless(peep, edges);
gPeepPathFindGoalPosition = TileCoordsXYZ(gParkEntrances[chosenEntrance]); gPeepPathFindGoalPosition = TileCoordsXYZ(chosenEntrance.value());
gPeepPathFindIgnoreForeignQueues = true; gPeepPathFindIgnoreForeignQueues = true;
gPeepPathFindQueueRideIndex = RIDE_ID_NULL; gPeepPathFindQueueRideIndex = RIDE_ID_NULL;
@@ -1702,7 +1700,7 @@ static uint8_t get_nearest_peep_spawn_index(uint16_t x, uint16_t y)
* *
* rct2: 0x0069536C * rct2: 0x0069536C
*/ */
static int32_t guest_path_find_leaving_park(Peep* peep, uint8_t edges) static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges)
{ {
// Send peeps to the nearest spawn point. // Send peeps to the nearest spawn point.
uint8_t chosenSpawn = get_nearest_peep_spawn_index(peep->NextLoc.x, peep->NextLoc.y); uint8_t chosenSpawn = get_nearest_peep_spawn_index(peep->NextLoc.x, peep->NextLoc.y);
@@ -1733,41 +1731,32 @@ static int32_t guest_path_find_leaving_park(Peep* peep, uint8_t edges)
* *
* rct2: 0x00695161 * rct2: 0x00695161
*/ */
static int32_t guest_path_find_park_entrance(Peep* peep, uint8_t edges) static int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges)
{ {
// If entrance no longer exists, choose a new one TileCoordsXYZ entranceGoal{};
if ((peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN) && peep->ChosenParkEntrance.ToUnderlying() >= gParkEntrances.size()) if (peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)
{ {
peep->ChosenParkEntrance = ParkEntranceIndex::GetNull(); entranceGoal = peep->PathfindGoal;
peep->PeepFlags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN); auto* entranceElement = map_get_park_entrance_element_at(entranceGoal.ToCoordsXYZ(), false);
// If entrance no longer exists, choose a new one
if (entranceElement == nullptr)
{
peep->PeepFlags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN);
}
} }
if (!(peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)) if (!(peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN))
{ {
auto chosenEntrance = ParkEntranceIndex::GetNull(); auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc);
uint16_t nearestDist = 0xFFFF;
uint8_t entranceNum = 0;
for (const auto& entrance : gParkEntrances)
{
uint16_t dist = abs(entrance.x - peep->NextLoc.x) + abs(entrance.y - peep->NextLoc.y);
if (dist < nearestDist)
{
nearestDist = dist;
chosenEntrance = ParkEntranceIndex::FromUnderlying(entranceNum);
}
entranceNum++;
}
if (chosenEntrance.IsNull()) if (!chosenEntrance.has_value())
return guest_path_find_aimless(peep, edges); return guest_path_find_aimless(peep, edges);
peep->ChosenParkEntrance = chosenEntrance;
peep->PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; peep->PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN;
entranceGoal = TileCoordsXYZ(*chosenEntrance);
} }
const auto& entrance = gParkEntrances[peep->ChosenParkEntrance.ToUnderlying()]; gPeepPathFindGoalPosition = entranceGoal;
gPeepPathFindGoalPosition = TileCoordsXYZ(entrance);
gPeepPathFindIgnoreForeignQueues = true; gPeepPathFindIgnoreForeignQueues = true;
gPeepPathFindQueueRideIndex = RIDE_ID_NULL; gPeepPathFindQueueRideIndex = RIDE_ID_NULL;
@@ -2073,9 +2062,9 @@ int32_t guest_path_finding(Guest* peep)
switch (peep->State) switch (peep->State)
{ {
case PeepState::EnteringPark: case PeepState::EnteringPark:
return guest_path_find_entering_park(peep, edges); return GuestPathFindParkEntranceEntering(peep, edges);
case PeepState::LeavingPark: case PeepState::LeavingPark:
return guest_path_find_leaving_park(peep, edges); return GuestPathFindPeepSpawn(peep, edges);
default: default:
return guest_path_find_aimless(peep, edges); return guest_path_find_aimless(peep, edges);
} }
@@ -2140,7 +2129,7 @@ int32_t guest_path_finding(Guest* peep)
} }
PathfindLoggingDisable(); PathfindLoggingDisable();
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
return guest_path_find_park_entrance(peep, edges); return GuestPathFindParkEntranceLeaving(peep, edges);
} }
if (peep->GuestHeadingToRideId == RIDE_ID_NULL) if (peep->GuestHeadingToRideId == RIDE_ID_NULL)