diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tf/tf_gamerules.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/shared/tf/tf_gamerules.h')
| -rw-r--r-- | game/shared/tf/tf_gamerules.h | 1841 |
1 files changed, 1841 insertions, 0 deletions
diff --git a/game/shared/tf/tf_gamerules.h b/game/shared/tf/tf_gamerules.h new file mode 100644 index 0000000..4a9678e --- /dev/null +++ b/game/shared/tf/tf_gamerules.h @@ -0,0 +1,1841 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: The TF Game rules object +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//============================================================================= + +#ifndef TF_GAMERULES_H +#define TF_GAMERULES_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "teamplayroundbased_gamerules.h" +#include "convar.h" +#include "gamevars_shared.h" +#include "GameEventListener.h" +#include "tf_gamestats_shared.h" +#include "tf_match_description.h" + +#ifdef CLIENT_DLL +#include "c_tf_player.h" +#else +#include "tf_player.h" +#endif + +#ifdef CLIENT_DLL + + #define CTFGameRules C_TFGameRules + #define CTFGameRulesProxy C_TFGameRulesProxy + #define CBonusRoundLogic C_BonusRoundLogic +#else + extern CUtlString s_strNextMvMPopFile; + + extern BOOL no_cease_fire_text; + extern BOOL cease_fire; + + class CHealthKit; + class CTrainingModeLogic; + class CTFHolidayEntity; + class CTFNavArea; + class CTFBot; + class CTFBotRoster; + class CMedievalLogic; + class CCPTimerLogic; + class CPopulationManager; + class CCompetitiveLogic; +#endif + +class CBonusRoundLogic; +class CTeamTrainWatcher; +class CPhysicsProp; +class CObjectSentrygun; +class CGhost; +class CUpgrades; + +extern ConVar tf_spec_xray; +extern ConVar tf_avoidteammates; +extern ConVar tf_avoidteammates_pushaway; +extern ConVar mp_tournament_blueteamname; +extern ConVar mp_tournament_redteamname; +extern ConVar tf_arena_force_class; +extern ConVar tf_arena_change_limit; +extern ConVar tf_ctf_bonus_time; +extern ConVar tf_mvm_respec_enabled; +extern ConVar tf_spawn_glows_duration; +#ifdef TF_RAID_MODE + +class CRaidLogic; +class CBossBattleLogic; + +extern ConVar tf_gamemode_raid; +extern ConVar tf_gamemode_creep_wave; +extern ConVar tf_gamemode_boss_battle; + +#endif // TF_RAID_MODE + +class CMannVsMachineLogic; +class CMannVsMachineUpgrades; + +//extern ConVar tf_populator_health_multiplier; +//extern ConVar tf_populator_damage_multiplier; + +const int kMVM_DefendersTeamSize = 6; +const int kLadder_TeamSize_6v6 = 6; +const int kLadder_TeamSize_9v9 = 9; +const int kLadder_TeamSize_12v12 = 12; + +//#define TF_MVM_FCVAR_CHEAT 0 /* Cheats enabled */ +#define TF_MVM_FCVAR_CHEAT FCVAR_CHEAT /* Cheats disabled */ + +extern bool TF_IsHolidayActive( /*EHoliday*/ int eHoliday ); + +//============================================================================= +// HPE_BEGIN +// [msmith] Used for the client to tell the server that we're whatching a movie or not +// and weather or not we're ready to transition to the next map. +//============================================================================= +// Training mode cvars +extern ConVar tf_training_client_message; +enum { + TRAINING_CLIENT_MESSAGE_NONE = 0, + TRAINING_CLIENT_MESSAGE_WATCHING_INTRO_MOVIE, + TRAINING_CLIENT_MESSAGE_IN_SUMMARY_SCREEN, + TRAINING_CLIENT_MESSAGE_NEXT_MAP, + TRAINING_CLIENT_MESSAGE_REPLAY, + TRAINING_CLIENT_MESSAGE_MAX, +}; + +// How many achievements we show in the summary screen. +#define MAX_SHOWN_ACHIEVEMENTS 6 +//============================================================================= +// HPE_END +//============================================================================= + + +extern Vector g_TFClassViewVectors[]; + +#define NO_CLASS_LIMIT -1 + +enum { + STOPWATCH_CAPTURE_TIME_NOT_SET = 0, + STOPWATCH_RUNNING, + STOPWATCH_OVERTIME, +}; + +class CTFGameRulesProxy : public CTeamplayRoundBasedRulesProxy, public CGameEventListener +{ +public: + DECLARE_CLASS( CTFGameRulesProxy, CTeamplayRoundBasedRulesProxy ); + DECLARE_NETWORKCLASS(); + +#ifdef GAME_DLL + DECLARE_DATADESC(); + + CTFGameRulesProxy(); + + void InputSetRedTeamRespawnWaveTime( inputdata_t &inputdata ); + void InputSetBlueTeamRespawnWaveTime( inputdata_t &inputdata ); + void InputAddRedTeamRespawnWaveTime( inputdata_t &inputdata ); + void InputAddBlueTeamRespawnWaveTime( inputdata_t &inputdata ); + void InputSetRedTeamGoalString( inputdata_t &inputdata ); + void InputSetBlueTeamGoalString( inputdata_t &inputdata ); + void InputSetRedTeamRole( inputdata_t &inputdata ); + void InputSetBlueTeamRole( inputdata_t &inputdata ); + void InputSetRequiredObserverTarget( inputdata_t &inputdata ); + void InputAddRedTeamScore( inputdata_t &inputdata ); + void InputAddBlueTeamScore( inputdata_t &inputdata ); + void InputSetRedKothClockActive( inputdata_t &inputdata ); + void InputSetBlueKothClockActive( inputdata_t &inputdata ); + void InputSetCTFCaptureBonusTime( inputdata_t &inputdata ); + void InputPlayVORed( inputdata_t &inputdata ); + void InputPlayVOBlue( inputdata_t &inputdata ); + void InputPlayVO( inputdata_t &inputdata ); + void InputHandleMapEvent( inputdata_t &inputdata ); + void InputSetCustomUpgradesFile( inputdata_t &inputdata ); + void InputSetRoundRespawnFreezeEnabled( inputdata_t &inputdata ); + void InputSetMapForcedTruceDuringBossFight( inputdata_t &inputdata ); + + void TeamPlayerCountChanged( CTFTeam *pTeam ); + void PowerupTeamImbalance( int nTeam ); + void StateEnterRoundRunning( void ); + void StateEnterBetweenRounds( void ); + void StateEnterPreRound( void ); + void StateExitPreRound( void ); + void MatchSummaryStart( void ); + void TruceStart( void ); + void TruceEnd( void ); + + COutputEvent m_OnWonByTeam1; + COutputEvent m_OnWonByTeam2; + COutputInt m_Team1PlayersChanged; + COutputInt m_Team2PlayersChanged; + COutputEvent m_OnPowerupImbalanceTeam1; + COutputEvent m_OnPowerupImbalanceTeam2; + COutputEvent m_OnPowerupImbalanceMeasuresOver; + COutputEvent m_OnStateEnterRoundRunning; + COutputEvent m_OnStateEnterBetweenRounds; + COutputEvent m_OnStateEnterPreRound; + COutputEvent m_OnStateExitPreRound; + COutputEvent m_OnMatchSummaryStart; + COutputEvent m_OnTruceStart; + COutputEvent m_OnTruceEnd; + + virtual void Activate(); + +private: + +//============================================================================= +// HPE_BEGIN: +// [msmith] hud type so the game type and hud type can be separate. Used for +// training missions. +//============================================================================= + int m_nHudType; +//============================================================================= +// HPE_END +//============================================================================= + + + bool m_bOvertimeAllowedForCTF; +#endif + +public: // IGameEventListener Interface + virtual void FireGameEvent( IGameEvent * event ); +}; + +class CTFRadiusDamageInfo +{ + DECLARE_CLASS_NOBASE( CTFRadiusDamageInfo ); +public: + CTFRadiusDamageInfo( CTakeDamageInfo *pInfo, const Vector &vecSrcIn, float flRadiusIn, CBaseEntity *pIgnore = NULL, float flRJRadiusIn = 0, float flForceScaleIn = 1.0f ) + { + dmgInfo = pInfo; + vecSrc = vecSrcIn; + flRadius = flRadiusIn; + pEntityIgnore = pIgnore; + flRJRadius = flRJRadiusIn; + flFalloff = 0; + m_flForceScale = flForceScaleIn; + m_pEntityTarget = NULL; + + CalculateFalloff(); + } + + void CalculateFalloff( void ); + int ApplyToEntity( CBaseEntity *pEntity ); + +public: + // Fill these in & call RadiusDamage() + CTakeDamageInfo *dmgInfo; + Vector vecSrc; + float flRadius; + CBaseEntity *pEntityIgnore; + float flRJRadius; // Radius to use to calculate RJ, to maintain RJs when damage/radius changes on a RL + float m_flForceScale; + CBaseEntity *m_pEntityTarget; // Target being direct hit if any +private: + // These are used during the application of the RadiusDamage + float flFalloff; +}; + +struct PlayerRoundScore_t +{ + int iPlayerIndex; // player index + int iRoundScore; // how many points scored this round + int iTotalScore; // total points scored across all rounds +}; + +struct PlayerArenaRoundScore_t +{ + int iPlayerIndex; // player index + int iTotalDamage; // damage done this round + int iTotalHealing; // healing done this round + int iTimeAlive; // time alive (in seconds) + int iKillingBlows; // killing blows this round + int iScore; +}; + +#ifdef CLIENT_DLL +const char *GetMapType( const char *mapName ); +const char *GetMapDisplayName( const char *mapName ); +#else + +class CKothLogic; + +#endif + +// Used to sort the players in the list by their bonus score +typedef CTFPlayer *BONUSPLAYERPTR; +class CBonusPlayerListLess +{ +public: + bool Less( const BONUSPLAYERPTR &src1, const BONUSPLAYERPTR &src2, void *pCtx ) + { + if ( src1->m_Shared.GetItemFindBonus() > src2->m_Shared.GetItemFindBonus() ) + return true; + return false; + } +}; + +#define MAX_TEAMGOAL_STRING 256 +#define MAX_TEAMNAME_STRING 6 + +class CTFGameRules : public CTeamplayRoundBasedRules +{ +public: + DECLARE_CLASS( CTFGameRules, CTeamplayRoundBasedRules ); + + CTFGameRules(); + + virtual void LevelInitPostEntity( void ); + virtual float GetRespawnTimeScalar( int iTeam ); + virtual float GetRespawnWaveMaxLength( int iTeam, bool bScaleWithNumPlayers = true ); + + // Damage Queries. + virtual bool Damage_IsTimeBased( int iDmgType ); // Damage types that are time-based. + virtual bool Damage_ShowOnHUD( int iDmgType ); // Damage types that have client HUD art. + virtual bool Damage_ShouldNotBleed( int iDmgType ); // Damage types that don't make the player bleed. + // TEMP: + virtual int Damage_GetTimeBased( void ); + virtual int Damage_GetShowOnHud( void ); + virtual int Damage_GetShouldNotBleed( void ); + + int GetFarthestOwnedControlPoint( int iTeam, bool bWithSpawnpoints ); + virtual bool TeamMayCapturePoint( int iTeam, int iPointIndex ); + virtual bool PlayerMayCapturePoint( CBasePlayer *pPlayer, int iPointIndex, char *pszReason = NULL, int iMaxReasonLength = 0 ); + virtual bool PlayerMayBlockPoint( CBasePlayer *pPlayer, int iPointIndex, char *pszReason = NULL, int iMaxReasonLength = 0 ); + + static int CalcPlayerScore( RoundStats_t *pRoundStats, CTFPlayer *pPlayer ); + static int CalcPlayerSupportScore( RoundStats_t *pRoundStats, int iPlayerIdx ); + + bool IsBirthday( void ) const; + bool IsBirthdayOrPyroVision( void ) const; + virtual bool IsHolidayActive( /*EHoliday*/ int eHoliday ) const; + + virtual const unsigned char *GetEncryptionKey( void ) { return GetTFEncryptionKey(); } + + int GetClassLimit( int iClass ); + bool CanPlayerChooseClass( CBasePlayer *pPlayer, int iClass ); + + virtual bool ShouldBalanceTeams( void ); + + virtual int GetBonusRoundTime( bool bGameOver = false ) OVERRIDE; + +#ifdef GAME_DLL +public: + virtual void Precache( void ); + + // Override this to prevent removal of game specific entities that need to persist + virtual bool RoundCleanupShouldIgnore( CBaseEntity *pEnt ); + virtual bool ShouldCreateEntity( const char *pszClassName ); + virtual void CleanUpMap( void ); + + virtual void FrameUpdatePostEntityThink(); + + virtual void RespawnPlayers( bool bForceRespawn, bool bTeam = false, int iTeam = TEAM_UNASSIGNED ) OVERRIDE; + + // Called when a new round is being initialized + virtual void SetupOnRoundStart( void ); + + // Called when a new round is off and running + virtual void SetupOnRoundRunning( void ); + + // Called before a new round is started (so the previous round can end) + virtual void PreviousRoundEnd( void ); + + // Send the team scores down to the client + virtual void SendTeamScoresEvent( void ) { return; } + + // Send the end of round info displayed in the win panel + virtual void SendWinPanelInfo( bool bGameOver ) OVERRIDE; + void SendArenaWinPanelInfo( void ); + void SendPVEWinPanelInfo( void ); + + // Setup spawn points for the current round before it starts + virtual void SetupSpawnPointsForRound( void ); + + // Called when a round has entered stalemate mode (timer has run out) + virtual void SetupOnStalemateStart( void ); + virtual void SetupOnStalemateEnd( void ); + + virtual void RecalculateControlPointState( void ); + + void TeamPlayerCountChanged( CTFTeam *pTeam ); + void PowerupTeamImbalance( int nTeam ); + int GetAssignedHumanTeam( void ); + virtual void HandleSwitchTeams( void ); + virtual void HandleScrambleTeams( void ); + bool CanChangeClassInStalemate( void ); + bool CanChangeTeam( int iCurrentTeam ) const; + + virtual void SetRoundOverlayDetails( void ); + virtual void ShowRoundInfoPanel( CTFPlayer *pPlayer = NULL ); // NULL pPlayer means show the panel to everyone + + virtual bool TimerMayExpire( void ); + + virtual void Activate(); + + virtual bool AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ); + + void SetTeamGoalString( int iTeam, const char *pszGoal ); +//============================================================================= +// HPE_BEGIN: +// [msmith] Added a HUD type separate from the game mode so we can do different +// HUDs for the same mode. This is used in training maps. +//============================================================================= + void SetHUDType( int nHudType ); +//============================================================================= +// HPE_END +//============================================================================= + + // Speaking, vcds, voice commands. + virtual void InitCustomResponseRulesDicts(); + virtual void ShutdownCustomResponseRulesDicts(); + + virtual bool HasPassedMinRespawnTime( CBasePlayer *pPlayer ); + virtual bool ShouldRespawnQuickly( CBasePlayer *pPlayer ); + + bool ShouldScorePerRound( void ); + + virtual bool IsValveMap( void ); + + virtual void PlayTrainCaptureAlert( CTeamControlPoint *pPoint, bool bFinalPointInMap ); + + void SetRequiredObserverTarget( CBaseEntity *pEnt ){ m_hRequiredObserverTarget = pEnt; } + void SetObjectiveObserverTarget( CBaseEntity *pEnt ) { m_hObjectiveObserverTarget = pEnt; } + EHANDLE GetRequiredObserverTarget( void ){ return m_hRequiredObserverTarget.Get(); } + EHANDLE GetObjectiveObserverTarget( void ){ return m_hObjectiveObserverTarget.Get(); } + + virtual void GetTaggedConVarList( KeyValues *pCvarTagList ); + + virtual bool PointsMayBeCaptured( void ); + virtual bool PointsMayAlwaysBeBlocked(){ return ( GetGameType() == TF_GAMETYPE_ESCORT ); } + + virtual void PlaySpecialCapSounds( int iCappingTeam, CTeamControlPoint *pPoint ); + + virtual CTacticalMissionManager *TacticalMissionManagerFactory( void ); + + virtual bool ShouldSwitchTeams( void ); + virtual bool ShouldScrambleTeams( void ); + + virtual void ClientCommandKeyValues( edict_t *pEntity, KeyValues *pKeyValues ); + + bool CanBotChangeClass( CBasePlayer* pPlayer ); + bool CanBotChooseClass( CBasePlayer *pPlayer, int iClass ); + + void SetCTFCaptureBonusTime( float flTime ){ m_flCTFCaptureBonusTime = flTime; } + float GetCTFCaptureBonusTime( void ) + { + float flRetVal = tf_ctf_bonus_time.GetFloat(); + if ( m_flCTFCaptureBonusTime >= 0.0f ) + { + flRetVal = m_flCTFCaptureBonusTime; + } + + return flRetVal; + } + + // populate vector with set of control points the player needs to capture + virtual void CollectCapturePoints( CBasePlayer *player, CUtlVector< CTeamControlPoint * > *captureVector ) const; + + // populate vector with set of control points the player needs to defend from capture + virtual void CollectDefendPoints( CBasePlayer *player, CUtlVector< CTeamControlPoint * > *defendVector ) const; + + CObjectSentrygun *FindSentryGunWithMostKills( int team = TEAM_ANY ) const; + + // Client connection/disconnection + virtual bool ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); + + virtual bool ShouldSkipAutoScramble( void ) + { + return IsPVEModeActive(); + } + + bool ShouldMakeChristmasAmmoPack( void ); + + void UpdatePeriodicEvent( CTFPlayer *pPlayer, eEconPeriodicScoreEvents eEvent, uint32 nCount ); + + void HandleMapEvent( inputdata_t &inputdata ); + + void SetCustomUpgradesFile( inputdata_t &inputdata ); + + virtual bool ShouldWaitToStartRecording( void ); + + void SetGravityMultiplier( float flValue ){ m_flGravityMultiplier.Set( flValue ); } + + bool CanFlagBeCaptured( CBaseEntity *pOther ); + bool PowerupModeFlagStandoffActive( void ); + + void TeleportPlayersToTargetEntities( int iTeam, const char *pszEntTargetName, CUtlVector< CTFPlayer * > *pTeleportedPlayers ); + + virtual void LoadMapCycleFileIntoVector ( const char *pszMapCycleFile, CUtlVector<char *> &mapList ) OVERRIDE; + + void OnWorkshopMapUpdated( PublishedFileId_t nWorkshopID ); + + void RecalculateTruce( void ); + + void SetMapForcedTruceDuringBossFight( bool bState ){ m_bMapForcedTruceDuringBossFight = bState; } + bool IsMapForcedTruceDuringBossFight( void ){ return m_bMapForcedTruceDuringBossFight; } + +protected: + virtual void LoadMapCycleFile( void ) OVERRIDE; + void TrackWorkshopMapsInMapCycle( void ); + + virtual const char* GetStalemateSong( int nTeam ) OVERRIDE; + virtual const char* WinSongName( int nTeam ) OVERRIDE; + virtual const char* LoseSongName( int nTeam ) OVERRIDE; + + virtual void InitTeams( void ); + + virtual void RoundRespawn( void ); + virtual void RespawnTeam( int iTeam ); + + virtual void InternalHandleTeamWin( int iWinningTeam ); + + static int PlayerRoundScoreSortFunc( const PlayerRoundScore_t *pRoundScore1, const PlayerRoundScore_t *pRoundScore2 ); + static int PlayerArenaRoundScoreSortFunc( const PlayerArenaRoundScore_t *pRoundScore1, const PlayerArenaRoundScore_t *pRoundScore2 ); + + virtual void FillOutTeamplayRoundWinEvent( IGameEvent *event ); + + virtual bool CanChangelevelBecauseOfTimeLimit( void ); + virtual bool CanGoToStalemate( void ); + + virtual void RestoreActiveTimer( void ); + + void BroadcastDrawLine( CTFPlayer *pTFPlayer, KeyValues *pKeyValues ); + +#endif // GAME_DLL + +public: + // Bonus round handling +#ifdef GAME_DLL + virtual bool ShouldGoToBonusRound( void ); + virtual void SetupOnBonusStart( void ); + virtual void SetupOnBonusEnd( void ); + virtual void BonusStateThink( void ); + void BonusStateAbort( void ); + void SetBonusItem( itemid_t iItemID ); + + // Between rounds handling + virtual void BetweenRounds_Start( void ); + virtual void BetweenRounds_End( void ); + virtual void BetweenRounds_Think( void ); + virtual void PreRound_Start( void ) OVERRIDE; + virtual void PreRound_End( void ) OVERRIDE; +#endif + +public: + // Return the value of this player towards capturing a point + virtual int GetCaptureValueForPlayer( CBasePlayer *pPlayer ); + + // Collision and Damage rules. + virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 ); + + int GetTimeLeft( void ); + + // Get the view vectors for this mod. + virtual const CViewVectors *GetViewVectors() const; + + virtual void FireGameEvent( IGameEvent *event ); + + virtual const char *GetGameTypeName( void ); + virtual int GetGameType( void ){ return m_nGameType; } + + virtual void ClientSpawned( edict_t * pPlayer ); + + virtual void OnFileReceived( const char * fileName, unsigned int transferID ); + + virtual bool FlagsMayBeCapped( void ); + + void RunPlayerConditionThink ( void ); + + const char *GetTeamGoalString( int iTeam ); + + int GetStopWatchState( void ) { return m_nStopWatchState; } + + // Game Modes + virtual bool IsInArenaMode( void ) const OVERRIDE; + virtual bool IsInKothMode( void ) const OVERRIDE { return m_bPlayingKoth; } + bool IsInMedievalMode( void ) const { return m_bPlayingMedieval; } + bool IsHolidayMap( int nHoliday ) const { return m_nMapHolidayType == nHoliday; } + +#ifdef TF_RAID_MODE + bool IsRaidMode( void ) const; + bool IsBossBattleMode( void ) const; +#endif // TF_RAID_MODE + +#ifdef TF_CREEP_MODE +bool IsCreepWaveMode( void ) const; +#endif + + bool IsMannVsMachineMode( void ) const { return m_bPlayingMannVsMachine; } + + void SetMannVsMachineAlarmStatus( bool bStatus ){ m_bMannVsMachineAlarmStatus.Set( bStatus ); } + bool GetMannVsMachineAlarmStatus( void ){ return m_bMannVsMachineAlarmStatus; } + + bool IsQuickBuildTime( void ); + + bool GameModeUsesUpgrades( void ); + bool GameModeUsesCurrency( void ) { return IsMannVsMachineMode() || IsBountyMode(); } + bool GameModeUsesMiniBosses( void ) { return IsMannVsMachineMode() || IsBountyMode(); } + + bool IsPasstimeMode() const { return m_nGameType == TF_GAMETYPE_PASSTIME; } + +#ifdef STAGING_ONLY + bool GameModeUsesExperience( void ) { return IsBountyMode(); } +#endif // STAGING_ONLY + bool IsMannVsMachineRespecEnabled( void ) { return IsMannVsMachineMode() && tf_mvm_respec_enabled.GetBool(); } + bool CanPlayerUseRespec( CTFPlayer *pTFPlayer ); + bool IsPowerupMode( void ) { return m_bPowerupMode; } + void SetPowerupMode( bool bValue ); + +#ifdef GAME_DLL + // Managed competitive matches should go through the End/StopCompetitiveMatch path + void EndManagedMvMMatch( bool bKickPlayersToParties ); +#endif + + // Competitive games + bool IsCompetitiveMode( void ) const; // means we're using competitive/casual matchmaking + bool IsMatchTypeCasual( void ) const; + bool IsMatchTypeCompetitive( void ) const; + // Are we showing the match-start-countdown doors right now + bool BInMatchStartCountdown() const; +#ifdef GAME_DLL + void SyncMatchSettings(); + // ! Check return + bool StartManagedMatch(); + void SetCompetitiveMode( bool bValue ); +#endif + void StartCompetitiveMatch( void ); + void StopCompetitiveMatch( CMsgGC_Match_Result_Status nCode ); + void EndCompetitiveMatch( void ); + void ManageCompetitiveMode( void ); + bool ReportMatchResultsToGC( CMsgGC_Match_Result_Status nCode ); + bool MatchmakingShouldUseStopwatchMode(); + + EMatchGroup GetCurrentMatchGroup() const; + bool IsManagedMatchEnded() const; + + bool UsePlayerReadyStatusMode( void ); + bool PlayerReadyStatus_HaveMinPlayersToEnable( void ); +#ifdef GAME_DLL + bool PlayerReadyStatus_ArePlayersOnTeamReady( int iTeam ); + bool PlayerReadyStatus_ShouldStartCountdown( void ); + void PlayerReadyStatus_ResetState( void ); + void PlayerReadyStatus_UpdatePlayerState( CTFPlayer *pTFPlayer, bool bState ); +#endif // GAME_DLL + + bool IsDefaultGameMode( void ); // The absence of arena, mvm, tournament mode, etc + + // Upgrades + int GetCostForUpgrade( CMannVsMachineUpgrades *pUpgrade, int iItemSlot, int nClass, CTFPlayer *pPurchaser = NULL ); + bool CanUpgradeWithAttrib( CTFPlayer *pPlayer, int iWeaponSlot, attrib_definition_index_t iAttribIndex, CMannVsMachineUpgrades *pUpgrade ); + int GetUpgradeTier( int iUpgrade ); + bool IsUpgradeTierEnabled( CTFPlayer *pTFPlayer, int iItemSlot, int iUpgrade ); + bool IsPVEModeActive( void ) const; // return true if we are playing a PvE mode + bool IsPVEModeControlled( CBaseEntity *who ) const; // return true for PvE opponents (ie: enemy bot team) + const char* GetCustomUpgradesFile() { return m_pszCustomUpgradesFile.Get(); } + +//============================================================================= +// HPE_BEGIN: +// [msmith] Training Status. And HUD type. +//============================================================================= + bool IsInTraining( void ){ return m_bIsInTraining; } + bool AllowTrainingAchievements() { return m_bAllowTrainingAchievements; } + void SetAllowTrainingAchievements( bool bAllow) { m_bAllowTrainingAchievements = bAllow; } + bool IsWaitingForTrainingContinue() { return m_bIsWaitingForTrainingContinue; } + void SetIsWaitingForTrainingContinue( bool bWaiting ) { m_bIsWaitingForTrainingContinue = bWaiting; } + int GetHUDType( void ){ return m_nHudType; } +//============================================================================= +// HPE_END +//============================================================================= + bool IsTrainingHUDVisible( void ) { return IsInTraining() && m_bIsTrainingHUDVisible; } + void SetTrainingHUDVisible( bool bVisible ) { m_bIsTrainingHUDVisible.Set( bVisible ); } + + virtual bool IsInItemTestingMode( void ) { return m_bIsInItemTestingMode; } + void SetInItemTestingMode( bool bInTesting ) { m_bIsInItemTestingMode.Set( bInTesting ); } + int ItemTesting_GetBotAnim( void ) { return m_iItemTesting_BotAnim; } + float ItemTesting_GetBotAnimSpeed( void ); + bool ItemTesting_GetBotForceFire( void ) { return m_bItemTesting_BotForceFire; } + bool ItemTesting_GetBotTurntable( void ) { return m_bItemTesting_BotTurntable; } + bool ItemTesting_GetBotViewScan( void ) { return m_bItemTesting_BotViewScan; } + void ItemTesting_SetupFromKV( KeyValues *pKV ); + + bool IsPlayingHybrid_CTF_CP( void ) const { return m_bPlayingHybrid_CTF_CP; } + bool IsPlayingSpecialDeliveryMode( void ) const { return m_bPlayingSpecialDeliveryMode; } + bool IsPlayingRobotDestructionMode( void ) const { return m_bPlayingRobotDestructionMode; } + + virtual bool AllowThirdPersonCamera( void ) { return ( IsInMedievalMode() || ShowMatchSummary() ); } + + // Bonus rounds + CBonusRoundLogic *GetBonusLogic( void ) { return m_hBonusLogic.Get(); } + void BuildBonusPlayerList( void ); + + CTeamRoundTimer *GetRedKothRoundTimer( void ) { return m_hRedKothTimer.Get(); } + CTeamRoundTimer *GetBlueKothRoundTimer( void ) { return m_hBlueKothTimer.Get(); } + + int GetStatsMinimumPlayers( void ); + int GetStatsMinimumPlayedTime( void ); + + // BountyMode +#ifdef STAGING_ONLY + bool IsBountyMode( void ) { return m_bBountyModeEnabled && !IsMannVsMachineMode() && !IsInTraining(); } +#else + bool IsBountyMode( void ) { return false; } +#endif + + float GetGravityMultiplier( void ){ return m_flGravityMultiplier; } + + virtual bool IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ); + + void SetPlayersInHell( bool bState ){ m_bHelltowerPlayersInHell.Set( bState ); } // used for Halloween 2013 state of the game (players in the underworld fighting) + bool ArePlayersInHell( void ) const { return m_bHelltowerPlayersInHell; } + void SpawnPlayerInHell( CTFPlayer *pPlayer, const char *pszSpawnPointName ); + + // Halloween 2013 + void PlayHelltowerAnnouncerVO( int iRedLine, int iBlueLine ); + + void SetUsingSpells( bool bState ) + { + m_bIsUsingSpells.Set( bState ); + } + + bool IsUsingSpells( void ) const; + bool IsUsingGrapplingHook( void ) const; + + bool IsTruceActive( void ) const; + + bool MapHasMatchSummaryStage( void ){ return m_bMapHasMatchSummaryStage; } + bool PlayersAreOnMatchSummaryStage( void ){ return m_bPlayersAreOnMatchSummaryStage; } + + bool ShowMatchSummary( void ){ return m_bShowMatchSummary; } + + bool HaveStopWatchWinner( void ) { return m_bStopWatchWinner; } + + int GetGameTeamForGCTeam( TF_GC_TEAM nGCTeam ); + TF_GC_TEAM GetGCTeamForGameTeam( int nGameTeam ); + + enum ENextMapVotingState + { + NEXT_MAP_VOTE_STATE_NONE, + NEXT_MAP_VOTE_STATE_WAITING_FOR_USERS_TO_VOTE, + NEXT_MAP_VOTE_STATE_MAP_CHOSEN_PAUSE, + }; + + enum EUserNextMapVote + { + USER_NEXT_MAP_VOTE_MAP_0 = 0, + USER_NEXT_MAP_VOTE_MAP_1, + USER_NEXT_MAP_VOTE_MAP_2, + USER_NEXT_MAP_VOTE_UNDECIDED, + + NUM_VOTE_STATES + }; + + EUserNextMapVote GetWinningVote( int (&nVotes)[ EUserNextMapVote::NUM_VOTE_STATES ] ) const; + EUserNextMapVote PlayerNextMapVoteState( int nIndex ) const { return m_ePlayerWantsRematch.Get( nIndex ); } + ENextMapVotingState GetCurrentNextMapVotingState() const { return m_eRematchState; } + MapDefIndex_t GetNextMapVoteOption( int nIndex ) const { return m_nNextMapVoteOptions.Get( nIndex ); } + +#ifdef GAME_DLL + void UpdateNextMapVoteOptionsFromLobby(); + void KickPlayersNewMatchIDRequestFailed(); + + void CheckAndSetPartyLeader( CTFPlayer *pTFPlayer, int iTeam ); +#endif // GAME_DLL + +#ifdef STAGING_ONLY +#ifdef GAME_DLL + void SetBountyMode( bool bValue ); +#endif // GAME_DLL + +#endif // STAGING_ONLY + +#ifdef CLIENT_DLL + + DECLARE_CLIENTCLASS_NOBASE(); // This makes data tables able to access our private vars. + + virtual ~CTFGameRules(); + + virtual void OnDataChanged( DataUpdateType_t updateType ); + virtual void HandleOvertimeBegin(); + + bool ShouldShowTeamGoal( void ); + + const char *GetVideoFileForMap( bool bWithExtension = true ); + + const char *FormatVideoName( const char *videoName, bool bWithExtension = true ); + + void SetUpVisionFilterKeyValues( void ); + + bool UseSillyGibs( void ); + + virtual bool AllowMapParticleEffect( const char *pszParticleEffect ); + + virtual bool AllowWeatherParticles( void ); + + virtual bool AllowMapVisionFilterShaders( void ); + virtual const char* TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName ); + + virtual void ModifySentChat( char *pBuf, int iBufSize ); + + virtual void GetTeamGlowColor( int nTeam, float &r, float &g, float &b ); + + virtual bool ShouldConfirmOnDisconnect(); + + bool ShouldShowPreRoundDoors() const; + bool RecievedBaseline() const { return m_bRecievedBaseline; } + +#else + + DECLARE_SERVERCLASS_NOBASE(); // This makes data tables able to access our private vars. + + virtual ~CTFGameRules(); + + virtual void LevelShutdown(); + virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); + virtual void Think(); + + void PeriodicHalloweenUpdate(); + + virtual bool SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); + + bool CheckWinLimit( bool bAllowEnd = true, int nAddValueWhenChecking = 0 ) OVERRIDE; + bool SetCtfWinningTeam(); + bool SetPasstimeWinningTeam(); + bool CheckCapsPerRound(); + virtual void CheckRespawnWaves(); + virtual void PlayWinSong( int team ) OVERRIDE; + +//============================================================================= +// HPE_BEGIN: +// [msmith] Used in training to load the next training map in sequence. +//============================================================================= + void LoadNextTrainingMap(); +//============================================================================= +// HPE_END +//============================================================================= + + virtual void SetWinningTeam( int team, int iWinReason, bool bForceMapReset = true, bool bSwitchTeams = false, bool bDontAddScore = false, bool bFinal = false ) OVERRIDE; + virtual void SetStalemate( int iReason, bool bForceMapReset = true, bool bSwitchTeams = false ); + + void CheckTauntAchievement( CTFPlayer *pAchiever, int nGibs, int *pTauntCamAchievements ); + + virtual bool FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker, const CTakeDamageInfo &info ); + + // Spawing rules. + CBaseEntity *GetPlayerSpawnSpot( CBasePlayer *pPlayer ); + bool IsSpawnPointValid( CBaseEntity *pSpot, CBasePlayer *pPlayer, bool bIgnorePlayers, PlayerTeamSpawnMode_t nSpawndMode = PlayerTeamSpawnMode_Normal ); + + virtual int ItemShouldRespawn( CItem *pItem ); + virtual float FlItemRespawnTime( CItem *pItem ); + virtual Vector VecItemRespawnSpot( CItem *pItem ); + virtual QAngle VecItemRespawnAngles( CItem *pItem ); + + virtual const char *GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ); + void ClientSettingsChanged( CBasePlayer *pPlayer ); + void ChangePlayerName( CTFPlayer *pPlayer, const char *pszNewName ); + + virtual VoiceCommandMenuItem_t *VoiceCommand( CBaseMultiplayerPlayer *pPlayer, int iMenu, int iItem ); + + float GetPreMatchEndTime() const; // Returns the time at which the prematch will be over. + void GoToIntermission( void ); + + virtual int GetAutoAimMode() { return AUTOAIM_NONE; } + void SetSetup( bool bSetup ); + void ManageStopwatchTimer( bool bInSetup ); + virtual void HandleTeamScoreModify( int iTeam, int iScore); + + bool CanHaveAmmo( CBaseCombatCharacter *pPlayer, int iAmmoIndex ); + + virtual const char *GetGameDescription( void ){ return "Team Fortress"; } + + virtual void Status( void (*print) (PRINTF_FORMAT_STRING const char *fmt, ...) ); + + // Sets up g_pPlayerResource. + virtual void CreateStandardEntities(); + + virtual void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); + virtual void PlayerKilledCheckAchievements( CTFPlayer *pAttacker, CTFPlayer *pVictim ); + virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ); + virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info, const char* eventName ); + virtual CBasePlayer *GetDeathScorer( CBaseEntity *pKiller, CBaseEntity *pInflictor, CBaseEntity *pVictim ); + + void CalcDominationAndRevenge( CTFPlayer *pAttacker, CBaseEntity *pWeapon, CTFPlayer *pVictim, bool bIsAssist, int *piDeathFlags ); + + const char *GetKillingWeaponName( const CTakeDamageInfo &info, CTFPlayer *pVictim, int *iWeaponID ); + CBasePlayer *GetAssister( CBasePlayer *pVictim, CBasePlayer *pScorer, CBaseEntity *pInflictor ); + CTFPlayer *GetRecentDamager( CTFPlayer *pVictim, int iDamager, float flMaxElapsed ); + + virtual void ClientDisconnected( edict_t *pClient ); + + virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ); + void RadiusDamage( CTFRadiusDamageInfo &info ); + + bool ApplyOnDamageModifyRules( CTakeDamageInfo &info, CBaseEntity *pVictimBaseEntity, bool bAllowDamage ); + + struct DamageModifyExtras_t + { + bool bIgniting; + bool bSelfBlastDmg; + bool bSendPreFeignDamage; + bool bPlayDamageReductionSound; + }; + float ApplyOnDamageAliveModifyRules( const CTakeDamageInfo &info, CBaseEntity *pVictimBaseEntity, DamageModifyExtras_t& outParams ); + + virtual float FlPlayerFallDamage( CBasePlayer *pPlayer ); + + virtual bool FlPlayerFallDeathDoesScreenFade( CBasePlayer *pl ) { return false; } + + virtual bool UseSuicidePenalty() { return false; } + + int GetPreviousRoundWinners( void ) { return m_iPreviousRoundWinners; } + + void SendHudNotification( IRecipientFilter &filter, HudNotification_t iType, bool bForceShow = false ); + void SendHudNotification( IRecipientFilter &filter, const char *pszText, const char *pszIcon, int iTeam = TEAM_UNASSIGNED ); + void StopWatchModeThink( void ); + + virtual void RestartTournament( void ); + + bool TFVoiceManager( CBasePlayer *pListener, CBasePlayer *pTalker ); + + void OnNavMeshLoad( void ); + void OnDispenserBuilt( CBaseEntity *dispenser ); + void OnDispenserDestroyed( CBaseEntity *dispenser ); + void OnPlayerSpawned( CTFPlayer *pPlayer ); + void OnCoachJoining( uint32 unCoachAccountID, uint32 unStudentAccountID ); + void OnRemoveCoach( uint32 unCoachAccountID ); + + //Arena + void AddPlayerToQueue( CTFPlayer *pPlayer ); + void AddPlayerToQueueHead( CTFPlayer *pPlayer ); + void RemovePlayerFromQueue( CTFPlayer *pPlayer ); + virtual bool BHavePlayers( void ) OVERRIDE; + + void Arena_RunTeamLogic( void ); + void Arena_ResetLosersScore( bool bResetAll ); + void Arena_PrepareNewPlayerQueue( bool bResetAll ); + int Arena_PlayersNeededForMatch( void ); + void Arena_CleanupPlayerQueue( void ); + void Arena_ClientDisconnect( const char *playername ); + void Arena_SendPlayerNotifications( void ); + void Arena_NotifyTeamSizeChange( void ); + float GetRoundStart( void ) { return m_flRoundStartTime; } + + // Voting + void ManageServerSideVoteCreation( void ); + +#ifdef TF_RAID_MODE + // Raid game mode + CRaidLogic *GetRaidLogic( void ) const { return m_hRaidLogic.Get(); } +#endif // TF_RAID_MODE + + // Currency awarding + int CalculateCurrencyAmount_CustomPack( int nAmount ); // If we should drop a custom currency pack, and how much money to put in - 0 means don't drop + int CalculateCurrencyAmount_ByType( CurrencyRewards_t nType ); // How much to give players for specific items and events, i.e. cash collection bonus, small packs + int DistributeCurrencyAmount( int nAmount, CTFPlayer *pTFPlayer = NULL, bool bShared = true, bool bCountAsDropped = false, bool bIsBonus = false ); // Distributes nAmount to a specific player or team + + virtual bool StopWatchShouldBeTimedWin( void ) OVERRIDE; + +public: + void SetPlayerNextMapVote( int nIndex, EUserNextMapVote eState ) { m_ePlayerWantsRematch.Set( nIndex, eState ); } + + CTrainingModeLogic *GetTrainingModeLogic() { return m_hTrainingModeLogic; } + CTFHolidayEntity *GetHolidayLogic() const { return m_hHolidayLogic; } + + void HandleCTFCaptureBonus( int nTeam ); + bool TournamentModeCanEndWithTimelimit( void ){ return ( GetStopWatchTimer() == NULL ); } + + CTeamRoundTimer *GetKothTeamTimer( int iTeam ) + { + if ( IsInKothMode() == false ) + return NULL; + + if ( iTeam == TF_TEAM_RED ) + { + return m_hRedKothTimer.Get(); + } + else if ( iTeam == TF_TEAM_BLUE ) + { + return m_hBlueKothTimer.Get(); + } + + return NULL; + } + + void SetKothTeamTimer( int iTeam, CTeamRoundTimer *pTimer ) + { + if ( iTeam == TF_TEAM_RED ) + { + m_hRedKothTimer.Set( pTimer ); + } + else if ( iTeam == TF_TEAM_BLUE ) + { + m_hBlueKothTimer.Set( pTimer ); + } + } + + void SetOvertimeAllowedForCTF( bool bAllowed ){ m_bOvertimeAllowedForCTF = bAllowed; } + bool GetOvertimeAllowedForCTF( void ){ return m_bOvertimeAllowedForCTF; } + + const CUtlVector< CHandle< CBaseEntity > > &GetHealthEntityVector( void ); // return vector of health entities + const CUtlVector< CHandle< CBaseEntity > > &GetAmmoEntityVector( void ); // return vector of ammo entities + + CHandle< CTeamTrainWatcher > GetPayloadToPush( int pushingTeam ) const; // return the train watcher for the Payload cart the given team needs to push to win, or NULL if none currently exists + CHandle< CTeamTrainWatcher > GetPayloadToBlock( int blockingTeam ) const; // return the train watcher for the Payload cart the given team needs to block from advancing, or NULL if none currently exists + + virtual void ProcessVerboseLogOutput( void ); + + void PushAllPlayersAway( const Vector& vFromThisPoint, float flRange, float flForce, int nTeam, CUtlVector< CTFPlayer* > *pPushedPlayers = NULL ); + + bool ShouldDropSpellPickup(); + void DropSpellPickup( const Vector& vPosition, int nTier = 0 ) const; + + bool ShouldDropBonusDuck( void ); + bool ShouldDropBonusDuckFromPlayer( CTFPlayer *pScorer, CTFPlayer *pVictim ); + void DropBonusDuck( const Vector& vPosition, CTFPlayer *pScorer = NULL, CTFPlayer *pAssistor = NULL, CTFPlayer *pVictim = NULL, bool bCrit = false, bool bObjective = false ) const; + + void DropHalloweenSoulPackToTeam( int nAmount, const Vector& vecPosition, int nTeamNumber, int nSourceTeam ); + void DropHalloweenSoulPack( int nAmount, const Vector& vecSource, CBaseEntity *pTarget, int nSourceTeam ); + +#ifdef STAGING_ONLY + void MatchSummaryTest( void ); +#endif // STAGING_ONLY + void MatchSummaryStart( void ); + void MatchSummaryEnd( void ); + + int GetTeamAssignmentOverride( CTFPlayer *pTFPlayer, int iDesiredTeam, bool bAutoBalance = false ); +private: + + void ChooseNextMapVoteOptions(); + + int DefaultFOV( void ) { return 75; } + int GetDuckSkinForClass( int nTeam, int nClass ) const; + void MatchSummaryTeleport(); + + void StopWatchShouldBeTimedWin_Calculate( void ); + +#endif // GAME_DLL + +private: + + void ComputeHealthAndAmmoVectors( void ); // compute internal vectors of health and ammo locations + bool m_areHealthAndAmmoVectorsReady; + + +#ifdef GAME_DLL + + + void CheckHelltowerCartAchievement( int iTeam ); + + Vector2D m_vecPlayerPositions[MAX_PLAYERS]; + + CUtlVector<CHandle<CHealthKit> > m_hDisabledHealthKits; + + + char m_szMostRecentCappers[MAX_PLAYERS+1]; // list of players who made most recent capture. Stored as string so it can be passed in events. + int m_iNumCaps[TF_TEAM_COUNT]; // # of captures ever by each team during a round + + int SetCurrentRoundStateBitString(); + void SetMiniRoundBitMask( int iMask ); + int m_iPrevRoundState; // bit string representing the state of the points at the start of the previous miniround + int m_iCurrentRoundState; + int m_iCurrentMiniRoundMask; + + CHandle<CTeamRoundTimer> m_hStopWatchTimer; + + + CTeamRoundTimer* GetStopWatchTimer( void ) { return (CTeamRoundTimer*)m_hStopWatchTimer.Get(); } + + EHANDLE m_hRequiredObserverTarget; + EHANDLE m_hObjectiveObserverTarget; + + CHandle<CTFGameRulesProxy> m_hGamerulesProxy; + + //Arena + bool IsFirstBloodAllowed( void ); + EHANDLE m_hArenaEntity; + CUtlVector<CHandle<CTFPlayer> > m_hArenaPlayerQueue; + int m_iPreviousTeamSize; + bool m_bArenaFirstBlood; + + float m_flSendNotificationTime; + + // Tournament + CHandle< CCompetitiveLogic > m_hCompetitiveLogicEntity; + + CHandle<CTrainingModeLogic> m_hTrainingModeLogic; + CHandle<CTFHolidayEntity> m_hHolidayLogic; + + bool m_bOvertimeAllowedForCTF; + + // for bot rosters + CHandle<CTFBotRoster> m_hBlueBotRoster; + CHandle<CTFBotRoster> m_hRedBotRoster; + + // coaching + typedef CUtlMap<uint32, uint32> tCoachToStudentMap; + tCoachToStudentMap m_mapCoachToStudentMap; + + // Automatic vote called near the end of a map + bool m_bVoteCalled; + bool m_bServerVoteOnReset; + float m_flVoteCheckThrottle; + + CUtlVector< CHandle< CCPTimerLogic > > m_CPTimerEnts; + float m_flCapInProgressBuffer; + + float m_flMatchSummaryTeleportTime; + +#ifdef TF_RAID_MODE + CHandle< CRaidLogic > m_hRaidLogic; + CHandle< CBossBattleLogic > m_hBossBattleLogic; +#endif // TF_RAID_MODE + + int m_nCurrencyAccumulator; + int m_iCurrencyPool; + + float m_flCheckPlayersConnectingTime; + + CountdownTimer m_helltowerTimer; // used for Halloween 2013 Announcer VO in plr_hightower_event + CountdownTimer m_doomsdaySetupTimer; // used for Halloween 2014 Announcer Setup VO in sd_doomsday_event + CountdownTimer m_doomsdayTicketsTimer; // Used on sd_doomsday_event to nag players about picking up the tickets + + float m_flNextStrangeEventProcessTime; + + bool m_bMapForcedTruceDuringBossFight; + float m_flNextHalloweenGiftUpdateTime; +#else + + KeyValues *m_pkvVisionFilterTranslations; + KeyValues *m_pkvVisionFilterShadersMapWhitelist; + + bool m_bSillyGibs; + +#endif + + CNetworkVar( ETFGameType, m_nGameType ); // Type of game this map is (CTF, CP) + CNetworkVar( int, m_nStopWatchState ); + CNetworkString( m_pszTeamGoalStringRed, MAX_TEAMGOAL_STRING ); + CNetworkString( m_pszTeamGoalStringBlue, MAX_TEAMGOAL_STRING ); + CNetworkVar( float, m_flCapturePointEnableTime ); + CNetworkVar( int, m_iGlobalAttributeCacheVersion ); + +//============================================================================= +// HPE_BEGIN: +// [msmith] Training and HUD status. +//============================================================================= + CNetworkVar( int, m_nHudType ); // Used by map authors to override the default HUD clients are showing + CNetworkVar( bool, m_bIsInTraining ); + CNetworkVar( bool, m_bAllowTrainingAchievements ); + CNetworkVar( bool, m_bIsWaitingForTrainingContinue ); +//============================================================================= +// HPE_END +//============================================================================= + CNetworkVar( bool, m_bIsTrainingHUDVisible ); + + CNetworkVar( bool, m_bIsInItemTestingMode ); + int m_iItemTesting_BotAnim; + float m_flItemTesting_BotAnimSpeed; + bool m_bItemTesting_BotForceFire; + bool m_bItemTesting_BotTurntable; + bool m_bItemTesting_BotViewScan; + + CNetworkVar( CHandle<CBonusRoundLogic>, m_hBonusLogic ); + + CNetworkVar( bool, m_bPlayingKoth ); + CNetworkVar( bool, m_bPowerupMode ); + CNetworkVar( bool, m_bPlayingRobotDestructionMode ); + CNetworkVar( bool, m_bPlayingMedieval ); + CNetworkVar( bool, m_bPlayingHybrid_CTF_CP ); + CNetworkVar( bool, m_bPlayingSpecialDeliveryMode ); + + CNetworkVar( bool, m_bPlayingMannVsMachine ); + CNetworkVar( bool, m_bMannVsMachineAlarmStatus ); + CNetworkVar( bool, m_bHaveMinPlayersToEnableReady ); + + CNetworkVar( bool, m_bBountyModeEnabled ); + CNetworkVar( bool, m_bCompetitiveMode ); + CNetworkVar( float, m_flGravityMultiplier ); + CNetworkVar( int, m_nMatchGroupType ); + CNetworkVar( bool, m_bMatchEnded ); + + // This is used to check if players are in hell. The name doesn't make sense because we thought this would only be used for Halloween 2013 + // cannot change the name because it's network var which will break demo + CNetworkVar( bool, m_bHelltowerPlayersInHell ); + + CNetworkVar( bool, m_bIsUsingSpells ); + + CNetworkVar( bool, m_bTruceActive ); + CNetworkVar( bool, m_bTeamsSwitched ); + +#ifdef GAME_DLL + float m_flNextFlagAlarm; + float m_flNextFlagAlert; + + float m_flSafeToLeaveTimer; + + CBaseEntity *m_pUpgrades; +#endif + + CNetworkVar( CHandle<CTeamRoundTimer>, m_hRedKothTimer ); + CNetworkVar( CHandle<CTeamRoundTimer>, m_hBlueKothTimer ); + + CNetworkVar( int, m_nMapHolidayType ); // Used by map authors to indicate this is a holiday map + + CNetworkString( m_pszCustomUpgradesFile, MAX_PATH ); + + CNetworkVar( bool, m_bShowMatchSummary ); + CNetworkVar( bool, m_bMapHasMatchSummaryStage ); + CNetworkVar( bool, m_bPlayersAreOnMatchSummaryStage ); + CNetworkVar( bool, m_bStopWatchWinner ); + // This is called m_ePlayerWantsRematch because we initially had rematches, but now we + // let players vote on the next map instead. Can't rename this variable, so we're just + // going to use with the wrong name + CNetworkArray( EUserNextMapVote, m_ePlayerWantsRematch, MAX_PLAYERS + 1 ); + CNetworkVar( ENextMapVotingState, m_eRematchState ); + CNetworkArray( MapDefIndex_t, m_nNextMapVoteOptions, 3 ); + + float m_flCTFCaptureBonusTime; +public: + + bool m_bControlSpawnsPerTeam[ MAX_TEAMS ][ MAX_CONTROL_POINTS ]; + int m_iPreviousRoundWinners; + + float GetCapturePointTime( void ) { return m_flCapturePointEnableTime; } + + virtual bool ShouldDrawHeadLabels() + { + if ( IsInTournamentMode() ) + return false; + + return BaseClass::ShouldDrawHeadLabels(); + } + + enum HalloweenScenarioType + { + HALLOWEEN_SCENARIO_NONE = 0, + HALLOWEEN_SCENARIO_MANN_MANOR, + HALLOWEEN_SCENARIO_VIADUCT, + HALLOWEEN_SCENARIO_LAKESIDE, + HALLOWEEN_SCENARIO_HIGHTOWER, + HALLOWEEN_SCENARIO_DOOMSDAY, + }; + HalloweenScenarioType GetHalloweenScenario( void ) const; + bool IsHalloweenScenario( HalloweenScenarioType scenario ) const; + + bool CanInitiateDuels( void ); + +#ifdef GAME_DLL + + // Used on sd_doomsday_event to nag players about picking up the tickets + void StartDoomsdayTicketsTimer( void ) { m_doomsdayTicketsTimer.Start( RandomInt( 30, 60 ) ); } + void StopDoomsdayTicketsTimer( void ) { m_doomsdayTicketsTimer.Invalidate(); } + bool DoomsdayTicketTimerElapsed( void ) const { return m_doomsdayTicketsTimer.HasStarted() && m_doomsdayTicketsTimer.IsElapsed(); } + + int GetBossCount() const { return m_activeBosses.Count(); } + + CBaseCombatCharacter *GetActiveBoss( int iBoss = 0 ) + { + if ( iBoss < 0 || iBoss >= m_activeBosses.Count() ) + return NULL; + + return m_activeBosses[iBoss]; + } + + void AddActiveBoss( CBaseCombatCharacter *boss ) + { + // don't add the same boss + if ( m_activeBosses.Find( boss ) != m_activeBosses.InvalidIndex() ) + return; + + m_activeBosses.AddToTail( boss ); + } + + void RemoveActiveBoss( CBaseCombatCharacter *boss ) + { + m_activeBosses.FindAndRemove( boss ); + } + + CBaseEntity *GetIT( void ) const // who is the boss chasing + { + return m_itHandle; + } + + void SetIT( CBaseEntity *who ); + void SetBirthdayPlayer( CBaseEntity *pEntity ); + + void SetHalloweenEffectStatus( int effect, float duration ) // Update the current Halloween effect on the HUD + { + m_nHalloweenEffect = effect; + m_fHalloweenEffectStartTime = gpGlobals->curtime; + m_fHalloweenEffectDuration = duration; + } + + + // remove all projectiles in the world + void RemoveAllProjectiles(); + + // remove all buildings in the world + void RemoveAllBuildings( bool bExplodeBuildings = false ); + + // remove all sentry's ammo + void RemoveAllSentriesAmmo(); + + // remove all projectiles and objects + void RemoveAllProjectilesAndBuildings( bool bExplodeBuildings = false ); + +#endif // GAME_DLL + + void ClearHalloweenEffectStatus( void ) // Clear the current Halloween effect and hide the HUD display + { + m_nHalloweenEffect = -1; + m_fHalloweenEffectStartTime = -1.0f; + m_fHalloweenEffectDuration = -1.0f; + } + + bool IsIT( CBaseEntity *who ) const + { + return ( who && who == m_itHandle.Get() ); + } + + CBaseEntity *GetBirthdayPlayer( void ) const + { + return m_hBirthdayPlayer.Get(); + } + + bool IsHalloweenEffectStatusActive( void ) const + { + return m_nHalloweenEffect >= 0; + } + + int GetHalloweenEffectStatus( void ) const + { + return m_nHalloweenEffect; + } + + float GetHalloweenEffectTimeLeft( void ) const + { + float expireTime = m_fHalloweenEffectStartTime + m_fHalloweenEffectDuration; + + return expireTime - gpGlobals->curtime; + } + + float GetHalloweenEffectDuration( void ) const + { + return m_fHalloweenEffectDuration; + } + + int GetGlobalAttributeCacheVersion( void ) const + { + return m_iGlobalAttributeCacheVersion; + } + + void FlushAllAttributeCaches( void ) + { + m_iGlobalAttributeCacheVersion++; + } + +private: +#ifdef CLIENT_DLL + bool m_bRecievedBaseline; +#endif + + + CountdownTimer m_botCountTimer; + + CUtlVector< CHandle< CBaseEntity > > m_ammoVector; // vector of active ammo entities + bool m_isAmmoVectorReady; // for lazy evaluation + + CUtlVector< CHandle< CBaseEntity > > m_healthVector; // vector of active health entities + bool m_isHealthVectorReady; // for lazy evaluation + + bool m_bUseMatchHUD; + bool m_bUsePreRoundDoors; +#ifdef GAME_DLL + mutable CHandle< CTeamTrainWatcher > m_redPayloadToPush; + mutable CHandle< CTeamTrainWatcher > m_bluePayloadToPush; + mutable CHandle< CTeamTrainWatcher > m_redPayloadToBlock; + mutable CHandle< CTeamTrainWatcher > m_bluePayloadToBlock; + + bool m_hasSpawnedToy; + void SpawnHalloweenBoss( void ); + CountdownTimer m_halloweenBossTimer; + CUtlVector< CHandle< CBaseCombatCharacter > > m_activeBosses; + bool m_bHasSpawnedSoccerBall[TF_TEAM_COUNT]; + + CountdownTimer m_ghostTimer; + + void SpawnZombieMob( void ); + CountdownTimer m_zombieMobTimer; + int m_zombiesLeftToSpawn; + Vector m_zombieSpawnSpot; + +public: + void BeginHaunting( int nDesiredCount, float flMinDuration, float flMaxDuration ); + + void StartHalloweenBossTimer( float flTime, float flVariation = 0.f ) + { + m_halloweenBossTimer.Start( RandomFloat( flTime - flVariation, flTime + flVariation ) ); + } + + // Recent player stuff + void PlayerHistory_AddPlayer( CTFPlayer *pTFPlayer ); + PlayerHistoryInfo_t *PlayerHistory_GetPlayerInfo( CTFPlayer *pTFPlayer ); + int PlayerHistory_GetTimeSinceLastSeen( CTFPlayer *pTFPlayer ); + + CUtlVector< Vector > *GetHalloweenSpawnLocations() { return &m_halloweenGiftSpawnLocations; } + + bool BAttemptMapVoteRollingMatch(); + + bool BIsManagedMatchEndImminent( void ); + +private: + CUtlVector< CHandle< CGhost > > m_ghostVector; + CUtlVector< PlayerHistoryInfo_t > m_vecPlayerHistory; + + struct TeleportLocation_t + { + Vector m_vecPosition; + QAngle m_qAngles; + }; + CUtlMap< string_t, CUtlVector< TeleportLocation_t >* > m_mapTeleportLocations; + + // Keep track of kills made with powerups + int m_nPowerupKillsRedTeam; + int m_nPowerupKillsBlueTeam; + float m_flTimeToRunImbalanceMeasures; + float m_flTimeToStopImbalanceMeasures; + bool m_bPowerupImbalanceMeasuresRunning; + + bool m_bMapCycleNeedsUpdate; + + CUtlVector< Vector > m_halloweenGiftSpawnLocations; // vector of valid gift spawn locations from the map + float m_flCompModeRespawnPlayersAtMatchStart; + +#endif // GAME_DLL + + // LEGACY BOSS CODE. Keeping this to not break demo + CNetworkVar( int, m_nBossHealth ); + CNetworkVar( int, m_nMaxBossHealth ); + CNetworkVar( float, m_fBossNormalizedTravelDistance ); + + CNetworkHandle( CBaseEntity, m_itHandle ); // entindex of current IT entity (0 = no it) + CNetworkHandle( CBaseEntity, m_hBirthdayPlayer ); // entindex of current birthday player (0 = none) + + CNetworkVar( int, m_nHalloweenEffect ); + CNetworkVar( float, m_fHalloweenEffectStartTime ); + CNetworkVar( float, m_fHalloweenEffectDuration ); + CNetworkVar( HalloweenScenarioType, m_halloweenScenario ); + +// MvM Helpers +#ifdef GAME_DLL +public: + void SetNextMvMPopfile ( const char * next ); + const char * GetNextMvMPopfile (); + + virtual void BalanceTeams( bool bRequireSwitcheesToBeDead ); +#endif +}; + +//----------------------------------------------------------------------------- +// Gets us at the team fortress game rules +//----------------------------------------------------------------------------- + +inline CTFGameRules* TFGameRules() +{ + return static_cast<CTFGameRules*>(g_pGameRules); +} + +inline float CTFGameRules::ItemTesting_GetBotAnimSpeed( void ) +{ + static const ConVar *pHostTimescale = NULL; + + if ( !pHostTimescale ) + { + pHostTimescale = cvar->FindVar( "host_timescale" ); + } + + if ( pHostTimescale ) + return (m_flItemTesting_BotAnimSpeed * pHostTimescale->GetFloat()); + return m_flItemTesting_BotAnimSpeed; +} + +#ifdef TF_RAID_MODE + +inline bool CTFGameRules::IsRaidMode( void ) const +{ +#ifdef GAME_DLL + return m_hRaidLogic != NULL; +#else + return tf_gamemode_raid.GetBool(); +#endif +} + + + +inline bool CTFGameRules::IsBossBattleMode( void ) const +{ + return tf_gamemode_boss_battle.GetBool(); +} + +#endif // TF_RAID_MODE + +#ifdef TF_CREEP_MODE + +inline bool CTFGameRules::IsCreepWaveMode( void ) const +{ + return tf_gamemode_creep_wave.GetBool(); +} + +#endif + + +inline bool CTFGameRules::IsHalloweenScenario( HalloweenScenarioType scenario ) const +{ + return m_halloweenScenario == scenario; +} + + +#ifdef GAME_DLL +bool EntityPlacementTest( CBaseEntity *pMainEnt, const Vector &vOrigin, Vector &outPos, bool bDropToGround ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CArenaLogic : public CPointEntity +{ + DECLARE_CLASS( CArenaLogic, CPointEntity ); +public: + DECLARE_DATADESC(); + + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } + + virtual void ArenaLogicThink( void ); + virtual void Spawn( void ); + + COutputEvent m_OnArenaRoundStart; + float m_flTimeToEnableCapPoint; + COutputEvent m_OnCapEnabled; + bool m_bFiredOutput; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CCompetitiveLogic : public CPointEntity +{ + DECLARE_CLASS( CCompetitiveLogic, CPointEntity ); +public: + DECLARE_DATADESC(); + + void OnSpawnRoomDoorsShouldLock( void ); + void OnSpawnRoomDoorsShouldUnlock( void ); + + COutputEvent m_OnSpawnRoomDoorsShouldLock; + COutputEvent m_OnSpawnRoomDoorsShouldUnlock; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CLogicMannPower : public CPointEntity +{ + DECLARE_CLASS( CLogicMannPower, CPointEntity ); +public: + DECLARE_DATADESC(); +}; + +//----------------------------------------------------------------------------- +// Purpose: New training stuff +//----------------------------------------------------------------------------- +class CTrainingModeLogic : public CPointEntity +{ + DECLARE_CLASS( CTrainingModeLogic, CPointEntity ); +public: + DECLARE_DATADESC(); + + void SetupOnRoundStart( void ); + void SetTrainingMsg( const char *msg ); + void SetTrainingObjective( const char *msg ); + void OnPlayerSpawned( CTFPlayer *pPlayer ); + void OnPlayerDied( CTFPlayer *pPlayer, CBaseEntity *pKiller ); + void OnBotDied( CTFPlayer *pPlayer, CBaseEntity *pKiller ); + void OnPlayerSwitchedWeapons( CTFPlayer *pPlayer ); + void OnPlayerWantsToContinue(); + void OnPlayerBuiltBuilding( CTFPlayer *pPlayer, CBaseObject *pBaseObject ); + void OnPlayerUpgradedBuilding( CTFPlayer *pPlayer, CBaseObject *pBaseObject ); + void OnPlayerDetonateBuilding( CTFPlayer *pPlayer, CBaseObject *pBaseObject ); + void UpdateHUDObjective(); + const char* GetNextMap(); + const char* GetTrainingEndText(); + int GetDesiredClass() const; + + // Inputs + void InputForcePlayerSpawnAsClassOutput( inputdata_t &inputdata ); + void InputKickAllBots( inputdata_t &inputdata ); + void InputShowTrainingMsg( inputdata_t &inputdata ); + void InputShowTrainingObjective( inputdata_t &inputdata ); + void InputShowTrainingHUD( inputdata_t &inputdata ); + void InputHideTrainingHUD( inputdata_t &inputdata ); + void InputEndTraining( inputdata_t &inputdata ); + void InputPlaySoundOnPlayer( inputdata_t &inputdata ); + void InputWaitForTimerOrKeypress( inputdata_t &inputdata ); + void InputSetNextMap( inputdata_t &inputdata ); + void InputForcePlayerSwapToWeapon( inputdata_t &inputdata ); + +protected: + enum + { + kMaxLengthObjectiveText = 128, + }; + + // outputs based on the class the player spawned as + COutputEvent m_outputOnPlayerSpawnAsScout; + COutputEvent m_outputOnPlayerSpawnAsSniper; + COutputEvent m_outputOnPlayerSpawnAsSoldier; + COutputEvent m_outputOnPlayerSpawnAsDemoman; + COutputEvent m_outputOnPlayerSpawnAsMedic; + COutputEvent m_outputOnPlayerSpawnAsHeavy; + COutputEvent m_outputOnPlayerSpawnAsPyro; + COutputEvent m_outputOnPlayerSpawnAsSpy; + COutputEvent m_outputOnPlayerSpawnAsEngineer; + // outputs based on the weapon the player swapped to + COutputEvent m_outputOnPlayerSwappedToWeaponSlotPrimary; + COutputEvent m_outputOnPlayerSwappedToWeaponSlotSecondary; + COutputEvent m_outputOnPlayerSwappedToWeaponSlotMelee; + COutputEvent m_outputOnPlayerSwappedToWeaponSlotBuilding; + COutputEvent m_outputOnPlayerSwappedToWeaponSlotPDA; + // outputs based on if the player built inside a suggested area + COutputEvent m_outputOnPlayerBuiltOutsideSuggestedArea; + // player detonated their own building + COutputEvent m_outputOnPlayerDetonateBuilding; + // other outputs + COutputEvent m_outputOnPlayerDied; + COutputEvent m_outputOnBotDied; + + CHandle<CBaseEntity> m_waitingForKeypressTimer; + string_t m_nextMapName; + char m_objText[kMaxLengthObjectiveText]; + string_t m_endTrainingText; +}; + +class CMultipleEscort : public CPointEntity +{ + DECLARE_CLASS( CMultipleEscort, CPointEntity ); +public: + + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } +}; + +class CMedievalLogic : public CPointEntity +{ + DECLARE_CLASS( CMedievalLogic, CPointEntity ); +public: + + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } +}; + +class CHybridMap_CTF_CP : public CPointEntity +{ + DECLARE_CLASS( CHybridMap_CTF_CP, CPointEntity ); +public: + + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } +}; + +class CTFHolidayEntity : public CPointEntity, public CGameEventListener +{ + DECLARE_CLASS( CTFHolidayEntity, CPointEntity ); +public: + DECLARE_DATADESC(); + + CTFHolidayEntity() + { + m_nHolidayType = kHoliday_None; + m_nTauntInHell = 0; + m_nAllowHaunting = 0; + ListenForGameEvent( "player_turned_to_ghost" ); + ListenForGameEvent( "player_disconnect" ); + ListenForGameEvent( "player_team" ); + } + ~CTFHolidayEntity() + { + } + + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } + int GetHolidayType( void ){ return m_nHolidayType; } + bool ShouldTauntInHell( void ){ return ( m_nTauntInHell > 0 ); } + bool ShouldAllowHaunting( void ){ return ( m_nAllowHaunting > 0 ); } + + void InputHalloweenSetUsingSpells( inputdata_t &inputdata ); + void InputHalloweenTeleportToHell( inputdata_t &inputdata ); + + virtual void FireGameEvent( IGameEvent *event ); + + void ResetWinner() { m_nWinningTeam = TF_TEAM_COUNT; } + int GetWinningTeam() const { return m_nWinningTeam; } +private: + + void HalloweenTeleportToHellDanceThink( void ); + void Teleport(); + + CUtlVector< CHandle<CTFPlayer> > m_vecDancers; + int m_nWinningTeam; + + int m_nHolidayType; + int m_nTauntInHell; + int m_nAllowHaunting; +}; + +class CKothLogic : public CPointEntity +{ + DECLARE_CLASS( CKothLogic, CPointEntity ); +public: + DECLARE_DATADESC(); + + CKothLogic() + { + m_nTimerInitialLength = 180; // seconds + m_nTimeToUnlockPoint = 30; // seconds + + m_hRedTimer = NULL; + m_hBlueTimer = NULL; + } + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } + + int GetInitialTimerLength( void ){ return m_nTimerInitialLength; } + int GetTimerToUnlockPoint( void ){ return m_nTimeToUnlockPoint; } + + void InputRoundSpawn( inputdata_t &inputdata ); + void InputRoundActivate( inputdata_t &inputdata ); + void InputSetRedTimer( inputdata_t &inputdata ); + void InputSetBlueTimer( inputdata_t &inputdata ); + void InputAddRedTimer( inputdata_t &inputdata ); + void InputAddBlueTimer( inputdata_t &inputdata ); + +private: + int m_nTimerInitialLength; + int m_nTimeToUnlockPoint; + + CHandle< CTeamRoundTimer > m_hRedTimer; + CHandle< CTeamRoundTimer > m_hBlueTimer; +}; + +#define CP_TIMER_THINK "CCPTimerLogicThink" +class CCPTimerLogic : public CPointEntity +{ + DECLARE_CLASS( CCPTimerLogic, CPointEntity ); +public: + DECLARE_DATADESC(); + + CCPTimerLogic() + { + m_nTimerLength = 60; // seconds + m_iszControlPointName = NULL_STRING; + m_hControlPoint = NULL; + m_bFire15SecRemain = m_bFire10SecRemain = m_bFire5SecRemain = true; + + SetContextThink( &CCPTimerLogic::Think, gpGlobals->curtime + 0.15, CP_TIMER_THINK ); + } + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } + + void InputRoundSpawn( inputdata_t &inputdata ); + void Think( void ); + bool TimerMayExpire( void ); + +private: + int m_nTimerLength; + string_t m_iszControlPointName; + CHandle<CTeamControlPoint> m_hControlPoint; + CountdownTimer m_pointTimer; + + bool m_bFire15SecRemain; + bool m_bFire10SecRemain; + bool m_bFire5SecRemain; + + COutputEvent m_onCountdownStart; + COutputEvent m_onCountdown15SecRemain; + COutputEvent m_onCountdown10SecRemain; + COutputEvent m_onCountdown5SecRemain; + COutputEvent m_onCountdownEnd; +}; +#endif + +class CBonusRoundLogic : public CBaseEntity +{ + DECLARE_CLASS( CBonusRoundLogic, CBaseEntity ); +public: + DECLARE_NETWORKCLASS(); + +#ifdef GAME_DLL + bool InitBonusRound( void ); + void SetBonusItem( itemid_t iItemID ); + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } +#endif + + void BuildBonusPlayerList( void ); + int GetNumBonusPlayers( void ) { return m_aBonusPlayerList.Count(); } + CTFPlayer *GetBonusPlayer( int i ) { Assert ( i < m_aBonusPlayerList.Count() ); return m_aBonusPlayerList[i]; } + CTFPlayer *GetBonusWinner( void ) { return m_hBonusWinner.Get(); } + void SetBonusStateAborted( bool bAborted ) { m_bAbortedBonusRound = bAborted; } + bool BonusStateAborted( void ) { return m_bAbortedBonusRound; } + int GetPlayerBonusRoll( int iPlayer ) { return (iPlayer < m_aBonusPlayerRoll.Count()) ? m_aBonusPlayerRoll[iPlayer] : 0; } + CEconItemView *GetBonusItem( void ) { return &m_Item; } + +private: + CUtlSortVector< BONUSPLAYERPTR, CBonusPlayerListLess > m_aBonusPlayerList; + CUtlVector<int> m_aBonusPlayerRoll; + CNetworkVar( CHandle<CTFPlayer>, m_hBonusWinner ); + CNetworkVar( bool, m_bAbortedBonusRound ); + itemid_t m_iBonusItemID; + CNetworkVarEmbedded( CEconItemView, m_Item ); +}; + +#ifdef GAME_DLL +class CSingleUserReliableRecipientFilter : public CRecipientFilter +{ +public: + CSingleUserReliableRecipientFilter( CBasePlayer *player ) + { + AddRecipient( player ); + MakeReliable(); + } +}; +#endif + +#endif // TF_GAMERULES_H |