summaryrefslogtreecommitdiff
path: root/game/client/tf/c_tf_player.h
blob: c6a7807228ee0a0c8b9a3502b9ba1e6774effb63 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================

#ifndef C_TF_PLAYER_H
#define C_TF_PLAYER_H
#ifdef _WIN32
#pragma once
#endif

#include "tf_playeranimstate.h"
#include "c_baseplayer.h"
#include "tf_shareddefs.h"
#include "baseparticleentity.h"
#include "tf_player_shared.h"
#include "c_tf_playerclass.h"
#include "tf_item.h"
#include "props_shared.h"
#include "hintsystem.h"
#include "c_playerattachedmodel.h"
#include "c_playerrelativemodel.h"
#include "iinput.h"
#include "ihasattributes.h"
#include "GameEventListener.h"
#include "tf_item_inventory.h"
#include "c_tf_mvm_boss_progress_user.h"
#include "c_te_legacytempents.h"


class C_MuzzleFlashModel;
class C_BaseObject;
class C_TFRagdoll;
class C_TFWearable;
class C_CaptureZone;
class C_MerasmusBombEffect;
class CTFReviveDialog;
class C_TFDroppedWeapon;
class C_PasstimePlayerReticle;
class C_PasstimeAskForBallReticle;

extern ConVar tf_medigun_autoheal;
extern ConVar cl_autorezoom;
extern ConVar cl_autoreload;

enum EBonusEffectFilter_t
{
	kEffectFilter_AttackerOnly,
	kEffectFilter_AttackerTeam,
	kEffectFilter_VictimOnly,
	kEffectFilter_VictimTeam,
	kEffectFilter_AttackerAndVictimOnly,
	kEffectFilter_BothTeams,
};

struct BonusEffect_t
{
	BonusEffect_t( const char* pszSoundName, const char* pszParticleName, EBonusEffectFilter_t eParticleFilter, EBonusEffectFilter_t eSoundFilter, bool bPlaySoundInAttackersEars )
		: m_pszSoundName( pszSoundName )
		, m_pszParticleName( pszParticleName )
		, m_eParticleFilter( eParticleFilter )
		, m_eSoundFilter( eSoundFilter )
		, m_bPlaySoundInAttackersEars( bPlaySoundInAttackersEars )

	{}

	const char* m_pszSoundName;
	const char* m_pszParticleName;
	EBonusEffectFilter_t m_eParticleFilter;
	EBonusEffectFilter_t m_eSoundFilter;
	bool m_bPlaySoundInAttackersEars;
};

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
class C_TFPlayer : public C_BasePlayer, public IHasAttributes, public IInventoryUpdateListener, public C_TFMvMBossProgressUser
{
public:

	DECLARE_CLASS( C_TFPlayer, C_BasePlayer );
	DECLARE_CLIENTCLASS();
	DECLARE_PREDICTABLE();
	DECLARE_INTERPOLATION();

	C_TFPlayer();
	~C_TFPlayer();

	virtual void Spawn();

	static C_TFPlayer* GetLocalTFPlayer();

	virtual void UpdateOnRemove( void );

	virtual const QAngle& GetRenderAngles();
	virtual void UpdateClientSideAnimation();
	virtual void SetDormant( bool bDormant );
	virtual void OnPreDataChanged( DataUpdateType_t updateType );
	virtual void OnDataChanged( DataUpdateType_t updateType );
	virtual void ProcessMuzzleFlashEvent();
	virtual void ValidateModelIndex( void );
	void Touch( CBaseEntity *pOther );

	virtual Vector GetObserverCamOrigin( void );
	virtual int DrawModel( int flags );

	virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform );
	virtual void BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );

	virtual bool CreateMove( float flInputSampleTime, CUserCmd *pCmd ) OVERRIDE;
	void CreateVehicleMove( float flInputSampleTime, CUserCmd *pCmd );

	virtual bool		IsAllowedToSwitchWeapons( void );

	void    StopViewModelParticles( C_BaseEntity *pParticleEnt );

	virtual void ClientThink();

	// Deal with recording
	virtual void GetToolRecordingState( KeyValues *msg );

	CTFWeaponBase *GetActiveTFWeapon( void ) const;
	bool IsActiveTFWeapon( CEconItemDefinition *weaponHandle ) const;
	bool IsActiveTFWeapon( const CSchemaItemDefHandle &weaponHandle ) const;

	virtual void Simulate( void );
	virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ) OVERRIDE;
	virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) OVERRIDE;

	CNewParticleEffect *SpawnHalloweenSpellFootsteps( ParticleAttachment_t eParticleAttachment, int iHalloweenFootstepType );

	void FireBullet( CTFWeaponBase *pWpn, const FireBulletsInfo_t &info, bool bDoEffects, int nDamageType, int nCustomDamageType = TF_DMG_CUSTOM_NONE );

	void ImpactWaterTrace( trace_t &trace, const Vector &vecStart );

	bool CanAttack( int iCanAttackFlags = 0 );

	const C_TFPlayerClass *GetPlayerClass( void ) const	{ return &m_PlayerClass; }
	C_TFPlayerClass *GetPlayerClass( void )				{ return &m_PlayerClass; }
	bool IsPlayerClass( int iClass ) const;
	virtual int GetMaxHealth( void ) const;
	int			GetMaxHealthForBuffing()  const;

	virtual int GetRenderTeamNumber( void );

	bool IsWeaponLowered( void );

	void	AvoidPlayers( CUserCmd *pCmd );

	bool	IsABot( void );

	// Get the ID target entity index. The ID target is the player that is behind our crosshairs, used to
	// display the player's name.
	void UpdateIDTarget();
	int GetIDTarget() const;
	void SetForcedIDTarget( int iTarget );

	void SetAnimation( PLAYER_ANIM playerAnim );

	virtual float GetMinFOV() const;

	virtual const QAngle& EyeAngles();

	bool	ShouldDrawSpyAsDisguised();
	virtual int GetBody( void );

	int GetBuildResources( void );

	// MATTTODO: object selection if necessary
	void SetSelectedObject( C_BaseObject *pObject ) {}

	void GetTeamColor( Color &color );
	bool InSameDisguisedTeam( CBaseEntity *pEnt );

	virtual void ComputeFxBlend( void );

	// Taunts/VCDs
	virtual bool	StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget );
	virtual	bool	ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
	virtual void	CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
	bool			StartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
	bool			StopGestureSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
	void			TurnOnTauntCam( void );
	void			TurnOnTauntCam_Finish( void );
	void			TurnOffTauntCam( void );
	void			TurnOffTauntCam_Finish( void );
	bool			IsTaunting( void ) const { return m_Shared.InCond( TF_COND_TAUNTING ); }

	virtual void	InitPhonemeMappings();

	// Gibs.
	void InitPlayerGibs( void );
	void CheckAndUpdateGibType( void );
	void CreatePlayerGibs( const Vector &vecOrigin, const Vector &vecVelocity, float flImpactScale, bool bBurning, bool bWearableGibs=false, bool bOnlyHead=false, bool bDisguiseGibs=false );
	void DropPartyHat( breakablepropparams_t &breakParams, Vector &vecBreakVelocity );
	void DropWearable( C_TFWearable *pItem, const breakablepropparams_t &params );

	int	GetObjectCount( void );
	C_BaseObject *GetObject( int index );
	C_BaseObject *GetObjectOfType( int iObjectType, int iObjectMode=0 ) const;
	int GetNumObjects( int iObjectType, int iObjectMode=0 );

	virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;

	float GetPercentInvisible( void );
	float GetEffectiveInvisibilityLevel( void );	// takes viewer into account
	virtual bool IsTransparent( void ) OVERRIDE { return GetPercentInvisible() > 0.f; }

	virtual void AddDecal( const Vector& rayStart, const Vector& rayEnd,
		const Vector& decalCenter, int hitbox, int decalIndex, bool doTrace, trace_t& tr, int maxLODToDecal = ADDDECAL_TO_ALL_LODS );

	virtual void CalcDeathCamView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov);
	virtual Vector GetChaseCamViewOffset( CBaseEntity *target );
	virtual Vector GetDeathViewPosition();

	void ClientPlayerRespawn( void );

	virtual bool	ShouldDraw();

	virtual int		GetVisionFilterFlags( bool bWeaponsCheck = false );
	virtual void	CalculateVisionUsingCurrentFlags( void );

	void CreateSaveMeEffect( MedicCallerType nType = CALLER_TYPE_NORMAL );
	void StopSaveMeEffect( bool bForceRemoveInstantly = false );

	void CreateTauntWithMeEffect();
	void StopTauntWithMeEffect();

	void CreateKart();
	void RemoveKart();
	C_BaseAnimating *GetKart() const { return m_pKart; }
	void CreateKartEffect( const char *pszEffectName );
	void StopKartEffect();
	void UpdateKartSounds();
	void StartKartBrakeEffect();
	void StopKartBrakeEffect();
	CNetworkVar( int, m_iKartState );

	bool IsAllowedToTaunt( void );
	
	virtual bool	IsOverridingViewmodel( void );
	virtual int		DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags );

	void			SetHealer( C_TFPlayer *pHealer, float flChargeLevel );
	void			SetWasHealedByLocalPlayer( bool bState )	{ m_bWasHealedByLocalPlayer = bState; }
	void			GetHealer( C_TFPlayer **pHealer, float *flChargeLevel ) { *pHealer = m_hHealer; *flChargeLevel = m_flHealerChargeLevel; }
	bool			GetWasHealedByLocalPlayer() { return m_bWasHealedByLocalPlayer; }
	float			MedicGetChargeLevel( CTFWeaponBase **pRetMedigun = NULL );
	bool			MedicIsReleasingCharge( void );
	CBaseEntity		*MedicGetHealTarget( void );

	void			StartBurningSound( void );
	void			StopBurningSound( void );

	void			StopBlastJumpLoopSound( int iUserID );
	
	void			UpdateSpyStateChange( void );

	void			UpdateRecentlyTeleportedEffect( void );
	void			UpdateOverhealEffect( void );
	void			UpdatedMarkedForDeathEffect( bool bFroceStop = false );
	void			CreateOverhealEffect( int iTeam );
	void			UpdateRuneIcon( bool bForceStop = false );

	bool			CanShowClassMenu( void );
	bool			CanShowTeamMenu( void );

	void			InitializePoseParams( void );
	void			UpdateLookAt( void );

	bool			IsEnemyPlayer( void );
	void			ShowNemesisIcon( bool bShow );
	void			ShowDuelingIcon( bool bShow );
	void			ShowIconForIT( bool bShow );

#ifdef STAGING_ONLY
	void			UpdateTranqMark( bool bShow, bool bForceStop = false );
	void			UpdateSpyClassStealParticle( bool bShow );
#endif // STAGING_ONLY
	void			ShowBirthdayEffect( bool bShow );

	CUtlVector<EHANDLE>		*GetSpawnedGibs( void ) { return &m_hSpawnedGibs; }

	bool			HasBombinomiconEffectOnDeath( void );

	Vector			GetClassEyeHeight( void );

	void			ForceUpdateObjectHudState( void );

	bool			GetMedigunAutoHeal( void ){ return tf_medigun_autoheal.GetBool(); }
	bool			ShouldAutoRezoom( void ){ return cl_autorezoom.GetBool(); }
	bool			ShouldAutoReload( void ){ return cl_autoreload.GetBool(); }

	void			GetTargetIDDataString( bool bIsDisguised, OUT_Z_BYTECAP(iMaxLenInBytes) wchar_t *sDataString, int iMaxLenInBytes, bool &bIsAmmoData, bool &bIsKillStreakData );

	void			RemoveDisguise( void );
	bool			CanDisguise( void );
	bool			CanDisguise_OnKill( void );

	virtual void OnAchievementAchieved( int iAchievement );

	virtual void OverrideView( CViewSetup *pSetup );

	bool			CanAirDash( void ) const;
	bool			CanGetWet() const;

	void			CreateBoneAttachmentsFromWearables( C_TFRagdoll *pRagdoll, bool bDisguised );

	bool			CanUseFirstPersonCommand( void );

	bool			IsEffectRateLimited( EBonusEffectFilter_t effect, const C_TFPlayer* pAttacker ) const;
	bool			ShouldPlayEffect( EBonusEffectFilter_t filter, const C_TFPlayer* pAttacker, const C_TFPlayer* pVictim ) const;
	virtual void	FireGameEvent( IGameEvent *event );

	virtual const char* ModifyEventParticles( const char* token );

	// Set the distances the camera should use. 
	void			SetTauntCameraTargets( float back, float up );

	// TF-specific color values for GlowEffect
	virtual void	GetGlowEffectColor( float *r, float *g, float *b );
	void UpdateGlowColor( void );

	virtual const Vector&	GetRenderOrigin( void );

	RTime32			GetSpottedInPVSTime() const { return m_rtSpottedInPVSTime; }
	RTime32			GetJoinedSpectatorTeamTime() const { return m_rtJoinedSpectatorTeam; }
	RTime32			GetJoinedNormalTeamTime() const { return m_rtJoinedNormalTeam; }

	// IHasAttributes
	CAttributeManager		*GetAttributeManager( void ) { return &m_AttributeManager; }
	CAttributeContainer		*GetAttributeContainer( void ) { return NULL; }
	CBaseEntity				*GetAttributeOwner( void ) { return NULL; }
	CAttributeList			*GetAttributeList( void ) { return &m_AttributeList; }
	virtual void			ReapplyProvision( void ) { return; }

	// ITFMvMBossProgressUser
	virtual const char* GetBossProgressImageName() const OVERRIDE;
	virtual float GetBossStatusProgress() const OVERRIDE;

protected:
	CNetworkVarEmbedded(	CAttributeContainerPlayer, m_AttributeManager );

	// IClientNetworkable implementation.
public:
	virtual void	NotifyShouldTransmit( ShouldTransmitState_t state );

public:
	// Shared functions
	float			GetMovementForwardPull( void ) const;
	bool			CanPlayerMove() const;
	float			TeamFortress_CalculateMaxSpeed( bool bIgnoreSpecialAbility = false ) const;
	void			TeamFortress_SetSpeed();
	bool			HasItem( void ) const;				// Currently can have only one item at a time.
	void			SetItem( C_TFItem *pItem );
	C_TFItem		*GetItem( void ) const;
	bool			HasTheFlag( ETFFlagType exceptionTypes[] = NULL, int nNumExceptions = 0 ) const;
	virtual bool	IsAllowedToPickUpFlag( void ) const;
	float			GetCritMult( void ) { return m_Shared.GetCritMult(); }

	virtual void	ItemPostFrame( void );

	void			SetOffHandWeapon( CTFWeaponBase *pWeapon );
	void			HolsterOffHandWeapon( void );
	CTFWeaponBase*	GetOffHandWeapon( void ) { return m_hOffHandWeapon; }

	void			GetActiveSets( CUtlVector<const CEconItemSetDefinition *> *pItemSets );

	virtual int GetSkin();

	float GetLastDamageTime( void ) const { return m_flLastDamageTime; }

	virtual bool		Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon );

	virtual bool		Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) OVERRIDE;
	virtual	bool		Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 ) OVERRIDE;
	virtual void 		SelectItem( const char *pstr, int iSubType = 0 ) OVERRIDE;

	virtual void		UpdateWearables() OVERRIDE;
	CTFWearable			*GetEquippedWearableForLoadoutSlot( int iLoadoutSlot );
	CBaseEntity			*GetEntityForLoadoutSlot( int iLoadoutSlot );			//Gets whatever entity is associated with the loadout slot (wearable or weapon)

	CTFWeaponBase		*Weapon_OwnsThisID( int iWeaponID ) const;
	CTFWeaponBase		*Weapon_GetWeaponByType( int iType );

	virtual void		GetStepSoundVelocities( float *velwalk, float *velrun );
	virtual void		SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking );
	virtual const char *GetOverrideStepSound( const char *pszBaseStepSoundName );

	virtual void		OnEmitFootstepSound( const CSoundParameters& params, const Vector& vecOrigin, float fVolume );

	virtual void		ModifyEmitSoundParams( EmitSound_t &params );

	virtual void		ThirdPersonSwitch( bool bThirdperson );

	bool	DoClassSpecialSkill( void );
	bool	EndClassSpecialSkill( void );
	bool	CanGoInvisible( bool bAllowWhileCarryingFlag = false );
	int		GetMaxAmmo( int iAmmoIndex, int iClassIndex = -1 );

	//-----------------------------------------------------------------------------------------------------
	// Return true if we are a "mini boss" in Mann Vs Machine mode
	bool IsMiniBoss( void ) const;
	bool ShouldTauntHintIconBeVisible() const;
	virtual bool IsHealthBarVisible( void ) const OVERRIDE;

	bool	CanStartPhase( void );

	bool	CanPickupBuilding( CBaseObject *pPickupObject );
	bool	TryToPickupBuilding( void );
	void	StartBuildingObjectOfType( int iType, int iObjectMode=0 );

	void			FeignDeath( CTakeDamageInfo& info );

	C_CaptureZone *GetCaptureZoneStandingOn( void );
	C_CaptureZone *GetClosestCaptureZone( void );

	float			GetMetersRan( void )	{ return m_fMetersRan; }
	void			SetMetersRan( float fMeters, int iFrame );

	CEconItemView *GetInspectItem( int *iLastItem );

	void			SetBodygroupsDirty( void );
	void			RecalcBodygroupsIfDirty( void );

	bool			CanMoveDuringTaunt();
	bool			ShouldStopTaunting();
	bool			IsTauntForceMovingForward() const { return m_bTauntForceMoveForward; }
	float			GetTauntMoveAcceleration() const { return m_flTauntMoveAccelerationTime; }
	float			GetTauntMoveSpeed() const { return m_flTauntForceMoveForwardSpeed; }
	float			GetTauntTurnAccelerationTime() const { return m_flTauntTurnAccelerationTime; }
	bool			IsReadyToTauntWithPartner( void ) const { return m_bIsReadyToHighFive; }
	CTFPlayer *		GetTauntPartner( void )		{ return m_hHighFivePartner; }
	float			GetTauntYaw( void )				{ return m_flTauntYaw; }
	float			GetPrevTauntYaw( void )		{ return m_flPrevTauntYaw; }
	void			SetTauntYaw( float flTauntYaw );
	int				GetActiveTauntSlot() const { return m_nActiveTauntSlot; }
	void			PlayTauntSoundLoop( const char *pszSoundLoopName );
	void			StopTauntSoundLoop();
	float			GetCurrentTauntMoveSpeed() const { return m_flCurrentTauntMoveSpeed; }
	void			SetCurrentTauntMoveSpeed( float flSpeed ) { m_flCurrentTauntMoveSpeed = flSpeed; }
	float			GetVehicleReverseTime() const { return m_flVehicleReverseTime; }
	void			SetVehicleReverseTime( float flTime ) { m_flVehicleReverseTime = flTime; }

	CEconItemView	*GetTauntEconItemView() { return m_TauntEconItemView.IsValid() ? &m_TauntEconItemView : NULL; }

	float			GetHeadScale() const { return m_flHeadScale; }
	float			GetTorsoScale() const { return m_flTorsoScale; }
	float			GetHandScale() const { return m_flHandScale; }
	float			GetLastResistTime()	const { return m_flLastResistTime; }
	bool			BRenderAsZombie( bool bWeaponsCheck = false );
	static void AdjustSkinIndexForZombie( int iClassIndex, int &iSkinIndex );

	// Ragdolls.
	virtual C_BaseAnimating *BecomeRagdollOnClient();
	virtual IRagdoll		*GetRepresentativeRagdoll() const;
	EHANDLE	m_hRagdoll;
	Vector m_vecRagdollVelocity;

	// Objects
	int CanBuild( int iObjectType, int iObjectMode=0 );
	CUtlVector< CHandle<C_BaseObject> > m_aObjects;

	virtual CStudioHdr *OnNewModel( void );

	void				DisplaysHintsForTarget( C_BaseEntity *pTarget );

	// Shadows
	virtual ShadowType_t ShadowCastType( void ) ;
	virtual void GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType );
	virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
	virtual bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const;

	CMaterialReference *GetInvulnMaterialRef( void ) { return &m_InvulnerableMaterial; }
	bool IsNemesisOfLocalPlayer();
	bool ShouldShowDuelingIcon();
	bool ShouldShowNemesisIcon();

	virtual	IMaterial *GetHeadLabelMaterial( void );

	// Spy Cigarette
	bool CanLightCigarette( void );

	void		UpdateDemomanEyeEffect( int iDecapitations );
	const char* GetDemomanEyeEffectName( int iDecapitations );

	int		GetCurrency( void ){ return m_nCurrency; }

	virtual void UpdateMVMEyeGlowEffect( bool bVisible );

	void	UpdateKillStreakEffects( int iCount, bool bKillScored = false );
	const char *GetEyeGlowEffect() { return m_pszEyeGlowEffectName; }
	Vector GetEyeGlowColor( bool bAlternate ) { return bAlternate? m_vEyeGlowColor1 : m_vEyeGlowColor2 ; }

	// Bounty Mode
	int	 GetExperienceLevel( void ) { return m_nExperienceLevel; }

	// Matchmaking
	bool	GetMatchSafeToLeave() { return m_bMatchSafeToLeave; }

	// Halloween silliness.
	void	HalloweenBombHeadUpdate( void );


	bool	IsUsingVRHeadset( void ){ return m_bUsingVRHeadset; }

	bool	ShouldPlayerDrawParticles( void );

	bool	IsPlayerOnSteamFriendsList( C_BasePlayer *pPlayer );

protected:

	void ResetFlexWeights( CStudioHdr *pStudioHdr );

	virtual void CalcInEyeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );

	virtual void UpdateGlowEffect( void );
	virtual void DestroyGlowEffect( void );

private:

	bool ShouldShowPowerupGlowEffect();
	void GetPowerupGlowEffectColor( float *r, float *g, float *b );

	void HandleTaunting( void );
	void TauntCamInterpolation( void );

	void OnPlayerClassChange( void );
	void UpdatePartyHat( void );

	void InitInvulnerableMaterial( void );

	void GetHorriblyHackedRailgunPosition( const Vector& vStart, Vector *out_pvStartPos );
	void MaybeDrawRailgunBeam( IRecipientFilter *pFilter, CTFWeaponBase *pWeapon, const Vector& vStartPos, const Vector& vEndPos );

	bool				m_bWasTaunting;
	bool				m_bTauntInterpolating;
	CameraThirdData_t	m_TauntCameraData;
	float				m_flTauntCamCurrentDist;
	float				m_flTauntCamTargetDist;
	float				m_flTauntCamCurrentDistUp;
	float				m_flTauntCamTargetDistUp;

	QAngle				m_angTauntPredViewAngles;
	QAngle				m_angTauntEngViewAngles;

	CSoundPatch			*m_pTauntSoundLoop;

	C_TFPlayerClass		m_PlayerClass;

	// ID Target
	int					m_iIDEntIndex;
	int					m_iForcedIDTarget;

	CNewParticleEffect	*m_pTeleporterEffect;
	bool				m_bToolRecordingVisibility;

	int					m_iOldSpawnCounter;

	// Healer
	CHandle<C_TFPlayer>	m_hHealer;
	bool				m_bWasHealedByLocalPlayer;
	float				m_flHealerChargeLevel;
	int					m_iOldHealth;
	int					m_nOldMaxHealth;

	float				m_fMetersRan;
	int					m_iLastRanFrame;

	HPARTICLEFFECT		m_pEyeEffect;

	bool				m_bOldCustomModelVisible;

	CHandle< C_BaseCombatWeapon > m_hOldActiveWeapon;

	// Look At
	/*
	int m_headYawPoseParam;
	int m_headPitchPoseParam;
	float m_headYawMin;
	float m_headYawMax;
	float m_headPitchMin;
	float m_headPitchMax;
	float m_flLastBodyYaw;
	float m_flCurrentHeadYaw;
	float m_flCurrentHeadPitch;
	*/

	// Spy cigarette smoke
	bool m_bCigaretteSmokeActive;

	// Medic callout particle effect
	CNewParticleEffect	*m_pSaveMeEffect;
	CNewParticleEffect	*m_pTauntWithMeEffect;

	bool m_bUpdateObjectHudState;
	bool	m_bBodygroupsDirty;

	HPARTICLEFFECT	m_hKartDamageEffect;
	CNetworkVar( float, m_flKartNextAvailableBoost );
	CNetworkVar( int,	m_iKartHealth );
	int			m_iOldKartHealth;
	void		UpdateKartEffects();

	void		UpdateKartState();
	int			m_iOldKartState;

	C_BaseAnimating *m_pKart;

public:
	float			GetKartSpeedBoost( void );
	float			GetKartHealth( void )				{ return m_iKartHealth; }

	CTFPlayerShared m_Shared;
	friend class CTFPlayerShared;

// Called by shared code.
public:
	float GetClassChangeTime() const { return m_flChangeClassTime; }
	void SetFootStamps( int nFootStamps ) { m_nFootStamps = nFootStamps; }

	void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 );
	bool PlayAnimEventInPrediction( PlayerAnimEvent_t event );

	bool							GetPredictable( void ) const;

	// Halloween
	void CreateBombonomiconHint();
	void DestroyBombonomiconHint();

	void CleanUpAnimationOnSpawn();
	CTFPlayerAnimState *m_PlayerAnimState;

	QAngle	m_angEyeAngles;
	CInterpolatedVar< QAngle >	m_iv_angEyeAngles;

	CNetworkHandle( C_TFItem, m_hItem );

	CNetworkHandle( C_TFWeaponBase, m_hOffHandWeapon );
	CNetworkHandle( C_TFPlayer, m_hCoach );
	CNetworkHandle( C_TFPlayer, m_hStudent );

	CGlowObject		*m_pStudentGlowEffect;
	CGlowObject		*m_pPowerupGlowEffect;

	int				m_iOldPlayerClass;	// Used to detect player class changes
	bool			m_bIsDisplayingNemesisIcon;
	bool			m_bIsDisplayingDuelingIcon;
	bool			m_bIsDisplayingIconForIT;
	bool			m_bIsDisplayingTranqMark;
	bool			m_bShouldShowBirthdayEffect;

	RuneTypes_t		m_eDisplayingRuneIcon;

	float			m_flLastDamageTime;

	bool			m_bInPowerPlay;

	int				m_iSpawnCounter;
	bool			m_bArenaSpectator;

	bool			m_bIsMiniBoss;
	bool			m_bIsABot;
	int				m_nBotSkill;
	int				m_nOldBotSkill;
	bool			m_bSaveMeParity;
	bool			m_bOldSaveMeParity;
	bool			m_bIsCoaching;

private:
	void			UpdateTauntItem();
	void			ParseSharedTauntDataFromEconItemView( CEconItemView *pEconItemView );

	bool			m_bAllowMoveDuringTaunt;
	bool			m_bTauntForceMoveForward;
	float			m_flTauntForceMoveForwardSpeed;
	float			m_flTauntMoveAccelerationTime;
	float			m_flTauntTurnSpeed;
	float			m_flTauntTurnAccelerationTime;
	bool			m_bIsReadyToHighFive;
	CNetworkHandle( C_TFPlayer, m_hHighFivePartner );
	int				m_nForceTauntCam;
	float			m_flTauntYaw;
	float			m_flPrevTauntYaw;
	int				m_nActiveTauntSlot;
	int				m_nPrevTauntSlot;
	item_definition_index_t	m_iTauntItemDefIndex;
	item_definition_index_t m_iPrevTauntItemDefIndex;
	float			m_flCurrentTauntMoveSpeed;
	float			m_flVehicleReverseTime;

	int				m_nTauntSequence;
	float			m_flTauntStartTime;
	float			m_flTauntDuration;

	CEconItemView	m_TauntEconItemView;

public:

	int				m_nOldWaterLevel;
	float			m_flWaterEntryTime;
	bool			m_bWaterExitEffectActive;

	bool			m_bDuckJumpInterp;
	float			m_flFirstDuckJumpInterp;
	float			m_flLastDuckJumpInterp;
	float			m_flDuckJumpInterp;

	CMaterialReference	m_InvulnerableMaterial;


	// Burning
	CSoundPatch			*m_pBurningSound;
	HPARTICLEFFECT      m_pBurningEffect;
	float				m_flBurnEffectStartTime;

	// Urine
	HPARTICLEFFECT		m_pUrineEffect;

	// Milk
	HPARTICLEFFECT		m_pMilkEffect;

	// Soldier Buff
	HPARTICLEFFECT		m_pSoldierOffensiveBuffEffect;
	HPARTICLEFFECT		m_pSoldierDefensiveBuffEffect;
	HPARTICLEFFECT		m_pSoldierOffensiveHealthRegenBuffEffect;
	HPARTICLEFFECT		m_pSoldierNoHealingDamageBuffEffect;

	// Speed boost
	HPARTICLEFFECT		m_pSpeedBoostEffect;

	// Taunt effects
	HPARTICLEFFECT		m_pTauntEffect;

	// Temp HACK for crit boost
	HPARTICLEFFECT m_pCritBoostEffect;

	HPARTICLEFFECT m_pOverHealedEffect;
	HPARTICLEFFECT m_pPhaseStandingEffect;

	HPARTICLEFFECT m_pStunnedEffect;

	HPARTICLEFFECT m_pMegaHealEffect;
	HPARTICLEFFECT m_pRadiusHealEffect;
	HPARTICLEFFECT m_pKingRuneRadiusEffect;
	HPARTICLEFFECT m_pKingBuffRadiusEffect;
	HPARTICLEFFECT m_pRunePlagueEffect;
	C_LocalTempEntity*	m_pTempShield;
	float				m_flLastResistTime;

	HPARTICLEFFECT m_pSappedPlayerEffect;
	HPARTICLEFFECT m_pMVMEyeGlowEffect[ 2 ];

	// KillStreak Weapons
	char m_pszEyeGlowEffectName[MAX_PATH];
	Vector m_vEyeGlowColor1;
	Vector m_vEyeGlowColor2;
	HPARTICLEFFECT m_pEyeGlowEffect[ 2 ];
	float m_flNextSheenStartTime;
	
	HPARTICLEFFECT m_pMVMBotRadiowave;

	HPARTICLEFFECT m_pRuneChargeReadyEffect;

#ifdef STAGING_ONLY
	HPARTICLEFFECT m_pRocketPackEffect;
#endif // STAGING_ONLY

	enum EKartParticles
	{
		KART_PARTICLE_LEFT_LIGHT = 0,
		KART_PARTICLE_RIGHT_LIGHT,

		KART_PARTICLE_LEFT_WHEEL,
		KART_PARTICLE_RIGHT_WHEEL,
		NUM_KART_PARTICLES
	};
	HPARTICLEFFECT m_pKartParticles[ NUM_KART_PARTICLES ];

	enum EKartSounds
	{
		KART_SOUND_ENGINE_LOOP = 0,
		KART_SOUND_BURNOUT_LOOP,

		NUM_KART_SOUNDS,
	};
	CSoundPatch			*m_pKartSounds[ NUM_KART_SOUNDS ];

	CNewParticleEffect	*m_pDisguisingEffect;
	float m_flDisguiseEffectStartTime;
	float m_flDisguiseEndEffectStartTime;

	EHANDLE					m_hFirstGib;
	EHANDLE					m_hHeadGib;
	CUtlVector<EHANDLE>		m_hSpawnedGibs;

	int				m_iOldTeam;
	int				m_iOldClass;
	int				m_iOldDisguiseTeam;
	int				m_iOldDisguiseClass;
	int				m_iOldObserverMode;
	EHANDLE			m_hOldObserverTarget;

	bool			m_bDisguised;
	int				m_iPreviousMetal;

	int GetNumActivePipebombs( void );

	int				m_iSpyMaskBodygroup;
	Vector			m_vecCustomModelOrigin;

	// Halloween
	CHandle<C_PlayerAttachedModel>	m_hHalloweenBombHat;
	CHandle<C_MerasmusBombEffect>	m_hBombonomiconHint;
	CHandle<C_PlayerAttachedModel>	m_hHalloweenKartCage;
	float			m_flBombDelay;

	// Achievements
	float m_flSaveMeExpireTime;

	//CountdownTimer m_LeaveServerTimer;

	//----------------------------
	// INVENTORY MANAGEMENT
public:
	// IInventoryUpdateListener
	virtual void InventoryUpdated( CPlayerInventory *pInventory );
	virtual void SOCacheUnsubscribed( const CSteamID & steamIDOwner ) { m_Shared.SetLoadoutUnavailable( true ); }
	void		 UpdateInventory( bool bInit );

	// Inventory access
	CTFPlayerInventory	*Inventory( void ) { return &m_Inventory; }

	bool		CanDisplayAllSeeEffect( EAttackBonusEffects_t effect ) const;
	void		SetNextAllSeeEffectTime( EAttackBonusEffects_t effect, float flTime );

private:
	CTFPlayerInventory	m_Inventory;
	bool				m_bInventoryReceived;

private:
	float			m_flChangeClassTime;

	float m_flWaterImpactTime;
	RTime32 m_rtSpottedInPVSTime;
	RTime32 m_rtJoinedSpectatorTeam;
	RTime32 m_rtJoinedNormalTeam;

	// Gibs.
	CUtlVector< int > m_aSillyGibs;
	CUtlVector< char* > m_aNormalGibs;
	CUtlVector<breakmodel_t>	m_aGibs;

	C_TFPlayer( const C_TFPlayer & );

	mutable char m_bIsCalculatingMaximumSpeed;

	// In-game currency
	int m_nCurrency;
	int m_nOldCurrency;

	// Bounty Mode
	int m_nExperienceLevel;
	int m_nExperienceLevelProgress;
	int m_nPrevExperienceLevel;

	// Matchmaking
	// is this player bound to the match on penalty of abandon. Sync'd via local-player-only DT
	bool m_bMatchSafeToLeave;

	// Medic healtarget active weapon ammo/clip count
	uint16	m_nActiveWpnClip;
	
	// Blast jump whistle
	CSoundPatch		*m_pBlastJumpLoop;
	float			m_flBlastJumpLaunchTime;

	CNetworkVar( float, m_flHeadScale );
	CNetworkVar( float, m_flTorsoScale );
	CNetworkVar( float, m_flHandScale );

	// Allseecrit throttle - other clients ask us if we can be the source of another particle+sound
	float	m_flNextMiniCritEffectTime[ kBonusEffect_Count ];

	CNetworkVar( bool, m_bUseBossHealthBar );

	CNetworkVar( bool, m_bUsingVRHeadset );

	CNetworkVar( bool, m_bForcedSkin );
	CNetworkVar( int, m_nForcedSkin );

	int m_nFootStamps;

	vgui::DHANDLE< CTFReviveDialog > m_hRevivePrompt;

public:
	void SetShowHudMenuTauntSelection( bool bShow ) { m_bShowHudMenuTauntSelection = bShow; }
	bool ShouldShowHudMenuTauntSelection() const { return m_bShowHudMenuTauntSelection; }

private:
	bool m_bShowHudMenuTauntSelection;

public:
	CBaseEntity *GetGrapplingHookTarget() const { return m_hGrapplingHookTarget; }

	bool IsUsingActionSlot() const { return m_bUsingActionSlot; }
	void SetUsingActionSlot( bool bUsingActionSlot ) { m_bUsingActionSlot = bUsingActionSlot; }
	
	void SetSecondaryLastWeapon( CBaseCombatWeapon *pSecondaryLastWeapon ) { m_hSecondaryLastWeapon = pSecondaryLastWeapon; }
	CBaseCombatWeapon* GetSecondaryLastWeapon() const { return m_hSecondaryLastWeapon; }

	bool CanPickupDroppedWeapon( const C_TFDroppedWeapon *pWeapon );
	C_TFDroppedWeapon* GetDroppedWeaponInRange();

	bool HasCampaignMedal( int iMedal );
	CampaignMedalDisplayType_t GetCampaignMedalType( void );
	const char *GetCampaignMedalImage( void );

	void SetInspectTime( float flInspectTime ) { m_flInspectTime = flInspectTime; }
	bool IsInspecting() const;
	void HandleInspectHint();

	bool AddOverheadEffect( const char *pszEffectName );
	void RemoveOverheadEffect( const char *pszEffectName, bool bRemoveInstantly );
	void UpdateOverheadEffects();
	Vector GetOverheadEffectPosition();

	int GetSkinOverride() const { return m_iPlayerSkinOverride; }

private:
	CNetworkHandle( CBaseEntity, m_hGrapplingHookTarget );
	CNetworkHandle( CBaseCombatWeapon, m_hSecondaryLastWeapon );
	CNetworkVar( bool, m_bUsingActionSlot );
	CNetworkVar( int, m_iCampaignMedals );
	CNetworkVar( float, m_flInspectTime );

	bool m_bNotifiedWeaponInspectThisLife;

	C_PasstimePlayerReticle *m_pPasstimePlayerReticle;
	C_PasstimeAskForBallReticle *m_pPasstimeAskForBallReticle;

	CUtlMap< const char *, HPARTICLEFFECT > m_mapOverheadEffects;
	float m_flOverheadEffectStartTime;

	CNetworkVar( int, m_iPlayerSkinOverride );
};

inline C_TFPlayer* ToTFPlayer( C_BaseEntity *pEntity )
{
	if ( !pEntity || !pEntity->IsPlayer() )
		return NULL;

	Assert( dynamic_cast<C_TFPlayer*>( pEntity ) != 0 );
	return static_cast< C_TFPlayer* >( pEntity );
}

void SetAppropriateCamera( C_TFPlayer *pPlayer );

class C_TFPlayerPreviewEffect
{
public:
	// If you re-order this list, please update TF_ImportPreview_Effect* in tf_english.txt
	enum PREVIEW_EFFECT
	{
		PREVIEW_EFFECT_NONE,
		PREVIEW_EFFECT_UBER,
		//PREVIEW_EFFECT_CRIT,	// Punting on particle effects for now
		PREVIEW_EFFECT_URINE,
		//PREVIEW_EFFECT_MILK,	// Punting on particle effects for now
		//PREVIEW_EFFECT_INVIS,	// The CMDLPanel draw path doesn't handle transparency at the moment
		PREVIEW_EFFECT_BURN,
		NUM_PREVIEW_EFFECTS
	};

public:
	C_TFPlayerPreviewEffect();

	void SetEffect(PREVIEW_EFFECT nEffect) { m_nPreviewEffect = nEffect; }
	PREVIEW_EFFECT GetEffect() const { return m_nPreviewEffect; }

	void SetTeam(int nTeam);
	int GetTeam() const { return m_nTeam; }

	CMaterialReference *GetInvulnMaterialRef( void ) { return &m_InvulnerableMaterial; }

	void Reset();

protected:
	PREVIEW_EFFECT m_nPreviewEffect;
	int m_nTeam;
	CMaterialReference	m_InvulnerableMaterial;
};
extern C_TFPlayerPreviewEffect g_PlayerPreviewEffect;

#endif // C_TF_PLAYER_H