mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2024-12-25 14:25:32 +03:00
Optional support for fired bullets notifying targets (currently only used for NPC companion speech)
This commit is contained in:
parent
85c1f7d113
commit
9070d9a844
@ -1265,6 +1265,38 @@ void CAI_PlayerAlly::OnKilledNPC( CBaseCombatCharacter *pKilled )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_PlayerAlly::OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd )
|
||||
{
|
||||
BaseClass::OnEnemyRangeAttackedMe( pEnemy, vecDir, vecEnd );
|
||||
|
||||
if ( IRelationType( pEnemy ) <= D_FR )
|
||||
{
|
||||
AI_CriteriaSet modifiers;
|
||||
ModifyOrAppendEnemyCriteria( modifiers, pEnemy );
|
||||
|
||||
Vector vecEntDir = (pEnemy->EyePosition() - EyePosition());
|
||||
float flDot = DotProduct( vecEntDir.Normalized(), vecDir );
|
||||
modifiers.AppendCriteria( "shot_dot", CNumStr( flDot ) );
|
||||
|
||||
if (GetLastDamageTime() == gpGlobals->curtime)
|
||||
modifiers.AppendCriteria( "missed", "0" );
|
||||
else
|
||||
modifiers.AppendCriteria( "missed", "1" );
|
||||
|
||||
// Check if they're out of ammo
|
||||
if ( pEnemy->IsCombatCharacter() && pEnemy->MyCombatCharacterPointer()->GetActiveWeapon() && pEnemy->MyCombatCharacterPointer()->GetActiveWeapon()->Clip1() <= 0 )
|
||||
modifiers.AppendCriteria( "last_attack", "1" );
|
||||
else
|
||||
modifiers.AppendCriteria( "last_attack", "0" );
|
||||
|
||||
SpeakIfAllowed( TLK_TAKING_FIRE, modifiers );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_PlayerAlly::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
|
||||
{
|
||||
|
@ -322,6 +322,10 @@ public:
|
||||
//---------------------------------
|
||||
void OnKilledNPC( CBaseCombatCharacter *pKilled );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd );
|
||||
#endif
|
||||
|
||||
//---------------------------------
|
||||
// Damage handling
|
||||
//---------------------------------
|
||||
|
@ -263,6 +263,10 @@ public:
|
||||
|
||||
virtual bool CanBecomeServerRagdoll( void ) { return true; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual void OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd ) {}
|
||||
#endif
|
||||
|
||||
// -----------------------
|
||||
// Damage
|
||||
// -----------------------
|
||||
|
@ -7734,6 +7734,93 @@ void CBasePlayer::ResetAutoaim( void )
|
||||
m_fOnTarget = false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar player_debug_probable_aim_target( "player_debug_probable_aim_target", "0", FCVAR_CHEAT, "" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity *CBasePlayer::GetProbableAimTarget( const Vector &vecSrc, const Vector &vecDir )
|
||||
{
|
||||
trace_t tr;
|
||||
CBaseEntity *pIgnore = NULL;
|
||||
if (IsInAVehicle())
|
||||
pIgnore = GetVehicleEntity();
|
||||
|
||||
CTraceFilterSkipTwoEntities traceFilter( this, pIgnore, COLLISION_GROUP_NONE );
|
||||
|
||||
// Based on dot product and distance
|
||||
// If we aim directly at something, only return it if there's not a larger entity slightly off-center
|
||||
// Should be weighted based on whether an entity is a NPC, etc.
|
||||
CBaseEntity *pBestEnt = NULL;
|
||||
float flBestWeight = 0.0f;
|
||||
for (CBaseEntity *pEntity = UTIL_EntitiesInPVS( this, NULL ); pEntity; pEntity = UTIL_EntitiesInPVS( this, pEntity ))
|
||||
{
|
||||
// Combat characters can be unviewable if they just died
|
||||
if (!pEntity->IsViewable() && !pEntity->IsCombatCharacter())
|
||||
continue;
|
||||
|
||||
if (pEntity == this || pEntity->GetMoveParent() == this || pEntity == GetVehicleEntity())
|
||||
continue;
|
||||
|
||||
Vector vecEntDir = (pEntity->EyePosition() - vecSrc);
|
||||
float flDot = DotProduct( vecEntDir.Normalized(), vecDir);
|
||||
|
||||
if (flDot < m_flFieldOfView)
|
||||
continue;
|
||||
|
||||
// Make sure we can see it
|
||||
UTIL_TraceLine( vecSrc, pEntity->EyePosition(), MASK_SHOT, &traceFilter, &tr );
|
||||
if (tr.m_pEnt != pEntity)
|
||||
{
|
||||
if (pEntity->IsCombatCharacter())
|
||||
{
|
||||
// Trace between centers as well just in case our eyes are blocked
|
||||
UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_SHOT, &traceFilter, &tr );
|
||||
if (tr.m_pEnt != pEntity)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
float flWeight = flDot - (vecEntDir.LengthSqr() / Square( 2048.0f ));
|
||||
|
||||
if (pEntity->IsCombatCharacter())
|
||||
{
|
||||
// Hostile NPCs are more likely targets
|
||||
if (IRelationType( pEntity ) <= D_FR)
|
||||
flWeight += 0.5f;
|
||||
}
|
||||
else if (pEntity->GetFlags() & FL_AIMTARGET)
|
||||
{
|
||||
// FL_AIMTARGET is often used for props like explosive barrels
|
||||
flWeight += 0.25f;
|
||||
}
|
||||
|
||||
if (player_debug_probable_aim_target.GetBool())
|
||||
{
|
||||
float flWeightClamped = 1.0f - RemapValClamped( flWeight, -2.0f, 2.0f, 0.0f, 1.0f );
|
||||
pEntity->EntityText( 0, UTIL_VarArgs( "%f", flWeight ), 2.0f, flWeightClamped * 255.0f, 255.0f, flWeightClamped * 255.0f, 255 );
|
||||
}
|
||||
|
||||
if (flWeight > flBestWeight)
|
||||
{
|
||||
pBestEnt = pEntity;
|
||||
flBestWeight = flWeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (player_debug_probable_aim_target.GetBool())
|
||||
{
|
||||
Msg( "Best probable aim target is %s\n", pBestEnt->GetDebugName() );
|
||||
NDebugOverlay::EntityBounds( pBestEnt, 255, 100, 0, 0, 2.0f );
|
||||
}
|
||||
|
||||
return pBestEnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ==========================================================================
|
||||
// > Weapon stuff
|
||||
// ==========================================================================
|
||||
|
@ -608,6 +608,11 @@ public:
|
||||
virtual bool ShouldAutoaim( void );
|
||||
void SetTargetInfo( Vector &vecSrc, float flDist );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Tries to figure out what the player is trying to aim at
|
||||
CBaseEntity *GetProbableAimTarget( const Vector &vecSrc, const Vector &vecDir );
|
||||
#endif
|
||||
|
||||
void SetViewEntity( CBaseEntity *pEntity );
|
||||
CBaseEntity *GetViewEntity( void ) { return m_hViewEntity; }
|
||||
|
||||
|
@ -83,6 +83,10 @@ ConVar ai_shot_bias_min( "ai_shot_bias_min", "-1.0", FCVAR_REPLICATED );
|
||||
ConVar ai_shot_bias_max( "ai_shot_bias_max", "1.0", FCVAR_REPLICATED );
|
||||
ConVar ai_debug_shoot_positions( "ai_debug_shoot_positions", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
|
||||
|
||||
#if defined(MAPBASE) && defined(GAME_DLL)
|
||||
ConVar ai_shot_notify_targets( "ai_shot_notify_targets", "0", FCVAR_NONE, "Allows fired bullets to notify the NPCs and players they are targeting, regardless of whether they hit them or not. Can be used for custom AI and speech." );
|
||||
#endif
|
||||
|
||||
// Utility func to throttle rate at which the "reasonable position" spew goes out
|
||||
static double s_LastEntityReasonableEmitTime;
|
||||
bool CheckEmitReasonablePhysicsSpew()
|
||||
@ -2081,6 +2085,25 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info )
|
||||
CTakeDamageInfo dmgInfo( this, pAttacker, flCumulativeDamage, nDamageType );
|
||||
gamestats->Event_WeaponHit( pPlayer, info.m_bPrimaryAttack, pPlayer->GetActiveWeapon()->GetClassname(), dmgInfo );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ai_shot_notify_targets.GetBool() )
|
||||
{
|
||||
if ( IsPlayer() )
|
||||
{
|
||||
// Look for probable target to notify of attack
|
||||
CBaseEntity *pAimTarget = static_cast<CBasePlayer*>(this)->GetProbableAimTarget( info.m_vecSrc, info.m_vecDirShooting );
|
||||
if ( pAimTarget && pAimTarget->IsCombatCharacter() )
|
||||
{
|
||||
pAimTarget->MyCombatCharacterPointer()->OnEnemyRangeAttackedMe( this, vecDir, vecEnd );
|
||||
}
|
||||
}
|
||||
else if ( GetEnemy() && GetEnemy()->IsCombatCharacter() )
|
||||
{
|
||||
GetEnemy()->MyCombatCharacterPointer()->OnEnemyRangeAttackedMe( this, vecDir, vecEnd );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user