aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobTheBob9 <for.oliver.kirkham@gmail.com>2023-01-08 02:10:48 +0000
committerBobTheBob9 <for.oliver.kirkham@gmail.com>2023-01-08 02:10:48 +0000
commitb78f7dc3f9b277c22843cc289346fc68b29fc087 (patch)
tree31b7bffb57bba8cbac5bc4eb82a92e5ab53fc7c4
parentb56684cd86eeb21ff2a4008938286ff7d593a544 (diff)
downloadNorthstarLauncher-b78f7dc3f9b277c22843cc289346fc68b29fc087.tar.gz
NorthstarLauncher-b78f7dc3f9b277c22843cc289346fc68b29fc087.zip
assign bot teams and fix issue with bot_add occasionally not workin
-rw-r--r--NorthstarDLL/engine/hoststate.cpp2
-rw-r--r--NorthstarDLL/server/auth/serverauthentication.cpp21
-rw-r--r--NorthstarDLL/server/bots.cpp109
-rw-r--r--NorthstarDLL/server/bots.h4
4 files changed, 125 insertions, 11 deletions
diff --git a/NorthstarDLL/engine/hoststate.cpp b/NorthstarDLL/engine/hoststate.cpp
index d474b908..df2e9362 100644
--- a/NorthstarDLL/engine/hoststate.cpp
+++ b/NorthstarDLL/engine/hoststate.cpp
@@ -3,6 +3,7 @@
#include "masterserver/masterserver.h"
#include "server/auth/serverauthentication.h"
#include "server/serverpresence.h"
+#include "server/bots.h"
#include "shared/playlist.h"
#include "core/tier0.h"
#include "engine/r2engine.h"
@@ -105,6 +106,7 @@ void, __fastcall, (CHostState* self))
CHostState__State_ChangeLevelMP(self);
spdlog::info("loading took {}s", Tier0::Plat_FloatTime() - dStartTime);
+ g_pBots->StartMatch();
g_pServerPresence->SetMap(g_pHostState->m_levelName);
}
diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp
index c6283b7a..7b3f7436 100644
--- a/NorthstarDLL/server/auth/serverauthentication.cpp
+++ b/NorthstarDLL/server/auth/serverauthentication.cpp
@@ -399,6 +399,27 @@ void,, (R2::CBaseClient* self, uint32_t unknownButAlways1, const char* pReason,
_CBaseClient__Disconnect(self, unknownButAlways1, buf);
}
+// clang-format off
+AUTOHOOK(CBaseClient__Clear, engine.dll + 0x101480,
+ void, __fastcall, (R2::CBaseClient* self))
+// clang-format on
+{
+ // final cleanup, humans should never hit this without being disconnected already!
+ // bots generally will on level change, however, so this is necessary
+ if (g_pServerAuthentication->m_PlayerAuthenticationData.find(self) != g_pServerAuthentication->m_PlayerAuthenticationData.end())
+ {
+ if (!self->m_bFakePlayer)
+ spdlog::warn("player {} has auth data in CBaseClient::Clear()!");
+
+ // fully cleanup
+ g_pServerAuthentication->RemovePlayerAuthData(self);
+ g_pServerAuthentication->RemovePlayer(self);
+ g_pServerLimits->RemovePlayer(self);
+ }
+
+ CBaseClient__Clear(self);
+}
+
void ConCommand_ns_resetpersistence(const CCommand& args)
{
if (*R2::g_pServerState == R2::server_state_t::ss_active)
diff --git a/NorthstarDLL/server/bots.cpp b/NorthstarDLL/server/bots.cpp
index f1102c42..68473d68 100644
--- a/NorthstarDLL/server/bots.cpp
+++ b/NorthstarDLL/server/bots.cpp
@@ -21,6 +21,7 @@ void (*__fastcall ServerGameClients__ClientFullyConnect)(void* self, uint16_t ed
void (*__fastcall CBasePlayer__RunNullCommand)(R2::CBasePlayer* self);
+// maybe this could be defined in a cfg instead at some point?
const std::vector<const char*> BOT_NAMES = {
// normal titanfall names
"Jack",
@@ -93,13 +94,13 @@ void, __fastcall, (char a1))
}
void ConCommand_bot_add(const CCommand& arg)
-{
- if (arg.ArgC() == 1)
- g_pBots->AddBot();
- else if (arg.ArgC() == 2)
+{
+ if (arg.ArgC() == 2)
g_pBots->AddBot(arg.Arg(1));
- else if (arg.ArgC() == 2)
+ else if (arg.ArgC() == 3)
g_pBots->AddBot(arg.Arg(1), std::stoi(arg.Arg(2)));
+ else
+ g_pBots->AddBot();
}
ServerBotManager::ServerBotManager()
@@ -112,13 +113,58 @@ ServerBotManager::ServerBotManager()
void ServerBotManager::AddBot(const char* pName, int iTeam)
{
if (!*pName)
+ {
+ for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ {
+ R2::CBaseClient* pClient = &R2::g_pClientArray[i];
+ if (pClient->m_Signon >= R2::eSignonState::CONNECTED)
+ {
+ }
+ }
+ }
pName = BOT_NAMES[rand() % BOT_NAMES.size()];
- if (iTeam == -1)
+ const bool bCheckTeams = iTeam == -1;
+ const int nMaxPlayers = std::stoi(R2::GetCurrentPlaylistVar("max_players", true));
+
+ int nPlayers = 0;
+
+ int nImcPlayers = 0;
+ int nMilitiaPlayers = 0;
+
+ // NOTE: doesn't currently support ffa teams
+ for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ {
+ R2::CBaseClient* pClient = &R2::g_pClientArray[i];
+ if (pClient->m_Signon >= R2::eSignonState::CONNECTED)
+ nPlayers++;
+
+ R2::CBasePlayer* pPlayer = R2::UTIL_PlayerByIndex(i + 1);
+ if (!pPlayer)
+ continue;
+
+ if (bCheckTeams)
+ {
+ if (pPlayer->m_nTeam == 2)
+ nImcPlayers++;
+ else
+ nMilitiaPlayers++;
+ }
+ }
+
+ if (nPlayers >= nMaxPlayers)
+ {
+ spdlog::warn("tried to spawn more bots than the server has slots available!");
+ return;
+ }
+
+ if (bCheckTeams)
{
// pick team that needs players
- // oops i cant be bothered just do imc for now
- iTeam = 2;
+ if (nImcPlayers > nMilitiaPlayers)
+ iTeam = 3;
+ else
+ iTeam = 2;
}
const R2::CBaseClient* pPlayer = CBaseServer__CreateFakeClient(pServer, pName, "", "", iTeam);
@@ -131,9 +177,44 @@ void ServerBotManager::AddBot(const char* pName, int iTeam)
// add bots at the start of a game
void ServerBotManager::StartMatch()
{
- int nNumBots = Cvar_bot_quota->GetInt() - g_pServerAuthentication->m_PlayerAuthenticationData.size();
- for (int i = nNumBots; i > 0; i--)
- AddBot();
+ UpdateBotCounts();
+}
+
+void ServerBotManager::UpdateBotCounts()
+{
+ int nNumBots = 0;
+ int nNumHumans = 0;
+
+ for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ {
+ R2::CBaseClient* pClient = &R2::g_pClientArray[i];
+ if (pClient->m_Signon >= R2::eSignonState::CONNECTED)
+ {
+ if (pClient->m_bFakePlayer)
+ nNumBots++;
+ else
+ nNumHumans++;
+ }
+ }
+
+ // ignore specified number of humans unless convar = -1
+ if (Cvar_bot_quota_ignorehumans->GetInt() >= 0)
+ nNumHumans = std::max(0, nNumHumans - Cvar_bot_quota_ignorehumans->GetInt());
+ else
+ nNumHumans = 0;
+
+ int nRequiredBots = Cvar_bot_quota->GetInt() - nNumBots - nNumHumans;
+ if (nRequiredBots >= 0)
+ {
+ for (int i = nRequiredBots; i > 0; i--)
+ AddBot();
+ }
+ else
+ {
+ // remove bots
+ //for (int i = nRequiredBots; i < 0; i++)
+
+ }
}
// setup bot after it connects
@@ -145,6 +226,9 @@ void ServerBotManager::SetupPlayer(R2::CBaseClient* pPlayer)
// every server frame, run bot usercmds
void ServerBotManager::SimulatePlayers()
{
+ if (!Cvar_bot_simulate->GetBool())
+ return;
+
for (int i = 0; i < R2::GetMaxPlayers(); i++)
{
R2::CBaseClient* pClient = &R2::g_pClientArray[i];
@@ -160,7 +244,10 @@ ON_DLL_LOAD_RELIESON("engine.dll", Bots, (ConVar, ConCommand), (CModule module))
{
g_pBots = new ServerBotManager;
g_pBots->Cvar_bot_quota = new ConVar("bot_quota", "0", FCVAR_GAMEDLL, "Minimum number of players when filling game with bots");
+ g_pBots->Cvar_bot_quota_ignorehumans =
+ new ConVar("bot_quota_ignorehumans", "0", FCVAR_GAMEDLL, "Number of human players to ignore for bot_quota, -1 to ignore all (for ignoring spectator players)");
g_pBots->Cvar_bot_clantag = new ConVar("bot_clantag", "BOT", FCVAR_GAMEDLL, "Clantag to give bots");
+ g_pBots->Cvar_bot_simulate = new ConVar("bot_simulate", "1", FCVAR_GAMEDLL, "Whether to run bot movement at all");
g_pBots->Cvar_bot_pilot_settings = new ConVar("bot_pilot_settings", "", FCVAR_GAMEDLL, "force pilot playersettings for bots");
g_pBots->Cvar_bot_force_pilot_primary = new ConVar("bot_force_pilot_primary", "", FCVAR_GAMEDLL, "force pilot primary weapon for bots");
diff --git a/NorthstarDLL/server/bots.h b/NorthstarDLL/server/bots.h
index 62f90370..48adcb7b 100644
--- a/NorthstarDLL/server/bots.h
+++ b/NorthstarDLL/server/bots.h
@@ -7,10 +7,13 @@ class ServerBotManager
public:
ConVar* Cvar_bot_quota;
+ ConVar* Cvar_bot_quota_ignorehumans;
ConVar* Cvar_bot_teams;
ConVar* Cvar_bot_clantag;
+ ConVar* Cvar_bot_simulate;
+
ConVar* Cvar_bot_pilot_settings;
ConVar* Cvar_bot_force_pilot_primary;
ConVar* Cvar_bot_force_pilot_secondary;
@@ -29,6 +32,7 @@ class ServerBotManager
// events we react to
void StartMatch();
+ void UpdateBotCounts();
void SetupPlayer(R2::CBaseClient* pPlayer);
void SimulatePlayers();