From ece1a612ced93d068b8f4743789052921ef5e521 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 27 Oct 2021 23:59:27 -0500 Subject: [PATCH] Integrated custom cover hints into base AI movement code --- sp/src/game/server/BaseAnimatingOverlay.cpp | 15 +++++++++++-- sp/src/game/server/BaseAnimatingOverlay.h | 6 +++-- sp/src/game/server/ai_basenpc.cpp | 25 +++++++++++++++++++++ sp/src/game/server/ai_basenpc_schedule.cpp | 18 ++++++++++++--- sp/src/game/server/ai_motor.cpp | 20 ++++++++++++++--- sp/src/game/server/ai_motor.h | 3 +++ sp/src/game/server/ai_navigator.cpp | 17 +++++++++++--- sp/src/game/server/ai_tacticalservices.cpp | 5 +++++ 8 files changed, 96 insertions(+), 13 deletions(-) diff --git a/sp/src/game/server/BaseAnimatingOverlay.cpp b/sp/src/game/server/BaseAnimatingOverlay.cpp index d04ff89d..06bf690e 100644 --- a/sp/src/game/server/BaseAnimatingOverlay.cpp +++ b/sp/src/game/server/BaseAnimatingOverlay.cpp @@ -1095,9 +1095,9 @@ void CBaseAnimatingOverlay::SetLayerNoRestore( int iLayer, bool bNoRestore ) } -#ifdef MAPBASE // From Alien Swarm SDK +#ifdef MAPBASE //----------------------------------------------------------------------------- -// Purpose: +// From Alien Swarm SDK //----------------------------------------------------------------------------- void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents ) { @@ -1113,6 +1113,17 @@ void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents ) m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_NOEVENTS; } } + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBaseAnimatingOverlay::IsLayerFinished( int iLayer ) +{ + if (!IsValidLayer( iLayer )) + return true; + + return m_AnimOverlay[iLayer].m_bSequenceFinished; +} #endif diff --git a/sp/src/game/server/BaseAnimatingOverlay.h b/sp/src/game/server/BaseAnimatingOverlay.h index d7b882f8..38ee7ed1 100644 --- a/sp/src/game/server/BaseAnimatingOverlay.h +++ b/sp/src/game/server/BaseAnimatingOverlay.h @@ -181,8 +181,10 @@ public: void SetLayerAutokill( int iLayer, bool bAutokill ); void SetLayerLooping( int iLayer, bool bLooping ); void SetLayerNoRestore( int iLayer, bool bNoRestore ); -#ifdef MAPBASE // From Alien Swarm SDK - void SetLayerNoEvents( int iLayer, bool bNoEvents ); +#ifdef MAPBASE + void SetLayerNoEvents( int iLayer, bool bNoEvents ); // From Alien Swarm SDK + + bool IsLayerFinished( int iLayer ); #endif Activity GetLayerActivity( int iLayer ); diff --git a/sp/src/game/server/ai_basenpc.cpp b/sp/src/game/server/ai_basenpc.cpp index 16faea3a..02a8b725 100644 --- a/sp/src/game/server/ai_basenpc.cpp +++ b/sp/src/game/server/ai_basenpc.cpp @@ -2598,7 +2598,11 @@ bool CAI_BaseNPC::FValidateHintType ( CAI_Hint *pHint ) Activity CAI_BaseNPC::GetHintActivity( short sHintType, Activity HintsActivity ) { if ( HintsActivity != ACT_INVALID ) +#ifdef MAPBASE + return TranslateActivity( HintsActivity ); // Always translate the activity +#else return HintsActivity; +#endif return ACT_IDLE; } @@ -6866,7 +6870,12 @@ void CAI_BaseNPC::ResolveActivityToSequence(Activity NewActivity, int &iSequence translatedActivity = TranslateActivity( NewActivity, &weaponActivity ); +#ifdef MAPBASE + // Cover cases where TranslateActivity() returns a sequence by using ACT_SCRIPT_CUSTOM_MOVE + if ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE || translatedActivity == ACT_SCRIPT_CUSTOM_MOVE ) +#else if ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE ) +#endif { iSequence = GetScriptCustomMoveSequence(); } @@ -7339,6 +7348,15 @@ void CAI_BaseNPC::OnChangeActivity( Activity eNewActivity ) eNewActivity == ACT_WALK ) { Stand(); + +#ifdef MAPBASE + // Unlock custom cover nodes + if (GetHintNode() && GetHintNode()->HintType() == HINT_TACTICAL_COVER_CUSTOM && HasMemory(bits_MEMORY_INCOVER)) + { + GetHintNode()->Unlock( GetHintDelay( GetHintNode()->HintType() ) ); + SetHintNode( NULL ); + } +#endif } } @@ -9358,6 +9376,13 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget ) return UTIL_VecToYaw( vecProjection - GetLocalOrigin() ); } +#ifdef MAPBASE + // Allow hint nodes to override the yaw without needing to control AI + else if (GetHintNode() && GetHintNode()->OverridesNPCYaw( this )) + { + return GetHintNode()->Yaw(); + } +#endif else { return UTIL_VecToYaw ( vecTarget - GetLocalOrigin() ); diff --git a/sp/src/game/server/ai_basenpc_schedule.cpp b/sp/src/game/server/ai_basenpc_schedule.cpp index bcb54c81..e0c9feef 100644 --- a/sp/src/game/server/ai_basenpc_schedule.cpp +++ b/sp/src/game/server/ai_basenpc_schedule.cpp @@ -980,11 +980,12 @@ bool CAI_BaseNPC::FindCoverFromEnemy( bool bNodesOnly, float flMinDistance, floa // FIXME: add to goal if (GetHintNode()) { - GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) ); #ifdef MAPBASE - if (GetHintNode()->GetIgnoreFacing() != HIF_NO) -#endif + GetHintNode()->NPCHandleStartNav( this, true ); +#else + GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) ); GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() ); +#endif } return true; @@ -3431,6 +3432,17 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) // If the yaw is locked, this function will not act correctly Assert( GetMotor()->IsYawLocked() == false ); +#ifdef MAPBASE + if ( GetHintNode() && GetHintNode()->OverridesNPCYaw( this ) ) + { + // If the yaw is supposed to use that of a hint node, chain to TASK_FACE_HINTNODE + GetMotor()->SetIdealYaw( GetHintNode()->Yaw() ); + GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw + ChainRunTask( TASK_FACE_HINTNODE, pTask->flTaskData ); + break; + } +#endif + Vector vecEnemyLKP = GetEnemyLKP(); if (!FInAimCone( vecEnemyLKP )) { diff --git a/sp/src/game/server/ai_motor.cpp b/sp/src/game/server/ai_motor.cpp index c9c6fb8e..f54432ff 100644 --- a/sp/src/game/server/ai_motor.cpp +++ b/sp/src/game/server/ai_motor.cpp @@ -14,6 +14,9 @@ #include "ai_basenpc.h" #include "ai_localnavigator.h" #include "ai_moveprobe.h" +#ifdef MAPBASE +#include "ai_hint.h" +#endif #include "saverestore_utlvector.h" // memdbgon must be the last include file in a .cpp file!!! @@ -836,9 +839,20 @@ void CAI_Motor::MoveFacing( const AILocalMoveGoal_t &move ) { // FIXME: move this up to navigator so that path goals can ignore these overrides. Vector dir; - float flInfluence = GetFacingDirection( dir ); - dir = move.facing * (1 - flInfluence) + dir * flInfluence; - VectorNormalize( dir ); + +#ifdef MAPBASE + if (IsDeceleratingToGoal() && (GetOuter()->GetHintNode() /*|| GetOuter()->m_hOpeningDoor*/)) + { + // Don't let the facing queue interfere with arrival direction in important cases + dir = move.facing; + } + else +#endif + { + float flInfluence = GetFacingDirection( dir ); + dir = move.facing * (1 - flInfluence) + dir * flInfluence; + VectorNormalize( dir ); + } // ideal facing direction float idealYaw = UTIL_AngleMod( UTIL_VecToYaw( dir ) ); diff --git a/sp/src/game/server/ai_motor.h b/sp/src/game/server/ai_motor.h index b5f5d297..29c05f84 100644 --- a/sp/src/game/server/ai_motor.h +++ b/sp/src/game/server/ai_motor.h @@ -87,6 +87,9 @@ public: const Vector & GetCurVel() const { return m_vecVelocity; } virtual float OverrideMaxYawSpeed( Activity activity ) { return -1; } +#ifdef MAPBASE + virtual +#endif bool IsDeceleratingToGoal() const { return false; } //--------------------------------- diff --git a/sp/src/game/server/ai_navigator.cpp b/sp/src/game/server/ai_navigator.cpp index 9d6ae06a..59c06822 100644 --- a/sp/src/game/server/ai_navigator.cpp +++ b/sp/src/game/server/ai_navigator.cpp @@ -999,12 +999,23 @@ int CAI_Navigator::GetArrivalSequence( int curSequence ) activity = ACT_IDLE; } - sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), curSequence ); + Activity translatedActivity = GetOuter()->TranslateActivity( activity ); + sequence = GetOuter()->SelectWeightedSequence( translatedActivity, curSequence ); if ( sequence == ACT_INVALID ) { - DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() ); - sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence ); +#ifdef MAPBASE + if ( translatedActivity == ACT_SCRIPT_CUSTOM_MOVE ) + { + // ACT_SCRIPT_CUSTOM_MOVE allows activity translation to resolve into specific sequences + sequence = GetOuter()->GetScriptCustomMoveSequence(); + } + else +#endif + { + DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() ); + sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence ); + } } Assert( sequence != ACT_INVALID ); GetPath()->SetArrivalSequence( sequence ); diff --git a/sp/src/game/server/ai_tacticalservices.cpp b/sp/src/game/server/ai_tacticalservices.cpp index 87399c4f..8bcdcc08 100644 --- a/sp/src/game/server/ai_tacticalservices.cpp +++ b/sp/src/game/server/ai_tacticalservices.cpp @@ -411,7 +411,12 @@ int CAI_TacticalServices::FindCoverNode(const Vector &vNearPos, const Vector &vT // -------------------------------------------------------- pNode->Lock( 1.0 ); +#ifdef MAPBASE + if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW + || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_CUSTOM ) ) +#else if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW ) ) +#endif { if ( GetOuter()->GetHintNode() ) {