hl2_src-leak-2017/src/game/client/tf2/c_ragdoll_shadow.cpp

247 lines
6.6 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "model_types.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "solidsetdefaults.h"
#include "c_basetfplayer.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
CPhysCollide *PhysCreateBbox( const Vector &mins, const Vector &maxs );
extern CSolidSetDefaults g_SolidSetup;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_RagdollShadow : public C_BaseAnimating
{
DECLARE_CLASS( C_RagdollShadow, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_RagdollShadow( void );
~C_RagdollShadow( void );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
virtual int DrawModel( int flags );
public:
IPhysicsObject *VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation );
void VPhysicsSetObject( IPhysicsObject *pPhysics );
void VPhysicsDestroyObject( void );
int m_nPlayer;
EHANDLE m_hPlayer;
IPhysicsObject *m_pPhysicsObject;
IPhysicsSpring *m_pSpring;
};
IMPLEMENT_CLIENTCLASS_DT( C_RagdollShadow, DT_RagdollShadow, CRagdollShadow )
RecvPropInt( RECVINFO( m_nPlayer ) ),
END_RECV_TABLE()
C_RagdollShadow::C_RagdollShadow( void )
{
m_nPlayer = -1;
m_hPlayer = NULL;
m_pPhysicsObject = NULL;
m_pSpring = NULL;
}
C_RagdollShadow::~C_RagdollShadow( void )
{
VPhysicsDestroyObject();
delete m_pSpring;
}
void C_RagdollShadow::VPhysicsDestroyObject( void )
{
if ( m_pPhysicsObject )
{
physenv->DestroyObject( m_pPhysicsObject );
m_pPhysicsObject = NULL;
}
}
// Create a physics thingy based on an existing collision model
IPhysicsObject *PhysModelCreateCustom( C_BaseEntity *pEntity, const CPhysCollide *pModel, const Vector &origin, const QAngle &angles, const char *props )
{
solid_t solid;
solid.params = g_PhysDefaultObjectParams;
solid.params.mass = 85.0f;
solid.params.inertia = 1e24f;
int surfaceProp = -1;
if ( props && props[0] )
{
surfaceProp = physprops->GetSurfaceIndex( props );
}
solid.params.pGameData = static_cast<void *>(pEntity);
IPhysicsObject *pObject = physenv->CreatePolyObject( pModel, surfaceProp, origin, angles, &solid.params );
return pObject;
}
IPhysicsObject *PhysModelCreateRagdoll( C_BaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles )
{
vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex );
if ( !pCollide )
return NULL;
solid_t solid;
memset( &solid, 0, sizeof(solid) );
solid.params = g_PhysDefaultObjectParams;
IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues );
while ( !pParse->Finished() )
{
const char *pBlock = pParse->GetCurrentBlockName();
if ( !strcmpi( pBlock, "solid" ) )
{
pParse->ParseSolid( &solid, &g_SolidSetup );
break;
}
else
{
pParse->SkipBlock();
}
}
physcollision->VPhysicsKeyParserDestroy( pParse );
// collisions are off by default
solid.params.enableCollisions = true;
int surfaceProp = -1;
if ( solid.surfaceprop[0] )
{
surfaceProp = physprops->GetSurfaceIndex( solid.surfaceprop );
}
solid.params.pGameData = static_cast<void *>(pEntity);
solid.params.pName = "ragdoll_player";
IPhysicsObject *pObject = physenv->CreatePolyObject( pCollide->solids[0], surfaceProp, origin, angles, &solid.params );
//PhysCheckAdd( pObject, STRING(pEntity->m_iClassname) );
return pObject;
}
void C_RagdollShadow::VPhysicsSetObject( IPhysicsObject *pPhysics )
{
if ( m_pPhysicsObject && pPhysics )
{
Warning( "C_RagdollShadow::Overwriting physics object!\n" );
}
m_pPhysicsObject = pPhysics;
}
// This creates a vphysics object with a shadow controller that follows the AI
IPhysicsObject *C_RagdollShadow::VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation )
{
CStudioHdr *hdr = GetModelPtr();
if ( !hdr )
{
return NULL;
}
// If this entity already has a physics object, then it should have been deleted prior to making this call.
Assert(!m_pPhysicsObject);
// make sure m_vecOrigin / m_vecAngles are correct
const Vector &origin = GetAbsOrigin();
QAngle angles = GetAbsAngles();
IPhysicsObject *pPhysicsObject = NULL;
if ( GetSolid() == SOLID_BBOX )
{
const char *pSurfaceProps = "flesh";
if ( GetModelIndex() && modelinfo->GetModelType( GetModel() ) == mod_studio )
{
pSurfaceProps = Studio_GetDefaultSurfaceProps( hdr );
}
angles = vec3_angle;
CPhysCollide *pCollide = PhysCreateBbox( WorldAlignMins(), WorldAlignMaxs() );
if ( !pCollide )
return NULL;
pPhysicsObject = PhysModelCreateCustom( this, pCollide, origin, angles, pSurfaceProps );
}
else
{
pPhysicsObject = PhysModelCreateRagdoll( this, GetModelIndex(), origin, angles );
}
VPhysicsSetObject( pPhysicsObject );
pPhysicsObject->SetShadow( 1e4, 1e4, allowPhysicsMovement, allowPhysicsRotation );
pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 );
// PhysAddShadow( this );
return pPhysicsObject;
}
void C_RagdollShadow::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Has to happen *after* the client handle is set
SetNextClientThink( CLIENT_THINK_ALWAYS );
bool bnewentity = (updateType == DATA_UPDATE_CREATED);
if ( bnewentity && ( m_nPlayer != 0 ) )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
Assert( !m_pPhysicsObject );
C_BaseEntity *pl = static_cast< C_BaseEntity * >( cl_entitylist->GetEnt( m_nPlayer ) );
if ( pl )
{
m_hPlayer = pl;
}
m_pPhysicsObject = VPhysicsInitShadow( true, false );
}
if ( m_pPhysicsObject )
{
// Create the spring if we don't have one yet
if ( !m_pSpring )
{
C_BaseTFPlayer *pl = static_cast< C_BaseTFPlayer * >( (C_BaseEntity *)m_hPlayer );
if ( pl && pl->VPhysicsGetObject() )
{
springparams_t spring;
spring.constant = 15000;
spring.damping = 1.0;
spring.naturalLength = 0.0f;
spring.relativeDamping = 100.0f;
VectorCopy( vec3_origin, spring.startPosition );
VectorCopy( vec3_origin, spring.endPosition );
spring.useLocalPositions = true;
m_pSpring = physenv->CreateSpring( m_pPhysicsObject, pl->VPhysicsGetObject(), &spring );
PhysDisableObjectCollisions( m_pPhysicsObject, pl->VPhysicsGetObject() );
}
}
m_pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 );
}
}
void C_RagdollShadow::ClientThink( void )
{
BaseClass::ClientThink();
}
int C_RagdollShadow::DrawModel( int flags )
{
// int drawn = BaseClass::DrawModel( flags );
// return drawn;
return 0;
}