Hand Viewmodels

==Introduction==
Have you ever wanted those fancy hand viewmodels like , or other great games?
Well, now you can!
==Implementation==
Create the following file and put it in the src/game/shared folder:
===handviewmodel_shared.cpp===
#include "cbase.h"
#include "baseviewmodel_shared.h"
#if defined( CLIENT_DLL )
	#define CHandViewModel C_HandViewModel
#endif
class CHandViewModel : public CBaseViewModel
{
	DECLARE_CLASS( CHandViewModel, CBaseViewModel );
public:
	DECLARE_NETWORKCLASS();
private:
};
LINK_ENTITY_TO_CLASS( hand_viewmodel, CHandViewModel );
IMPLEMENT_NETWORKCLASS_ALIASED( HandViewModel, DT_HandViewModel )
// For whatever reason the parent doesn't get sent 
// And I don't really want to mess with BaseViewModel
// so now it does
BEGIN_NETWORK_TABLE( CHandViewModel, DT_HandViewModel )
#ifndef CLIENT_DLL
	SendPropEHandle( SENDINFO_NAME( m_hMoveParent, moveparent ) ),
#else
	RecvPropInt( RECVINFO_NAME( m_hNetworkMoveParent, moveparent ), 0, RecvProxy_IntToMoveParent ),
#endif
END_NETWORK_TABLE()
===player.h===
In src/server/player.h you should now add the following below the CreateViewModel( int viewmodelindex = 0 ); declaration:
virtual void	 CreateHandModel( int viewmodelindex = 1, int iOtherVm = 0 );
===player.cpp===
In src/server/player.cpp put this below the CreateViewModel( int index /*=0*/ ) function:
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBasePlayer::CreateHandModel( int index, int iOtherVm )
{
	Assert( index >= 0 && index < MAX_VIEWMODELS && iOtherVm >= 0 && iOtherVm < MAX_VIEWMODELS );
	if ( GetViewModel( index ) )
		return;
	CBaseViewModel *vm = (CBaseViewModel *)CreateEntityByName( "hand_viewmodel" );
	if ( vm )
	{
		vm->SetAbsOrigin( GetAbsOrigin() );
		vm->SetOwner( this );
		vm->SetIndex( index );
		DispatchSpawn( vm );
		vm->FollowEntity( GetViewModel( iOtherVm ), true );
		m_hViewModel.Set( index, vm );
	}
}
Now we need to call it. So inside the Spawn function, and below CreateViewModel();, add:
	CreateHandModel();
===your_player.cpp===
So now that the HandViewModel has been created we need to set its model.
Put this in your player's Spawn function sometime after the hand model has been created:
	GetViewModel(1)->SetModel( "models/coolhandsfolder/cool_arms.mdl" );
Also make sure your model has been precached first! To do this add the following into your Precache function:
	PrecacheModel( "models/coolhandsfolder/cool_arms.mdl" );
==Fixes==
===Fix for multiplayer mods with a round system===
If you are using this method for multiplayer and your mod has a round system, you will have to add your new viewmodel's entity name (in this tutorial it's hand_viewmodel) into s_PreserveEnts[] array which is located in the gamerules file (hl2mp_gamerules.cpp for example) so it will look something like this:
static const char *s_PreserveEnts[] = 
{
	"ai_network",
	"ai_hint",
	"hl2mp_gamerules",
	"team_manager",
	"player_manager",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"func_brush",
	"func_wall",
	"func_buyzone",
	"func_illusionary",
	"infodecal",
	"info_projecteddecal",
	"info_node",
	"info_target",
	"info_node_hint",
	"info_player_deathmatch",
	"info_player_combine",
	"info_player_rebel",
	"info_map_parameters",
	"keyframe_rope",
	"move_rope",
	"info_ladder",
	"player",
	"point_viewcontrol",
	"scene_manager",
	"shadow_control",
	"sky_camera",
	"soundent",
	"trigger_soundscape",
	"viewmodel",
	"predicted_viewmodel",
	"hand_viewmodel", // Our new viewmodel entity
	"worldspawn",
	"point_devshot_camera",
	"", // END Marker
};
If you don't do it, your hands viewmodel will be removed every time new round has started.
===Fix for multiplayer mods with first person ragdolls===
In multiplayer, an error was found where hands are displayed at the time of the player's death if you have first person ragdolls implemented.
To prevent it, open player.cpp and find the PlayerDeathThink(void) function and add this somewere inside it:
	GetViewModel(1)->SetModel( "" ); // FIX: Removes hand model when the player is dead
===Fix for vanishing hands in singleplayer===
In singleplayer if the player takes a prop using the +use key the hands model will vanish until the player fires with a weapon, the same thing happens when the player exits a vehicle.
To prevent it you need to edit the function void CBaseCombatWeapon::SetWeaponVisible( bool visible ) in basecombatweapon_shared.cpp :
void CBaseCombatWeapon::SetWeaponVisible( bool visible )
{
	CBaseViewModel *vm = NULL;
	CBaseViewModel* hm = NULL;
	CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
	if ( pOwner )
	{
		vm = pOwner->GetViewModel();
		hm = pOwner->GetViewModel(1);
	}
	if ( visible )
	{
		RemoveEffects( EF_NODRAW );
		if ( vm )
		{
			vm->RemoveEffects( EF_NODRAW );
		}
		if ( hm )
		{
			hm->RemoveEffects( EF_NODRAW );
		}
	}
	else
	{
		AddEffects( EF_NODRAW );
		if ( vm )
		{
			vm->AddEffects( EF_NODRAW );
		}
		if ( hm )
		{
			hm->AddEffects( EF_NODRAW );
		}
	}
}
Category:Programming
Category:Tutorials