summaryrefslogtreecommitdiff
path: root/game/server/tf/player_vs_environment/tf_population_manager.h
blob: d1420bf626c91708fb73a699a7c389b2baa3f34b (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
//========= Copyright Valve Corporation, All rights reserved. ============//
// tf_populator.h
// KeyValues driven procedural population system
// Michael Booth, April 2011

#ifndef TF_POPULATOR_H
#define TF_POPULATOR_H


#include "bot/tf_bot.h"
#include "tf_mann_vs_machine_stats.h"
#include "tf_populator_spawners.h"
#include "tf_populators.h"

class CMannVsMachineStats;
class KeyValues;
class IPopulator;
class CPopulationManager;
class CWave;

#define MVM_POP_FILE_PATH "scripts/population"

//-----------------------------------------------------------------------
class CPopulationManager : public CPointEntity, public CGameEventListener
{
public:
	DECLARE_CLASS( CPopulationManager, CPointEntity );
	DECLARE_DATADESC();

	CPopulationManager( void );
	virtual ~CPopulationManager();

	// CPointEntity
	virtual void Spawn( void );				// entity spawn

	// CGameEventListener
	virtual void FireGameEvent( IGameEvent *gameEvent );

	virtual void Reset( void );
	virtual bool Initialize( void );
	virtual void Precache( void );

	const char *GetPopulationFilename( void );
	const char *GetPopulationFilenameShort( void );
	void SetPopulationFilename( const char *populationFile );

	// Resolve a pop file shortname to a full name
	bool FindPopulationFileByShortName( const char *pShortName, CUtlString &outFullName );

	// Enumerate possible population files for this map, searching e.g. mapname_*.pop, //BSP/.../*.pop
	// This is separate from the explicit popfile lists for tours.
	static void FindDefaultPopulationFileShortNames( CUtlVector< CUtlString > &outVecShortNames );

	void SetupOnRoundStart( void );

	void Update( void );					// continuously invoked to modify population over time

	// Triggered by GameRules for any mode specific logic that isn't suitable for the entity think (e.g. not simulating)
	void GameRulesThink();

	void UpdateObjectiveResource( void );
	void ResetMap( void );

	void CycleMission ( void );
	bool LoadMissionCycleFile ( void );
	bool IsValidMvMMap( const char *pszMapName );

	// Waves
	void ShowNextWaveDescription( void );
	void StartCurrentWave( void );
	void JumpToWave( uint32 waveNumber, float fCleanMoneyPercent = -1.0f );
	void WaveEnd ( bool bSuccess );

	CWave *GetCurrentWave( void );

	int	 GetWaveNumber( void ) { return m_iCurrentWaveIndex; }
	int GetTotalWaveCount( void ) { return m_waveVector.Count(); }

	// Check Points
	void ClearCheckpoint( void );
	void SetCheckpoint( int waveNumber );
	void RestoreCheckpoint( void );
	void RestoreItemToCheckpointState( CTFPlayer *player, CEconItemView *item );
	void ForgetOtherBottleUpgrades ( CTFPlayer *player, CEconItemView *pItem, int upgradeToKeep );
	void RestorePlayerCurrency ();

	CUtlVector< CUpgradeInfo > *GetPlayerUpgradeHistory ( CTFPlayer *player );	// Returns the Upgrade vector for a given player
	int GetPlayerCurrencySpent ( CTFPlayer *player );
	void AddPlayerCurrencySpent ( CTFPlayer *player, int cost );
	void SendUpgradesToPlayer ( CTFPlayer *player );

	void OnPlayerKilled( CTFPlayer *corpse );
	void OnCurrencyPackFade( void );
	void OnCurrencyCollected( int nAmount, bool bCountAsDropped, bool bIsBonus );
	int GetTotalPopFileCurrency( void );

	void AdjustMinPlayerSpawnTime( void );

	void MarkAllCurrentPlayersSafeToLeave();
	void MvMVictory( void );
	void PlayerDoneViewingLoot( const CTFPlayer* pPlayer );

	void GetSentryBusterDamageAndKillThreshold( int &nDamage, int &nKills ) const;

	bool IsInEndlessWaves ( void );

	// Endless
	float GetHealthMultiplier ( bool bIsTank = false );
	float GetDamageMultiplier ( void );
	void EndlessParseBotUpgrades( void );
	void EndlessRollEscalation ( void );
	void EndlessSetAttributesForBot( CTFBot *pBot );
	bool EndlessShouldResetFlag ();
	void EndlessFlagHasReset ();

	// inlined
	bool IsRestoringCheckpoint( void ) const;	// return true if we are in the process of restoring players to their checkpointed state
	float GetElapsedTime( void ) const;		// return elapsed time since scenario started
	int GetStartingCurrency( void ) const;
	int GetRespawnWaveTime( void ) const;
	bool CanBotsAttackWhileInSpawnRoom( void ) const;
	KeyValues *GetTemplate( const char *pszName ) const;

	bool IsAdvancedPopFile( void ) { return m_bAdvancedPopFile; }
	void SetMapRestartTime( float flTime ) { m_flMapRestartTime = flTime; }
	bool IsPopFileEventType( int fileType ) { return m_nMvMEventPopfileType == fileType; }
	
	void DebugWaveStats();

	void AllocateBots();

	void PauseSpawning();
	void UnpauseSpawning();
	bool IsSpawningPaused() const { return m_bSpawningPaused; }

	bool IsBonusRound() const { return m_bBonusRound; }
	CBaseCombatCharacter* GetBonusBoss() const { return m_hBonusBoss; }

	enum { MVM_INVADERS_TEAM_SIZE = 22 };

	static bool GetWavesUseReadyBetween() { return true; }

	void SetDefaultEventChangeAttributesName( const char* pszDefaultEventChangeAttributesName ) { m_defaultEventChangeAttributesName = pszDefaultEventChangeAttributesName; }
	const char* GetDefaultEventChangeAttributesName() const { return m_defaultEventChangeAttributesName.String(); }
	bool HasEventChangeAttributes( const char* pszEventName ) const;

	static int CollectMvMBots ( CUtlVector< CTFPlayer *> *pBots );

	// Respec
	void RemovePlayerAndItemUpgradesFromHistory( CTFPlayer *pPlayer );
	void AddRespecToPlayer( CTFPlayer *pPlayer );
	void RemoveRespecFromPlayer( CTFPlayer *pPlayer );
	void SetNumRespecsForPlayer( CTFPlayer *pPlayer, int nCount );
	int GetNumRespecsAvailableForPlayer( CTFPlayer *pPlayer );
	int GetNumRespecsEarnedInWave( void ) { return m_nRespecsAwardedInWave; }
	int GetNumRespecsEarned( void ) { return m_nRespecsAwarded; }
	void ResetRespecPoints( void );

	// Buyback
	void SetBuybackCreditsForPlayer( CTFPlayer *pPlayer, int nCount );
	void RemoveBuybackCreditFromPlayer( CTFPlayer *pPlayer );
	int GetNumBuybackCreditsForPlayer( CTFPlayer *pPlayer );
	bool IsPlayerBeingTrackedForBuybacks( CTFPlayer *pPlayer );


private:
	struct CheckpointSnapshotInfo
	{
		CSteamID m_steamId;							// which player this snapshot is for	
		int m_currencySpent;						// how much money they had spent up to this check point
		CUtlVector< CUpgradeInfo > m_upgradeVector;	// the upgrades the player had as this checkpoint
	};

	struct PlayerUpgradeHistory
	{	
		CSteamID m_steamId;							// which player this snapshot is for
		CUtlVector< CUpgradeInfo > m_upgradeVector;	 
		int m_currencySpent;
	};

	void PostInitialize( void );
	bool Parse( void );	// read in population from file from m_filename

	CheckpointSnapshotInfo *FindCheckpointSnapshot( CTFPlayer *player ) const;
	CheckpointSnapshotInfo *FindCheckpointSnapshot( CSteamID id ) const;
	PlayerUpgradeHistory *FindOrAddPlayerUpgradeHistory ( CTFPlayer *player );
	PlayerUpgradeHistory *FindOrAddPlayerUpgradeHistory ( CSteamID steamId );

	void LoadLastKnownMission();
	bool LoadMvMMission( KeyValues *pNextMission );

	CUtlVector< IPopulator * > m_populatorVector;
	char m_popfileFull[ MAX_PATH ];
	char m_popfileShort[ MAX_PATH ];
	
	KeyValues	*m_pTemplates;

	bool m_bIsInitialized;
	bool m_bAllocatedBots;
	
	bool m_bBonusRound;
	CHandle< CBaseCombatCharacter > m_hBonusBoss;

	int m_nStartingCurrency;
	int m_nLobbyBonusCurrency;
	int m_nMvMEventPopfileType;
	int m_nRespawnWaveTime;
	bool m_bFixedRespawnWaveTime;
	bool m_canBotsAttackWhileInSpawnRoom;
	int m_sentryBusterDamageDealtThreshold;
	int m_sentryBusterKillThreshold;

	uint32	m_iCurrentWaveIndex;
	CUtlVector< CWave * > m_waveVector;		// pointers to waves within m_populationVector

	float m_flMapRestartTime;					// Restart the Map if gameover and this time elapses

	CUtlVector< PlayerUpgradeHistory * > m_playerUpgrades;		// list of all players and their upgrades who have played on this MVM rotation

	bool m_isRestoringCheckpoint;

	// checkpoint data must be static because the population manager entity is destroyed and recreated each round
	static CUtlVector< CheckpointSnapshotInfo * > m_checkpointSnapshot;	// snapshot of player state at the saved checkpoint

	static int m_checkpointWaveIndex;				// wave to restart at if scenario lost
	static int m_nNumConsecutiveWipes;

	bool m_bAdvancedPopFile;
	bool m_bCheckForCurrencyAchievement;

	CMannVsMachineStats *m_pMVMStats;
	KeyValues *m_pKvpMvMMapCycle;

	bool m_bSpawningPaused;
	bool m_bIsWaveJumping;
	bool m_bEndlessOn;
	CUtlVector< CMvMBotUpgrade > m_BotUpgradesList;
	CUtlVector< CMvMBotUpgrade > m_EndlessActiveBotUpgrades;
	CUniformRandomStream m_randomizer;
	CUtlVector< int > m_EndlessSeeds;
	bool m_bShouldResetFlag;
	CUtlVector< const CTFPlayer* > m_donePlayers;

	CUtlString m_defaultEventChangeAttributesName;

	// Respec
	CUtlMap< uint64, int > m_PlayerRespecPoints;	// The number of upgrade respecs players (steamID) have
	int m_nRespecsAwarded;
	int m_nRespecsAwardedInWave;
	int m_nCurrencyCollectedForRespec;

	// Buyback
	CUtlMap< uint64, int > m_PlayerBuybackPoints;	// The number of times a player can buyback

};

inline bool CPopulationManager::IsRestoringCheckpoint( void ) const
{
	return m_isRestoringCheckpoint;
}

inline int CPopulationManager::GetStartingCurrency( void ) const
{ 
	return m_nStartingCurrency + m_nLobbyBonusCurrency;
}

inline int CPopulationManager::GetRespawnWaveTime( void ) const
{ 
	return m_nRespawnWaveTime; 
}

inline bool CPopulationManager::CanBotsAttackWhileInSpawnRoom( void ) const
{
	return m_canBotsAttackWhileInSpawnRoom;
}

inline KeyValues *CPopulationManager::GetTemplate( const char *pszName ) const
{ 
	return m_pTemplates->FindKey( pszName ); 
}

// singleton accessor
extern CPopulationManager *g_pPopulationManager;


#endif // TF_POPULATOR_H