mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-29 17:43:01 +00:00
692 lines
22 KiB
C++
692 lines
22 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "baseviewmodel_shared.h"
|
||
|
#include "datacache/imdlcache.h"
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
#include "iprediction.h"
|
||
|
#include "prediction.h"
|
||
|
#include "client_virtualreality.h"
|
||
|
#include "sourcevr/isourcevirtualreality.h"
|
||
|
#else
|
||
|
#include "vguiscreen.h"
|
||
|
#endif
|
||
|
|
||
|
#if defined( CLIENT_DLL ) && defined( SIXENSE )
|
||
|
#include "sixense/in_sixense.h"
|
||
|
#include "sixense/sixense_convars_extern.h"
|
||
|
#endif
|
||
|
|
||
|
#ifdef SIXENSE
|
||
|
extern ConVar in_forceuser;
|
||
|
#include "iclientmode.h"
|
||
|
#endif
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
#define VIEWMODEL_ANIMATION_PARITY_BITS 3
|
||
|
#define SCREEN_OVERLAY_MATERIAL "vgui/screens/vgui_overlay"
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseViewModel::CBaseViewModel()
|
||
|
{
|
||
|
#if defined( CLIENT_DLL )
|
||
|
// NOTE: We do this here because the color is never transmitted for the view model.
|
||
|
m_nOldAnimationParity = 0;
|
||
|
m_EntClientFlags |= ENTCLIENTFLAG_ALWAYS_INTERPOLATE;
|
||
|
#endif
|
||
|
SetRenderColor( 255, 255, 255, 255 );
|
||
|
|
||
|
// View model of this weapon
|
||
|
m_sVMName = NULL_STRING;
|
||
|
// Prefix of the animations that should be used by the player carrying this weapon
|
||
|
m_sAnimationPrefix = NULL_STRING;
|
||
|
|
||
|
m_nViewModelIndex = 0;
|
||
|
|
||
|
m_nAnimationParity = 0;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseViewModel::~CBaseViewModel()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CBaseViewModel::UpdateOnRemove( void )
|
||
|
{
|
||
|
BaseClass::UpdateOnRemove();
|
||
|
|
||
|
DestroyControlPanels();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::Precache( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::Spawn( void )
|
||
|
{
|
||
|
Precache( );
|
||
|
SetSize( Vector( -8, -4, -2), Vector(8, 4, 2) );
|
||
|
SetSolid( SOLID_NONE );
|
||
|
}
|
||
|
|
||
|
|
||
|
#if defined ( CSTRIKE_DLL ) && !defined ( CLIENT_DLL )
|
||
|
#define VGUI_CONTROL_PANELS
|
||
|
#endif
|
||
|
|
||
|
#if defined ( TF_DLL )
|
||
|
#define VGUI_CONTROL_PANELS
|
||
|
#endif
|
||
|
|
||
|
#ifdef INVASION_DLL
|
||
|
#define VGUI_CONTROL_PANELS
|
||
|
#endif
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::SetControlPanelsActive( bool bState )
|
||
|
{
|
||
|
#if defined( VGUI_CONTROL_PANELS )
|
||
|
// Activate control panel screens
|
||
|
for ( int i = m_hScreens.Count(); --i >= 0; )
|
||
|
{
|
||
|
if (m_hScreens[i].Get())
|
||
|
{
|
||
|
m_hScreens[i]->SetActive( bState );
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// This is called by the base object when it's time to spawn the control panels
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::SpawnControlPanels()
|
||
|
{
|
||
|
#if defined( VGUI_CONTROL_PANELS )
|
||
|
char buf[64];
|
||
|
|
||
|
// Destroy existing panels
|
||
|
DestroyControlPanels();
|
||
|
|
||
|
CBaseCombatWeapon *weapon = m_hWeapon.Get();
|
||
|
|
||
|
if ( weapon == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
MDLCACHE_CRITICAL_SECTION();
|
||
|
|
||
|
// FIXME: Deal with dynamically resizing control panels?
|
||
|
|
||
|
// If we're attached to an entity, spawn control panels on it instead of use
|
||
|
CBaseAnimating *pEntityToSpawnOn = this;
|
||
|
char *pOrgLL = "controlpanel%d_ll";
|
||
|
char *pOrgUR = "controlpanel%d_ur";
|
||
|
char *pAttachmentNameLL = pOrgLL;
|
||
|
char *pAttachmentNameUR = pOrgUR;
|
||
|
/*
|
||
|
if ( IsBuiltOnAttachment() )
|
||
|
{
|
||
|
pEntityToSpawnOn = dynamic_cast<CBaseAnimating*>((CBaseEntity*)m_hBuiltOnEntity.Get());
|
||
|
if ( pEntityToSpawnOn )
|
||
|
{
|
||
|
char sBuildPointLL[64];
|
||
|
char sBuildPointUR[64];
|
||
|
Q_snprintf( sBuildPointLL, sizeof( sBuildPointLL ), "bp%d_controlpanel%%d_ll", m_iBuiltOnPoint );
|
||
|
Q_snprintf( sBuildPointUR, sizeof( sBuildPointUR ), "bp%d_controlpanel%%d_ur", m_iBuiltOnPoint );
|
||
|
pAttachmentNameLL = sBuildPointLL;
|
||
|
pAttachmentNameUR = sBuildPointUR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pEntityToSpawnOn = this;
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
Assert( pEntityToSpawnOn );
|
||
|
|
||
|
// Lookup the attachment point...
|
||
|
int nPanel;
|
||
|
for ( nPanel = 0; true; ++nPanel )
|
||
|
{
|
||
|
Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel );
|
||
|
int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
|
||
|
if (nLLAttachmentIndex <= 0)
|
||
|
{
|
||
|
// Try and use my panels then
|
||
|
pEntityToSpawnOn = this;
|
||
|
Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel );
|
||
|
nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
|
||
|
if (nLLAttachmentIndex <= 0)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel );
|
||
|
int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
|
||
|
if (nURAttachmentIndex <= 0)
|
||
|
{
|
||
|
// Try and use my panels then
|
||
|
Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel );
|
||
|
nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
|
||
|
if (nURAttachmentIndex <= 0)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const char *pScreenName;
|
||
|
weapon->GetControlPanelInfo( nPanel, pScreenName );
|
||
|
if (!pScreenName)
|
||
|
continue;
|
||
|
|
||
|
const char *pScreenClassname;
|
||
|
weapon->GetControlPanelClassName( nPanel, pScreenClassname );
|
||
|
if ( !pScreenClassname )
|
||
|
continue;
|
||
|
|
||
|
// Compute the screen size from the attachment points...
|
||
|
matrix3x4_t panelToWorld;
|
||
|
pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld );
|
||
|
|
||
|
matrix3x4_t worldToPanel;
|
||
|
MatrixInvert( panelToWorld, worldToPanel );
|
||
|
|
||
|
// Now get the lower right position + transform into panel space
|
||
|
Vector lr, lrlocal;
|
||
|
pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld );
|
||
|
MatrixGetColumn( panelToWorld, 3, lr );
|
||
|
VectorTransform( lr, worldToPanel, lrlocal );
|
||
|
|
||
|
float flWidth = lrlocal.x;
|
||
|
float flHeight = lrlocal.y;
|
||
|
|
||
|
CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex );
|
||
|
pScreen->ChangeTeam( GetTeamNumber() );
|
||
|
pScreen->SetActualSize( flWidth, flHeight );
|
||
|
pScreen->SetActive( false );
|
||
|
pScreen->MakeVisibleOnlyToTeammates( false );
|
||
|
|
||
|
#ifdef INVASION_DLL
|
||
|
pScreen->SetOverlayMaterial( SCREEN_OVERLAY_MATERIAL );
|
||
|
#endif
|
||
|
pScreen->SetAttachedToViewModel( true );
|
||
|
int nScreen = m_hScreens.AddToTail( );
|
||
|
m_hScreens[nScreen].Set( pScreen );
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void CBaseViewModel::DestroyControlPanels()
|
||
|
{
|
||
|
#if defined( VGUI_CONTROL_PANELS )
|
||
|
// Kill the control panels
|
||
|
int i;
|
||
|
for ( i = m_hScreens.Count(); --i >= 0; )
|
||
|
{
|
||
|
DestroyVGuiScreen( m_hScreens[i].Get() );
|
||
|
}
|
||
|
m_hScreens.RemoveAll();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pEntity -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::SetOwner( CBaseEntity *pEntity )
|
||
|
{
|
||
|
m_hOwner = pEntity;
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
// Make sure we're linked into hierarchy
|
||
|
//SetParent( pEntity );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : nIndex -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::SetIndex( int nIndex )
|
||
|
{
|
||
|
m_nViewModelIndex = nIndex;
|
||
|
Assert( m_nViewModelIndex < (1 << VIEWMODEL_INDEX_BITS) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseViewModel::ViewModelIndex( ) const
|
||
|
{
|
||
|
return m_nViewModelIndex;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Pass our visibility on to our child screens
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::AddEffects( int nEffects )
|
||
|
{
|
||
|
if ( nEffects & EF_NODRAW )
|
||
|
{
|
||
|
SetControlPanelsActive( false );
|
||
|
}
|
||
|
|
||
|
BaseClass::AddEffects( nEffects );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Pass our visibility on to our child screens
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::RemoveEffects( int nEffects )
|
||
|
{
|
||
|
if ( nEffects & EF_NODRAW )
|
||
|
{
|
||
|
SetControlPanelsActive( true );
|
||
|
}
|
||
|
|
||
|
BaseClass::RemoveEffects( nEffects );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *modelname -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::SetWeaponModel( const char *modelname, CBaseCombatWeapon *weapon )
|
||
|
{
|
||
|
m_hWeapon = weapon;
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
SetModel( modelname );
|
||
|
#else
|
||
|
string_t str;
|
||
|
if ( modelname != NULL )
|
||
|
{
|
||
|
str = MAKE_STRING( modelname );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
str = NULL_STRING;
|
||
|
}
|
||
|
|
||
|
if ( str != m_sVMName )
|
||
|
{
|
||
|
// Msg( "SetWeaponModel %s at %f\n", modelname, gpGlobals->curtime );
|
||
|
m_sVMName = str;
|
||
|
SetModel( STRING( m_sVMName ) );
|
||
|
|
||
|
// Create any vgui control panels associated with the weapon
|
||
|
SpawnControlPanels();
|
||
|
|
||
|
bool showControlPanels = weapon && weapon->ShouldShowControlPanels();
|
||
|
SetControlPanelsActive( showControlPanels );
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Output : CBaseCombatWeapon
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseCombatWeapon *CBaseViewModel::GetOwningWeapon( void )
|
||
|
{
|
||
|
return m_hWeapon.Get();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : sequence -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseViewModel::SendViewModelMatchingSequence( int sequence )
|
||
|
{
|
||
|
// since all we do is send a sequence number down to the client,
|
||
|
// set this here so other weapons code knows which sequence is playing.
|
||
|
SetSequence( sequence );
|
||
|
|
||
|
m_nAnimationParity = ( m_nAnimationParity + 1 ) & ( (1<<VIEWMODEL_ANIMATION_PARITY_BITS) - 1 );
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
m_nOldAnimationParity = m_nAnimationParity;
|
||
|
|
||
|
// Force frame interpolation to start at exactly frame zero
|
||
|
m_flAnimTime = gpGlobals->curtime;
|
||
|
#else
|
||
|
CBaseCombatWeapon *weapon = m_hWeapon.Get();
|
||
|
bool showControlPanels = weapon && weapon->ShouldShowControlPanels();
|
||
|
SetControlPanelsActive( showControlPanels );
|
||
|
#endif
|
||
|
|
||
|
// Restart animation at frame 0
|
||
|
SetCycle( 0 );
|
||
|
ResetSequenceInfo();
|
||
|
}
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
#include "ivieweffects.h"
|
||
|
#endif
|
||
|
|
||
|
void CBaseViewModel::CalcViewModelView( CBasePlayer *owner, const Vector& eyePosition, const QAngle& eyeAngles )
|
||
|
{
|
||
|
// UNDONE: Calc this on the server? Disabled for now as it seems unnecessary to have this info on the server
|
||
|
#if defined( CLIENT_DLL )
|
||
|
QAngle vmangoriginal = eyeAngles;
|
||
|
QAngle vmangles = eyeAngles;
|
||
|
Vector vmorigin = eyePosition;
|
||
|
|
||
|
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
|
||
|
//Allow weapon lagging
|
||
|
if ( pWeapon != NULL )
|
||
|
{
|
||
|
#if defined( CLIENT_DLL )
|
||
|
if ( !prediction->InPrediction() )
|
||
|
#endif
|
||
|
{
|
||
|
// add weapon-specific bob
|
||
|
pWeapon->AddViewmodelBob( this, vmorigin, vmangles );
|
||
|
#if defined ( CSTRIKE_DLL )
|
||
|
CalcViewModelLag( vmorigin, vmangles, vmangoriginal );
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
// Add model-specific bob even if no weapon associated (for head bob for off hand models)
|
||
|
AddViewModelBob( owner, vmorigin, vmangles );
|
||
|
#if !defined ( CSTRIKE_DLL )
|
||
|
// This was causing weapon jitter when rotating in updated CS:S; original Source had this in above InPrediction block 07/14/10
|
||
|
// Add lag
|
||
|
CalcViewModelLag( vmorigin, vmangles, vmangoriginal );
|
||
|
#endif
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
if ( !prediction->InPrediction() )
|
||
|
{
|
||
|
// Let the viewmodel shake at about 10% of the amplitude of the player's view
|
||
|
vieweffects->ApplyShake( vmorigin, vmangles, 0.1 );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if( UseVR() )
|
||
|
{
|
||
|
g_ClientVirtualReality.OverrideViewModelTransform( vmorigin, vmangles, pWeapon && pWeapon->ShouldUseLargeViewModelVROverride() );
|
||
|
}
|
||
|
|
||
|
SetLocalOrigin( vmorigin );
|
||
|
SetLocalAngles( vmangles );
|
||
|
|
||
|
#ifdef SIXENSE
|
||
|
if( g_pSixenseInput->IsEnabled() && (owner->GetObserverMode()==OBS_MODE_NONE) && !UseVR() )
|
||
|
{
|
||
|
const float max_gun_pitch = 20.0f;
|
||
|
|
||
|
float viewmodel_fov_ratio = g_pClientMode->GetViewModelFOV()/owner->GetFOV();
|
||
|
QAngle gun_angles = g_pSixenseInput->GetViewAngleOffset() * -viewmodel_fov_ratio;
|
||
|
|
||
|
// Clamp pitch a bit to minimize seeing back of viewmodel
|
||
|
if( gun_angles[PITCH] < -max_gun_pitch )
|
||
|
{
|
||
|
gun_angles[PITCH] = -max_gun_pitch;
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32 // ShouldFlipViewModel comes up unresolved on osx? Mabye because it's defined inline? fixme
|
||
|
if( ShouldFlipViewModel() )
|
||
|
{
|
||
|
gun_angles[YAW] *= -1.0f;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
vmangles = EyeAngles() + gun_angles;
|
||
|
|
||
|
SetLocalAngles( vmangles );
|
||
|
}
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float g_fMaxViewModelLag = 1.5f;
|
||
|
|
||
|
void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& original_angles )
|
||
|
{
|
||
|
Vector vOriginalOrigin = origin;
|
||
|
QAngle vOriginalAngles = angles;
|
||
|
|
||
|
// Calculate our drift
|
||
|
Vector forward;
|
||
|
AngleVectors( angles, &forward, NULL, NULL );
|
||
|
|
||
|
if ( gpGlobals->frametime != 0.0f )
|
||
|
{
|
||
|
Vector vDifference;
|
||
|
VectorSubtract( forward, m_vecLastFacing, vDifference );
|
||
|
|
||
|
float flSpeed = 5.0f;
|
||
|
|
||
|
// If we start to lag too far behind, we'll increase the "catch up" speed. Solves the problem with fast cl_yawspeed, m_yaw or joysticks
|
||
|
// rotating quickly. The old code would slam lastfacing with origin causing the viewmodel to pop to a new position
|
||
|
float flDiff = vDifference.Length();
|
||
|
if ( (flDiff > g_fMaxViewModelLag) && (g_fMaxViewModelLag > 0.0f) )
|
||
|
{
|
||
|
float flScale = flDiff / g_fMaxViewModelLag;
|
||
|
flSpeed *= flScale;
|
||
|
}
|
||
|
|
||
|
// FIXME: Needs to be predictable?
|
||
|
VectorMA( m_vecLastFacing, flSpeed * gpGlobals->frametime, vDifference, m_vecLastFacing );
|
||
|
// Make sure it doesn't grow out of control!!!
|
||
|
VectorNormalize( m_vecLastFacing );
|
||
|
VectorMA( origin, 5.0f, vDifference * -1.0f, origin );
|
||
|
|
||
|
Assert( m_vecLastFacing.IsValid() );
|
||
|
}
|
||
|
|
||
|
Vector right, up;
|
||
|
AngleVectors( original_angles, &forward, &right, &up );
|
||
|
|
||
|
float pitch = original_angles[ PITCH ];
|
||
|
if ( pitch > 180.0f )
|
||
|
pitch -= 360.0f;
|
||
|
else if ( pitch < -180.0f )
|
||
|
pitch += 360.0f;
|
||
|
|
||
|
if ( g_fMaxViewModelLag == 0.0f )
|
||
|
{
|
||
|
origin = vOriginalOrigin;
|
||
|
angles = vOriginalAngles;
|
||
|
}
|
||
|
|
||
|
//FIXME: These are the old settings that caused too many exposed polys on some models
|
||
|
VectorMA( origin, -pitch * 0.035f, forward, origin );
|
||
|
VectorMA( origin, -pitch * 0.03f, right, origin );
|
||
|
VectorMA( origin, -pitch * 0.02f, up, origin);
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Stub to keep networking consistent for DEM files
|
||
|
//-----------------------------------------------------------------------------
|
||
|
#if defined( CLIENT_DLL )
|
||
|
extern void RecvProxy_EffectFlags( const CRecvProxyData *pData, void *pStruct, void *pOut );
|
||
|
void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut );
|
||
|
#endif
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Resets anim cycle when the server changes the weapon on us
|
||
|
//-----------------------------------------------------------------------------
|
||
|
#if defined( CLIENT_DLL )
|
||
|
static void RecvProxy_Weapon( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||
|
{
|
||
|
CBaseViewModel *pViewModel = ((CBaseViewModel*)pStruct);
|
||
|
CBaseCombatWeapon *pOldWeapon = pViewModel->GetOwningWeapon();
|
||
|
|
||
|
// Chain through to the default recieve proxy ...
|
||
|
RecvProxy_IntToEHandle( pData, pStruct, pOut );
|
||
|
|
||
|
// ... and reset our cycle index if the server is switching weapons on us
|
||
|
CBaseCombatWeapon *pNewWeapon = pViewModel->GetOwningWeapon();
|
||
|
if ( pNewWeapon != pOldWeapon )
|
||
|
{
|
||
|
// Restart animation at frame 0
|
||
|
pViewModel->SetCycle( 0 );
|
||
|
pViewModel->m_flAnimTime = gpGlobals->curtime;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( viewmodel, CBaseViewModel );
|
||
|
|
||
|
IMPLEMENT_NETWORKCLASS_ALIASED( BaseViewModel, DT_BaseViewModel )
|
||
|
|
||
|
BEGIN_NETWORK_TABLE_NOBASE(CBaseViewModel, DT_BaseViewModel)
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
SendPropModelIndex(SENDINFO(m_nModelIndex)),
|
||
|
SendPropInt (SENDINFO(m_nBody), 8),
|
||
|
SendPropInt (SENDINFO(m_nSkin), 10),
|
||
|
SendPropInt (SENDINFO(m_nSequence), 8, SPROP_UNSIGNED),
|
||
|
SendPropInt (SENDINFO(m_nViewModelIndex), VIEWMODEL_INDEX_BITS, SPROP_UNSIGNED),
|
||
|
SendPropFloat (SENDINFO(m_flPlaybackRate), 8, SPROP_ROUNDUP, -4.0, 12.0f),
|
||
|
SendPropInt (SENDINFO(m_fEffects), 10, SPROP_UNSIGNED),
|
||
|
SendPropInt (SENDINFO(m_nAnimationParity), 3, SPROP_UNSIGNED ),
|
||
|
SendPropEHandle (SENDINFO(m_hWeapon)),
|
||
|
SendPropEHandle (SENDINFO(m_hOwner)),
|
||
|
|
||
|
SendPropInt( SENDINFO( m_nNewSequenceParity ), EF_PARITY_BITS, SPROP_UNSIGNED ),
|
||
|
SendPropInt( SENDINFO( m_nResetEventsParity ), EF_PARITY_BITS, SPROP_UNSIGNED ),
|
||
|
SendPropInt( SENDINFO( m_nMuzzleFlashParity ), EF_MUZZLEFLASH_BITS, SPROP_UNSIGNED ),
|
||
|
|
||
|
#if !defined( INVASION_DLL ) && !defined( INVASION_CLIENT_DLL )
|
||
|
SendPropArray (SendPropFloat(SENDINFO_ARRAY(m_flPoseParameter), 8, 0, 0.0f, 1.0f), m_flPoseParameter),
|
||
|
#endif
|
||
|
#else
|
||
|
RecvPropInt (RECVINFO(m_nModelIndex)),
|
||
|
RecvPropInt (RECVINFO(m_nSkin)),
|
||
|
RecvPropInt (RECVINFO(m_nBody)),
|
||
|
RecvPropInt (RECVINFO(m_nSequence), 0, RecvProxy_SequenceNum ),
|
||
|
RecvPropInt (RECVINFO(m_nViewModelIndex)),
|
||
|
RecvPropFloat (RECVINFO(m_flPlaybackRate)),
|
||
|
RecvPropInt (RECVINFO(m_fEffects), 0, RecvProxy_EffectFlags ),
|
||
|
RecvPropInt (RECVINFO(m_nAnimationParity)),
|
||
|
RecvPropEHandle (RECVINFO(m_hWeapon), RecvProxy_Weapon ),
|
||
|
RecvPropEHandle (RECVINFO(m_hOwner)),
|
||
|
|
||
|
RecvPropInt( RECVINFO( m_nNewSequenceParity )),
|
||
|
RecvPropInt( RECVINFO( m_nResetEventsParity )),
|
||
|
RecvPropInt( RECVINFO( m_nMuzzleFlashParity )),
|
||
|
|
||
|
#if !defined( INVASION_DLL ) && !defined( INVASION_CLIENT_DLL )
|
||
|
RecvPropArray(RecvPropFloat(RECVINFO(m_flPoseParameter[0]) ), m_flPoseParameter ),
|
||
|
#endif
|
||
|
#endif
|
||
|
END_NETWORK_TABLE()
|
||
|
|
||
|
#ifdef CLIENT_DLL
|
||
|
|
||
|
BEGIN_PREDICTION_DATA( CBaseViewModel )
|
||
|
|
||
|
// Networked
|
||
|
DEFINE_PRED_FIELD( m_nModelIndex, FIELD_SHORT, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
|
||
|
DEFINE_PRED_FIELD( m_nSkin, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||
|
DEFINE_PRED_FIELD( m_nBody, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||
|
DEFINE_PRED_FIELD( m_nSequence, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||
|
DEFINE_PRED_FIELD( m_nViewModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||
|
DEFINE_PRED_FIELD_TOL( m_flPlaybackRate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, 0.125f ),
|
||
|
DEFINE_PRED_FIELD( m_fEffects, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_OVERRIDE ),
|
||
|
DEFINE_PRED_FIELD( m_nAnimationParity, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||
|
DEFINE_PRED_FIELD( m_hWeapon, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
|
||
|
DEFINE_PRED_FIELD( m_flAnimTime, FIELD_FLOAT, 0 ),
|
||
|
|
||
|
DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
|
||
|
DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT ),
|
||
|
DEFINE_FIELD( m_Activity, FIELD_INTEGER ),
|
||
|
DEFINE_PRED_FIELD( m_flCycle, FIELD_FLOAT, FTYPEDESC_PRIVATE | FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ),
|
||
|
|
||
|
END_PREDICTION_DATA()
|
||
|
|
||
|
void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||
|
{
|
||
|
CBaseViewModel *model = (CBaseViewModel *)pStruct;
|
||
|
if (pData->m_Value.m_Int != model->GetSequence())
|
||
|
{
|
||
|
MDLCACHE_CRITICAL_SECTION();
|
||
|
|
||
|
model->SetSequence(pData->m_Value.m_Int);
|
||
|
model->m_flAnimTime = gpGlobals->curtime;
|
||
|
model->SetCycle(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseViewModel::LookupAttachment( const char *pAttachmentName )
|
||
|
{
|
||
|
if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() )
|
||
|
return m_hWeapon.Get()->LookupAttachment( pAttachmentName );
|
||
|
|
||
|
return BaseClass::LookupAttachment( pAttachmentName );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseViewModel::GetAttachment( int number, matrix3x4_t &matrix )
|
||
|
{
|
||
|
if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() )
|
||
|
return m_hWeapon.Get()->GetAttachment( number, matrix );
|
||
|
|
||
|
return BaseClass::GetAttachment( number, matrix );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseViewModel::GetAttachment( int number, Vector &origin )
|
||
|
{
|
||
|
if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() )
|
||
|
return m_hWeapon.Get()->GetAttachment( number, origin );
|
||
|
|
||
|
return BaseClass::GetAttachment( number, origin );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseViewModel::GetAttachment( int number, Vector &origin, QAngle &angles )
|
||
|
{
|
||
|
if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() )
|
||
|
return m_hWeapon.Get()->GetAttachment( number, origin, angles );
|
||
|
|
||
|
return BaseClass::GetAttachment( number, origin, angles );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseViewModel::GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel )
|
||
|
{
|
||
|
if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() )
|
||
|
return m_hWeapon.Get()->GetAttachmentVelocity( number, originVel, angleVel );
|
||
|
|
||
|
return BaseClass::GetAttachmentVelocity( number, originVel, angleVel );
|
||
|
}
|
||
|
|
||
|
#endif
|