// vim: set ts=4 sw=4 tw=99 noet: // // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). // Copyright (C) The AMX Mod X Development Team. // // This software is licensed under the GNU General Public License, version 3 or higher. // Additional exceptions apply. For full license details, see LICENSE.txt or visit: // https://alliedmods.net/amxmodx-license // // Natural Selection Module // /* This file includes game-related stuff, such as message IDs * and forwards */ #ifndef GAMEMANAGER_H #define GAMEMANAGER_H #include class GameManager { private: // Basic game variables int m_IsCombat; int m_HudText2; // Message IDS int m_SetFOV; // Forwards int m_ChangeclassForward; int m_BuiltForward; int m_SpawnForward; int m_TeamForward; int m_RoundStartForward; int m_RoundEndForward; int m_MapResetForward; REAL m_fRoundStartTime; // Time the match should start int m_RoundInProgress; // Whether or not there is a match in progress edict_t *m_SavedEdict; // saved edict for client_built int m_iTitlesMap; bool m_SendMapReset; public: GameManager() { m_SendMapReset = true; m_IsCombat=0; m_HudText2=0; m_SetFOV=0; m_SavedEdict=NULL; m_RoundInProgress=0; ResetForwards(); }; inline void CheckMap(void) { ke::AString MapName; MapName = UTIL_ToLowerCase(STRING(gpGlobals->mapname)); m_iTitlesMap=0; if (MapName.compare("ns_bast")==0 || MapName.compare("ns_bast_classic") == 0 || MapName.compare("ns_hera") == 0 || MapName.compare("ns_nothing") == 0 || MapName.compare("ns_caged") == 0 || MapName.compare("ns_tanith") == 0 || MapName.compare("ns_eclipse") == 0 || MapName.compare("ns_veil") == 0 || MapName.compare("ns_nancy") == 0) { m_iTitlesMap=1; } }; inline int &TitleMap(void) { return m_iTitlesMap; }; inline void SetCombat(int value) { m_IsCombat=value; }; inline int &IsCombat(void) { return m_IsCombat; }; inline void UpdateHudText2(void) { if (!m_HudText2) { GetMessageIDs(); } }; inline void UpdateSetFOV(void) { if (!m_SetFOV) { GetMessageIDs(); } }; inline int &GetHudText2(void) { return m_HudText2; }; inline int &GetSetFOV(void) { return m_SetFOV; }; inline void GetMessageIDs(void) { m_HudText2=GET_USER_MSG_ID(&Plugin_info,"HudText2",NULL); m_SetFOV=GET_USER_MSG_ID(&Plugin_info,"SetFOV",NULL); }; inline void EvaluateCombat(void) { const char *Map=STRING(gpGlobals->mapname); // if map starts with co_ it is combat // otherwise it is classic gameplay if ((Map[0]=='c' || Map[0]=='C') && (Map[1]=='o' || Map[1]=='O') && (Map[2]=='_')) { SetCombat(1); return; } SetCombat(0); }; inline void ResetForwards(void) { m_ChangeclassForward=-1; m_BuiltForward=-1; m_SpawnForward=-1; m_TeamForward=-1; m_RoundStartForward=-1; m_RoundEndForward=-1; m_MapResetForward=-1; }; inline void RegisterForwards(void) { ResetForwards(); m_SpawnForward = MF_RegisterForward("client_spawn",ET_IGNORE,FP_CELL/*id*/,FP_DONE); m_TeamForward = MF_RegisterForward("client_changeteam",ET_IGNORE,FP_CELL/*id*/,FP_CELL/*new team*/,FP_CELL/*old team*/,FP_DONE); m_ChangeclassForward = MF_RegisterForward("client_changeclass", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); m_RoundStartForward = MF_RegisterForward("round_start", ET_IGNORE, FP_DONE); m_RoundEndForward = MF_RegisterForward("round_end", ET_IGNORE, FP_FLOAT, FP_DONE); m_MapResetForward = MF_RegisterForward("map_reset", ET_IGNORE, FP_CELL, FP_DONE); }; inline void StartFrame(void) { if (gpGlobals->time >= m_fRoundStartTime) { g_pFunctionTable->pfnStartFrame=NULL; RoundStart(); } }; /** * This is called from MessageHandler's Countdown * hook. It passes the only byte sent (time) */ inline void HandleCountdown(int &Time) { // Begin hooking start frame g_pFunctionTable->pfnStartFrame=::StartFrame; // set time of round start m_fRoundStartTime=gpGlobals->time + Time; m_SendMapReset = true; }; /** * This is called from MessageHandler's GameStatus * hook. It passes the first byte sent. * 2 = Round End */ inline void HandleGameStatus(int &FirstByte) { switch (FirstByte) { case 0: if (m_SendMapReset) { MF_ExecuteForward(m_MapResetForward, 0); } m_SendMapReset = false; break; case 1: MF_ExecuteForward(m_MapResetForward, 1); break; case 2: RoundEnd(); break; } }; inline void RoundStart() { m_RoundInProgress=1; MF_ExecuteForward(m_RoundStartForward); }; inline void RoundEnd() { m_RoundInProgress=0; MF_ExecuteForward(m_RoundEndForward,gpGlobals->time - m_fRoundStartTime); }; inline int &RoundInProgress() { return m_RoundInProgress; }; // no need to check -1 forwards in these // amxmodx checks it anyway inline void ExecuteClientBuilt(int &PlayerID, int StructureID, int &StructureType, int &Impulse) { MF_ExecuteForward(m_BuiltForward,PlayerID, StructureID, StructureType, Impulse); }; inline void ExecuteClientSpawn(int &PlayerID) { MF_ExecuteForward(m_SpawnForward,PlayerID); }; inline void ExecuteClientChangeTeam(int &PlayerID, int &NewTeam, int &OldTeam) { MF_ExecuteForward(m_TeamForward, PlayerID, NewTeam, OldTeam); }; inline void ExecuteClientChangeClass(int &PlayerID, int &NewClass, int &OldClass) { MF_ExecuteForward(m_ChangeclassForward,PlayerID,NewClass,OldClass); }; inline void ExecuteRoundStart(void) { MF_ExecuteForward(m_RoundStartForward); }; inline void ExecuteRoundEnd(void) { MF_ExecuteForward(m_RoundEndForward); }; /** * The next few functions tell the module what metamod hooks * i need. This tries to run-time optimize out what we * do not need. */ void HookPreThink(void); void HookPostThink_Post(void); void HookPreThink_Post(void); void HookUpdateClientData(void); void HookLogs(void); // AlertMessage AND CreateNamedEntity inline void CheckAllHooks(void) { HookPreThink(); HookPostThink_Post(); HookPreThink_Post(); HookUpdateClientData(); HookLogs(); }; inline void SetTemporaryEdict(edict_t *Edict) { m_SavedEdict=Edict; }; inline edict_t *GetTemporaryEdict(void) { return m_SavedEdict; }; }; extern GameManager GameMan; #endif // GAMEMANAGER_H