diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/NextBot/Path/NextBotChasePath.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'game/server/NextBot/Path/NextBotChasePath.cpp')
| -rw-r--r-- | game/server/NextBot/Path/NextBotChasePath.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/game/server/NextBot/Path/NextBotChasePath.cpp b/game/server/NextBot/Path/NextBotChasePath.cpp new file mode 100644 index 0000000..1674fc3 --- /dev/null +++ b/game/server/NextBot/Path/NextBotChasePath.cpp @@ -0,0 +1,166 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" + +#include "NextBotChasePath.h" +#include "tier1/fmtstr.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//---------------------------------------------------------------------------------------------- +/** + * Try to cutoff our chase subject + */ +Vector ChasePath::PredictSubjectPosition( INextBot *bot, CBaseEntity *subject ) const +{ + ILocomotion *mover = bot->GetLocomotionInterface(); + + const Vector &subjectPos = subject->GetAbsOrigin(); + + Vector to = subjectPos - bot->GetPosition(); + to.z = 0.0f; + float flRangeSq = to.LengthSqr(); + + // don't lead if subject is very far away + float flLeadRadiusSq = GetLeadRadius(); + flLeadRadiusSq *= flLeadRadiusSq; + if ( flRangeSq > flLeadRadiusSq ) + return subjectPos; + + // Normalize in place + float range = sqrt( flRangeSq ); + to /= ( range + 0.0001f ); // avoid divide by zero + + // estimate time to reach subject, assuming maximum speed + float leadTime = 0.5f + ( range / ( mover->GetRunSpeed() + 0.0001f ) ); + + // estimate amount to lead the subject + Vector lead = leadTime * subject->GetAbsVelocity(); + lead.z = 0.0f; + + if ( DotProduct( to, lead ) < 0.0f ) + { + // the subject is moving towards us - only pay attention + // to his perpendicular velocity for leading + Vector2D to2D = to.AsVector2D(); + to2D.NormalizeInPlace(); + + Vector2D perp( -to2D.y, to2D.x ); + + float enemyGroundSpeed = lead.x * perp.x + lead.y * perp.y; + + lead.x = enemyGroundSpeed * perp.x; + lead.y = enemyGroundSpeed * perp.y; + } + + // compute our desired destination + Vector pathTarget = subjectPos + lead; + + // validate this destination + + // don't lead through walls + if ( lead.LengthSqr() > 36.0f ) + { + float fraction; + if ( !mover->IsPotentiallyTraversable( subjectPos, pathTarget, ILocomotion::IMMEDIATELY, &fraction ) ) + { + // tried to lead through an unwalkable area - clip to walkable space + pathTarget = subjectPos + fraction * ( pathTarget - subjectPos ); + } + } + + // don't lead over cliffs + CNavArea *leadArea = NULL; + +#ifdef NEED_GPGLOBALS_SERVERCOUNT_TO_DO_THIS + CBaseCombatCharacter *pBCC = subject->MyCombatCharacterPointer(); + if ( pBCC && CloseEnough( pathTarget, subjectPos, 3.0 ) ) + { + pathTarget = subjectPos; + leadArea = pBCC->GetLastKnownArea(); // can return null? + } + else + { + struct CacheEntry_t + { + CacheEntry_t() : pArea(NULL) {} + Vector target; + CNavArea *pArea; + }; + + static int iServer; + static CacheEntry_t cache[4]; + static int iNext; + int i; + + bool bFound = false; + if ( iServer != gpGlobals->serverCount ) + { + for ( i = 0; i < ARRAYSIZE(cache); i++ ) + { + cache[i].pArea = NULL; + } + iServer = gpGlobals->serverCount; + } + else + { + for ( i = 0; i < ARRAYSIZE(cache); i++ ) + { + if ( cache[i].pArea && CloseEnough( cache[i].target, pathTarget, 2.0 ) ) + { + pathTarget = cache[i].target; + leadArea = cache[i].pArea; + bFound = true; + break; + } + } + } + + if ( !bFound ) + { + leadArea = TheNavMesh->GetNearestNavArea( pathTarget ); + if ( leadArea ) + { + cache[iNext].target = pathTarget; + cache[iNext].pArea = leadArea; + iNext = ( iNext + 1 ) % ARRAYSIZE( cache ); + } + } + } +#else + leadArea = TheNavMesh->GetNearestNavArea( pathTarget ); +#endif + + + if ( !leadArea || leadArea->GetZ( pathTarget.x, pathTarget.y ) < pathTarget.z - mover->GetMaxJumpHeight() ) + { + // would fall off a cliff + return subjectPos; + } + + /** This needs more thought - it is preventing bots from using dropdowns + if ( mover->HasPotentialGap( subjectPos, pathTarget, &fraction ) ) + { + // tried to lead over a cliff - clip to safe region + pathTarget = subjectPos + fraction * ( pathTarget - subjectPos ); + } + */ + + return pathTarget; +} + +// if the victim is a player, poke them so they know they're being chased +void DirectChasePath::NotifyVictim( INextBot *me, CBaseEntity *victim ) +{ + CBaseCombatCharacter *pBCCVictim = ToBaseCombatCharacter( victim ); + if ( !pBCCVictim ) + return; + + pBCCVictim->OnPursuedBy( me ); +}
\ No newline at end of file |