1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Part of pathfinding rework

This commit is contained in:
LordOfLunacy
2022-05-13 19:18:46 -04:00
parent 07520ce0ba
commit 45013a90cc
7 changed files with 59 additions and 26 deletions

View File

@@ -27,6 +27,7 @@
#include "localisation/Localisation.h"
#include "management/NewsItem.h"
#include "network/network.h"
#include "./peep/GuestPathfinding.h"
#include "platform/Platform.h"
#include "profiling/Profiling.h"
#include "ride/Vehicle.h"
@@ -88,6 +89,9 @@ void GameState::InitAll(const TileCoordsXY& mapSize)
CheatsReset();
ClearRestrictedScenery();
// TODO: find a better place for this
gGuestPathfinder = new OriginalPathfinding();
#ifdef ENABLE_SCRIPTING
auto& scriptEngine = GetContext()->GetScriptEngine();
scriptEngine.ClearParkStorage();

View File

@@ -81,6 +81,7 @@ static void* _crowdSoundChannel = nullptr;
static void peep_128_tick_update(Peep* peep, int32_t index);
static void peep_release_balloon(Guest* peep, int16_t spawn_height);
static PeepActionSpriteType PeepSpecialSpriteToSpriteTypeMap[] = {
PeepActionSpriteType::None,
PeepActionSpriteType::HoldMat,
@@ -2357,7 +2358,7 @@ void Peep::PerformNextAction(uint8_t& pathing_result, TileElement*& tile_result)
if (guest != nullptr)
{
result = guest_path_finding(guest);
result = gGuestPathfinder->guest_path_finding(guest);
}
else
{

View File

@@ -399,7 +399,7 @@ public: // Peep
bool IsActionInterruptable() const;
// Reset the peep's stored goal, which means they will forget any stored pathfinding history
// on the next peep_pathfind_choose_direction call.
// on the next GuestPathfinding::peep_pathfind_choose_direction call.
void ResetPathfindGoal();
void SetDestination(const CoordsXY& coords);

View File

@@ -66,6 +66,8 @@ colour_t gStaffHandymanColour;
colour_t gStaffMechanicColour;
colour_t gStaffSecurityColour;
GuestPathfinding* gGuestPathfinder;
// Maximum manhattan distance that litter can be for a handyman to seek to it
const uint16_t MAX_LITTER_DISTANCE = 3 * COORDS_XY_STEP;
@@ -181,7 +183,7 @@ bool Staff::CanIgnoreWideFlag(const CoordsXYZ& staffPos, TileElement* path) cons
}
/* test_element is a path */
if (!IsValidPathZAndDirection(test_element, adjacPos.z / COORDS_Z_STEP, adjac_dir))
if (!GuestPathfinding::IsValidPathZAndDirection(test_element, adjacPos.z / COORDS_Z_STEP, adjac_dir))
continue;
/* test_element is a connected path */
@@ -722,7 +724,7 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat
PathfindLoggingEnable(this);
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
Direction pathfindDirection = peep_pathfind_choose_direction(TileCoordsXYZ{ NextLoc }, this);
Direction pathfindDirection = gGuestPathfinder->peep_pathfind_choose_direction(TileCoordsXYZ{ NextLoc }, this);
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
PathfindLoggingDisable();
@@ -732,7 +734,7 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat
{
/* Heuristic search failed for all directions.
* 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 GuestPathfinding::peep_pathfind_choose_direction().
* This lets the heuristic search "try again" in case the player has
* edited the path layout or the mechanic was already stuck in the
* save game (e.g. with a worse version of the pathfinding). */

View File

@@ -289,7 +289,7 @@ static uint8_t footpath_element_next_in_direction(TileCoordsXYZ loc, PathElement
continue;
if (nextTileElement->GetType() != TileElementType::Path)
continue;
if (!IsValidPathZAndDirection(nextTileElement, loc.z, chosenDirection))
if (!GuestPathfinding::IsValidPathZAndDirection(nextTileElement, loc.z, chosenDirection))
continue;
if (nextTileElement->AsPath()->IsWide())
return PATH_SEARCH_WIDE;
@@ -382,7 +382,7 @@ static uint8_t footpath_element_dest_in_dir(TileCoordsXYZ loc, Direction chosenD
break;
case TileElementType::Path:
{
if (!IsValidPathZAndDirection(tileElement, loc.z, chosenDirection))
if (!GuestPathfinding::IsValidPathZAndDirection(tileElement, loc.z, chosenDirection))
continue;
if (tileElement->AsPath()->IsWide())
return PATH_SEARCH_WIDE;
@@ -824,7 +824,7 @@ static void peep_pathfind_heuristic_search(
* queue path.
* 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;
// Path may be sloped, so set z to path base height.
@@ -1261,7 +1261,7 @@ static void peep_pathfind_heuristic_search(
*
* rct2: 0x0069A5F0
*/
Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
{
PROFILED_FUNCTION();
@@ -1661,7 +1661,7 @@ static std::optional<CoordsXYZ> GetNearestParkEntrance(const CoordsXY& loc)
*
* 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.
auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc);
@@ -1710,7 +1710,7 @@ static uint8_t get_nearest_peep_spawn_index(uint16_t x, uint16_t y)
*
* 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.
uint8_t chosenSpawn = get_nearest_peep_spawn_index(peep->NextLoc.x, peep->NextLoc.y);
@@ -1741,7 +1741,7 @@ static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges)
*
* rct2: 0x00695161
*/
static int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges)
int32_t OriginalPathfinding::GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges)
{
TileCoordsXYZ entranceGoal{};
if (peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)
@@ -1971,7 +1971,7 @@ static StationIndex guest_pathfinding_select_random_station(
*
* rct2: 0x00694C35
*/
int32_t guest_path_finding(Guest* peep)
int32_t OriginalPathfinding::guest_path_finding(Guest* peep)
{
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
PathfindLoggingEnable(peep);
@@ -2266,7 +2266,7 @@ int32_t guest_path_finding(Guest* 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())
{

View File

@@ -17,6 +17,8 @@ struct Peep;
struct Guest;
struct TileElement;
// The tile position of the place the peep is trying to get to (park entrance/exit, ride
// entrance/exit, or the end of the queue line for a ride).
//
@@ -37,19 +39,42 @@ extern RideId gPeepPathFindQueueRideIndex;
// In practice, if this is false, gPeepPathFindQueueRideIndex is always RIDE_ID_NULL.
extern bool gPeepPathFindIgnoreForeignQueues;
// Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide
// the direction the peep should walk in from the current tile.
Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep);
class GuestPathfinding
{
public:
// Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide
// the direction the peep should walk in from the current tile.
virtual Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) = 0;
// Test whether the given tile can be walked onto, if the peep is currently at height currentZ and
// moving in direction currentDirection.
bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection);
// Test whether the given tile can be walked onto, if the peep is currently at height currentZ and
// moving in direction currentDirection.
static bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection);
// Overall guest pathfinding AI. Sets up Peep::DestinationX/DestinationY (which they move to in a
// straight line, no pathfinding). Called whenever the guest has arrived at their previously set destination.
//
// Returns 0 if the guest has successfully had a new destination set up, nonzero otherwise.
int32_t guest_path_finding(Guest* peep);
// Overall guest pathfinding AI. Sets up Peep::DestinationX/DestinationY (which they move to in a
// straight line, no pathfinding). Called whenever the guest has arrived at their previously set destination.
//
// Returns 0 if the guest has successfully had a new destination set up, nonzero otherwise.
virtual int32_t guest_path_finding(Guest* peep) = 0;
};
class OriginalPathfinding : public GuestPathfinding
{
public:
Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep);
int32_t guest_path_finding(Guest* peep);
private:
int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges);
int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges);
int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges);
};
//TODO: Implement a better solution than a global variable for the utilized pathfinder
extern GuestPathfinding* gGuestPathfinder;
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
# define PATHFIND_DEBUG \

View File

@@ -16,6 +16,7 @@
using namespace OpenRCT2;
static std::ostream& operator<<(std::ostream& os, const TileCoordsXYZ& coords)
{
return os << "(" << coords.x << ", " << coords.y << ", " << coords.z << ")";
@@ -84,7 +85,7 @@ protected:
// Pick the direction the peep should initially move in, given the goal position.
// This will also store the goal position and initialize pathfinding data for the peep.
gPeepPathFindGoalPosition = goal;
const Direction moveDir = peep_pathfind_choose_direction(*pos, peep);
const Direction moveDir = gGuestPathfinder->peep_pathfind_choose_direction(*pos, peep);
if (moveDir == INVALID_DIRECTION)
{
// Couldn't determine a direction to move off in