//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: The TF Game rules object // // $Workfile: $ // $Date: $ // $NoKeywords: $ //=============================================================================// #ifndef CS_GAMERULES_H #define CS_GAMERULES_H #ifdef _WIN32 #pragma once #endif #include "teamplay_gamerules.h" #include "convar.h" #include "cs_shareddefs.h" #include "cs_weapon_parse.h" #include "gamevars_shared.h" #include "bot/bot_constants.h" #include "../../../common/input_device.h" #include "cstrike15_gcconstants.h" #include "cstrike15_gcmessages.pb.h" #include "usermessages.h" #if defined( GAME_DLL ) #include "maprules.h" #endif //#define DEBUG_QUESTS_IN_CLIENT #ifdef CLIENT_DLL #include "networkstringtable_clientdll.h" class C_CSPlayer; #define CCSPlayer C_CSPlayer #else #include "funfactmgr_cs.h" class CCSPlayer; #endif #define WINNER_NONE 0 #define WINNER_DRAW 1 #define WINNER_TER TEAM_TERRORIST #define WINNER_CT TEAM_CT #define CUSTOM_BOT_DIFFICULTY_NOBOTS 0 #define CUSTOM_BOT_DIFFICULTY_DUMB 1 #define CUSTOM_BOT_DIFFICULTY_EASY 2 #define CUSTOM_BOT_DIFFICULTY_MEDIUM 3 #define CUSTOM_BOT_DIFFICULTY_HARD 4 #define CUSTOM_BOT_DIFFICULTY_EXPERT 5 #define CUSTOM_BOT_MIN_DIFFICULTY_FOR_AWARDS_PROGRESS CUSTOM_BOT_DIFFICULTY_EASY #define MAX_WEAPON_NAME_POPUP_RANGE 128.0 #define MAX_GIFT_GIVERS_FEATURED_COUNT 4 #define MAX_TOURNAMENT_ACTIVE_CASTER_COUNT 4 class CCSBot; class CHostage; class CCSWeaponInfo; struct quest_data_t; extern ConVar mp_startmoney; extern ConVar mp_maxmoney; extern ConVar mp_afterroundmoney; extern ConVar mp_playercashawards; extern ConVar mp_teamcashawards; extern ConVar mp_tkpunish; extern ConVar mp_c4timer; extern ConVar mp_buytime; extern ConVar mp_freezetime; extern ConVar mp_playerid; extern ConVar mp_defuser_allocation; extern ConVar mp_death_drop_gun; extern ConVar mp_death_drop_grenade; extern ConVar mp_death_drop_defuser; extern ConVar ammo_grenade_limit_total; extern ConVar sv_competitive_official_5v5; namespace DefuserAllocation { enum Type { None = 0, Random = 1, All = 2, }; }; namespace TeamCashAward { enum Type { NONE = 0, TERRORIST_WIN_BOMB, ELIMINATION_HOSTAGE_MAP_T, ELIMINATION_HOSTAGE_MAP_CT, ELIMINATION_BOMB_MAP, WIN_BY_TIME_RUNNING_OUT_HOSTAGE, WIN_BY_TIME_RUNNING_OUT_BOMB, WIN_BY_DEFUSING_BOMB, WIN_BY_HOSTAGE_RESCUE, LOSER_BONUS, LOSER_BONUS_CONSECUTIVE_ROUNDS, RESCUED_HOSTAGE, HOSTAGE_ALIVE, PLANTED_BOMB_BUT_DEFUSED, HOSTAGE_INTERACTION, LOSER_ZERO, SURVIVE_GUARDIAN_WAVE, CUSTOM_AWARD, }; }; namespace RoundResult { enum Reason { UNDEFINED = 0, CT_WIN_ELIMINATION, CT_WIN_RESCUE, CT_WIN_DEFUSE, CT_WIN_TIME, T_WIN_ELIMINATION, T_WIN_BOMB, T_WIN_TIME, COUNT, UNKNOWN }; }; namespace PlayerCashAward { enum Type { NONE = 0, KILL_TEAMMATE, KILLED_ENEMY, BOMB_PLANTED, BOMB_DEFUSED, RESCUED_HOSTAGE, INTERACT_WITH_HOSTAGE, DAMAGE_HOSTAGE, KILL_HOSTAGE, RESPAWN, GET_KILLED, }; }; namespace AutobalanceStatus { enum Type { NONE = 0, NEXT_ROUND, THIS_ROUND }; }; //-------------------------------------------------------------------------------------------------------------- struct GGWeaponAliasName { CSWeaponID id; const char *aliasName; }; #define GGLIST_PISTOLS_TOTAL 9 #define GGLIST_RIFLES_TOTAL 7 #define GGLIST_MGS_TOTAL 2 #define GGLIST_SGS_TOTAL 4 #define GGLIST_SMGS_TOTAL 6 #define GGLIST_SNIPERS_TOTAL 3 #define GGLIST_PISTOLS_START 0 #define GGLIST_PISTOLS_LAST (GGLIST_PISTOLS_START+GGLIST_PISTOLS_TOTAL-1) #define GGLIST_RIFLES_START GGLIST_PISTOLS_LAST+1 #define GGLIST_RIFLES_LAST (GGLIST_RIFLES_START+GGLIST_RIFLES_TOTAL-1) #define GGLIST_MGS_START GGLIST_RIFLES_LAST+1 #define GGLIST_MGS_LAST (GGLIST_MGS_START+GGLIST_MGS_TOTAL-1) #define GGLIST_SGS_START GGLIST_MGS_LAST+1 #define GGLIST_SGS_LAST (GGLIST_SGS_START+GGLIST_SGS_TOTAL-1) #define GGLIST_SMGS_START GGLIST_SGS_LAST+1 #define GGLIST_SMGS_LAST (GGLIST_SMGS_START+GGLIST_SMGS_TOTAL-1) #define GGLIST_SNIPERS_START GGLIST_SMGS_LAST+1 #define GGLIST_SNIPERS_LAST (GGLIST_SNIPERS_START+GGLIST_SNIPERS_TOTAL-1) //-------------------------------------------------------------------------------------------------------------- // NOTE: Array must be NULL-terminated static GGWeaponAliasName ggWeaponAliasNameList[] = { //pistols { WEAPON_DEAGLE, "deagle" }, { WEAPON_DEAGLE, "revolver" }, { WEAPON_ELITE, "elite" }, { WEAPON_FIVESEVEN, "fiveseven" }, { WEAPON_GLOCK, "glock" }, { WEAPON_TEC9, "tec9" }, { WEAPON_HKP2000, "hkp2000" }, { WEAPON_HKP2000, "usp_silencer" }, { WEAPON_P250, "p250" }, //rifles { WEAPON_AK47, "ak47" }, { WEAPON_AUG, "aug" }, { WEAPON_FAMAS, "famas" }, { WEAPON_GALILAR, "galilar" }, { WEAPON_M4A1, "m4a1" }, { WEAPON_M4A1, "m4a1_silencer" }, { WEAPON_SG556, "sg556" }, //mgs { WEAPON_M249, "m249" }, { WEAPON_NEGEV, "negev" }, //shotguns { WEAPON_XM1014, "xm1014" }, { WEAPON_MAG7, "mag7" }, { WEAPON_SAWEDOFF, "sawedoff" }, { WEAPON_NOVA, "nova" }, //smgs { WEAPON_MAC10, "mac10" }, { WEAPON_P90, "p90" }, { WEAPON_UMP45, "ump45" }, { WEAPON_BIZON, "bizon" }, { WEAPON_MP7, "mp7" }, { WEAPON_MP9, "mp9" }, //snipers // { WEAPON_SSG08, "ssg08" }, { WEAPON_SCAR20, "scar20" }, { WEAPON_G3SG1, "g3sg1" }, { WEAPON_AWP, "awp" }, { WEAPON_NONE, "" } }; class CEconItemPreviewDataBlock; // forward declare item data class CCSUsrMsg_PlayerDecalDigitalSignature; // forward declare proto message #ifndef CLIENT_DLL extern ConVar mp_autoteambalance; #endif // !CLIENT_DLL #ifdef CLIENT_DLL #define CCSGameRules C_CSGameRules #define CCSGameRulesProxy C_CSGameRulesProxy #endif #if !defined( CLIENT_DLL ) // forward declare GC message class CMsgGCCStrike15_v2_MatchmakingServerRoundStats; class CMsgGCCStrike15_v2_MatchmakingGC2ServerReserve; int ScramblePlayersSort( CCSPlayer* const *p1, CCSPlayer* const *p2 ); class CCSMatch { public: CCSMatch(); void Reset( void ); void SetPhase( GamePhase phase ); GamePhase GetPhase( void ) const { return m_phase; } //These functions add to both the score and the number of rounds void AddTerroristWins( int numWins ); void AddCTWins( int numWins); void IncrementRound( int nNumRounds ); //These functions only adjust the score (without adding to the number of rounds played) void AddTerroristBonusPoints( int numWins ); void AddCTBonusPoints( int numWins); int GetTerroristScore( void ) const { return m_terroristScoreTotal; } int GetCTScore( void ) const { return m_ctScoreTotal; } int GetTeamScore( int nTeam ) const { switch( nTeam ) { case TEAM_TERRORIST: return GetTerroristScore(); case TEAM_CT: return GetCTScore(); default: Assert( !"unexpected value for nTeam" ); return 0; } } int GetRoundsPlayed( void ) const { return m_actualRoundsPlayed; } //Since the teams change in halftime modes and we want to retain their scores, we swap the scores //between halves. void SwapTeamScores( void ); int GetWinningTeam( void ); //These are the internal functions that actually mess with the scores, adjusting the appropriate phase-specific scores as well. void AddTerroristScore( int score ); void AddCTScore( int score ); void GoToOvertime( int numOvertimesToAdd ); private: //This is called anytime the match-internal scores are updated to reflect the changes in the team object (so the scores can be replicated) void UpdateTeamScores( void ); // Called when we wish to change the full all-talk rules, based on entering a specific phase of the match void EnableFullAlltalk( bool bEnable ); //This is the number of rounds that have been played, regardless of the actual score of the match (e.g. Demolition mode can give bonus points) short m_actualRoundsPlayed; // This is the index of the overtime that is being played, 0 when game has no overtime or is still in regulation time, 1 for first overtime, 2 for second, etc. short m_nOvertimePlaying; short m_ctScoreFirstHalf; short m_ctScoreSecondHalf; short m_ctScoreOvertime; short m_ctScoreTotal; short m_terroristScoreFirstHalf; short m_terroristScoreSecondHalf; short m_terroristScoreOvertime; short m_terroristScoreTotal; GamePhase m_phase; }; class SpawnPoint : public CServerOnlyPointEntity { DECLARE_CLASS( SpawnPoint, CServerOnlyPointEntity ); DECLARE_DATADESC(); public: SpawnPoint(); void Spawn( void ); bool IsEnabled() { return m_bEnabled; } void InputSetEnabled( inputdata_t &inputdata ); void InputSetDisabled( inputdata_t &inputdata ); void InputToggleEnabled( inputdata_t &inputdata ); void SetSpawnEnabled( bool bEnabled ); int m_iPriority; bool m_bEnabled; int m_nType; enum Type { Default = 0, Deathmatch = 1, ArmsRace = 2, }; }; class SpawnPointCoopEnemy : public SpawnPoint { DECLARE_CLASS( SpawnPointCoopEnemy, SpawnPoint ); DECLARE_DATADESC(); public: SpawnPointCoopEnemy(); void Spawn( void ); void Precache( void ); const char *GetWeaponsToGive( void ) { return STRING( m_szWeaponsToGive ); } const char *GetPlayerModelToUse( void ) { return STRING( m_szPlayerModelToUse ); } int GetArmorToSpawnWith( void ) { return m_nArmorToSpawnWith; } bool ShouldStartAsleep( void ) { return m_bStartAsleep; } int GetBotDifficulty( void ) { return m_nBotDifficulty; } bool IsBotAgressive( void ) { return m_bIsAgressive; } CNavArea *FindNearestArea( void ); float HideRadius() const { return m_flHideRadius; } void HideRadius(bool val) { m_flHideRadius = val; } enum BotDefaultBehavior_t { DEFEND_AREA = 0, HUNT, CHARGE_ENEMY, DEFEND_INVESTIGATE, }; BotDefaultBehavior_t GetDefaultBehavior() const { return m_nDefaultBehavior; } void SetDefaultBehavior( BotDefaultBehavior_t val ) { m_nDefaultBehavior = val; } protected: string_t m_szWeaponsToGive; string_t m_szPlayerModelToUse; int m_nArmorToSpawnWith; BotDefaultBehavior_t m_nDefaultBehavior; int m_nBotDifficulty; bool m_bIsAgressive; bool m_bStartAsleep; float m_flHideRadius; CNavArea *m_pMyArea; }; #endif //!CLIENT_DLL class CCSGameRulesProxy : public CGameRulesProxy { public: DECLARE_CLASS( CCSGameRulesProxy, CGameRulesProxy ); DECLARE_NETWORKCLASS(); }; class CCSGameRules : public CTeamplayRules { public: DECLARE_CLASS( CCSGameRules, CTeamplayRules ); // Stuff that is shared between client and server. bool IsFreezePeriod(); bool IsWarmupPeriod() const; float GetWarmupPeriodEndTime() const; bool IsWarmupPeriodPaused(); void SetWarmupPeriodStartTime( float fl ) { m_fWarmupPeriodStart = fl; } float GetWarmupPeriodStartTime( void ) { return m_fWarmupPeriodStart; } bool AllowTaunts( void ); bool IsTimeOutActive() const { return ( IsTerroristTimeOutActive() || IsCTTimeOutActive() ); } bool IsTerroristTimeOutActive() const { return m_bTerroristTimeOutActive; } bool IsCTTimeOutActive() const { return m_bCTTimeOutActive; } void StartTerroristTimeOut( void ); void StartCTTimeOut( void ); void EndTerroristTimeOut( void ); void EndCTTimeOut( void ); float GetCTTimeOutRemaining() const { return m_flCTTimeOutRemaining; } float GetTerroristTimeOutRemaining() const { return m_flTerroristTimeOutRemaining; } int GetCTTimeOuts( ) const { return m_nCTTimeOuts; } int GetTerroristTimeOuts( ) const { return m_nTerroristTimeOuts; } #ifdef CLIENT_DLL virtual bool AllowThirdPersonCamera(); bool IsGoodDownTime( void ); // this returns true when its a good time to do things like garbage collection bool IsLoadoutAllowed( void ); void MarkClientStopRecordAtRoundEnd( bool bStop ); #endif #ifndef CLIENT_DLL void StartWarmup( void ); void EndWarmup( void ); virtual bool IsTeamChangeSilent( CBasePlayer *pPlayer, int iTeamNum, bool bAutoTeam, bool bSilent ) { return bSilent || m_bForceTeamChangeSilent; } void CheckForGiftsLeaderboardUpdate(); #endif bool IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ); virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 ); virtual float GetRoundRestartTime( void ) { return m_flRestartRoundTime; } virtual bool IsGameRestarting( void ) { return m_bGameRestart; } float GetMapRemainingTime(); // time till end of map, -1 if timelimit is disabled float GetMapElapsedTime(); // How much time has elapsed since the map started. float GetRoundRemainingTime() const; // time till end of round float GetRoundStartTime(); // When this round started. float GetRoundElapsedTime(); // How much time has elapsed since the round started. float GetBuyTimeLength(); int GetRoundLength() const { return m_iRoundTime; } int SelectDefaultTeam( bool ignoreBots = false ); int GetHumanTeam(); // TEAM_UNASSIGNED if no restrictions void CalculateMaxGunGameProgressiveWeaponIndex( void ); int GetMaxGunGameProgressiveWeaponIndex( void ) { return m_iMaxGunGameProgressiveWeaponIndex; } AcquireResult::Type IsWeaponAllowed( const CCSWeaponInfo *pWeaponInfo, int nTeamNumber ,CEconItemView *pItem = NULL ); bool IsBombDefuseMap() const; bool IsHostageRescueMap() const; bool MapHasBuyZone() const; bool CanSpendMoneyInMap(); bool IsIntermission() const; bool IsLogoMap() const; bool IsSpawnPointValid( CBaseEntity *pSpot, CBasePlayer *pPlayer ); bool IsSpawnPointHiddenFromOtherPlayers( CBaseEntity *pSpot, CBasePlayer *pPlayer, int nHideFromTeam = 0 ); bool IsBuyTimeElapsed(); bool IsMatchWaitingForResume( void ); void SetMatchWaitingForResume( bool pause ) { m_bMatchWaitingForResume = pause; }; virtual int DefaultFOV(); // Get the view vectors for this mod. virtual const CViewVectors* GetViewVectors() const; bool IsCSGOBirthday( void ); int GetStartMoney( void ); int GetMaxMoney( void ); int GetBetweenRoundMoney( void ); bool PlayerCashAwardsEnabled( void ); bool TeamCashAwardsEnabled( void ); void AddHostageRescueTime( void ); bool IsPlayingCustomGametype( void ) const; bool IsPlayingGunGameProgressive( void ) const; bool IsPlayingGunGameDeathmatch( void ) const; bool IsPlayingGunGameTRBomb( void ) const; bool IsPlayingGunGame( void ) const; bool IsPlayingClassic( void ) const; bool IsPlayingOffline( void ) const; bool IsPlayingTraining( void ) const; bool IsPlayingCooperativeGametype( void ) const; bool IsPlayingClassicCasual( void ) const; bool IsPlayingAnyCompetitiveStrictRuleset( void ) const; bool IsPlayingCoopGuardian( void ) const; bool IsPlayingCoopMission( void ) const; bool IsQueuedMatchmaking( void ) const; bool IsValveDS( void ) const; bool IsQuestEligible( void ) const; bool ShouldRecordMatchStats( void ) const; virtual bool IgnorePlayerKillCommand( void ) const { return IsQueuedMatchmaking() && !IsWarmupPeriod(); } bool IsAwardsProgressAllowedForBotDifficulty() const; // returns false if the user is playing offline with trivial bots (no bots, harmless bots) bool IsTeammateSolid( void ) const; // returns true if teammates are solid obstacles in the current game mode bool IsArmorFree( void ) const; bool HasHalfTime( void ) const; bool IsRoundOver() const; int GetCustomBotDifficulty( void ) const; int GetCurrentGunGameWeapon ( int nCurrentWeaponIndex, int nTeamID ); int GetNextGunGameWeapon( int nCurrentWeaponIndex, int nTeamID ); int GetPreviousGunGameWeapon( int nCurrentWeaponIndex, int nTeamID ); bool IsFinalGunGameProgressiveWeapon( int nCurrentWeaponIndex, int nTeamID ); int GetGunGameNumKillsRequiredForWeapon( int nCurrentWeaponIndex, int nTeamID ); void AddGunGameWeapon( const char* pWeaponName, int nNumKillsToUpgrade, int nTeamID ); int GetNumProgressiveGunGameWeapons( int nTeamID ) const; int GetProgressiveGunGameWeapon( int nWeaponIndex, int nTeamID ) const { return nTeamID == TEAM_CT ? m_GGProgressiveWeaponOrderCT[nWeaponIndex] : m_GGProgressiveWeaponOrderT[nWeaponIndex]; } int GetProgressiveGunGameWeaponKillRequirement( int nWeaponIndex, int nTeamID ) const { return nTeamID == TEAM_CT ? m_GGProgressiveWeaponKillUpgradeOrderCT[nWeaponIndex] : m_GGProgressiveWeaponKillUpgradeOrderT[nWeaponIndex]; } int GetGunGameTRBonusGrenade( CCSPlayer *pPlayer ); void IncrementGunGameTerroristWeapons( void ); void IncrementGunGameCTWeapons( void ); bool IsBotOnlyTeam( int nTeamNumber ); int TeamCashAwardValue( TeamCashAward::Type reason); int PlayerCashAwardValue( PlayerCashAward::Type reason); int GetMaxSpectatorSlots( void ) const; float GetTimeUntilNextPhaseStarts( void ) { return m_timeUntilNextPhaseStarts; } GamePhase GetGamePhase( void ) const { return ( GamePhase ) m_gamePhase.Get(); } int GetTotalRoundsPlayed( void ) const { return m_totalRoundsPlayed; } int GetOvertimePlaying( void ) const { return m_nOvertimePlaying; } int GetNumWinsToClinch( void ) const; bool IsLastRoundOfMatch() const; bool IsMatchPoint() const; // AreTeamsPlayingSwitchedSides() -- will return true when match is in second half, or in the half of overtime period where teams are switched. // Overtime logic is as follows: TeamA plays CTs as first half of regulation, then Ts as second half of regulation, // then if tied in regulation continues to play Ts as first half of 1st overtime, then switches to CTs for second half of 1st overtime, // then if still tied after 1st OT they continue to play CTs as first half of 2nd overtime, then switch to Ts for second half of 2nd overtime, // then if still tied after 2nd OT they continue to play Ts as first half of 3rd overtime, then switch to CTs for second half of 3rd overtime, // and so on until the match determines a winner. // So AreTeamsPlayingSwitchedSides will return true when TeamA is playing T-side and will return false when TeamA plays CT-side as they started match on CT // in scenario outlined above. bool AreTeamsPlayingSwitchedSides() const; void SetIsWarmupPeriod( bool bIsWarmup ) { m_bWarmupPeriod = bIsWarmup; } bool HasMatchStarted() { return m_bHasMatchStarted; } int GetWeaponScoreForDeathmatch( int nPos ); float GetRestartRoundTime( void ) const; #if !defined( CLIENT_DLL ) int GetCoopWaveNumber( void ) { return m_nGuardianModeWaveNumber; } CGameCoopMissionManager *GetCoopMissionManager( void ); EHANDLE m_coopMissionManager; void SetCoopMissionManager( CBaseEntity *pPoint ) { m_coopMissionManager = pPoint; } void CoopSetBotQuotaAndRefreshSpawns( int nMaxEnemiesToSpawn ); void CoopMissionSetNextRespawnIn( float flSeconds, bool bIncrementWaveNumber ); void CoopMissionSpawnFirstEnemies( int nMaxEnemiesToSpawn ); void CoopMissionSpawnNextWave( int nMaxEnemiesToSpawn ); void CoopMissionRespawnDeadPlayers( void ); void CoopCollectBonusCoin( void ); virtual bool OnReplayPrompt( CBasePlayer *pVictim, CBasePlayer *pScorer ) OVERRIDE; #endif int GetGuardianRequiredKills( void ) const; int GetGuardianKillsRemaining( void ) const; int GetGuardianSpecialWeapon( void ) const; private: float GetExplosionDamageAdjustment(Vector & vecSrc, Vector & vecEnd, CBaseEntity *pEntityToIgnore); // returns multiplier between 0.0 and 1.0 that is the percentage of any damage done from vecSrc to vecEnd that actually makes it. float GetAmountOfEntityVisible(Vector & src, CBaseEntity *player); // returns a value from 0 to 1 that is the percentage of player visible from src. CNetworkVar( bool, m_bFreezePeriod ); // TRUE at beginning of round, set to FALSE when the period expires CNetworkVar( bool, m_bWarmupPeriod ); // CNetworkVar( float, m_fWarmupPeriodEnd ); // OBSOLETE. LEFT IN FOR DEMO COMPATIBILITY. CNetworkVar( float, m_fWarmupPeriodStart ); CNetworkVar( bool, m_bTerroristTimeOutActive ); CNetworkVar( bool, m_bCTTimeOutActive ); CNetworkVar( float, m_flTerroristTimeOutRemaining ); CNetworkVar( float, m_flCTTimeOutRemaining ); CNetworkVar( int, m_nTerroristTimeOuts ); CNetworkVar( int, m_nCTTimeOuts ); CNetworkVar( bool, m_bMatchWaitingForResume ); // When mp_pause_match is called, this state becomes true and will prevent the next freezetime from ending. CNetworkVar( int, m_iRoundTime ); // (From mp_roundtime) - How many seconds long this round is. CNetworkVar( float, m_fMatchStartTime ); // time when match has started CNetworkVar( float, m_fRoundStartTime ); // time round has started CNetworkVar( float, m_flRestartRoundTime ); // the global time when the round is supposed to end, if this is not 0 CNetworkVar( bool, m_bGameRestart ); // True = mp_restartgame is being processed CNetworkVar( float, m_flGameStartTime ); CNetworkVar( float, m_timeUntilNextPhaseStarts ); CNetworkVar( int, m_gamePhase ); CNetworkVar( int, m_totalRoundsPlayed); CNetworkVar( int, m_nOvertimePlaying); CNetworkVar( int, m_iHostagesRemaining ); CNetworkVar( bool, m_bAnyHostageReached ); CNetworkVar( bool, m_bMapHasBombTarget ); CNetworkVar( bool, m_bMapHasRescueZone ); CNetworkVar( bool, m_bMapHasBuyZone ); CNetworkVar( bool, m_bIsQueuedMatchmaking ); CNetworkVar( bool, m_bIsValveDS ); CNetworkVar( bool, m_bLogoMap ); // If there's an info_player_logo entity, then it's a logo map. CNetworkVar( int, m_iNumGunGameProgressiveWeaponsCT ); // total number of CT gun game progressive weapons CNetworkVar( int, m_iNumGunGameProgressiveWeaponsT ); // total number of T gun game progressive weapons CNetworkVar( int, m_iSpectatorSlotCount ); // max spectator slots available CNetworkArray( int, m_GGProgressiveWeaponOrderCT, 60 ); // CT gun game weapon order and # kills per weapon. Size is meant to be larger than the current number of different weapons defined in the CSWeaponID enum CNetworkArray( int, m_GGProgressiveWeaponOrderT, 60 ); // T gun game weapon order and # kills per weapon. Size is meant to be larger than the current number of different weapons defined in the CSWeaponID enum CNetworkArray( int, m_GGProgressiveWeaponKillUpgradeOrderCT, 60 ); // CT gun game number of kills per weapon. Size is meant to be larger than the current number of different weapons defined in the CSWeaponID enum CNetworkArray( int, m_GGProgressiveWeaponKillUpgradeOrderT, 60 ); // T gun game number of kills per weapon. Size is meant to be larger than the current number of different weapons defined in the CSWeaponID enum CNetworkVar( int, m_MatchDevice ); CNetworkVar( bool, m_bHasMatchStarted ); CNetworkVar( float, m_flDMBonusStartTime ); CNetworkVar( float, m_flDMBonusTimeLength ); CNetworkVar( uint16, m_unDMBonusWeaponLoadoutSlot ); CNetworkVar( bool, m_bDMBonusActive ); CNetworkVar( int, m_nNextMapInMapgroup ); CNetworkString( m_szTournamentEventName, MAX_PATH ); CNetworkString( m_szTournamentEventStage, MAX_PATH ); CNetworkString( m_szMatchStatTxt, MAX_PATH ); CNetworkString( m_szTournamentPredictionsTxt, MAX_PATH ); CNetworkVar( int, m_nTournamentPredictionsPct ); CNetworkVar( float, m_flCMMItemDropRevealStartTime ); CNetworkVar( float, m_flCMMItemDropRevealEndTime ); CNetworkVar( bool, m_bIsDroppingItems ); // CNetworkVar( bool, m_bIsQuestEligible ); CNetworkVar( int, m_nGuardianModeWaveNumber ); CNetworkVar( int, m_nGuardianModeSpecialKillsRemaining ); CNetworkVar( int, m_nGuardianModeSpecialWeaponNeeded ); int m_nGuardianGrenadesToGiveBots; public: // HACK: Low on time, don't have a better place for this. Hang some global data guardian needs to bookkeep heavy spawns. int m_nNumHeaviesToSpawn; // // Holiday gifts global presence // CNetworkVar( uint32, m_numGlobalGiftsGiven ); CNetworkVar( uint32, m_numGlobalGifters ); CNetworkVar( uint32, m_numGlobalGiftsPeriodSeconds ); CNetworkArray( uint32, m_arrFeaturedGiftersAccounts, MAX_GIFT_GIVERS_FEATURED_COUNT ); CNetworkArray( uint32, m_arrFeaturedGiftersGifts, MAX_GIFT_GIVERS_FEATURED_COUNT ); #define MAX_PROHIBITED_ITEMS 100 CNetworkArray( uint16, m_arrProhibitedItemIndices, MAX_PROHIBITED_ITEMS ); // // Tournament Casters // CNetworkArray( uint32, m_arrTournamentActiveCasterAccounts, MAX_TOURNAMENT_ACTIVE_CASTER_COUNT ); // These three are part of a hack to move an expensive network call (ClientPrint) out of // the death code and defer it by a short time. The level of network traffic is causing hitches on ps3. // CCallQueue m_DeferredCallQueue; // float m_flDeferredCallDispatchTime; // Tournament best-of-N CNetworkVar( int, m_numBestOfMaps ); // halloween mask seed CNetworkVar( int, m_nHalloweenMaskListSeed ); CNetworkVar( bool, m_bBombDropped ); CNetworkVar( bool, m_bBombPlanted ); CNetworkVar( int, m_iRoundWinStatus ); // 1 == CT's won last round, 2 == Terrorists did, 3 == Draw, no winner CNetworkVar( int, m_eRoundWinReason ); // see: e_RoundEndReason CNetworkVar( bool, m_bTCantBuy ); // Who can and can't buy. CNetworkVar( bool, m_bCTCantBuy ); CNetworkVar( float, m_flGuardianBuyUntilTime ); CNetworkArray( int, m_iMatchStats_RoundResults, MAX_MATCH_STATS_ROUNDS ); CNetworkArray( int, m_iMatchStats_PlayersAlive_CT, MAX_MATCH_STATS_ROUNDS ); CNetworkArray( int, m_iMatchStats_PlayersAlive_T, MAX_MATCH_STATS_ROUNDS ); CNetworkArray( float, m_TeamRespawnWaveTimes, MAX_TEAMS ); // Time between each team's respawn wave CEconQuestDefinition* GetActiveAssassinationQuest( void ) const; int GetActiveServerQuestID( void ) const { return m_iActiveAssassinationTargetMissionID; } protected: CNetworkArray( float, m_flNextRespawnWave, MAX_TEAMS ); // Minor waste, but cleaner code CNetworkVar( int, m_iActiveAssassinationTargetMissionID ); // we cannot change the name of this field for networking compatibility, but in coopgametypes this means the server questid bool m_bDontIncrementCoopWave; public: float GetCMMItemDropRevealDuration(); float GetCMMItemDropRevealEndTime() { return m_flCMMItemDropRevealEndTime; } bool IsDroppingItems() { return m_bIsDroppingItems; } loadout_positions_t GetDMBonusWeaponLoadoutSlot( void ) { return ( loadout_positions_t )m_unDMBonusWeaponLoadoutSlot.Get(); } float GetDMBonusStartTime( void ) { return m_flDMBonusStartTime; } float GetDMBonusTimeLength( void ) { return m_flDMBonusTimeLength; } bool IsDMBonusActive( void ) { return m_bDMBonusActive; } void SetNextMapInMapGroup( int nIndex ) { m_nNextMapInMapgroup = nIndex; } int GetNextMapInMapGroup( void ) { return m_nNextMapInMapgroup; } #if defined( GAME_DLL ) bool CheckGotGuardianModeSpecialKill( CWeaponCSBase* pAttackerWeapon ); #endif int GetNumHostagesRemaining( void ) { return m_iHostagesRemaining; } virtual CBaseCombatWeapon *GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); virtual const unsigned char *GetEncryptionKey( void ) { return (unsigned char *)"d7NSuLq2"; } // both the client and server need this key void CreateFriendlyMapNameToken( const char* szShortName, char* szOutBuffer, int nBuffSize ); // This is unlocalized and shouldn't be used for display const char *GetDefaultTeamName( int nTeam ); void OpenBuyMenu( int nPlayerIndex ); void CloseBuyMenu( int nPlayerIndex ); // respawn void SetNextTeamRespawnWaveDelay( int iTeam, float flDelay ); virtual float GetNextRespawnWave( int iTeam, CBasePlayer *pPlayer ); float GetMinTimeWhenPlayerMaySpawn( CBasePlayer *pPlayer ); float GetRespawnWaveMaxLength( int iTeam, bool bScaleWithNumPlayers = true ); float GetRespawnTimeScalar( int iTeam ); //float GetTimeUntilEndMatchNextMapVoteEnds( void ); bool IsEndMatchVotingForNextMap(); bool IsEndMatchVotingForNextMapEnabled(); // End Match Voting CNetworkArray( int, m_nEndMatchMapGroupVoteOptions, MAX_ENDMATCH_VOTE_PANELS ); // For mapgroups >10 maps these will be vote options // these functions cover recording and sending item drops for display in game modes where you don't allow drops during the match/round CUtlVector< CEconItemPreviewDataBlock * > m_ItemsPtrDroppedDuringMatch; const CUtlVector< CEconItemPreviewDataBlock * >& GetItemsDroppedDuringMatch( void ) const { return m_ItemsPtrDroppedDuringMatch; } void ClearItemsDroppedDuringMatch( void ); void RecordPlayerItemDrop( const CEconItemPreviewDataBlock &iteminfo ); static int GetMaxPlayers(); // always available // COOP void CoopResetRoundStartTime( void ); void CoopGiveC4sToCTs( int nC4sToGive ); #ifndef CLIENT_DLL int m_coopBonusCoinsFound; bool m_coopBonusPistolsOnly; bool m_coopPlayersInDeploymentZone; #endif #ifdef CLIENT_DLL DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. CCSGameRules(); ~CCSGameRules(); // helper function - this will eventually support side car info (and will probably move) const wchar_t* GetFriendlyMapName( const char* szShortName ); bool GetFriendlyMapNameToken( const char* szShortName, char* szOutBuffer, int nBuffSize ); char const * GetTournamentEventName() const; char const * GetTournamentEventStage() const; char const * GetTournamentPredictionsTxt() const { return m_szTournamentPredictionsTxt; } int GetTournamentPredictionsPct() const { return m_nTournamentPredictionsPct; } char const * GetMatchStatTeamsTxt() const { return m_szMatchStatTxt; } CUserMessageBinder m_UMCMsgSendPlayerItemDrops; CUserMessageBinder m_UMCMsgSendPlayerItemFound; bool m_bMarkClientStopRecordAtRoundEnd; static void RecvProxy_TournamentActiveCasterAccounts( const CRecvProxyData *pData, void *pStruct, void *pOut ); void ResetCasterConvars( void ); #else DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. CCSGameRules(); virtual ~CCSGameRules(); virtual void RefreshSkillData( bool forceUpdate ); void DumpTimers( void ) const; // debugging to help track down a stuck server (rare?) CBaseEntity *GetPlayerSpawnSpot( CBasePlayer *pPlayer ); static void EndRound(); virtual void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); virtual void Think(); void SwitchTeamsAtRoundReset( void ); void ClearGunGameData( void ); void FreezePlayers( void ); // Called at the end of GameFrame (i.e. after all game logic has run this frame) virtual void EndGameFrame( void ); // Called when game rules are destroyed by CWorld virtual void LevelShutdown( void ); void UpdateTeamClanNames( int nTeam ); void UpdateTeamPredictions(); // vscript function void SetPlayerCompletedTraining( bool bCompleted ); bool GetPlayerCompletedTraining( void ); void SetBestTrainingCourseTime( int nTime ); int GetBestTrainingCourseTime( void ); int GetValveTrainingCourseTime( void ); bool IsLocalPlayerUsingController( void ); void TrainingGivePlayerAmmo( void ); void TrainingSetRadarHidden( bool bHide ); void TrainingSetMiniScoreHidden( bool bHide ); void TrainingHighlightAmmoCounter( void ); void TrainingShowFinishMsgBox( void ); void TrainingShowExitDoorMsg( void ); virtual void RegisterScriptFunctions( void ); virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); virtual void PlayerSpawn( CBasePlayer *pPlayer ); void ShowSpawnPoints( int duration ); virtual void SpawningLatePlayer( CCSPlayer* pLatePlayer ); bool IsPistolRound( void ); void HostageKilled( void ) { m_hostageWasKilled = true; } void HostageInjured( void ) { m_hostageWasInjured = true; } bool WasHostageKilled( void ) { return m_hostageWasKilled; } bool WasHostageInjured( void ) { return m_hostageWasInjured; } void PlayerTookDamage( CCSPlayer* player, const CTakeDamageInfo &damageInfo ); void SendKickBanToGC( CCSPlayer *pPlayer, EMsgGCCStrike15_v2_MatchmakingKickBanReason_t eReason ); void SendKickBanToGCforAccountId( uint32 uiAccountId, EMsgGCCStrike15_v2_MatchmakingKickBanReason_t eReason ); virtual bool PlayTextureSounds( void ) { return true; } // Let the game rules specify if fall death should fade screen to black virtual bool FlPlayerFallDeathDoesScreenFade( CBasePlayer *pl ) { return FALSE; } virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ); void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld ); virtual void UpdateClientData( CBasePlayer *pl ); virtual CCSPlayer* CheckAndAwardAssists( CCSPlayer* pCSVictim, CCSPlayer* pKiller ); // Death notices virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ); IGameEvent * CreateWeaponKillGameEvent( char const *szEventName, const CTakeDamageInfo &info ); virtual void InitDefaultAIRelationships( void ); virtual const char *GetGameDescription( void ) { return "Counter-Strike: Global Offensive"; } // this is the game name that gets seen in the server browser virtual const char *AIClassText(int classType); virtual bool FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ); virtual const char *SetDefaultPlayerTeam( CBasePlayer *pPlayer ); // Called before entities are created virtual void LevelInitPreEntity(); // Called after the map has finished loading. virtual void LevelInitPostEntity(); virtual float FlPlayerFallDamage( CBasePlayer *pPlayer ); virtual bool ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); virtual void ClientDisconnected( edict_t *pClient ); virtual void ClientCommandKeyValues( edict_t *pEntity, KeyValues *pKeyValues ); virtual int GetMaxHumanPlayers() const; // Recreate all the map entities from the map data (preserving their indices), // then remove everything else except the players. // Also get rid of all world decals. void CleanUpMap(); void CheckFreezePeriodExpired(); void CheckRoundTimeExpired(); // check if the scenario has been won/lost // return true if the scenario is over, false if the scenario is still in progress bool CheckWinConditions( void ); // this is used by entities like X and increments the round and ends it void IncrementAndTerminateRound( float tmDelay, int reason ); void TerminateRound( float tmDelay, int reason ); void ProcessEndOfRoundAchievements( int iWinnerTeam, int iReason ); void SaveRoundDataInformation( char const *szFilenameOverride = NULL ); void LoadRoundDataInformation( char const *szFilename ); void ResetMasterSpawnPointsForCoop( void ); // The following round-related functions are called as follows: // // At Match Start: // PreRestartRound() -> RestartRound() -> PostRestartRound() // // During Subsequent Round Gameplay: // RoundWin() is called at the point when the winner of the round has been determined - prior to free-play commencing // PreRestartRound() is called with 1 second remaining prior to the round officially ending (This is after a round // winner has been chosen and players are allowed to continue playing) // RoundEnd() is then called when the round has completely ended // RestartRound() is then called immediately after RoundEnd() // PostRestartRound() is called immediately after RestartRound() has completed void PreRestartRound( void ); void RestartRound( void ); void PostRestartRound( void ); void RoundWin( void ); void RoundEnd( void ); int GetRoundsPlayed( void ) const { return m_match.GetRoundsPlayed(); } void BalanceTeams( void ); void HandleScrambleTeams( void ); void HandleSwapTeams( void ); void MoveHumansToHumanTeam( void ); bool TeamFull( int team_id ); int MaxNumPlayersOnTerrTeam(); int MaxNumPlayersOnCTTeam(); bool WillTeamHaveRoomForPlayer( CCSPlayer* pPlayer, int newTeam ); bool TeamStacked( int newTeam_id, int curTeam_id ); bool FPlayerCanRespawn( CBasePlayer *pPlayer ); void UpdateTeamScores(); void CheckMapConditions(); void MarkLivingPlayersOnTeamAsNotReceivingMoneyNextRound(int team); // Check various conditions to end the map. bool CheckGameOver(); bool CheckWinLimit(); bool CheckFragLimit(); void CheckLevelInitialized(); void CheckRestartRound(); virtual bool FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ); virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ); bool CanPlayerHearTalker( CBasePlayer* pListener, CBasePlayer *pSpeaker, bool bTeamOnly ); virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); virtual bool PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker, bool bTeamOnly ); void GuardianUpdateBotAccountAndWeapons( CCSPlayer *pBot ); void GiveGuardianBotGrenades( CCSPlayer *pBot ); // repsawning void SetTeamRespawnWaveTime( int iTeam, float flValue ); virtual bool HasPassedMinRespawnTime( CBasePlayer *pPlayer ); void CheckRespawnWaves( void ); // Checks if it still needs players to start a round, or if it has enough players to start rounds. // Starts a round and returns true if there are enough players. bool NeededPlayersCheck( bool &bNeededPlayers ); // Setup counts for m_iNumTerrorist, m_iNumCT, m_iNumSpawnableTerrorist, m_iNumSpawnableCT, etc. void InitializePlayerCounts( int &NumAliveTerrorist, int &NumAliveCT, int &NumDeadTerrorist, int &NumDeadCT ); // Check to see if the round is over for the various game types. Terminates the round // and returns true if the round should end. bool PrisonRoundEndCheck(); bool BombRoundEndCheck( bool bNeededPlayers ); bool HostageRescueRoundEndCheck( bool bNeededPlayers ); bool BombPlantedRoundEndCheck(); bool CTsReachedHostageRoundEndCheck(); bool GuardianAllKillsAchievedCheck(); bool m_bHasHostageBeenTouched; CCSPlayer* CalculateEndOfRoundMVP(); // Check to see if the teams exterminated each other. Ends the round and returns true if so. bool TeamExterminationCheck( int NumAliveTerrorist, int NumAliveCT, int NumDeadTerrorist, int NumDeadCT, bool bNeededPlayers ); void ReadMultiplayCvars(); void SwapAllPlayers(); void OnTeamsSwappedAtRoundReset(); void ResetForTradeshow( void ); // reset player scores, reset team scores, reset player controls, restart round; used for demos void BroadcastSound( const char *sound, int team = -1 ); // GUN GAME PROGRESSIVE FUNCTION bool GunGameProgressiveEndCheck( void ); // BOMB MAP FUNCTIONS void GiveC4ToRandomPlayer(); void GiveDefuserToRandomPlayer(); CCSPlayer *IsThereABomber(); bool IsThereABomb(); // HOSTAGE MAP FUNCTIONS void HostageTouched(); // Contribution score helpers void ScorePlayerKill( CCSPlayer* pPlayer ); void ScorePlayerAssist( CCSPlayer* pPlayer, CCSPlayer* pCSVictim ); void ScorePlayerObjectiveKill( CCSPlayer* pPlayer ); void ScorePlayerSuicide( CCSPlayer* pPlayer ); void ScorePlayerTeamKill( CCSPlayer* pPlayer ); void ScorePlayerDamage( CCSPlayer* pPlayer, float fDamage ); void ScoreBombPlant( CCSPlayer* pPlayer ); void ScoreBombExploded( CCSPlayer* pPlayer ); void ScoreBombDefuse( CCSPlayer* pPlayer, bool bMajorEvent ); void ScoreHostageRescue( CCSPlayer* pPlayer, CHostage* pHostage, bool bMajorEvent ); void ScoreHostageKilled( CCSPlayer* pPlayer ); void ScoreHostageDamage( CCSPlayer* pPlayer, float fDamage ); void ScoreFriendlyFire( CCSPlayer* pPlayer, float fDamage ); void ScoreBlindEnemy( CCSPlayer* pPlayer ); void ScoreBlindFriendly( CCSPlayer* pPlayer ); // Sets up g_pPlayerResource. virtual void CreateStandardEntities(); virtual const char *GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer ); virtual const char *GetChatLocation( bool bTeamOnly, CBasePlayer *pPlayer ); virtual const char *GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ); void ClientSettingsChanged( CBasePlayer *pPlayer ); virtual bool CanClientCustomizeOwnIdentity() OVERRIDE; bool IsCareer( void ) const { return false; } // returns true if this is a CZ "career" game virtual bool FAllowNPCs( void ); bool CheckSetVoteTime(); void GoToMatchRestartIntermission(); CCSMatch* GetMatch( void ); // Let's the match store recplicated vars in the game rules. void SetGamePhase( GamePhase newPhase ) { m_gamePhase = newPhase; } void SetTotalRoundsPlayed( int roundsPlayed ) { m_totalRoundsPlayed = roundsPlayed; } void SetOvertimePlaying( int nOvertimePlaying ) { m_nOvertimePlaying = nOvertimePlaying; } void SetScrambleTeamsOnRestart( bool scramble ) { m_bScrambleTeamsOnRestart = scramble; } bool GetScrambleTeamsOnRestart( void ) { return m_bScrambleTeamsOnRestart; } void SetSwapTeamsOnRestart( bool swapTeams ) { m_bSwapTeamsOnRestart = swapTeams; } bool GetSwapTeamsOnRestart( void ) { return m_bSwapTeamsOnRestart; } bool GameModeSupportsHealthBuffer( void ); protected: // these functions cover recording and sending item drops for display in game modes where you don't allow drops during the match/round void SendPlayerItemDropsToClient( void ); bool m_bPlayerItemsHaveBeenDisplayed; void RewardMatchEndDrops( bool bAbortedMatch ); virtual void GoToIntermission( bool bAbortedMatch = false ); void UpdateMatchStats( CCSPlayer* pPlayer, int winnerIndex ) ; static void SplitScoreAmongPlayersInZone( int iPoints, int iTeam, CCSPlayer* pExcludePlayer, uint iPlace ); static void SplitScoreAmongPlayersInRange( int iPoints, int iTeam, CCSPlayer* pExcludePlayer, const Vector& center, float fRangeInner, float fRangeOuter ); void GotoTRBombModeHalftime( void ); void EndTRBombModeHalftime( void ); float CalculateAveragePlayerContributionScore( void ); float CalculateAverageBotContributionScore( void ); public: void ModifyRealtimeBotDifficulty( CCSPlayer* pOnlyBotToProcess = NULL ); public: bool IsFriendlyFireOn() const; bool IsLastRoundBeforeHalfTime( void ); virtual void SetAllowWeaponSwitch( bool allow ); virtual bool GetAllowWeaponSwitch( void ); bool ShouldGunGameSpawnBomb( void ); void SetGunGameSpawnBomb( bool allow ); bool IsClanTeam( CTeam *pTeam ); //int GetEndMatchCurrentMapVotes(); // VARIABLES FOR ALL TYPES OF MAPS bool m_bLevelInitialized; int m_iTotalRoundsPlayed; int m_iUnBalancedRounds; // keeps track of the # of consecutive rounds that have gone by where one team outnumbers the other team by more than 2 bool m_endMatchOnRoundReset; bool m_endMatchOnThink; float m_flCoopRespawnAndHealTime; // GAME TIMES int m_iFreezeTime; // (From mp_freezetime) - How many seconds long the intro round (when players are frozen) is. int m_iNumTerrorist; // The number of terrorists on the team (this is generated at the end of a round) int m_iNumCT; // The number of CTs on the team (this is generated at the end of a round) int m_iNumSpawnableTerrorist; int m_iNumSpawnableCT; CUtlVector< int > m_arrSelectedHostageSpawnIndices; // The indices of hostage spawn locations selected for the match bool m_bFirstConnected; bool m_bCompleteReset; // Set to TRUE to have the scores reset next time round restarts bool m_bPickNewTeamsOnReset; bool m_bScrambleTeamsOnRestart; bool m_bSwapTeamsOnRestart; enum EEndMatchMapVoteState_t { k_EEndMatchMapVoteState_MatchInProgress, k_EEndMatchMapVoteState_VoteInProgress, k_EEndMatchMapVoteState_VoteTimeEnded, k_EEndMatchMapVoteState_AllPlayersVoted, k_EEndMatchMapVoteState_SelectingWinner, k_EEndMatchMapVoteState_SettingNextLevel, k_EEndMatchMapVoteState_VoteAllDone, }; #ifndef CLIENT_DLL EEndMatchMapVoteState_t m_eEndMatchMapVoteState; int m_nEndMatchMapVoteWinner; CUtlVector m_nEndMatchTiedVotes; void CreateEndMatchMapGroupVoteOptions( void ); enum EQueuedMatchmakingRematchState_t { k_EQueuedMatchmakingRematchState_MatchInProgress, k_EQueuedMatchmakingRematchState_VoteStarting, k_EQueuedMatchmakingRematchState_VoteToRematchInProgress, k_EQueuedMatchmakingRematchState_VoteToRematchSucceeded, k_EQueuedMatchmakingRematchState_VoteToRematchFailed, k_EQueuedMatchmakingRematchState_VoteToRematchFailed_Done, k_EQueuedMatchmakingRematchState_VoteToRematch_Done, k_EQueuedMatchmakingRematchState_VoteToRematch_T_Surrender, k_EQueuedMatchmakingRematchState_VoteToRematch_CT_Surrender, k_EQueuedMatchmakingRematchState_VoteToRematch_Aborted, }; EQueuedMatchmakingRematchState_t m_eQueuedMatchmakingRematchState; bool m_bNeedToAskPlayersForContinueVote; uint32 m_numQueuedMatchmakingAccounts; char *m_pQueuedMatchmakingReservationString; uint32 m_numTotalTournamentDrops; uint32 m_numSpectatorsCountMax; uint32 m_numSpectatorsCountMaxTV; uint32 m_numSpectatorsCountMaxLnk; CMsgGCCStrike15_v2_MatchmakingServerRoundStats *m_pQueuedMatchmakingReportedRoundStats; static CMsgGCCStrike15_v2_MatchmakingGC2ServerReserve sm_QueuedServerReservation; void ReportRoundEndStatsToGC( CMsgGCCStrike15_v2_MatchmakingServerRoundStats **ppAllocateStats = NULL ); struct CQMMPlayerData_t { CQMMPlayerData_t() { Q_memset( this, 0, offsetof( CQMMPlayerData_t, m_uiCustomNonPodFields ) ); } void Reset() { // Reset everything starting from m_numKills to the end Q_memset( ( ( char * ) this ) + offsetof( CQMMPlayerData_t, m_numKills ), 0, offsetof( CQMMPlayerData_t, m_uiCustomNonPodFields ) - offsetof( CQMMPlayerData_t, m_numKills ) ); } uint32 m_uiPlayerAccountId; // QMM player account ID int m_iDraftIndex; // Index of the player in the draft [0-4: team 1; 5-9: team 2] uint32 m_msDisconnectionTimestamp; // Timestamp of player's disconnection if not 0 uint32 m_uiAbandonRecordedReason; // We recorded the fact that the player abandoned the match and this is the reason bool m_bAbandonAllowsSurrender; // This player abandoning the match allows for his teammates to surrender char m_chPlayerName[128]; // Last known player name bool m_bEverFullyConnected; // Has this player ever connected to the server bool m_bDisconnection1MinWarningPrinted; // Whether 1 minute warning has been printed // RESETTABLE SECTION: int m_numKills; // number of kills int m_numAssists; // number of assists int m_numDeaths; // number of deaths int m_numScorePoints; // number of score points int m_numMVPs; // number of MVP rounds int m_cash; // player's cash int m_numTeamKills; // number of team kills int m_numTeamDamagePoints; // number of team damage points int m_numHostageKills; // number of hostages killed int m_numEnemyKills; // number of enemies killed int m_numEnemyKillHeadshots; // number of enemies killed with headshot int m_numEnemy3Ks; // number of 3Ks int m_numEnemy4Ks; // number of 4Ks int m_numEnemy5Ks; // number of 5Ks int m_numEnemyKillsAgg; // number of enemies killed on aggregate int m_numRoundsWon; // rounds won int m_numFirstKills; // number of times this player got first kill of the round int m_numClutchKills; // number of times this player got a kill with no teammates alive int m_numPistolKills; // number of pistol kills this player got int m_numSniperKills; // number of sniper kills this player got int m_numHealthPointsRemovedTotal; // total number of health points removed (used for coop gameplay) int m_numHealthPointsDealtTotal; // total number of health points dmg dealt to enemies (used for coop gameplay) int m_numShotsFiredTotal; // total number of shots fired (incremented by one every time player pulls trigger, not per each shotgun pellet; used for coop gameplay) int m_numShotsOnTargetTotal; // total number of shots on target (incremented by no moer than one per each time player pulls trigger, not per each shotgun pellet; used for coop gameplay) bool m_bReceiveNoMoneyNextRound; // player is marked to not receive any money next round // match stat data for the spectator graphs int m_iMatchStats_Kills[MAX_MATCH_STATS_ROUNDS]; int m_iMatchStats_Damage[MAX_MATCH_STATS_ROUNDS]; int m_iMatchStats_EquipmentValue[MAX_MATCH_STATS_ROUNDS]; int m_iMatchStats_MoneySaved[MAX_MATCH_STATS_ROUNDS]; int m_iMatchStats_KillReward[MAX_MATCH_STATS_ROUNDS]; int m_iMatchStats_LiveTime[MAX_MATCH_STATS_ROUNDS]; int m_iMatchStats_Deaths[ MAX_MATCH_STATS_ROUNDS ]; int m_iMatchStats_Assists[ MAX_MATCH_STATS_ROUNDS ]; int m_iMatchStats_HeadShotKills[ MAX_MATCH_STATS_ROUNDS ]; int m_iMatchStats_Objective[ MAX_MATCH_STATS_ROUNDS ]; int m_iMatchStats_CashEarned[ MAX_MATCH_STATS_ROUNDS ]; int m_iMatchStats_UtilityDamage[ MAX_MATCH_STATS_ROUNDS ]; int m_iMatchStats_EnemiesFlashed[ MAX_MATCH_STATS_ROUNDS ]; // per weapon kills uint32 m_uiCustomNonPodFields; // END RESETTABLE SECTION CUtlMap< uint32, uint32, int, CDefLess< uint32 > > m_mapQuestEventPoints; // TODO: If we have more attributes we want to be processed with the timed rewards job, try to generify this typedef CUtlMap< itemid_t, attrib_value_t, int, CDefLess< itemid_t > > StattrakMusicKitValues_t; StattrakMusicKitValues_t m_mapMusicKitUpdates; // once the player purchases an econ item, cache it and rebuy it from the cache. typedef CUtlMap< uint16, item_definition_index_t, int16, CDefLess< uint16 > > LoadoutSlotToDefIndexMap_t; LoadoutSlotToDefIndexMap_t m_mapLoadoutSlotToItem[ 2 ]; }; typedef CUtlMap< uint32, CQMMPlayerData_t *, int32, CDefLess< uint32 > > QueuedMatchmakingPlayersDataMap_t; QueuedMatchmakingPlayersDataMap_t m_mapQueuedMatchmakingPlayersData; CQMMPlayerData_t * QueuedMatchmakingPlayersDataFind( uint32 uiAccountID ) const { if ( !uiAccountID ) return NULL; QueuedMatchmakingPlayersDataMap_t::IndexType_t idx = m_mapQueuedMatchmakingPlayersData.Find( uiAccountID ); return ( idx == m_mapQueuedMatchmakingPlayersData.InvalidIndex() ) ? NULL : m_mapQueuedMatchmakingPlayersData.Element( idx ); } CQMMPlayerData_t * QueuedMatchmakingPlayersDataFindOrCreate( CCSPlayer *pPlayer ); struct CGcBanInformation_t { uint32 m_uiReason; double m_dblExpiration; }; typedef CUtlMap< uint32, CGcBanInformation_t > GcBanInformationMap_t; static GcBanInformationMap_t sm_mapGcBanInformation; bool m_bForceTeamChangeSilent; bool m_bLoadingRoundBackupData; class ICalculateEndOfRoundMVPHook_t { public: virtual CCSPlayer* CalculateEndOfRoundMVP() = 0; }; ICalculateEndOfRoundMVPHook_t *m_pfnCalculateEndOfRoundMVPHook; typedef CUtlMap< int32, uint32, int32, CDefLess< int32 > > MapMatchInfoShownCounts; MapMatchInfoShownCounts m_mapMatchInfoShownCounts; // tracks how many times each match info piece was shown enum MapMatchInfoShownCountsSpecial_t { k_MapMatchInfoShownCounts_None = 0xF0000, k_MapMatchInfoShownCounts_Predictions = 0xF0001, k_MapMatchInfoShownCounts_MapDraft = 0xF0002, }; int m_nMatchInfoShowType; // which match info is preferred to be shown float m_flMatchInfoDecidedTime; // what curtime moment was when match info was decided struct ServerPlayerDecalData_t { ServerPlayerDecalData_t() { V_memset( this, 0, sizeof(*this) ); } bool operator == ( ServerPlayerDecalData_t const &x ) const { return !V_memcmp( this, &x, offsetof( ServerPlayerDecalData_t, m_rtGcTime ) ); } AccountID_t m_unAccountID; int m_nTraceID; Vector m_vecOrigin; Vector m_vecStart; Vector m_vecRight; Vector m_vecNormal; int m_nEquipSlot; int m_nPlayer; int m_nEntity; int m_nHitbox; int m_nTintID; float m_flCreationTime; uint32 m_rtGcTime; // not participating in memcmp (set by GC, authoritative) void CopyToMsg( CCSUsrMsg_PlayerDecalDigitalSignature &msg ) const; void InitFromMsg( CCSUsrMsg_PlayerDecalDigitalSignature const &msg ); }; CUtlVector< ServerPlayerDecalData_t > m_arrServerPlayerDecalData; #endif int m_iAccountTerrorist; int m_iAccountCT; int m_iNumConsecutiveCTLoses; //SupraFiend: the number of rounds the CTs have lost in a row. int m_iNumConsecutiveTerroristLoses;//SupraFiend: the number of rounds the Terrorists have lost in a row. int m_iSpawnPointCount_Terrorist; // Number of Terrorist spawn points int m_iSpawnPointCount_CT; // Number of CT spawn points int m_iMaxNumTerrorists; int m_iMaxNumCTs; int m_iLoserBonus; // SupraFiend: the amount of money the losing team gets. This scales up as they lose more rounds in a row float m_tmNextPeriodicThink; bool m_bVoiceWonMatchBragFired; float m_fWarmupNextChatNoticeTime; CHandle m_pMVP; // HOSTAGE RESCUE VARIABLES int m_iHostagesRescued; int m_iHostagesTouched; float m_flNextHostageAnnouncement; // [tj] Accessor for weapons donation ability bool GetCanDonateWeapon( void ) { return m_bCanDonateWeapons; } // [tj] flawless and lossless round related flags bool m_bNoTerroristsKilled; bool m_bNoCTsKilled; bool m_bNoTerroristsDamaged; bool m_bNoCTsDamaged; bool m_bNoEnemiesKilled; // [tj] Find out if dropped weapons count as donations bool m_bCanDonateWeapons; // [tj] Keep track of first kill CHandle m_pFirstKill; float m_firstKillTime; // [menglish] Keep track of first blood CHandle m_pFirstBlood; float m_firstBloodTime; // [dwenger] Rescue-related achievement values CUtlVector< CHandle > m_arrRescuers; bool m_hostageWasInjured; bool m_hostageWasKilled; // [menglish] Fun Fact Manager CCSFunFactMgr *m_pFunFactManager; // Automatic vote called near the end of a map bool m_bVoteCalled; bool m_bServerVoteOnReset; float m_flVoteCheckThrottle; // [tj] To avoid rewriting the same piece of code, we can get all the information // we want from one call that fills in an array of structures. struct TeamPlayerCounts { int totalPlayers; int totalAlivePlayers; int totalDeadPlayers; //sum of killedPlayers + suicidedPlayers + unenteredPlayers int killedPlayers; int suicidedPlayers; int unenteredPlayers; }; void GetPlayerCounts( TeamPlayerCounts teamCounts[TEAM_MAXCOUNT] ); bool m_bBuyTimeEnded; int m_nLastFreezeEndBeep; // PRISON ESCAPE VARIABLES int m_iHaveEscaped; bool m_bMapHasEscapeZone; int m_iNumEscapers; int m_iNumEscapeRounds; // keeps track of the # of consecutive rounds of escape played.. Teams will be swapped after 8 rounds // BOMB MAP VARIABLES bool m_bTargetBombed; // whether or not the bomb has been bombed bool m_bBombDefused; // whether or not the bomb has been defused bool m_bMapHasBombZone; /* bool m_bBombPlanted;*/ bool m_bGunGameRespawnWithBomb; // Whether or not the next terrorist to spawn should have the bomb float m_fGunGameBombRespawnTimer; // Time until the bomb can be respawned void AddTeamAccount( int team, TeamCashAward::Type reason ); void AddTeamAccount( int team, TeamCashAward::Type reason, int amount, const char* szAwardText = NULL ); public: CBaseEntity* GetNextSpawnpoint( int teamNumber ); void DoCoopSpawnAndNavInit( void ); void AddSpawnPointToMasterList( SpawnPoint* pSpawnPoint ); void GenerateSpawnPointListsFirstTime( void ); void RefreshCurrentSpawnPointLists( void ); CCSMatch m_match; Vector m_vecMainCTSpawnPos; void ShuffleSpawnPointLists( void ); void ShuffleMasterSpawnPointLists( void ); void SortSpawnPointLists( void ); void SortMasterSpawnPointLists( void ); void ShufflePlayerList( CUtlVector< CCSPlayer* > &playersList ); protected: CUtlVector< SpawnPoint* > m_CTSpawnPointsMasterList; // The master list of CT spawn points (contains all points whether enabled or disabled) CUtlVector< SpawnPoint* > m_TerroristSpawnPointsMasterList; // The master list of Terrorist spawn points (contains all points whether enabled or disabled) int m_iNextCTSpawnPoint; // Used when picking the next CT spawn point to assign int m_iNextTerroristSpawnPoint; // Used when picking the next Terrorist spawn point to assign CUtlVector< SpawnPoint* > m_CTSpawnPoints; // List of CT spawn points sorted by their priorities CUtlVector< SpawnPoint* > m_TerroristSpawnPoints; // List of Terrorist spawn points sorted by their priorities private: float m_fAutobalanceDisplayTime; AutobalanceStatus::Type m_AutobalanceStatus; CRecipientFilter m_AutoBalanceTraitors; CRecipientFilter m_AutoBalanceLoyalists; // Don't allow switching weapons while gaining new technologies bool m_bAllowWeaponSwitch; bool m_bRoundTimeWarningTriggered; float m_phaseChangeAnnouncementTime; float m_fNextUpdateTeamClanNamesTime; float m_flLastThinkTime; CRecipientFilter m_filterTerrorist; CRecipientFilter m_filterCT; #endif // Methods & memeber variables on both client and server DLLs public: virtual bool ForceSplitScreenPlayersOnToSameTeam( void ); void UpdatePlayerEloBracket( CCSPlayer *pPlayer, int32 bracket ); bool IsSwitchingTeamsAtRoundReset( void ) { return m_bSwitchingTeamsAtRoundReset; } float CheckTotalSmokedLength( float flRadius, Vector vecGrenadePos, Vector from, Vector to ); protected: loadout_positions_t PickRandomWeaponForDMBonus( void ); void AssignStartingMoneyToAllPlayers( void ); void InitializeGameTypeAndMode( void ); bool m_bHasTriggeredRoundStartMusic; bool m_bHasTriggeredCoopSpawnReset; public: BotProfileDevice_t GetMatchDevice( void ) const { return ( BotProfileDevice_t )( m_MatchDevice.Get() ); } void AddDroppedWeaponToList( CWeaponCSBase *pWeapon ); void RemoveDroppedWeaponFromList( CWeaponCSBase *pWeapon ); int GetTotalDroppedWeaponsInWorld( void ) { return m_weaponsDroppedInWorld.Count(); } protected: void ProcessAutoBalance( void ); private: void UnfreezeAllPlayers( void ); bool m_bSwitchingTeamsAtRoundReset; int m_iMaxGunGameProgressiveWeaponIndex; CUtlVector< CHandle > m_weaponsDroppedInWorld; }; bool EconEntity_OnOwnerKillEaterEvent( CEconItemView *pEconItemView, CCSPlayer *pOwner, CCSPlayer *pVictim, kill_eater_event_t eEventType, int iAmount = 1, uint32 *pNewValue = NULL ); //----------------------------------------------------------------------------- // Gets us at the team fortress game rules //----------------------------------------------------------------------------- inline CCSGameRules* CSGameRules() { return static_cast(g_pGameRules); } #define IGNORE_SPECTATORS false #define IGNORE_UNASSIGNED true int UTIL_HumansInGame( bool ignoreSpectators = false, bool ignoreUnassigned = false ); int UTIL_SpectatorsInGame( void ); //----------------------------------------------------------------------------- // Music Selection //----------------------------------------------------------------------------- enum CsMusicType_t { CSMUSIC_NONE = 0, CSMUSIC_STARTGG, CSMUSIC_START, CSMUSIC_ACTION, CSMUSIC_DEATHCAM, CSMUSIC_BOMB, CSMUSIC_BOMBTEN, CSMUSIC_ROUNDTEN, CSMUSIC_WONROUND, CSMUSIC_LOSTROUND, CSMUSIC_HOSTAGE, CSMUSIC_MVP, CSMUSIC_SELECTION, CSMUSIC_HALFTIME }; #define CSMUSIC_NOPACK 0 #ifdef CLIENT_DLL void PlayMusicSelection( IRecipientFilter& filter, CsMusicType_t nMusicType , int nPlayerEntIndex = 0 , float flPreElapsedTime = 0.0 ); #endif //----------------------------------------------------------------------------- // Purpose: Useful utility functions //----------------------------------------------------------------------------- #ifdef CLIENT_DLL #else class CTFTeam; CTFTeam *GetOpposingTeam( CTeam *pTeam ); bool EntityPlacementTest( CBaseEntity *pMainEnt, const Vector &vOrigin, Vector &outPos, bool bDropToGround, unsigned int mask = MASK_SOLID, ITraceFilter *pFilter = NULL ); #endif // Assassination quest helper funcs bool IsAssassinationQuest( const CEconQuestDefinition *pQuest ); bool IsAssassinationQuest( uint32 questID ); bool IsAssassinationQuestActive( const CEconQuestDefinition *pQuest ); extern const float g_flWarmupToFreezetimeDelay; #endif // TF_GAMERULES_H