Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1054 lines
32 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #ifdef CLIENT_DLL
  8. #include "achievementmgr.h"
  9. #include "baseachievement.h"
  10. #include "tf_hud_statpanel.h"
  11. #include "c_tf_team.h"
  12. #include "c_tf_player.h"
  13. #include "c_tf_playerresource.h"
  14. #include "tf_gamerules.h"
  15. #include "achievements_tf.h"
  16. //----------------------------------------------------------------------------------------------------------------
  17. class CAchievementTFPyro_BaseBurn : public CBaseTFAchievement
  18. {
  19. public:
  20. virtual void ListenForEvents()
  21. {
  22. ListenForGameEvent( "player_ignited" );
  23. }
  24. virtual void FireGameEvent_Internal( IGameEvent *event )
  25. {
  26. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  27. if ( FStrEq( event->GetName(), "player_ignited" ) )
  28. {
  29. int iPyro = event->GetInt( "pyro_entindex" );
  30. CBaseEntity *pPyro = UTIL_PlayerByIndex( iPyro );
  31. if ( pPyro == pLocalPlayer )
  32. {
  33. int iVictim = event->GetInt( "victim_entindex" );
  34. C_TFPlayer *pTFVictim = ToTFPlayer( UTIL_PlayerByIndex( iVictim ) );
  35. if ( pTFVictim )
  36. {
  37. BurnedVictim( pPyro, pTFVictim, event );
  38. }
  39. }
  40. }
  41. }
  42. virtual void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  43. {
  44. }
  45. };
  46. //----------------------------------------------------------------------------------------------------------------
  47. class CAchievementTFPyro_KillPlayersWhileDead : public CBaseTFAchievement
  48. {
  49. void Init()
  50. {
  51. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  52. SetGoal( 15 );
  53. SetStoreProgressInSteam( true );
  54. }
  55. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  56. {
  57. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  58. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  59. {
  60. if ( !pLocalPlayer->IsAlive() )
  61. {
  62. IncrementCount();
  63. }
  64. }
  65. }
  66. };
  67. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillPlayersWhileDead, ACHIEVEMENT_TF_PYRO_KILL_POSTDEATH, "TF_PYRO_KILL_POSTDEATH", 1 );
  68. //----------------------------------------------------------------------------------------------------------------
  69. class CAchievementTFPyro_BurnFlagCarriers : public CAchievementTFPyro_BaseBurn
  70. {
  71. void Init()
  72. {
  73. SetFlags( ACH_SAVE_GLOBAL );
  74. SetGoal( 5 );
  75. SetStoreProgressInSteam( true );
  76. }
  77. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  78. {
  79. if ( pTFVictim->HasTheFlag() )
  80. {
  81. IncrementCount();
  82. }
  83. }
  84. };
  85. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnFlagCarriers, ACHIEVEMENT_TF_PYRO_KILL_CARRIERS, "TF_PYRO_KILL_CARRIERS", 5 );
  86. //----------------------------------------------------------------------------------------------------------------
  87. class CAchievementTFPyro_BurnCloakedSpies : public CAchievementTFPyro_BaseBurn
  88. {
  89. void Init()
  90. {
  91. SetFlags( ACH_SAVE_GLOBAL );
  92. SetGoal( 10 );
  93. SetStoreProgressInSteam( true );
  94. }
  95. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  96. {
  97. if ( pTFVictim->IsPlayerClass(TF_CLASS_SPY) && pTFVictim->m_Shared.InCond( TF_COND_STEALTHED ) )
  98. {
  99. IncrementCount();
  100. }
  101. }
  102. };
  103. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnCloakedSpies, ACHIEVEMENT_TF_PYRO_REVEAL_SPIES, "TF_PYRO_REVEAL_SPIES", 5 );
  104. //----------------------------------------------------------------------------------------------------------------
  105. class CAchievementTFPyro_BurnSpiesAsMe : public CAchievementTFPyro_BaseBurn
  106. {
  107. void Init()
  108. {
  109. SetFlags( ACH_SAVE_GLOBAL );
  110. SetGoal( 10 );
  111. SetStoreProgressInSteam( true );
  112. }
  113. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  114. {
  115. if ( pTFVictim->IsPlayerClass(TF_CLASS_SPY) && pTFVictim->m_Shared.InCond( TF_COND_DISGUISED ) )
  116. {
  117. IncrementCount();
  118. }
  119. }
  120. };
  121. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnSpiesAsMe, ACHIEVEMENT_TF_PYRO_BURN_SPIES_AS_YOU, "TF_PYRO_BURN_SPIES_AS_YOU", 5 );
  122. //----------------------------------------------------------------------------------------------------------------
  123. class CAchievementTFPyro_AxeKillsNoDeaths : public CBaseTFAchievement
  124. {
  125. void Init()
  126. {
  127. SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
  128. SetGoal( 1 );
  129. m_iConsecutiveKills = 0;
  130. }
  131. virtual void ListenForEvents()
  132. {
  133. ListenForGameEvent( "teamplay_round_active" );
  134. ListenForGameEvent( "localplayer_respawn" );
  135. }
  136. void FireGameEvent_Internal( IGameEvent *event )
  137. {
  138. if ( FStrEq( event->GetName(), "teamplay_round_active" ) )
  139. {
  140. m_iConsecutiveKills = 0;
  141. }
  142. else if ( FStrEq( event->GetName(), "localplayer_respawn" ) )
  143. {
  144. m_iConsecutiveKills = 0;
  145. }
  146. }
  147. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  148. {
  149. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  150. if ( pLocalPlayer == pVictim )
  151. {
  152. m_iConsecutiveKills = 0;
  153. }
  154. else if ( pLocalPlayer == pAttacker && event->GetInt( "weaponid" ) == TF_WEAPON_FIREAXE )
  155. {
  156. m_iConsecutiveKills++;
  157. if ( m_iConsecutiveKills >= GetNumKillsNeeded() )
  158. {
  159. IncrementCount();
  160. }
  161. }
  162. }
  163. virtual int GetNumKillsNeeded( void )
  164. {
  165. return 3;
  166. }
  167. private:
  168. int m_iConsecutiveKills;
  169. };
  170. DECLARE_ACHIEVEMENT( CAchievementTFPyro_AxeKillsNoDeaths, ACHIEVEMENT_TF_PYRO_KILL_AXE_SMALL, "TF_PYRO_KILL_AXE_SMALL", 5 );
  171. class CAchievementTFPyro_AxeKillsNoDeathsLarge : public CAchievementTFPyro_AxeKillsNoDeaths
  172. {
  173. virtual int GetNumKillsNeeded( void )
  174. {
  175. return 6;
  176. }
  177. };
  178. DECLARE_ACHIEVEMENT( CAchievementTFPyro_AxeKillsNoDeathsLarge, ACHIEVEMENT_TF_PYRO_KILL_AXE_LARGE, "TF_PYRO_KILL_AXE_LARGE", 5 );
  179. //----------------------------------------------------------------------------------------------------------------
  180. class CAchievementTFPyro_BurnZoomedSnipers : public CAchievementTFPyro_BaseBurn
  181. {
  182. void Init()
  183. {
  184. SetFlags( ACH_SAVE_GLOBAL );
  185. SetGoal( 10 );
  186. SetStoreProgressInSteam( true );
  187. }
  188. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  189. {
  190. if ( pTFVictim->IsPlayerClass(TF_CLASS_SNIPER) && pTFVictim->m_Shared.InCond( TF_COND_ZOOMED ) )
  191. {
  192. IncrementCount();
  193. }
  194. }
  195. };
  196. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnZoomedSnipers, ACHIEVEMENT_TF_PYRO_BURN_SNIPERS_ZOOMED, "TF_PYRO_BURN_SNIPERS_ZOOMED", 5 );
  197. //----------------------------------------------------------------------------------------------------------------
  198. class CAchievementTFPyro_BurnChargedMedics : public CAchievementTFPyro_BaseBurn
  199. {
  200. void Init()
  201. {
  202. SetFlags( ACH_SAVE_GLOBAL );
  203. SetGoal( 3 );
  204. SetStoreProgressInSteam( true );
  205. }
  206. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  207. {
  208. if ( pTFVictim->IsPlayerClass(TF_CLASS_MEDIC) && pTFVictim->MedicGetChargeLevel() >= 1.0 )
  209. {
  210. IncrementCount();
  211. }
  212. }
  213. };
  214. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnChargedMedics, ACHIEVEMENT_TF_PYRO_BURN_MEDICS_CHARGED, "TF_PYRO_BURN_MEDICS_CHARGED", 5 );
  215. //----------------------------------------------------------------------------------------------------------------
  216. class CAchievementTFPyro_KillHeaviesWithFlamethrower : public CBaseTFAchievement
  217. {
  218. void Init()
  219. {
  220. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  221. SetGoal( 50 );
  222. SetStoreProgressInSteam( true );
  223. }
  224. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  225. {
  226. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  227. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  228. {
  229. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  230. if ( pTFVictim && pTFVictim->IsPlayerClass(TF_CLASS_HEAVYWEAPONS) && event->GetInt( "weaponid" ) == TF_WEAPON_FLAMETHROWER )
  231. {
  232. IncrementCount();
  233. }
  234. }
  235. }
  236. };
  237. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillHeaviesWithFlamethrower, ACHIEVEMENT_TF_PYRO_KILL_HEAVIES, "TF_PYRO_KILL_HEAVIES", 1 );
  238. //----------------------------------------------------------------------------------------------------------------
  239. class CAchievementTFPyro_KillUnderwater : public CBaseTFAchievement
  240. {
  241. void Init()
  242. {
  243. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  244. SetGoal( 10 );
  245. SetStoreProgressInSteam( true );
  246. }
  247. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  248. {
  249. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  250. if( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  251. {
  252. if ( pLocalPlayer->GetWaterLevel() >= WL_Eyes && pVictim->GetWaterLevel() >= WL_Waist )
  253. {
  254. IncrementCount();
  255. }
  256. }
  257. }
  258. };
  259. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillUnderwater, ACHIEVEMENT_TF_PYRO_KILL_UNDERWATER, "TF_PYRO_KILL_UNDERWATER", 1 );
  260. //----------------------------------------------------------------------------------------------------------------
  261. class CAchievementTFPyro_AssistMedic : public CBaseTFAchievement
  262. {
  263. void Init()
  264. {
  265. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  266. SetGoal( 1 );
  267. m_iPlayersKilled = 0;
  268. }
  269. virtual void ListenForEvents()
  270. {
  271. ListenForGameEvent( "player_invulned" );
  272. }
  273. virtual void FireGameEvent_Internal( IGameEvent *event )
  274. {
  275. if ( FStrEq( event->GetName(), "player_invulned" ) )
  276. {
  277. int iTarget = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  278. CBaseEntity *pPlayer = UTIL_PlayerByIndex( iTarget );
  279. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  280. if ( pPlayer == pLocalPlayer )
  281. {
  282. m_iPlayersKilled = 0;
  283. }
  284. }
  285. }
  286. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  287. {
  288. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  289. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  290. {
  291. if ( pLocalPlayer->m_Shared.InCond( TF_COND_INVULNERABLE ) || pLocalPlayer->m_Shared.InCond( TF_COND_CRITBOOSTED ) ||
  292. pLocalPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF ) )
  293. {
  294. m_iPlayersKilled++;
  295. if ( m_iPlayersKilled >= 3 )
  296. {
  297. IncrementCount();
  298. }
  299. }
  300. }
  301. }
  302. private:
  303. int m_iPlayersKilled;
  304. };
  305. DECLARE_ACHIEVEMENT( CAchievementTFPyro_AssistMedic, ACHIEVEMENT_TF_PYRO_KILL_UBERCHARGE, "TF_PYRO_KILL_UBERCHARGE", 5 );
  306. //----------------------------------------------------------------------------------------------------------------
  307. class CAchievementTFPyro_DestroyBuildings : public CBaseTFAchievement
  308. {
  309. void Init()
  310. {
  311. SetFlags( ACH_SAVE_GLOBAL );
  312. SetGoal( 50 );
  313. SetStoreProgressInSteam( true );
  314. }
  315. virtual void ListenForEvents()
  316. {
  317. ListenForGameEvent( "object_destroyed" );
  318. }
  319. void FireGameEvent_Internal( IGameEvent *event )
  320. {
  321. if ( Q_strcmp( event->GetName(), "object_destroyed" ) == 0 )
  322. {
  323. int iIndex = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
  324. CBaseEntity *pDestroyer = UTIL_PlayerByIndex( iIndex );
  325. C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  326. if ( pDestroyer == pTFPlayer )
  327. {
  328. IncrementCount();
  329. }
  330. }
  331. }
  332. };
  333. DECLARE_ACHIEVEMENT( CAchievementTFPyro_DestroyBuildings, ACHIEVEMENT_TF_PYRO_DESTROY_BUILDINGS, "TF_PYRO_DESTROY_BUILDINGS", 1 );
  334. //----------------------------------------------------------------------------------------------------------------
  335. class CAchievementTFPyro_KillGrind : public CBaseTFAchievement
  336. {
  337. void Init()
  338. {
  339. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  340. SetGoal( 500 );
  341. SetStoreProgressInSteam( true );
  342. }
  343. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  344. {
  345. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  346. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  347. {
  348. IncrementCount();
  349. }
  350. }
  351. };
  352. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillGrind, ACHIEVEMENT_TF_PYRO_KILL_GRIND, "TF_PYRO_KILL_GRIND", 1 );
  353. //----------------------------------------------------------------------------------------------------------------
  354. class CAchievementTFPyro_KillGrindLarge : public CBaseTFAchievement
  355. {
  356. void Init()
  357. {
  358. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  359. SetGoal( 1000 );
  360. SetStoreProgressInSteam( true );
  361. }
  362. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  363. {
  364. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  365. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  366. {
  367. IncrementCount();
  368. }
  369. }
  370. };
  371. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillGrindLarge, ACHIEVEMENT_TF_PYRO_KILL_GRIND_LARGE, "TF_PYRO_KILL_GRIND_LARGE", 1 );
  372. //----------------------------------------------------------------------------------------------------------------
  373. class CAchievementTFPyro_KillFromBehindWithFlamethrower : public CBaseTFAchievement
  374. {
  375. void Init()
  376. {
  377. SetFlags( ACH_SAVE_GLOBAL );
  378. SetGoal( 50 );
  379. SetStoreProgressInSteam( true );
  380. }
  381. // Kill 50 players from behind with the flamethrower
  382. // server awards this achievement, no other code within achievement necessary
  383. };
  384. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillFromBehindWithFlamethrower, ACHIEVEMENT_TF_PYRO_KILL_FROM_BEHIND, "TF_PYRO_KILL_FROM_BEHIND", 1 );
  385. //----------------------------------------------------------------------------------------------------------------
  386. class CAchievementTFPyro_BurnTauntingSpy : public CAchievementTFPyro_BaseBurn
  387. {
  388. void Init()
  389. {
  390. SetFlags( ACH_SAVE_GLOBAL );
  391. SetGoal( 1 );
  392. }
  393. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  394. {
  395. // This will 'fail' if we add new PDAs that have a different taunt
  396. if ( pTFVictim->IsPlayerClass(TF_CLASS_SPY) && pTFVictim->IsTaunting() &&
  397. pTFVictim->GetActiveTFWeapon() && pTFVictim->GetActiveTFWeapon()->GetWeaponID() == TF_WEAPON_PDA_SPY )
  398. {
  399. IncrementCount();
  400. }
  401. }
  402. };
  403. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnTauntingSpy, ACHIEVEMENT_TF_PYRO_BURN_SPY_TAUNT, "TF_PYRO_BURN_SPY_TAUNT", 5 );
  404. //----------------------------------------------------------------------------------------------------------------
  405. class CAchievementTFPyro_KillTaunters : public CBaseTFAchievement
  406. {
  407. void Init()
  408. {
  409. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  410. SetGoal( 3 );
  411. SetStoreProgressInSteam( true );
  412. }
  413. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  414. {
  415. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  416. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  417. {
  418. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  419. if ( pTFVictim && pTFVictim->IsTaunting() )
  420. {
  421. IncrementCount();
  422. }
  423. }
  424. }
  425. };
  426. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillTaunters, ACHIEVEMENT_TF_PYRO_KILL_TAUNTERS, "TF_PYRO_KILL_TAUNTERS", 5 );
  427. //----------------------------------------------------------------------------------------------------------------
  428. class CAchievementTFPyro_DoubleKO : public CBaseTFAchievement
  429. {
  430. void Init()
  431. {
  432. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  433. SetGoal( 1 );
  434. }
  435. virtual void ListenForEvents( void )
  436. {
  437. // Clear data on level init
  438. ResetDeaths();
  439. }
  440. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  441. {
  442. // Retire expired deaths
  443. int iCount = m_DeathHistory.Count();
  444. for ( int i = iCount-1; i >= 0; i-- )
  445. {
  446. if ( ( gpGlobals->curtime - m_DeathHistory[i].m_flTime ) > 1.0f )
  447. {
  448. m_DeathHistory.Remove( i );
  449. }
  450. }
  451. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  452. if ( pVictim == pLocalPlayer )
  453. {
  454. m_flLocalDeathTime = gpGlobals->curtime;
  455. m_hLocalKiller = pAttacker;
  456. EvaluateDeaths();
  457. }
  458. else if ( pAttacker == pLocalPlayer && pVictim->IsPlayer() )
  459. {
  460. int index = m_DeathHistory.AddToTail();
  461. m_DeathHistory[index].m_hTarget = pVictim;
  462. m_DeathHistory[index].m_flTime = gpGlobals->curtime;
  463. EvaluateDeaths();
  464. }
  465. }
  466. void EvaluateDeaths( void )
  467. {
  468. if ( m_flLocalDeathTime == -1 )
  469. return;
  470. // See if we've died within 1 second of a victim's death
  471. int iCount = m_DeathHistory.Count();
  472. for ( int i = 0; i < iCount; i++ )
  473. {
  474. if ( fabs(m_flLocalDeathTime - m_DeathHistory[i].m_flTime) <= 1.0 )
  475. {
  476. if ( m_hLocalKiller == m_DeathHistory[i].m_hTarget )
  477. {
  478. IncrementCount();
  479. return;
  480. }
  481. }
  482. }
  483. }
  484. void ResetDeaths( void )
  485. {
  486. m_flLocalDeathTime = -1;
  487. m_hLocalKiller = NULL;
  488. m_DeathHistory.Purge();
  489. }
  490. private:
  491. typedef struct
  492. {
  493. EHANDLE m_hTarget;
  494. float m_flTime;
  495. } target_history_t;
  496. CUtlVector< target_history_t > m_DeathHistory;
  497. float m_flLocalDeathTime;
  498. EHANDLE m_hLocalKiller;
  499. };
  500. DECLARE_ACHIEVEMENT( CAchievementTFPyro_DoubleKO, ACHIEVEMENT_TF_PYRO_DOUBLE_KO, "TF_PYRO_DOUBLE_KO", 5 );
  501. //----------------------------------------------------------------------------------------------------------------
  502. class CAchievementTFPyro_ForceEnemiesIntoWater : public CBaseTFAchievement
  503. {
  504. void Init()
  505. {
  506. SetFlags( ACH_SAVE_GLOBAL );
  507. SetGoal( 10 );
  508. SetStoreProgressInSteam( true );
  509. }
  510. // Force 20 burning enemies into water.
  511. // server awards this achievement, no other code within achievement necessary
  512. };
  513. DECLARE_ACHIEVEMENT( CAchievementTFPyro_ForceEnemiesIntoWater, ACHIEVEMENT_TF_PYRO_FORCE_WATERJUMP, "TF_PYRO_FORCE_WATERJUMP", 5 );
  514. //----------------------------------------------------------------------------------------------------------------
  515. class CAchievementTFPyro_MultiWeaponKills : public CBaseTFAchievement
  516. {
  517. void Init()
  518. {
  519. SetFlags( ACH_SAVE_GLOBAL );
  520. SetGoal( 20 );
  521. SetStoreProgressInSteam( true );
  522. }
  523. // Kill 20 enemies that you've ignited with one of your other weapons.
  524. // server awards this achievement, no other code within achievement necessary
  525. };
  526. DECLARE_ACHIEVEMENT( CAchievementTFPyro_MultiWeaponKills, ACHIEVEMENT_TF_PYRO_KILL_MULTIWEAPONS, "TF_PYRO_KILL_MULTIWEAPONS", 5 );
  527. //----------------------------------------------------------------------------------------------------------------
  528. class CAchievementTFPyro_RageQuit : public CBaseTFAchievement
  529. {
  530. void Init()
  531. {
  532. SetFlags( ACH_SAVE_GLOBAL );
  533. SetGoal( 1 );
  534. }
  535. // Cause a dominated player to leave the server
  536. // server awards this achievement, no other code within achievement necessary
  537. };
  538. DECLARE_ACHIEVEMENT( CAchievementTFPyro_RageQuit, ACHIEVEMENT_TF_PYRO_DOMINATE_LEAVESVR, "TF_PYRO_DOMINATE_LEAVESVR", 5 );
  539. //----------------------------------------------------------------------------------------------------------------
  540. class CAchievementTFPyro_KillWithTaunt : public CBaseTFAchievement
  541. {
  542. void Init()
  543. {
  544. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  545. SetGoal( 1 );
  546. }
  547. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  548. {
  549. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  550. if ( pAttacker == pLocalPlayer )
  551. {
  552. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  553. if ( pTFVictim && ( event->GetInt( "customkill" ) == TF_DMG_CUSTOM_TAUNTATK_HADOUKEN || event->GetInt( "customkill" ) == TF_DMG_CUSTOM_TAUNTATK_ARMAGEDDON ) )
  554. {
  555. IncrementCount();
  556. }
  557. }
  558. }
  559. };
  560. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillWithTaunt, ACHIEVEMENT_TF_PYRO_KILL_TAUNT, "TF_PYRO_KILL_TAUNT", 1 );
  561. //----------------------------------------------------------------------------------------------------------------
  562. class CAchievementTFPyro_BurnSimulScouts : public CAchievementTFPyro_BaseBurn
  563. {
  564. DECLARE_CLASS( CAchievementTFPyro_BurnSimulScouts, CAchievementTFPyro_BaseBurn );
  565. void Init()
  566. {
  567. SetFlags( ACH_SAVE_GLOBAL );
  568. SetGoal( 1 );
  569. }
  570. virtual void ListenForEvents( void )
  571. {
  572. BaseClass::ListenForEvents();
  573. // Clear data on level init
  574. m_hBurnedScouts.Purge();
  575. }
  576. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  577. {
  578. if ( !pTFVictim->IsPlayerClass(TF_CLASS_SCOUT ))
  579. return;
  580. if ( m_hBurnedScouts.Find(pTFVictim) != m_hBurnedScouts.InvalidIndex() )
  581. return;
  582. // Remove any non-burning scouts from the list
  583. int iCount = m_hBurnedScouts.Count();
  584. for ( int i = iCount-1; i >= 0; i-- )
  585. {
  586. if ( !m_hBurnedScouts[i] || !m_hBurnedScouts[i]->m_Shared.InCond(TF_COND_BURNING) )
  587. {
  588. m_hBurnedScouts.Remove(i);
  589. }
  590. }
  591. m_hBurnedScouts.AddToTail( pTFVictim );
  592. if ( m_hBurnedScouts.Count() >= 2 )
  593. {
  594. IncrementCount();
  595. }
  596. }
  597. private:
  598. CUtlVector< CHandle<C_TFPlayer> > m_hBurnedScouts;
  599. };
  600. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnSimulScouts, ACHIEVEMENT_TF_PYRO_SIMULBURN_SCOUTS, "TF_PYRO_SIMULBURN_SCOUTS", 5 );
  601. //----------------------------------------------------------------------------------------------------------------
  602. class CAchievementTFPyro_BurnSappingSpies : public CBaseTFAchievement
  603. {
  604. void Init()
  605. {
  606. SetFlags( ACH_SAVE_GLOBAL );
  607. SetGoal( 5 );
  608. SetStoreProgressInSteam( true );
  609. }
  610. // Ignite a spy who's got a sapper on a friendly sentrygun
  611. // server awards this achievement, no other code within achievement necessary
  612. };
  613. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnSappingSpies, ACHIEVEMENT_TF_PYRO_KILL_SPIES, "TF_PYRO_KILL_SPIES", 5 );
  614. //----------------------------------------------------------------------------------------------------------------
  615. class CAchievementTFPyro_BurnTeleportees : public CAchievementTFPyro_BaseBurn
  616. {
  617. void Init()
  618. {
  619. SetFlags( ACH_SAVE_GLOBAL );
  620. SetGoal( 10 );
  621. SetStoreProgressInSteam( true );
  622. }
  623. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  624. {
  625. if ( pTFVictim->m_Shared.InCond(TF_COND_TELEPORTED) )
  626. {
  627. IncrementCount();
  628. }
  629. }
  630. };
  631. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnTeleportees, ACHIEVEMENT_TF_PYRO_CAMP_TELEPORTERS, "TF_PYRO_CAMP_TELEPORTERS", 5 );
  632. //----------------------------------------------------------------------------------------------------------------
  633. class CAchievementTFPyro_KillCamping : public CBaseTFAchievement
  634. {
  635. void Init()
  636. {
  637. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  638. SetGoal( 1 );
  639. }
  640. virtual void ListenForEvents( void )
  641. {
  642. m_iKills = -1;
  643. }
  644. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  645. {
  646. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  647. if ( pAttacker == pLocalPlayer && pVictim != pLocalPlayer )
  648. {
  649. // If it's too far from our previous position, start again
  650. Vector vecOrg = pVictim->GetAbsOrigin();
  651. if ( m_iKills == -1 || ((m_vecPosition - vecOrg).LengthSqr() > (1024*1024)) )
  652. {
  653. m_vecPosition = vecOrg;
  654. m_iKills = 1;
  655. }
  656. else
  657. {
  658. m_iKills++;
  659. }
  660. if ( m_iKills >= 3 )
  661. {
  662. IncrementCount();
  663. }
  664. }
  665. }
  666. private:
  667. Vector m_vecPosition;
  668. int m_iKills;
  669. };
  670. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillCamping, ACHIEVEMENT_TF_PYRO_CAMP_POSITION, "TF_PYRO_CAMP_POSITION", 5 );
  671. //----------------------------------------------------------------------------------------------------------------
  672. class CAchievementTFPyro_DefendControlPoints : public CBaseTFAchievement
  673. {
  674. void Init()
  675. {
  676. SetFlags( ACH_SAVE_GLOBAL );
  677. SetGoal( 50 );
  678. SetStoreProgressInSteam( true );
  679. }
  680. // Burn a player who's capping a control point
  681. // server awards this achievement, no other code within achievement necessary
  682. };
  683. DECLARE_ACHIEVEMENT( CAchievementTFPyro_DefendControlPoints, ACHIEVEMENT_TF_PYRO_DEFEND_POINTS, "TF_PYRO_DEFEND_POINTS", 5 );
  684. //----------------------------------------------------------------------------------------------------------------
  685. class CAchievementTFPyro_BurnRJer : public CBaseTFAchievement
  686. {
  687. void Init()
  688. {
  689. SetFlags( ACH_SAVE_GLOBAL );
  690. SetGoal( 1 );
  691. }
  692. // Burn a rocket jumping soldier in mid-air
  693. // server awards this achievement, no other code within achievement necessary
  694. };
  695. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnRJer, ACHIEVEMENT_TF_PYRO_BURN_RJ_SOLDIER, "TF_PYRO_BURN_RJ_SOLDIER", 5 );
  696. //----------------------------------------------------------------------------------------------------------------
  697. class CAchievementTFPyro_FreezeTaunts : public CBaseTFAchievement
  698. {
  699. void Init()
  700. {
  701. SetFlags( ACH_SAVE_GLOBAL );
  702. SetGoal( 3 );
  703. SetStoreProgressInSteam( true );
  704. }
  705. // Give opponents freezecams of you taunting
  706. // server awards this achievement, no other code within achievement necessary
  707. };
  708. DECLARE_ACHIEVEMENT( CAchievementTFPyro_FreezeTaunts, ACHIEVEMENT_TF_PYRO_FREEZECAM_TAUNTS, "TF_PYRO_FREEZECAM_TAUNTS", 5 );
  709. //----------------------------------------------------------------------------------------------------------------
  710. class CAchievementTFPyro_BurnMedicPair : public CAchievementTFPyro_BaseBurn
  711. {
  712. DECLARE_CLASS( CAchievementTFPyro_BurnMedicPair, CAchievementTFPyro_BaseBurn );
  713. void Init()
  714. {
  715. SetFlags( ACH_SAVE_GLOBAL );
  716. SetGoal( 1 );
  717. }
  718. virtual void ListenForEvents( void )
  719. {
  720. BaseClass::ListenForEvents();
  721. ListenForGameEvent( "localplayer_respawn" );
  722. // Clear data on level init
  723. m_hBurnVictims.Purge();
  724. }
  725. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  726. {
  727. bool bIgnitedPair = false;
  728. // If our victim is a Medic, and we've ignited his target already, we're done.
  729. if ( pTFVictim->IsPlayerClass(TF_CLASS_MEDIC) )
  730. {
  731. CBaseEntity *pTarget = pTFVictim->MedicGetHealTarget();
  732. if ( pTarget )
  733. {
  734. C_TFPlayer *pPlayer = ToTFPlayer(pTarget);
  735. if ( pPlayer && m_hBurnVictims.Find(pPlayer) != m_hBurnVictims.InvalidIndex() )
  736. {
  737. // We've ignited the medic target previously. If he's still burning, we're done.
  738. bIgnitedPair = (pPlayer->m_Shared.InCond(TF_COND_BURNING));
  739. }
  740. }
  741. }
  742. // See if any of our previous targets are medics, healing this new target
  743. int iCount = m_hBurnVictims.Count();
  744. for ( int i = iCount-1; i >= 0; i-- )
  745. {
  746. // Remove players from the list when they're not burning anymore
  747. if ( !m_hBurnVictims[i] || !m_hBurnVictims[i]->m_Shared.InCond(TF_COND_BURNING) )
  748. {
  749. m_hBurnVictims.Remove(i);
  750. }
  751. else
  752. {
  753. CBaseEntity *pTarget = m_hBurnVictims[i]->MedicGetHealTarget();
  754. if ( pTarget == pTFVictim )
  755. {
  756. bIgnitedPair = true;
  757. }
  758. }
  759. }
  760. if ( bIgnitedPair )
  761. {
  762. IncrementCount();
  763. m_hBurnVictims.Purge();
  764. }
  765. else
  766. {
  767. if ( m_hBurnVictims.Find(pTFVictim) == m_hBurnVictims.InvalidIndex() )
  768. {
  769. m_hBurnVictims.AddToTail( pTFVictim );
  770. }
  771. }
  772. }
  773. void FireGameEvent_Internal( IGameEvent *event )
  774. {
  775. const char *pszEventName = event->GetName();
  776. if ( FStrEq( pszEventName, "localplayer_respawn" ) )
  777. {
  778. m_hBurnVictims.Purge();
  779. }
  780. BaseClass::FireGameEvent_Internal(event);
  781. }
  782. private:
  783. CUtlVector< CHandle<C_TFPlayer> > m_hBurnVictims;
  784. };
  785. DECLARE_ACHIEVEMENT( CAchievementTFPyro_BurnMedicPair, ACHIEVEMENT_TF_PYRO_BURN_MEDICPAIR, "TF_PYRO_BURN_MEDICPAIR", 5 );
  786. //----------------------------------------------------------------------------------------------------------------
  787. class CAchievementTFPyro_KillTeamwork : public CBaseTFAchievement
  788. {
  789. void Init()
  790. {
  791. SetFlags( ACH_SAVE_GLOBAL );
  792. SetGoal( 1 );
  793. }
  794. // Kill an enemy who was ignited by another Pyro
  795. // server awards this achievement, no other code within achievement necessary
  796. };
  797. DECLARE_ACHIEVEMENT( CAchievementTFPyro_KillTeamwork, ACHIEVEMENT_TF_PYRO_KILL_TEAMWORK, "TF_PYRO_KILL_TEAMWORK", 5 );
  798. //----------------------------------------------------------------------------------------------------------------
  799. class CAchievementTFPyro_IgniteFlaregun : public CAchievementTFPyro_BaseBurn
  800. {
  801. void Init()
  802. {
  803. SetFlags( ACH_SAVE_GLOBAL );
  804. SetGoal( 100 );
  805. SetStoreProgressInSteam( true );
  806. }
  807. void BurnedVictim( CBaseEntity *pPyro, C_TFPlayer *pTFVictim, IGameEvent *event )
  808. {
  809. if ( event->GetInt( "weaponid" ) == TF_WEAPON_FLAREGUN )
  810. {
  811. IncrementCount();
  812. }
  813. }
  814. };
  815. DECLARE_ACHIEVEMENT( CAchievementTFPyro_IgniteFlaregun, ACHIEVEMENT_TF_PYRO_IGNITE_FLAREGUN, "TF_PYRO_IGNITE_FLAREGUN", 5 );
  816. //----------------------------------------------------------------------------------------------------------------
  817. class CAchievementTFPyro_ReflectProjectiles : public CBaseTFAchievement
  818. {
  819. void Init()
  820. {
  821. SetFlags( ACH_SAVE_GLOBAL );
  822. SetGoal( 100 );
  823. }
  824. // Reflect projectiles with the compression blast
  825. // server awards this achievement, no other code within achievement necessary
  826. };
  827. DECLARE_ACHIEVEMENT( CAchievementTFPyro_ReflectProjectiles, ACHIEVEMENT_TF_PYRO_REFLECT_PROJECTILES, "TF_PYRO_REFLECT_PROJECTILES", 5 );
  828. //----------------------------------------------------------------------------------------------------------------
  829. class CAchievementTFPyro_ReflectCrocketKill : public CBaseTFAchievement
  830. {
  831. void Init()
  832. {
  833. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  834. SetGoal( 1 );
  835. }
  836. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  837. {
  838. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  839. if ( pAttacker == pLocalPlayer && (event->GetInt( "weaponid" ) == TF_WEAPON_ROCKETLAUNCHER) && (event->GetInt("damagebits") & DMG_CRITICAL) )
  840. {
  841. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  842. if ( pTFVictim->IsPlayerClass(TF_CLASS_SOLDIER) )
  843. {
  844. IncrementCount();
  845. }
  846. }
  847. }
  848. };
  849. DECLARE_ACHIEVEMENT( CAchievementTFPyro_ReflectCrocketKill, ACHIEVEMENT_TF_PYRO_REFLECT_CROCKET_KILL, "TF_PYRO_REFLECT_CROCKET_KILL", 5 );
  850. class CAchievementTFPyro_DamageGrind : public CBaseTFAchievement
  851. {
  852. void Init()
  853. {
  854. SetFlags( ACH_SAVE_GLOBAL );
  855. SetGoal( 1000000 );
  856. }
  857. void OnPlayerStatsUpdate()
  858. {
  859. ClassStats_t &classStats = CTFStatPanel::GetClassStats( TF_CLASS_PYRO );
  860. int iOldCount = m_iCount;
  861. m_iCount = classStats.accumulated.m_iStat[TFSTAT_FIREDAMAGE];
  862. if ( m_iCount != iOldCount )
  863. {
  864. m_pAchievementMgr->SetDirty( true );
  865. }
  866. if ( IsLocalTFPlayerClass( TF_CLASS_PYRO ) )
  867. {
  868. EvaluateNewAchievement();
  869. }
  870. }
  871. };
  872. DECLARE_ACHIEVEMENT( CAchievementTFPyro_DamageGrind, ACHIEVEMENT_TF_PYRO_DAMAGE_GRIND, "TF_PYRO_DAMAGE_GRIND", 5 );
  873. //----------------------------------------------------------------------------------------------------------------
  874. class CAchievementTFPyro_AchieveProgress1 : public CAchievement_AchievedCount
  875. {
  876. public:
  877. DECLARE_CLASS( CAchievementTFPyro_AchieveProgress1, CAchievement_AchievedCount );
  878. void Init()
  879. {
  880. BaseClass::Init();
  881. SetAchievementsRequired( 10, ACHIEVEMENT_TF_PYRO_START_RANGE, ACHIEVEMENT_TF_PYRO_END_RANGE );
  882. }
  883. };
  884. DECLARE_ACHIEVEMENT( CAchievementTFPyro_AchieveProgress1, ACHIEVEMENT_TF_PYRO_ACHIEVE_PROGRESS1, "TF_PYRO_ACHIEVE_PROGRESS1", 5 );
  885. //----------------------------------------------------------------------------------------------------------------
  886. class CAchievementTFPyro_AchieveProgress2 : public CAchievement_AchievedCount
  887. {
  888. public:
  889. DECLARE_CLASS( CAchievementTFPyro_AchieveProgress2, CAchievement_AchievedCount );
  890. void Init()
  891. {
  892. BaseClass::Init();
  893. SetAchievementsRequired( 16, ACHIEVEMENT_TF_PYRO_START_RANGE, ACHIEVEMENT_TF_PYRO_END_RANGE );
  894. }
  895. };
  896. DECLARE_ACHIEVEMENT( CAchievementTFPyro_AchieveProgress2, ACHIEVEMENT_TF_PYRO_ACHIEVE_PROGRESS2, "TF_PYRO_ACHIEVE_PROGRESS2", 5 );
  897. //----------------------------------------------------------------------------------------------------------------
  898. class CAchievementTFPyro_AchieveProgress3 : public CAchievement_AchievedCount
  899. {
  900. public:
  901. DECLARE_CLASS( CAchievementTFPyro_AchieveProgress3, CAchievement_AchievedCount );
  902. void Init()
  903. {
  904. BaseClass::Init();
  905. SetAchievementsRequired( 22, ACHIEVEMENT_TF_PYRO_START_RANGE, ACHIEVEMENT_TF_PYRO_END_RANGE );
  906. }
  907. };
  908. DECLARE_ACHIEVEMENT( CAchievementTFPyro_AchieveProgress3, ACHIEVEMENT_TF_PYRO_ACHIEVE_PROGRESS3, "TF_PYRO_ACHIEVE_PROGRESS3", 5 );
  909. //----------------------------------------------------------------------------------------------------------------
  910. class CAchievementTFPyro_IgniteWithRainbow : public CBaseTFAchievement
  911. {
  912. void Init()
  913. {
  914. SetFlags( ACH_SAVE_GLOBAL );
  915. SetGoal( 1 );
  916. }
  917. // server awards this achievement, no other code within achievement necessary
  918. };
  919. DECLARE_ACHIEVEMENT( CAchievementTFPyro_IgniteWithRainbow, ACHIEVEMENT_TF_PYRO_IGNITE_WITH_RAINBOW, "TF_PYRO_IGNITE_WITH_RAINBOW", 5 );
  920. //----------------------------------------------------------------------------------------------------------------
  921. class CAchievementTFPyro_IgnitePlayerBeingFlipped : public CBaseTFAchievement
  922. {
  923. void Init()
  924. {
  925. SetFlags( ACH_SAVE_GLOBAL );
  926. SetGoal( 1 );
  927. }
  928. // server awards this achievement, no other code within achievement necessary
  929. };
  930. DECLARE_ACHIEVEMENT( CAchievementTFPyro_IgnitePlayerBeingFlipped, ACHIEVEMENT_TF_PYRO_IGNITE_PLAYER_BEING_FLIPPED, "TF_PYRO_IGNITE_PLAYER_BEING_FLIPPED", 5 );
  931. #endif // CLIENT_DLL