diff --git a/r5dev/game/server/physics_main.cpp b/r5dev/game/server/physics_main.cpp index 0990f820..6aa1ebfd 100644 --- a/r5dev/game/server/physics_main.cpp +++ b/r5dev/game/server/physics_main.cpp @@ -5,14 +5,41 @@ // $NoKeywords: $ //=============================================================================// #include "core/stdafx.h" +#include "tier1/cvar.h" #include "player.h" #include "physics_main.h" +#include "engine/client/client.h" +#include "game/shared/util_shared.h" + +//----------------------------------------------------------------------------- +// Purpose: Runs the command simulation for fake players +//----------------------------------------------------------------------------- +void Physics_RunBotSimulation(bool bSimulating) +{ + if (!sv_simulateBots->GetBool()) + return; + + for (int i = 0; i < MAX_PLAYERS; i++) + { + CClient* pClient = g_pClient->GetClient(i); + if (!pClient) + continue; + + if (pClient->IsActive() && pClient->IsFakeClient()) + { + CPlayer* pPlayer = UTIL_PlayerByIndex(i + 1); + if (pPlayer) + pPlayer->RunNullCommand(); + } + } +} //----------------------------------------------------------------------------- // Purpose: Runs the main physics simulation loop against all entities ( except players ) //----------------------------------------------------------------------------- void Physics_RunThinkFunctions(bool bSimulating) { + Physics_RunBotSimulation(bSimulating); v_Physics_RunThinkFunctions(bSimulating); } diff --git a/r5dev/game/server/player.h b/r5dev/game/server/player.h index 090ff8e2..795e788a 100644 --- a/r5dev/game/server/player.h +++ b/r5dev/game/server/player.h @@ -20,6 +20,13 @@ #include "basecombatcharacter.h" #include +enum PlayerConnectedState +{ + PlayerConnected, + PlayerDisconnecting, + PlayerDisconnected, +}; + // TODO: Move to separate header file!! struct ThirdPersonViewData @@ -244,6 +251,9 @@ public: void PlayerRunCommand(CUserCmd* pUserCmd, IMoveHelper* pMover); void SetLastUserCommand(CUserCmd* pUserCmd); + bool IsConnected() const { return m_iConnected != PlayerDisconnected; } + bool IsDisconnecting() const { return m_iConnected == PlayerDisconnecting; } + private: int m_StuckLast; char gap_5a8c[4]; diff --git a/r5dev/game/shared/usercmd.h b/r5dev/game/shared/usercmd.h index 0cefdf22..52e89aa6 100644 --- a/r5dev/game/shared/usercmd.h +++ b/r5dev/game/shared/usercmd.h @@ -38,7 +38,7 @@ public: CUserCmd* Copy(CUserCmd* pSource) { - v_CUserCmd__Copy(this, pSource); + return v_CUserCmd__Copy(this, pSource); } int32_t command_number; diff --git a/r5dev/game/shared/util_shared.cpp b/r5dev/game/shared/util_shared.cpp index 3370bda8..1ad82542 100644 --- a/r5dev/game/shared/util_shared.cpp +++ b/r5dev/game/shared/util_shared.cpp @@ -15,6 +15,11 @@ CPlayer* UTIL_PlayerByIndex(int nIndex) { + if (nIndex < 1 || nIndex > g_pGlobals->m_nMaxClients || nIndex == FL_EDICT_INVALID) + return nullptr; + // !TODO: Improve this!!! + CPlayer* pPlayer = *reinterpret_cast(g_pGlobals->m_pInterlock + nIndex + 0x7808); + return pPlayer; } #endif // CLIENT_DLL diff --git a/r5dev/game/shared/util_shared.h b/r5dev/game/shared/util_shared.h index e69de29b..986bc616 100644 --- a/r5dev/game/shared/util_shared.h +++ b/r5dev/game/shared/util_shared.h @@ -0,0 +1,16 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#ifndef UTIL_SHARED_H +#define UTIL_SHARED_H +#ifndef CLIENT_DLL +#include "game/server/player.h" +#endif + +#ifndef CLIENT_DLL +CPlayer* UTIL_PlayerByIndex(int nIndex); +#endif // CLIENT_DLL + +#endif // !UTIL_SHARED_H diff --git a/r5dev/tier1/IConVar.cpp b/r5dev/tier1/IConVar.cpp index 5c1a2b99..387e603b 100644 --- a/r5dev/tier1/IConVar.cpp +++ b/r5dev/tier1/IConVar.cpp @@ -107,6 +107,7 @@ void ConVar::Init(void) sv_statusRefreshRate = ConVar::Create("sv_statusRefreshRate" , "0.5", FCVAR_RELEASE, "Server status refresh rate (seconds).", false, 0.f, false, 0.f, nullptr, nullptr); sv_autoReloadRate = ConVar::Create("sv_autoReloadRate" , "0" , FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null). ", true, 0.f, false, 0.f, nullptr, nullptr); sv_quota_stringCmdsPerSecond = ConVar::Create("sv_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands.", true, 0.f, false, 0.f, nullptr, nullptr); + sv_simulateBots = ConVar::Create("sv_simulateBots", "1", FCVAR_RELEASE, "Simulate user commands for bots on the server.", true, 0.f, false, 0.f, nullptr, nullptr); #ifdef DEDICATED sv_rcon_debug = ConVar::Create("sv_rcon_debug" , "0" , FCVAR_RELEASE, "Show rcon debug information ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); sv_rcon_sendlogs = ConVar::Create("sv_rcon_sendlogs" , "0" , FCVAR_RELEASE, "Network console logs to connected and authenticated sockets.", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/tier1/cvar.cpp b/r5dev/tier1/cvar.cpp index 1665d519..48412c51 100644 --- a/r5dev/tier1/cvar.cpp +++ b/r5dev/tier1/cvar.cpp @@ -74,6 +74,8 @@ ConVar* sv_forceChatToTeamOnly = nullptr; ConVar* sv_autoReloadRate = nullptr; ConVar* sv_quota_stringCmdsPerSecond = nullptr; +ConVar* sv_simulateBots = nullptr; + #ifdef DEDICATED ConVar* sv_rcon_debug = nullptr; ConVar* sv_rcon_sendlogs = nullptr; diff --git a/r5dev/tier1/cvar.h b/r5dev/tier1/cvar.h index 82446557..4e3b3442 100644 --- a/r5dev/tier1/cvar.h +++ b/r5dev/tier1/cvar.h @@ -70,6 +70,8 @@ extern ConVar* sv_forceChatToTeamOnly; extern ConVar* sv_autoReloadRate; extern ConVar* sv_quota_stringCmdsPerSecond; +extern ConVar* sv_simulateBots; + #ifdef DEDICATED extern ConVar* sv_rcon_debug; extern ConVar* sv_rcon_sendlogs;