Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect neo_game_config, expand gamemode detection #769

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions mp/src/game/client/neo/ui/neo_root.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "tier1/interface.h"
#include <ctime>
#include "ui/neo_loading.h"
#include "neo_gamerules.h"
#include "neo_misc.h"

#include <vgui/IInput.h>
#include <vgui_controls/Controls.h>
Expand Down Expand Up @@ -348,9 +350,9 @@ void CNeoRoot::ApplySchemeSettings(IScheme *pScheme)
g_uiCtx.iMarginY = tall / 108;
g_iAvatar = wide / 30;
const float flWide = static_cast<float>(wide);
float flWideAs43 = static_cast<float>(tall) * (4.0f / 3.0f);
if (flWideAs43 > flWide) flWideAs43 = flWide;
g_iRootSubPanelWide = static_cast<int>(flWideAs43 * 0.9f);
m_flWideAs43 = static_cast<float>(tall) * (4.0f / 3.0f);
if (m_flWideAs43 > flWide) m_flWideAs43 = flWide;
g_iRootSubPanelWide = static_cast<int>(m_flWideAs43 * 0.9f);

constexpr int PARTITION = GSIW__TOTAL * 4;
const int iSubDiv = g_iRootSubPanelWide / PARTITION;
Expand Down Expand Up @@ -669,14 +671,23 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param)

g_uiCtx.dPanel.x = iRightXPos;
g_uiCtx.dPanel.y = iRightSideYStart;
g_uiCtx.dPanel.wide = g_iRootSubPanelWide - iRightXPos + (g_uiCtx.iMarginX * 2);
if (engine->IsInGame())
{
g_uiCtx.dPanel.wide = m_flWideAs43 * 0.7f;
g_uiCtx.flWgXPerc = 0.25f;
}
else
{
g_uiCtx.dPanel.wide = GetWide() - iRightXPos - (g_uiCtx.iMarginX * 2);
}
NeoUI::BeginSection();
{
if (engine->IsInGame())
{
// Show the current server's information
NeoUI::Label(L"Hostname:", m_wszHostname);
NeoUI::Label(L"Map:", m_wszMap);
NeoUI::Label(L"Game mode:", NEO_GAME_TYPE_DESC_STRS[NEORules()->GetGameType()].wszStr);
// TODO: more info, g_PR, scoreboard stuff, etc...
}
else
Expand Down
1 change: 1 addition & 0 deletions mp/src/game/client/neo/ui/neo_root.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class CNeoRoot : public vgui::EditablePanel, public CGameEventListener

bool m_bOnLoadingScreen = false;
int m_iSavedYOffsets[NeoUI::MAX_SECTIONS] = {};
float m_flWideAs43 = 0.0f;
};

extern CNeoRoot *g_pNeoRoot;
3 changes: 2 additions & 1 deletion mp/src/game/client/neo/ui/neo_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ void BeginContext(NeoUI::Context *ctx, const NeoUI::Mode eMode, const wchar_t *w
g_pCtx->eMode = eMode;
g_pCtx->iLayoutY = -(g_pCtx->iYOffset[0] * g_pCtx->iRowTall);
g_pCtx->iWidget = 0;
g_pCtx->iWgXPos = static_cast<int>(g_pCtx->dPanel.wide * 0.4f);
g_pCtx->iSection = 0;
g_pCtx->iHasMouseInPanel = 0;
g_pCtx->iHorizontalWidth = 0;
g_pCtx->iHorizontalMargin = 0;
g_pCtx->flWgXPerc = 0.4f;
g_pCtx->bValueEdited = false;
g_pCtx->eButtonTextStyle = TEXTSTYLE_CENTER;
g_pCtx->eLabelTextStyle = TEXTSTYLE_LEFT;
Expand Down Expand Up @@ -194,6 +194,7 @@ void BeginSection(const bool bDefaultFocus)
g_pCtx->iLayoutY = -(g_pCtx->iYOffset[g_pCtx->iSection] * g_pCtx->iRowTall);
g_pCtx->iWidget = 0;
g_pCtx->iCanActives = 0;
g_pCtx->iWgXPos = static_cast<int>(g_pCtx->dPanel.wide * g_pCtx->flWgXPerc);

g_pCtx->iMouseRelX = g_pCtx->iMouseAbsX - g_pCtx->dPanel.x;
g_pCtx->iMouseRelY = g_pCtx->iMouseAbsY - g_pCtx->dPanel.y;
Expand Down
1 change: 1 addition & 0 deletions mp/src/game/client/neo/ui/neo_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ struct Context
int iPartitionY; // Only increments when Y-pos goes down
int iLayoutX;
int iLayoutY;
float flWgXPerc;
int iWgXPos;
int iYOffset[MAX_SECTIONS] = {};
bool abYMouseDragOffset[MAX_SECTIONS] = {};
Expand Down
2 changes: 2 additions & 0 deletions mp/src/game/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,8 @@ target_sources_grouped(
neo/neo_client.cpp
neo/neo_detpack.cpp
neo/neo_detpack.h
neo/neo_game_config.cpp
neo/neo_game_config.h
neo/neo_ghost_spawn_point.cpp
neo/neo_ghost_spawn_point.h
neo/neo_grenade.cpp
Expand Down
10 changes: 10 additions & 0 deletions mp/src/game/server/neo/neo_game_config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "neo_game_config.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

LINK_ENTITY_TO_CLASS(neo_game_config, CNEOGameConfig);

BEGIN_DATADESC(CNEOGameConfig)
DEFINE_KEYFIELD(m_GameType, FIELD_INTEGER, "GameType"),
END_DATADESC()
14 changes: 14 additions & 0 deletions mp/src/game/server/neo/neo_game_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "cbase.h"
#include "baseentity.h"
#include "neo_gamerules.h"

class CNEOGameConfig : public CLogicalEntity
{
DECLARE_CLASS(CNEOGameConfig, CBaseEntity);
DECLARE_DATADESC();

public:
int m_GameType = NEO_GAME_TYPE_TDM;
};
2 changes: 1 addition & 1 deletion mp/src/game/server/neo/neo_ghost_spawn_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ class CNEOGhostSpawnPoint : public CPointEntity
DECLARE_CLASS(CNEOGhostSpawnPoint, CPointEntity);
};

#endif // NEO_GHOST_SPAWN_POINT_H
#endif // NEO_GHOST_SPAWN_POINT_H
160 changes: 129 additions & 31 deletions mp/src/game/shared/neo/neo_gamerules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "inetchannelinfo.h"
#include "neo_dm_spawn.h"
#include "neo_misc.h"
#include "neo_game_config.h"

extern ConVar weaponstay;
#endif
Expand All @@ -49,14 +50,33 @@ ConVar neo_sv_clantag_allow("neo_sv_clantag_allow", "1", FCVAR_REPLICATED, "", t
ConVar neo_sv_dev_test_clantag("neo_sv_dev_test_clantag", "", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Debug-mode only - Override all clantags with this value.");
#endif

ConVar neo_vote_game_mode("neo_vote_game_mode", "1", FCVAR_USERINFO, "Vote on game mode to play. TDM=0, CTG=1, VIP=2, DM=3", true, 0, true, NEO_GAME_TYPE__TOTAL - 1);
#define STR_GAMEOPTS "TDM=0, CTG=1, VIP=2, DM=3"
#define STR_GAMEBWOPTS "TDM=1, CTG=2, VIP=4, DM=8"
ConVar neo_vote_game_mode("neo_vote_game_mode", "1", FCVAR_USERINFO, "Vote on game mode to play. " STR_GAMEOPTS, true, 0, true, NEO_GAME_TYPE__TOTAL - 1);
ConVar neo_vip_eligible("neo_cl_vip_eligible", "1", FCVAR_ARCHIVE, "Eligible for VIP", true, 0, true, 1);
#ifdef GAME_DLL
ConVar sv_neo_vip_ctg_on_death("sv_neo_vip_ctg_on_death", "0", FCVAR_ARCHIVE, "Spawn Ghost when VIP dies, continue the game", true, 0, true, 1);
#endif

#ifdef GAME_DLL
ConVar sv_neo_change_game_type_mid_round("sv_neo_change_game_type_mid_round", "1", FCVAR_REPLICATED, "Allow game type change mid-match");
// NEO TODO (nullsystem): Change how voting done from convar to menu selection
enum eGamemodeEnforcement
{
GAMEMODE_ENFORCEMENT_MAP = 0, // Only use the gamemode enforced by the map
GAMEMODE_ENFORCEMENT_SINGLE, // Only use the single gamemode enforced by the server
GAMEMODE_ENFORCEMENT_RAND, // Randomly choose a gamemode on each map initialization based on a list
GAMEMODE_ENFORCEMENT_VOTE, // Allow vote by players on pre-match

GAMEMODE_ENFORCEMENT__TOTAL,
};
ConVar neo_sv_gamemode_enforcement("neo_sv_gamemode_enforcement", "0", FCVAR_REPLICATED,
"How the gamemode are determined. 0 = By map, 1 = By neo_sv_gamemode_single, 2 = Random, 3 = Pre-match voting",
true, 0.0f, true, GAMEMODE_ENFORCEMENT__TOTAL - 1);
ConVar neo_sv_gamemode_single("neo_sv_gamemode_single", "3", FCVAR_REPLICATED, "The gamemode that is enforced by the server. " STR_GAMEOPTS,
true, 0.0f, true, NEO_GAME_TYPE__TOTAL - 1);
ConVar neo_sv_gamemode_random_allow("neo_sv_gamemode_random_allow", "11", FCVAR_REPLICATED,
"In bitwise, the gamemodes that are allowed for random selection. Default = TDM+CTG+DM. " STR_GAMEBWOPTS,
true, 1.0f, true, (1 << NEO_GAME_TYPE__TOTAL)); // Can't be zero, minimum has to set to a bitwise value
#endif

#ifdef GAME_DLL
Expand Down Expand Up @@ -244,6 +264,7 @@ extern CBaseEntity *g_pLastJinraiSpawn, *g_pLastNSFSpawn;
static const char *s_NeoPreserveEnts[] =
{
"neo_gamerules",
"neo_game_config",
"info_player_attacker",
"info_player_defender",
"info_player_start",
Expand Down Expand Up @@ -366,10 +387,7 @@ CNEORules::CNEORules()
}
}

if (GetGameType() == NEO_GAME_TYPE_CTG || GetGameType() == NEO_GAME_TYPE_VIP)
{
ResetGhostCapPoints();
}
m_nGameTypeSelected = NEO_GAME_TYPE_CTG;
#endif

ResetMapSessionCommon();
Expand Down Expand Up @@ -641,13 +659,105 @@ void CNEORules::GetDMHighestScorers(
}
}

#ifdef GAME_DLL
void CNEORules::CheckGameType()
{
// Static as CNEORules doesn't persists through map changes
static int iStaticInitOnCmd = -1;
static int iStaticInitOnRandAllow = -1;
static bool staticGamemodesCanPick[NEO_GAME_TYPE__TOTAL] = {};
static int iStaticLastPick = -1; // Mostly so it doesn't repeat on array refresh

const int iGamemodeEnforce = neo_sv_gamemode_enforcement.GetInt();
const int iGamemodeRandAllow = neo_sv_gamemode_random_allow.GetInt();
// Update on what to select on first map load or server operator changes neo_sv_gamemode_enforcement
const bool bCheckOnGameType = (!m_bGamemodeTypeBeenInitialized || iGamemodeEnforce != iStaticInitOnCmd ||
iGamemodeRandAllow != iStaticInitOnRandAllow);
if (!bCheckOnGameType)
{
return;
}

// NEO NOTE (nullsystem): CNEORules always recreated on map change, yet entities properly found
// happens later. So checking and init on game type will execute here once.
switch (iGamemodeEnforce)
{
case GAMEMODE_ENFORCEMENT_SINGLE:
{
m_nGameTypeSelected = neo_sv_gamemode_single.GetInt();
} break;
case GAMEMODE_ENFORCEMENT_RAND:
{
const int iBWAllow = neo_sv_gamemode_random_allow.GetInt(); // Min of 1, cannot be zero
Assert(iBWAllow > 0);

// Check if all are used up
{
int iAllowsPicks = 0;
for (int i = 0; i < NEO_GAME_TYPE__TOTAL; ++i)
{
iAllowsPicks += staticGamemodesCanPick[i];
}
if (iAllowsPicks == 0 || iGamemodeRandAllow != iStaticInitOnRandAllow)
{
#ifdef DEBUG
DevMsg("Array reset!\n");
#endif
// Preset true to those not-allowed, preset false to those allowed
int iTotalPicks = 0;
for (int i = 0; i < NEO_GAME_TYPE__TOTAL; ++i)
{
const bool bCanPick = (iBWAllow & (1 << i));
iTotalPicks += bCanPick;
staticGamemodesCanPick[i] = bCanPick;
}
if (iTotalPicks <= 1)
{
iStaticLastPick = -1;
}
}
}

m_nGameTypeSelected = RandomInt(0, NEO_GAME_TYPE__TOTAL - 1);
for (int iWalk = 0;
(!staticGamemodesCanPick[m_nGameTypeSelected] || m_nGameTypeSelected == iStaticLastPick) &&
iWalk < NEO_GAME_TYPE__TOTAL;
++iWalk)
{
m_nGameTypeSelected = LoopAroundInArray(m_nGameTypeSelected + 1, NEO_GAME_TYPE__TOTAL);
}

#ifdef DEBUG
for (int i = 0; i < NEO_GAME_TYPE__TOTAL; ++i)
{
DevMsg("%d | %s: %s\n", i, NEO_GAME_TYPE_DESC_STRS[i].szStr, staticGamemodesCanPick[i] ? "Allowed" : "Not allowed");
}
DevMsg("Pick: %d | Prev: %d\n", m_nGameTypeSelected.Get(), iStaticLastPick);
#endif

staticGamemodesCanPick[m_nGameTypeSelected] = false;
iStaticLastPick = m_nGameTypeSelected;
} break;
default:
{
const auto pEntGameCfg = static_cast<CNEOGameConfig *>(gEntList.FindEntityByClassname(nullptr, "neo_game_config"));
m_nGameTypeSelected = (pEntGameCfg) ? pEntGameCfg->m_GameType : NEO_GAME_TYPE_CTG;
} break;
}
m_bGamemodeTypeBeenInitialized = true;
iStaticInitOnCmd = iGamemodeEnforce;
iStaticInitOnRandAllow = iGamemodeRandAllow;
}
#endif

void CNEORules::Think(void)
{
#ifdef GAME_DLL
const bool bIsIdleState = m_nRoundStatus == NeoRoundStatus::Idle || m_nRoundStatus == NeoRoundStatus::Warmup;
bool bIsPause = m_nRoundStatus == NeoRoundStatus::Pause;
if (bIsIdleState && gpGlobals->curtime > m_flNeoNextRoundStartTime)
{
CheckGameType();
StartNextRound();
return;
}
Expand Down Expand Up @@ -1881,18 +1991,18 @@ void CNEORules::StartNextRound()

CleanUpMap();

if (neo_sv_gamemode_enforcement.GetInt() == GAMEMODE_ENFORCEMENT_VOTE && m_nRoundStatus == NeoRoundStatus::Warmup)
{
GatherGameTypeVotes();
}

// NEO TODO (nullsystem): There should be a more sophisticated logic to be able to restore XP
// for when moving from idle to preroundfreeze, or in the future, competitive with whatever
// extra stuff in there. But to keep it simple: just clear if it was a warmup.
const bool clearXP = (m_nRoundStatus == NeoRoundStatus::Warmup);
SetRoundStatus(NeoRoundStatus::PreRoundFreeze);
++m_iRoundNumber;

if (!GetGameType() || sv_neo_change_game_type_mid_round.GetBool())
{
GatherGameTypeVotes();
}

for (int i = 1; i <= gpGlobals->maxClients; i++)
{
CNEO_Player *pPlayer = (CNEO_Player*)UTIL_PlayerByIndex(i);
Expand Down Expand Up @@ -1957,11 +2067,6 @@ void CNEORules::StartNextRound()

FireLegacyEvent_NeoRoundEnd();

if (!GetGameType() || sv_neo_change_game_type_mid_round.GetBool())
{
GatherGameTypeVotes();
}

char RoundMsg[27];
static_assert(sizeof(RoundMsg) == sizeof("- CTG ROUND 99 STARTED -\n\0"), "RoundMsg requires to fit round numbers up to 2 digits");
V_sprintf_safe(RoundMsg, "- %s ROUND %d STARTED -\n", GetGameTypeName(), Min(99, m_iRoundNumber.Get()));
Expand Down Expand Up @@ -2032,23 +2137,16 @@ void CNEORules::CreateStandardEntities(void)
#endif
}

const SZWSZTexts NEO_GAME_TYPE_DESC_STRS[NEO_GAME_TYPE__TOTAL] = {
SZWSZ_INIT("Team Deathmatch"),
SZWSZ_INIT("Capture the Ghost"),
SZWSZ_INIT("Extract or Kill the VIP"),
SZWSZ_INIT("Deathmatch"),
};

const char *CNEORules::GetGameDescription(void)
{
//DevMsg("Querying CNEORules game description\n");

// NEO TODO (Rain): get a neo_game_config so we can specify better
switch(GetGameType()) {
case NEO_GAME_TYPE_TDM:
return "Team Deathmatch";
case NEO_GAME_TYPE_CTG:
return "Capture the Ghost";
case NEO_GAME_TYPE_VIP:
return "Extract or Kill the VIP";
case NEO_GAME_TYPE_DM:
return "Deathmatch";
default:
return BaseClass::GetGameDescription();
}
return NEO_GAME_TYPE_DESC_STRS[GetGameType()].szStr;
}

const CViewVectors *CNEORules::GetViewVectors() const
Expand Down
5 changes: 5 additions & 0 deletions mp/src/game/shared/neo/neo_gamerules.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "GameEventListener.h"
#include "neo_player_shared.h"
#include "neo_misc.h"

#ifdef CLIENT_DLL
#include "c_neo_player.h"
Expand Down Expand Up @@ -107,6 +108,8 @@ enum NeoGameType {
NEO_GAME_TYPE__TOTAL // Number of game types
};

extern const SZWSZTexts NEO_GAME_TYPE_DESC_STRS[NEO_GAME_TYPE__TOTAL];

enum NeoRoundStatus {
Idle = 0,
Warmup,
Expand Down Expand Up @@ -257,6 +260,7 @@ class CNEORules : public CHL2MPRules, public CGameEventListener
bool m_bIgnoreOverThreshold = false;
bool ReadyUpPlayerIsReady(CNEO_Player *pNeoPlayer) const;

void CheckGameType();
void StartNextRound();

virtual const char* GetChatFormat(bool bTeamOnly, CBasePlayer* pPlayer) OVERRIDE;
Expand Down Expand Up @@ -376,6 +380,7 @@ class CNEORules : public CHL2MPRules, public CGameEventListener
int m_arrayiEntPrevCap[MAX_PLAYERS + 1]; // This is to check for cap-prevention workaround attempts
int m_iEntPrevCapSize = 0;
int m_iPrintHelpCounter = 0;
bool m_bGamemodeTypeBeenInitialized = false;
#endif
CNetworkVar(int, m_nRoundStatus);
CNetworkVar(int, m_nGameTypeSelected);
Expand Down
Loading