diff --git a/src/game/client/cdll_client_int.cpp b/src/game/client/cdll_client_int.cpp index fbc1f34ac..3e89ba283 100644 --- a/src/game/client/cdll_client_int.cpp +++ b/src/game/client/cdll_client_int.cpp @@ -939,6 +939,15 @@ static void RestrictNeoClientCheats() AssertMsg1(false, "convar or concmd named \"%s\" was not found\n", cheatName); } } + +bool NeoIsSteamOffline() +{ +#ifdef NO_STEAM + return false; +#else + return !ClientSteamContext().BLoggedOn(); +#endif +} #endif // Purpose: Called when the DLL is first loaded. diff --git a/src/game/client/cdll_client_int.h b/src/game/client/cdll_client_int.h index 40b4fc294..356125a9c 100644 --- a/src/game/client/cdll_client_int.h +++ b/src/game/client/cdll_client_int.h @@ -127,6 +127,8 @@ extern bool g_bLevelInitialized; extern bool g_bTextMode; #ifdef NEO +bool NeoIsSteamOffline(); + template requires (STR_LIMIT_SIZE > 0) // De-mangle bad Unicode and trim leading and trailing whitespace. diff --git a/src/game/client/neo/ui/neo_root.cpp b/src/game/client/neo/ui/neo_root.cpp index a421191ca..3fadf139b 100644 --- a/src/game/client/neo/ui/neo_root.cpp +++ b/src/game/client/neo/ui/neo_root.cpp @@ -971,6 +971,7 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) } if (NeoUI::Button(m_wszCachedTexts[MMBTN_CREATESERVER]).bPressed) { + DefaultNewGameLanMode(); m_state = STATE_NEWGAME; } if (!bIsInGame) @@ -979,11 +980,19 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) if (NeoUI::Button(m_wszCachedTexts[MMBTN_TUTORIAL]).bPressed) { m_state = STATE_ROOT; + if (NeoIsSteamOffline()) + { + ConVarRef("sv_lan").SetValue(true); + } engine->ClientCmd("sv_use_steam_networking 0; map " TUTORIAL_MAP_CLASSES); } if (NeoUI::Button(m_wszCachedTexts[MMBTN_FIRINGRANGE]).bPressed) { m_state = STATE_ROOT; + if (NeoIsSteamOffline()) + { + ConVarRef("sv_lan").SetValue(true); + } engine->ClientCmd("sv_use_steam_networking 0; map " TUTORIAL_MAP_SHOOTING); } if (NeoUI::Button(L"CREDITS").bPressed) @@ -1509,6 +1518,21 @@ void CNeoRoot::MainLoopSettings(const MainLoopParam param) } } +// Give m_newGame.bLanMode its default from whether Steam is currently reachable. +// For players in Steam offline mode that might not know about sv_lan. +void CNeoRoot::DefaultNewGameLanMode() +{ + const bool bSteamOffline = NeoIsSteamOffline(); + if (m_bLanModeDefaulted && m_bLanModeDefaultedWhileOffline == bSteamOffline) + { + return; + } + + m_newGame.bLanMode = bSteamOffline; + m_bLanModeDefaultedWhileOffline = bSteamOffline; + m_bLanModeDefaulted = true; +} + void CNeoRoot::MainLoopNewGame(const MainLoopParam param) { static const wchar_t *DIFFICULTY_LABELS[] = { L"Easy", L"Normal", L"Hard", L"Expert" }; @@ -1536,6 +1560,7 @@ void CNeoRoot::MainLoopNewGame(const MainLoopParam param) NeoUI::TextEdit(L"Password", m_newGame.wszPassword, SZWSZ_LEN(m_newGame.wszPassword), cl_neo_streamermode.GetBool() ? NeoUI::TEXTEDITFLAG_PASSWORD : NeoUI::TEXTEDITFLAG_NONE); NeoUI::RingBoxBool(L"Friendly fire", &m_newGame.bFriendlyFire); + NeoUI::RingBoxBool(L"LAN mode", &m_newGame.bLanMode); NeoUI::RingBoxBool(L"Use Steam networking", &m_newGame.bUseSteamNetworking); } NeoUI::EndSection(); @@ -1576,7 +1601,8 @@ void CNeoRoot::MainLoopNewGame(const MainLoopParam param) ConVarRef("hostname").SetValue(szHostname); ConVarRef("sv_password").SetValue(szPassword); ConVarRef("mp_friendlyfire").SetValue(m_newGame.bFriendlyFire); - ConVarRef("sv_use_steam_networking").SetValue(m_newGame.bUseSteamNetworking); + ConVarRef("sv_lan").SetValue(m_newGame.bLanMode); + ConVarRef("sv_use_steam_networking").SetValue(!NeoIsSteamOffline() && m_newGame.bUseSteamNetworking); ConVarRef("neo_bot_quota").SetValue(m_newGame.iBotQuota); ConVarRef("neo_bot_difficulty").SetValue(m_newGame.iBotDifficulty); diff --git a/src/game/client/neo/ui/neo_root.h b/src/game/client/neo/ui/neo_root.h index 394a8d507..66edc00fa 100644 --- a/src/game/client/neo/ui/neo_root.h +++ b/src/game/client/neo/ui/neo_root.h @@ -34,6 +34,7 @@ struct NeoNewGame int iBotDifficulty = 2; wchar_t wszPassword[64] = L"neo"; bool bFriendlyFire = true; + bool bLanMode = false; bool bUseSteamNetworking = false; }; @@ -173,6 +174,14 @@ class CNeoRoot : public vgui::EditablePanel, public CGameEventListener NeoSettings m_ns = {}; NeoNewGame m_newGame = {}; + + // m_newGame.bLanMode is defaulted from whether Steam is reachable, since a listen server + // hosted while Steam is offline has to run in LAN mode or the engine's Steam auth drops + // unauthenticated players a couple of minutes in. + void DefaultNewGameLanMode(); + bool m_bLanModeDefaulted = false; + bool m_bLanModeDefaultedWhileOffline = false; + struct MapInfo { wchar_t wszName[64];