|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_ai_basenpc.h"
#include "engine/ivdebugoverlay.h"
#if defined( HL2_DLL ) || defined( HL2_EPISODIC )
#include "c_basehlplayer.h"
#endif
#include "death_pose.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define PING_MAX_TIME 2.0
//
// Global accessors for GLaDOS for lighted mouth proxy
//
CHandle<C_BaseAnimating> g_GLaDOSActor;
void SetGLaDOSActor( C_BaseAnimating *pActor ) { g_GLaDOSActor = pActor; }
C_BaseAnimating *GetGLaDOSActor( void ) { return g_GLaDOSActor; }
IMPLEMENT_CLIENTCLASS_DT( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC ) RecvPropInt( RECVINFO( m_lifeState ) ), RecvPropBool( RECVINFO( m_bPerformAvoidance ) ), RecvPropBool( RECVINFO( m_bIsMoving ) ), RecvPropBool( RECVINFO( m_bFadeCorpse ) ), RecvPropInt( RECVINFO ( m_iDeathPose) ), RecvPropInt( RECVINFO( m_iDeathFrame) ), RecvPropInt( RECVINFO( m_iSpeedModRadius ) ), RecvPropInt( RECVINFO( m_iSpeedModSpeed ) ), RecvPropInt( RECVINFO( m_bSpeedModActive ) ), RecvPropBool( RECVINFO( m_bImportanRagdoll ) ), RecvPropFloat( RECVINFO( m_flTimePingEffect ) ), END_RECV_TABLE()
extern ConVar cl_npc_speedmod_intime;
bool NPC_IsImportantNPC( C_BaseAnimating *pAnimating ) { C_AI_BaseNPC *pBaseNPC = pAnimating->MyNPCPointer(); if ( pBaseNPC == NULL ) return false;
return pBaseNPC->ImportantRagdoll(); }
C_AI_BaseNPC::C_AI_BaseNPC() { }
//-----------------------------------------------------------------------------
// Makes ragdolls ignore npcclip brushes
//-----------------------------------------------------------------------------
unsigned int C_AI_BaseNPC::PhysicsSolidMaskForEntity( void ) const { // This allows ragdolls to move through npcclip brushes
if ( !IsRagdoll() ) { return MASK_NPCSOLID; } return MASK_SOLID; }
void C_AI_BaseNPC::ClientThink( void ) { BaseClass::ClientThink();
#ifdef HL2_DLL
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( ShouldModifyPlayerSpeed() == true ) { if ( pPlayer ) { float flDist = (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr();
if ( flDist <= GetSpeedModifyRadius() ) { if ( pPlayer->m_hClosestNPC ) { if ( pPlayer->m_hClosestNPC != this ) { float flDistOther = (pPlayer->m_hClosestNPC->GetAbsOrigin() - pPlayer->GetAbsOrigin()).Length();
//If I'm closer than the other NPC then replace it with myself.
if ( flDist < flDistOther ) { pPlayer->m_hClosestNPC = this; pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat(); } } } else { pPlayer->m_hClosestNPC = this; pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat(); } } } } #endif // HL2_DLL
#ifdef HL2_EPISODIC
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( pPlayer && m_flTimePingEffect > gpGlobals->curtime ) { float fPingEffectTime = m_flTimePingEffect - gpGlobals->curtime; if ( fPingEffectTime > 0.0f ) { Vector vRight, vUp; Vector vMins, vMaxs;
float fFade;
if( fPingEffectTime <= 1.0f ) { fFade = 1.0f - (1.0f - fPingEffectTime); } else { fFade = 1.0f; }
GetRenderBounds( vMins, vMaxs ); AngleVectors (pPlayer->GetAbsAngles(), NULL, &vRight, &vUp ); Vector p1 = GetAbsOrigin() + vRight * vMins.x + vUp * vMins.z; Vector p2 = GetAbsOrigin() + vRight * vMaxs.x + vUp * vMins.z; Vector p3 = GetAbsOrigin() + vUp * vMaxs.z;
int r = 0 * fFade; int g = 255 * fFade; int b = 0 * fFade;
debugoverlay->AddLineOverlay( p1, p2, r, g, b, true, 0.05f ); debugoverlay->AddLineOverlay( p2, p3, r, g, b, true, 0.05f ); debugoverlay->AddLineOverlay( p3, p1, r, g, b, true, 0.05f ); } } #endif
}
void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type ) { BaseClass::OnDataChanged( type );
// Make sure we're thinking
if ( type == DATA_UPDATE_CREATED ) { // If this is the GLaDOS actor, then setup a handle to it, globally
if ( FStrEq( STRING( GetEntityName() ), "@glados" ) || FStrEq( STRING( GetEntityName() ), "@actor_potatos" ) ) { SetGLaDOSActor( this ); MouthInfo().ActivateEnvelope(); } } if ( ( ShouldModifyPlayerSpeed() == true ) || ( m_flTimePingEffect > gpGlobals->curtime ) ) { SetNextClientThink( CLIENT_THINK_ALWAYS ); } }
void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt ) { ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ); GetRagdollCurSequenceWithDeathPose( this, pDeltaBones1, gpGlobals->curtime, m_iDeathPose, m_iDeathFrame ); float ragdollCreateTime = PhysGetSyncCreateTime(); if ( ragdollCreateTime != gpGlobals->curtime ) { // The next simulation frame begins before the end of this frame
// so initialize the ragdoll at that time so that it will reach the current
// position at curtime. Otherwise the ragdoll will simulate forward from curtime
// and pop into the future a bit at this point of transition
ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ); } else { SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ); } }
|