summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_weapon_medigun.h
blob: fdc1fc73d2f2e75d7548dc764149c145b961501e (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================

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

#include "tf_weaponbase_gun.h"

#if defined( CLIENT_DLL )
#define CWeaponMedigun C_WeaponMedigun
#define CTFMedigunShield C_TFMedigunShield
#endif

class CTFMedigunShield;
class CTFReviveMarker;

enum medigun_weapontypes_t
{
	MEDIGUN_STANDARD = 0,
	MEDIGUN_UBER,
	MEDIGUN_QUICKFIX,
	MEDIGUN_RESIST,
};

enum medigun_resist_types_t
{
	MEDIGUN_BULLET_RESIST = 0,
	MEDIGUN_BLAST_RESIST,
	MEDIGUN_FIRE_RESIST,
	MEDIGUN_NUM_RESISTS
};

struct MedigunEffects_t
{
	ETFCond eCondition;
	ETFCond eWearingOffCondition;
	const char *pszChargeOnSound;
	const char *pszChargeOffSound;
};

extern MedigunEffects_t g_MedigunEffects[MEDIGUN_NUM_CHARGE_TYPES];

#define MAX_HEALING_TARGETS			1	//6

#define CLEAR_ALL_TARGETS			-1




//=========================================================
// Beam healing gun
//=========================================================
class CWeaponMedigun : public CTFWeaponBaseGun
{
	DECLARE_CLASS( CWeaponMedigun, CTFWeaponBaseGun );
public:
	DECLARE_NETWORKCLASS();
	DECLARE_PREDICTABLE();

	CWeaponMedigun( void );
	~CWeaponMedigun( void );

	virtual void	Precache();

	virtual bool	Deploy( void );
	virtual bool	Holster( CBaseCombatWeapon *pSwitchingTo );
	virtual void	UpdateOnRemove( void );
	virtual void	ItemHolsterFrame( void );
	virtual void	ItemPostFrame( void );
	virtual bool	Lower( void );
	virtual void	PrimaryAttack( void );
	virtual void	SecondaryAttack( void );
	virtual void	WeaponIdle( void );
	void			DrainCharge( void );
	virtual void	WeaponReset( void );

	virtual float	GetTargetRange( void );
	virtual float	GetStickRange( void );
	virtual float	GetHealRate( void );
	virtual bool	AppliesModifier( void ) { return true; }

	virtual int		GetWeaponID( void ) const			{ return TF_WEAPON_MEDIGUN; }
	int				GetMedigunType( void ) const;


	bool			IsReleasingCharge( void ) const;
	medigun_charge_types GetChargeType( void ) const;

	void			CycleResistType();
	medigun_resist_types_t GetResistType() const;

	CBaseEntity		*GetHealTarget( void ) { return IsAttachedToBuilding() ? NULL : m_hHealingTarget.Get(); }

	bool			IsAllowedToTargetBuildings( void );
	bool			IsAttachedToBuilding( void );

#ifdef GAME_DLL
	// We may or may not be healing this person still. Resets on WeaponReset
	CBaseEntity		*GetMostRecentHealTarget( void ) { return m_hLastHealingTarget.Get(); }
	void			RecalcEffectOnTarget( CTFPlayer *pPlayer, bool bInstantRemove = false );
#endif

	float			GetReleaseStartedAt( void ) { return m_flReleaseStartedAt; }

#if defined( CLIENT_DLL )
	// Stop all sounds being output.
	void			StopHealSound( bool bStopHealingSound = true, bool bStopNoTargetSound = true );

	virtual void	OnDataChanged( DataUpdateType_t updateType );
	virtual void	ClientThink();
	void			UpdateEffects( void );
	void			ForceHealingTargetUpdate( void ) { m_bUpdateHealingTargets = true; }

	void			StopChargeEffect( bool bImmediately );
	void			ManageChargeEffect( void );

	void			UpdateMedicAutoCallers( void );
#else

	void			HealTargetThink( void );
	void			AddCharge( float flPercentage );
	void			SubtractCharge( float flPercentage );
#endif

	void			SetChargeLevel( float flChargeLevel ) { m_flChargeLevel = flChargeLevel; }
	float			GetChargeLevel( void ) const { return m_flChargeLevel; }
	float			GetMinChargeAmount( void ) const;

	virtual void	OnControlStunned( void );

	virtual bool	IsHolstered(){ return m_bHolstered; }

	float			GetProgress( void );
	const char*		GetEffectLabelText( void ) { return "#TF_Rescue"; }
	bool			EffectMeterShouldFlash( void );

private:
	void					SubtractChargeAndUpdateDeployState( float flSubtractAmount, bool bForceDrain );
	bool					FindAndHealTargets( void );
	void					MaintainTargetInSlot();
	void					FindNewTargetForSlot();
	void					RemoveHealingTarget( bool bStopHealingSelf = false );
	bool					HealingTarget( CBaseEntity *pTarget );
	bool					AllowedToHealTarget( CBaseEntity *pTarget );
	void					CheckAchievementsOnHealTarget( void );
	void					StartHealingTarget( CBaseEntity *pTarget );
	void					StopHealingOwner( void );

	const char				*GetHealSound() const;

#ifdef GAME_DLL
	void					UberchargeChunkDeployed();
#endif

	void					CreateMedigunShield( void );
	void					RemoveMedigunShield( void );

public:

#ifdef STAGING_ONLY
	CTFMedigunShield		*GetMedigunShield() const { return m_hMedigunShield; }
	bool					HasPermanentShield() const;
#endif // STAGING_ONLY

#ifdef GAME_DLL
	CNetworkHandle( CBaseEntity, m_hHealingTarget );
	CHandle< CBaseEntity > m_hLastHealingTarget;
#else
	CNetworkHandle( C_BaseEntity, m_hHealingTarget );
#endif

	bool					m_bWasHealingBeforeDeath;

protected:
	// Networked data.
	CNetworkVar( bool,		m_bHealing );
	CNetworkVar( bool,		m_bAttacking );

	double					m_flNextBuzzTime;
	float					m_flHealEffectLifetime;	// Count down until the healing effect goes off.
	float					m_flReleaseStartedAt;

	CNetworkVar( bool,		m_bHolstered );
	CNetworkVar( bool,		m_bChargeRelease );
	CNetworkVar( float,		m_flChargeLevel );
	CNetworkVar( int,		m_nChargeResistType );

	float					m_flNextTargetCheckTime;
	bool					m_bCanChangeTarget; // used to track the PrimaryAttack key being released for AutoHeal mode
	bool					m_bAttack2Down;
	bool					m_bAttack3Down;
	bool					m_bReloadDown;
	float					m_flEndResistCharge;
	
	struct targetdetachtimes_t
	{
		float	flTime;
		EHANDLE	hTarget;
	};
	CUtlVector<targetdetachtimes_t>		m_DetachedTargets; // Tracks times we last applied charge to a target. Used to drain faster for more targets.

#ifdef GAME_DLL
	CDamageModifier			m_DamageModifier;		// This attaches to whoever we're healing.
	bool					m_bHealingSelf;
	int						m_nHealTargetClass;
	int						m_nChargesReleased;
#endif

	CHandle< CTFMedigunShield > m_hMedigunShield;
	CHandle< CTFReviveMarker > m_hReviveMarker;

#ifdef CLIENT_DLL
	bool					m_bPlayingSound;
	bool					m_bUpdateHealingTargets;
	struct healingtargeteffects_t
	{
		C_BaseEntity		*pOwner;
		C_BaseEntity		*pTarget;
		CNewParticleEffect	*pEffect;
		CNewParticleEffect	*pCustomEffect;
	};
	healingtargeteffects_t m_hHealingTargetEffect;

	float					m_flDenySecondary;
	bool					m_bOldChargeRelease;
	int						m_nOldChargeResistType;

	C_BaseEntity		*m_pChargeEffectOwner;
	CNewParticleEffect	*m_pChargeEffect;
	CSoundPatch			*m_pChargedSound;
	CSoundPatch			*m_pDisruptSound;

	CUtlVector< int >	m_iAutoCallers;
	float				m_flAutoCallerCheckTime;
#endif

private:														
	CWeaponMedigun( const CWeaponMedigun & );
};

class CTFMedigunShield : public CBaseAnimating
{
	DECLARE_CLASS( CTFMedigunShield, CBaseAnimating );

public:
	DECLARE_NETWORKCLASS();
	DECLARE_PREDICTABLE();
	DECLARE_DATADESC();

	CTFMedigunShield();
	~CTFMedigunShield();

	virtual void Spawn();
	virtual void Precache();
	virtual bool IsCombatItem( void ) const { return true; }

	void UpdateShieldPosition( void );

#ifdef GAME_DLL
	virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
	virtual int OnTakeDamage( const CTakeDamageInfo &info );

	static CTFMedigunShield *Create( CTFPlayer *pOwner );
	// virtual bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace );
	virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
	virtual void StartTouch( CBaseEntity *pOther ) OVERRIDE;
	void ShieldTouch( CBaseEntity *pOther );
	virtual void EndTouch( CBaseEntity *pOther ) OVERRIDE;
	void ShieldThink( void );
	void RemoveShield( void );

#ifdef STAGING_ONLY
	void SetPermanentShield( bool bPermanent ) { m_bPermanentShield = bPermanent; }
#endif // STAGING_ONLY

#else
	virtual void ClientThink();
#endif

private:
	int m_nBlinkCount;
#ifdef GAME_DLL
	float m_flShieldEnergyLevel;
	CSoundPatch	*m_pTouchLoop;

#ifdef STAGING_ONLY
	bool m_bPermanentShield;
#endif // STAGING_ONLY

#endif // GAME_DLL
};

#endif // TF_WEAPON_MEDIGUN_H