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 )
|
void CAI_PlayerAlly::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
|
||||||
{
|
{
|
||||||
|
@ -322,6 +322,10 @@ public:
|
|||||||
//---------------------------------
|
//---------------------------------
|
||||||
void OnKilledNPC( CBaseCombatCharacter *pKilled );
|
void OnKilledNPC( CBaseCombatCharacter *pKilled );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd );
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
// Damage handling
|
// Damage handling
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
@ -263,6 +263,10 @@ public:
|
|||||||
|
|
||||||
virtual bool CanBecomeServerRagdoll( void ) { return true; }
|
virtual bool CanBecomeServerRagdoll( void ) { return true; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd ) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// Damage
|
// Damage
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
@ -7734,6 +7734,93 @@ void CBasePlayer::ResetAutoaim( void )
|
|||||||
m_fOnTarget = false;
|
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
|
// > Weapon stuff
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -608,6 +608,11 @@ public:
|
|||||||
virtual bool ShouldAutoaim( void );
|
virtual bool ShouldAutoaim( void );
|
||||||
void SetTargetInfo( Vector &vecSrc, float flDist );
|
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 );
|
void SetViewEntity( CBaseEntity *pEntity );
|
||||||
CBaseEntity *GetViewEntity( void ) { return m_hViewEntity; }
|
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_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 );
|
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
|
// Utility func to throttle rate at which the "reasonable position" spew goes out
|
||||||
static double s_LastEntityReasonableEmitTime;
|
static double s_LastEntityReasonableEmitTime;
|
||||||
bool CheckEmitReasonablePhysicsSpew()
|
bool CheckEmitReasonablePhysicsSpew()
|
||||||
@ -2081,6 +2085,25 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info )
|
|||||||
CTakeDamageInfo dmgInfo( this, pAttacker, flCumulativeDamage, nDamageType );
|
CTakeDamageInfo dmgInfo( this, pAttacker, flCumulativeDamage, nDamageType );
|
||||||
gamestats->Event_WeaponHit( pPlayer, info.m_bPrimaryAttack, pPlayer->GetActiveWeapon()->GetClassname(), dmgInfo );
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user