1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +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_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_SHA1 "1EB460BB3C71BD21CCBE778BEF1E8CD593241A18")
set(REPLAYS_SHA1 "18BFAD02A453CE0D5926C13A856546ED825AD0F1")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests")

View File

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

View File

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

View File

@@ -40,7 +40,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "4"
#define NETWORK_STREAM_VERSION "5"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
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
* @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;
uint8_t i = 0;
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)
{
nearestDist = dist;
chosenEntrance = i;
chosenEntrance = parkEntrance;
}
i++;
}
return chosenEntrance;
}
@@ -1653,16 +1651,16 @@ static uint8_t get_nearest_park_entrance_index(uint16_t x, uint16_t y)
*
* 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.
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 (chosenEntrance == 0xFF)
if (!chosenEntrance.has_value())
return guest_path_find_aimless(peep, edges);
gPeepPathFindGoalPosition = TileCoordsXYZ(gParkEntrances[chosenEntrance]);
gPeepPathFindGoalPosition = TileCoordsXYZ(chosenEntrance.value());
gPeepPathFindIgnoreForeignQueues = true;
gPeepPathFindQueueRideIndex = RIDE_ID_NULL;
@@ -1702,7 +1700,7 @@ static uint8_t get_nearest_peep_spawn_index(uint16_t x, uint16_t y)
*
* 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.
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
*/
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
if ((peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN) && peep->ChosenParkEntrance.ToUnderlying() >= gParkEntrances.size())
TileCoordsXYZ entranceGoal{};
if (peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)
{
peep->ChosenParkEntrance = ParkEntranceIndex::GetNull();
peep->PeepFlags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN);
entranceGoal = peep->PathfindGoal;
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))
{
auto chosenEntrance = ParkEntranceIndex::GetNull();
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++;
}
auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc);
if (chosenEntrance.IsNull())
if (!chosenEntrance.has_value())
return guest_path_find_aimless(peep, edges);
peep->ChosenParkEntrance = chosenEntrance;
peep->PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN;
entranceGoal = TileCoordsXYZ(*chosenEntrance);
}
const auto& entrance = gParkEntrances[peep->ChosenParkEntrance.ToUnderlying()];
gPeepPathFindGoalPosition = TileCoordsXYZ(entrance);
gPeepPathFindGoalPosition = entranceGoal;
gPeepPathFindIgnoreForeignQueues = true;
gPeepPathFindQueueRideIndex = RIDE_ID_NULL;
@@ -2073,9 +2062,9 @@ int32_t guest_path_finding(Guest* peep)
switch (peep->State)
{
case PeepState::EnteringPark:
return guest_path_find_entering_park(peep, edges);
return GuestPathFindParkEntranceEntering(peep, edges);
case PeepState::LeavingPark:
return guest_path_find_leaving_park(peep, edges);
return GuestPathFindPeepSpawn(peep, edges);
default:
return guest_path_find_aimless(peep, edges);
}
@@ -2140,7 +2129,7 @@ int32_t guest_path_finding(Guest* peep)
}
PathfindLoggingDisable();
#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)