|
|
@ -43,7 +43,7 @@ static bool _pathFindDebug = false;
|
|
|
|
static utf8 _pathFindDebugPeepName[256];
|
|
|
|
static utf8 _pathFindDebugPeepName[256];
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
|
|
|
|
|
|
|
|
static int32_t guest_surface_path_finding(Peep* peep);
|
|
|
|
static int32_t guest_surface_path_finding(Peep& peep);
|
|
|
|
|
|
|
|
|
|
|
|
/* A junction history for the peep pathfinding heuristic search
|
|
|
|
/* A junction history for the peep pathfinding heuristic search
|
|
|
|
* The magic number 16 is the largest value returned by
|
|
|
|
* The magic number 16 is the largest value returned by
|
|
|
@ -124,10 +124,10 @@ static int32_t path_get_permitted_edges(PathElement* pathElement)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x0069524E
|
|
|
|
* rct2: 0x0069524E
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int32_t peep_move_one_tile(Direction direction, Peep* peep)
|
|
|
|
static int32_t peep_move_one_tile(Direction direction, Peep& peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
assert(direction_valid(direction));
|
|
|
|
assert(direction_valid(direction));
|
|
|
|
auto newTile = CoordsXY{ CoordsXY{ peep->NextLoc } + CoordsDirectionDelta[direction] }.ToTileCentre();
|
|
|
|
auto newTile = CoordsXY{ CoordsXY{ peep.NextLoc } + CoordsDirectionDelta[direction] }.ToTileCentre();
|
|
|
|
|
|
|
|
|
|
|
|
if (newTile.x >= MAXIMUM_MAP_SIZE_BIG || newTile.y >= MAXIMUM_MAP_SIZE_BIG)
|
|
|
|
if (newTile.x >= MAXIMUM_MAP_SIZE_BIG || newTile.y >= MAXIMUM_MAP_SIZE_BIG)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -135,8 +135,8 @@ static int32_t peep_move_one_tile(Direction direction, Peep* peep)
|
|
|
|
return guest_surface_path_finding(peep);
|
|
|
|
return guest_surface_path_finding(peep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
peep->PeepDirection = direction;
|
|
|
|
peep.PeepDirection = direction;
|
|
|
|
if (peep->State != PeepState::Queuing)
|
|
|
|
if (peep.State != PeepState::Queuing)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// When peeps are walking along a path, we would like them to be spread out across the width of the path,
|
|
|
|
// When peeps are walking along a path, we would like them to be spread out across the width of the path,
|
|
|
|
// instead of all walking along the exact centre line of the path.
|
|
|
|
// instead of all walking along the exact centre line of the path.
|
|
|
@ -159,19 +159,19 @@ static int32_t peep_move_one_tile(Direction direction, Peep* peep)
|
|
|
|
if (direction == 0 || direction == 2)
|
|
|
|
if (direction == 0 || direction == 2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Peep is moving along X, so apply the offset to the X position of the destination and clamp their current Y
|
|
|
|
// Peep is moving along X, so apply the offset to the X position of the destination and clamp their current Y
|
|
|
|
const int32_t centreLine = (peep->y & 0xFFE0) + COORDS_XY_HALF_TILE;
|
|
|
|
const int32_t centreLine = (peep.y & 0xFFE0) + COORDS_XY_HALF_TILE;
|
|
|
|
newTile.x += offset;
|
|
|
|
newTile.x += offset;
|
|
|
|
newTile.y = std::clamp<int32_t>(peep->y, centreLine - 3, centreLine + 3);
|
|
|
|
newTile.y = std::clamp<int32_t>(peep.y, centreLine - 3, centreLine + 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Peep is moving along Y, so apply the offset to the Y position of the destination and clamp their current X
|
|
|
|
// Peep is moving along Y, so apply the offset to the Y position of the destination and clamp their current X
|
|
|
|
const int32_t centreLine = (peep->x & 0xFFE0) + COORDS_XY_HALF_TILE;
|
|
|
|
const int32_t centreLine = (peep.x & 0xFFE0) + COORDS_XY_HALF_TILE;
|
|
|
|
newTile.x = std::clamp<int32_t>(peep->x, centreLine - 3, centreLine + 3);
|
|
|
|
newTile.x = std::clamp<int32_t>(peep.x, centreLine - 3, centreLine + 3);
|
|
|
|
newTile.y += offset;
|
|
|
|
newTile.y += offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
peep->SetDestination(newTile, 2);
|
|
|
|
peep.SetDestination(newTile, 2);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -180,9 +180,9 @@ static int32_t peep_move_one_tile(Direction direction, Peep* peep)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x00694C41
|
|
|
|
* rct2: 0x00694C41
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int32_t guest_surface_path_finding(Peep* peep)
|
|
|
|
static int32_t guest_surface_path_finding(Peep& peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto pathPos = CoordsXYRangedZ{ peep->NextLoc, peep->NextLoc.z, peep->NextLoc.z + PATH_CLEARANCE };
|
|
|
|
auto pathPos = CoordsXYRangedZ{ peep.NextLoc, peep.NextLoc.z, peep.NextLoc.z + PATH_CLEARANCE };
|
|
|
|
Direction randDirection = scenario_rand() & 3;
|
|
|
|
Direction randDirection = scenario_rand() & 3;
|
|
|
|
|
|
|
|
|
|
|
|
if (!fence_in_the_way(pathPos, randDirection))
|
|
|
|
if (!fence_in_the_way(pathPos, randDirection))
|
|
|
@ -208,8 +208,8 @@ static int32_t guest_surface_path_finding(Peep* peep)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
randDirection &= 3;
|
|
|
|
randDirection &= 3;
|
|
|
|
|
|
|
|
|
|
|
|
pathPos.x = peep->NextLoc.x;
|
|
|
|
pathPos.x = peep.NextLoc.x;
|
|
|
|
pathPos.y = peep->NextLoc.y;
|
|
|
|
pathPos.y = peep.NextLoc.y;
|
|
|
|
if (!fence_in_the_way(pathPos, randDirection))
|
|
|
|
if (!fence_in_the_way(pathPos, randDirection))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pathPos.x += CoordsDirectionDelta[randDirection].x;
|
|
|
|
pathPos.x += CoordsDirectionDelta[randDirection].x;
|
|
|
@ -228,8 +228,8 @@ static int32_t guest_surface_path_finding(Peep* peep)
|
|
|
|
randDirection -= 2;
|
|
|
|
randDirection -= 2;
|
|
|
|
randDirection &= 3;
|
|
|
|
randDirection &= 3;
|
|
|
|
|
|
|
|
|
|
|
|
pathPos.x = peep->NextLoc.x;
|
|
|
|
pathPos.x = peep.NextLoc.x;
|
|
|
|
pathPos.y = peep->NextLoc.y;
|
|
|
|
pathPos.y = peep.NextLoc.y;
|
|
|
|
if (!fence_in_the_way(pathPos, randDirection))
|
|
|
|
if (!fence_in_the_way(pathPos, randDirection))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pathPos.x += CoordsDirectionDelta[randDirection].x;
|
|
|
|
pathPos.x += CoordsDirectionDelta[randDirection].x;
|
|
|
@ -289,7 +289,7 @@ static uint8_t footpath_element_next_in_direction(TileCoordsXYZ loc, PathElement
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
if (nextTileElement->GetType() != TileElementType::Path)
|
|
|
|
if (nextTileElement->GetType() != TileElementType::Path)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
if (!IsValidPathZAndDirection(nextTileElement, loc.z, chosenDirection))
|
|
|
|
if (!GuestPathfinding::IsValidPathZAndDirection(nextTileElement, loc.z, chosenDirection))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
if (nextTileElement->AsPath()->IsWide())
|
|
|
|
if (nextTileElement->AsPath()->IsWide())
|
|
|
|
return PATH_SEARCH_WIDE;
|
|
|
|
return PATH_SEARCH_WIDE;
|
|
|
@ -382,7 +382,7 @@ static uint8_t footpath_element_dest_in_dir(TileCoordsXYZ loc, Direction chosenD
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case TileElementType::Path:
|
|
|
|
case TileElementType::Path:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!IsValidPathZAndDirection(tileElement, loc.z, chosenDirection))
|
|
|
|
if (!GuestPathfinding::IsValidPathZAndDirection(tileElement, loc.z, chosenDirection))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
if (tileElement->AsPath()->IsWide())
|
|
|
|
if (tileElement->AsPath()->IsWide())
|
|
|
|
return PATH_SEARCH_WIDE;
|
|
|
|
return PATH_SEARCH_WIDE;
|
|
|
@ -460,14 +460,14 @@ static uint8_t footpath_element_destination_in_direction(
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x00695225
|
|
|
|
* rct2: 0x00695225
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int32_t guest_path_find_aimless(Peep* peep, uint8_t edges)
|
|
|
|
static int32_t guest_path_find_aimless(Peep& peep, uint8_t edges)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (scenario_rand() & 1)
|
|
|
|
if (scenario_rand() & 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// If possible go straight
|
|
|
|
// If possible go straight
|
|
|
|
if (edges & (1 << peep->PeepDirection))
|
|
|
|
if (edges & (1 << peep.PeepDirection))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return peep_move_one_tile(peep->PeepDirection, peep);
|
|
|
|
return peep_move_one_tile(peep.PeepDirection, peep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -486,21 +486,21 @@ static int32_t guest_path_find_aimless(Peep* peep, uint8_t edges)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x0069A60A
|
|
|
|
* rct2: 0x0069A60A
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static uint8_t peep_pathfind_get_max_number_junctions(Peep* peep)
|
|
|
|
static uint8_t peep_pathfind_get_max_number_junctions(Peep& peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (peep->Is<Staff>())
|
|
|
|
if (peep.Is<Staff>())
|
|
|
|
return 8;
|
|
|
|
return 8;
|
|
|
|
|
|
|
|
|
|
|
|
// PEEP_FLAGS_2? It's cleared here but not set anywhere!
|
|
|
|
// PEEP_FLAGS_2? It's cleared here but not set anywhere!
|
|
|
|
if ((peep->PeepFlags & PEEP_FLAGS_2))
|
|
|
|
if ((peep.PeepFlags & PEEP_FLAGS_2))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ((scenario_rand() & 0xFFFF) <= 7281)
|
|
|
|
if ((scenario_rand() & 0xFFFF) <= 7281)
|
|
|
|
peep->PeepFlags &= ~PEEP_FLAGS_2;
|
|
|
|
peep.PeepFlags &= ~PEEP_FLAGS_2;
|
|
|
|
|
|
|
|
|
|
|
|
return 8;
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto* guest = peep->As<Guest>();
|
|
|
|
auto* guest = peep.As<Guest>();
|
|
|
|
if (guest == nullptr)
|
|
|
|
if (guest == nullptr)
|
|
|
|
return 8;
|
|
|
|
return 8;
|
|
|
|
|
|
|
|
|
|
|
@ -687,7 +687,7 @@ static constexpr const char* pathSearchToString(uint8_t pathFindSearchResult)
|
|
|
|
* rct2: 0x0069A997
|
|
|
|
* rct2: 0x0069A997
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static void peep_pathfind_heuristic_search(
|
|
|
|
static void peep_pathfind_heuristic_search(
|
|
|
|
TileCoordsXYZ loc, Peep* peep, TileElement* currentTileElement, bool inPatrolArea, uint8_t counter, uint16_t* endScore,
|
|
|
|
TileCoordsXYZ loc, Peep& peep, TileElement* currentTileElement, bool inPatrolArea, uint8_t counter, uint16_t* endScore,
|
|
|
|
Direction test_edge, uint8_t* endJunctions, TileCoordsXYZ junctionList[16], uint8_t directionList[16],
|
|
|
|
Direction test_edge, uint8_t* endJunctions, TileCoordsXYZ junctionList[16], uint8_t directionList[16],
|
|
|
|
TileCoordsXYZ* endXYZ, uint8_t* endSteps)
|
|
|
|
TileCoordsXYZ* endXYZ, uint8_t* endSteps)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -696,7 +696,7 @@ static void peep_pathfind_heuristic_search(
|
|
|
|
bool currentElementIsWide = currentTileElement->AsPath()->IsWide();
|
|
|
|
bool currentElementIsWide = currentTileElement->AsPath()->IsWide();
|
|
|
|
if (currentElementIsWide)
|
|
|
|
if (currentElementIsWide)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const Staff* staff = peep->As<Staff>();
|
|
|
|
const Staff* staff = peep.As<Staff>();
|
|
|
|
if (staff != nullptr && staff->CanIgnoreWideFlag(loc.ToCoordsXYZ(), currentTileElement))
|
|
|
|
if (staff != nullptr && staff->CanIgnoreWideFlag(loc.ToCoordsXYZ(), currentTileElement))
|
|
|
|
currentElementIsWide = false;
|
|
|
|
currentElementIsWide = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -721,7 +721,7 @@ static void peep_pathfind_heuristic_search(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nextInPatrolArea = inPatrolArea;
|
|
|
|
bool nextInPatrolArea = inPatrolArea;
|
|
|
|
auto* staff = peep->As<Staff>();
|
|
|
|
auto* staff = peep.As<Staff>();
|
|
|
|
if (staff != nullptr && staff->IsMechanic())
|
|
|
|
if (staff != nullptr && staff->IsMechanic())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
nextInPatrolArea = staff->IsLocationInPatrol(loc.ToCoordsXY());
|
|
|
|
nextInPatrolArea = staff->IsLocationInPatrol(loc.ToCoordsXY());
|
|
|
@ -824,7 +824,7 @@ static void peep_pathfind_heuristic_search(
|
|
|
|
* queue path.
|
|
|
|
* queue path.
|
|
|
|
* Otherwise, peeps walk on path tiles to get to the goal. */
|
|
|
|
* Otherwise, peeps walk on path tiles to get to the goal. */
|
|
|
|
|
|
|
|
|
|
|
|
if (!IsValidPathZAndDirection(tileElement, loc.z, test_edge))
|
|
|
|
if (!GuestPathfinding::IsValidPathZAndDirection(tileElement, loc.z, test_edge))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// Path may be sloped, so set z to path base height.
|
|
|
|
// Path may be sloped, so set z to path base height.
|
|
|
@ -1075,14 +1075,14 @@ static void peep_pathfind_heuristic_search(
|
|
|
|
/* First check if going through the junction would be
|
|
|
|
/* First check if going through the junction would be
|
|
|
|
* a loop. If so, the current search path ends here.
|
|
|
|
* a loop. If so, the current search path ends here.
|
|
|
|
* Path finding loop detection can take advantage of both the
|
|
|
|
* Path finding loop detection can take advantage of both the
|
|
|
|
* peep->PathfindHistory - loops through remembered junctions
|
|
|
|
* peep.PathfindHistory - loops through remembered junctions
|
|
|
|
* the peep has already passed through getting to its
|
|
|
|
* the peep has already passed through getting to its
|
|
|
|
* current position while on the way to its current goal;
|
|
|
|
* current position while on the way to its current goal;
|
|
|
|
* _peepPathFindHistory - loops in the current search path. */
|
|
|
|
* _peepPathFindHistory - loops in the current search path. */
|
|
|
|
bool pathLoop = false;
|
|
|
|
bool pathLoop = false;
|
|
|
|
/* Check the peep->PathfindHistory to see if this junction has
|
|
|
|
/* Check the peep.PathfindHistory to see if this junction has
|
|
|
|
* already been visited by the peep while heading for this goal. */
|
|
|
|
* already been visited by the peep while heading for this goal. */
|
|
|
|
for (auto& pathfindHistory : peep->PathfindHistory)
|
|
|
|
for (auto& pathfindHistory : peep.PathfindHistory)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (pathfindHistory == loc)
|
|
|
|
if (pathfindHistory == loc)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1261,7 +1261,7 @@ static void peep_pathfind_heuristic_search(
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x0069A5F0
|
|
|
|
* rct2: 0x0069A5F0
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
Direction OriginalPathfinding::ChooseDirection(const TileCoordsXYZ& loc, Peep& peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PROFILED_FUNCTION();
|
|
|
|
PROFILED_FUNCTION();
|
|
|
|
|
|
|
|
|
|
|
@ -1270,9 +1270,9 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
|
|
|
|
|
|
|
|
/* The max number of tiles to check - a whole-search limit.
|
|
|
|
/* The max number of tiles to check - a whole-search limit.
|
|
|
|
* Mainly to limit the performance impact of the path finding. */
|
|
|
|
* Mainly to limit the performance impact of the path finding. */
|
|
|
|
int32_t maxTilesChecked = (peep->Is<Staff>()) ? 50000 : 15000;
|
|
|
|
int32_t maxTilesChecked = (peep.Is<Staff>()) ? 50000 : 15000;
|
|
|
|
// Used to allow walking through no entry banners
|
|
|
|
// Used to allow walking through no entry banners
|
|
|
|
_peepPathFindIsStaff = peep->Is<Staff>();
|
|
|
|
_peepPathFindIsStaff = peep.Is<Staff>();
|
|
|
|
|
|
|
|
|
|
|
|
TileCoordsXYZ goal = gPeepPathFindGoalPosition;
|
|
|
|
TileCoordsXYZ goal = gPeepPathFindGoalPosition;
|
|
|
|
|
|
|
|
|
|
|
@ -1322,7 +1322,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if this path element is a thin junction.
|
|
|
|
/* Check if this path element is a thin junction.
|
|
|
|
* Only 'thin' junctions are remembered in peep->PathfindHistory.
|
|
|
|
* Only 'thin' junctions are remembered in peep.PathfindHistory.
|
|
|
|
* NO attempt is made to merge the overlaid path elements and
|
|
|
|
* NO attempt is made to merge the overlaid path elements and
|
|
|
|
* check if the combination is 'thin'!
|
|
|
|
* check if the combination is 'thin'!
|
|
|
|
* The junction is considered 'thin' simply if any of the
|
|
|
|
* The junction is considered 'thin' simply if any of the
|
|
|
@ -1338,9 +1338,9 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
|
|
|
|
|
|
|
|
permitted_edges &= 0xF;
|
|
|
|
permitted_edges &= 0xF;
|
|
|
|
uint8_t edges = permitted_edges;
|
|
|
|
uint8_t edges = permitted_edges;
|
|
|
|
if (isThin && peep->PathfindGoal == goal)
|
|
|
|
if (isThin && peep.PathfindGoal == goal)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Use of peep->PathfindHistory[]:
|
|
|
|
/* Use of peep.PathfindHistory[]:
|
|
|
|
* When walking to a goal, the peep PathfindHistory stores
|
|
|
|
* When walking to a goal, the peep PathfindHistory stores
|
|
|
|
* the last 4 thin junctions that the peep walked through.
|
|
|
|
* the last 4 thin junctions that the peep walked through.
|
|
|
|
* For each of these 4 thin junctions the peep remembers
|
|
|
|
* For each of these 4 thin junctions the peep remembers
|
|
|
@ -1355,7 +1355,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
/* If the peep remembers walking through this junction
|
|
|
|
/* If the peep remembers walking through this junction
|
|
|
|
* previously while heading for its goal, retrieve the
|
|
|
|
* previously while heading for its goal, retrieve the
|
|
|
|
* directions it has not yet tried. */
|
|
|
|
* directions it has not yet tried. */
|
|
|
|
for (auto& pathfindHistory : peep->PathfindHistory)
|
|
|
|
for (auto& pathfindHistory : peep.PathfindHistory)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (pathfindHistory == loc)
|
|
|
|
if (pathfindHistory == loc)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1405,15 +1405,15 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
|
|
|
|
|
|
|
|
/* If this is a new goal for the peep. Store it and reset the peep's
|
|
|
|
/* If this is a new goal for the peep. Store it and reset the peep's
|
|
|
|
* PathfindHistory. */
|
|
|
|
* PathfindHistory. */
|
|
|
|
if (!direction_valid(peep->PathfindGoal.direction) || peep->PathfindGoal != goal)
|
|
|
|
if (!direction_valid(peep.PathfindGoal.direction) || peep.PathfindGoal != goal)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
peep->PathfindGoal = { goal, 0 };
|
|
|
|
peep.PathfindGoal = { goal, 0 };
|
|
|
|
|
|
|
|
|
|
|
|
// Clear pathfinding history
|
|
|
|
// Clear pathfinding history
|
|
|
|
TileCoordsXYZD nullPos;
|
|
|
|
TileCoordsXYZD nullPos;
|
|
|
|
nullPos.SetNull();
|
|
|
|
nullPos.SetNull();
|
|
|
|
|
|
|
|
|
|
|
|
std::fill(std::begin(peep->PathfindHistory), std::end(peep->PathfindHistory), nullPos);
|
|
|
|
std::fill(std::begin(peep.PathfindHistory), std::end(peep.PathfindHistory), nullPos);
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1504,13 +1504,13 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
uint8_t endDirectionList[16] = { 0 };
|
|
|
|
uint8_t endDirectionList[16] = { 0 };
|
|
|
|
|
|
|
|
|
|
|
|
bool inPatrolArea = false;
|
|
|
|
bool inPatrolArea = false;
|
|
|
|
auto* staff = peep->As<Staff>();
|
|
|
|
auto* staff = peep.As<Staff>();
|
|
|
|
if (staff != nullptr && staff->IsMechanic())
|
|
|
|
if (staff != nullptr && staff->IsMechanic())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Mechanics are the only staff type that
|
|
|
|
/* Mechanics are the only staff type that
|
|
|
|
* pathfind to a destination. Determine if the
|
|
|
|
* pathfind to a destination. Determine if the
|
|
|
|
* mechanic is in their patrol area. */
|
|
|
|
* mechanic is in their patrol area. */
|
|
|
|
inPatrolArea = staff->IsLocationInPatrol(peep->NextLoc);
|
|
|
|
inPatrolArea = staff->IsLocationInPatrol(peep.NextLoc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(DEBUG_LEVEL_2) && DEBUG_LEVEL_2
|
|
|
|
#if defined(DEBUG_LEVEL_2) && DEBUG_LEVEL_2
|
|
|
@ -1592,20 +1592,20 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (int32_t i = 0; i < 4; ++i)
|
|
|
|
for (int32_t i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (peep->PathfindHistory[i] == loc)
|
|
|
|
if (peep.PathfindHistory[i] == loc)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Peep remembers this junction, so remove the
|
|
|
|
/* Peep remembers this junction, so remove the
|
|
|
|
* chosen_edge from those left to try. */
|
|
|
|
* chosen_edge from those left to try. */
|
|
|
|
peep->PathfindHistory[i].direction &= ~(1 << chosen_edge);
|
|
|
|
peep.PathfindHistory[i].direction &= ~(1 << chosen_edge);
|
|
|
|
/* Also remove the edge through which the peep
|
|
|
|
/* Also remove the edge through which the peep
|
|
|
|
* entered the junction from those left to try. */
|
|
|
|
* entered the junction from those left to try. */
|
|
|
|
peep->PathfindHistory[i].direction &= ~(1 << direction_reverse(peep->PeepDirection));
|
|
|
|
peep.PathfindHistory[i].direction &= ~(1 << direction_reverse(peep.PeepDirection));
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_verbose(
|
|
|
|
log_verbose(
|
|
|
|
"Updating existing pf_history (in index: %d) for %d,%d,%d without entry edge %d & exit edge %d.", i,
|
|
|
|
"Updating existing pf_history (in index: %d) for %d,%d,%d without entry edge %d & exit edge %d.", i,
|
|
|
|
loc.x, loc.y, loc.z, direction_reverse(peep->PeepDirection), chosen_edge);
|
|
|
|
loc.x, loc.y, loc.z, direction_reverse(peep.PeepDirection), chosen_edge);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
return chosen_edge;
|
|
|
|
return chosen_edge;
|
|
|
@ -1614,20 +1614,20 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
|
|
|
|
|
|
|
|
|
|
|
/* Peep does not remember this junction, so forget a junction
|
|
|
|
/* Peep does not remember this junction, so forget a junction
|
|
|
|
* and remember this junction. */
|
|
|
|
* and remember this junction. */
|
|
|
|
int32_t i = peep->PathfindGoal.direction++;
|
|
|
|
int32_t i = peep.PathfindGoal.direction++;
|
|
|
|
peep->PathfindGoal.direction &= 3;
|
|
|
|
peep.PathfindGoal.direction &= 3;
|
|
|
|
peep->PathfindHistory[i] = { loc, permitted_edges };
|
|
|
|
peep.PathfindHistory[i] = { loc, permitted_edges };
|
|
|
|
/* Remove the chosen_edge from those left to try. */
|
|
|
|
/* Remove the chosen_edge from those left to try. */
|
|
|
|
peep->PathfindHistory[i].direction &= ~(1 << chosen_edge);
|
|
|
|
peep.PathfindHistory[i].direction &= ~(1 << chosen_edge);
|
|
|
|
/* Also remove the edge through which the peep
|
|
|
|
/* Also remove the edge through which the peep
|
|
|
|
* entered the junction from those left to try. */
|
|
|
|
* entered the junction from those left to try. */
|
|
|
|
peep->PathfindHistory[i].direction &= ~(1 << direction_reverse(peep->PeepDirection));
|
|
|
|
peep.PathfindHistory[i].direction &= ~(1 << direction_reverse(peep.PeepDirection));
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_verbose(
|
|
|
|
log_verbose(
|
|
|
|
"Storing new pf_history (in index: %d) for %d,%d,%d without entry edge %d & exit edge %d.", i, loc.x, loc.y,
|
|
|
|
"Storing new pf_history (in index: %d) for %d,%d,%d without entry edge %d & exit edge %d.", i, loc.x, loc.y,
|
|
|
|
loc.z, direction_reverse(peep->PeepDirection), chosen_edge);
|
|
|
|
loc.z, direction_reverse(peep.PeepDirection), chosen_edge);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1661,10 +1661,10 @@ static std::optional<CoordsXYZ> GetNearestParkEntrance(const CoordsXY& loc)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x006952C0
|
|
|
|
* rct2: 0x006952C0
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges)
|
|
|
|
int32_t OriginalPathfinding::GuestPathFindParkEntranceEntering(Peep& peep, uint8_t edges)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Send peeps to the nearest park entrance.
|
|
|
|
// Send peeps to the nearest park entrance.
|
|
|
|
auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc);
|
|
|
|
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.has_value())
|
|
|
|
if (!chosenEntrance.has_value())
|
|
|
@ -1674,7 +1674,7 @@ static int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges)
|
|
|
|
gPeepPathFindIgnoreForeignQueues = true;
|
|
|
|
gPeepPathFindIgnoreForeignQueues = true;
|
|
|
|
gPeepPathFindQueueRideIndex = RideId::GetNull();
|
|
|
|
gPeepPathFindQueueRideIndex = RideId::GetNull();
|
|
|
|
|
|
|
|
|
|
|
|
Direction chosenDirection = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep);
|
|
|
|
Direction chosenDirection = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep);
|
|
|
|
|
|
|
|
|
|
|
|
if (chosenDirection == INVALID_DIRECTION)
|
|
|
|
if (chosenDirection == INVALID_DIRECTION)
|
|
|
|
return guest_path_find_aimless(peep, edges);
|
|
|
|
return guest_path_find_aimless(peep, edges);
|
|
|
@ -1710,10 +1710,10 @@ static uint8_t get_nearest_peep_spawn_index(uint16_t x, uint16_t y)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x0069536C
|
|
|
|
* rct2: 0x0069536C
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges)
|
|
|
|
int32_t OriginalPathfinding::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);
|
|
|
|
|
|
|
|
|
|
|
|
// If no defined spawns were found, walk aimlessly.
|
|
|
|
// If no defined spawns were found, walk aimlessly.
|
|
|
|
if (chosenSpawn == 0xFF)
|
|
|
|
if (chosenSpawn == 0xFF)
|
|
|
@ -1723,14 +1723,14 @@ static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges)
|
|
|
|
Direction direction = peepSpawnLoc.direction;
|
|
|
|
Direction direction = peepSpawnLoc.direction;
|
|
|
|
|
|
|
|
|
|
|
|
gPeepPathFindGoalPosition = TileCoordsXYZ(peepSpawnLoc);
|
|
|
|
gPeepPathFindGoalPosition = TileCoordsXYZ(peepSpawnLoc);
|
|
|
|
if (peepSpawnLoc.x == peep->NextLoc.x && peepSpawnLoc.y == peep->NextLoc.y)
|
|
|
|
if (peepSpawnLoc.x == peep.NextLoc.x && peepSpawnLoc.y == peep.NextLoc.y)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return peep_move_one_tile(direction, peep);
|
|
|
|
return peep_move_one_tile(direction, peep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gPeepPathFindIgnoreForeignQueues = true;
|
|
|
|
gPeepPathFindIgnoreForeignQueues = true;
|
|
|
|
gPeepPathFindQueueRideIndex = RideId::GetNull();
|
|
|
|
gPeepPathFindQueueRideIndex = RideId::GetNull();
|
|
|
|
direction = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep);
|
|
|
|
direction = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep);
|
|
|
|
if (direction == INVALID_DIRECTION)
|
|
|
|
if (direction == INVALID_DIRECTION)
|
|
|
|
return guest_path_find_aimless(peep, edges);
|
|
|
|
return guest_path_find_aimless(peep, edges);
|
|
|
|
|
|
|
|
|
|
|
@ -1741,28 +1741,28 @@ static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x00695161
|
|
|
|
* rct2: 0x00695161
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges)
|
|
|
|
int32_t OriginalPathfinding::GuestPathFindParkEntranceLeaving(Peep& peep, uint8_t edges)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
TileCoordsXYZ entranceGoal{};
|
|
|
|
TileCoordsXYZ entranceGoal{};
|
|
|
|
if (peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)
|
|
|
|
if (peep.PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
entranceGoal = peep->PathfindGoal;
|
|
|
|
entranceGoal = peep.PathfindGoal;
|
|
|
|
auto* entranceElement = map_get_park_entrance_element_at(entranceGoal.ToCoordsXYZ(), false);
|
|
|
|
auto* entranceElement = map_get_park_entrance_element_at(entranceGoal.ToCoordsXYZ(), false);
|
|
|
|
// If entrance no longer exists, choose a new one
|
|
|
|
// If entrance no longer exists, choose a new one
|
|
|
|
if (entranceElement == nullptr)
|
|
|
|
if (entranceElement == nullptr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
peep->PeepFlags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN);
|
|
|
|
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 = GetNearestParkEntrance(peep->NextLoc);
|
|
|
|
auto chosenEntrance = GetNearestParkEntrance(peep.NextLoc);
|
|
|
|
|
|
|
|
|
|
|
|
if (!chosenEntrance.has_value())
|
|
|
|
if (!chosenEntrance.has_value())
|
|
|
|
return guest_path_find_aimless(peep, edges);
|
|
|
|
return guest_path_find_aimless(peep, edges);
|
|
|
|
|
|
|
|
|
|
|
|
peep->PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN;
|
|
|
|
peep.PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN;
|
|
|
|
entranceGoal = TileCoordsXYZ(*chosenEntrance);
|
|
|
|
entranceGoal = TileCoordsXYZ(*chosenEntrance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1774,7 +1774,7 @@ static int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges)
|
|
|
|
PathfindLoggingEnable(peep);
|
|
|
|
PathfindLoggingEnable(peep);
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
|
|
|
|
|
|
|
|
Direction chosenDirection = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep);
|
|
|
|
Direction chosenDirection = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep);
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
@ -1942,9 +1942,9 @@ static void get_ride_queue_end(TileCoordsXYZ& loc)
|
|
|
|
* appropriate.
|
|
|
|
* appropriate.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static StationIndex guest_pathfinding_select_random_station(
|
|
|
|
static StationIndex guest_pathfinding_select_random_station(
|
|
|
|
const Guest* guest, int32_t numEntranceStations, BitSet<OpenRCT2::Limits::MaxStationsPerRide>& entranceStations)
|
|
|
|
const Guest& guest, int32_t numEntranceStations, BitSet<OpenRCT2::Limits::MaxStationsPerRide>& entranceStations)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int32_t select = guest->GuestNumRides % numEntranceStations;
|
|
|
|
int32_t select = guest.GuestNumRides % numEntranceStations;
|
|
|
|
while (select > 0)
|
|
|
|
while (select > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (StationIndex::UnderlyingType i = 0; i < OpenRCT2::Limits::MaxStationsPerRide; i++)
|
|
|
|
for (StationIndex::UnderlyingType i = 0; i < OpenRCT2::Limits::MaxStationsPerRide; i++)
|
|
|
@ -1971,22 +1971,22 @@ static StationIndex guest_pathfinding_select_random_station(
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* rct2: 0x00694C35
|
|
|
|
* rct2: 0x00694C35
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int32_t guest_path_finding(Guest* peep)
|
|
|
|
int32_t OriginalPathfinding::CalculateNextDestination(Guest& peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
PathfindLoggingEnable(peep);
|
|
|
|
PathfindLoggingEnable(peep);
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info("Starting guest_path_finding for %s", _pathFindDebugPeepName);
|
|
|
|
log_info("Starting CalculateNextDestination for %s", _pathFindDebugPeepName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
|
|
|
|
|
|
|
|
if (peep->GetNextIsSurface())
|
|
|
|
if (peep.GetNextIsSurface())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return guest_surface_path_finding(peep);
|
|
|
|
return guest_surface_path_finding(peep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TileCoordsXYZ loc{ peep->NextLoc };
|
|
|
|
TileCoordsXYZ loc{ peep.NextLoc };
|
|
|
|
|
|
|
|
|
|
|
|
auto* pathElement = map_get_path_element_at(loc);
|
|
|
|
auto* pathElement = map_get_path_element_at(loc);
|
|
|
|
if (pathElement == nullptr)
|
|
|
|
if (pathElement == nullptr)
|
|
|
@ -2002,7 +2002,7 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
return guest_surface_path_finding(peep);
|
|
|
|
return guest_surface_path_finding(peep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!peep->OutsideOfPark && peep->HeadingForRideOrParkExit())
|
|
|
|
if (!peep.OutsideOfPark && peep.HeadingForRideOrParkExit())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* If this tileElement is adjacent to any non-wide paths,
|
|
|
|
/* If this tileElement is adjacent to any non-wide paths,
|
|
|
|
* remove all of the edges to wide paths. */
|
|
|
|
* remove all of the edges to wide paths. */
|
|
|
@ -2024,14 +2024,14 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
edges = adjustedEdges;
|
|
|
|
edges = adjustedEdges;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32_t direction = direction_reverse(peep->PeepDirection);
|
|
|
|
int32_t direction = direction_reverse(peep.PeepDirection);
|
|
|
|
// Check if in a dead end (i.e. only edge is where the peep came from)
|
|
|
|
// Check if in a dead end (i.e. only edge is where the peep came from)
|
|
|
|
if (!(edges & ~(1 << direction)))
|
|
|
|
if (!(edges & ~(1 << direction)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// In a dead end. Check if peep is lost, etc.
|
|
|
|
// In a dead end. Check if peep is lost, etc.
|
|
|
|
peep->CheckIfLost();
|
|
|
|
peep.CheckIfLost();
|
|
|
|
peep->CheckCantFindRide();
|
|
|
|
peep.CheckCantFindRide();
|
|
|
|
peep->CheckCantFindExit();
|
|
|
|
peep.CheckCantFindExit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -2048,7 +2048,7 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info(
|
|
|
|
log_info(
|
|
|
|
"Completed guest_path_finding for %s - taking only direction available: %d.", _pathFindDebugPeepName,
|
|
|
|
"Completed CalculateNextDestination for %s - taking only direction available: %d.", _pathFindDebugPeepName,
|
|
|
|
direction);
|
|
|
|
direction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
@ -2060,16 +2060,16 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
|
|
|
|
|
|
|
|
// Peep is outside the park.
|
|
|
|
// Peep is outside the park.
|
|
|
|
// loc_694F19:
|
|
|
|
// loc_694F19:
|
|
|
|
if (peep->OutsideOfPark)
|
|
|
|
if (peep.OutsideOfPark)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info("Completed guest_path_finding for %s - peep is outside the park.", _pathFindDebugPeepName);
|
|
|
|
log_info("Completed CalculateNextDestination for %s - peep is outside the park.", _pathFindDebugPeepName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
switch (peep->State)
|
|
|
|
switch (peep.State)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case PeepState::EnteringPark:
|
|
|
|
case PeepState::EnteringPark:
|
|
|
|
return GuestPathFindParkEntranceEntering(peep, edges);
|
|
|
|
return GuestPathFindParkEntranceEntering(peep, edges);
|
|
|
@ -2086,7 +2086,7 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
* In principle, peeps with food are not paying as much attention to
|
|
|
|
* In principle, peeps with food are not paying as much attention to
|
|
|
|
* where they are going and are consequently more like to walk up
|
|
|
|
* where they are going and are consequently more like to walk up
|
|
|
|
* dead end paths, paths to ride exits, etc. */
|
|
|
|
* dead end paths, paths to ride exits, etc. */
|
|
|
|
if (!peep->HasFoodOrDrink() && (scenario_rand() & 0xFFFF) >= 2184)
|
|
|
|
if (!peep.HasFoodOrDrink() && (scenario_rand() & 0xFFFF) >= 2184)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint8_t adjustedEdges = edges;
|
|
|
|
uint8_t adjustedEdges = edges;
|
|
|
|
for (Direction chosenDirection : ALL_DIRECTIONS)
|
|
|
|
for (Direction chosenDirection : ALL_DIRECTIONS)
|
|
|
@ -2113,41 +2113,41 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
/* If there are still multiple directions to choose from,
|
|
|
|
/* If there are still multiple directions to choose from,
|
|
|
|
* peeps with maps will randomly read the map: probability of doing so
|
|
|
|
* peeps with maps will randomly read the map: probability of doing so
|
|
|
|
* is much higher when heading for a ride or the park exit. */
|
|
|
|
* is much higher when heading for a ride or the park exit. */
|
|
|
|
if (peep->HasItem(ShopItem::Map))
|
|
|
|
if (peep.HasItem(ShopItem::Map))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// If at least 2 directions consult map
|
|
|
|
// If at least 2 directions consult map
|
|
|
|
if (bitcount(edges) >= 2)
|
|
|
|
if (bitcount(edges) >= 2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint16_t probability = 1638;
|
|
|
|
uint16_t probability = 1638;
|
|
|
|
if (peep->HeadingForRideOrParkExit())
|
|
|
|
if (peep.HeadingForRideOrParkExit())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
probability = 9362;
|
|
|
|
probability = 9362;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((scenario_rand() & 0xFFFF) < probability)
|
|
|
|
if ((scenario_rand() & 0xFFFF) < probability)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
peep->ReadMap();
|
|
|
|
peep.ReadMap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (peep->PeepFlags & PEEP_FLAGS_LEAVING_PARK)
|
|
|
|
if (peep.PeepFlags & PEEP_FLAGS_LEAVING_PARK)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info("Completed guest_path_finding for %s - peep is leaving the park.", _pathFindDebugPeepName);
|
|
|
|
log_info("Completed CalculateNextDestination for %s - peep is leaving the park.", _pathFindDebugPeepName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
return GuestPathFindParkEntranceLeaving(peep, edges);
|
|
|
|
return GuestPathFindParkEntranceLeaving(peep, edges);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (peep->GuestHeadingToRideId.IsNull())
|
|
|
|
if (peep.GuestHeadingToRideId.IsNull())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info("Completed guest_path_finding for %s - peep is aimless.", _pathFindDebugPeepName);
|
|
|
|
log_info("Completed CalculateNextDestination for %s - peep is aimless.", _pathFindDebugPeepName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
@ -2155,7 +2155,7 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Peep is heading for a ride.
|
|
|
|
// Peep is heading for a ride.
|
|
|
|
RideId rideIndex = peep->GuestHeadingToRideId;
|
|
|
|
RideId rideIndex = peep.GuestHeadingToRideId;
|
|
|
|
auto ride = get_ride(rideIndex);
|
|
|
|
auto ride = get_ride(rideIndex);
|
|
|
|
if (ride == nullptr || ride->status != RideStatus::Open)
|
|
|
|
if (ride == nullptr || ride->status != RideStatus::Open)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -2163,7 +2163,8 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info(
|
|
|
|
log_info(
|
|
|
|
"Completed guest_path_finding for %s - peep is heading to closed ride == aimless.", _pathFindDebugPeepName);
|
|
|
|
"Completed CalculateNextDestination for %s - peep is heading to closed ride == aimless.",
|
|
|
|
|
|
|
|
_pathFindDebugPeepName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
@ -2194,7 +2195,7 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
entranceStations[stationIndex.ToUnderlying()] = true;
|
|
|
|
entranceStations[stationIndex.ToUnderlying()] = true;
|
|
|
|
|
|
|
|
|
|
|
|
TileCoordsXYZD entranceLocation = station.Entrance;
|
|
|
|
TileCoordsXYZD entranceLocation = station.Entrance;
|
|
|
|
auto score = CalculateHeuristicPathingScore(entranceLocation, TileCoordsXYZ{ peep->NextLoc });
|
|
|
|
auto score = CalculateHeuristicPathingScore(entranceLocation, TileCoordsXYZ{ peep.NextLoc });
|
|
|
|
if (score < bestScore)
|
|
|
|
if (score < bestScore)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bestScore = score;
|
|
|
|
bestScore = score;
|
|
|
@ -2234,22 +2235,23 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
gPeepPathFindGoalPosition = loc;
|
|
|
|
gPeepPathFindGoalPosition = loc;
|
|
|
|
gPeepPathFindIgnoreForeignQueues = true;
|
|
|
|
gPeepPathFindIgnoreForeignQueues = true;
|
|
|
|
|
|
|
|
|
|
|
|
direction = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep);
|
|
|
|
direction = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep);
|
|
|
|
|
|
|
|
|
|
|
|
if (direction == INVALID_DIRECTION)
|
|
|
|
if (direction == INVALID_DIRECTION)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Heuristic search failed for all directions.
|
|
|
|
/* Heuristic search failed for all directions.
|
|
|
|
* Reset the PathfindGoal - this means that the PathfindHistory
|
|
|
|
* Reset the PathfindGoal - this means that the PathfindHistory
|
|
|
|
* will be reset in the next call to peep_pathfind_choose_direction().
|
|
|
|
* will be reset in the next call to ChooseDirection().
|
|
|
|
* This lets the heuristic search "try again" in case the player has
|
|
|
|
* This lets the heuristic search "try again" in case the player has
|
|
|
|
* edited the path layout or the mechanic was already stuck in the
|
|
|
|
* edited the path layout or the mechanic was already stuck in the
|
|
|
|
* save game (e.g. with a worse version of the pathfinding). */
|
|
|
|
* save game (e.g. with a worse version of the pathfinding). */
|
|
|
|
peep->ResetPathfindGoal();
|
|
|
|
peep.ResetPathfindGoal();
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info("Completed guest_path_finding for %s - failed to choose a direction == aimless.", _pathFindDebugPeepName);
|
|
|
|
log_info(
|
|
|
|
|
|
|
|
"Completed CalculateNextDestination for %s - failed to choose a direction == aimless.", _pathFindDebugPeepName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
@ -2259,14 +2261,14 @@ int32_t guest_path_finding(Guest* peep)
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
if (_pathFindDebug)
|
|
|
|
if (_pathFindDebug)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_info("Completed guest_path_finding for %s - direction chosen: %d.", _pathFindDebugPeepName, direction);
|
|
|
|
log_info("Completed CalculateNextDestination for %s - direction chosen: %d.", _pathFindDebugPeepName, direction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
PathfindLoggingDisable();
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
return peep_move_one_tile(direction, peep);
|
|
|
|
return peep_move_one_tile(direction, peep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection)
|
|
|
|
bool GuestPathfinding::IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (tileElement->AsPath()->IsSloped())
|
|
|
|
if (tileElement->AsPath()->IsSloped())
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -2311,18 +2313,18 @@ void Peep::ResetPathfindGoal()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
|
|
|
void PathfindLoggingEnable([[maybe_unused]] Peep* peep)
|
|
|
|
void PathfindLoggingEnable([[maybe_unused]] Peep& peep)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
# if defined(PATHFIND_DEBUG) && PATHFIND_DEBUG
|
|
|
|
# if defined(PATHFIND_DEBUG) && PATHFIND_DEBUG
|
|
|
|
/* Determine if the pathfinding debugging is wanted for this peep. */
|
|
|
|
/* Determine if the pathfinding debugging is wanted for this peep. */
|
|
|
|
format_string(gPathFindDebugPeepName, sizeof(gPathFindDebugPeepName), peep->name_string_idx, &(peep->Id));
|
|
|
|
format_string(gPathFindDebugPeepName, sizeof(gPathFindDebugPeepName), peep.name_string_idx, &(peep.Id));
|
|
|
|
|
|
|
|
|
|
|
|
/* For guests, use the existing PEEP_FLAGS_TRACKING flag to
|
|
|
|
/* For guests, use the existing PEEP_FLAGS_TRACKING flag to
|
|
|
|
* determine for which guest(s) the pathfinding debugging will
|
|
|
|
* determine for which guest(s) the pathfinding debugging will
|
|
|
|
* be output for. */
|
|
|
|
* be output for. */
|
|
|
|
if (peep->type == PEEP_TYPE_GUEST)
|
|
|
|
if (peep.type == PEEP_TYPE_GUEST)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
gPathFindDebug = peep->PeepFlags & PEEP_FLAGS_TRACKING;
|
|
|
|
gPathFindDebug = peep.PeepFlags & PEEP_FLAGS_TRACKING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* For staff, there is no tracking button (any other similar
|
|
|
|
/* For staff, there is no tracking button (any other similar
|
|
|
|
* suitable existing mechanism?), so fall back to a crude
|
|
|
|
* suitable existing mechanism?), so fall back to a crude
|
|
|
|