De/First Person Ragdolls

In den meisten Multiplayer Source Mods wechselt die Sicht von Firstperson zu Thirdperson wenn der Spieler stirbt. Die folgende einfache Codeänderung gibt dem Spieler die Option nach dem Tod durch die Augen seiner Spielfigur zu sehen.
== Vorraussetzungen ==
Damit der Code funktioniert muss das Playermodel ein Attachment (eyes) besitzen, dieses repräsentiert die Stelle wo sich im Playermodel die Augen befinden. Die HL2 Playermodels haben bereits eines, aber für deine eigenen musst du es via und hinzufügen.
== Codeänderungen ==
Der folgende Code ist für Mods die auf den Code von HL2DM basieren ausgelegt, sollten aber mit ein paar Änderungen auch woanders funktionieren.
=== c_hl2mp_player.cpp ===
Weil der Code client-seitig ist öffnen wir cl_dll\hl2mp\c_hl2mp_player.cpp.
Zuerst fügen wir ein Konsolenkommando hinzu womit wir die Firstperson sich nach dem Tod aktivieren und deaktivieren können.
Dieser Code sollte oben in der Datei neben den anderen Konsolenkommandos plaziert werden.
static ConVar cl_fp_ragdoll ( "cl_fp_ragdoll", "1", FCVAR_ARCHIVE, "Firstperson nach Tod erlauben" );
static ConVar cl_fp_ragdoll_auto ( "cl_fp_ragdoll_auto", "1", FCVAR_ARCHIVE, "Automatisch zu Thirdperson wechseln wenn nötig" );
Der nächste Schritt ist, dass wir die CalcView Funktion editieren.
Diese Funktion überprüft ob der Spieler tot ist, wenn ja wechselt er zur Thirdperson.
In unserem Fall fügen wir den Code für unsere Firstpersonansicht hinzu:
void C_HL2MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov )
{
	// Ueberprüfung ob wir tot sind
	if ( m_lifeState != LIFE_ALIVE && !IsObserver() )
	{
		// Firstperson
		if ( cl_fp_ragdoll.GetBool() && m_hRagdoll.Get() )
		{
			// pointer zum Spieler
			C_HL2MPRagdoll *pRagdoll = (C_HL2MPRagdoll*)m_hRagdoll.Get();
			// Die Quelle und Winkel der Augen
			pRagdoll->GetAttachment( pRagdoll->LookupAttachment( "eyes" ), eyeOrigin, eyeAngles );
			Vector vForward; 
			AngleVectors( eyeAngles, &vForward );
			if ( cl_fp_ragdoll_auto.GetBool() )
			{
				// DM: Firstperson nicht benutzen wenn etwas den Blick versperrt (z.B. eine Mauer)
				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; // ueber den Spieler schauen, nicht hindurch
		}
		BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
		eyeOrigin = origin;
		Vector vForward; 
		AngleVectors( eyeAngles, &vForward );
		VectorNormalize( vForward );
		VectorMA( origin, -CHASE_CAM_DISTANCE, 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 );
}
Wenn cl_fp_ragdoll_auto an ist wird also automatisch zur Thirdperson gewechselt wenn nicht viel zu sehen ist. (Man z.B. vor einer Wand liegt.)
== Kleine Probleme ==
Manchmal kann es vorkommen das der Kopf des Spielers so nah an einer Fläche liegt, dass man auf die andere Seite sehen kann. Das ist weil die Augen (das "Eyes" Attachment) dicht an einer Fläche ist.
Das könntest du vermeiden, indem du das Gewicht des models änderst und es so natürlicher fällt. Und indem du den Kopf in Nähe von Nase und Augenbrauen im physikalischen Model vergrößerst.