Example #1
0
void C_HL2MPRagdoll::CreateHL2MPRagdoll( void )
{
	// First, initialize all our data. If we have the player's entity on our client,
	// then we can make ourselves start out exactly where the player is.
	C_HL2MP_Player *pPlayer = dynamic_cast< C_HL2MP_Player* >( m_hPlayer.Get() );
	
	if ( pPlayer && !pPlayer->IsDormant() )
	{
		// move my current model instance to the ragdoll's so decals are preserved.
		pPlayer->SnatchModelInstance( this );

		VarMapping_t *varMap = GetVarMapping();

		// Copy all the interpolated vars from the player entity.
		// The entity uses the interpolated history to get bone velocity.
		bool bRemotePlayer = (pPlayer != C_BasePlayer::GetLocalPlayer());			
		if ( bRemotePlayer )
		{
			Interp_Copy( pPlayer );

			SetAbsAngles( pPlayer->GetRenderAngles() );
			GetRotationInterpolator().Reset();

			m_flAnimTime = pPlayer->m_flAnimTime;
			SetSequence( pPlayer->GetSequence() );
			m_flPlaybackRate = pPlayer->GetPlaybackRate();
		}
		else
		{
			// This is the local player, so set them in a default
			// pose and slam their velocity, angles and origin
			SetAbsOrigin( m_vecRagdollOrigin );
			
			SetAbsAngles( pPlayer->GetRenderAngles() );

			SetAbsVelocity( m_vecRagdollVelocity );

			int iSeq = pPlayer->GetSequence();
			if ( iSeq == -1 )
			{
				Assert( false );	// missing walk_lower?
				iSeq = 0;
			}
			
			SetSequence( iSeq );	// walk_lower, basic pose
			SetCycle( 0.0 );

			Interp_Reset( varMap );
		}		
	}
	else
	{
		// overwrite network origin so later interpolation will
		// use this position
		SetNetworkOrigin( m_vecRagdollOrigin );

		SetAbsOrigin( m_vecRagdollOrigin );
		SetAbsVelocity( m_vecRagdollVelocity );

		Interp_Reset( GetVarMapping() );
		
	}

	SetModelIndex( m_nModelIndex );

	// Make us a ragdoll..
	m_nRenderFX = kRenderFxRagdoll;

	matrix3x4_t boneDelta0[MAXSTUDIOBONES];
	matrix3x4_t boneDelta1[MAXSTUDIOBONES];
	matrix3x4_t currentBones[MAXSTUDIOBONES];
	const float boneDt = 0.05f;

	if ( pPlayer && !pPlayer->IsDormant() )
	{
		pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
	}
	else
	{
		GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
	}

	InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
}
Example #2
0
void C_SDKRagdoll::CreateRagdoll()
{
	// First, initialize all our data. If we have the player's entity on our client,
	// then we can make ourselves start out exactly where the player is.
	C_SDKPlayer *pPlayer = dynamic_cast< C_SDKPlayer* >( m_hPlayer.Get() );

	if ( pPlayer && !pPlayer->IsDormant() )
	{
		// move my current model instance to the ragdoll's so decals are preserved.
		pPlayer->SnatchModelInstance( this );

		VarMapping_t *varMap = GetVarMapping();

		// Copy all the interpolated vars from the player entity.
		// The entity uses the interpolated history to get bone velocity.
		if ( !pPlayer->IsLocalPlayer() && pPlayer->IsInterpolationEnabled() )
		{
			Interp_Copy( pPlayer );

			SetAbsAngles( pPlayer->GetRenderAngles() );
			GetRotationInterpolator().Reset();

			m_flAnimTime = pPlayer->m_flAnimTime;
			SetSequence( pPlayer->GetSequence() );
			m_flPlaybackRate = pPlayer->GetPlaybackRate();
		}
		else
		{
			// This is the local player, so set them in a default
			// pose and slam their velocity, angles and origin
			SetAbsOrigin( m_vecRagdollOrigin );

			SetAbsAngles( pPlayer->GetRenderAngles() );

			SetAbsVelocity( m_vecRagdollVelocity );

			int iSeq = LookupSequence( "RagdollSpawn" );	// hax, find a neutral standing pose
			if ( iSeq == -1 )
			{
				Assert( false );	// missing look_idle?
				iSeq = 0;
			}
			
			SetSequence( iSeq );	// look_idle, basic pose
			SetCycle( 0.0 );

			Interp_Reset( varMap );
		}		

		m_nBody = pPlayer->GetBody();
	}
	else
	{
		// overwrite network origin so later interpolation will
		// use this position
		SetNetworkOrigin( m_vecRagdollOrigin );

		SetAbsOrigin( m_vecRagdollOrigin );
		SetAbsVelocity( m_vecRagdollVelocity );

		Interp_Reset( GetVarMapping() );

	}

	SetModelIndex( m_nModelIndex );
	
	// Turn it into a ragdoll.
	if ( cl_ragdoll_physics_enable.GetInt() )
	{
		// Make us a ragdoll..
		m_nRenderFX = kRenderFxRagdoll;

		matrix3x4_t boneDelta0[MAXSTUDIOBONES];
		matrix3x4_t boneDelta1[MAXSTUDIOBONES];
		matrix3x4_t currentBones[MAXSTUDIOBONES];
		const float boneDt = 0.05f;

		if ( pPlayer && pPlayer == C_BasePlayer::GetLocalPlayer() )
		{
			pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
		}
		else
		{
			GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
		}

		InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
	}
	else
	{
		ClientLeafSystem()->SetRenderGroup( GetRenderHandle(), RENDER_GROUP_TRANSLUCENT_ENTITY );
	}		

	// Fade out the ragdoll in a while
	StartFadeOut( cl_ragdoll_fade_time.GetFloat() );
	SetNextClientThink( gpGlobals->curtime + 5.0f );
}
void C_GENPCRagdoll::CreateRagdoll( void )
{
	// First, initialize all our data. If we have the player's entity on our client,
	// then we can make ourselves start out exactly where the player is.
	C_AI_BaseNPC *pNPC = dynamic_cast< C_AI_BaseNPC* >( m_hNPC.Get() );

	// Cache away our skin before we start meddling (setting it later down)
	int skin = 0;
	if ( pNPC )
		skin = pNPC->GetSkin();

	if ( pNPC && !pNPC->IsDormant() )
	{
		// move my current model instance to the ragdoll's so decals are preserved.
		pNPC->SnatchModelInstance( this );

		// Copy all the interpolated vars from the player entity.
		// The entity uses the interpolated history to get bone velocity.
		Interp_Copy( pNPC );

		SetAbsAngles( pNPC->GetRenderAngles() );
		GetRotationInterpolator().Reset();

		m_flAnimTime = pNPC->m_flAnimTime;
		SetSequence( pNPC->GetSequence() );
		m_flPlaybackRate = pNPC->GetPlaybackRate();
	}
	else
	{
		// overwrite network origin so later interpolation will
		// use this position
		SetNetworkOrigin( m_vecRagdollOrigin );

		SetAbsOrigin( m_vecRagdollOrigin );
		SetAbsVelocity( m_vecRagdollVelocity );

		Interp_Reset( GetVarMapping() );
	}

	SetModelIndex( m_nModelIndex );

	// Make us a ragdoll..
	m_nRenderFX = kRenderFxRagdoll;

	matrix3x4_t boneDelta0[MAXSTUDIOBONES];
	matrix3x4_t boneDelta1[MAXSTUDIOBONES];
	matrix3x4_t currentBones[MAXSTUDIOBONES];
	const float boneDt = 0.05f;

	if ( pNPC && !pNPC->IsDormant() )
	{
		pNPC->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
	}
	else
	{
		GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
	}

	// Finally reset our skin
	m_nSkin = skin;

	InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
}
void C_ClientPartialRagdoll::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName )
{
	BaseClass::ImpactTrace( pTrace, iDamageType, pCustomImpactName );

	// client entities have the network index -1 so lots of effects don't work easily
	if ( BloodColor() != DONT_BLEED )
	{
		const char *pszDecalName = NULL;

		switch ( BloodColor() )
		{
		case BLOOD_COLOR_RED:
			pszDecalName = "Blood";
			break;
		}

		int index = decalsystem->GetDecalIndexForName( pszDecalName );
		Vector vecDir = pTrace->endpos - pTrace->startpos;
		if ( vecDir.LengthSqr() > FLT_EPSILON )
		{
			vecDir.NormalizeInPlace();
		}

		if ( index >= 0 )
		{
			SetShrinkingEnabled( false );
			InvalidateBoneCache();
			SetupBones( NULL, -1, BONE_USED_BY_ANYTHING, gpGlobals->curtime );

			// add decal to model
			AddDecal( pTrace->startpos, pTrace->endpos, pTrace->endpos, pTrace->hitbox,
						index, false, *pTrace );

			SetShrinkingEnabled( true );
			InvalidateBoneCache();
		}

		// add decal to world
		trace_t tr;
		UTIL_TraceLine( pTrace->endpos, pTrace->endpos + vecDir * 35.0f, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );

		UTIL_BloodDecalTrace( &tr, BloodColor() );
		if ( ShouldCreateBloodParticles() )
		{
			UTIL_BloodImpact( pTrace->endpos, -vecDir, BloodColor(), 5 );
		}
	}

	if ( m_bReleaseRagdoll || m_bFadingOut )
		return;

	const float flGibbingChance = ( ( iDamageType & DMG_BLAST ) != 0 ) ?
		gstring_gibbing_explosion_chance.GetFloat() : gstring_gibbing_chance.GetFloat();
	const bool bSniperImpact = ( iDamageType & DMG_SNIPER ) != 0;

	if ( !bSniperImpact && RandomFloat() > flGibbingChance / 100.0f )
		return;

	CStudioHdr *pHdr = GetModelPtr();

	if ( pHdr == NULL )
		return;

	int iStudioBone = ConvertPhysBoneToStudioBone( this, pTrace->physicsbone );
	const bool bExplosionImpact = ( iDamageType & DMG_BLAST ) != 0;

	// if the hit bone is a valid studio bone and we know that this bone
	// is drawn as a normal bone (not shrunken)
	if ( iStudioBone >= 0
		&& m_normalBones.IsBitSet( iStudioBone )
		|| bExplosionImpact )
	{
		CUtlVector< ragdollparams_partial_t > gibModels;

		// we've been analysed already so use the known hit group
		// and try recusive splitting
		GibbingParamsRecursive_t params;
		params.pHdr = pHdr;
		params.pszHitBone = ( iStudioBone >= 0 && !bExplosionImpact ) ? pHdr->pBone( iStudioBone )->pszName() : NULL;
		params.pszParentName = STRING( m_strRecursiveParent );
		params.pszRootBone = ( m_iBranchRootBone >= 0 && m_iBranchRootBone < pHdr->numbones() )
			? pHdr->pBone( m_iBranchRootBone )->pszName() : NULL;
		params.pJointBones = &m_jointBones;

		const char *pszParentSplitBone;

		// find a suitable joint to cut
		if ( C_GibConfig::GetInstance()->GetGibsForGroup( params, gibModels, &pszParentSplitBone )
			|| bExplosionImpact && C_GibConfig::GetInstance()->GetRandomGibsForGroup( params, gibModels, &pszParentSplitBone ) )
		{
			int iSplitboneIndex = Studio_BoneIndexByName( pHdr, pszParentSplitBone );

			// don't do cutting if we cut this joint in the past
			// or if this joint is our current branch root
			if ( iSplitboneIndex < 0
				|| m_jointBones.IsBitSet( iSplitboneIndex )
				|| m_iBranchRootBone == iSplitboneIndex )
				return;

			matrix3x4_t boneDelta0[MAXSTUDIOBONES];
			matrix3x4_t boneDelta1[MAXSTUDIOBONES];
			matrix3x4_t currentBones[MAXSTUDIOBONES];
			const float boneDt = 0.1f;

			// setup bones without shrinking to position the new gibs
			SetShrinkingEnabled( false );
			GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
			SetShrinkingEnabled( true );

			InvalidateBoneCache();

			// create the new gibmodels
			FOR_EACH_VEC( gibModels, i )
			{
				ragdollparams_partial_t &partial = gibModels[ i ];

				// add old trunk joints
				for ( int iBit = m_jointBones.FindNextSetBit( 0 );
					iBit >= 0; iBit = m_jointBones.FindNextSetBit( iBit + 1 ) )
				{
					if ( m_iBranchRootBone == iBit )
						continue;

					const char *pszName = pHdr->pBone( iBit )->pszName();

					partial.trunkBones.AddToTail( pszName );
				}

				// if we create a trunk from an existing branch
				// we have to propagate the branch root bone
				if ( partial.rootBone.IsEmpty()
					&& m_iBranchRootBone >= 0 )
				{
					partial.rootBone = pHdr->pBone( m_iBranchRootBone )->pszName();
				}

				C_BaseAnimating *pGib = CreateRagdollCopy( false );
				C_ClientPartialRagdoll *pRecursiveRagdoll = dynamic_cast< C_ClientPartialRagdoll* >( pGib );
				Assert( pRecursiveRagdoll );

				// apply force and propagate cut information
				if ( pRecursiveRagdoll != NULL )
				{
					pRecursiveRagdoll->SetRecursiveGibData( STRING( m_strRecursiveParent ), STRING( m_strRecursiveGoreName ),
						STRING( m_strRecursiveGoreMaterialName ) );
					pRecursiveRagdoll->SetShrinkingEnabled( true );

					Vector vecDelta = pTrace->endpos - pTrace->startpos;
					if ( vecDelta.LengthSqr() <= FLT_EPSILON )
					{
						vecDelta = RandomVector( -1, 1 );
					}
					vecDelta.NormalizeInPlace();

					pRecursiveRagdoll->m_vecForce = vecDelta * RandomFloat( 15000.0f, 35000.0f );
					pRecursiveRagdoll->m_nForceBone = pTrace->physicsbone;

					pRecursiveRagdoll->SetBloodColor( BloodColor() );
					pRecursiveRagdoll->m_jointBones.Or( m_jointBones, &pRecursiveRagdoll->m_jointBones );

					//FOR_EACH_VEC( m_Gore, i )
					//{
					//	const int iBone = m_Gore[ i ].m_iBone;

					//	if ( iBone >= 0 && iBone == m_iBranchRootBone )
					//	{

					//	}
					//	pRecursiveRagdoll->m_Gore.AddToTail( m_Gore[ i ] );
					//	m_Gore.Remove( i );
					//	i--;
					//}
				}

				pGib->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt, false, &partial );

				if ( bExplosionImpact
					&& RandomFloat() <= gstring_gibbing_explosion_recursive_chance.GetFloat() / 100.0f )
				{
					pGib->ImpactTrace( pTrace, iDamageType, pCustomImpactName );
				}

				if ( BloodColor() == BLOOD_COLOR_RED
					&& ( !pRecursiveRagdoll || !pRecursiveRagdoll->m_bReleaseRagdoll )
					&& ShouldCreateBloodParticles() )
				{
					Assert( pszParentSplitBone != NULL );

					DispatchGibParticle( pGib, pszParentSplitBone, bExplosionImpact, BloodColor() );
				}
			}
Example #5
0
void C_CFRagdoll::CreateRagdoll()
{
	// First, initialize all our data. If we have the player's entity on our client,
	// then we can make ourselves start out exactly where the player is.
	C_CFPlayer *pPlayer = dynamic_cast< C_CFPlayer* >( m_hPlayer.Get() );

	if ( pPlayer && !pPlayer->IsDormant() )
	{
		// move my current model instance to the ragdoll's so decals are preserved.
		pPlayer->SnatchModelInstance( this );

		VarMapping_t *varMap = GetVarMapping();

		// Copy all the interpolated vars from the player entity.
		// The entity uses the interpolated history to get bone velocity.
		bool bRemotePlayer = (pPlayer != C_BasePlayer::GetLocalPlayer());			
		if ( bRemotePlayer )
		{
			Interp_Copy( pPlayer );

			SetAbsAngles( pPlayer->GetRenderAngles() );
			GetRotationInterpolator().Reset();

			m_flAnimTime = pPlayer->m_flAnimTime;
			SetSequence( pPlayer->GetSequence() );
			m_flPlaybackRate = pPlayer->GetPlaybackRate();
		}
		else
		{
			// This is the local player, so set them in a default
			// pose and slam their velocity, angles and origin
			SetAbsOrigin( m_vecRagdollOrigin );

			SetAbsAngles( pPlayer->GetRenderAngles() );

			SetAbsVelocity( m_vecRagdollVelocity );

			int iSeq = LookupSequence( "idle" );
			if ( iSeq == -1 )
			{
				Assert( false );	// missing walk_lower?
				iSeq = 0;
			}

			SetSequence( iSeq );	// walk_lower, basic pose
			SetCycle( 0.0 );

			Interp_Reset( varMap );
		}		
	}
	else
	{
		// overwrite network origin so later interpolation will
		// use this position
		SetNetworkOrigin( m_vecRagdollOrigin );

		SetAbsOrigin( m_vecRagdollOrigin );
		SetAbsVelocity( m_vecRagdollVelocity );

		Interp_Reset( GetVarMapping() );

	}

	if (pPlayer)
	{
		SetModelIndex( m_nModelIndex );
		m_nSkin = pPlayer->m_nSkin;
		SetBodygroup(1, pPlayer->m_bIsDecapitated);
	}

	// Turn it into a ragdoll.
	if ( cl_ragdoll_physics_enable.GetBool() )
	{
		// Make us a ragdoll..
		m_nRenderFX = kRenderFxRagdoll;

		matrix3x4_t boneDelta0[MAXSTUDIOBONES];
		matrix3x4_t boneDelta1[MAXSTUDIOBONES];
		matrix3x4_t currentBones[MAXSTUDIOBONES];
		const float boneDt = 0.05f;

		// We have to make sure that we're initting this client ragdoll off of the same model.
		// GetRagdollInitBoneArrays uses the *player* Hdr, which may be a different model than
		// the ragdoll Hdr, if we try to create a ragdoll in the same frame that the player
		// changes their player model.
		CStudioHdr *pRagdollHdr = GetModelPtr();
		CStudioHdr *pPlayerHdr = NULL;
		if ( pPlayer )
			pPlayerHdr = pPlayer->GetModelPtr();

		bool bChangedModel = false;

		if ( pRagdollHdr && pPlayerHdr )
		{
			bChangedModel = pRagdollHdr->GetVirtualModel() != pPlayerHdr->GetVirtualModel();

			Assert( !bChangedModel && "C_CFRagdoll::CreateRagdoll: Trying to create ragdoll with a different model than the player it's based on" );
		}

		if ( pPlayer && !pPlayer->IsDormant() && !bChangedModel && pPlayerHdr )
		{
			pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
		}
		else
		{
			GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
		}

		InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
	}
	SetNextClientThink( CLIENT_THINK_ALWAYS );
}