Hand Viewmodels

From Valve Developer Community
Revision as of 12:36, 1 June 2021 by Slam12f (talk | contribs) (Fix Source Engine 2013 MP during death)
Jump to: navigation, search


Have you ever wanted fancy c_ models like all those cool games?

Well, now you can!


Create the following file and put it in the src/game/shared folder:


#include "cbase.h"
#include "baseviewmodel_shared.h"

#if defined( CLIENT_DLL )
	#define CHandViewModel C_HandViewModel

class CHandViewModel : public CBaseViewModel
	DECLARE_CLASS( CHandViewModel, CBaseViewModel );



LINK_ENTITY_TO_CLASS( hand_viewmodel, CHandViewModel );

// 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 ) ),
	RecvPropInt( RECVINFO_NAME( m_hNetworkMoveParent, moveparent ), 0, RecvProxy_IntToMoveParent ),


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 );


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 ) )

	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:



Note.png Note: Depending on the base you're modifying you'll have to pick the relevant file for this. If it's an SP mod modify hl2_player.cpp, if it's an MP mod modify hl2mp_player.cpp or if you have your own player class just modify that.

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" );
Note.png Note: This might not work perfectly on the Alien Swarm Alien Swarm branch since it does weird stuff with bone merging sometimes.

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" );

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[] = 
	"hand_viewmodel", // Our new viewmodel entity
	"", // END Marker

If you don't do it, your hands viewmodel will be removed every time new round has started.

Fix Source Engine 2013 MP during death

In multiplayer, an error was found. Hands are displayed at the time of the player's death if you have first-person Raggdols.

To prevent it, open player.cpp find function: CBasePlayer::PlayerDeathThink

and write some were inside this:

	GetViewModel(1)->SetModel(""); // fix - remove hands model when player dead.