summaryrefslogtreecommitdiff
path: root/game/shared/tf/achievements_tf_demoman.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tf/achievements_tf_demoman.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/tf/achievements_tf_demoman.cpp')
-rw-r--r--game/shared/tf/achievements_tf_demoman.cpp1885
1 files changed, 1885 insertions, 0 deletions
diff --git a/game/shared/tf/achievements_tf_demoman.cpp b/game/shared/tf/achievements_tf_demoman.cpp
new file mode 100644
index 0000000..6a48a58
--- /dev/null
+++ b/game/shared/tf/achievements_tf_demoman.cpp
@@ -0,0 +1,1885 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+
+#include "cbase.h"
+
+#ifdef CLIENT_DLL
+
+#include "achievementmgr.h"
+#include "baseachievement.h"
+#include "tf_hud_statpanel.h"
+#include "c_tf_team.h"
+#include "c_tf_player.h"
+#include "c_tf_playerresource.h"
+#include "tf_gamerules.h"
+#include "achievements_tf.h"
+#include "c_tf_objective_resource.h"
+#include "tf_weapon_shovel.h"
+#include "movevars_shared.h"
+
+//======================================================================================================================================
+// DEMOMAN ACHIEVEMENT PACK
+//======================================================================================================================================
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillSoldierGrind : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
+ SetGoal( 500 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
+ {
+ // no friendly fire kills
+ if ( pVictim->GetTeamNumber() != pAttacker->GetTeamNumber() )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_SOLDIER ) )
+ {
+ // we killed a soldier
+ IncrementCount();
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillSoldierGrind, ACHIEVEMENT_TF_DEMOMAN_KILL_SOLDIER_GRIND, "TF_DEMOMAN_KILL_SOLDIER_GRIND", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DestroyBuildingsWithMedic : public CBaseTFAchievement
+{
+ DECLARE_CLASS( CAchievementTFDemoman_DestroyBuildingsWithMedic, CBaseTFAchievement );
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ m_iBuildingsDestroyed = 0;
+ }
+
+ virtual void ListenForEvents()
+ {
+ BaseClass::ListenForEvents();
+ ListenForGameEvent( "player_invulned" );
+ ListenForGameEvent( "object_destroyed" );
+ }
+
+ virtual void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "player_invulned" ) )
+ {
+ int iTarget = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ CBaseEntity *pPlayer = UTIL_PlayerByIndex( iTarget );
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pPlayer == pLocalPlayer )
+ {
+ m_iBuildingsDestroyed = 0;
+ }
+ }
+ else if ( Q_strcmp( event->GetName(), "object_destroyed" ) == 0 )
+ {
+ int iAttackerIndex = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
+ if ( iAttackerIndex > 0 )
+ {
+ CBaseEntity *pAttacker = UTIL_PlayerByIndex( iAttackerIndex );
+ C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pTFPlayer && pTFPlayer == pAttacker )
+ {
+ if ( pTFPlayer->m_Shared.InCond( TF_COND_INVULNERABLE ) || pTFPlayer->m_Shared.InCond( TF_COND_CRITBOOSTED ) ||
+ pTFPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF ) )
+ {
+ m_iBuildingsDestroyed++;
+ if ( m_iBuildingsDestroyed >= 5 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ BaseClass::FireGameEvent_Internal( event );
+ }
+ }
+
+private:
+ int m_iBuildingsDestroyed;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DestroyBuildingsWithMedic, ACHIEVEMENT_TF_DEMOMAN_DESTROY_BUILDINGS_WITH_MEDIC, "TF_DEMOMAN_DESTROY_BUILDINGS_WITH_MEDIC", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DecapitateCloakedSpy : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( !pTFVictim )
+ return;
+
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_SPY ) && pTFVictim->m_Shared.InCond( TF_COND_STEALTHED ) )
+ {
+ int customdmg = event->GetInt( "customkill" );
+ if ( customdmg == TF_DMG_CUSTOM_DECAPITATION )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DecapitateCloakedSpy, ACHIEVEMENT_TF_DEMOMAN_DECAPITATE_CLOAKED_SPY, "TF_DEMOMAN_DECAPITATE_CLOAKED_SPY", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillWithDirectPipe : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 50 );
+ SetStoreProgressInSteam( true );
+ }
+
+ // Kill 50 enemies with direct hits from the pipebomb launcher
+ // The server (tf_player) awards this achievement - no code necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillWithDirectPipe, ACHIEVEMENT_TF_DEMOMAN_KILL_X_WITH_DIRECTPIPE, "TF_DEMOMAN_KILL_X_WITH_DIRECTPIPE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_BounceAndKill : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ SetDefLessFunc( m_BouncedPlayers );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "localplayer_respawn" );
+ ListenForGameEvent( "player_hurt" );
+ m_BouncedPlayers.RemoveAll();
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
+ FStrEq( event->GetName(), "localplayer_respawn" ) )
+ {
+ m_BouncedPlayers.RemoveAll();
+ }
+ else if ( FStrEq( event->GetName(), "player_hurt" ) )
+ {
+ int iAttacker = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
+ CBasePlayer *pAttacker = UTIL_PlayerByIndex( iAttacker );
+ if ( pAttacker == C_TFPlayer::GetLocalTFPlayer() )
+ {
+ int iVictim = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ CBasePlayer *pVictim = UTIL_PlayerByIndex( iVictim );
+ if ( pVictim )
+ {
+ bool bVictimGrounded = pVictim->GetFlags() & FL_ONGROUND;
+ if ( bVictimGrounded )
+ {
+ int iIndex = m_BouncedPlayers.Find( pVictim->GetUserID() );
+ if ( iIndex != m_BouncedPlayers.InvalidIndex() )
+ {
+ // they're already in our list
+ m_BouncedPlayers[iIndex] = gpGlobals->curtime;
+ }
+ else
+ {
+ // we need to add them
+ m_BouncedPlayers.Insert( pVictim->GetUserID(), gpGlobals->curtime );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( pVictim == C_BasePlayer::GetLocalPlayer() )
+ {
+ m_BouncedPlayers.RemoveAll();
+ return;
+ }
+
+ if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
+ {
+ C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && !( pTFVictim->GetFlags() & FL_ONGROUND ) )
+ {
+ int iIndex = m_BouncedPlayers.Find( pTFVictim->GetUserID() );
+ if ( iIndex != m_BouncedPlayers.InvalidIndex() )
+ {
+ if ( gpGlobals->curtime < m_BouncedPlayers[iIndex] + 4.0f )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+
+ CUtlMap< int, float > m_BouncedPlayers; // userID and most recent time they were bounced
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_BounceAndKill, ACHIEVEMENT_TF_DEMOMAN_BOUNCE_AND_KILL, "TF_DEMOMAN_BOUNCE_AND_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DecapitatePlayers : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 50 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( pLocalPlayer != pAttacker )
+ return;
+
+ int customdmg = event->GetInt( "customkill" );
+ if ( customdmg == TF_DMG_CUSTOM_DECAPITATION )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DecapitatePlayers, ACHIEVEMENT_TF_DEMOMAN_DECAPITATE_PLAYERS, "TF_DEMOMAN_DECAPITATE_PLAYERS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DecapitatePlayersFast : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "localplayer_respawn" );
+ m_iTimelyDecapitations = 0;
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
+ FStrEq( event->GetName(), "localplayer_respawn" ) )
+ {
+ m_iTimelyDecapitations = 0;
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( pLocalPlayer != pAttacker )
+ return;
+
+ int customdmg = event->GetInt( "customkill" );
+ if ( customdmg == TF_DMG_CUSTOM_DECAPITATION )
+ {
+ if ( (m_iTimelyDecapitations == 0) || ((m_iTimelyDecapitations > 0) && (gpGlobals->curtime < m_flLastDecapTime + 10.f)) )
+ {
+ m_iTimelyDecapitations++;
+ }
+ else
+ {
+ m_iTimelyDecapitations = 1;
+ }
+
+ m_flLastDecapTime = gpGlobals->curtime;
+
+ if ( m_iTimelyDecapitations == 4 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+
+ int m_iTimelyDecapitations;
+ float m_flLastDecapTime;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DecapitatePlayersFast, ACHIEVEMENT_TF_DEMOMAN_DECAPITATE_PLAYERS_FAST, "TF_DEMOMAN_DECAPITATE_PLAYERS_FAST", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFSoldier_DuoDemomanKills : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 10 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "player_death" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "player_death" ) )
+ {
+ int iAttackerIndex = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
+ if ( iAttackerIndex == 0 )
+ return;
+ CTFPlayer *pAttacker = ToTFPlayer( UTIL_PlayerByIndex( iAttackerIndex ) );
+ if ( !pAttacker )
+ return;
+
+ int iAssisterIndex = engine->GetPlayerForUserID( event->GetInt( "assister" ) );
+ if ( iAssisterIndex == 0 )
+ return;
+ CTFPlayer *pAssister = ToTFPlayer( UTIL_PlayerByIndex( iAssisterIndex ) );
+ if ( !pAssister )
+ return;
+
+ if ( pAttacker == C_BasePlayer::GetLocalPlayer() && pAssister->IsPlayerClass( TF_CLASS_DEMOMAN ) )
+ {
+ // We are the attacker and the assist is from a demoman.
+ IncrementCount();
+ return;
+ }
+
+ if ( pAssister == C_BasePlayer::GetLocalPlayer() && pAttacker->IsPlayerClass( TF_CLASS_DEMOMAN ) )
+ {
+ // We are the assister and the kill is from a demoman.
+ IncrementCount();
+ return;
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFSoldier_DuoDemomanKills, ACHIEVEMENT_TF_DEMOMAN_DUO_DEMOMAN_KILLS, "TF_DEMOMAN_DUO_DEMOMAN_KILLS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillTwoDuringStickyJump : public CBaseTFAchievement
+{
+ // While airborne after a sticky-jump, kill at least two enemy players
+
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "sticky_jump" );
+ ListenForGameEvent( "sticky_jump_landed" );
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "localplayer_respawn" );
+ m_iKilledDuringStickyJump = 0;
+ m_bStickyJumping = false;
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
+ FStrEq( event->GetName(), "localplayer_respawn" ) )
+ {
+ m_iKilledDuringStickyJump = 0;
+ m_bStickyJumping = false;
+ }
+ else if ( FStrEq( event->GetName(), "sticky_jump_landed" ) )
+ {
+ int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ if ( iIndex > 0 )
+ {
+ C_TFPlayer *pJumper = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
+
+ if ( pJumper && ( pJumper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ m_iKilledDuringStickyJump = 0;
+ m_bStickyJumping = false;
+ }
+ }
+
+ return;
+ }
+ else if ( FStrEq( event->GetName(), "sticky_jump" ) )
+ {
+ int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ if ( iIndex > 0 )
+ {
+ C_TFPlayer *pJumper = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
+
+ if ( pJumper && ( pJumper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ m_iKilledDuringStickyJump = 0;
+ m_bStickyJumping = true;
+ }
+ }
+
+ return;
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ if ( pAttacker && ( pAttacker == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ if ( m_bStickyJumping )
+ {
+ m_iKilledDuringStickyJump++;
+
+ if ( m_iKilledDuringStickyJump == 2 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+
+private:
+ bool m_bStickyJumping;
+ int m_iKilledDuringStickyJump;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillTwoDuringStickyJump, ACHIEVEMENT_TF_DEMOMAN_KILL_TWO_DURING_STICKYJUMP, "TF_DEMOMAN_KILL_TWO_DURING_STICKYJUMP", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillPlayerAfterTeleport : public CBaseTFAchievement
+{
+ // Kill an enemy player within X seconds of them teleporting in
+
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( event->GetInt( "weaponid" ) == TF_WEAPON_GRENADE_PIPEBOMB )
+ {
+ if ( pTFVictim->m_Shared.InCond( TF_COND_TELEPORTED ) && ( gpGlobals->curtime - pTFVictim->m_Shared.GetTimeTeleEffectAdded() <= 5.0 ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillPlayerAfterTeleport, ACHIEVEMENT_TF_DEMOMAN_KILL_PLAYER_AFTER_TP, "TF_DEMOMAN_KILL_PLAYER_AFTER_TP", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DominateEngineerThreeTimes : public CBaseTFAchievement
+{
+ // Dominate three Engineers
+
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 3 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ bool bDomination = event->GetInt( "death_flags" ) & TF_DEATH_DOMINATION;
+ if ( bDomination == true )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_ENGINEER ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DominateEngineerThreeTimes, ACHIEVEMENT_TF_DEMOMAN_DOMINATE_THREE_ENGINEERS, "TF_DEMOMAN_DOMINATE_THREE_ENGINEERS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillBuildingDirectHit : public CBaseTFAchievement
+{
+ // Kill an Engineer building that you can't see with a direct hit from your Grenade Launcher
+ // Server awards this achievement (tf_obj.cpp) - no other code necessary
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillBuildingDirectHit, ACHIEVEMENT_TF_DEMOMAN_KILL_BUILDING_DIRECT_HIT, "TF_DEMOMAN_KILL_BUILDING_DIRECT_HIT", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_MeleeKillWhileJumping : public CBaseTFAchievement
+{
+ // Get a melee kill while in sticky jump
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "sticky_jump" );
+ ListenForGameEvent( "sticky_jump_landed" );
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "localplayer_respawn" );
+ m_bStickyJumping = false;
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
+ FStrEq( event->GetName(), "localplayer_respawn" ) )
+ {
+ m_bStickyJumping = false;
+ }
+ else if ( FStrEq( event->GetName(), "sticky_jump_landed" ) )
+ {
+ int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ if ( iIndex > 0 )
+ {
+ C_TFPlayer *pJumper = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
+
+ if ( pJumper && ( pJumper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ m_bStickyJumping = false;
+ }
+ }
+
+ return;
+ }
+ else if ( FStrEq( event->GetName(), "sticky_jump" ) )
+ {
+ int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ if ( iIndex > 0 )
+ {
+ C_TFPlayer *pJumper = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
+
+ if ( pJumper && ( pJumper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ m_bStickyJumping = true;
+ }
+ }
+
+ return;
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ if ( pAttacker && ( pAttacker == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ if ( m_bStickyJumping )
+ {
+ if ( event->GetInt( "weaponid" ) == TF_WEAPON_BOTTLE || event->GetInt( "weaponid" ) == TF_WEAPON_SWORD )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+
+private:
+ bool m_bStickyJumping;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_MeleeKillWhileJumping, ACHIEVEMENT_TF_DEMOMAN_MELEE_KILL_WHILE_STICKYJUMPING, "TF_DEMOMAN_MELEE_KILL_WHILE_STICKYJUMPING", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillEngiSentryDispenser : public CBaseTFAchievement
+{
+ // Kill an Engineer, his Sentry and Dispenser, with one sticky detonation
+
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ SetDefLessFunc( m_Engineers );
+ SetDefLessFunc( m_SentryDestroyed );
+ SetDefLessFunc( m_DispenserDestroyed );
+ ResetTracking();
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "localplayer_respawn" );
+ ListenForGameEvent( "object_destroyed" );
+ ResetTracking();
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "teamplay_round_active" ) ||
+ FStrEq( event->GetName(), "localplayer_respawn" ) )
+ {
+ ResetTracking();
+ }
+ else if ( FStrEq( event->GetName(), "object_destroyed" ) )
+ {
+ if ( event->GetInt( "weaponid" ) == TF_WEAPON_GRENADE_PIPEBOMB )
+ {
+ int iAttacker = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
+ CBaseEntity *pAttacker = UTIL_PlayerByIndex( iAttacker );
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+
+ if ( !pLocalPlayer )
+ return;
+
+ if ( pLocalPlayer != pAttacker )
+ return;
+
+ int iEngineer = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ int iObject = event->GetInt( "objecttype" );
+
+ if ( iObject == OBJ_SENTRYGUN )
+ {
+ int iIndex = m_SentryDestroyed.Find( iEngineer );
+ if ( iIndex != m_SentryDestroyed.InvalidIndex() )
+ {
+ // already tracking them, update the time
+ m_SentryDestroyed[iIndex] = gpGlobals->curtime;
+ }
+ else
+ {
+ m_SentryDestroyed.Insert( iEngineer, gpGlobals->curtime );
+ }
+
+ CheckGoalMet();
+ }
+ if ( iObject == OBJ_DISPENSER )
+ {
+ int iIndex = m_DispenserDestroyed.Find( iEngineer );
+ if ( iIndex != m_DispenserDestroyed.InvalidIndex() )
+ {
+ // already tracking them, update the time
+ m_DispenserDestroyed[iIndex] = gpGlobals->curtime;
+ }
+ else
+ {
+ m_DispenserDestroyed.Insert( iEngineer, gpGlobals->curtime );
+ }
+
+ CheckGoalMet();
+ }
+ }
+ }
+ }
+
+ void ResetTracking( void )
+ {
+ m_Engineers.RemoveAll();
+ m_SentryDestroyed.RemoveAll();
+ m_DispenserDestroyed.RemoveAll();
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( event->GetInt( "weaponid" ) == TF_WEAPON_GRENADE_PIPEBOMB )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_ENGINEER ) )
+ {
+ int iEngineer = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ m_Engineers.InsertOrReplace( iEngineer, gpGlobals->curtime );
+
+ CheckGoalMet();
+ }
+ }
+ }
+
+ void CheckGoalMet( void )
+ {
+ FOR_EACH_MAP_FAST ( m_Engineers, numEngineers )
+ {
+ int iEngineer = m_Engineers.Key( numEngineers );
+
+ // Destroyed their Sentry?
+ int iSentry = m_SentryDestroyed.Find( iEngineer );
+ if ( iSentry != m_SentryDestroyed.InvalidIndex() )
+ {
+ // Destroyed their Dispenser?
+ int iDispenser = m_DispenserDestroyed.Find( iEngineer );
+ if ( iDispenser != m_DispenserDestroyed.InvalidIndex() )
+ {
+ // All three at the same time?
+// if ( ( m_Engineers[numEngineers] == m_SentryDestroyed[iSentry] ) &&
+// ( m_Engineers[numEngineers] == m_DispenserDestroyed[iDispenser] ) )
+ if ( ( gpGlobals->curtime < m_SentryDestroyed[iSentry] + 0.1f ) &&
+ ( gpGlobals->curtime < m_DispenserDestroyed[iDispenser] + 0.1f ) &&
+ ( gpGlobals->curtime < m_Engineers[numEngineers] + 0.1f ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+
+private:
+ CUtlMap< int, float > m_SentryDestroyed; // Engineer userID and time sentry was destroyed
+ CUtlMap< int, float > m_DispenserDestroyed; // Engineer userID and time dispenser was destroyed
+ CUtlMap< int, float > m_Engineers; // Engineers we've killed and the time
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillEngiSentryDispenser, ACHIEVEMENT_TF_DEMOMAN_KILL_ENGI_SENTRY_DISPENSER, "TF_DEMOMAN_KILL_ENGI_SENTRY_DISPENSER", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DecapitateEqualizer : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( !pTFVictim )
+ return;
+
+ if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_SOLDIER ) )
+ {
+ CTFShovel *pShovel = dynamic_cast<CTFShovel*>( pTFVictim->GetActiveTFWeapon() );
+ if ( pShovel && (pShovel->GetShovelType() == SHOVEL_DAMAGE_BOOST) )
+ {
+ int customdmg = event->GetInt( "customkill" );
+ if ( customdmg == TF_DMG_CUSTOM_DECAPITATION )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DecapitateEqualizer, ACHIEVEMENT_TF_DEMOMAN_DECAPITATE_EQUALIZER, "TF_DEMOMAN_DECAPITATE_EQUALIZER", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DecapitateNemesis : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( !pTFVictim )
+ return;
+
+ if ( pTFVictim && pTFVictim->IsNemesisOfLocalPlayer() )
+ {
+ int customdmg = event->GetInt( "customkill" );
+ if ( customdmg == TF_DMG_CUSTOM_DECAPITATION )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DecapitateNemesis, ACHIEVEMENT_TF_DEMOMAN_DECAPITATE_NEMESIS, "TF_DEMOMAN_DECAPITATE_NEMESIS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DamageGrind : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1000000 );
+ SetStoreProgressInSteam( true );
+ }
+
+ void OnPlayerStatsUpdate()
+ {
+ ClassStats_t &classStats = CTFStatPanel::GetClassStats( TF_CLASS_DEMOMAN );
+ int iOldCount = m_iCount;
+ m_iCount = classStats.accumulated.m_iStat[TFSTAT_BLASTDAMAGE];
+ if ( m_iCount != iOldCount )
+ {
+ m_pAchievementMgr->SetDirty( true );
+ }
+
+ if ( IsLocalTFPlayerClass( TF_CLASS_DEMOMAN ) )
+ {
+ EvaluateNewAchievement();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DamageGrind, ACHIEVEMENT_TF_DEMOMAN_DAMAGE_GRIND, "TF_DEMOMAN_DAMAGE_GRIND", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillXCapping : public CBaseTFAchievement
+{
+ // Kill "x" players that are capping or pushing the cart with one detonation, "y" times
+ // Server checks for this achievement - no code necessary
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 3 );
+ SetStoreProgressInSteam( true );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillXCapping, ACHIEVEMENT_TF_DEMOMAN_KILL_X_CAPPING_ONEDET, "TF_DEMOMAN_KILL_X_CAPPING_ONEDET", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillXDefending : public CBaseTFAchievement
+{
+ // Kill "x" players that are defending
+ // Server checks for this achievement - no code necessary
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 25 );
+ SetStoreProgressInSteam( true );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillXDefending, ACHIEVEMENT_TF_DEMOMAN_KILL_X_DEFENDING, "TF_DEMOMAN_KILL_X_DEFENDING", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DestroyBuildings : public CBaseTFAchievement
+{
+ // Destroy "x" buildings
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 50 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "object_destroyed" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "object_destroyed" ) )
+ {
+ int iIndex = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
+ CBaseEntity *pDestroyer = UTIL_PlayerByIndex( iIndex );
+ C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pDestroyer == pTFPlayer )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DestroyBuildings, ACHIEVEMENT_TF_DEMOMAN_DESTROY_BUILDINGS_GRIND, "TF_DEMOMAN_DESTROY_BUILDINGS_GRIND", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillXHeaviesAtFull : public CBaseTFAchievement
+{
+ // Kill 3 Heavies from full health with a single Sticky detonation
+ // Server checks for this achievement - no code necessary
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 3 );
+ SetStoreProgressInSteam( true );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillXHeaviesAtFull, ACHIEVEMENT_TF_DEMOMAN_KILL_X_HEAVIES_FULLHP_ONEDET, "TF_DEMOMAN_KILL_X_HEAVIES_FULLHP_ONEDET", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillXScoutsPyros : public CBaseTFAchievement
+{
+ // Kill 25 Scouts or Pyros with the grenade launcher
+
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 25 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ C_TFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim->IsPlayerClass( TF_CLASS_PYRO ) || pTFVictim->IsPlayerClass( TF_CLASS_SCOUT ) )
+ {
+ if ( event->GetInt( "weaponid" ) == TF_WEAPON_GRENADE_DEMOMAN )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillXScoutsPyros, ACHIEVEMENT_TF_DEMOMAN_KILL_X_SCOUTS_PYROS, "TF_DEMOMAN_KILL_X_SCOUTS_PYROS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_TauntKill : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ // was this a taunt kill?
+ if ( event->GetInt( "customkill" ) == TF_DMG_CUSTOM_TAUNTATK_BARBARIAN_SWING )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_TauntKill, ACHIEVEMENT_TF_DEMOMAN_TAUNT_KILL, "TF_DEMOMAN_TAUNT_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_ChargeKill : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ // was this a taunt kill?
+ if ( event->GetInt( "customkill" ) == TF_DMG_CUSTOM_CHARGE_IMPACT )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_ChargeKill, ACHIEVEMENT_TF_DEMOMAN_CHARGE_KILL, "TF_DEMOMAN_CHARGE_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_CritSwordKill : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER );
+ SetGoal( 5 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ // was this a charge kill with the sword?
+ int nDamageBits = event->GetInt( "damagebits" );
+ if ( (nDamageBits & DMG_CRITICAL) && (event->GetInt( "customkill" ) == TF_DMG_CUSTOM_DECAPITATION) )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_CritSwordKill, ACHIEVEMENT_TF_DEMOMAN_CRIT_SWORD_KILL, "TF_DEMOMAN_CRIT_SWORD_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_AirBurstKills : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER );
+ SetGoal( 30 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ // was this an air burst kill?
+ if ( event->GetInt( "customkill" ) == TF_DMG_CUSTOM_AIR_STICKY_BURST )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_AirBurstKills, ACHIEVEMENT_TF_DEMOMAN_AIR_BURST_KILLS, "TF_DEMOMAN_AIR_BURST_KILLS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_StickyJumpCap : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_FILTER_ATTACKER_IS_PLAYER );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents( void )
+ {
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "teamplay_point_startcapture" );
+ ListenForGameEvent( "controlpoint_endtouch" );
+ ListenForGameEvent( "teamplay_point_captured" );
+ ListenForGameEvent( "sticky_jump_landed" );
+ ResetTracking();
+ }
+
+ void CheckGoalMet( void )
+ {
+ // If sticky_jump_landed and startcapture times occurred roughly together...
+ float fTemp1 = 0;
+ float fTemp2 = 0;
+ if ( m_fLandTime > m_fCapStartTime )
+ {
+ fTemp1 = m_fLandTime;
+ fTemp2 = m_fCapStartTime;
+ }
+ else
+ {
+ fTemp1 = m_fCapStartTime;
+ fTemp2 = m_fLandTime;
+ }
+
+ float fDelta = fTemp1 - fTemp2;
+ if ( fDelta <= 0.5f )
+ {
+ // Check if we successfully capped the point we landed on
+ if ( m_bCapped )
+ {
+ IncrementCount();
+ }
+ }
+ }
+
+ void ResetTracking( void )
+ {
+ m_bCapped = false;
+ m_fLandTime = 0;
+ m_fCapStartTime = 0;
+ m_iCapID = -1;
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ // Only check CP maps
+ if ( TFGameRules() && TFGameRules()->GetGameType() != TF_GAMETYPE_CP && TFGameRules()->GetGameType() != TF_GAMETYPE_ARENA )
+ return;
+
+ // Capture the time we land
+ if ( FStrEq( event->GetName(), "sticky_jump_landed" ) )
+ {
+ int iIndex = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ if ( iIndex > 0 )
+ {
+ C_TFPlayer *pJumper = ToTFPlayer( UTIL_PlayerByIndex( iIndex ) );
+
+ if ( pJumper && ( pJumper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ m_fLandTime = gpGlobals->curtime;
+ CheckGoalMet();
+ }
+ }
+
+ return;
+ }
+ // Capture the time we start capping
+ else if ( FStrEq( event->GetName(), "teamplay_point_startcapture" ) )
+ {
+ const char *cappers = event->GetString( "cappers" );
+ for ( int i = 0; i < Q_strlen( cappers ); i++ )
+ {
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( !pLocalPlayer )
+ return;
+
+ int iPlayerIndex = (int) cappers[i];
+ CTFPlayer *pCapper = ToTFPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
+ if ( pCapper && ( pCapper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ m_fCapStartTime = gpGlobals->curtime;
+ m_iCapID = event->GetInt( "cp" );
+ CheckGoalMet();
+ }
+ }
+ }
+ else if ( FStrEq( event->GetName(), "teamplay_point_captured" ) )
+ {
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( !pLocalPlayer )
+ return;
+
+ int iTeam = event->GetInt( "team" );
+ if ( iTeam == pLocalPlayer->GetTeamNumber() )
+ {
+ const char *cappers = event->GetString( "cappers" );
+ for ( int i = 0; i < Q_strlen( cappers ); i++ )
+ {
+ int iPlayerIndex = (int) cappers[i];
+ CTFPlayer *pCapper = ToTFPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
+ if ( pCapper && ( pCapper == C_BasePlayer::GetLocalPlayer() ) )
+ {
+ if ( m_iCapID == event->GetInt( "cp" ) )
+ {
+ m_bCapped = true;
+ CheckGoalMet();
+ }
+ }
+ }
+ }
+ }
+ else if ( FStrEq( event->GetName(), "controlpoint_endtouch" ) )
+ {
+ int iPlayerIndex = event->GetInt( "player", 0 );
+ if ( iPlayerIndex == GetLocalPlayerIndex() )
+ {
+ // We failed to take the point
+ ResetTracking();
+ }
+ }
+ else if ( FStrEq( event->GetName(), "teamplay_round_active" ) )
+ {
+ // Reset tracking at the start of a new round
+ ResetTracking();
+ }
+ }
+
+private:
+ float m_fLandTime;
+ float m_fCapStartTime;
+ bool m_bCapped;
+ int m_iCapID;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_StickyJumpCap, ACHIEVEMENT_TF_DEMOMAN_STICKYJUMP_CAP, "TF_DEMOMAN_STICKYJUMP_CAP", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_FreezeTaunt : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ // Give opponents freezecams of you taunting
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_FreezeTaunt, ACHIEVEMENT_TF_DEMOMAN_FREEZECAM_SMILE, "TF_DEMOMAN_FREEZECAM_SMILE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_FreezeTauntRump : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ // Give opponents freezecams of you taunting
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_FreezeTauntRump, ACHIEVEMENT_TF_DEMOMAN_FREEZECAM_RUMP, "TF_DEMOMAN_FREEZECAM_RUMP", 5 );
+
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_EnvironmentalKill : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_ENEMY_EVENTS );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( !pTFVictim )
+ return;
+
+ CTFPlayer *pLocalPlayer = ToTFPlayer( CBasePlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( pTFVictim->m_Shared.GetWeaponKnockbackID() == pLocalPlayer->GetUserID() )
+ {
+ int custom = event->GetInt( "customkill" );
+ int damagebits = event->GetInt( "damagebits" );
+ if ( ( damagebits & DMG_VEHICLE ) || // They were hit by a freakin' train!
+ ( pAttacker && pAttacker->IsBrushModel() ) || // They were smashed by the world! Gah!
+ ( !pAttacker || (pAttacker == pVictim) ) || // He killed himself!
+ ( custom == TF_DMG_CUSTOM_SUICIDE ) ||
+ ( custom == TF_DMG_CUSTOM_TRIGGER_HURT ) ) // A trigger-hurt got him!
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_EnvironmentalKill, ACHIEVEMENT_TF_DEMOMAN_ENVIRONMENTAL_KILL, "TF_DEMOMAN_ENVIRONMENTAL_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_DestroyStickyBombs : public CBaseTFAchievement
+{
+ // Destroy X stickybombs with the Scottish Defender
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 100 );
+ SetStoreProgressInSteam( true );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_DestroyStickyBombs, ACHIEVEMENT_TF_DEMOMAN_DESTROY_X_STICKYBOMBS, "TF_DEMOMAN_DESTROY_X_STICKYBOMBS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_StickyJumpDistance : public CBaseTFAchievement
+{
+ DECLARE_CLASS( CAchievementTFDemoman_StickyJumpDistance, CBaseTFAchievement );
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_KILL_EVENTS );
+ SetGoal( 1 );
+ ResetTracking();
+ }
+
+ virtual bool IsActive()
+ {
+ return BaseClass::IsActive();
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_active" );
+ ListenForGameEvent( "localplayer_respawn" );
+ ListenForGameEvent( "sticky_jump" );
+ ListenForGameEvent( "sticky_jump_landed" );
+ ResetTracking();
+ }
+
+ void ResetTracking( void )
+ {
+ ClearThink();
+ m_vecStartJump = vec3_origin;
+ }
+
+ void CheckJump( void )
+ {
+ CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( pLocalTFPlayer )
+ {
+ // someone has messed with gravity, so reset our tracking
+ if ( GetCurrentGravity() != 800.0f )
+ {
+ ResetTracking();
+ return;
+ }
+
+ Vector vecCurrent = pLocalTFPlayer->GetAbsOrigin();
+ vecCurrent.z = 0;
+ float flDistSqr = (vecCurrent - m_vecStartJump).Length2DSqr();
+ if ( flDistSqr > (2048 * 2048) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ const char *pszEvent = event->GetName();
+
+ if ( FStrEq( pszEvent, "teamplay_round_active" ) ||
+ FStrEq( pszEvent, "localplayer_respawn" ) )
+ {
+ ResetTracking();
+ }
+ else if ( FStrEq( pszEvent, "sticky_jump" ) )
+ {
+ int iUserID = event->GetInt( "userid" );
+
+ CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( pLocalTFPlayer && pLocalTFPlayer->GetUserID() == iUserID )
+ {
+ m_vecStartJump = pLocalTFPlayer->GetAbsOrigin();
+ m_vecStartJump.z = 0;
+ SetNextThink( 0.1 );
+ }
+ }
+ else if ( FStrEq( pszEvent, "sticky_jump_landed" ) )
+ {
+ int iUserID = event->GetInt( "userid" );
+
+ CTFPlayer *pLocalTFPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( pLocalTFPlayer && pLocalTFPlayer->GetUserID() == iUserID )
+ {
+ CheckJump();
+ ResetTracking();
+ }
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( !pVictim || !pVictim->IsPlayer() )
+ return;
+
+ if ( pVictim == C_BasePlayer::GetLocalPlayer() )
+ {
+ ResetTracking();
+ }
+ }
+
+ virtual void Think( void )
+ {
+ CheckJump();
+ SetNextThink( 0.1 );
+ }
+
+private:
+ Vector m_vecStartJump;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_StickyJumpDistance, ACHIEVEMENT_TF_DEMOMAN_STICKJUMP_DISTANCE, "TF_DEMOMAN_STICKJUMP_DISTANCE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_Kill3WithDetonation : public CBaseTFAchievement
+{
+ // Destroy 3 players with a single pipebomb
+
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_Kill3WithDetonation, ACHIEVEMENT_TF_DEMOMAN_KILL3_WITH_DETONATION, "TF_DEMOMAN_KILL3_WITH_DETONATION", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillXSappingSpies : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS );
+ SetGoal( 20 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "player_sapped_object" );
+ m_hTargets.Purge();
+ }
+
+ int FindSpyInList( int iUserID )
+ {
+ for ( int i = m_hTargets.Count() - 1; i >= 0; i-- )
+ {
+ if ( m_hTargets[i].flTime < gpGlobals->curtime )
+ {
+ // time has run out on this one
+ m_hTargets.Remove( i );
+ continue;
+ }
+
+ if ( m_hTargets[i].nSpyUserID == iUserID )
+ return i;
+ }
+
+ return -1;
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && pTFVictim->IsPlayerClass( TF_CLASS_SPY ) )
+ {
+ int iIndex = FindSpyInList( pTFVictim->GetUserID() );
+ if ( iIndex != -1 )
+ {
+ IncrementCount();
+ m_hTargets.Remove( iIndex );
+ }
+ }
+ }
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ const char *pszEventName = event->GetName();
+
+ if ( FStrEq( pszEventName, "player_sapped_object" ) )
+ {
+ int nUserID = event->GetInt( "userid" );
+ int iIndex = FindSpyInList( nUserID );
+ if ( iIndex == -1 )
+ {
+ iIndex = m_hTargets.AddToTail();
+ m_hTargets[iIndex].nSpyUserID = nUserID;
+ }
+ m_hTargets[iIndex].flTime = gpGlobals->curtime + 5.0;
+ }
+ }
+
+private:
+ struct targets_t
+ {
+ int nSpyUserID;
+ float flTime;
+ };
+
+ CUtlVector<targets_t> m_hTargets;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillXSappingSpies, ACHIEVEMENT_TF_DEMOMAN_KILLXSAPPINGSPIES, "TF_DEMOMAN_KILLXSAPPINGSPIES", 5 );
+
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_Kill3WithPipeSetup : public CBaseTFAchievement
+{
+ // Kill 3 players in separate explosions without placing new sticky bombs
+
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ResetCounts();
+ }
+
+ void ResetCounts()
+ {
+ m_iConsecutiveKillsWithoutRefiring = 0;
+ m_flPrevKillTime = 0;
+ m_iPipebombCount = 0;
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ if ( event->GetInt( "weaponid" ) == TF_WEAPON_GRENADE_PIPEBOMB )
+ {
+ if ( !m_iConsecutiveKillsWithoutRefiring )
+ {
+ // We're starting.
+ m_iConsecutiveKillsWithoutRefiring = 1;
+ m_flPrevKillTime = gpGlobals->curtime;
+ m_iPipebombCount = pLocalPlayer->GetNumActivePipebombs();
+ SetNextThink( 0.1 );
+ }
+ else if ( (gpGlobals->curtime - m_flPrevKillTime) > 0.2 ) // Make sure it wasn't in the same detonation
+ {
+ m_iConsecutiveKillsWithoutRefiring++;
+ m_flPrevKillTime = gpGlobals->curtime;
+ if ( m_iConsecutiveKillsWithoutRefiring >= 3 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+
+ virtual void Think( void )
+ {
+ CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
+ if ( !pLocalPlayer )
+ return;
+
+ int nPipes = pLocalPlayer->GetNumActivePipebombs();
+ if ( m_iPipebombCount < nPipes )
+ {
+ // They laid new pipes. We're done.
+ ResetCounts();
+ }
+ else
+ {
+ m_iPipebombCount = nPipes;
+ SetNextThink( 0.1 );
+ }
+ }
+
+private:
+ int m_iPipebombCount;
+ int m_iConsecutiveKillsWithoutRefiring;
+ float m_flPrevKillTime;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_Kill3WithPipeSetup, ACHIEVEMENT_TF_DEMOMAN_KILL3_WITH_PIPE_SETUPS, "TF_DEMOMAN_KILL3_WITH_PIPE_SETUPS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_AchieveProgress1 : public CAchievement_AchievedCount
+{
+public:
+ DECLARE_CLASS( CAchievementTFDemoman_AchieveProgress1, CAchievement_AchievedCount );
+ void Init()
+ {
+ BaseClass::Init();
+ SetAchievementsRequired( 5, ACHIEVEMENT_TF_DEMOMAN_START_RANGE, ACHIEVEMENT_TF_DEMOMAN_END_RANGE );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_AchieveProgress1, ACHIEVEMENT_TF_DEMOMAN_ACHIEVE_PROGRESS1, "TF_DEMOMAN_ACHIEVE_PROGRESS1", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_AchieveProgress2 : public CAchievement_AchievedCount
+{
+public:
+ DECLARE_CLASS( CAchievementTFDemoman_AchieveProgress2, CAchievement_AchievedCount );
+ void Init()
+ {
+ BaseClass::Init();
+ SetAchievementsRequired( 11, ACHIEVEMENT_TF_DEMOMAN_START_RANGE, ACHIEVEMENT_TF_DEMOMAN_END_RANGE );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_AchieveProgress2, ACHIEVEMENT_TF_DEMOMAN_ACHIEVE_PROGRESS2, "TF_DEMOMAN_ACHIEVE_PROGRESS2", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_AchieveProgress3 : public CAchievement_AchievedCount
+{
+public:
+ DECLARE_CLASS( CAchievementTFDemoman_AchieveProgress3, CAchievement_AchievedCount );
+ void Init()
+ {
+ BaseClass::Init();
+ SetAchievementsRequired( 17, ACHIEVEMENT_TF_DEMOMAN_START_RANGE, ACHIEVEMENT_TF_DEMOMAN_END_RANGE );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_AchieveProgress3, ACHIEVEMENT_TF_DEMOMAN_ACHIEVE_PROGRESS3, "TF_DEMOMAN_ACHIEVE_PROGRESS3", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_ParachuteKillGroup : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ ResetTracking();
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "parachute_deploy" );
+ ListenForGameEvent( "parachute_holster" );
+ }
+
+ void ResetTracking( void )
+ {
+ m_nKills = 0;
+ m_bParachuteDeployed = false;
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ const char *pszEvent = event->GetName();
+
+ if ( FStrEq( pszEvent, "parachute_deploy" ) )
+ {
+ if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
+ {
+ ResetTracking();
+ m_bParachuteDeployed = true;
+ }
+ }
+ else if ( FStrEq( pszEvent, "parachute_holster" ) )
+ {
+ if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
+ {
+ ResetTracking();
+ }
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( pVictim )
+ {
+ // Local player died
+ if ( pVictim == C_BasePlayer::GetLocalPlayer() )
+ {
+ ResetTracking();
+ }
+ else if ( pAttacker == C_BasePlayer::GetLocalPlayer() )
+ {
+ if ( m_bParachuteDeployed )
+ {
+ m_nKills++;
+ if ( m_nKills >= 3 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+
+private:
+ int m_nKills;
+ bool m_bParachuteDeployed;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_ParachuteKillGroup, ACHIEVEMENT_TF_DEMOMAN_PARACHUTE_KILL_GROUP, "TF_DEMOMAN_PARACHUTE_KILL_GROUP", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_ParachuteDistance : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1233619 );
+ SetStoreProgressInSteam( true );
+ ResetTracking();
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "parachute_deploy" );
+ ListenForGameEvent( "parachute_holster" );
+ }
+
+ void ResetTracking( void )
+ {
+ ClearThink();
+ m_flLastZ = 0.0;
+ }
+
+ void CheckHeight( void )
+ {
+ CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer )
+ {
+ float flCurrentZ = pLocalPlayer->GetAbsOrigin().z;
+ float flDela = m_flLastZ - flCurrentZ;
+
+ // make sure we've fallen....we may have been pushed upwards
+ if ( flDela > 0.0f )
+ {
+ IncrementCount( ( int )( flDela ) );
+ }
+
+ m_flLastZ = flCurrentZ;
+ }
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ const char *pszEvent = event->GetName();
+
+ if ( FStrEq( pszEvent, "parachute_deploy" ) )
+ {
+ if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
+ {
+ CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer )
+ {
+ m_flLastZ = pLocalPlayer->GetAbsOrigin().z;
+ SetNextThink( 0.1 );
+ }
+ }
+ }
+ else if ( FStrEq( pszEvent, "parachute_holster" ) )
+ {
+ if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
+ {
+ ResetTracking();
+ }
+ }
+ }
+
+ virtual void Think( void )
+ {
+ CheckHeight();
+ SetNextThink( 0.1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ // Local player died
+ if ( pVictim == C_BasePlayer::GetLocalPlayer() )
+ {
+ ResetTracking();
+ }
+ }
+
+private:
+ float m_flLastZ;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_ParachuteDistance, ACHIEVEMENT_TF_DEMOMAN_PARACHUTE_DISTANCE, "TF_DEMOMAN_PARACHUTE_DISTANCE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_ParachuteKillParachute : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFAttacker && pTFVictim && ( pTFAttacker == C_TFPlayer::GetLocalTFPlayer() ) )
+ {
+ if ( ( pTFAttacker->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) && ( pTFVictim->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_ParachuteKillParachute, ACHIEVEMENT_TF_DEMOMAN_PARACHUTE_KILL_PARACHUTE, "TF_DEMOMAN_PARACHUTE_KILL_PARACHUTE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_KillPlayerYouDidntSee : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_KillPlayerYouDidntSee, ACHIEVEMENT_TF_DEMOMAN_KILL_PLAYER_YOU_DIDNT_SEE, "TF_DEMOMAN_KILL_PLAYER_YOU_DIDNT_SEE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_QuickKills : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "kill_refills_meter" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "kill_refills_meter" ) )
+ {
+ if ( event->GetInt( "index" ) == GetLocalPlayerIndex() )
+ {
+ int iNewIndex = m_Times.AddToTail();
+ m_Times[iNewIndex] = gpGlobals->curtime;
+
+ // we only care about the last three times we killed someone
+ if ( m_Times.Count() > 3 )
+ {
+ m_Times.Remove( 0 );
+ }
+
+ if ( m_Times.Count() == 3 )
+ {
+ if ( m_Times.Tail() - m_Times.Head() <= 6.0 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+
+private:
+ CUtlVector< float > m_Times;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_QuickKills, ACHIEVEMENT_TF_DEMOMAN_QUICK_KILLS, "TF_DEMOMAN_QUICK_KILLS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFDemoman_ChargeKillChargingDemo : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+
+ if ( pTFAttacker && pTFVictim && ( pTFAttacker == C_TFPlayer::GetLocalTFPlayer() ) )
+ {
+ if ( pTFAttacker->m_Shared.InCond( TF_COND_SHIELD_CHARGE ) && pTFVictim->m_Shared.InCond( TF_COND_SHIELD_CHARGE ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFDemoman_ChargeKillChargingDemo, ACHIEVEMENT_TF_DEMOMAN_CHARGE_KILL_CHARGING_DEMO, "TF_DEMOMAN_CHARGE_KILL_CHARGING_DEMO", 5 );
+
+#endif // CLIENT_DLL
+
+
+