summaryrefslogtreecommitdiff
path: root/game/shared/tf/achievements_tf.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.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.cpp')
-rw-r--r--game/shared/tf/achievements_tf.cpp1495
1 files changed, 1495 insertions, 0 deletions
diff --git a/game/shared/tf/achievements_tf.cpp b/game/shared/tf/achievements_tf.cpp
new file mode 100644
index 0000000..b481805
--- /dev/null
+++ b/game/shared/tf/achievements_tf.cpp
@@ -0,0 +1,1495 @@
+//========= 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 "econ_wearable.h"
+#include "achievements_tf.h"
+
+// NVNT include for tf2 damage
+#include "haptics/haptic_utils.h"
+
+CAchievementMgr g_AchievementMgrTF; // global achievement mgr for TF
+
+bool CheckWinNoEnemyCaps( IGameEvent *event, int iRole );
+
+// Grace period that we allow a player to start after level init and still consider them to be participating for the full round. This is fairly generous
+// because it can in some cases take a client several minutes to connect with respect to when the server considers the game underway
+#define TF_FULL_ROUND_GRACE_PERIOD ( 4 * 60.0f )
+
+bool IsLocalTFPlayerClass( int iClass );
+
+
+bool CBaseTFAchievementSimple::LocalPlayerCanEarn( void )
+{
+ if ( TFGameRules() )
+ {
+ bool bMVMAchievement = ( m_iAchievementID >= ACHIEVEMENT_TF_MVM_START_RANGE && m_iAchievementID <= ACHIEVEMENT_TF_MVM_END_RANGE );
+
+ if ( bMVMAchievement )
+ {
+ if ( !TFGameRules()->IsMannVsMachineMode() || ( GetLocalPlayerTeam() != TF_TEAM_PVE_DEFENDERS ) )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if ( TFGameRules()->IsMannVsMachineMode() )
+ {
+ return false;
+ }
+ }
+ }
+
+ return BaseClass::LocalPlayerCanEarn();
+}
+
+void CBaseTFAchievementSimple::FireGameEvent( IGameEvent *event )
+{
+ if ( !LocalPlayerCanEarn() )
+ return;
+
+ BaseClass::FireGameEvent( event );
+}
+
+
+bool CBaseTFAchievement::LocalPlayerCanEarn( void )
+{
+ // Swallow game events if we're not allowed to earn achievements, or if the local player isn't the right class
+ if ( !GameRulesAllowsAchievements() )
+ {
+ return false;
+ }
+
+ // Determine class & check it
+ if ( m_iAchievementID >= ACHIEVEMENT_START_CLASS_SPECIFIC && m_iAchievementID <= ACHIEVEMENT_END_CLASS_SPECIFIC )
+ {
+ int iClass = floor( (m_iAchievementID - ACHIEVEMENT_START_CLASS_SPECIFIC) / 100.0f ) + 1;
+ if ( !IsLocalTFPlayerClass( iClass ) )
+ {
+ return false;
+ }
+ }
+
+ return BaseClass::LocalPlayerCanEarn();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAchievementFullRound::Init()
+{
+ m_iFlags |= ACH_FILTER_FULL_ROUND_ONLY;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAchievementFullRound::ListenForEvents()
+{
+ ListenForGameEvent( "teamplay_round_win" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAchievementFullRound::FireGameEvent_Internal( IGameEvent *event )
+{
+ if ( 0 == Q_strcmp( event->GetName(), "teamplay_round_win" ) )
+ {
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer )
+ {
+ // is the player currently on a game team?
+ int iTeam = pLocalPlayer->GetTeamNumber();
+ if ( iTeam >= FIRST_GAME_TEAM )
+ {
+ float flRoundTime = event->GetFloat( "round_time", 0 );
+ if ( flRoundTime > 0 )
+ {
+ Event_OnRoundComplete( flRoundTime, event );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFAchievementFullRound::PlayerWasInEntireRound( float flRoundTime )
+{
+ float flTeamplayStartTime = m_pAchievementMgr->GetTeamplayStartTime();
+ if ( flTeamplayStartTime > 0 )
+ {
+ // has the player been present and on a game team since the start of this round (minus a grace period)?
+ if ( flTeamplayStartTime < ( gpGlobals->curtime - flRoundTime ) + TF_FULL_ROUND_GRACE_PERIOD )
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class CAchievementTFPlayGameEveryClass : public CTFAchievementFullRound
+{
+ DECLARE_CLASS( CAchievementTFPlayGameEveryClass, CTFAchievementFullRound );
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_HAS_COMPONENTS | ACH_FILTER_FULL_ROUND_ONLY );
+ SetGoal( ( TF_LAST_NORMAL_CLASS - 1 ) - TF_FIRST_NORMAL_CLASS + 1 ); //( TF_LAST_NORMAL_CLASS - 1 ) to exclude the new civilian class
+ BaseClass::Init();
+ }
+
+ virtual void Event_OnRoundComplete( float flRoundTime, IGameEvent *event )
+ {
+ float flLastClassChangeTime = m_pAchievementMgr->GetLastClassChangeTime();
+ if ( flLastClassChangeTime > 0 )
+ {
+ // has the player been present and not changed class since the start of this round (minus a grace period)?
+ if ( flLastClassChangeTime < ( gpGlobals->curtime - flRoundTime ) + TF_FULL_ROUND_GRACE_PERIOD )
+ {
+ C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pTFPlayer )
+ {
+ int iClass = pTFPlayer->GetPlayerClass()->GetClassIndex();
+ if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass <= ( TF_LAST_NORMAL_CLASS - 1 ) ) //( TF_LAST_NORMAL_CLASS - 1 ) to exclude the new civilian class
+ {
+ // yes, the achievement is satisfied for this class, set the corresponding bit
+ int iBitNumber =( iClass - TF_FIRST_NORMAL_CLASS );
+ EnsureComponentBitSetAndEvaluate( iBitNumber );
+ }
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFPlayGameEveryClass, ACHIEVEMENT_TF_PLAY_GAME_EVERYCLASS, "TF_PLAY_GAME_EVERYCLASS", 5 );
+
+class CAchievementTFPlayGameEveryMap : public CTFAchievementFullRound
+{
+ DECLARE_CLASS( CAchievementTFPlayGameEveryMap, CTFAchievementFullRound );
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_HAS_COMPONENTS | ACH_FILTER_FULL_ROUND_ONLY );
+
+ static const char *szComponents[] =
+ {
+ "cp_dustbowl", "cp_granary", "cp_gravelpit", "cp_well", "ctf_2fort", "tc_hydro"
+ };
+ m_pszComponentNames = szComponents;
+ m_iNumComponents = ARRAYSIZE( szComponents );
+ SetGoal( m_iNumComponents );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ virtual void Event_OnRoundComplete( float flRoundTime, IGameEvent *event )
+ {
+ float flTeamplayStartTime = m_pAchievementMgr->GetTeamplayStartTime();
+ if ( flTeamplayStartTime > 0 )
+ {
+ // has the player been present and on a game team since the start of this round (minus a grace period)?
+ if ( flTeamplayStartTime < ( gpGlobals->curtime - flRoundTime ) + TF_FULL_ROUND_GRACE_PERIOD )
+ {
+ // yes, the achievement is satisfied for this map, set the corresponding bit
+ OnComponentEvent( m_pAchievementMgr->GetMapName() );
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFPlayGameEveryMap, ACHIEVEMENT_TF_PLAY_GAME_EVERYMAP, "TF_PLAY_GAME_EVERYMAP", 5 );
+
+class CAchievementTFGetHealPoints : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 25000 );
+ }
+
+ void OnPlayerStatsUpdate()
+ {
+ ClassStats_t &classStats = CTFStatPanel::GetClassStats( TF_CLASS_MEDIC );
+ int iOldCount = m_iCount;
+ m_iCount = classStats.accumulated.m_iStat[TFSTAT_HEALING];
+ if ( m_iCount != iOldCount )
+ {
+ m_pAchievementMgr->SetDirty( true );
+ }
+
+ if ( IsLocalTFPlayerClass( TF_CLASS_MEDIC ) )
+ {
+ EvaluateNewAchievement();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFGetHealPoints, ACHIEVEMENT_TF_GET_HEALPOINTS, "TF_GET_HEALPOINTS", 5 );
+
+class CAchievementTFBurnPlayersInMinimumTime : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFBurnPlayersInMinimumTime, ACHIEVEMENT_TF_BURN_PLAYERSINMINIMIMTIME, "TF_BURN_PLAYERSINMINIMUMTIME", 5 );
+
+class CAchievementTFGetTurretKills : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFGetTurretKills, ACHIEVEMENT_TF_GET_TURRETKILLS, "TF_GET_TURRETKILLS", 5 );
+
+class CAchievementTFGetHeadshots: public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 25 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ // was this a headshot by this player?
+ if ( ( pAttacker == C_TFPlayer::GetLocalTFPlayer() ) && ( IsHeadshot(event->GetInt( "customkill" ) ) ) )
+ {
+ // Increment count. Count will also get slammed whenever we get a stats update from server. They should generally agree,
+ // but server is authoritative.
+ IncrementCount();
+ }
+ }
+
+ void OnPlayerStatsUpdate()
+ {
+ // when stats are updated by server, use most recent stat value
+ ClassStats_t &classStats = CTFStatPanel::GetClassStats( TF_CLASS_SNIPER );
+ int iOldCount = m_iCount;
+ m_iCount = classStats.accumulated.m_iStat[TFSTAT_HEADSHOTS];
+ if ( m_iCount != iOldCount )
+ {
+ m_pAchievementMgr->SetDirty( true );
+ }
+
+ if ( IsLocalTFPlayerClass( TF_CLASS_SNIPER ) )
+ {
+ EvaluateNewAchievement();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFGetHeadshots, ACHIEVEMENT_TF_GET_HEADSHOTS, "TF_GET_HEADSHOTS", 5 );
+
+class CAchievementTFKillNemesis : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 5 );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ if ( ( ( event->GetInt( "death_flags" ) & TF_DEATH_REVENGE ) ) && ( pAttacker == C_TFPlayer::GetLocalTFPlayer() ) )
+ {
+ // local player got revenge as primary killer
+ IncrementCount();
+ }
+ else if ( event->GetInt( "death_flags" ) & TF_DEATH_ASSISTER_REVENGE )
+ {
+ int iAssisterIndex = engine->GetPlayerForUserID( event->GetInt( "assister" ) );
+ if ( iAssisterIndex > 0 )
+ {
+ CBaseEntity *pAssister = UTIL_PlayerByIndex( iAssisterIndex );
+ if ( pAssister && ( pAssister == C_TFPlayer::GetLocalTFPlayer() ) )
+ {
+ // local player got revenge as assister
+ IncrementCount();
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFKillNemesis, ACHIEVEMENT_TF_KILL_NEMESIS, "TF_KILL_NEMESIS", 5 );
+
+class CAchievementTFGetConsecutiveKillsNoDeaths : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ m_iConsecutiveKills = 0;
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer == pVictim )
+ {
+ m_iConsecutiveKills = 0;
+ }
+ else if ( pLocalPlayer == pAttacker )
+ {
+ m_iConsecutiveKills++;
+ if ( 5 == m_iConsecutiveKills )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ int m_iConsecutiveKills;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFGetConsecutiveKillsNoDeaths, ACHIEVEMENT_TF_GET_CONSECUTIVEKILLS_NODEATHS, "TF_GET_CONSECUTIVEKILLS_NODEATHS", 10 );
+
+class CAchievementTFGetHealedByEnemy: public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFGetHealedByEnemy, ACHIEVEMENT_TF_GET_HEALED_BYENEMY, "TF_GET_HEALED_BYENEMY", 15 );
+
+class CAchievementTFPlayGameFriendsOnly : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_FILTER_FULL_ROUND_ONLY );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( 0 == Q_strcmp( event->GetName(), "teamplay_round_win" ) )
+ {
+ // Are there at least 7 friends in the game? (at least 8 players total)
+ if ( CalcPlayersOnFriendsList( 7 ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFPlayGameFriendsOnly, ACHIEVEMENT_TF_PLAY_GAME_FRIENDSONLY, "TF_PLAY_GAME_FRIENDSONLY", 10 );
+
+class CAchievementTFWinMultipleGames : public CTFAchievementFullRound
+{
+ DECLARE_CLASS( CAchievementTFWinMultipleGames, CTFAchievementFullRound );
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_FILTER_FULL_ROUND_ONLY );
+ SetGoal( 20 );
+ BaseClass::Init();
+ }
+
+ virtual void Event_OnRoundComplete( float flRoundTime, IGameEvent *event )
+ {
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pLocalPlayer )
+ {
+ // was the player on the winning team?
+ int iPlayerTeam = pLocalPlayer->GetTeamNumber();
+ int iWinningTeam = event->GetInt( "team" );
+ if ( ( iWinningTeam >= FIRST_GAME_TEAM ) && ( iPlayerTeam == iWinningTeam ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFWinMultipleGames, ACHIEVEMENT_TF_WIN_MULTIPLEGAMES, "TF_WIN_MULTIPLEGAMES", 10 );
+
+class CAchievementTFGetMultipleKills : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ // listen for player kill enemy events, base class will increment count each time that happens
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1000 );
+ }
+
+ void OnPlayerStatsUpdate()
+ {
+ // when stats are updated by server, use most recent stat values
+
+ int iKills = 0;
+ // get sum of kills per class across all classes to get total kills
+ for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass <= ( TF_LAST_NORMAL_CLASS - 1 ); iClass++ ) //( TF_LAST_NORMAL_CLASS - 1 ) to exclude the new civilian class
+ {
+ ClassStats_t &classStats = CTFStatPanel::GetClassStats( iClass );
+ iKills += classStats.accumulated.m_iStat[TFSTAT_KILLS];
+ }
+
+ int iOldCount = m_iCount;
+ m_iCount = iKills;
+ if ( m_iCount != iOldCount )
+ {
+ m_pAchievementMgr->SetDirty( true );
+ }
+
+ EvaluateNewAchievement();
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFGetMultipleKills, ACHIEVEMENT_TF_GET_MULTIPLEKILLS, "TF_GET_MULTIPLEKILLS", 15 );
+
+class CAchievementTFWin2FortNoEnemyCaps : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ SetMapNameFilter( "ctf_2fort" );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( 0 == Q_strcmp( event->GetName(), "teamplay_round_win" ) )
+ {
+ if ( event->GetBool( "was_sudden_death" ) == false )
+ {
+ if ( event->GetInt( "team" ) == GetLocalPlayerTeam() )
+ {
+ // did the enemy team get any flag captures?
+ C_TFTeam *pEnemyTeam = GetGlobalTFTeam( TF_TEAM_BLUE + TF_TEAM_RED - GetLocalPlayerTeam() );
+ if ( 0 == pEnemyTeam->GetFlagCaptures() )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFWin2FortNoEnemyCaps, ACHIEVEMENT_TF_WIN_2FORT_NOENEMYCAPS, "TF_WIN_2FORT_NOENEMYCAPS", 5 );
+
+class CAchievementTFWinWellMinimumTime : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ SetMapNameFilter( "cp_well" );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( 0 == Q_strcmp( event->GetName(), "teamplay_round_win" ) )
+ {
+ if ( event->GetInt( "team" ) == GetLocalPlayerTeam() )
+ {
+ float flRoundTime = event->GetFloat( "round_time", 0 );
+ if ( flRoundTime > 0 && flRoundTime < 5 * 60 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFWinWellMinimumTime, ACHIEVEMENT_TF_WIN_WELL_MINIMUMTIME, "TF_WIN_WELL_MINIMUMTIME", 10 );
+
+class CAchievementTFWinHydroNoEnemyCaps : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_FILTER_FULL_ROUND_ONLY );
+ SetGoal( 1 );
+ SetMapNameFilter( "tc_hydro" );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ // winning hydro with no enemy caps means there were 2 previous minirounds completed (3 total for a shutout)
+ // and local player's team won the final round
+ if ( ( 2 == m_pAchievementMgr->GetMiniroundsCompleted() ) && ( CheckWinNoEnemyCaps( event, TEAM_ROLE_NONE ) ) )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFWinHydroNoEnemyCaps, ACHIEVEMENT_TF_WIN_HYDRO_NOENEMYCAPS, "TF_WIN_HYDRO_NOENEMYCAPS", 20 );
+
+class CAchievementTFWinDustbowlNoEnemyCaps : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_FILTER_FULL_ROUND_ONLY );
+ SetGoal( 1 );
+ SetMapNameFilter( "cp_dustbowl" );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ // defending dustbowl with no enemy caps means there were no previous minirounds completed (that would be an attacker capture),
+ // the player was on the defending team and they won with no enemy caps
+ if ( ( 0 == m_pAchievementMgr->GetMiniroundsCompleted() ) && CheckWinNoEnemyCaps( event, TEAM_ROLE_DEFENDERS ) )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFWinDustbowlNoEnemyCaps, ACHIEVEMENT_TF_WIN_DUSTBOWL_NOENEMYCAPS, "TF_WIN_DUSTBOWL_NOENEMYCAPS", 10 );
+
+class CAchievementTFWinGravelPitNoEnemyCaps : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ SetMapNameFilter( "cp_gravelpit" );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ // Was player on defenders and won with no enemy caps?
+ if ( CheckWinNoEnemyCaps( event, TEAM_ROLE_DEFENDERS ) )
+ {
+ IncrementCount();
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFWinGravelPitNoEnemyCaps, ACHIEVEMENT_TF_WIN_GRAVELPIT_NOENEMYCAPS, "TF_WIN_GRAVELPIT_NOENEMYCAPS", 30 );
+
+class CAchievementTFKillEnemiesAfterTeleporting : public CTFAchievementTeleporterTimingKills<CBaseAchievement>
+{
+ // stub -- all code in parent class
+};
+DECLARE_ACHIEVEMENT( CAchievementTFKillEnemiesAfterTeleporting, ACHIEVEMENT_TF_GENERAL_KILL_ENEMIES_AFTER_TELEPORTING, "TF_GENERAL_KILL_ENEMIES_AFTER_TELEPORTING", 10 );
+
+//-----------------------------------------------------------------------------
+// Purpose: see if a round win was a win for the local player with no enemy caps
+//-----------------------------------------------------------------------------
+bool CheckWinNoEnemyCaps( IGameEvent *event, int iRole )
+{
+ if ( 0 == Q_strcmp( event->GetName(), "teamplay_round_win" ) )
+ {
+ if ( event->GetInt( "team" ) == GetLocalPlayerTeam() )
+ {
+ int iLosingTeamCaps = event->GetInt( "losing_team_num_caps" );
+ if ( 0 == iLosingTeamCaps )
+ {
+ C_TFTeam *pLocalTeam = GetGlobalTFTeam( GetLocalPlayerTeam() );
+ if ( pLocalTeam )
+ {
+ int iRolePlayer = pLocalTeam->GetRole();
+ if ( iRole > TEAM_ROLE_NONE && ( iRolePlayer != iRole ) )
+ return false;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper function to determine if local player is specified class
+//-----------------------------------------------------------------------------
+bool IsLocalTFPlayerClass( int iClass )
+{
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+ return( pLocalPlayer && pLocalPlayer->IsPlayerClass( iClass ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Query if the gamerules allows achievement progress at this time
+//-----------------------------------------------------------------------------
+bool GameRulesAllowsAchievements( void )
+{
+ bool bRetVal = false;
+
+ if ( ( TFGameRules()->State_Get() < GR_STATE_TEAM_WIN ) ||
+ ( TFGameRules()->State_Get() == GR_STATE_STALEMATE ) )
+ {
+ bRetVal = true;
+ }
+
+ return bRetVal;
+}
+
+//----------------------------------------------------------------------------------------------------------------
+// Receive the PlayerIgnitedInv user message and send out a clientside event for achievements to hook.
+void __MsgFunc_PlayerIgnitedInv( bf_read &msg )
+{
+ int iPyroEntIndex = (int) msg.ReadByte();
+ int iVictimEntIndex = (int) msg.ReadByte();
+ int iMedicEntIndex = (int) msg.ReadByte();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_ignited_inv" );
+ if ( event )
+ {
+ event->SetInt( "pyro_entindex", iPyroEntIndex );
+ event->SetInt( "victim_entindex", iVictimEntIndex );
+ event->SetInt( "medic_entindex", iMedicEntIndex );
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+
+// Receive the PlayerIgnited user message and send out a clientside event for achievements to hook.
+void __MsgFunc_PlayerIgnited( bf_read &msg )
+{
+ int iPyroEntIndex = (int) msg.ReadByte();
+ int iVictimEntIndex = (int) msg.ReadByte();
+ int iWeaponID = (int) msg.ReadByte();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_ignited" );
+ if ( event )
+ {
+ event->SetInt( "pyro_entindex", iPyroEntIndex );
+ event->SetInt( "victim_entindex", iVictimEntIndex );
+ event->SetInt( "weaponid", iWeaponID );
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+
+// Receive the Damage user message and send out a clientside event for achievements to hook.
+void __MsgFunc_Damage( bf_read &msg )
+{
+ int iDamage = msg.ReadShort();
+ int iDmgBits = msg.ReadLong();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_damaged" );
+ if ( event )
+ {
+ event->SetInt( "amount", iDamage );
+ event->SetInt( "type", iDmgBits );
+ gameeventmanager->FireEventClientSide( event );
+ }
+ // NVNT START implementing rest of message for damage directions
+ if(iDamage == 0)
+ return; // no damage forces for no damage.
+
+ // get the local player.
+ C_TFPlayer *pLocal = C_TFPlayer::GetLocalTFPlayer();
+ if(!pLocal)
+ return;// if we dont have a local player ignore this message.
+
+ Vector attackerPosition(0,0,0);
+ if(msg.ReadOneBit())
+ {
+ // if we read one bit then that means we have shooters origin.
+ msg.ReadBitVec3Coord( attackerPosition );
+ }else{
+ // if it is non origin, just set the origin below the player
+ attackerPosition = pLocal->GetAbsOrigin() + Vector(0,0,-10);
+ }
+ // get the direction in world
+ Vector attackDirectionLocal(vec3_origin);
+ // rotate the direction to the local players view
+ pLocal->WorldToEntitySpace(attackerPosition, &attackDirectionLocal);
+
+ if ( haptics )
+ {
+ Vector hapticSpace( attackDirectionLocal.y, -attackDirectionLocal.z, attackDirectionLocal.x );
+
+ hapticSpace.NormalizeInPlace();
+
+ haptics->ApplyDamageEffect((float)iDamage, iDmgBits, hapticSpace);
+ }
+ // NVNT END
+}
+
+// Receive the UpdateAchievement user message and send out a clientside event for achievements to hook.
+void __MsgFunc_UpdateAchievement( bf_read &msg )
+{
+ int iIndex = (int) msg.ReadShort();
+ int nData = (int) msg.ReadShort();
+
+ g_AchievementMgrTF.UpdateAchievement( iIndex, nData );
+}
+
+// Receive the PlayerJarated user message and send out a clientside event for achievements to hook.
+void __MsgFunc_PlayerJarated( bf_read &msg )
+{
+ int iThrowerEntIndex = (int) msg.ReadByte();
+ int iVictimEntIndex = (int) msg.ReadByte();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_jarated" );
+ if ( event )
+ {
+ event->SetInt( "thrower_entindex", iThrowerEntIndex );
+ event->SetInt( "victim_entindex", iVictimEntIndex );
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+
+void __MsgFunc_PlayerJaratedFade( bf_read &msg )
+{
+ int iThrowerEntIndex = (int) msg.ReadByte();
+ int iVictimEntIndex = (int) msg.ReadByte();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_jarated_fade" );
+ if ( event )
+ {
+ event->SetInt( "thrower_entindex", iThrowerEntIndex );
+ event->SetInt( "victim_entindex", iVictimEntIndex );
+
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+//This is so dumb.
+void __MsgFunc_PlayerShieldBlocked( bf_read &msg )
+{
+ int iAttacker = (int) msg.ReadByte();
+ int iBlocker = (int) msg.ReadByte();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_shield_blocked" );
+ if ( event )
+ {
+ event->SetInt( "attacker_entindex", iAttacker );
+ event->SetInt( "blocker_entindex", iBlocker );
+
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+
+// Receive the PlayerExtinguished user message and send out a clientside event for achievements to hook.
+void __MsgFunc_PlayerExtinguished( bf_read &msg )
+{
+ int iMedicEntIndex = (int) msg.ReadByte();
+ int iVictimEntIndex = (int) msg.ReadByte();
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_extinguished" );
+ if ( event )
+ {
+ event->SetInt( "victim", iVictimEntIndex );
+ event->SetInt( "healer", iMedicEntIndex );
+
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+
+void CAchievementTopScoreboard::Init()
+{
+ SetFlags( ACH_SAVE_GLOBAL | ACH_FILTER_FULL_ROUND_ONLY );
+ SetGoal(1);
+}
+
+void CAchievementTopScoreboard::ListenForEvents()
+{
+ BaseClass::ListenForEvents();
+ ListenForGameEvent( "teamplay_round_active" );
+}
+
+void CAchievementTopScoreboard::Event_OnRoundComplete( float flRoundTime, IGameEvent *event )
+{
+ if ( PlayerWasInEntireRound( flRoundTime ) )
+ {
+ int iLocalTeam = C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber();
+
+ if ( GetGlobalTFTeam(iLocalTeam) && GetGlobalTFTeam(iLocalTeam)->GetNumPlayers() >= 6 )
+ {
+ if ( g_TF_PR )
+ {
+ bool bHighest = true;
+ int iLocalScore = g_TF_PR->GetTotalScore( C_TFPlayer::GetLocalTFPlayer()->entindex() );
+
+ // See if the player's on the top of the scoreboard
+ for( int playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++ )
+ {
+ if ( !g_PR->IsConnected( playerIndex ) || g_PR->IsLocalPlayer( playerIndex ) )
+ continue;
+
+ if ( g_PR->GetTeam(playerIndex) != iLocalTeam )
+ continue;
+
+ if ( g_TF_PR->GetTotalScore(playerIndex) > iLocalScore )
+ {
+ bHighest = false;
+ break;
+ }
+ }
+
+ if ( bHighest )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+extern int Training_GetNumCourses();
+extern int Training_GetProgressCount();
+class CAchievementTFCompleteTraining : public CBaseTFAchievementSimple
+{
+ DECLARE_CLASS( CAchievementTFCompleteTraining, CBaseAchievement );
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL | ACH_HAS_COMPONENTS );
+ SetGoal( Training_GetNumCourses() );
+ SetStoreProgressInSteam( true );
+ SetCount( Training_GetProgressCount() );
+ BaseClass::Init();
+ }
+
+ virtual void UpdateAchievement( int nData )
+ {
+ SetCount( nData );
+ EvaluateNewAchievement();
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFCompleteTraining, ACHIEVEMENT_TF_COMPLETE_TRAINING, "TF_COMPLETE_TRAINING", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_FireWaterJump : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_FireWaterJump, ACHIEVEMENT_TF_FIRE_WATERJUMP, "TF_FIRE_WATERJUMP", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFChristmasCollectGifts : public CBaseTFAchievementSimple
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 3 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "christmas_gift_grab" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( !TFGameRules()->IsHolidayActive( kHoliday_Christmas ) )
+ return;
+
+ if ( Q_strcmp( event->GetName(), "christmas_gift_grab" ) == 0 )
+ {
+ int iPlayer = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
+ CBaseEntity *pPlayer = UTIL_PlayerByIndex( iPlayer );
+
+ if ( pPlayer && pPlayer == C_TFPlayer::GetLocalTFPlayer() )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTFChristmasCollectGifts, ACHIEVEMENT_TF_CHRISTMAS_COLLECT_GIFTS, "TF_CHRISTMAS_COLLECT_GIFTS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_KillBalloonicornOwners : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 79 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CSchemaItemDefHandle pItemDef_Balloonicorn( "Pet Balloonicorn" );
+ CSchemaItemDefHandle pItemDef_BalloonicornPromo( "Pet Balloonicorn Promo" );
+ CSchemaItemDefHandle pItemDef_BalloonicornPlushPromo( "Pet Balloonicorn Plush Promo" );
+ CSchemaItemDefHandle pItemDef_Reindoonicorn( "Pet Reindoonicorn" );
+
+ C_TFPlayer *pLocalPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
+ if ( pLocalPlayer )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+
+ if ( pTFVictim && ( pAttacker == pLocalPlayer ) && ( pTFVictim->GetTeamNumber() != pLocalPlayer->GetTeamNumber() ) )
+ {
+ int nVisionOptInFlags = 0;
+ CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, nVisionOptInFlags, vision_opt_in_flags );
+
+ // Does the local player have PyroVision on?
+ if ( nVisionOptInFlags & TF_VISION_FILTER_PYRO )
+ {
+ // Is the victim wearing the Balloonicorn?
+ for ( int i = 0 ; i < pTFVictim->GetNumWearables() ; ++i )
+ {
+ C_EconWearable *pWearable = pTFVictim->GetWearable( i );
+ if ( pWearable && pWearable->GetAttributeContainer() )
+ {
+ CEconItemView *pItem = pWearable->GetAttributeContainer()->GetItem();
+ if ( pItem && pItem->IsValid() )
+ {
+ if ( pItem->GetItemDefinition() == pItemDef_Balloonicorn ||
+ pItem->GetItemDefinition() == pItemDef_BalloonicornPromo ||
+ pItem->GetItemDefinition() == pItemDef_BalloonicornPlushPromo ||
+ pItem->GetItemDefinition() == pItemDef_Reindoonicorn )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_KillBalloonicornOwners, ACHIEVEMENT_TF_KILL_BALLOONICORN_OWNERS, "TF_KILL_BALLOONICORN_OWNERS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_MultipleBFF : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_KILL_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents( void )
+ {
+ ListenForGameEvent( "remove_nemesis_relationships" );
+
+ // clear data on level init
+ m_hBFFs.Purge();
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "remove_nemesis_relationships" ) )
+ {
+ int iPlayerIndex = event->GetInt( "player" );
+ if ( iPlayerIndex == GetLocalPlayerIndex() )
+ {
+ // this is the local player, clear our list
+ m_hBFFs.Purge();
+ }
+ else
+ {
+ // is this player in our list?
+ CTFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
+
+ int index = m_hBFFs.Find( pPlayer );
+ if ( index != m_hBFFs.InvalidIndex() )
+ {
+ m_hBFFs.Remove( index );
+ }
+ }
+ }
+ }
+
+ void ValidateList( void )
+ {
+ // remove anyone on the local player's team to clean up changing teams, getting
+ // team balanced, etc., if they're still on the other team, we're fine.
+ for ( int i = m_hBFFs.Count() - 1 ; i >= 0 ; i-- )
+ {
+ C_TFPlayer *pPlayer = m_hBFFs[i];
+ if ( pPlayer->GetTeamNumber() == GetLocalPlayerTeam() )
+ {
+ m_hBFFs.Remove( i );
+ }
+ }
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ C_TFPlayer *pLocalPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
+ if ( pLocalPlayer )
+ {
+ CTFPlayer *pTFAttacker = ToTFPlayer( pAttacker );
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ int iDeathFlags = event->GetInt( "death_flags" );
+ bool bDomination = ( iDeathFlags & TF_DEATH_DOMINATION ) || ( iDeathFlags & TF_DEATH_ASSISTER_DOMINATION );
+ bool bRevenge = ( iDeathFlags & TF_DEATH_REVENGE ) || ( iDeathFlags & TF_DEATH_ASSISTER_REVENGE );
+
+ if ( pTFVictim && ( pTFAttacker == pLocalPlayer ) && bDomination )
+ {
+ ValidateList();
+
+ int nVisionOptInFlags = 0;
+ CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, nVisionOptInFlags, vision_opt_in_flags );
+
+ if ( nVisionOptInFlags & TF_VISION_FILTER_PYRO )
+ {
+ int index = m_hBFFs.Find( pTFVictim );
+ if ( index == m_hBFFs.InvalidIndex() )
+ {
+ m_hBFFs.AddToHead( pTFVictim );
+ }
+
+ if ( m_hBFFs.Count() >= 2 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ else if ( pTFAttacker && ( pTFVictim == pLocalPlayer ) && bRevenge )
+ {
+ ValidateList();
+
+ int index = m_hBFFs.Find( pTFAttacker );
+ if ( index != m_hBFFs.InvalidIndex() )
+ {
+ m_hBFFs.Remove( index );
+ }
+ }
+ }
+ }
+
+private:
+ CUtlVector< CHandle<C_TFPlayer> > m_hBFFs;
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_MultipleBFF, ACHIEVEMENT_TF_MULTIPLE_BFF, "TF_MULTIPLE_BFF", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_TeamPyrovision : public CBaseTFAchievement
+{
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+
+ SetNextThink( 1.0 );
+ }
+
+ virtual void Think( void )
+ {
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer && ( pLocalPlayer->GetTeamNumber() >= FIRST_GAME_TEAM ) )
+ {
+ int nVisionOptInFlags = 0;
+ CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, nVisionOptInFlags, vision_opt_in_flags );
+
+ if ( nVisionOptInFlags & TF_VISION_FILTER_PYRO )
+ {
+ int nCount = 0;
+
+ for ( int i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ C_BasePlayer *pPlayer = UTIL_PlayerByIndex( i );
+ if ( !pPlayer )
+ continue;
+
+ if ( pPlayer == pLocalPlayer )
+ {
+ nCount++;
+ }
+ else if ( pPlayer->GetTeamNumber() == pLocalPlayer->GetTeamNumber() )
+ {
+ int nTempFlags = 0;
+ CALL_ATTRIB_HOOK_INT_ON_OTHER( pPlayer, nTempFlags, vision_opt_in_flags );
+
+ if ( nTempFlags & TF_VISION_FILTER_PYRO )
+ {
+ nCount++;
+ }
+ }
+ }
+
+ if ( nCount >= 6 )
+ {
+ IncrementCount();
+ ClearThink();
+ return;
+ }
+ }
+ }
+
+ SetNextThink( 1.0 );
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_TeamPyrovision, ACHIEVEMENT_TF_TEAM_PYROVISION, "TF_TEAM_PYROVISION", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_DominateForGoggles : public CBaseTFAchievement
+{
+ 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 *pTFVictim = ToTFPlayer( pVictim );
+ bool bDomination = event->GetInt( "death_flags" ) & TF_DEATH_DOMINATION;
+
+ if ( pTFVictim && ( pAttacker == C_TFPlayer::GetLocalTFPlayer() ) && ( bDomination == true ) )
+ {
+ // are they wearing the PyroVision goggles?
+ for ( int i = 0 ; i < pTFVictim->GetNumWearables() ; ++i )
+ {
+ C_EconWearable *pWearable = pTFVictim->GetWearable( i );
+ if ( pWearable && pWearable->GetAttributeContainer() )
+ {
+ CEconItemView *pItem = pWearable->GetAttributeContainer()->GetItem();
+ if ( pItem && pItem->IsValid() )
+ {
+ if ( ( pItem->GetItemDefIndex() == 743 ) || // Autogrant PyroVision Goggles
+ ( pItem->GetItemDefIndex() == 744 ) ) // PyroVision Goggles
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_DominateForGoggles, ACHIEVEMENT_TF_DOMINATE_FOR_GOGGLES, "TF_DOMINATE_FOR_GOGGLES", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_ParachuteKillGrind : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_GLOBAL );
+ SetGoal( 10 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event )
+ {
+ CTFPlayer *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && ( pAttacker == C_TFPlayer::GetLocalTFPlayer() ) )
+ {
+ if ( pTFVictim->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_ParachuteKillGrind, ACHIEVEMENT_TF_PARACHUTE_KILL_GRIND, "TF_PARACHUTE_KILL_GRIND", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_MeleeKillClassicRifleSniper : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 10 );
+ SetStoreProgressInSteam( true );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_MeleeKillClassicRifleSniper, ACHIEVEMENT_TF_MELEE_KILL_CLASSIC_RIFLE_SNIPER, "TF_MELEE_KILL_CLASSIC_RIFLE_SNIPER", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_KillChargingDemo : 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 *pTFVictim = ToTFPlayer( pVictim );
+ if ( pTFVictim && ( pAttacker == C_TFPlayer::GetLocalTFPlayer() ) )
+ {
+ if ( pTFVictim->m_Shared.InCond( TF_COND_SHIELD_CHARGE ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_KillChargingDemo, ACHIEVEMENT_TF_KILL_CHARGING_DEMO, "TF_KILL_CHARGING_DEMO", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFTaunt_CongaKill : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ virtual void ListenForEvents( void )
+ {
+ ListenForGameEvent( "conga_kill" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "conga_kill" ) )
+ {
+ 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() <= 5.0 )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+ }
+
+private:
+ CUtlVector< float > m_Times;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFTaunt_CongaKill, ACHIEVEMENT_TF_TAUNT_CONGA_KILL, "TF_TAUNT_CONGA_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFTaunt_CongaLine : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFTaunt_CongaLine, ACHIEVEMENT_TF_TAUNT_CONGA_LINE, "TF_TAUNT_CONGA_LINE", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFTaunt_RPSRock : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ m_iCount = 0;
+ }
+
+ virtual void ListenForEvents( void )
+ {
+ ListenForGameEvent( "rps_taunt_event" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "rps_taunt_event" ) )
+ {
+ if ( event->GetInt( "winner" ) == GetLocalPlayerIndex() )
+ {
+ m_iCount = 0;
+ }
+ else if ( event->GetInt( "loser" ) == GetLocalPlayerIndex() )
+ {
+ if ( event->GetInt( "loser_rps" ) == 0 ) // 0:rock 1:paper 2:scissors
+ {
+ m_iCount++;
+ if ( m_iCount >= 3 )
+ {
+ IncrementCount();
+ }
+ }
+ else
+ {
+ m_iCount = 0;
+ }
+ }
+ }
+ }
+
+private:
+ int m_iCount;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFTaunt_RPSRock, ACHIEVEMENT_TF_TAUNT_RPS_ROCK, "TF_TAUNT_RPS_ROCK", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFTaunt_RPSScissors : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ m_iCount = 0;
+ }
+
+ virtual void ListenForEvents( void )
+ {
+ ListenForGameEvent( "rps_taunt_event" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( FStrEq( event->GetName(), "rps_taunt_event" ) )
+ {
+ if ( event->GetInt( "winner" ) == GetLocalPlayerIndex() )
+ {
+ if ( event->GetInt( "winner_rps" ) == 2 ) // 0:rock 1:paper 2:scissors
+ {
+ m_iCount++;
+ if ( m_iCount >= 3 )
+ {
+ IncrementCount();
+ }
+ }
+ else
+ {
+ m_iCount = 0;
+ }
+ }
+ else if ( event->GetInt( "loser" ) == GetLocalPlayerIndex() )
+ {
+ m_iCount = 0;
+ }
+ }
+ }
+
+private:
+ int m_iCount;
+};
+DECLARE_ACHIEVEMENT( CAchievementTFTaunt_RPSScissors, ACHIEVEMENT_TF_TAUNT_RPS_SCISSORS, "TF_TAUNT_RPS_SCISSORS", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFTaunt_DosidoMeleeKill : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 10 );
+ SetStoreProgressInSteam( true );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFTaunt_DosidoMeleeKill, ACHIEVEMENT_TF_TAUNT_DOSIDO_MELLE_KILL, "TF_TAUNT_DOSIDO_MELLE_KILL", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTFTaunt_TauntWhileCapping : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 10 );
+ SetStoreProgressInSteam( true );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTFTaunt_TauntWhileCapping, ACHIEVEMENT_TF_TAUNT_WHILE_CAPPING, "TF_TAUNT_WHILE_CAPPING", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_PassTimeHat : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 1 );
+ }
+
+ // server awards this achievement, no other code within achievement necessary
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_PassTimeHat, ACHIEVEMENT_TF_PASS_TIME_HAT, "TF_PASS_TIME_HAT", 5 );
+
+//----------------------------------------------------------------------------------------------------------------
+class CAchievementTF_PassTimeGrind : public CBaseTFAchievement
+{
+public:
+ void Init()
+ {
+ SetFlags( ACH_SAVE_GLOBAL );
+ SetGoal( 10 );
+ SetStoreProgressInSteam( true );
+ }
+
+ virtual void ListenForEvents()
+ {
+ ListenForGameEvent( "teamplay_round_win" );
+ }
+
+ void FireGameEvent_Internal( IGameEvent *event )
+ {
+ if ( TFGameRules() && TFGameRules()->IsPasstimeMode() )
+ {
+ if ( FStrEq( event->GetName(), "teamplay_round_win" ) )
+ {
+ // Were we on the winning team?
+ int iTeam = event->GetInt( "team" );
+ if ( ( iTeam >= FIRST_GAME_TEAM ) && ( iTeam == GetLocalPlayerTeam() ) )
+ {
+ IncrementCount();
+ }
+ }
+ }
+ }
+};
+DECLARE_ACHIEVEMENT( CAchievementTF_PassTimeGrind, ACHIEVEMENT_TF_PASS_TIME_GRIND, "TF_PASS_TIME_GRIND", 5 );
+
+#endif // CLIENT_DLL