//========= 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 &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 > 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 m_hStopWatchTimer; CTeamRoundTimer* GetStopWatchTimer( void ) { return (CTeamRoundTimer*)m_hStopWatchTimer.Get(); } EHANDLE m_hRequiredObserverTarget; EHANDLE m_hObjectiveObserverTarget; CHandle m_hGamerulesProxy; //Arena bool IsFirstBloodAllowed( void ); EHANDLE m_hArenaEntity; CUtlVector > m_hArenaPlayerQueue; int m_iPreviousTeamSize; bool m_bArenaFirstBlood; float m_flSendNotificationTime; // Tournament CHandle< CCompetitiveLogic > m_hCompetitiveLogicEntity; CHandle m_hTrainingModeLogic; CHandle m_hHolidayLogic; bool m_bOvertimeAllowedForCTF; // for bot rosters CHandle m_hBlueBotRoster; CHandle m_hRedBotRoster; // coaching typedef CUtlMap 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, 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, m_hRedKothTimer ); CNetworkVar( CHandle, 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(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 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 > 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 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 m_aBonusPlayerRoll; CNetworkVar( CHandle, 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