//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef AI_TRACKPATHER_H #define AI_TRACKPATHER_H #if defined( _WIN32 ) #pragma once #endif #include "ai_basenpc.h" class CPathTrack; //------------------------------------------------------------------------------ class CAI_TrackPather : public CAI_BaseNPC { DECLARE_CLASS( CAI_TrackPather, CAI_BaseNPC ); DECLARE_DATADESC(); public: bool IsOnPathTrack() { return (m_pCurrentPathTarget != NULL); } protected: void InitPathingData( float flTrackArrivalTolerance, float flTargetDistance, float flAvoidDistance ); virtual bool GetTrackPatherTarget( Vector *pPos ) { return false; } virtual CBaseEntity *GetTrackPatherTargetEnt() { return NULL; } const Vector & GetDesiredPosition() const { return m_vecDesiredPosition; } void SetDesiredPosition( const Vector &v ) { m_vecDesiredPosition = v; } const Vector & GetGoalOrientation() const { return m_vecGoalOrientation; } void SetGoalOrientation( const Vector &v ) { m_vecGoalOrientation = v; } bool CurPathTargetIsDest() { return ( m_pDestPathTarget == m_pCurrentPathTarget ); } virtual bool HasReachedTarget( void ) { return (WorldSpaceCenter() - m_vecDesiredPosition).Length() < 128; } CPathTrack * GetDestPathTarget() { return m_pDestPathTarget; } bool IsInForcedMove() const { return m_bForcedMove; } void ClearForcedMove() { m_bForcedMove = false; } float GetPathMaxSpeed() const { return m_flPathMaxSpeed; } void OnSave( IEntitySaveUtils *pUtils ); void OnRestore( void ); protected: enum PauseState_t { PAUSE_NO_PAUSE = 0, PAUSED_AT_POSITION, PAUSE_AT_NEXT_LOS_POSITION, PAUSE_FORCE_DWORD = 0xFFFFFFFF, }; // Sets a track void SetTrack( string_t strTrackName ); void SetTrack( CBaseEntity *pGoalEnt ); // Fly to a particular track point via the path virtual void InputFlyToPathTrack( inputdata_t &inputdata ); // Updates the nav target if we've reached it void UpdateTrackNavigation( void ); // Computes distance + nearest point from the current path.. float ClosestPointToCurrentPath( Vector *pVecPoint ) const; // Computes a "path" velocity at a particular point along the current path void ComputePathTangent( float t, Vector *pVecTangent ) const; // Computes the *normalized* velocity at which the helicopter should approach the final point void ComputeNormalizedDestVelocity( Vector *pVecVelocity ) const; // Sets the farthest path distance void SetFarthestPathDist( float flMaxPathDist ); // Returns the next/previous path along our current path CPathTrack *NextAlongCurrentPath( CPathTrack *pPath ) const; CPathTrack *PreviousAlongCurrentPath( CPathTrack *pPath ) const; // Adjusts a "next"most node based on the current movement direction CPathTrack *AdjustForMovementDirection( CPathTrack *pPath ) const; // Enemy visibility check virtual CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos ); // Compute a point n units along a path void ComputePointAlongPath( const Vector &vecStartPoint, float flDistance, Vector *pTarget ); // Are we leading? bool IsLeading() const { return m_bLeading && !m_bForcedMove; } // Leading + leading distance void EnableLeading( bool bEnable ); void SetLeadingDistance( float flLeadDistance ); float GetLeadingDistance( ) const; // Compute a point n units along the current path from our current position // (but don't pass the desired target point) void ComputePointAlongCurrentPath( float flDistance, float flPerpDist, Vector *pTarget ); // Returns the perpendicular distance of the target from the nearest path point float TargetDistanceToPath() const { return m_flTargetDistFromPath; } // Returns the speed of the target relative to the path float TargetSpeedAlongPath() const; // Returns the speed of the target *across* the path float TargetSpeedAcrossPath() const; // Compute a path direction void ComputePathDirection( CPathTrack *pPath, Vector *pVecPathDir ); // What's the current path direction? void CurrentPathDirection( Vector *pVecPathDir ); // Returns the max distance we can be from the path float MaxDistanceFromCurrentPath() const; // true to use farthest, false for nearest void UseFarthestPathPoint( bool useFarthest ); // Moves to an explicit track point void MoveToTrackPoint( CPathTrack *pTrack ); // Sets up a new current path target void SetupNewCurrentTarget( CPathTrack *pTrack ); // Compute the distance to the leading position float ComputeDistanceToLeadingPosition(); // Compute the distance to the target position float ComputeDistanceToTargetPosition(); // Set the pause state. void SetPauseState( PauseState_t pauseState ) { m_nPauseState = pauseState; } // Does this path track have LOS to the target? bool HasLOSToTarget( CPathTrack *pTrack ); // FIXME: Work this back into the base class virtual bool ShouldUseFixedPatrolLogic() { return false; } // Deal with teleportation void Teleported(); private: CPathTrack *BestPointOnPath( CPathTrack *pPath, const Vector &targetPos, float avoidRadius, bool visible, bool bFarthestPointOnPath ); // Input methods void InputSetTrack( inputdata_t &inputdata ); void InputChooseFarthestPathPoint( inputdata_t &inputdata ); void InputChooseNearestPathPoint( inputdata_t &inputdata ); void InputStartBreakableMovement( inputdata_t &inputdata ); void InputStopBreakableMovement( inputdata_t &inputdata ); void InputStartPatrol( inputdata_t &inputdata ); void InputStopPatrol( inputdata_t &inputdata ); void InputStartLeading( inputdata_t &inputdata ); void InputStopLeading( inputdata_t &inputdata ); // Obsolete, for backward compatibility void InputStartPatrolBreakable( inputdata_t &inputdata ); // Flies to a point on a track void FlyToPathTrack( string_t strTrackName ); // Selects a new destination target void SelectNewDestTarget(); // Makes sure we've picked the right position along the path if we're chasing an enemy void UpdateTargetPosition( ); // Moves to the track void UpdateCurrentTarget(); void UpdateCurrentTargetLeading(); // Track debugging info void VisualizeDebugInfo( const Vector &vecNearestPoint, const Vector &vecTarget ); // Moves to the closest track point void MoveToClosestTrackPoint( CPathTrack *pTrack ); // Are the two path tracks connected? bool IsOnSameTrack( CPathTrack *pPath1, CPathTrack *pPath2 ) const; // Is pPathTest in "front" of pPath on the same path? (Namely, does GetNext() get us there?) bool IsForwardAlongPath( CPathTrack *pPath, CPathTrack *pPathTest ) const; // Purpose: void UpdateTargetPositionLeading( void ); // Compute a point n units along a path CPathTrack *ComputeLeadingPointAlongPath( const Vector &vecStartPoint, CPathTrack *pFirstTrack, float flDistance, Vector *pTarget ); // Finds the closest point on the path, returns a signed perpendicular distance CPathTrack *FindClosestPointOnPath( CPathTrack *pPath, const Vector &targetPos, Vector *pVecClosestPoint, Vector *pVecPathDir, float *pDistanceFromPath ); // Methods to find a signed perp distance from the track // and to compute a point off the path based on the signed perp distance float ComputePerpDistanceFromPath( const Vector &vecPointOnPath, const Vector &vecPathDir, const Vector &vecPointOffPath ); void ComputePointFromPerpDistance( const Vector &vecPointOnPath, const Vector &vecPathDir, float flPerpDist, Vector *pResult ); // Returns the direction of the path at the closest point to the target const Vector &TargetPathDirection() const; const Vector &TargetPathAcrossDirection() const; // Returns distance along path to target, returns -1 if there's no path float ComputePathDistance( CPathTrack *pStart, CPathTrack *pDest, bool bForward ) const; // Compute the distance to a particular point on the path float ComputeDistanceAlongPathToPoint( CPathTrack *pStartTrack, CPathTrack *pDestTrack, const Vector &vecDestPosition, bool bMovingForward ); private: //--------------------------------- Vector m_vecDesiredPosition; Vector m_vecGoalOrientation; // orientation of the goal entity. // NOTE: CurrentPathTarget changes meaning based on movement direction // For this *after* means the "next" (m_pnext) side of the line segment // and "before" means the "prev" (m_pprevious) side of the line segment // CurrentPathTarget is *after* the desired point when moving forward, // and *before* the desired point when moving backward. // DestPathTarget + TargetNearestPath always represent points // *after* the desired point. CHandle m_pCurrentPathTarget; CHandle m_pDestPathTarget; CHandle m_pLastPathTarget; CHandle m_pTargetNearestPath; // Used only by leading, it specifies the path point *after* where the target is string_t m_strCurrentPathName; string_t m_strDestPathName; string_t m_strLastPathName; string_t m_strTargetNearestPathName; Vector m_vecLastGoalCheckPosition; // Last position checked for moving towards float m_flEnemyPathUpdateTime; // Next time to update our enemies position bool m_bForcedMove; // Means the destination point must be reached regardless of enemy position bool m_bPatrolling; // If set, move back and forth along the current track until we see an enemy bool m_bPatrolBreakable; // If set, I'll stop patrolling if I see an enemy bool m_bLeading; // If set, we can lead our enemies // Derived class pathing data float m_flTargetDistanceThreshold;// Distance threshold used to determine when a target has moved enough to update our navigation to it float m_flAvoidDistance; // float m_flTargetTolerance; // How far from a path track do we need to be before we 'reached' it? Vector m_vecSegmentStartPoint; // Starting point for the current segment Vector m_vecSegmentStartSplinePoint; // Used to define a spline which is used to compute path velocity bool m_bMovingForward; bool m_bChooseFarthestPoint; float m_flFarthestPathDist; // How far from a path track do we need to be before we 'reached' it? float m_flPathMaxSpeed; float m_flTargetDistFromPath; // How far is the target from the closest point on the path? float m_flLeadDistance; Vector m_vecTargetPathDir; Vector m_vecTargetPathPoint; // What point on the path is closest to the target? PauseState_t m_nPauseState; }; //------------------------------------------------------------------------------ #endif // AI_TRACKPATHER_H