|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_tfc_player.h"
#include "c_user_message_register.h"
#include "view.h"
#include "iclientvehicle.h"
#include "ivieweffects.h"
#include "input.h"
#include "IEffects.h"
#include "fx.h"
#include "c_basetempentity.h"
#include "hud_macros.h"
#include "engine/ivdebugoverlay.h"
#include "smoke_fog_overlay.h"
#include "playerandobjectenumerator.h"
#include "bone_setup.h"
#include "in_buttons.h"
#include "r_efx.h"
#include "dlight.h"
#include "shake.h"
#include "cl_animevent.h"
#include "weapon_tfcbase.h"
#if defined( CTFCPlayer )
#undef CTFCPlayer
#endif
#include "materialsystem/imesh.h" //for materials->FindMaterial
#include "iviewrender.h" //for view->
// -------------------------------------------------------------------------------- //
// Player animation event. Sent to the client when a player fires, jumps, reloads, etc..
// -------------------------------------------------------------------------------- //
class C_TEPlayerAnimEvent : public C_BaseTempEntity { public: DECLARE_CLASS( C_TEPlayerAnimEvent, C_BaseTempEntity ); DECLARE_CLIENTCLASS();
virtual void PostDataUpdate( DataUpdateType_t updateType ) { // Create the effect.
C_TFCPlayer *pPlayer = dynamic_cast< C_TFCPlayer* >( m_hPlayer.Get() ); if ( pPlayer && !pPlayer->IsDormant() ) { pPlayer->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get(), m_nData ); } }
public: CNetworkHandle( CBasePlayer, m_hPlayer ); CNetworkVar( int, m_iEvent ); CNetworkVar( int, m_nData ); };
IMPLEMENT_CLIENTCLASS_EVENT( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent, CTEPlayerAnimEvent );
// ------------------------------------------------------------------------------------------ //
// Data tables and prediction tables.
// ------------------------------------------------------------------------------------------ //
BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent ) RecvPropEHandle( RECVINFO( m_hPlayer ) ), RecvPropInt( RECVINFO( m_iEvent ) ), RecvPropInt( RECVINFO( m_nData ) ) END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT( C_TFCPlayer, DT_TFCPlayer, CTFCPlayer ) RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ), RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ), RecvPropDataTable( RECVINFO_DT( m_Shared ), 0, &REFERENCE_RECV_TABLE( DT_TFCPlayerShared ) ) END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_TFCPlayer ) DEFINE_PRED_TYPEDESCRIPTION( m_Shared, CTFCPlayerShared ), END_PREDICTION_DATA()
// ------------------------------------------------------------------------------------------ //
// C_TFCPlayer implementation.
// ------------------------------------------------------------------------------------------ //
C_TFCPlayer::C_TFCPlayer() : m_iv_angEyeAngles( "C_TFCPlayer::m_iv_angEyeAngles" ) { m_PlayerAnimState = CreatePlayerAnimState( this ); m_Shared.Init( this );
AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); }
C_TFCPlayer::~C_TFCPlayer() { m_PlayerAnimState->Release(); }
C_TFCPlayer* C_TFCPlayer::GetLocalTFCPlayer() { return ToTFCPlayer( C_BasePlayer::GetLocalPlayer() ); }
const QAngle& C_TFCPlayer::GetRenderAngles() { if ( IsRagdoll() ) { return vec3_angle; } else { return m_PlayerAnimState->GetRenderAngles(); } }
void C_TFCPlayer::UpdateClientSideAnimation() { // Update the animation data. It does the local check here so this works when using
// a third-person camera (and we don't have valid player angles).
if ( this == C_TFCPlayer::GetLocalTFCPlayer() ) m_PlayerAnimState->Update( EyeAngles()[YAW], m_angEyeAngles[PITCH] ); else m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] );
BaseClass::UpdateClientSideAnimation(); }
void C_TFCPlayer::PostDataUpdate( DataUpdateType_t updateType ) { // C_BaseEntity assumes we're networking the entity's angles, so pretend that it
// networked the same value we already have.
SetNetworkAngles( GetLocalAngles() ); BaseClass::PostDataUpdate( updateType ); }
void C_TFCPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) { m_PlayerAnimState->DoAnimationEvent( event, nData ); }
void C_TFCPlayer::ProcessMuzzleFlashEvent() { // Reenable when the weapons have muzzle flash attachments in the right spot.
if ( this != C_BasePlayer::GetLocalPlayer() ) { Vector vAttachment; QAngle dummyAngles; C_WeaponTFCBase *pWeapon = m_Shared.GetActiveTFCWeapon(); if ( pWeapon ) { int iAttachment = pWeapon->LookupAttachment( "muzzle_flash" ); if ( iAttachment > 0 ) { float flScale = 1; pWeapon->GetAttachment( iAttachment, vAttachment, dummyAngles ); // The way the models are setup, the up vector points along the barrel.
Vector vForward, vRight, vUp; AngleVectors( dummyAngles, &vForward, &vRight, &vUp ); VectorAngles( vUp, dummyAngles );
FX_MuzzleEffect( vAttachment, dummyAngles, flScale, INVALID_EHANDLE_INDEX, NULL, true ); } } }
Vector vAttachment; QAngle dummyAngles; bool bFoundAttachment = GetAttachment( 1, vAttachment, dummyAngles ); // If we have an attachment, then stick a light on it.
if ( bFoundAttachment ) { dlight_t *el = effects->CL_AllocDlight( LIGHT_INDEX_MUZZLEFLASH + index ); el->origin = vAttachment; el->radius = 24; el->decay = el->radius / 0.05f; el->die = gpGlobals->curtime + 0.05f; el->color.r = 255; el->color.g = 192; el->color.b = 64; el->color.exponent = 5; } }
|