First Person Ragdolls

In most Source multi-player mods, when a player dies the view switches from first to third person perspective. This following simple code change allows you to give the player an option of seeing things from the ragdolls perspective, in short letting it see the world through the ragdoll's own eyes.
== Pre-requisites ==
For the code to work, your player model needs an attachment called eyes which represents where on the ragdoll the players view will come from. In the case of the default HL2 human characters they already have one but if your player model doesn't you can add it in via the QC File and HLMV.
== Code changes ==
The following is for mods based on HL2DM but should work with others with some minor editing.
=== c_hl2mp_player.cpp ===
As this code is clientside, we're making edits to the file client\hl2mp\c_hl2mp_player.cpp.
The first part is to add a console command to enable or disable first person ragdolls. This should be placed at the top of the file along with the other console commands:
static ConVar cl_fp_ragdoll ( "cl_fp_ragdoll", "1", FCVAR_ARCHIVE, "Allow first person ragdolls" );
static ConVar cl_fp_ragdoll_auto ( "cl_fp_ragdoll_auto", "1", FCVAR_ARCHIVE, "Autoswitch to ragdoll thirdperson-view when necessary" );
The next step is to edit the CalcView function. This function checks to see if the player is dead and if so, switches to third person view. In this case we're adding the extra code for first person ragdolls:
void C_HL2MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov )
{
	// if we're dead, we want to deal with first or third person ragdolls.
	if ( m_lifeState != LIFE_ALIVE && !IsObserver() )
	{
		// First person ragdolls
		if ( cl_fp_ragdoll.GetBool() && m_hRagdoll.Get() )
		{
			// pointer to the ragdoll
			C_HL2MPRagdoll *pRagdoll = (C_HL2MPRagdoll*)m_hRagdoll.Get();
			// gets its origin and angles
			pRagdoll->GetAttachment( pRagdoll->LookupAttachment( "eyes" ), eyeOrigin, eyeAngles );
			Vector vForward; 
			AngleVectors( eyeAngles, &vForward );
			if ( cl_fp_ragdoll_auto.GetBool() )
			{
				// DM: Don't use first person view when we are very close to something
				trace_t tr;
				UTIL_TraceLine( eyeOrigin, eyeOrigin + ( vForward * 10000 ), MASK_ALL, pRagdoll, COLLISION_GROUP_NONE, &tr );
				if ( (!(tr.fraction < 1) || (tr.endpos.DistTo(eyeOrigin) > 25)) )
					return;
			}
			else
				return;
		}
		eyeOrigin = vec3_origin;
		eyeAngles = vec3_angle;
		Vector origin = EyePosition();
		IRagdoll *pRagdoll = GetRepresentativeRagdoll();
		if ( pRagdoll )
		{
			origin = pRagdoll->GetRagdollOrigin();
			origin.z += VEC_DEAD_VIEWHEIGHT.z; // look over ragdoll, not through
		}
		BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
		eyeOrigin = origin;
		Vector vForward; 
		AngleVectors( eyeAngles, &vForward );
		VectorNormalize( vForward );
		VectorMA( origin, -CHASE_CAM_DISTANCE_MAX, vForward, eyeOrigin );
		Vector WALL_MIN( -WALL_OFFSET, -WALL_OFFSET, -WALL_OFFSET );
		Vector WALL_MAX( WALL_OFFSET, WALL_OFFSET, WALL_OFFSET );
		trace_t trace; // clip against world
		// HACK don't recompute positions while doing RayTrace
		C_BaseEntity::EnableAbsRecomputations( false );
		UTIL_TraceHull( origin, eyeOrigin, WALL_MIN, WALL_MAX, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace );
		C_BaseEntity::EnableAbsRecomputations( true );
		if (trace.fraction < 1.0)
		{
			eyeOrigin = trace.endpos;
		}
		return;
	}
	BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
}
When cl_fp_ragdoll_auto is also on, the code automatically switches to third person when there isn't much to see.
== Minor issues ==
Occasionally you may find that when the players head is close to a surface it clips through allowing you to see through to the other side. This is often because the eye origin is extremely close or even through the surface itself.
Often this can be tracked down to the default HL2 physics model which is very loose and in the case of the head, quite small. You may find that you can reduce this happening by editing the physics model's weights and constraints so that the ragdoll falls in a more natural way. Also making the head part of the physics model a little larger near the nose and brow often helps in stopping the eye attachment from penetrating a surface.
== See also ==
First Person Ragdolls in Singleplayer
Category:Programming