diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/ai_route.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/ai_route.cpp')
| -rw-r--r-- | mp/src/game/server/ai_route.cpp | 1366 |
1 files changed, 683 insertions, 683 deletions
diff --git a/mp/src/game/server/ai_route.cpp b/mp/src/game/server/ai_route.cpp index 3a4a147d..91175b78 100644 --- a/mp/src/game/server/ai_route.cpp +++ b/mp/src/game/server/ai_route.cpp @@ -1,683 +1,683 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "ai_link.h"
-#include "ai_navtype.h"
-#include "ai_waypoint.h"
-#include "ai_pathfinder.h"
-#include "ai_navgoaltype.h"
-#include "ai_routedist.h"
-#include "ai_route.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-BEGIN_SIMPLE_DATADESC(CAI_Path)
- // m_Waypoints (reconsititute on load)
- DEFINE_FIELD( m_goalTolerance, FIELD_FLOAT ),
- DEFINE_CUSTOM_FIELD( m_activity, ActivityDataOps() ),
- DEFINE_FIELD( m_target, FIELD_EHANDLE ),
- DEFINE_FIELD( m_sequence, FIELD_INTEGER ),
- DEFINE_FIELD( m_vecTargetOffset, FIELD_VECTOR ),
- DEFINE_FIELD( m_waypointTolerance, FIELD_FLOAT ),
- DEFINE_CUSTOM_FIELD( m_arrivalActivity, ActivityDataOps() ),
- DEFINE_FIELD( m_arrivalSequence, FIELD_INTEGER ),
- // m_iLastNodeReached
- DEFINE_FIELD( m_bGoalPosSet, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_goalPos, FIELD_POSITION_VECTOR),
- DEFINE_FIELD( m_bGoalTypeSet, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_goalType, FIELD_INTEGER ),
- DEFINE_FIELD( m_goalFlags, FIELD_INTEGER ),
- DEFINE_FIELD( m_routeStartTime, FIELD_TIME ),
- DEFINE_FIELD( m_goalDirection, FIELD_VECTOR ),
- DEFINE_FIELD( m_goalDirectionTarget, FIELD_EHANDLE ),
- DEFINE_FIELD( m_goalSpeed, FIELD_FLOAT ),
- DEFINE_FIELD( m_goalSpeedTarget, FIELD_EHANDLE ),
- DEFINE_FIELD( m_goalStoppingDistance, FIELD_FLOAT ),
-END_DATADESC()
-
-//-----------------------------------------------------------------------------
-AI_Waypoint_t CAI_Path::gm_InvalidWaypoint( Vector(0,0,0), 0, NAV_NONE, 0, 0 );
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetWaypoints(AI_Waypoint_t* route, bool fSetGoalFromLast)
-{
- m_Waypoints.Set(route);
-
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- if ( pLast )
- {
- pLast->flPathDistGoal = -1;
- if ( fSetGoalFromLast )
- {
- if ( pLast )
- {
- m_bGoalPosSet = false;
- pLast->ModifyFlags( bits_WP_TO_GOAL, true );
- SetGoalPosition(pLast->GetPos());
- }
- }
- }
-
- AssertRouteValid( m_Waypoints.GetFirst() );
-}
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::PrependWaypoints( AI_Waypoint_t *pWaypoints )
-{
- m_Waypoints.PrependWaypoints( pWaypoints );
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- pLast->flPathDistGoal = -1;
-
- AssertRouteValid( m_Waypoints.GetFirst() );
-}
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags )
-{
- m_Waypoints.PrependWaypoint( newPoint, navType, waypointFlags );
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- pLast->flPathDistGoal = -1;
-
- AssertRouteValid( m_Waypoints.GetFirst() );
-}
-
-//-----------------------------------------------------------------------------
-
-float CAI_Path::GetPathLength()
-{
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- if ( pLast && pLast->flPathDistGoal == -1 )
- {
- ComputeRouteGoalDistances( pLast );
- }
- AI_Waypoint_t *pCurrent = GetCurWaypoint();
- return ( ( pCurrent ) ? pCurrent->flPathDistGoal : 0 );
-}
-
-//-----------------------------------------------------------------------------
-
-float CAI_Path::GetPathDistanceToGoal( const Vector &startPos )
-{
- AI_Waypoint_t *pCurrent = GetCurWaypoint();
- if ( pCurrent )
- {
- return ( GetPathLength() + ComputePathDistance(pCurrent->NavType(), startPos, pCurrent->GetPos()) );
- }
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-
-Activity CAI_Path::SetMovementActivity(Activity activity)
-{
- Assert( activity != ACT_RESET && activity != ACT_INVALID );
- //Msg("Set movement to %s\n", ActivityList_NameForIndex(activity) );
-
- m_sequence = ACT_INVALID;
- return (m_activity = activity);
-}
-
-//-----------------------------------------------------------------------------
-
-Activity CAI_Path::GetArrivalActivity( ) const
-{
- if ( !m_Waypoints.IsEmpty() )
- {
- return m_arrivalActivity;
- }
- return ACT_INVALID;
-}
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetArrivalActivity(Activity activity)
-{
- m_arrivalActivity = activity;
- m_arrivalSequence = ACT_INVALID;
-}
-
-//-----------------------------------------------------------------------------
-
-int CAI_Path::GetArrivalSequence( ) const
-{
- if ( !m_Waypoints.IsEmpty() )
- {
- return m_arrivalSequence;
- }
- return ACT_INVALID;
-}
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetArrivalSequence( int sequence )
-{
- m_arrivalSequence = sequence;
-}
-
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetGoalDirection( const Vector &goalDirection )
-{
- m_goalDirectionTarget = NULL;
- m_goalDirection = goalDirection;
- VectorNormalize( m_goalDirection );
- /*
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- if ( pLast )
- {
- NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 );
- NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 );
- }
- */
-}
-
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetGoalDirection( CBaseEntity *pTarget )
-{
- m_goalDirectionTarget = pTarget;
-
- if (pTarget)
- {
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- if ( pLast )
- {
- m_goalDirection = pTarget->GetAbsOrigin() - pLast->vecLocation;
- VectorNormalize( m_goalDirection );
- /*
- NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 );
- NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 );
- */
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-
-Vector CAI_Path::GetGoalDirection( const Vector &startPos )
-{
- if (m_goalDirectionTarget)
- {
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- if ( pLast )
- {
- AI_Waypoint_t *pPrev = pLast->GetPrev();
- if (pPrev)
- {
- Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - pPrev->vecLocation;
- VectorNormalize( goalDirection );
- return goalDirection;
- }
- else
- {
- Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - startPos;
- VectorNormalize( goalDirection );
- return goalDirection;
- }
- }
- }
- else if (m_goalDirection == vec3_origin)
- {
- // Assert(0); // comment out the default directions in SetGoal() to find test cases for missing initialization
- AI_Waypoint_t *pLast = m_Waypoints.GetLast();
- if ( pLast )
- {
- AI_Waypoint_t *pPrev = pLast->GetPrev();
- if (pPrev)
- {
- Vector goalDirection = pLast->vecLocation - pPrev->vecLocation;
- VectorNormalize( goalDirection );
- return goalDirection;
- }
- else
- {
- Vector goalDirection =pLast->vecLocation - startPos;
- VectorNormalize( goalDirection );
- return goalDirection;
- }
- }
- }
-
- return m_goalDirection;
-}
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetGoalSpeed( float flSpeed )
-{
- m_goalSpeed = flSpeed;
-}
-
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetGoalSpeed( CBaseEntity *pTarget )
-{
- m_goalSpeedTarget = pTarget;
-}
-
-//-----------------------------------------------------------------------------
-
-float CAI_Path::GetGoalSpeed( const Vector &startPos )
-{
- if (m_goalSpeedTarget)
- {
- Vector goalDirection = GetGoalDirection( startPos );
- Vector targetVelocity = m_goalSpeedTarget->GetSmoothedVelocity();
- float dot = DotProduct( goalDirection, targetVelocity );
- dot = MAX( 0.0f, dot );
- // return a relative impact speed of m_goalSpeed
- if (m_goalSpeed > 0.0)
- {
- return dot + m_goalSpeed;
- }
- return dot;
- }
- return m_goalSpeed;
-}
-
-
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::SetGoalStoppingDistance( float flDistance )
-{
- m_goalStoppingDistance = flDistance;
-}
-
-//-----------------------------------------------------------------------------
-
-float CAI_Path::GetGoalStoppingDistance( ) const
-{
- return m_goalStoppingDistance;
-}
-
-
-//-----------------------------------------------------------------------------
-const Vector &CAI_Path::CurWaypointPos() const
-{
- if ( GetCurWaypoint() )
- return GetCurWaypoint()->GetPos();
- AssertMsg(0, "Invalid call to CurWaypointPos()");
- return gm_InvalidWaypoint.GetPos();
-}
-
-//-----------------------------------------------------------------------------
-const Vector &CAI_Path::NextWaypointPos() const
-{
- if ( GetCurWaypoint() && GetCurWaypoint()->GetNext())
- return GetCurWaypoint()->GetNext()->GetPos();
- static Vector invalid( 0, 0, 0 );
- AssertMsg(0, "Invalid call to NextWaypointPos()");
- return gm_InvalidWaypoint.GetPos();
-}
-
-//-----------------------------------------------------------------------------
-float CAI_Path::CurWaypointYaw() const
-{
- return GetCurWaypoint()->flYaw;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CAI_Path::SetGoalPosition(const Vector &goalPos)
-{
-
-#ifdef _DEBUG
- // Make sure goal position isn't set more than once
- if (m_bGoalPosSet == true)
- {
- DevMsg( "GetCurWaypoint Goal Position Set Twice!\n");
- }
-#endif
-
- m_bGoalPosSet = true;
- VectorAdd( goalPos, m_vecTargetOffset, m_goalPos );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets last node as goal and goal position
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CAI_Path::SetLastNodeAsGoal(bool bReset)
-{
- #ifdef _DEBUG
- // Make sure goal position isn't set more than once
- if (!bReset && m_bGoalPosSet == true)
- {
- DevMsg( "GetCurWaypoint Goal Position Set Twice!\n");
- }
- #endif
-
- // Find the last node
- if (GetCurWaypoint())
- {
- AI_Waypoint_t* waypoint = GetCurWaypoint();
-
- while (waypoint)
- {
- if (!waypoint->GetNext())
- {
- m_goalPos = waypoint->GetPos();
- m_bGoalPosSet = true;
- waypoint->ModifyFlags( bits_WP_TO_GOAL, true );
- return;
- }
- waypoint = waypoint->GetNext();
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Explicitly change the goal position w/o check
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CAI_Path::ResetGoalPosition(const Vector &goalPos)
-{
- m_bGoalPosSet = true;
- VectorAdd( goalPos, m_vecTargetOffset, m_goalPos );
-}
-
-
-//-----------------------------------------------------------------------------
-// Returns the *base* goal position (without the offset applied)
-//-----------------------------------------------------------------------------
-const Vector& CAI_Path::BaseGoalPosition() const
-{
-#ifdef _DEBUG
- // Make sure goal position was set
- if (m_bGoalPosSet == false)
- {
- DevMsg( "GetCurWaypoint Goal Position Never Set!\n");
- }
-#endif
-
- // FIXME: A little risky; store the base if this becomes a problem
- static Vector vecResult;
- VectorSubtract( m_goalPos, m_vecTargetOffset, vecResult );
- return vecResult;
-}
-
-
-//-----------------------------------------------------------------------------
- // Returns the *actual* goal position (with the offset applied)
-//-----------------------------------------------------------------------------
-const Vector & CAI_Path::ActualGoalPosition(void) const
-{
-#ifdef _DEBUG
- // Make sure goal position was set
- if (m_bGoalPosSet == false)
- {
- DevMsg( "GetCurWaypoint Goal Position Never Set!\n");
- }
-#endif
-
- return m_goalPos;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CAI_Path::SetGoalType(GoalType_t goalType)
-{
-
-#ifdef _DEBUG
- // Make sure goal position isn't set more than once
- if (m_goalType != GOALTYPE_NONE && goalType != GOALTYPE_NONE )
- {
- DevMsg( "GetCurWaypoint Goal Type Set Twice!\n");
- }
-#endif
-
- if (m_goalType != GOALTYPE_NONE)
- {
- m_routeStartTime = gpGlobals->curtime;
- m_bGoalTypeSet = true;
- }
- else
- m_bGoalTypeSet = false;
-
- m_goalType = goalType;
-
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-GoalType_t CAI_Path::GoalType(void) const
-{
- return m_goalType;
-}
-
-
-//-----------------------------------------------------------------------------
-
-void CAI_Path::Advance( void )
-{
- if ( CurWaypointIsGoal() )
- return;
-
- // -------------------------------------------------------
- // If I have another waypoint advance my path
- // -------------------------------------------------------
- if (GetCurWaypoint()->GetNext())
- {
- AI_Waypoint_t *pNext = GetCurWaypoint()->GetNext();
-
- // If waypoint was a node take note of it
- if (GetCurWaypoint()->Flags() & bits_WP_TO_NODE)
- {
- m_iLastNodeReached = GetCurWaypoint()->iNodeID;
- }
-
- delete GetCurWaypoint();
- SetWaypoints(pNext);
-
- return;
- }
- // -------------------------------------------------
- // This is an error catch that should *not* happen
- // It means a route was created with no goal
- // -------------------------------------------------
- else
- {
- DevMsg( "!!ERROR!! Force end of route with no goal!\n");
- GetCurWaypoint()->ModifyFlags( bits_WP_TO_GOAL, true );
- }
-
- AssertRouteValid( m_Waypoints.GetFirst() );
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Clears the route and resets all its fields to default values
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CAI_Path::Clear( void )
-{
- m_Waypoints.RemoveAll();
-
- m_goalType = GOALTYPE_NONE; // Type of goal
- m_goalPos = vec3_origin; // Our ultimate goal position
- m_bGoalPosSet = false; // Was goal position set
- m_bGoalTypeSet = false; // Was goal position set
- m_goalFlags = false;
- m_vecTargetOffset = vec3_origin;
- m_routeStartTime = FLT_MAX;
-
- m_goalTolerance = 0.0; // How close do we need to get to the goal
- // FIXME: split m_goalTolerance into m_buildTolerance and m_moveTolerance, let them be seperatly controllable.
-
- m_activity = ACT_INVALID;
- m_sequence = ACT_INVALID;
- m_target = NULL;
-
- m_arrivalActivity = ACT_INVALID;
- m_arrivalSequence = ACT_INVALID;
-
- m_goalDirectionTarget = NULL;
- m_goalDirection = vec3_origin;
-
- m_goalSpeedTarget = NULL;
- m_goalSpeed = -1.0f; // init to an invalid speed
-
- m_goalStoppingDistance = 0.0; // How close to we want to get to the goal
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-Navigation_t CAI_Path::CurWaypointNavType() const
-{
- if (!GetCurWaypoint())
- {
- return NAV_NONE;
- }
- else
- {
- return GetCurWaypoint()->NavType();
- }
-}
-
-int CAI_Path::CurWaypointFlags() const
-{
- if (!GetCurWaypoint())
- {
- return 0;
- }
- else
- {
- return GetCurWaypoint()->Flags();
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Get the goal's flags
-// Output : unsigned
-//-----------------------------------------------------------------------------
-unsigned CAI_Path::GoalFlags( void ) const
-{
- return m_goalFlags;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns true if current waypoint is my goal
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-bool CAI_Path::CurWaypointIsGoal( void ) const
-{
-// Assert( GetCurWaypoint() );
-
- if( !GetCurWaypoint() )
- return false;
-
-
- if ( GetCurWaypoint()->Flags() & bits_WP_TO_GOAL )
- {
- #ifdef _DEBUG
- if (GetCurWaypoint()->GetNext())
- {
- DevMsg( "!!ERROR!! Goal is not last waypoint!\n");
- }
- if ((GetCurWaypoint()->GetPos() - m_goalPos).Length() > 0.1)
- {
- DevMsg( "!!ERROR!! Last waypoint isn't in goal position!\n");
- }
- #endif
- return true;
- }
- if ( GetCurWaypoint()->Flags() & bits_WP_TO_PATHCORNER )
- {
- // UNDONE: Refresh here or somewhere else?
- }
-#ifdef _DEBUG
- if (!GetCurWaypoint()->GetNext())
- {
- DevMsg( "!!ERROR!! GetCurWaypoint has no goal!\n");
- }
-#endif
-
- return false;
-}
-
-
-//-----------------------------------------------------------------------------
-// Computes the goal distance for each waypoint along the route
-//-----------------------------------------------------------------------------
-void CAI_Path::ComputeRouteGoalDistances(AI_Waypoint_t *pGoalWaypoint)
-{
- // The goal distance is the distance from any waypoint to the goal waypoint
-
- // Backup through the list and calculate distance to goal
- AI_Waypoint_t *pPrev;
- AI_Waypoint_t *pCurWaypoint = pGoalWaypoint;
- pCurWaypoint->flPathDistGoal = 0;
- while (pCurWaypoint->GetPrev())
- {
- pPrev = pCurWaypoint->GetPrev();
-
- float flWaypointDist = ComputePathDistance(pCurWaypoint->NavType(), pPrev->GetPos(), pCurWaypoint->GetPos());
- pPrev->flPathDistGoal = pCurWaypoint->flPathDistGoal + flWaypointDist;
-
- pCurWaypoint = pPrev;
- }
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-CAI_Path::CAI_Path()
-{
- m_goalType = GOALTYPE_NONE; // Type of goal
- m_goalPos = vec3_origin; // Our ultimate goal position
- m_goalTolerance = 0.0; // How close do we need to get to the goal
- m_activity = ACT_INVALID; // The activity to use during motion
- m_sequence = ACT_INVALID;
- m_target = NULL;
- m_goalFlags = 0;
- m_routeStartTime = FLT_MAX;
- m_arrivalActivity = ACT_INVALID;
- m_arrivalSequence = ACT_INVALID;
-
- m_iLastNodeReached = NO_NODE;
-
- m_waypointTolerance = DEF_WAYPOINT_TOLERANCE;
-
-}
-
-CAI_Path::~CAI_Path()
-{
- DeleteAll( GetCurWaypoint() );
-}
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "ai_link.h" +#include "ai_navtype.h" +#include "ai_waypoint.h" +#include "ai_pathfinder.h" +#include "ai_navgoaltype.h" +#include "ai_routedist.h" +#include "ai_route.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SIMPLE_DATADESC(CAI_Path) + // m_Waypoints (reconsititute on load) + DEFINE_FIELD( m_goalTolerance, FIELD_FLOAT ), + DEFINE_CUSTOM_FIELD( m_activity, ActivityDataOps() ), + DEFINE_FIELD( m_target, FIELD_EHANDLE ), + DEFINE_FIELD( m_sequence, FIELD_INTEGER ), + DEFINE_FIELD( m_vecTargetOffset, FIELD_VECTOR ), + DEFINE_FIELD( m_waypointTolerance, FIELD_FLOAT ), + DEFINE_CUSTOM_FIELD( m_arrivalActivity, ActivityDataOps() ), + DEFINE_FIELD( m_arrivalSequence, FIELD_INTEGER ), + // m_iLastNodeReached + DEFINE_FIELD( m_bGoalPosSet, FIELD_BOOLEAN ), + DEFINE_FIELD( m_goalPos, FIELD_POSITION_VECTOR), + DEFINE_FIELD( m_bGoalTypeSet, FIELD_BOOLEAN ), + DEFINE_FIELD( m_goalType, FIELD_INTEGER ), + DEFINE_FIELD( m_goalFlags, FIELD_INTEGER ), + DEFINE_FIELD( m_routeStartTime, FIELD_TIME ), + DEFINE_FIELD( m_goalDirection, FIELD_VECTOR ), + DEFINE_FIELD( m_goalDirectionTarget, FIELD_EHANDLE ), + DEFINE_FIELD( m_goalSpeed, FIELD_FLOAT ), + DEFINE_FIELD( m_goalSpeedTarget, FIELD_EHANDLE ), + DEFINE_FIELD( m_goalStoppingDistance, FIELD_FLOAT ), +END_DATADESC() + +//----------------------------------------------------------------------------- +AI_Waypoint_t CAI_Path::gm_InvalidWaypoint( Vector(0,0,0), 0, NAV_NONE, 0, 0 ); + +//----------------------------------------------------------------------------- + +void CAI_Path::SetWaypoints(AI_Waypoint_t* route, bool fSetGoalFromLast) +{ + m_Waypoints.Set(route); + + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + if ( pLast ) + { + pLast->flPathDistGoal = -1; + if ( fSetGoalFromLast ) + { + if ( pLast ) + { + m_bGoalPosSet = false; + pLast->ModifyFlags( bits_WP_TO_GOAL, true ); + SetGoalPosition(pLast->GetPos()); + } + } + } + + AssertRouteValid( m_Waypoints.GetFirst() ); +} + +//----------------------------------------------------------------------------- + +void CAI_Path::PrependWaypoints( AI_Waypoint_t *pWaypoints ) +{ + m_Waypoints.PrependWaypoints( pWaypoints ); + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + pLast->flPathDistGoal = -1; + + AssertRouteValid( m_Waypoints.GetFirst() ); +} + +//----------------------------------------------------------------------------- + +void CAI_Path::PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags ) +{ + m_Waypoints.PrependWaypoint( newPoint, navType, waypointFlags ); + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + pLast->flPathDistGoal = -1; + + AssertRouteValid( m_Waypoints.GetFirst() ); +} + +//----------------------------------------------------------------------------- + +float CAI_Path::GetPathLength() +{ + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + if ( pLast && pLast->flPathDistGoal == -1 ) + { + ComputeRouteGoalDistances( pLast ); + } + AI_Waypoint_t *pCurrent = GetCurWaypoint(); + return ( ( pCurrent ) ? pCurrent->flPathDistGoal : 0 ); +} + +//----------------------------------------------------------------------------- + +float CAI_Path::GetPathDistanceToGoal( const Vector &startPos ) +{ + AI_Waypoint_t *pCurrent = GetCurWaypoint(); + if ( pCurrent ) + { + return ( GetPathLength() + ComputePathDistance(pCurrent->NavType(), startPos, pCurrent->GetPos()) ); + } + return 0; +} + +//----------------------------------------------------------------------------- + +Activity CAI_Path::SetMovementActivity(Activity activity) +{ + Assert( activity != ACT_RESET && activity != ACT_INVALID ); + //Msg("Set movement to %s\n", ActivityList_NameForIndex(activity) ); + + m_sequence = ACT_INVALID; + return (m_activity = activity); +} + +//----------------------------------------------------------------------------- + +Activity CAI_Path::GetArrivalActivity( ) const +{ + if ( !m_Waypoints.IsEmpty() ) + { + return m_arrivalActivity; + } + return ACT_INVALID; +} + +//----------------------------------------------------------------------------- + +void CAI_Path::SetArrivalActivity(Activity activity) +{ + m_arrivalActivity = activity; + m_arrivalSequence = ACT_INVALID; +} + +//----------------------------------------------------------------------------- + +int CAI_Path::GetArrivalSequence( ) const +{ + if ( !m_Waypoints.IsEmpty() ) + { + return m_arrivalSequence; + } + return ACT_INVALID; +} + +//----------------------------------------------------------------------------- + +void CAI_Path::SetArrivalSequence( int sequence ) +{ + m_arrivalSequence = sequence; +} + + +//----------------------------------------------------------------------------- + +void CAI_Path::SetGoalDirection( const Vector &goalDirection ) +{ + m_goalDirectionTarget = NULL; + m_goalDirection = goalDirection; + VectorNormalize( m_goalDirection ); + /* + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + if ( pLast ) + { + NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 ); + NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 ); + } + */ +} + + +//----------------------------------------------------------------------------- + +void CAI_Path::SetGoalDirection( CBaseEntity *pTarget ) +{ + m_goalDirectionTarget = pTarget; + + if (pTarget) + { + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + if ( pLast ) + { + m_goalDirection = pTarget->GetAbsOrigin() - pLast->vecLocation; + VectorNormalize( m_goalDirection ); + /* + NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 ); + NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 ); + */ + } + } +} + +//----------------------------------------------------------------------------- + +Vector CAI_Path::GetGoalDirection( const Vector &startPos ) +{ + if (m_goalDirectionTarget) + { + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + if ( pLast ) + { + AI_Waypoint_t *pPrev = pLast->GetPrev(); + if (pPrev) + { + Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - pPrev->vecLocation; + VectorNormalize( goalDirection ); + return goalDirection; + } + else + { + Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - startPos; + VectorNormalize( goalDirection ); + return goalDirection; + } + } + } + else if (m_goalDirection == vec3_origin) + { + // Assert(0); // comment out the default directions in SetGoal() to find test cases for missing initialization + AI_Waypoint_t *pLast = m_Waypoints.GetLast(); + if ( pLast ) + { + AI_Waypoint_t *pPrev = pLast->GetPrev(); + if (pPrev) + { + Vector goalDirection = pLast->vecLocation - pPrev->vecLocation; + VectorNormalize( goalDirection ); + return goalDirection; + } + else + { + Vector goalDirection =pLast->vecLocation - startPos; + VectorNormalize( goalDirection ); + return goalDirection; + } + } + } + + return m_goalDirection; +} + +//----------------------------------------------------------------------------- + +void CAI_Path::SetGoalSpeed( float flSpeed ) +{ + m_goalSpeed = flSpeed; +} + + +//----------------------------------------------------------------------------- + +void CAI_Path::SetGoalSpeed( CBaseEntity *pTarget ) +{ + m_goalSpeedTarget = pTarget; +} + +//----------------------------------------------------------------------------- + +float CAI_Path::GetGoalSpeed( const Vector &startPos ) +{ + if (m_goalSpeedTarget) + { + Vector goalDirection = GetGoalDirection( startPos ); + Vector targetVelocity = m_goalSpeedTarget->GetSmoothedVelocity(); + float dot = DotProduct( goalDirection, targetVelocity ); + dot = MAX( 0.0f, dot ); + // return a relative impact speed of m_goalSpeed + if (m_goalSpeed > 0.0) + { + return dot + m_goalSpeed; + } + return dot; + } + return m_goalSpeed; +} + + + +//----------------------------------------------------------------------------- + +void CAI_Path::SetGoalStoppingDistance( float flDistance ) +{ + m_goalStoppingDistance = flDistance; +} + +//----------------------------------------------------------------------------- + +float CAI_Path::GetGoalStoppingDistance( ) const +{ + return m_goalStoppingDistance; +} + + +//----------------------------------------------------------------------------- +const Vector &CAI_Path::CurWaypointPos() const +{ + if ( GetCurWaypoint() ) + return GetCurWaypoint()->GetPos(); + AssertMsg(0, "Invalid call to CurWaypointPos()"); + return gm_InvalidWaypoint.GetPos(); +} + +//----------------------------------------------------------------------------- +const Vector &CAI_Path::NextWaypointPos() const +{ + if ( GetCurWaypoint() && GetCurWaypoint()->GetNext()) + return GetCurWaypoint()->GetNext()->GetPos(); + static Vector invalid( 0, 0, 0 ); + AssertMsg(0, "Invalid call to NextWaypointPos()"); + return gm_InvalidWaypoint.GetPos(); +} + +//----------------------------------------------------------------------------- +float CAI_Path::CurWaypointYaw() const +{ + return GetCurWaypoint()->flYaw; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +void CAI_Path::SetGoalPosition(const Vector &goalPos) +{ + +#ifdef _DEBUG + // Make sure goal position isn't set more than once + if (m_bGoalPosSet == true) + { + DevMsg( "GetCurWaypoint Goal Position Set Twice!\n"); + } +#endif + + m_bGoalPosSet = true; + VectorAdd( goalPos, m_vecTargetOffset, m_goalPos ); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets last node as goal and goal position +// Input : +// Output : +//----------------------------------------------------------------------------- +void CAI_Path::SetLastNodeAsGoal(bool bReset) +{ + #ifdef _DEBUG + // Make sure goal position isn't set more than once + if (!bReset && m_bGoalPosSet == true) + { + DevMsg( "GetCurWaypoint Goal Position Set Twice!\n"); + } + #endif + + // Find the last node + if (GetCurWaypoint()) + { + AI_Waypoint_t* waypoint = GetCurWaypoint(); + + while (waypoint) + { + if (!waypoint->GetNext()) + { + m_goalPos = waypoint->GetPos(); + m_bGoalPosSet = true; + waypoint->ModifyFlags( bits_WP_TO_GOAL, true ); + return; + } + waypoint = waypoint->GetNext(); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Explicitly change the goal position w/o check +// Input : +// Output : +//----------------------------------------------------------------------------- +void CAI_Path::ResetGoalPosition(const Vector &goalPos) +{ + m_bGoalPosSet = true; + VectorAdd( goalPos, m_vecTargetOffset, m_goalPos ); +} + + +//----------------------------------------------------------------------------- +// Returns the *base* goal position (without the offset applied) +//----------------------------------------------------------------------------- +const Vector& CAI_Path::BaseGoalPosition() const +{ +#ifdef _DEBUG + // Make sure goal position was set + if (m_bGoalPosSet == false) + { + DevMsg( "GetCurWaypoint Goal Position Never Set!\n"); + } +#endif + + // FIXME: A little risky; store the base if this becomes a problem + static Vector vecResult; + VectorSubtract( m_goalPos, m_vecTargetOffset, vecResult ); + return vecResult; +} + + +//----------------------------------------------------------------------------- + // Returns the *actual* goal position (with the offset applied) +//----------------------------------------------------------------------------- +const Vector & CAI_Path::ActualGoalPosition(void) const +{ +#ifdef _DEBUG + // Make sure goal position was set + if (m_bGoalPosSet == false) + { + DevMsg( "GetCurWaypoint Goal Position Never Set!\n"); + } +#endif + + return m_goalPos; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +void CAI_Path::SetGoalType(GoalType_t goalType) +{ + +#ifdef _DEBUG + // Make sure goal position isn't set more than once + if (m_goalType != GOALTYPE_NONE && goalType != GOALTYPE_NONE ) + { + DevMsg( "GetCurWaypoint Goal Type Set Twice!\n"); + } +#endif + + if (m_goalType != GOALTYPE_NONE) + { + m_routeStartTime = gpGlobals->curtime; + m_bGoalTypeSet = true; + } + else + m_bGoalTypeSet = false; + + m_goalType = goalType; + +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +GoalType_t CAI_Path::GoalType(void) const +{ + return m_goalType; +} + + +//----------------------------------------------------------------------------- + +void CAI_Path::Advance( void ) +{ + if ( CurWaypointIsGoal() ) + return; + + // ------------------------------------------------------- + // If I have another waypoint advance my path + // ------------------------------------------------------- + if (GetCurWaypoint()->GetNext()) + { + AI_Waypoint_t *pNext = GetCurWaypoint()->GetNext(); + + // If waypoint was a node take note of it + if (GetCurWaypoint()->Flags() & bits_WP_TO_NODE) + { + m_iLastNodeReached = GetCurWaypoint()->iNodeID; + } + + delete GetCurWaypoint(); + SetWaypoints(pNext); + + return; + } + // ------------------------------------------------- + // This is an error catch that should *not* happen + // It means a route was created with no goal + // ------------------------------------------------- + else + { + DevMsg( "!!ERROR!! Force end of route with no goal!\n"); + GetCurWaypoint()->ModifyFlags( bits_WP_TO_GOAL, true ); + } + + AssertRouteValid( m_Waypoints.GetFirst() ); +} + + + +//----------------------------------------------------------------------------- +// Purpose: Clears the route and resets all its fields to default values +// Input : +// Output : +//----------------------------------------------------------------------------- +void CAI_Path::Clear( void ) +{ + m_Waypoints.RemoveAll(); + + m_goalType = GOALTYPE_NONE; // Type of goal + m_goalPos = vec3_origin; // Our ultimate goal position + m_bGoalPosSet = false; // Was goal position set + m_bGoalTypeSet = false; // Was goal position set + m_goalFlags = false; + m_vecTargetOffset = vec3_origin; + m_routeStartTime = FLT_MAX; + + m_goalTolerance = 0.0; // How close do we need to get to the goal + // FIXME: split m_goalTolerance into m_buildTolerance and m_moveTolerance, let them be seperatly controllable. + + m_activity = ACT_INVALID; + m_sequence = ACT_INVALID; + m_target = NULL; + + m_arrivalActivity = ACT_INVALID; + m_arrivalSequence = ACT_INVALID; + + m_goalDirectionTarget = NULL; + m_goalDirection = vec3_origin; + + m_goalSpeedTarget = NULL; + m_goalSpeed = -1.0f; // init to an invalid speed + + m_goalStoppingDistance = 0.0; // How close to we want to get to the goal +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +Navigation_t CAI_Path::CurWaypointNavType() const +{ + if (!GetCurWaypoint()) + { + return NAV_NONE; + } + else + { + return GetCurWaypoint()->NavType(); + } +} + +int CAI_Path::CurWaypointFlags() const +{ + if (!GetCurWaypoint()) + { + return 0; + } + else + { + return GetCurWaypoint()->Flags(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the goal's flags +// Output : unsigned +//----------------------------------------------------------------------------- +unsigned CAI_Path::GoalFlags( void ) const +{ + return m_goalFlags; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if current waypoint is my goal +// Input : +// Output : +//----------------------------------------------------------------------------- +bool CAI_Path::CurWaypointIsGoal( void ) const +{ +// Assert( GetCurWaypoint() ); + + if( !GetCurWaypoint() ) + return false; + + + if ( GetCurWaypoint()->Flags() & bits_WP_TO_GOAL ) + { + #ifdef _DEBUG + if (GetCurWaypoint()->GetNext()) + { + DevMsg( "!!ERROR!! Goal is not last waypoint!\n"); + } + if ((GetCurWaypoint()->GetPos() - m_goalPos).Length() > 0.1) + { + DevMsg( "!!ERROR!! Last waypoint isn't in goal position!\n"); + } + #endif + return true; + } + if ( GetCurWaypoint()->Flags() & bits_WP_TO_PATHCORNER ) + { + // UNDONE: Refresh here or somewhere else? + } +#ifdef _DEBUG + if (!GetCurWaypoint()->GetNext()) + { + DevMsg( "!!ERROR!! GetCurWaypoint has no goal!\n"); + } +#endif + + return false; +} + + +//----------------------------------------------------------------------------- +// Computes the goal distance for each waypoint along the route +//----------------------------------------------------------------------------- +void CAI_Path::ComputeRouteGoalDistances(AI_Waypoint_t *pGoalWaypoint) +{ + // The goal distance is the distance from any waypoint to the goal waypoint + + // Backup through the list and calculate distance to goal + AI_Waypoint_t *pPrev; + AI_Waypoint_t *pCurWaypoint = pGoalWaypoint; + pCurWaypoint->flPathDistGoal = 0; + while (pCurWaypoint->GetPrev()) + { + pPrev = pCurWaypoint->GetPrev(); + + float flWaypointDist = ComputePathDistance(pCurWaypoint->NavType(), pPrev->GetPos(), pCurWaypoint->GetPos()); + pPrev->flPathDistGoal = pCurWaypoint->flPathDistGoal + flWaypointDist; + + pCurWaypoint = pPrev; + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +// Input : +// Output : +//----------------------------------------------------------------------------- +CAI_Path::CAI_Path() +{ + m_goalType = GOALTYPE_NONE; // Type of goal + m_goalPos = vec3_origin; // Our ultimate goal position + m_goalTolerance = 0.0; // How close do we need to get to the goal + m_activity = ACT_INVALID; // The activity to use during motion + m_sequence = ACT_INVALID; + m_target = NULL; + m_goalFlags = 0; + m_routeStartTime = FLT_MAX; + m_arrivalActivity = ACT_INVALID; + m_arrivalSequence = ACT_INVALID; + + m_iLastNodeReached = NO_NODE; + + m_waypointTolerance = DEF_WAYPOINT_TOLERANCE; + +} + +CAI_Path::~CAI_Path() +{ + DeleteAll( GetCurWaypoint() ); +} + + |