diff options
Diffstat (limited to 'game/server/tf/nav_mesh/tf_path_follower.cpp')
| -rw-r--r-- | game/server/tf/nav_mesh/tf_path_follower.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/game/server/tf/nav_mesh/tf_path_follower.cpp b/game/server/tf/nav_mesh/tf_path_follower.cpp new file mode 100644 index 0000000..f566330 --- /dev/null +++ b/game/server/tf/nav_mesh/tf_path_follower.cpp @@ -0,0 +1,158 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_path_follower.cpp +// Simplified path following for TF2 +// Author: Michael Booth, November 2010 + +#include "cbase.h" + +#include "NextBotManager.h" +#include "tf_path_follower.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + + +//-------------------------------------------------------------------------------------------------------------- +/** + * Constructor + */ +CTFPathFollower::CTFPathFollower( void ) +{ + m_goal = NULL; + m_minLookAheadRange = 300.0f; +} + + +//-------------------------------------------------------------------------------------------------------------- +CTFPathFollower::~CTFPathFollower() +{ + // allow bots to detach pointer to me + CUtlVector< INextBot * > botVector; + TheNextBots().CollectAllBots( &botVector ); + + for( int i=0; i<botVector.Count(); ++i ) + { + botVector[i]->NotifyPathDestruction( this ); + } +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * When the path is invalidated, the follower is also reset + */ +void CTFPathFollower::Invalidate( void ) +{ + // extend + Path::Invalidate(); + + m_goal = NULL; + MoveCursorToStart(); +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * Invoked when the path is (re)computed (path is valid at the time of this call) + */ +void CTFPathFollower::OnPathChanged( INextBot *bot, Path::ResultType result ) +{ + // start from the beginning + m_goal = FirstSegment(); + MoveCursorToStart(); +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * Move mover along path + */ +void CTFPathFollower::Update( INextBot *bot ) +{ + VPROF_BUDGET( "CTFPathFollower::Update", "NextBot" ); + ILocomotion *mover = bot->GetLocomotionInterface(); + + // track most recent path followed + bot->SetCurrentPath( this ); + + if ( !IsValid() || m_goal == NULL ) + { + return; + } + + // check if we've reached the end of the path + const float nearRange = 25.0f; + if ( mover->IsOnGround() && ( GetEndPosition() - mover->GetFeet() ).AsVector2D().IsLengthLessThan( nearRange ) ) + { + // the end of the path has been reached + mover->GetBot()->OnMoveToSuccess( this ); + + if ( bot->IsDebugging( NEXTBOT_PATH ) ) + { + DevMsg( "CTFPathFollower: OnMoveToSuccess\n" ); + } + + // don't invalidate if OnMoveToSuccess just recomputed a new path + if ( GetAge() > 0.0f ) + { + Invalidate(); + } + + return; + } + + // move along the path + MoveCursorToClosestPosition( mover->GetFeet(), SEEK_AHEAD ); + float myCursorPosition = GetCursorPosition(); + const Path::Data &data = GetCursorData(); + + if ( !data.segmentPrior ) + { + // this shouldn't happen + mover->GetBot()->OnMoveToFailure( this, FAIL_STUCK ); + Invalidate(); + return; + } + + // set goal to be just ahead of wherever we happen to be on the path + m_goal = NextSegment( data.segmentPrior ); + + if ( !m_goal ) + { + m_goal = data.segmentPrior; + } + + // find actual move-to position farther down the path + Vector moveToPos = m_goal->pos; + + // follow point farther down the path to smooth out our movement + for( float ahead = m_minLookAheadRange; ahead > 0.0f; ahead -= 50.0f ) + { + MoveCursor( myCursorPosition, PATH_ABSOLUTE_DISTANCE ); + MoveCursor( ahead, PATH_RELATIVE_DISTANCE ); + + // get path data at this lookahead point + const Path::Data &data = GetCursorData(); + + if ( mover->IsPotentiallyTraversable( mover->GetFeet(), data.pos ) ) + { + moveToPos = data.pos; + break; + } + } + + // move bot along path + mover->FaceTowards( moveToPos ); + mover->Approach( moveToPos ); + + // debug display + if ( bot->IsDebugging( NEXTBOT_PATH ) ) + { + Path::Draw(); + + NDebugOverlay::Cross3D( moveToPos, 5.0f, 150, 150, 255, true, 0.1f ); + NDebugOverlay::Line( bot->GetEntity()->WorldSpaceCenter(), moveToPos, 255, 255, 0, true, 0.1f ); + } +} + |