Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

497 lines
15 KiB
C++

#ifndef TASK_VEHICLE_PARK_H
#define TASK_VEHICLE_PARK_H
// Gta headers.
#include "Renderer/HierarchyIds.h"
#include "Task/Scenario/ScenarioChainingTests.h" // CParkingSpaceFreeFromObstructionsTestHelper
#include "Task/System/Task.h"
#include "Task/System/TaskComplex.h"
#include "Task/System/TaskHelpers.h"
#include "Task\System\TaskTypes.h"
#include "VehicleAi\task\TaskVehicleMissionBase.h"
#include "ai/AITarget.h"
class CVehicle;
class CVehControls;
//Rage headers.
#include "Vector/Vector3.h"
//
//
//
class CTaskVehicleStop : public CTaskVehicleMissionBase
{
public:
typedef enum
{
State_Invalid = -1,
State_Stop
} VehicleControlState;
enum
{
SF_SupressBrakeLight = BIT(0),
SF_DontTerminateWhenStopped = BIT(1),
SF_DontResetSteerAngle = BIT(2),
SF_UseFullBrake = BIT(3),
SF_EnableTimeslicingWhenStill = BIT(4),
SF_NumStopFlags = 5
};
// Constructor/destructor
CTaskVehicleStop(u32 Stopflags = 0);
~CTaskVehicleStop(){}
int GetTaskTypeInternal() const { return CTaskTypes::TASK_VEHICLE_STOP; }
aiTask* Copy() const {return rage_new CTaskVehicleStop(m_StopFlags);}
// FSM implementations
FSM_Return UpdateFSM(const s32 iState, const FSM_Event iEvent);
s32 GetDefaultStateAfterAbort() const {return State_Stop;}
#if !__FINAL
friend class CTaskClassInfoManager;
static const char * GetStaticStateName( s32 );
#endif //!__FINAL
FSM_Return ProcessPreFSM();
virtual bool IsSyncedAcrossNetwork() const { return true; }
virtual CTaskVehicleSerialiserBase* GetTaskSerialiser() const { return rage_new CTaskVehicleSerialiser<CTaskVehicleStop>; }
virtual void CloneUpdate(CVehicle *pVehicle);
virtual void CleanUp();
void Serialise(CSyncDataBase& serialiser)
{
SERIALISE_UNSIGNED(serialiser, m_StopFlags, SF_NumStopFlags, "Stop flags");
}
float ComputeThrottleForSpeed(CVehicle& in_Vehicle, float in_Speed);
private:
// FSM function implementations
//State_Stop
FSM_Return Stop_OnUpdate (CVehicle* pVehicle);
u32 m_StopFlags;
};
//
//
//
class CTaskVehiclePullOver : public CTaskVehicleMissionBase
{
public:
typedef enum
{
State_Invalid = -1,
State_Cruise,
State_HeadForTarget,
State_Slowdown,
State_Stop,
} VehicleControlState;
typedef enum
{
Force_NoPreference,
Force_Left,
Force_Right,
} ForcePulloverDirection;
// Constructor/destructor
CTaskVehiclePullOver(bool bForcePullOverRightAway = false, ForcePulloverDirection forceDirection = Force_NoPreference
, bool bJustPullOverToSideOfCurrentLane = false);
~CTaskVehiclePullOver()
{
delete m_pFollowRoute;
}
virtual void CleanUp();
int GetTaskTypeInternal() const { return CTaskTypes::TASK_VEHICLE_PULL_OVER; }
aiTask* Copy() const {return rage_new CTaskVehiclePullOver(m_bForcePullOverRightAway, m_ForcePulloverInDirection, m_bJustPullOverToSideOfCurrentLane);}
// FSM implementations
FSM_Return UpdateFSM(const s32 iState, const FSM_Event iEvent);
s32 GetDefaultStateAfterAbort() const {return State_Cruise;}
#if !__FINAL
friend class CTaskClassInfoManager;
static const char * GetStaticStateName( s32 );
#endif //!__FINAL
float GetPointToAimFor(CVehicle *pVehicle, Vector3 *pPointToAimFor, float& fDotProductOut);
FSM_Return ProcessPreFSM();
virtual CVehicleNodeList * GetNodeList() { return GetState() == State_Cruise ? NULL : &m_NodeList;}
virtual const CVehicleFollowRouteHelper* GetFollowRouteHelper() const { return GetState() == State_Cruise ? NULL : m_pFollowRoute;}
virtual void CopyNodeList(const CVehicleNodeList * pNodeList);
virtual bool IsSyncedAcrossNetwork() const { return true; }
virtual CTaskVehicleSerialiserBase* GetTaskSerialiser() const { return rage_new CTaskVehicleSerialiser<CTaskVehiclePullOver>; }
private:
// FSM function implementations
//Cruise
void Cruise_OnEnter(CVehicle* pVehicle);
FSM_Return Cruise_OnUpdate(CVehicle* pVehicle);
// HeadForTarget
void HeadForTarget_OnEnter(CVehicle* pVehicle);
FSM_Return HeadForTarget_OnUpdate(CVehicle* pVehicle);
//State_Slowdown
void Slowdown_OnEnter(CVehicle* pVehicle);
FSM_Return Slowdown_OnUpdate(CVehicle* pVehicle);
//State_Stop
void Stop_OnEnter(CVehicle* pVehicle);
FSM_Return Stop_OnUpdate(CVehicle* pVehicle);
void UpdateIndicatorsForCar(CVehicle* pVeh);
bool HeadingIsWithinToleranceForVehicle(CVehicle* pVehicle, float fDot) const;
CVehicleNodeList m_NodeList;
CVehicleFollowRouteHelper* m_pFollowRoute;
ForcePulloverDirection m_ForcePulloverInDirection;
bool m_bRightSideOfRoad;
bool m_bFirstUpdateInCruise;
bool m_bForcePullOverRightAway;
bool m_bJustPullOverToSideOfCurrentLane;
};
class CTaskVehiclePassengerExit : public CTaskVehiclePullOver
{
public:
typedef enum
{
State_GoToTarget,
State_Stop,
State_WaitForPassengersToExit,
} PassengerExitState;
CTaskVehiclePassengerExit(const Vector3& target);
~CTaskVehiclePassengerExit() {}
int GetTaskTypeInternal() const { return CTaskTypes::TASK_VEHICLE_PASSENGER_EXIT; }
aiTask* Copy() const { return rage_new CTaskVehiclePassengerExit(m_vTarget); }
// FSM implementations
FSM_Return UpdateFSM(const s32 iState, const FSM_Event iEvent);
s32 GetDefaultStateAfterAbort() const { return State_Stop; }
#if !__FINAL
friend class CTaskClassInfoManager;
static const char * GetStaticStateName( s32 );
#endif //!__FINAL
FSM_Return ProcessPreFSM();
virtual bool IsSyncedAcrossNetwork() const { return true; }
virtual CTaskVehicleSerialiserBase* GetTaskSerialiser() const { return rage_new CTaskVehicleSerialiser<CTaskVehiclePassengerExit>; }
private:
void GoToTarget_OnEnter(CVehicle* pVehicle);
FSM_Return GoToTarget_OnUpdate(CVehicle* pVehicle);
void Stop_OnEnter(CVehicle* pVehicle);
FSM_Return Stop_OnUpdate(CVehicle* pVehicle);
void WaitForPassengersToExit_OnEnter(CVehicle* pVehicle);
FSM_Return WaitForPassengersToExit_OnUpdate(CVehicle* pVehicle);
CScenarioPoint* GetDriverScenarioPoint(const CVehicle* pVehicle) const;
void GivePedExitTask(CPed* pPed, CVehicle* pVehicle) const;
atArray<RegdPed> m_exitingPeds;
Vector3 m_vTarget;
u32 m_uNumPassengersToExit;
};
class CTaskVehicleParkNew : public CTaskVehicleMissionBase
{
public:
struct Tunables : public CTuning
{
Tunables();
// PURPOSE: If tests are enabled to see if the parking space is blocked,
// this is the number of seconds we wait until we do the next test.
float m_ParkingSpaceBlockedWaitTimePerAttempt;
// PURPOSE: If tests are enabled to see if the parking space is blocked,
// this is the number of times we wait for the parking space
// to become unblocked before failing the task.
// NOTES: For example, if this is set to 2 and m_ParkingSpaceBlockedWaitTimePerAttempt
// is 5.0 s, we can spend 10.0 seconds waiting before giving up. There
// can however be 3 tests done, since we would do one final test before
// driving off after the last wait.
u8 m_ParkingSpaceBlockedMaxAttempts;
PAR_PARSABLE;
};
typedef enum
{
State_Invalid = -1,
State_Start,
State_Navigate,
State_ForwardIntoSpace,
State_BackIntoSpace,
State_BackAwayFromSpace,
State_PullForward, //before backing in, pull up in front of the space
State_PullOver,
State_PassengerExit,
State_Stop,
State_Failed // Parking spot blocked, or similar failure causing us to give up
} VehicleControlState;
typedef enum
{
Park_Parallel,
Park_Perpendicular_NoseIn,
Park_Perpendicular_BackIn,
Park_PullOver,
Park_LeaveParallelSpace,
Park_BackOutPerpendicularSpace,
Park_PassengerExit,
Park_PullOverImmediate,
} ParkType;
CTaskVehicleParkNew(const sVehicleMissionParams& params, const Vector3& direction = VEC3_ZERO, const ParkType parkType = Park_Parallel, const float toleranceRadians = 0.0f, const bool bKeepLightsOn=false);
~CTaskVehicleParkNew();
int GetTaskTypeInternal() const { return CTaskTypes::TASK_VEHICLE_PARK_NEW; }
aiTask* Copy() const;
bool GetDoTestsForBlockedSpace() const { return m_bDoTestsForBlockedSpace; }
void SetDoTestsForBlockedSpace(bool b) { m_bDoTestsForBlockedSpace = b; }
int GetMaxPathSearchDistance() const { return m_iMaxPathSearchDistance; }
void SetMaxPathSearchDistance(int dist) { m_iMaxPathSearchDistance = dist; }
// FSM implementations
FSM_Return ProcessPreFSM ();
FSM_Return UpdateFSM(const s32 iState, const FSM_Event iEvent);
s32 GetDefaultStateAfterAbort() const {return State_Start;}
#if !__FINAL
friend class CTaskClassInfoManager;
static const char * GetStaticStateName( s32 );
virtual void Debug() const;
#endif //!__FINAL
virtual bool IsSyncedAcrossNetwork() const { return true; }
virtual CTaskVehicleSerialiserBase* GetTaskSerialiser() const { return rage_new CTaskVehicleSerialiser<CTaskVehicleParkNew>; }
void Serialise(CSyncDataBase& serialiser)
{
static const unsigned SIZEOF_DIRECTION = 10;
static const unsigned SIZEOF_PARK_TYPE = 3;
static const unsigned SIZEOF_HEADING = 8;
// only the target is used by the task. Serialising everything will exceed the max task size
CTaskVehicleMissionBase::SerialiseTarget(serialiser);
bool hasDir = m_SpaceDir.x != 0.0f || m_SpaceDir.y != 0.0f || m_SpaceDir.z != 0.0f;
SERIALISE_BOOL(serialiser, hasDir);
if (hasDir || serialiser.GetIsMaximumSizeSerialiser())
{
SERIALISE_PACKED_FLOAT(serialiser, m_SpaceDir.x, 1.01f, SIZEOF_DIRECTION, "Direction X");
SERIALISE_PACKED_FLOAT(serialiser, m_SpaceDir.y, 1.01f, SIZEOF_DIRECTION, "Direction Y");
SERIALISE_PACKED_FLOAT(serialiser, m_SpaceDir.z, 1.01f, SIZEOF_DIRECTION, "Direction Z");
m_SpaceDir.Normalize();
}
else
{
m_SpaceDir = VEC3_ZERO;
}
unsigned parkType = (unsigned)m_ParkType;
SERIALISE_UNSIGNED(serialiser, parkType, SIZEOF_PARK_TYPE, "Park Type");
SERIALISE_PACKED_FLOAT(serialiser, m_HeadingToleranceRadians, TWO_PI, SIZEOF_HEADING, "Heading tolerance");
m_ParkType = (ParkType) parkType;
}
private:
//Start
void Start_OnEnter(CVehicle* pVehicle);
FSM_Return Start_OnUpdate(CVehicle* pVehicle);
// Navigate
void Navigate_OnEnter(CVehicle* pVehicle);
FSM_Return Navigate_OnUpdate(CVehicle* pVehicle);
//ForwardIntoSpace
void ForwardIntoSpace_OnEnter(CVehicle* pVehicle);
FSM_Return ForwardIntoSpace_OnUpdate(CVehicle* pVehicle);
//BackIntoSpace
void BackIntoSpace_OnEnter(CVehicle* pVehicle);
FSM_Return BackIntoSpace_OnUpdate(CVehicle* pVehicle);
//BackAwayFromSpace
void BackAwayFromSpace_OnEnter(CVehicle* pVehicle);
FSM_Return BackAwayFromSpace_OnUpdate(CVehicle* pVehicle);
//PullForwardParallel
void PullForward_OnEnter(CVehicle* pVehicle);
FSM_Return PullForward_OnUpdate(CVehicle* pVehicle);
//PullOver
void PullOver_OnEnter(CVehicle* pVehicle);
FSM_Return PullOver_OnUpdate(CVehicle* pVehicle);
//PassengerExit
void PassengerExit_OnEnter(CVehicle* pVehicle);
FSM_Return PassengerExit_OnUpdate(CVehicle* pVehicle);
//Stop
void Stop_OnEnter(CVehicle* pVehicle);
FSM_Return Stop_OnUpdate(CVehicle* pVehicle);
//Failed
void Failed_OnEnter();
FSM_Return Failed_OnUpdate();
bool IsReadyToQuit(CVehicle* pVehicle) const;
void FixUpParkingSpaceDirection(CVehicle* pVehicle);
void HelperGetParkingSpaceFrontPosition(Vector3& vPositionOut) const;
void HelperGetParkingSpaceRearPosition(Vector3& vPositionOut) const;
void HelperGetPositionToSteerTo(CVehicle* pVehicle, Vector3& vPositionOut) const;
void HelperGetBackAwayFromSpacePosition(CVehicle* pVehicle, Vector3& vPositionOut) const;
bool HelperIsAnythingBlockingEntryToSpace(CVehicle* pVehicle) const;
bool HelperIsVehicleStopped(CVehicle* pVehicle) const;
bool HelperUseReverseSpace() const;
bool HelperUseRearBonnetPos() const;
bool IsCurrentHeadingWithinTolerance(CVehicle* pVehicle) const;
bool IsCurrentPositionWithinTolerance(CVehicle* pVehicle) const;
bool IsCurrentPositionWithinXTolerance(CVehicle* pVehicle) const;
bool IsCurrentPositionWithinYTolerance(CVehicle* pVehicle) const;
float GetDistanceInFrontOfSpace(CVehicle* pVehicle) const;
float GetCruiseSpeedForDistanceToTarget(CVehicle* pVehicle) const;
static dev_float ms_fCruiseSpeedToPark;
static dev_float ms_fCruiseSpeedToParkBoat;
static dev_float ms_fParkingSpaceHalfLength;
static dev_float ms_fParkingSpaceHalfWidth;
static dev_float ms_fPositionXTolerance;
static dev_float ms_fPositionYTolerance;
static dev_float ms_fPositionXToleranceBike;
static dev_float ms_fPositionYToleranceBike;
static dev_float ms_fPositionXTolerancePlane;
static dev_float ms_fPositionYTolerancePlane;
static dev_u16 ms_iParkingStuckTime;
// PURPOSE: Helper object used to do checks to see if the parking space
// is blocked by something.
CParkingSpaceFreeFromObstructionsTestHelper m_SpaceFreeFromObstructionsHelper;
//we don't necessarily care about +/- direction, we may flip it
//in the constructor based on the type of parking that the user
//has specified and the space's direction relative to the car's
Vector3 m_SpaceDir;
float m_HeadingToleranceRadians;
ParkType m_ParkType;
// PURPOSE: Number of times the intended parking space has been sequentially
// found to be blocked, when testing.
u8 m_NumTimesParkingSpaceBlocked;
// PURPOSE: Max distance for how far we can search for a path on roads leading to
// the parking space, or -1 for no limit at this level.
int m_iMaxPathSearchDistance;
// PURPOSE: If true, let the task do tests to see if the parking space is blocked,
// and potentially let it give up if the space has been blocked for enough time.
bool m_bDoTestsForBlockedSpace;
bool m_bKeepLightsOnAfterParking;
// PURPOSE: Static tuning data for this task.
static Tunables sm_Tunables;
};
//may pull over, may just wait
class CTaskVehicleReactToCopSiren : public CTaskVehicleMissionBase
{
public:
typedef enum
{
React_PullOverLeft,
React_PullOverRight,
React_JustWait,
React_NumReactions
} ReactToCopSirenType;
typedef enum
{
State_Invalid = -1,
State_Start,
State_Pullover,
State_Wait,
} VehicleControlState;
CTaskVehicleReactToCopSiren(ReactToCopSirenType reactionType = React_JustWait, u32 nWaitDuration = 0);
~CTaskVehicleReactToCopSiren() {};
int GetTaskTypeInternal() const { return CTaskTypes::TASK_VEHICLE_REACT_TO_COP_SIREN; }
aiTask* Copy() const {return rage_new CTaskVehicleReactToCopSiren(m_ReactionType, m_nWaitDuration);}
// FSM implementations
FSM_Return UpdateFSM(const s32 iState, const FSM_Event iEvent);
s32 GetDefaultStateAfterAbort() const {return State_Start;}
virtual void CleanUp();
#if !__FINAL
friend class CTaskClassInfoManager;
static const char * GetStaticStateName( s32 );
#endif //!__FINAL
virtual bool IsSyncedAcrossNetwork() const { return true; }
virtual CTaskVehicleSerialiserBase* GetTaskSerialiser() const { return rage_new CTaskVehicleSerialiser<CTaskVehicleReactToCopSiren>; }
void Serialise(CSyncDataBase& serialiser)
{
static unsigned const SIZE_OF_REACTION_TYPE = datBitsNeeded<React_NumReactions-1>::COUNT;
static unsigned const SIZE_OF_DURATION = 16;
SERIALISE_UNSIGNED(serialiser, reinterpret_cast<u32&>(m_ReactionType), SIZE_OF_REACTION_TYPE, "Reaction type");
SERIALISE_UNSIGNED(serialiser, m_nWaitDuration, SIZE_OF_DURATION, "Wait duration");
}
private:
//State_Start
FSM_Return Start_OnUpdate(CVehicle* pVehicle);
//State_Pullover
void Pullover_OnEnter(CVehicle* pVehicle);
FSM_Return Pullover_OnUpdate(CVehicle* pVehicle);
//State_Wait
void Wait_OnEnter(CVehicle* pVehicle);
FSM_Return Wait_OnUpdate(CVehicle* pVehicle);
//this task prevents the vehicle from going pretend-occupant,
//when it's done, restores the previous value
ReactToCopSirenType m_ReactionType;
u32 m_nWaitDuration;
bool m_bPreviousDisablePretendOccupantsCached;
};
#endif