You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
6.6 KiB
246 lines
6.6 KiB
//========= 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; |
|
}
|
|
|