Ru/Legs in Firstperson

Примечание: Работает только в 2007 версии движка( OB )
Это не работает в мультиплеере, потому что заменяет модель thirdperson на модель без рук и головы.
Примечание:Не работает в 2013 версии движка
== Рекомендуется ==
*Valve's Source Engine code ( 2007 ) Single Player.
*Программы для 3д моделирование ( XSI, 3DS Max, Blender etc )
*Модели ( доступные здесь Here ) <-- Исправленные текстуры
*Мозг
==Система анимации.==
Вам необходимо использовать код Malortie для работы.
Создайте два файла в shared папке вашего мода.
Первый это "singleplayer_animstate.h".
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Single Player animation state 'handler'. This utility is used
// to evaluate the pose parameter value based on the direction
// and speed of the player.
//
//====================================================================================//
#ifndef SINGLEPLAYER_ANIMSTATE_H
#define SINGLEPLAYER_ANIMSTATE_H
#ifdef _WIN32
#pragma once
#endif
#include "cbase.h"
#ifdef CLIENT_DLL
#include "c_baseplayer.h"
#else
#include "player.h"
#endif
class CSinglePlayerAnimState
{
public:
 enum
 {
 TURN_NONE = 0,
 TURN_LEFT,
 TURN_RIGHT
 };
 CSinglePlayerAnimState( CBasePlayer *pPlayer );
 void Init( CBasePlayer *pPlayer );
 Activity BodyYawTranslateActivity( Activity activity );
 void Update();
 const QAngle& GetRenderAngles();
 
 void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] );
 CBasePlayer *GetBasePlayer();
 void Release();
private:
 void GetOuterAbsVelocity( Vector& vel );
 int ConvergeAngles( float goal,float maxrate, float dt, float& current );
 void EstimateYaw( void );
 void ComputePoseParam_BodyYaw( void );
 void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr );
 void ComputePoseParam_BodyLookYaw( void );
 void ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr );
 void ComputePlaybackRate();
 CBasePlayer *m_pPlayer;
 float m_flGaitYaw;
 float m_flStoredCycle;
 float m_flGoalFeetYaw;
 float m_flCurrentFeetYaw;
 float m_flCurrentTorsoYaw;
 float m_flLastYaw;
 float m_flLastTurnTime;
 int m_nTurningInPlace;
 QAngle m_angRender;
 float m_flTurnCorrectionTime;
};
CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer );
#endif // SINGLEPLAYER_ANIMSTATE_H
Файл завершен добавляем второй файл "singleplayer_animstate.cpp"
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Single Player animation state 'handler'. This utility is used
// to evaluate the pose parameter value based on the direction
// and speed of the player.
//
//====================================================================================//
#include "cbase.h"
#include "singleplayer_animstate.h"
#include "tier0/vprof.h"
#include "animation.h"
#include "studio.h"
#include "apparent_velocity_helper.h"
#include "utldict.h"
#include "filesystem.h"
extern ConVar mp_facefronttime, mp_feetyawrate, mp_ik;
#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer )
{
 MDLCACHE_CRITICAL_SECTION();
 CSinglePlayerAnimState *pState = new CSinglePlayerAnimState( pPlayer );
 pState->Init(pPlayer);
 return pState;
}
// Below this many degrees, slow down turning rate linearly
#define FADE_TURN_DEGREES 45.0f
// After this, need to start turning feet
#define MAX_TORSO_ANGLE 90.0f
// Below this amount, don't play a turning animation/perform IK
#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
//static ConVar tf2_feetyawrunscale( "tf2_feetyawrunscale", "2", FCVAR_REPLICATED, "Multiplier on tf2_feetyawrate to allow turning faster when running." );
extern ConVar sv_backspeed;
extern ConVar mp_feetyawrate;
extern ConVar mp_facefronttime;
extern ConVar mp_ik;
CSinglePlayerAnimState::CSinglePlayerAnimState( CBasePlayer *pPlayer ): m_pPlayer( pPlayer )
{
 m_flGaitYaw = 0.0f;
 m_flGoalFeetYaw = 0.0f;
 m_flCurrentFeetYaw = 0.0f;
 m_flCurrentTorsoYaw = 0.0f;
 m_flLastYaw = 0.0f;
 m_flLastTurnTime = 0.0f;
 m_flTurnCorrectionTime = 0.0f;
 m_pPlayer = NULL;
};
void CSinglePlayerAnimState::Init( CBasePlayer *pPlayer )
{
 m_pPlayer = pPlayer;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::Update()
{
 m_angRender = GetBasePlayer()->GetLocalAngles();
 ComputePoseParam_BodyYaw();
 ComputePoseParam_BodyPitch(GetBasePlayer()->GetModelPtr());
 ComputePoseParam_BodyLookYaw();
 ComputePoseParam_HeadPitch(GetBasePlayer()->GetModelPtr());
 ComputePlaybackRate();
}
void CSinglePlayerAnimState::Release()
{
 delete this;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePlaybackRate()
{
 // Determine ideal playback rate
 Vector vel;
 GetOuterAbsVelocity( vel );
 float speed = vel.Length2D();
 bool isMoving = ( speed > 0.5f ) ? true : false;
 float maxspeed = GetBasePlayer()->GetSequenceGroundSpeed( GetBasePlayer()->GetSequence() );
 
 if ( isMoving && ( maxspeed > 0.0f ) )
 {
 float flFactor = 1.0f;
 // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below
 GetBasePlayer()->SetPlaybackRate( ( speed * flFactor ) / maxspeed );
 // BUG BUG:
 // This stuff really should be m_flPlaybackRate = speed / m_flGroundSpeed
 }
 else
 {
 GetBasePlayer()->SetPlaybackRate( 1.0f );
 }
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : CBasePlayer
//-----------------------------------------------------------------------------
CBasePlayer *CSinglePlayerAnimState::GetBasePlayer()
{
 return m_pPlayer;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : dt -
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::EstimateYaw( void )
{
 float dt = gpGlobals->frametime;
 if ( !dt )
 {
 return;
 }
 Vector est_velocity;
 QAngle angles;
 GetOuterAbsVelocity( est_velocity );
 angles = GetBasePlayer()->GetLocalAngles();
 if ( est_velocity[1] == 0 && est_velocity[0] == 0 )
 {
 float flYawDiff = angles[YAW] - m_flGaitYaw;
 flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;
 if (flYawDiff > 180)
 flYawDiff -= 360;
 if (flYawDiff < -180)
 flYawDiff += 360;
 if (dt < 0.25)
 flYawDiff *= dt * 4;
 else
 flYawDiff *= dt;
 m_flGaitYaw += flYawDiff;
 m_flGaitYaw = m_flGaitYaw - (int)(m_flGaitYaw / 360) * 360;
 }
 else
 {
 m_flGaitYaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);
 if (m_flGaitYaw > 180)
 m_flGaitYaw = 180;
 else if (m_flGaitYaw < -180)
 m_flGaitYaw = -180;
 }
}
//-----------------------------------------------------------------------------
// Purpose: Override for backpeddling
// Input : dt -
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_BodyYaw( void )
{
 int iYaw = GetBasePlayer()->LookupPoseParameter( "move_yaw" );
 if ( iYaw < 0 )
 return;
 // view direction relative to movement
 float flYaw;
 EstimateYaw();
 QAngle angles = GetBasePlayer()->GetLocalAngles();
 float ang = angles[ YAW ];
 if ( ang > 180.0f )
 {
 ang -= 360.0f;
 }
 else if ( ang < -180.0f )
 {
 ang += 360.0f;
 }
 // calc side to side turning
 flYaw = ang - m_flGaitYaw;
 // Invert for mapping into 8way blend
 flYaw = -flYaw;
 flYaw = flYaw - (int)(flYaw / 360) * 360;
 if (flYaw < -180)
 {
 flYaw = flYaw + 360;
 }
 else if (flYaw > 180)
 {
 flYaw = flYaw - 360;
 }
 
 GetBasePlayer()->SetPoseParameter( iYaw, flYaw );
#ifndef CLIENT_DLL
 //Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
 GetBasePlayer()->SetLocalAngles( QAngle( GetBasePlayer()->EyeAngles().x, m_flCurrentFeetYaw, 0 ) );
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
{
 // Get pitch from v_angle
 float flPitch = GetBasePlayer()->GetLocalAngles()[ PITCH ];
 if ( flPitch > 180.0f )
 {
 flPitch -= 360.0f;
 }
 flPitch = clamp( flPitch, -90, 90 );
 QAngle absangles = GetBasePlayer()->GetAbsAngles();
 absangles.x = 0.0f;
 m_angRender = absangles;
 // See if we have a blender for pitch
 GetBasePlayer()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : goal -
// maxrate -
// dt -
// current -
// Output : int
//-----------------------------------------------------------------------------
int CSinglePlayerAnimState::ConvergeAngles( float goal,float maxrate, float dt, float& current )
{
 int direction = TURN_NONE;
 float anglediff = goal - current;
 float anglediffabs = fabs( anglediff );
 anglediff = AngleNormalize( anglediff );
 float scale = 1.0f;
 if ( anglediffabs <= FADE_TURN_DEGREES )
 {
 scale = anglediffabs / FADE_TURN_DEGREES;
 // Always do at least a bit of the turn ( 1% )
 scale = clamp( scale, 0.01f, 1.0f );
 }
 float maxmove = maxrate * dt * scale;
 if ( fabs( anglediff ) < maxmove )
 {
 current = goal;
 }
 else
 {
 if ( anglediff > 0 )
 {
 current += maxmove;
 direction = TURN_LEFT;
 }
 else
 {
 current -= maxmove;
 direction = TURN_RIGHT;
 }
 }
 current = AngleNormalize( current );
 return direction;
}
void CSinglePlayerAnimState::ComputePoseParam_BodyLookYaw( void )
{
 QAngle absangles = GetBasePlayer()->GetAbsAngles();
 absangles.y = AngleNormalize( absangles.y );
 m_angRender = absangles;
 // See if we even have a blender for pitch
 int upper_body_yaw = GetBasePlayer()->LookupPoseParameter( "aim_yaw" );
 if ( upper_body_yaw < 0 )
 {
 return;
 }
 // Assume upper and lower bodies are aligned and that we're not turning
 float flGoalTorsoYaw = 0.0f;
 int turning = TURN_NONE;
 float turnrate = 360.0f;
 Vector vel;
 
 GetOuterAbsVelocity( vel );
 bool isMoving = ( vel.Length() > 1.0f ) ? true : false;
 if ( !isMoving )
 {
 // Just stopped moving, try and clamp feet
 if ( m_flLastTurnTime <= 0.0f )
 {
 m_flLastTurnTime = gpGlobals->curtime;
 m_flLastYaw = GetBasePlayer()->EyeAngles().y;
 // Snap feet to be perfectly aligned with torso/eyes
 m_flGoalFeetYaw = GetBasePlayer()->EyeAngles().y;
 m_flCurrentFeetYaw = m_flGoalFeetYaw;
 m_nTurningInPlace = TURN_NONE;
 }
 // If rotating in place, update stasis timer
 if ( m_flLastYaw != GetBasePlayer()->EyeAngles().y )
 {
 m_flLastTurnTime = gpGlobals->curtime;
 m_flLastYaw = GetBasePlayer()->EyeAngles().y;
 }
 if ( m_flGoalFeetYaw != m_flCurrentFeetYaw )
 {
 m_flLastTurnTime = gpGlobals->curtime;
 }
 turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw );
 QAngle eyeAngles = GetBasePlayer()->EyeAngles();
 QAngle vAngle = GetBasePlayer()->GetLocalAngles();
 // See how far off current feetyaw is from true yaw
 float yawdelta = GetBasePlayer()->EyeAngles().y - m_flCurrentFeetYaw;
 yawdelta = AngleNormalize( yawdelta );
 bool rotated_too_far = false;
 float yawmagnitude = fabs( yawdelta );
 // If too far, then need to turn in place
 if ( yawmagnitude > 45 )
 {
 rotated_too_far = true;
 }
 // Standing still for a while, rotate feet around to face forward
 // Or rotated too far
 // FIXME: Play an in place turning animation
 if ( rotated_too_far ||
 ( gpGlobals->curtime > m_flLastTurnTime + mp_facefronttime.GetFloat() ) )
 {
 m_flGoalFeetYaw = GetBasePlayer()->EyeAngles().y;
 m_flLastTurnTime = gpGlobals->curtime;
 /* float yd = m_flCurrentFeetYaw - m_flGoalFeetYaw;
 if ( yd > 0 )
 {
 m_nTurningInPlace = TURN_RIGHT;
 }
 else if ( yd < 0 )
 {
 m_nTurningInPlace = TURN_LEFT;
 }
 else
 {
 m_nTurningInPlace = TURN_NONE;
 }
 turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw );
 yawdelta = GetBasePlayer()->EyeAngles().y - m_flCurrentFeetYaw;*/
 }
 // Snap upper body into position since the delta is already smoothed for the feet
 flGoalTorsoYaw = yawdelta;
 m_flCurrentTorsoYaw = flGoalTorsoYaw;
 }
 else
 {
 m_flLastTurnTime = 0.0f;
 m_nTurningInPlace = TURN_NONE;
 m_flCurrentFeetYaw = m_flGoalFeetYaw = GetBasePlayer()->EyeAngles().y;
 flGoalTorsoYaw = 0.0f;
 m_flCurrentTorsoYaw = GetBasePlayer()->EyeAngles().y - m_flCurrentFeetYaw;
 }
 if ( turning == TURN_NONE )
 {
 m_nTurningInPlace = turning;
 }
 if ( m_nTurningInPlace != TURN_NONE )
 {
 // If we're close to finishing the turn, then turn off the turning animation
 if ( fabs( m_flCurrentFeetYaw - m_flGoalFeetYaw ) < MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION )
 {
 m_nTurningInPlace = TURN_NONE;
 }
 }
 // Rotate entire body into position
 absangles = GetBasePlayer()->GetAbsAngles();
 absangles.y = m_flCurrentFeetYaw;
 m_angRender = absangles;
 GetBasePlayer()->SetPoseParameter( upper_body_yaw, clamp( m_flCurrentTorsoYaw, -60.0f, 60.0f ) );
 /*
 // FIXME: Adrian, what is this?
 int body_yaw = GetBasePlayer()->LookupPoseParameter( "body_yaw" );
 if ( body_yaw >= 0 )
 {
 GetBasePlayer()->SetPoseParameter( body_yaw, 30 );
 }
 */
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr )
{
 // Get pitch from v_angle
 int iHeadPitch = GetBasePlayer()->LookupPoseParameter("head_pitch");
 float flPitch = GetBasePlayer()->EyeAngles()[PITCH];
 if ( flPitch > 180.0f )
 {
 flPitch -= 360.0f;
 }
 flPitch = clamp( flPitch, -90, 90 );
 QAngle absangles = GetBasePlayer()->GetAbsAngles();
 absangles.x = 0.0f;
 m_angRender = absangles;
 GetBasePlayer()->SetPoseParameter( pStudioHdr, iHeadPitch, flPitch );
}
 
//-----------------------------------------------------------------------------
// Purpose:
// Input : activity -
// Output : Activity
//-----------------------------------------------------------------------------
Activity CSinglePlayerAnimState::BodyYawTranslateActivity( Activity activity )
{
 // Not even standing still, sigh
 if ( activity != ACT_IDLE )
 return activity;
 // Not turning
 switch ( m_nTurningInPlace )
 {
 default:
 case TURN_NONE:
 return activity;
 /*
 case TURN_RIGHT:
 return ACT_TURNRIGHT45;
 case TURN_LEFT:
 return ACT_TURNLEFT45;
 */
 case TURN_RIGHT:
 case TURN_LEFT:
 return mp_ik.GetBool() ? ACT_TURN : activity;
 }
 Assert( 0 );
 return activity;
}
const QAngle& CSinglePlayerAnimState::GetRenderAngles()
{
 return m_angRender;
}
void CSinglePlayerAnimState::GetOuterAbsVelocity( Vector& vel )
{
#if defined( CLIENT_DLL )
 GetBasePlayer()->EstimateAbsVelocity( vel );
#else
 vel = GetBasePlayer()->GetAbsVelocity();
#endif
}
==Полная реализация ==
В "c_baseplayer.cpp" иищем следующие функцию:
bool IsInFreezeCam( void )
И внизу добавляем:
bool IsInEye( void )
{
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_IN_EYE )
	return true;
}
Потом, в этом файле ищем:
bool C_BasePlayer::ShouldDraw()
И заменяем на:
bool C_BasePlayer::ShouldDraw()
{
	return BaseClass::ShouldDraw();
}
static ConVar cl_legs("cl_legs", "1", FCVAR_CHEAT, "Enable or disable player leg rendering", true, 0, true, 1);
static ConVar cl_legs_origin_shift("cl_legs_origin_shift", "-17", FCVAR_CHEAT, "Amount in game units to shift the player model relative to the direction the player is facing");
static ConVar cl_legs_clip_height("cl_legs_clip_height", "0", FCVAR_CHEAT, "Amount in game units of the player model to render up to [0 = disable]", true, 0, false, 0);
const Vector& C_BasePlayer::GetRenderOrigin( void )
{
	// If we're not observing this player, or if we're not drawing it at the
	// moment then use the normal absolute origin.
	// NOTE: the GetCurrentlyDrawingEntity check is here to make sure the
	// shadow is rendered from the correct origin
	if(!IsInEye() || view->GetCurrentlyDrawingEntity() != this)
		return BaseClass::GetRenderOrigin();
	
	// Get the forward vector
	static Vector forward; // static because this method returns a reference
	AngleVectors(GetRenderAngles(), &forward);
	
	// Shift the render origin by a fixed amount
	forward *= cl_legs_origin_shift.GetFloat();
	forward += GetAbsOrigin();
	
	return forward;
}
Теперь в функции int C_BasePlayer::DrawModel( int flags )
Добавляем: 
CMatRenderContextPtr context(materials);
 if(cl_legs_clip_height.GetInt() > 0)
 {
 context->SetHeightClipMode(MATERIAL_HEIGHTCLIPMODE_RENDER_BELOW_HEIGHT);
 context->SetHeightClipZ(GetAbsOrigin().z+cl_legs_clip_height.GetFloat());
 }
Теперь, ищем функцию void C_BasePlayer::AddEntity( void )
и под этим 
// Add in lighting effects
CreateLightEffects();
добавляем
SetLocalAnglesDim(X_INDEX, 0 );
Сейчас, в "c_baseplayer.h", ищем
bool IsInFreezeCam( void );
и под этим добавляем:
bool IsInEye( void );
В этом же файле ищем:
virtual int DrawModel( int flags );
И добавляем:
const Vector& C_BasePlayer::GetRenderOrigin();
Потом, открываем "hl2_player.cpp" и добавляем #define PLAYER_MODEL "models/player.mdl"
После всех #define.
Сейчас ищем: void CHL2_Player::Precache( void )
И добавляем
PrecacheModel(PLAYER_MODEL);
Теперь, ищем void CHL2_Player::Spawn(void)
и ищем следующею линию 
SetModel( "models/player.mdl" );
и заменяем на 
SetModel( PLAYER_MODEL );
Сейчас, Ищем
CHL2_Player::~CHL2_Player( void )
и заменяем на:
	
CHL2_Player::~CHL2_Player( void )
{
	// FPLEGS - Destructor defualt empty! Added code below!
	// Clears the animation state.
	if ( m_pPlayerAnimState != NULL )
	{
	 m_pPlayerAnimState->Release();
	 m_pPlayerAnimState = NULL;
	}
}
Так, ищем
CHL2_Player::CHL2_Player()
и заменяем на:
CHL2_Player::CHL2_Player()
{
	// FPLEGS
	m_pPlayerAnimState = CreatePlayerAnimationState(this);
	m_angEyeAngles.Init();
	// FPLEGS END
	m_nNumMissPositions	= 0;
	m_pPlayerAISquad = 0;
	m_bSprintEnabled = true;
	m_flArmorReductionTime = 0.0f;
	m_iArmorReductionFrom = 0;
}
Сейчас, поднимите голову верх:void CHL2_Player::PostThink( void )
и замените на:
void CHL2_Player::PostThink( void )
{
	BaseClass::PostThink();
	if ( !g_fGameOver && !IsPlayerLockedInPlace() && IsAlive() )
	{
		 HandleAdmireGlovesAnimation();
	}
	// FPLEGS
	m_angEyeAngles = EyeAngles();
	QAngle angles = GetLocalAngles();
	angles[PITCH] = 0;
	SetLocalAngles( angles );
	m_pPlayerAnimState->Update();
}
Сейчас,Добавьте это в конец файла:
void CHL2_Player::SetAnimation( PLAYER_ANIM playerAnim )
{
 int animDesired;
 
 float speed;
 
 speed = GetAbsVelocity().Length2D();
 
 if ( GetFlags() & ( FL_FROZEN | FL_ATCONTROLS ) )
 {
 speed = 0;
 playerAnim = PLAYER_IDLE;
 }
 
 Activity idealActivity = ACT_HL2MP_RUN;
 
 if ( playerAnim == PLAYER_JUMP )
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_JUMP;
 else
 idealActivity = ACT_JUMP;
 }
 else if ( playerAnim == PLAYER_DIE )
 {
 if ( m_lifeState == LIFE_ALIVE )
 {
 return;
 }
 }
 else if ( playerAnim == PLAYER_ATTACK1 )
 {
 if ( GetActivity( ) == ACT_HOVER ||
 GetActivity( ) == ACT_SWIM ||
 GetActivity( ) == ACT_HOP ||
 GetActivity( ) == ACT_LEAP ||
 GetActivity( ) == ACT_DIESIMPLE )
 {
 idealActivity = GetActivity( );
 }
 else
 {
 idealActivity = ACT_HL2MP_GESTURE_RANGE_ATTACK;
 }
 }
 else if ( playerAnim == PLAYER_RELOAD )
 {
 idealActivity = ACT_HL2MP_GESTURE_RELOAD;
 }
 else if ( playerAnim == PLAYER_IDLE || playerAnim == PLAYER_WALK )
 {
 if ( !( GetFlags() & FL_ONGROUND ) && ( GetActivity( ) == ACT_HL2MP_JUMP || GetActivity( ) == ACT_JUMP ) ) // Still jumping
 {
 idealActivity = GetActivity( );
 } 
 else if ( GetWaterLevel() > 1 )
 {
 if ( speed == 0 )
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_IDLE;
 else
 idealActivity = ACT_IDLE;
 }
 else
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_RUN;
 else
 idealActivity = ACT_RUN;
 }
 }
 else
 {
 if ( GetFlags() & FL_DUCKING )
 {
 if ( speed > 0 )
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_WALK_CROUCH;
 else
 idealActivity = ACT_WALK_CROUCH;
 }
 else
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_IDLE_CROUCH;
 else
 idealActivity = ACT_COVER_LOW;
 }
 }
 else
 {
 if ( speed > 0 )
 {
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_RUN;
 else
 {
 if ( speed > HL2_WALK_SPEED + 20.0f )
 idealActivity = ACT_RUN;
 else
 idealActivity = ACT_WALK;
 }
 }
 }
 else
 {
 if ( HasWeapons() )
 idealActivity = ACT_HL2MP_IDLE;
 else
 idealActivity = ACT_IDLE;
 }
 }
 }
 
 //idealActivity = TranslateTeamActivity( idealActivity );
 }
 
 if ( IsInAVehicle() )
 {
 idealActivity = ACT_COVER_LOW;
 }
 
 if ( idealActivity == ACT_HL2MP_GESTURE_RANGE_ATTACK )
 {
 RestartGesture( Weapon_TranslateActivity( idealActivity ) );
 
 // FIXME: this seems a bit wacked
 Weapon_SetActivity( Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 );
 
 return;
 }
 else if ( idealActivity == ACT_HL2MP_GESTURE_RELOAD )
 {
 RestartGesture( Weapon_TranslateActivity( idealActivity ) );
 return;
 }
 else
 {
 SetActivity( idealActivity );
 
 animDesired = SelectWeightedSequence( Weapon_TranslateActivity ( idealActivity ) );
 
 if (animDesired == -1)
 {
 animDesired = SelectWeightedSequence( idealActivity );
 
 if ( animDesired == -1 )
 {
 animDesired = 0;
 }
 }
 
 // Already using the desired animation?
 if ( GetSequence() == animDesired )
 return;
 
 m_flPlaybackRate = 1.0;
 ResetSequence( animDesired );
 SetCycle( 0 );
 return;
 }
 
 // Already using the desired animation?
 if ( GetSequence() == animDesired )
 return;
 
 //Msg( "Set animation to %d\n", animDesired );
 // Reset to first frame of desired animation
 ResetSequence( animDesired );
 SetCycle( 0 );
}
Потом, идём в "hl2_player.h" и добавляем #include "singleplayer_animstate.h"
в начала файла.
Сейчас, идем в конец "public:" в классе class CHL2_Player : public 
и добавляем void SetAnimation( PLAYER_ANIM playerAnim );
сейчас,идём в конец класс, в "private:" секцую добавляем 
	CSinglePlayerAnimState *m_pPlayerAnimState;
	QAngle m_angEyeAngles;
==Weapon activity list tables==
в weapon_357.cpp:
В описание класса, ниже макроса "DECLARE_DATADESC()", добавляем следующею линию:
DECLARE_ACTTABLE();
ниже класса на 50 линию,где-то добавляем следующею таблицу :
acttable_t CWeapon357::m_acttable[] =
{
 { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false },
};
IMPLEMENT_ACTTABLE( CWeapon357 );
в weapon_ar2.cpp:
There is already an activity list. At it's foot, after // { ACT_RANGE_ATTACK2, ACT_RANGE_ATTACK_AR2_GRENADE, true },
add the following list:
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false },
In weapon_crossbow.cpp:
In the class description, around line 450, under the macro "DECLARE_DATADESC()", add this line:
DECLARE_ACTTABLE();
Under the class definition around line 489, add this activity table list:
acttable_t CWeaponCrossbow::m_acttable[] =
{
 { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_CROSSBOW, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_CROSSBOW, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_CROSSBOW, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_CROSSBOW, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_CROSSBOW, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_CROSSBOW, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, false },
};
IMPLEMENT_ACTTABLE( CWeaponCrossbow );
In weapon_crowbar.cpp:
There is already an activity list. At it's foot, after
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false },
add the following list:
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
 { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_MELEE, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_MELEE, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false },
In weapon_frag.cpp:
There is already an activity list. At it's foot, after
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
add the following list:
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_GRENADE, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_GRENADE, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_GRENADE, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_GRENADE, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false },
 { ACT_HL2MP_JUMP,
In weapon_physcannon.cpp:
In the class description, around line 1203, under the macro "DECLARE_DATADESC()", add this line:
DECLARE_ACTTABLE();
Under the class definition around line 1374, add this activity table list:
acttable_t CWeaponPhysCannon::m_acttable[] =
{
 { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PHYSGUN, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_PHYSGUN, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, false },
};
IMPLEMENT_ACTTABLE( CWeaponPhysCannon );
In weapon_pistol.cpp:
There is already an activity list. At it's foot, after
{ ACT_RUN, ACT_RUN_PISTOL, false },
add the following list:
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false },
In weapon_rpg.cpp:
There is already an activity list. At it's foot, after
{ ACT_COVER_LOW, ACT_COVER_LOW_RPG, true },
add the following list:
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_RPG, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_RPG, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_RPG, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_RPG, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_RPG, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_RPG, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_RPG, false },
In weapon_shotgun.cpp:
There is already an activity list. At it's foot, after
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false },
add the following list:
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SHOTGUN, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SHOTGUN, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SHOTGUN, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SHOTGUN, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SHOTGUN, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, false },
In weapon_smg1.cpp:
There is already an activity list. At it's foot, after
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true },
add the following list:
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SMG1, false },
 { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SMG1, false },
 { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SMG1, false },
 { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SMG1, false },
 { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false },
 { ACT_HL2MP_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false },
 { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SMG1, false },
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, false },
==Создание модели==
Если ты хочешь создать свою модель, скачайте оригинальные player.mdl SMD файлы вот ссылка здесь.
При создание модели делайте её как gordon_body_ref.smd или как на картинки здесь.
==Конечный продукт==
Посмотрите конечный продукт здесь на youtube.
==Благодарность ==
*Код анимации для сингла - Malortie
*Weapon Activity Tables - Malortie
*Другое - Zombie Killa
*Gordon Freeman - VALVe and DPFilms
*Туториал - ExoBacon
*Перевёл - я