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.

1890 lines
54 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. #include "c_tf_objective_resource.h"
  17. #include "tf_weapon_shovel.h"
  18. #include "tf_weapon_rocketlauncher.h"
  19. #include "movevars_shared.h"
  20. //======================================================================================================================================
  21. // SOLDIER ACHIEVEMENT PACK
  22. //======================================================================================================================================
  23. //----------------------------------------------------------------------------------------------------------------
  24. class CAchievementTFSoldier_RJEqualizerKill : public CBaseTFAchievement
  25. {
  26. void Init()
  27. {
  28. SetFlags( ACH_SAVE_GLOBAL );
  29. SetGoal( 1 );
  30. }
  31. // server awards this achievement, no other code within achievement necessary
  32. };
  33. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_RJEqualizerKill, ACHIEVEMENT_TF_SOLDIER_RJ_EQUALIZER_KILL, "TF_SOLDIER_RJ_EQUALIZER_KILL", 5 );
  34. //----------------------------------------------------------------------------------------------------------------
  35. class CAchievementTFSoldier_BuffTeammates : public CBaseTFAchievement
  36. {
  37. void Init()
  38. {
  39. SetFlags( ACH_SAVE_GLOBAL );
  40. SetGoal( 1 );
  41. }
  42. virtual void ListenForEvents()
  43. {
  44. ListenForGameEvent( "teamplay_round_active" );
  45. ListenForGameEvent( "localplayer_respawn" );
  46. ListenForGameEvent( "deploy_buff_banner" );
  47. ListenForGameEvent( "player_buff" );
  48. }
  49. void FireGameEvent_Internal( IGameEvent *event )
  50. {
  51. const char *pszEvent = event->GetName();
  52. if ( FStrEq( pszEvent, "teamplay_round_active" ) ||
  53. FStrEq( pszEvent, "localplayer_respawn" ) )
  54. {
  55. m_nBuffCount = 0;
  56. m_BuffedPlayers.RemoveAll();
  57. }
  58. else if ( FStrEq( pszEvent, "deploy_buff_banner" ) )
  59. {
  60. int iSoldier = engine->GetPlayerForUserID( event->GetInt( "buff_owner" ) );
  61. CBasePlayer *pSoldier = UTIL_PlayerByIndex( iSoldier );
  62. if ( pSoldier && pSoldier == C_TFPlayer::GetLocalTFPlayer() )
  63. {
  64. // the local player has deployed their banner, clear our list for the current banner so we can track who we buff
  65. m_BuffedPlayers.RemoveAll();
  66. }
  67. }
  68. else if ( FStrEq( pszEvent, "player_buff" ) )
  69. {
  70. int iSoldier = engine->GetPlayerForUserID( event->GetInt( "buff_owner" ) );
  71. CBasePlayer *pSoldier = UTIL_PlayerByIndex( iSoldier );
  72. if ( pSoldier && pSoldier == C_TFPlayer::GetLocalTFPlayer() )
  73. {
  74. int iPlayer = event->GetInt( "userid" );
  75. if ( iPlayer != pSoldier->GetUserID() )
  76. {
  77. // this is not the local player being buffed (can't buff yourself for this achievement)
  78. int iIndex = m_BuffedPlayers.Find( iPlayer );
  79. if ( iIndex == m_BuffedPlayers.InvalidIndex() )
  80. {
  81. // they're not in our list for the currently deployed banner
  82. m_BuffedPlayers.AddToTail( iPlayer );
  83. m_nBuffCount++;
  84. if ( m_nBuffCount >= 15 )
  85. {
  86. IncrementCount();
  87. }
  88. }
  89. }
  90. }
  91. }
  92. }
  93. private:
  94. int m_nBuffCount;
  95. CUtlVector< int > m_BuffedPlayers;
  96. };
  97. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_BuffTeammates, ACHIEVEMENT_TF_SOLDIER_BUFF_TEAMMATES, "TF_SOLDIER_BUFF_TEAMMATES", 5 );
  98. //----------------------------------------------------------------------------------------------------------------
  99. class CAchievementTFSoldier_KillDemomanGrind : public CBaseTFAchievement
  100. {
  101. void Init()
  102. {
  103. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  104. SetGoal( 500 );
  105. SetStoreProgressInSteam( true );
  106. }
  107. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  108. {
  109. if ( !pVictim || !pVictim->IsPlayer() )
  110. return;
  111. if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  112. {
  113. // no friendly fire kills
  114. if ( pVictim->GetTeamNumber() != pAttacker->GetTeamNumber() )
  115. {
  116. CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
  117. if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_DEMOMAN ) )
  118. {
  119. // we killed a demoman
  120. IncrementCount();
  121. }
  122. }
  123. }
  124. }
  125. };
  126. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillDemomanGrind, ACHIEVEMENT_TF_SOLDIER_KILL_DEMOMAN_GRIND, "TF_SOLDIER_KILL_DEMOMAN_GRIND", 5 );
  127. //----------------------------------------------------------------------------------------------------------------
  128. class CAchievementTFSoldier_KillEngy : public CBaseTFAchievement
  129. {
  130. void Init()
  131. {
  132. SetFlags( ACH_SAVE_GLOBAL );
  133. SetGoal( 1 );
  134. }
  135. // server awards this achievement, no other code within achievement necessary
  136. };
  137. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillEngy, ACHIEVEMENT_TF_SOLDIER_KILL_ENGY, "TF_SOLDIER_KILL_ENGY", 5 );
  138. //----------------------------------------------------------------------------------------------------------------
  139. class CAchievementTFSoldier_KillPyro : public CBaseTFAchievement
  140. {
  141. void Init()
  142. {
  143. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  144. SetGoal( 1 );
  145. SetDefLessFunc( m_Pyros );
  146. }
  147. virtual void ListenForEvents()
  148. {
  149. ListenForGameEvent( "teamplay_round_active" );
  150. ListenForGameEvent( "localplayer_respawn" );
  151. ListenForGameEvent( "object_deflected" );
  152. m_Pyros.RemoveAll();
  153. }
  154. void FireGameEvent_Internal( IGameEvent *event )
  155. {
  156. const char *pszEvent = event->GetName();
  157. if ( FStrEq( pszEvent, "teamplay_round_active" ) ||
  158. FStrEq( pszEvent, "localplayer_respawn" ) )
  159. {
  160. m_Pyros.RemoveAll();
  161. }
  162. else if ( FStrEq( pszEvent, "object_deflected" ) )
  163. {
  164. int iSoldier = engine->GetPlayerForUserID( event->GetInt( "ownerid" ) );
  165. CBasePlayer *pSoldier = UTIL_PlayerByIndex( iSoldier );
  166. if ( pSoldier && pSoldier == C_TFPlayer::GetLocalTFPlayer() )
  167. {
  168. int iWeaponID = event->GetInt( "weaponid" );
  169. bool bRocketLauncherUsed = (iWeaponID == TF_WEAPON_ROCKETLAUNCHER) || (iWeaponID == TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT);
  170. // this was one of our objects...was it a rocket?
  171. if ( bRocketLauncherUsed )
  172. {
  173. // add or update them in our list
  174. int iIndex = m_Pyros.Find( event->GetInt( "userid" ) );
  175. if ( iIndex != m_Pyros.InvalidIndex() )
  176. {
  177. m_Pyros[iIndex] = gpGlobals->curtime;
  178. }
  179. else
  180. {
  181. m_Pyros.Insert( event->GetInt( "userid" ), gpGlobals->curtime );
  182. }
  183. }
  184. }
  185. }
  186. }
  187. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  188. {
  189. if ( !pVictim || !pVictim->IsPlayer() )
  190. return;
  191. if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  192. {
  193. CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
  194. if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_PYRO ) )
  195. {
  196. int iIndex = m_Pyros.Find( pTFVictim->GetUserID() );
  197. if ( iIndex != m_Pyros.InvalidIndex() )
  198. {
  199. if ( gpGlobals->curtime - m_Pyros[iIndex] <= 10.0f )
  200. {
  201. // we killed someone in our list within the required time
  202. IncrementCount();
  203. }
  204. }
  205. }
  206. }
  207. }
  208. private:
  209. CUtlMap< int, float > m_Pyros; // userID and most recent time they deflected one of our rockets
  210. };
  211. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillPyro, ACHIEVEMENT_TF_SOLDIER_KILL_PYRO, "TF_SOLDIER_KILL_PYRO", 5 );
  212. //----------------------------------------------------------------------------------------------------------------
  213. class CAchievementTFSoldier_NemesisShovelKill : public CBaseTFAchievement
  214. {
  215. void Init()
  216. {
  217. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  218. SetGoal( 1 );
  219. }
  220. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  221. {
  222. if ( !pVictim || !pVictim->IsPlayer() )
  223. return;
  224. if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  225. {
  226. if ( event->GetInt( "weaponid" ) == TF_WEAPON_SHOVEL && event->GetInt( "customkill" ) == 0 )
  227. {
  228. // did the assister get revenge?
  229. if ( event->GetInt( "death_flags" ) & TF_DEATH_REVENGE )
  230. {
  231. IncrementCount();
  232. }
  233. }
  234. }
  235. }
  236. };
  237. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_NemesisShovelKill, ACHIEVEMENT_TF_SOLDIER_NEMESIS_SHOVEL_KILL, "TF_SOLDIER_NEMESIS_SHOVEL_KILL", 5 );
  238. //----------------------------------------------------------------------------------------------------------------
  239. class CAchievementTFSoldier_DestroyStickies : public CBaseTFAchievement
  240. {
  241. void Init()
  242. {
  243. SetFlags( ACH_SAVE_GLOBAL );
  244. SetGoal( 1 );
  245. m_nPipesDestroyed = 0;
  246. }
  247. virtual void ListenForEvents()
  248. {
  249. ListenForGameEvent( "teamplay_round_active" );
  250. ListenForGameEvent( "localplayer_respawn" );
  251. ListenForGameEvent( "player_destroyed_pipebomb" );
  252. }
  253. void FireGameEvent_Internal( IGameEvent *event )
  254. {
  255. const char *pszEvent = event->GetName();
  256. if ( FStrEq( pszEvent, "teamplay_round_active" ) ||
  257. FStrEq( pszEvent, "localplayer_respawn" ) )
  258. {
  259. m_nPipesDestroyed = 0;
  260. }
  261. else if ( FStrEq( pszEvent, "player_destroyed_pipebomb" ) )
  262. {
  263. int iUserID = event->GetInt( "userid" );
  264. CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  265. if ( pLocalTFPlayer && pLocalTFPlayer->GetUserID() == iUserID )
  266. {
  267. if ( pLocalTFPlayer->GetActiveTFWeapon() )
  268. {
  269. if ( pLocalTFPlayer->GetActiveTFWeapon()->GetWeaponID() == TF_WEAPON_SHOTGUN_SOLDIER )
  270. {
  271. m_nPipesDestroyed++;
  272. if ( m_nPipesDestroyed >= 10 )
  273. {
  274. IncrementCount();
  275. }
  276. }
  277. }
  278. }
  279. }
  280. }
  281. private:
  282. int m_nPipesDestroyed;
  283. };
  284. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_DestroyStickies, ACHIEVEMENT_TF_SOLDIER_DESTROY_STICKIES, "TF_SOLDIER_DESTROY_STICKIES", 5 );
  285. //----------------------------------------------------------------------------------------------------------------
  286. class CAchievementTFSoldier_CrouchRocketJump : public CBaseTFAchievement
  287. {
  288. void Init()
  289. {
  290. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  291. SetGoal( 1 );
  292. }
  293. virtual void ListenForEvents()
  294. {
  295. ListenForGameEvent( "teamplay_round_active" );
  296. ListenForGameEvent( "localplayer_respawn" );
  297. ListenForGameEvent( "rocket_jump" );
  298. ListenForGameEvent( "rocket_jump_landed" );
  299. ResetTracking();
  300. }
  301. void ResetTracking( void )
  302. {
  303. ClearThink();
  304. m_flStartingZ = 0.0f;
  305. }
  306. void CheckHeight( void )
  307. {
  308. CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  309. if ( pLocalTFPlayer )
  310. {
  311. float flCurrentZ = pLocalTFPlayer->GetAbsOrigin().z;
  312. // check the settings for gravity
  313. if ( ( flCurrentZ > m_flStartingZ ) && ( GetCurrentGravity() == 800.0f ) )
  314. {
  315. if ( flCurrentZ - m_flStartingZ > 450.0f )
  316. {
  317. IncrementCount();
  318. }
  319. }
  320. else
  321. {
  322. // we've fallen below our starting Z or someone has messed with gravity, so reset our tracking
  323. ResetTracking();
  324. }
  325. }
  326. }
  327. void FireGameEvent_Internal( IGameEvent *event )
  328. {
  329. const char *pszEvent = event->GetName();
  330. if ( FStrEq( pszEvent, "teamplay_round_active" ) ||
  331. FStrEq( pszEvent, "localplayer_respawn" ) )
  332. {
  333. ResetTracking();
  334. }
  335. else if ( FStrEq( pszEvent, "rocket_jump" ) )
  336. {
  337. int iUserID = event->GetInt( "userid" );
  338. CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  339. if ( pLocalTFPlayer && pLocalTFPlayer->GetUserID() == iUserID )
  340. {
  341. m_flStartingZ = pLocalTFPlayer->GetAbsOrigin().z;
  342. SetNextThink( 0.1 );
  343. }
  344. }
  345. else if ( FStrEq( pszEvent, "rocket_jump_landed" ) )
  346. {
  347. int iUserID = event->GetInt( "userid" );
  348. CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  349. if ( pLocalTFPlayer && pLocalTFPlayer->GetUserID() == iUserID )
  350. {
  351. CheckHeight();
  352. ResetTracking();
  353. }
  354. }
  355. }
  356. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  357. {
  358. if ( !pVictim || !pVictim->IsPlayer() )
  359. return;
  360. if ( pVictim == C_BasePlayer::GetLocalPlayer() )
  361. {
  362. ResetTracking();
  363. }
  364. }
  365. virtual void Think( void )
  366. {
  367. CheckHeight();
  368. SetNextThink( 0.1 );
  369. }
  370. private:
  371. float m_flStartingZ;
  372. };
  373. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_CrouchRocketJump, ACHIEVEMENT_TF_SOLDIER_CROUCH_ROCKET_JUMP, "TF_SOLDIER_CROUCH_ROCKET_JUMP", 5 );
  374. //----------------------------------------------------------------------------------------------------------------
  375. class CAchievementTFSoldier_EqualizerStreak : public CBaseTFAchievement
  376. {
  377. void Init()
  378. {
  379. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  380. SetGoal( 1 );
  381. m_nStreak = 0;
  382. }
  383. virtual void ListenForEvents()
  384. {
  385. ListenForGameEvent( "teamplay_round_active" );
  386. ListenForGameEvent( "localplayer_respawn" );
  387. ListenForGameEvent( "localplayer_healed" );
  388. }
  389. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  390. {
  391. if ( !pVictim || !pVictim->IsPlayer() )
  392. return;
  393. if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  394. {
  395. if ( event->GetInt( "weaponid" ) == TF_WEAPON_SHOVEL )
  396. {
  397. CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  398. if ( pLocalTFPlayer && pLocalTFPlayer->GetActiveTFWeapon() )
  399. {
  400. CTFShovel *pShovel = static_cast< CTFShovel* >( pLocalTFPlayer->GetActiveTFWeapon() );
  401. if ( pShovel && pShovel->GetShovelType() == SHOVEL_DAMAGE_BOOST )
  402. {
  403. m_nStreak++;
  404. if ( m_nStreak >= 3 )
  405. {
  406. IncrementCount();
  407. }
  408. }
  409. }
  410. }
  411. }
  412. }
  413. void FireGameEvent_Internal( IGameEvent *event )
  414. {
  415. if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
  416. FStrEq( event->GetName(), "localplayer_respawn" ) ||
  417. FStrEq( event->GetName(), "localplayer_healed" ) )
  418. {
  419. m_nStreak = 0;
  420. }
  421. }
  422. private:
  423. int m_nStreak;
  424. };
  425. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_EqualizerStreak, ACHIEVEMENT_TF_SOLDIER_EQUALIZER_STREAK, "TF_SOLDIER_EQUALIZER_STREAK", 5 );
  426. //----------------------------------------------------------------------------------------------------------------
  427. class CAchievementTFSoldier_BuffFriends : public CBaseTFAchievement
  428. {
  429. void Init()
  430. {
  431. SetFlags( ACH_SAVE_GLOBAL );
  432. SetGoal( 1 );
  433. }
  434. // client CTFPlayerShared::PulseSoldierBuff() awards this achievement, no other code within achievement necessary
  435. };
  436. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_BuffFriends, ACHIEVEMENT_TF_SOLDIER_BUFF_FRIENDS, "TF_SOLDIER_BUFF_FRIENDS", 5 );
  437. //----------------------------------------------------------------------------------------------------------------
  438. class CAchievementTFSoldier_KillGroupWithCrocket : public CBaseTFAchievement
  439. {
  440. void Init()
  441. {
  442. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  443. SetGoal( 1 );
  444. }
  445. virtual void ListenForEvents()
  446. {
  447. ListenForGameEvent( "teamplay_round_active" );
  448. ListenForGameEvent( "localplayer_respawn" );
  449. m_iKilledBySameRocket = 0;
  450. m_fDamageTime = 0;
  451. }
  452. void FireGameEvent_Internal( IGameEvent *event )
  453. {
  454. if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
  455. FStrEq( event->GetName(), "localplayer_respawn" ) )
  456. {
  457. m_iKilledBySameRocket = 0;
  458. m_fDamageTime = 0;
  459. }
  460. }
  461. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  462. {
  463. if ( !pVictim || !pVictim->IsPlayer() )
  464. return;
  465. int iWeaponID = event->GetInt( "weaponid" );
  466. if ( pAttacker == C_BasePlayer::GetLocalPlayer() &&
  467. (iWeaponID == TF_WEAPON_ROCKETLAUNCHER || iWeaponID == TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT) )
  468. {
  469. if ( event->GetInt( "damagebits" ) & DMG_CRITICAL )
  470. {
  471. if ( gpGlobals->curtime > m_fDamageTime+1.f )
  472. {
  473. m_fDamageTime = gpGlobals->curtime;
  474. m_iKilledBySameRocket = 0;
  475. }
  476. m_iKilledBySameRocket++;
  477. if ( m_iKilledBySameRocket == 3 )
  478. {
  479. IncrementCount();
  480. }
  481. }
  482. }
  483. }
  484. int m_iKilledBySameRocket;
  485. float m_fDamageTime;
  486. };
  487. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillGroupWithCrocket, ACHIEVEMENT_TF_SOLDIER_KILL_GROUP_WITH_CROCKET, "TF_SOLDIER_KILL_GROUP_WITH_CROCKET", 5 );
  488. //----------------------------------------------------------------------------------------------------------------
  489. class CAchievementTFSoldier_KillTwoDuringRocketJump : public CBaseTFAchievement
  490. {
  491. void Init()
  492. {
  493. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  494. SetGoal( 1 );
  495. }
  496. virtual void ListenForEvents()
  497. {
  498. ListenForGameEvent( "rocket_jump" );
  499. ListenForGameEvent( "rocket_jump_landed" );
  500. ListenForGameEvent( "teamplay_round_active" );
  501. ListenForGameEvent( "localplayer_respawn" );
  502. m_iKilledDuringRJ = 0;
  503. m_bRocketJumping = false;
  504. }
  505. void FireGameEvent_Internal( IGameEvent *event )
  506. {
  507. if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
  508. FStrEq( event->GetName(), "localplayer_respawn" ) )
  509. {
  510. m_iKilledDuringRJ = 0;
  511. m_bRocketJumping = false;
  512. }
  513. else if ( FStrEq( event->GetName(), "rocket_jump_landed" ) )
  514. {
  515. C_TFPlayer *pTFAttacker = NULL;
  516. int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  517. if ( iIndex > 0 )
  518. {
  519. pTFAttacker = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
  520. if ( pTFAttacker != C_BasePlayer::GetLocalPlayer() )
  521. return;
  522. }
  523. else
  524. return;
  525. m_iKilledDuringRJ = 0;
  526. m_bRocketJumping = false;
  527. }
  528. else if ( FStrEq( event->GetName(), "rocket_jump" ) )
  529. {
  530. C_TFPlayer *pTFAttacker = NULL;
  531. int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  532. if ( iIndex > 0 )
  533. {
  534. pTFAttacker = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
  535. if ( pTFAttacker != C_BasePlayer::GetLocalPlayer() )
  536. return;
  537. }
  538. else
  539. return;
  540. m_iKilledDuringRJ = 0;
  541. m_bRocketJumping = true;
  542. }
  543. }
  544. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  545. {
  546. if ( !pVictim || !pVictim->IsPlayer() )
  547. return;
  548. CTFPlayer *pTFPlayer = ToTFPlayer( pAttacker );
  549. if ( pTFPlayer && (pTFPlayer == C_BasePlayer::GetLocalPlayer()) )
  550. {
  551. if ( m_bRocketJumping )
  552. {
  553. m_iKilledDuringRJ++;
  554. if ( m_iKilledDuringRJ == 2 )
  555. {
  556. IncrementCount();
  557. }
  558. }
  559. }
  560. }
  561. bool m_bRocketJumping;
  562. int m_iKilledDuringRJ;
  563. };
  564. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillTwoDuringRocketJump, ACHIEVEMENT_TF_SOLDIER_KILL_TWO_DURING_ROCKET_JUMP, "TF_SOLDIER_KILL_TWO_DURING_ROCKET_JUMP", 5 );
  565. //----------------------------------------------------------------------------------------------------------------
  566. class CAchievementTFSoldier_KillTaunt : public CBaseTFAchievement
  567. {
  568. void Init()
  569. {
  570. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_ENEMY_EVENTS );
  571. SetGoal( 1 );
  572. }
  573. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  574. {
  575. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  576. if ( pAttacker == pLocalPlayer )
  577. {
  578. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  579. if ( pTFVictim && event->GetInt( "customkill" ) == TF_DMG_CUSTOM_TAUNTATK_GRENADE )
  580. {
  581. IncrementCount();
  582. }
  583. }
  584. }
  585. };
  586. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillTaunt, ACHIEVEMENT_TF_SOLDIER_KILL_TAUNT, "TF_SOLDIER_KILL_TAUNT", 5 );
  587. //----------------------------------------------------------------------------------------------------------------
  588. class CAchievementTFSoldier_DefendMedic : public CBaseTFAchievement
  589. {
  590. void Init()
  591. {
  592. SetFlags( ACH_SAVE_GLOBAL );
  593. SetGoal( 1 );
  594. }
  595. virtual void ListenForEvents()
  596. {
  597. ListenForGameEvent( "teamplay_round_active" );
  598. ListenForGameEvent( "localplayer_respawn" );
  599. ListenForGameEvent( "medic_defended" );
  600. m_iMedicDefended = 0;
  601. }
  602. void FireGameEvent_Internal( IGameEvent *event )
  603. {
  604. if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
  605. FStrEq( event->GetName(), "localplayer_respawn" ) )
  606. {
  607. m_iMedicDefended = 0;
  608. }
  609. else if ( FStrEq( event->GetName(), "medic_defended" ) )
  610. {
  611. m_iMedicDefended++;
  612. if ( m_iMedicDefended == 3 )
  613. {
  614. IncrementCount();
  615. }
  616. }
  617. }
  618. int m_iMedicDefended;
  619. };
  620. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_DefendMedic, ACHIEVEMENT_TF_SOLDIER_DEFEND_MEDIC, "TF_SOLDIER_DEFEND_MEDIC", 5 );
  621. //----------------------------------------------------------------------------------------------------------------
  622. class CAchievementTFSoldier_KillWithEqualizerWhileHurt : public CBaseTFAchievement
  623. {
  624. void Init()
  625. {
  626. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
  627. SetGoal( 20 );
  628. SetStoreProgressInSteam( true );
  629. }
  630. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  631. {
  632. if ( !pVictim || !pVictim->IsPlayer() )
  633. return;
  634. CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
  635. if ( pTFAttacker && (pTFAttacker == C_BasePlayer::GetLocalPlayer()) && (event->GetInt( "weaponid" ) == TF_WEAPON_SHOVEL) )
  636. {
  637. CTFShovel *pShovel = static_cast<CTFShovel*>(pTFAttacker->GetActiveWeapon());
  638. if ( pShovel && (pShovel->GetShovelType() == SHOVEL_DAMAGE_BOOST) )
  639. {
  640. if ( pAttacker->GetHealth() < 25 )
  641. {
  642. IncrementCount();
  643. }
  644. }
  645. }
  646. }
  647. };
  648. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillWithEqualizerWhileHurt, ACHIEVEMENT_TF_SOLDIER_KILL_WITH_EQUALIZER_WHILE_HURT, "TF_SOLDIER_KILL_WITH_EQUALIZER_WHILE_HURT", 5 );
  649. //----------------------------------------------------------------------------------------------------------------
  650. class CAchievementTFSoldier_KillAirborneTargetWhileAirborne : public CBaseTFAchievement
  651. {
  652. void Init()
  653. {
  654. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  655. SetGoal( 1 );
  656. }
  657. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  658. {
  659. if ( pAttacker == C_BasePlayer::GetLocalPlayer() && !(pAttacker->GetFlags() & FL_ONGROUND) )
  660. {
  661. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  662. if ( pTFVictim )
  663. {
  664. if ( !(pTFVictim->GetFlags() & FL_ONGROUND) && pTFVictim->IsPlayerClass( TF_CLASS_SOLDIER ) )
  665. {
  666. IncrementCount();
  667. }
  668. }
  669. }
  670. }
  671. };
  672. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillAirborneTargetWhileAirborne, ACHIEVEMENT_TF_SOLDIER_KILL_AIRBORNE_TARGET_WHILE_AIRBORNE, "TF_SOLDIER_KILL_AIRBORNE_TARGET_WHILE_AIRBORNE", 5 );
  673. //----------------------------------------------------------------------------------------------------------------
  674. class CAchievementTFSoldier_BounceThenShotgun : public CBaseTFAchievement
  675. {
  676. void Init()
  677. {
  678. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  679. SetGoal( 1 );
  680. SetDefLessFunc( m_BouncedPlayers );
  681. }
  682. virtual void ListenForEvents()
  683. {
  684. ListenForGameEvent( "teamplay_round_active" );
  685. ListenForGameEvent( "localplayer_respawn" );
  686. ListenForGameEvent( "player_hurt" );
  687. m_BouncedPlayers.RemoveAll();
  688. }
  689. void FireGameEvent_Internal( IGameEvent *event )
  690. {
  691. if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
  692. FStrEq( event->GetName(), "localplayer_respawn" ) )
  693. {
  694. m_BouncedPlayers.RemoveAll();
  695. }
  696. else if ( FStrEq( event->GetName(), "player_hurt" ) )
  697. {
  698. int iSoldier = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
  699. CBasePlayer *pSoldier = UTIL_PlayerByIndex( iSoldier );
  700. if ( pSoldier && pSoldier == C_TFPlayer::GetLocalTFPlayer() )
  701. {
  702. int iVictim = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  703. CBasePlayer *pVictim = UTIL_PlayerByIndex( iVictim );
  704. if ( pVictim )
  705. {
  706. //Vector vVictimVelocity = pVictim->GetAbsVelocity();
  707. bool bVictimGrounded = pVictim->GetFlags() & FL_ONGROUND;
  708. int iWeaponID = event->GetInt( "weaponid" );
  709. bool bRocketLauncherUsed = (iWeaponID == TF_WEAPON_ROCKETLAUNCHER) || (iWeaponID == TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT);
  710. if ( bVictimGrounded && bRocketLauncherUsed )
  711. {
  712. int iIndex = m_BouncedPlayers.Find( pVictim->GetUserID() );
  713. if ( iIndex != m_BouncedPlayers.InvalidIndex() )
  714. {
  715. // they're already in our list
  716. m_BouncedPlayers[iIndex] = gpGlobals->curtime;
  717. }
  718. else
  719. {
  720. // we need to add them
  721. m_BouncedPlayers.Insert( pVictim->GetUserID(), gpGlobals->curtime );
  722. }
  723. }
  724. }
  725. }
  726. }
  727. }
  728. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  729. {
  730. if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  731. {
  732. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  733. if ( pTFVictim && !( pTFVictim->GetFlags() & FL_ONGROUND ) && ( event->GetInt( "weaponid" ) == TF_WEAPON_SHOTGUN_SOLDIER ) )
  734. {
  735. int iIndex = m_BouncedPlayers.Find( pTFVictim->GetUserID() );
  736. if ( iIndex != m_BouncedPlayers.InvalidIndex() )
  737. {
  738. if ( gpGlobals->curtime < m_BouncedPlayers[iIndex] + 4.f )
  739. {
  740. IncrementCount();
  741. }
  742. }
  743. }
  744. }
  745. }
  746. CUtlMap< int, float > m_BouncedPlayers; // userID and most recent time they were bounced
  747. };
  748. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_BounceThenShotgun, ACHIEVEMENT_TF_SOLDIER_BOUNCE_THEN_SHOTGUN, "TF_SOLDIER_BOUNCE_THEN_SHOTGUN", 5 );
  749. //----------------------------------------------------------------------------------------------------------------
  750. class CAchievementTFSoldier_KillAirborneWithDirectHit : public CBaseTFAchievement
  751. {
  752. void Init()
  753. {
  754. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  755. SetGoal( 10 );
  756. SetStoreProgressInSteam( true );
  757. }
  758. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  759. {
  760. if ( pAttacker != C_BasePlayer::GetLocalPlayer() )
  761. return;
  762. C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
  763. if ( !pTFVictim )
  764. return;
  765. C_TFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
  766. if ( !pTFAttacker )
  767. return;
  768. CTFWeaponBase *pWeapon = pTFAttacker->GetActiveTFWeapon();
  769. int iMiniCritAirborne = 0;
  770. CALL_ATTRIB_HOOK_INT_ON_OTHER( pWeapon, iMiniCritAirborne, mini_crit_airborne );
  771. if ( iMiniCritAirborne == 1 && !(pTFVictim->GetFlags() & FL_ONGROUND) )
  772. {
  773. IncrementCount();
  774. }
  775. }
  776. };
  777. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillAirborneWithDirectHit, ACHIEVEMENT_TF_SOLDIER_KILL_AIRBORNE_WITH_DIRECT_HIT, "TF_SOLDIER_KILL_AIRBORNE_WITH_DIRECT_HIT", 5 );
  778. //----------------------------------------------------------------------------------------------------------------
  779. class CAchievementTFSoldier_KillSniperWhileDead : public CBaseTFAchievement
  780. {
  781. void Init()
  782. {
  783. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  784. SetGoal( 1 );
  785. }
  786. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  787. {
  788. CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
  789. int iWeaponID = event->GetInt( "weaponid" );
  790. bool bRocketLauncherUsed = (iWeaponID == TF_WEAPON_ROCKETLAUNCHER) || (iWeaponID == TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT);
  791. if ( pTFVictim && (pAttacker == C_TFPlayer::GetLocalTFPlayer()) && (pAttacker->IsAlive() == false) &&
  792. bRocketLauncherUsed && pTFVictim->IsPlayerClass( TF_CLASS_SNIPER ) )
  793. {
  794. IncrementCount();
  795. }
  796. }
  797. };
  798. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillSniperWhileDead, ACHIEVEMENT_TF_SOLDIER_KILL_SNIPER_WHILE_DEAD, "TF_SOLDIER_KILL_SNIPER_WHILE_DEAD", 5 );
  799. //----------------------------------------------------------------------------------------------------------------
  800. class CAchievementTFSoldier_DestroySentryOutOfRange : public CBaseTFAchievement
  801. {
  802. void Init()
  803. {
  804. SetFlags( ACH_SAVE_GLOBAL );
  805. SetGoal( 5 );
  806. SetStoreProgressInSteam( true );
  807. }
  808. };
  809. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_DestroySentryOutOfRange, ACHIEVEMENT_TF_SOLDIER_DESTROY_SENTRY_OUT_OF_RANGE, "TF_SOLDIER_DESTROY_SENTRY_OUT_OF_RANGE", 5 );
  810. //----------------------------------------------------------------------------------------------------------------
  811. class CAchievementTFSoldier_AssistMedicUbercharge : public CBaseTFAchievement
  812. {
  813. void Init()
  814. {
  815. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  816. SetGoal( 1 );
  817. m_iPlayersGibbed = 0;
  818. }
  819. virtual void ListenForEvents()
  820. {
  821. ListenForGameEvent( "player_invulned" );
  822. }
  823. virtual void FireGameEvent_Internal( IGameEvent *event )
  824. {
  825. if ( FStrEq( event->GetName(), "player_invulned" ) )
  826. {
  827. int iTarget = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  828. CBaseEntity *pPlayer = UTIL_PlayerByIndex( iTarget );
  829. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  830. if ( pPlayer == pLocalPlayer )
  831. {
  832. m_iPlayersGibbed = 0;
  833. }
  834. }
  835. }
  836. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  837. {
  838. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  839. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  840. {
  841. if ( event->GetInt( "death_flags" ) & TF_DEATH_GIBBED )
  842. {
  843. if ( pLocalPlayer->m_Shared.InCond( TF_COND_INVULNERABLE ) || pLocalPlayer->m_Shared.InCond( TF_COND_CRITBOOSTED ) ||
  844. pLocalPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF ) )
  845. {
  846. m_iPlayersGibbed++;
  847. if ( m_iPlayersGibbed >= 5 )
  848. {
  849. IncrementCount();
  850. }
  851. }
  852. }
  853. }
  854. }
  855. private:
  856. int m_iPlayersGibbed;
  857. };
  858. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_AssistMedicUbercharge, ACHIEVEMENT_TF_SOLDIER_ASSIST_MEDIC_UBER, "TF_SOLDIER_ASSIST_MEDIC_UBER", 5 );
  859. //----------------------------------------------------------------------------------------------------------------
  860. class CAchievementTFSoldier_ShootMultCrits : public CBaseTFAchievement
  861. {
  862. void Init()
  863. {
  864. SetFlags( ACH_SAVE_GLOBAL );
  865. SetGoal( 1 );
  866. }
  867. };
  868. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_ShootMultCrits, ACHIEVEMENT_TF_SOLDIER_SHOOT_MULT_CRITS, "TF_SOLDIER_SHOOT_MULT_CRITS", 5 );
  869. //----------------------------------------------------------------------------------------------------------------
  870. class CAchievementTFSoldier_KillDefenseless : public CBaseTFAchievement
  871. {
  872. void Init()
  873. {
  874. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  875. SetGoal( 1 );
  876. }
  877. virtual bool LocalPlayerCanEarn( void )
  878. {
  879. if ( TFGameRules() )
  880. {
  881. bool bMVMAchievement = ( m_iAchievementID >= ACHIEVEMENT_TF_MVM_START_RANGE && m_iAchievementID <= ACHIEVEMENT_TF_MVM_END_RANGE );
  882. if ( ( bMVMAchievement && !TFGameRules()->IsMannVsMachineMode() ) || ( !bMVMAchievement && TFGameRules()->IsMannVsMachineMode() ) )
  883. {
  884. return false;
  885. }
  886. }
  887. // This achievement can be earned while we're in the post-win state
  888. return IsLocalTFPlayerClass( TF_CLASS_SOLDIER );
  889. }
  890. virtual void ListenForEvents()
  891. {
  892. m_iPlayersKilled = 0;
  893. ListenForGameEvent( "teamplay_win_panel" );
  894. }
  895. virtual void FireGameEvent_Internal( IGameEvent *event )
  896. {
  897. if ( FStrEq( event->GetName(), "teamplay_win_panel" ) )
  898. {
  899. m_iPlayersKilled = 0;
  900. }
  901. }
  902. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  903. {
  904. if ( TFGameRules()->State_Get() != GR_STATE_TEAM_WIN )
  905. return;
  906. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  907. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  908. {
  909. m_iPlayersKilled++;
  910. if ( m_iPlayersKilled >= 3 )
  911. {
  912. IncrementCount();
  913. }
  914. }
  915. }
  916. private:
  917. int m_iPlayersKilled;
  918. };
  919. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillDefenseless, ACHIEVEMENT_TF_SOLDIER_KILL_DEFENSELESS, "TF_SOLDIER_KILL_DEFENSELESS", 5 );
  920. //----------------------------------------------------------------------------------------------------------------
  921. class CAchievementTFSoldier_KillWhileOnFire : public CBaseTFAchievement
  922. {
  923. void Init()
  924. {
  925. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  926. SetGoal( 20 );
  927. SetStoreProgressInSteam( true );
  928. }
  929. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  930. {
  931. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  932. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  933. {
  934. if ( pLocalPlayer->m_Shared.InCond(TF_COND_BURNING) )
  935. {
  936. IncrementCount();
  937. }
  938. }
  939. }
  940. };
  941. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillWhileOnFire, ACHIEVEMENT_TF_SOLDIER_KILL_ON_FIRE, "TF_SOLDIER_KILL_ON_FIRE", 5 );
  942. //----------------------------------------------------------------------------------------------------------------
  943. class CAchievementTFSoldier_FreezeTaunts : public CBaseTFAchievement
  944. {
  945. void Init()
  946. {
  947. SetFlags( ACH_SAVE_GLOBAL );
  948. SetGoal( 1 );
  949. }
  950. // Give opponents freezecams of you taunting
  951. // server awards this achievement, no other code within achievement necessary
  952. };
  953. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_FreezeTaunts, ACHIEVEMENT_TF_SOLDIER_FREEZECAM_TAUNT, "TF_SOLDIER_FREEZECAM_TAUNT", 5 );
  954. //----------------------------------------------------------------------------------------------------------------
  955. class CAchievementTFSoldier_FreezeGibs : public CBaseTFAchievement
  956. {
  957. void Init()
  958. {
  959. SetFlags( ACH_SAVE_GLOBAL );
  960. SetGoal( 1 );
  961. }
  962. // Give opponents freezecams of you with X gibs onscreen
  963. // server awards this achievement, no other code within achievement necessary
  964. };
  965. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_FreezeGibs, ACHIEVEMENT_TF_SOLDIER_FREEZECAM_GIBS, "TF_SOLDIER_FREEZECAM_GIBS", 5 );
  966. //----------------------------------------------------------------------------------------------------------------
  967. class CAchievementTFSoldier_KillSpyKiller : public CBaseTFAchievement
  968. {
  969. void Init()
  970. {
  971. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  972. SetGoal( 1 );
  973. }
  974. virtual void ListenForEvents( void )
  975. {
  976. m_vecBackstabbers.Purge();
  977. ListenForGameEvent( "teamplay_round_active" );
  978. ListenForGameEvent( "localplayer_respawn" );
  979. }
  980. void FireGameEvent_Internal( IGameEvent *event )
  981. {
  982. const char *pszEvent = event->GetName();
  983. if ( FStrEq( pszEvent, "teamplay_round_active" ) || FStrEq( pszEvent, "localplayer_respawn" ) )
  984. {
  985. m_vecBackstabbers.Purge();
  986. }
  987. }
  988. int GetBackstabberIndex( CBaseEntity *pTarget )
  989. {
  990. for ( int i = 0; i < m_vecBackstabbers.Count(); i++ )
  991. {
  992. if ( m_vecBackstabbers[i].hSpy == pTarget )
  993. return i;
  994. }
  995. return -1;
  996. }
  997. void AddNewBackstabber( CBaseEntity *pTarget )
  998. {
  999. if ( !pTarget )
  1000. return;
  1001. // see if the target is already in our list or get a new index
  1002. int iTargetIndex = GetBackstabberIndex( pTarget );
  1003. if ( iTargetIndex == -1 )
  1004. {
  1005. iTargetIndex = m_vecBackstabbers.AddToTail();
  1006. }
  1007. m_vecBackstabbers[iTargetIndex].hSpy = pTarget;
  1008. m_vecBackstabbers[iTargetIndex].flBackstabWindow = gpGlobals->curtime + 5.0f; // 5 seconds to kill the target
  1009. }
  1010. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1011. {
  1012. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1013. if ( pVictim == pLocalPlayer )
  1014. return;
  1015. CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
  1016. if ( pTFAttacker && pTFAttacker->IsPlayerClass( TF_CLASS_SPY ) && pVictim->InSameTeam( pLocalPlayer ) )
  1017. {
  1018. int customkill = event->GetInt( "customkill" );
  1019. if ( customkill == TF_DMG_CUSTOM_BACKSTAB )
  1020. {
  1021. AddNewBackstabber( pTFAttacker );
  1022. }
  1023. }
  1024. else if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() )
  1025. {
  1026. int iTargetIndex = GetBackstabberIndex( pVictim );
  1027. if ( iTargetIndex != -1 )
  1028. {
  1029. if ( m_vecBackstabbers[iTargetIndex].flBackstabWindow > gpGlobals->curtime )
  1030. {
  1031. // We killed him within 5 seconds of him backstabbing a buddy
  1032. IncrementCount();
  1033. }
  1034. m_vecBackstabbers.Remove( iTargetIndex );
  1035. }
  1036. }
  1037. }
  1038. private:
  1039. struct backstabber_t
  1040. {
  1041. EHANDLE hSpy;
  1042. float flBackstabWindow;
  1043. };
  1044. CUtlVector<backstabber_t> m_vecBackstabbers;
  1045. };
  1046. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillSpyKiller, ACHIEVEMENT_TF_SOLDIER_KILL_SPY_KILLER, "TF_SOLDIER_KILL_SPY_KILLER", 5 );
  1047. //----------------------------------------------------------------------------------------------------------------
  1048. class CAchievementTFSoldier_GibGrind : public CBaseTFAchievement
  1049. {
  1050. void Init()
  1051. {
  1052. SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
  1053. SetGoal( 1000 );
  1054. SetStoreProgressInSteam( true );
  1055. }
  1056. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1057. {
  1058. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1059. if ( pAttacker == pLocalPlayer && pVictim && pVictim->IsPlayer() && pVictim != pLocalPlayer )
  1060. {
  1061. if ( event->GetInt( "death_flags" ) & TF_DEATH_GIBBED )
  1062. {
  1063. IncrementCount();
  1064. }
  1065. }
  1066. }
  1067. };
  1068. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_GibGrind, ACHIEVEMENT_TF_SOLDIER_GIB_GRIND, "TF_SOLDIER_GIB_GRIND", 5 );
  1069. //----------------------------------------------------------------------------------------------------------------
  1070. class CAchievementTFSoldier_DuoSoldierKills : public CBaseTFAchievement
  1071. {
  1072. void Init()
  1073. {
  1074. SetFlags( ACH_SAVE_GLOBAL );
  1075. SetGoal( 10 );
  1076. SetStoreProgressInSteam( true );
  1077. }
  1078. virtual void ListenForEvents()
  1079. {
  1080. ListenForGameEvent( "player_death" );
  1081. }
  1082. void FireGameEvent_Internal( IGameEvent *event )
  1083. {
  1084. if ( FStrEq( event->GetName(), "player_death" ) )
  1085. {
  1086. int iAttackerIndex = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
  1087. if ( iAttackerIndex == 0 )
  1088. return;
  1089. CTFPlayer *pAttacker = ToTFPlayer( UTIL_PlayerByIndex( iAttackerIndex ) );
  1090. if ( !pAttacker )
  1091. return;
  1092. int iAssisterIndex = engine->GetPlayerForUserID( event->GetInt( "assister" ) );
  1093. if ( iAssisterIndex == 0 )
  1094. return;
  1095. CTFPlayer *pAssister = ToTFPlayer( UTIL_PlayerByIndex( iAssisterIndex ) );
  1096. if ( !pAssister )
  1097. return;
  1098. if ( pAttacker == C_BasePlayer::GetLocalPlayer() && pAssister->IsPlayerClass( TF_CLASS_SOLDIER ) )
  1099. {
  1100. // We are the attacker and the assist is from a soldier.
  1101. IncrementCount();
  1102. return;
  1103. }
  1104. if ( pAssister == C_BasePlayer::GetLocalPlayer() && pAttacker->IsPlayerClass( TF_CLASS_SOLDIER ) )
  1105. {
  1106. // We are the assister and the kill is from a soldier.
  1107. IncrementCount();
  1108. return;
  1109. }
  1110. }
  1111. }
  1112. };
  1113. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_DuoSoldierKills, ACHIEVEMENT_TF_SOLDIER_DUO_SOLDIER_KILLS, "TF_SOLDIER_DUO_SOLDIER_KILLS", 5 );
  1114. //----------------------------------------------------------------------------------------------------------------
  1115. class CAchievementTFSoldier_MVP : public CBaseTFAchievement
  1116. {
  1117. void Init()
  1118. {
  1119. SetFlags( ACH_SAVE_GLOBAL );
  1120. SetGoal( 10 );
  1121. SetStoreProgressInSteam( true );
  1122. }
  1123. virtual void ListenForEvents()
  1124. {
  1125. ListenForGameEvent( "player_mvp" );
  1126. }
  1127. void FireGameEvent_Internal( IGameEvent *event )
  1128. {
  1129. if ( FStrEq( event->GetName(), "player_mvp" ) )
  1130. {
  1131. CTFPlayer *pTFPlayer = ToTFPlayer( UTIL_PlayerByIndex( event->GetInt( "player" ) ) );
  1132. if ( !pTFPlayer )
  1133. return;
  1134. if ( pTFPlayer == C_BasePlayer::GetLocalPlayer() )
  1135. {
  1136. if ( CalcTeammateCount() >= 5 )
  1137. {
  1138. IncrementCount();
  1139. }
  1140. }
  1141. }
  1142. }
  1143. };
  1144. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_MVP, ACHIEVEMENT_TF_SOLDIER_MVP, "TF_SOLDIER_MVP", 5 );
  1145. //----------------------------------------------------------------------------------------------------------------
  1146. class CAchievementTFSoldier_ThreeDominations : public CBaseTFAchievement
  1147. {
  1148. void Init()
  1149. {
  1150. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  1151. SetGoal( 1 );
  1152. nDominations = 0;
  1153. }
  1154. virtual void ListenForEvents()
  1155. {
  1156. ListenForGameEvent( "teamplay_round_start" );
  1157. ListenForGameEvent( "localplayer_respawn" );
  1158. }
  1159. void FireGameEvent_Internal( IGameEvent *event )
  1160. {
  1161. const char *pszEvent = event->GetName();
  1162. if ( ( FStrEq( pszEvent, "localplayer_respawn" ) || FStrEq( pszEvent, "teamplay_round_start" ) ) )
  1163. {
  1164. nDominations = 0;
  1165. }
  1166. }
  1167. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1168. {
  1169. // Player died
  1170. if ( pVictim == C_BasePlayer::GetLocalPlayer() )
  1171. {
  1172. nDominations = 0;
  1173. return;
  1174. }
  1175. if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  1176. {
  1177. bool bDomination = event->GetInt( "death_flags" ) & TF_DEATH_DOMINATION;
  1178. if ( bDomination )
  1179. {
  1180. CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
  1181. if ( pTFVictim )
  1182. {
  1183. nDominations++;
  1184. }
  1185. }
  1186. }
  1187. if ( nDominations >= 3 )
  1188. {
  1189. IncrementCount();
  1190. }
  1191. }
  1192. private:
  1193. int nDominations;
  1194. };
  1195. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_ThreeDominations, ACHIEVEMENT_TF_SOLDIER_THREE_DOMINATIONS, "TF_SOLDIER_THREE_DOMINATIONS", 5 );
  1196. //----------------------------------------------------------------------------------------------------------------
  1197. class CAchievementTFSoldier_RideTheCart : public CBaseTFAchievement
  1198. {
  1199. void Init()
  1200. {
  1201. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  1202. SetGoal( 1 );
  1203. }
  1204. virtual void ListenForEvents()
  1205. {
  1206. ListenForGameEvent( "controlpoint_starttouch" );
  1207. ListenForGameEvent( "controlpoint_endtouch" );
  1208. ListenForGameEvent( "teamplay_round_win" );
  1209. ListenForGameEvent( "teamplay_round_start" );
  1210. ResetStatus();
  1211. m_nRideTime = 30;
  1212. }
  1213. void ResetStatus()
  1214. {
  1215. ClearThink();
  1216. m_bIsThinking = false;
  1217. m_fRideStartTime = 0;
  1218. }
  1219. void FireGameEvent_Internal( IGameEvent *event )
  1220. {
  1221. // Pushed the cart onto the cap before time
  1222. if ( Q_strcmp( event->GetName(), "teamplay_round_win" ) == 0 && m_bIsThinking )
  1223. {
  1224. ResetStatus();
  1225. }
  1226. if ( Q_strcmp( event->GetName(), "teamplay_round_start" ) == 0 && m_bIsThinking )
  1227. {
  1228. ResetStatus();
  1229. }
  1230. if ( !TFGameRules() || TFGameRules()->GetGameType() != TF_GAMETYPE_ESCORT )
  1231. return;
  1232. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1233. if ( !pLocalPlayer )
  1234. return;
  1235. C_TFTeam *pTeam = GetGlobalTFTeam( pLocalPlayer->GetTeamNumber() );
  1236. if ( pTeam->GetRole() != TEAM_ROLE_ATTACKERS )
  1237. return;
  1238. // Player in cart trigger. Register the time.
  1239. if ( Q_strcmp( event->GetName(), "controlpoint_starttouch" ) == 0 && !m_bIsThinking )
  1240. {
  1241. int iPlayerIndex = event->GetInt( "player", 0 );
  1242. if ( iPlayerIndex == GetLocalPlayerIndex() )
  1243. {
  1244. m_fRideStartTime = gpGlobals->curtime + (float)m_nRideTime;
  1245. SetNextThink( m_nRideTime );
  1246. m_bIsThinking = true;
  1247. }
  1248. }
  1249. // Reset conditions:
  1250. // Left the trigger
  1251. if ( Q_strcmp( event->GetName(), "controlpoint_endtouch" ) == 0 && m_bIsThinking )
  1252. {
  1253. int iPlayerIndex = event->GetInt( "player", 0 );
  1254. if ( iPlayerIndex == GetLocalPlayerIndex() )
  1255. {
  1256. ResetStatus();
  1257. }
  1258. }
  1259. }
  1260. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1261. {
  1262. // Died in the trigger
  1263. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1264. if ( pVictim == pLocalPlayer && m_bIsThinking )
  1265. {
  1266. ResetStatus();
  1267. }
  1268. }
  1269. virtual void Think( void )
  1270. {
  1271. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1272. if ( !TFGameRules() )
  1273. return;
  1274. if ( pLocalPlayer && pLocalPlayer->IsAlive() && m_fRideStartTime <= gpGlobals->curtime )
  1275. {
  1276. IncrementCount();
  1277. }
  1278. }
  1279. private:
  1280. int m_nRideTime;
  1281. float m_fRideStartTime;
  1282. bool m_bIsThinking;
  1283. };
  1284. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_RideTheCart, ACHIEVEMENT_TF_SOLDIER_RIDE_THE_CART, "TF_SOLDIER_RIDE_THE_CART", 5 );
  1285. //----------------------------------------------------------------------------------------------------------------
  1286. class CAchievementTFSoldier_KillTwentyFromAbove : public CBaseTFAchievement
  1287. {
  1288. void Init()
  1289. {
  1290. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  1291. SetGoal( 20 );
  1292. SetStoreProgressInSteam( true );
  1293. }
  1294. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1295. {
  1296. CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  1297. if ( pLocalPlayer )
  1298. {
  1299. int iWeaponID = event->GetInt( "weaponid" );
  1300. bool bRocketLauncherUsed = (iWeaponID == TF_WEAPON_ROCKETLAUNCHER) || (iWeaponID == TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT);
  1301. if ( pAttacker == pLocalPlayer && bRocketLauncherUsed )
  1302. {
  1303. // Determine height difference - probably need to factor in distance, too
  1304. Vector vecAttacker = pAttacker->GetAbsOrigin();
  1305. Vector vecVictim = pVictim->GetAbsOrigin();
  1306. Vector vecDelta = vecAttacker - vecVictim;
  1307. // Msg( "ZDelta: %f \n", vecDelta.z );
  1308. if ( vecDelta.z >= 92 )
  1309. {
  1310. IncrementCount();
  1311. }
  1312. }
  1313. }
  1314. }
  1315. };
  1316. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillTwentyFromAbove, ACHIEVEMENT_TF_SOLDIER_KILL_TWENTY_FROM_ABOVE, "TF_SOLDIER_KILL_TWENTY_FROM_ABOVE", 5 );
  1317. //----------------------------------------------------------------------------------------------------------------
  1318. class CAchievementTFSoldier_KillFiveStunned : public CBaseTFAchievement
  1319. {
  1320. void Init()
  1321. {
  1322. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  1323. SetGoal( 5 );
  1324. SetStoreProgressInSteam( true );
  1325. }
  1326. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1327. {
  1328. CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
  1329. if ( pLocalPlayer )
  1330. {
  1331. if ( pAttacker == pLocalPlayer )
  1332. {
  1333. int iStunFlags = event->GetInt( "stun_flags" );
  1334. if ( ( iStunFlags & TF_STUN_LOSER_STATE ) != 0 ||
  1335. ( iStunFlags & TF_STUN_CONTROLS ) != 0 )
  1336. {
  1337. IncrementCount();
  1338. }
  1339. }
  1340. }
  1341. }
  1342. };
  1343. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_KillFiveStunned, ACHIEVEMENT_TF_SOLDIER_KILL_FIVE_STUNNED, "TF_SOLDIER_KILL_FIVE_STUNNED", 5 );
  1344. //----------------------------------------------------------------------------------------------------------------
  1345. class CAchievementTFSoldier_DefendCapThirtyTimes : public CBaseTFAchievement
  1346. {
  1347. void Init()
  1348. {
  1349. SetFlags( ACH_SAVE_GLOBAL );
  1350. SetGoal( 30 );
  1351. SetStoreProgressInSteam( true );
  1352. }
  1353. virtual void ListenForEvents()
  1354. {
  1355. ListenForGameEvent( "teamplay_capture_blocked" );
  1356. }
  1357. void FireGameEvent_Internal( IGameEvent *event )
  1358. {
  1359. if ( FStrEq( event->GetName(), "teamplay_capture_blocked" ) )
  1360. {
  1361. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1362. if ( pLocalPlayer )
  1363. {
  1364. int iBlocker = event->GetInt( "blocker", 0 );
  1365. if ( iBlocker == GetLocalPlayerIndex() )
  1366. {
  1367. IncrementCount();
  1368. }
  1369. }
  1370. }
  1371. }
  1372. };
  1373. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_DefendCapThirtyTimes, ACHIEVEMENT_TF_SOLDIER_DEFEND_CAP_THIRTY_TIMES, "TF_SOLDIER_DEFEND_CAP_THIRTY_TIMES", 5 );
  1374. //----------------------------------------------------------------------------------------------------------------
  1375. class CAchievementTFSoldier_AchieveProgress1 : public CAchievement_AchievedCount
  1376. {
  1377. public:
  1378. DECLARE_CLASS( CAchievementTFSoldier_AchieveProgress1, CAchievement_AchievedCount );
  1379. void Init()
  1380. {
  1381. BaseClass::Init();
  1382. SetAchievementsRequired( 5, ACHIEVEMENT_TF_SOLDIER_START_RANGE, ACHIEVEMENT_TF_SOLDIER_END_RANGE );
  1383. }
  1384. };
  1385. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_AchieveProgress1, ACHIEVEMENT_TF_SOLDIER_ACHIEVE_PROGRESS1, "TF_SOLDIER_ACHIEVE_PROGRESS1", 5 );
  1386. //----------------------------------------------------------------------------------------------------------------
  1387. class CAchievementTFSoldier_AchieveProgress2 : public CAchievement_AchievedCount
  1388. {
  1389. public:
  1390. DECLARE_CLASS( CAchievementTFSoldier_AchieveProgress2, CAchievement_AchievedCount );
  1391. void Init()
  1392. {
  1393. BaseClass::Init();
  1394. SetAchievementsRequired( 11, ACHIEVEMENT_TF_SOLDIER_START_RANGE, ACHIEVEMENT_TF_SOLDIER_END_RANGE );
  1395. }
  1396. };
  1397. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_AchieveProgress2, ACHIEVEMENT_TF_SOLDIER_ACHIEVE_PROGRESS2, "TF_SOLDIER_ACHIEVE_PROGRESS2", 5 );
  1398. //----------------------------------------------------------------------------------------------------------------
  1399. class CAchievementTFSoldier_AchieveProgress3 : public CAchievement_AchievedCount
  1400. {
  1401. public:
  1402. DECLARE_CLASS( CAchievementTFSoldier_AchieveProgress3, CAchievement_AchievedCount );
  1403. void Init()
  1404. {
  1405. BaseClass::Init();
  1406. SetAchievementsRequired( 17, ACHIEVEMENT_TF_SOLDIER_START_RANGE, ACHIEVEMENT_TF_SOLDIER_END_RANGE );
  1407. }
  1408. };
  1409. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_AchieveProgress3, ACHIEVEMENT_TF_SOLDIER_ACHIEVE_PROGRESS3, "TF_SOLDIER_ACHIEVE_PROGRESS3", 5 );
  1410. //----------------------------------------------------------------------------------------------------------------
  1411. class CAchievementTFSoldier_ParachuteKillGroup : public CBaseTFAchievement
  1412. {
  1413. public:
  1414. void Init()
  1415. {
  1416. SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
  1417. SetGoal( 1 );
  1418. ResetTracking();
  1419. }
  1420. virtual void ListenForEvents()
  1421. {
  1422. ListenForGameEvent( "parachute_deploy" );
  1423. ListenForGameEvent( "parachute_holster" );
  1424. }
  1425. void ResetTracking( void )
  1426. {
  1427. m_nKills = 0;
  1428. m_bParachuteDeployed = false;
  1429. }
  1430. void FireGameEvent_Internal( IGameEvent *event )
  1431. {
  1432. const char *pszEvent = event->GetName();
  1433. if ( FStrEq( pszEvent, "parachute_deploy" ) )
  1434. {
  1435. if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
  1436. {
  1437. ResetTracking();
  1438. m_bParachuteDeployed = true;
  1439. }
  1440. }
  1441. else if ( FStrEq( pszEvent, "parachute_holster" ) )
  1442. {
  1443. if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
  1444. {
  1445. ResetTracking();
  1446. }
  1447. }
  1448. }
  1449. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1450. {
  1451. if ( pVictim )
  1452. {
  1453. // Local player died
  1454. if ( pVictim == C_BasePlayer::GetLocalPlayer() )
  1455. {
  1456. ResetTracking();
  1457. }
  1458. else if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
  1459. {
  1460. if ( m_bParachuteDeployed )
  1461. {
  1462. m_nKills++;
  1463. if ( m_nKills >= 3 )
  1464. {
  1465. IncrementCount();
  1466. }
  1467. }
  1468. }
  1469. }
  1470. }
  1471. private:
  1472. int m_nKills;
  1473. bool m_bParachuteDeployed;
  1474. };
  1475. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_ParachuteKillGroup, ACHIEVEMENT_TF_SOLDIER_PARACHUTE_KILL_GROUP, "TF_SOLDIER_PARACHUTE_KILL_GROUP", 5 );
  1476. //----------------------------------------------------------------------------------------------------------------
  1477. class CAchievementTFSoldier_ParachuteDistance : public CBaseTFAchievement
  1478. {
  1479. public:
  1480. void Init()
  1481. {
  1482. SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
  1483. SetGoal( 1233619 );
  1484. SetStoreProgressInSteam( true );
  1485. ResetTracking();
  1486. }
  1487. virtual void ListenForEvents()
  1488. {
  1489. ListenForGameEvent( "parachute_deploy" );
  1490. ListenForGameEvent( "parachute_holster" );
  1491. }
  1492. void ResetTracking( void )
  1493. {
  1494. ClearThink();
  1495. m_flLastZ = 0.0;
  1496. }
  1497. void CheckHeight( void )
  1498. {
  1499. CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1500. if ( pLocalPlayer )
  1501. {
  1502. float flCurrentZ = pLocalPlayer->GetAbsOrigin().z;
  1503. float flDela = m_flLastZ - flCurrentZ;
  1504. // make sure we've fallen....we may have been pushed upwards
  1505. if ( flDela > 0.0f )
  1506. {
  1507. IncrementCount( (int)( flDela ) );
  1508. }
  1509. m_flLastZ = flCurrentZ;
  1510. }
  1511. }
  1512. void FireGameEvent_Internal( IGameEvent *event )
  1513. {
  1514. const char *pszEvent = event->GetName();
  1515. if ( FStrEq( pszEvent, "parachute_deploy" ) )
  1516. {
  1517. if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
  1518. {
  1519. CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1520. if ( pLocalPlayer )
  1521. {
  1522. m_flLastZ = pLocalPlayer->GetAbsOrigin().z;
  1523. SetNextThink( 0.1 );
  1524. }
  1525. }
  1526. }
  1527. else if ( FStrEq( pszEvent, "parachute_holster" ) )
  1528. {
  1529. if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
  1530. {
  1531. ResetTracking();
  1532. }
  1533. }
  1534. }
  1535. virtual void Think( void )
  1536. {
  1537. CheckHeight();
  1538. SetNextThink( 0.1 );
  1539. }
  1540. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1541. {
  1542. // Local player died
  1543. if ( pVictim == C_BasePlayer::GetLocalPlayer() )
  1544. {
  1545. ResetTracking();
  1546. }
  1547. }
  1548. private:
  1549. float m_flLastZ;
  1550. };
  1551. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_ParachuteDistance, ACHIEVEMENT_TF_SOLDIER_PARACHUTE_DISTANCE, "TF_SOLDIER_PARACHUTE_DISTANCE", 5 );
  1552. //----------------------------------------------------------------------------------------------------------------
  1553. class CAchievementTFSoldier_ParachuteKillParachute : public CBaseTFAchievement
  1554. {
  1555. public:
  1556. void Init()
  1557. {
  1558. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  1559. SetGoal( 1 );
  1560. }
  1561. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1562. {
  1563. CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
  1564. CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
  1565. if ( pTFAttacker && pTFVictim && ( pTFAttacker == C_TFPlayer::GetLocalTFPlayer() ) )
  1566. {
  1567. if ( ( pTFAttacker->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) && ( pTFVictim->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) )
  1568. {
  1569. IncrementCount();
  1570. }
  1571. }
  1572. }
  1573. };
  1574. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_ParachuteKillParachute, ACHIEVEMENT_TF_SOLDIER_PARACHUTE_KILL_PARACHUTE, "TF_SOLDIER_PARACHUTE_KILL_PARACHUTE", 5 );
  1575. //----------------------------------------------------------------------------------------------------------------
  1576. class CAchievementTFSoldier_AirstrikeMaxClip : public CBaseTFAchievement
  1577. {
  1578. public:
  1579. void Init()
  1580. {
  1581. SetFlags( ACH_SAVE_GLOBAL );
  1582. SetGoal( 1 );
  1583. }
  1584. // server awards this achievement, no other code within achievement necessary
  1585. };
  1586. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_AirstrikeMaxClip, ACHIEVEMENT_TF_SOLDIER_AIRSTRIKE_MAX_CLIP, "TF_SOLDIER_AIRSTRIKE_MAX_CLIP", 5 );
  1587. //----------------------------------------------------------------------------------------------------------------
  1588. class CAchievementTFSoldier_AirstrikeGroupKill : public CBaseTFAchievement
  1589. {
  1590. public:
  1591. void Init()
  1592. {
  1593. SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
  1594. SetGoal( 1 );
  1595. }
  1596. void ResetTracking( void )
  1597. {
  1598. m_iKilledDuringRJ = 0;
  1599. m_bRocketJumping = false;
  1600. }
  1601. virtual void ListenForEvents()
  1602. {
  1603. ListenForGameEvent( "rocket_jump" );
  1604. ListenForGameEvent( "rocket_jump_landed" );
  1605. ListenForGameEvent( "teamplay_round_active" );
  1606. ListenForGameEvent( "localplayer_respawn" );
  1607. ResetTracking();
  1608. }
  1609. void FireGameEvent_Internal( IGameEvent *event )
  1610. {
  1611. const char *pszEventName = event->GetName();
  1612. if ( FStrEq( pszEventName, "teamplay_round_active" ) ||
  1613. FStrEq( pszEventName, "localplayer_respawn" ) )
  1614. {
  1615. ResetTracking();
  1616. }
  1617. else if ( FStrEq( pszEventName, "rocket_jump_landed" ) )
  1618. {
  1619. int iUserID = event->GetInt( "userid" );
  1620. CBasePlayer *pLocalPlayer = CBasePlayer::GetLocalPlayer();
  1621. if ( pLocalPlayer && ( pLocalPlayer->GetUserID() == iUserID ) )
  1622. {
  1623. ResetTracking();
  1624. }
  1625. }
  1626. else if ( FStrEq( pszEventName, "rocket_jump" ) )
  1627. {
  1628. int iUserID = event->GetInt( "userid" );
  1629. CBasePlayer *pLocalPlayer = CBasePlayer::GetLocalPlayer();
  1630. if ( pLocalPlayer && ( pLocalPlayer->GetUserID() == iUserID ) )
  1631. {
  1632. m_iKilledDuringRJ = 0;
  1633. m_bRocketJumping = true;
  1634. }
  1635. }
  1636. }
  1637. virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
  1638. {
  1639. if ( pVictim && ( pAttacker == CBasePlayer::GetLocalPlayer() ) )
  1640. {
  1641. if ( m_bRocketJumping && ( event->GetInt( "weaponid" ) == TF_WEAPON_ROCKETLAUNCHER ) )
  1642. {
  1643. CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
  1644. if ( pTFAttacker )
  1645. {
  1646. CTFWeaponBase *pWeapon = pTFAttacker->GetActiveTFWeapon();
  1647. if ( pWeapon )
  1648. {
  1649. int iClipSizeOnKills = 0;
  1650. CALL_ATTRIB_HOOK_INT_ON_OTHER( pWeapon, iClipSizeOnKills, clipsize_increase_on_kill );
  1651. if ( iClipSizeOnKills )
  1652. {
  1653. m_iKilledDuringRJ++;
  1654. if ( m_iKilledDuringRJ == 3 )
  1655. {
  1656. IncrementCount();
  1657. }
  1658. }
  1659. }
  1660. }
  1661. }
  1662. }
  1663. }
  1664. private:
  1665. bool m_bRocketJumping;
  1666. int m_iKilledDuringRJ;
  1667. };
  1668. DECLARE_ACHIEVEMENT( CAchievementTFSoldier_AirstrikeGroupKill, ACHIEVEMENT_TF_SOLDIER_AIRSTRIKE_GROUP_KILL, "TF_SOLDIER_AIRSTRIKE_GROUP_KILL", 5 );
  1669. #endif // CLIENT_DLL