void CRagdoll::Init( C_BaseEntity *ent, CStudioHdr *pstudiohdr, const Vector &forceVector, int forceBone, const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float dt, bool bFixedConstraints ) { ragdollparams_t params; params.pGameData = static_cast<void *>( ent ); params.modelIndex = ent->GetModelIndex(); params.pCollide = modelinfo->GetVCollide( params.modelIndex ); params.pStudioHdr = pstudiohdr; params.forceVector = forceVector; params.forceBoneIndex = forceBone; params.forcePosition.Init(); params.pCurrentBones = pCurrentBonePosition; params.jointFrictionScale = 1.0; params.allowStretch = false; params.fixedConstraints = bFixedConstraints; RagdollCreate( m_ragdoll, params, physenv ); ent->VPhysicsSetObject( NULL ); ent->VPhysicsSetObject( m_ragdoll.list[0].pObject ); // Mark the ragdoll as debris. //ent->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); ent->SetCollisionGroup( COLLISION_GROUP_WEAPON ); RagdollApplyAnimationAsVelocity( m_ragdoll, pDeltaBones0, pDeltaBones1, dt ); RagdollActivate( m_ragdoll, params.pCollide, ent->GetModelIndex() ); // It's moving now... m_flLastOriginChangeTime = gpGlobals->curtime; // So traces hit it. ent->AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); if ( !m_ragdoll.listCount ) return; BuildRagdollBounds( ent ); for ( int i = 0; i < m_ragdoll.listCount; i++ ) { g_pPhysSaveRestoreManager->AssociateModel( m_ragdoll.list[i].pObject, ent->GetModelIndex() ); } #if RAGDOLL_VISUALIZE memcpy( m_savedBone1, &pDeltaBones0[0], sizeof(matrix3x4_t) * pstudiohdr->numbones() ); memcpy( m_savedBone2, &pDeltaBones1[0], sizeof(matrix3x4_t) * pstudiohdr->numbones() ); memcpy( m_savedBone3, &pCurrentBonePosition[0], sizeof(matrix3x4_t) * pstudiohdr->numbones() ); #endif }
bool RagdollCreate( ragdoll_t &ragdoll, const ragdollparams_t ¶ms, IPhysicsCollision *pPhysCollision, IPhysicsEnvironment *pPhysEnv, IPhysicsSurfaceProps *pSurfaceDatabase ) { RagdollCreateObjects( pPhysCollision, pPhysEnv, pSurfaceDatabase, ragdoll, params ); if ( !ragdoll.listCount ) return false; int forceBone = params.forceBoneIndex; int i; float totalMass = 0; for ( i = 0; i < ragdoll.listCount; i++ ) { totalMass += ragdoll.list[i].pObject->GetMass(); } totalMass = max(totalMass,1); // distribute half to the forced bone, half to the rest of the model Vector nudgeForce = params.forceVector; if ( forceBone >= 0 && forceBone <= ragdoll.listCount ) { nudgeForce *= 0.5; ragdoll.list[forceBone].pObject->ApplyForceCenter( nudgeForce ); } else if ( params.forcePosition != vec3_origin ) { for ( i = 0; i < ragdoll.listCount; i++ ) { float scale = ragdoll.list[i].pObject->GetMass() / totalMass; ragdoll.list[i].pObject->ApplyForceOffset( scale * nudgeForce, params.forcePosition ); } nudgeForce.Init(); } RagdollApplyAnimationAsVelocity( ragdoll, params.pPrevBones, params.pCurrentBones, params.boneDt ); for ( i = 0; i < ragdoll.listCount; i++ ) { float scale = ragdoll.list[i].pObject->GetMass() / totalMass; ragdoll.list[i].pObject->ApplyForceCenter( scale * nudgeForce ); PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_PART_OF_RAGDOLL ); } return true; }