From c850e45ed2ba8884bec6a84a2d3fb449c9d57753 Mon Sep 17 00:00:00 2001 From: jeefo Date: Tue, 12 Jan 2016 23:57:02 +0300 Subject: [PATCH] some rework of autovacate... again --- include/core.h | 11 ++++++ source/interface.cpp | 22 ++++++++++++ source/manager.cpp | 80 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/include/core.h b/include/core.h index f712265..cd0ebc8 100644 --- a/include/core.h +++ b/include/core.h @@ -203,6 +203,14 @@ enum TaskID TASK_MAX }; +// autovacate state +enum QuotaOption +{ + QUOTA_NONE, + QUOTA_INCREMENT, + QUOTA_DECREMENT +}; + // supported cs's enum CSVersion { @@ -1367,6 +1375,8 @@ private: Array m_activeGrenades; edict_t *m_killerEntity; // killer entity for bots + int m_quotaOption; + protected: int CreateBot (const String &name, int difficulty, int personality, int team, int member); @@ -1411,6 +1421,7 @@ public: void RemoveMenu (edict_t *ent, int selection); void KillAll (int team = -1); void MaintainBotQuota (void); + void AdjustQuota (bool isPlayerConnection, edict_t *ent); void InitQuota (void); void ListBots (void); diff --git a/source/interface.cpp b/source/interface.cpp index d1778ce..3d3cd93 100644 --- a/source/interface.cpp +++ b/source/interface.cpp @@ -1111,6 +1111,25 @@ int ClientConnect (edict_t *ent, const char *name, const char *addr, char reject return (*g_functionTable.pfnClientConnect) (ent, name, addr, rejectReason); } +void ClientPutInServer (edict_t *ent) +{ + // this function is called once a just connected client actually enters the game, after + // having downloaded and synchronized its resources with the of the server's. It's the + // perfect place to hook for client connecting, since a client can always try to connect + // passing the ClientConnect() step, and not be allowed by the server later (because of a + // latency timeout or whatever reason). We can here keep track of both bots and players + // counts on occurence, since bots connect the server just like the way normal client do, + // and their third party bot flag is already supposed to be set then. If it's a bot which + // is connecting, we also have to awake its brain(s) by reading them from the disk. + + bots.AdjustQuota (true, ent); + + if (g_isMetamod) + RETURN_META (MRES_IGNORED); + + (*g_functionTable.pfnClientPutInServer) (ent); +} + void ClientDisconnect (edict_t *ent) { // this function is called whenever a client is VOLUNTARILY disconnected from the server, @@ -1124,6 +1143,8 @@ void ClientDisconnect (edict_t *ent) // to reset his entity pointer for safety. There are still a few server frames to go once a // listen server client disconnects, and we don't want to send him any sort of message then. + bots.AdjustQuota (false, ent); + int i = IndexOfEntity (ent) - 1; InternalAssert (i >= 0 && i < 32); @@ -2819,6 +2840,7 @@ export int GetEntityAPI2 (gamefuncs_t *functionTable, int *) functionTable->pfnTouch = Touch; functionTable->pfnClientConnect = ClientConnect; functionTable->pfnClientDisconnect = ClientDisconnect; + functionTable->pfnClientPutInServer = ClientPutInServer; functionTable->pfnClientUserInfoChanged = ClientUserInfoChanged; functionTable->pfnClientCommand = ClientCommand; functionTable->pfnServerActivate = ServerActivate; diff --git a/source/manager.cpp b/source/manager.cpp index 2612f64..979db9a 100644 --- a/source/manager.cpp +++ b/source/manager.cpp @@ -9,11 +9,10 @@ #include -ConVar yb_autovacate ("yb_autovacate", "-1"); +ConVar yb_autovacate ("yb_autovacate", "0"); -ConVar yb_quota ("yb_quota", "0"); -ConVar yb_quota_match ("yb_quota_match", "0"); -ConVar yb_quota_match_max ("yb_quota_match_max", "0"); +ConVar yb_quota ("yb_quota", "0", VT_NORMAL); +ConVar yb_quota_mode ("yb_quota_mode", "normal"); ConVar yb_join_after_player ("yb_join_after_player", "0"); ConVar yb_join_team ("yb_join_team", "any"); @@ -333,9 +332,21 @@ void BotManager::AddBot (const String &name, const String &difficulty, const Str m_creationTab.Push (bot); + int newBotsNum = GetBotsNum () + 1; + // keep quota number up to date - if (GetBotsNum () + 1 > yb_quota.GetInt ()) - yb_quota.SetInt (GetBotsNum () + 1); + if (newBotsNum < GetMaxClients () && newBotsNum > yb_quota.GetInt ()) + yb_quota.SetInt (newBotsNum); +} + +void BotManager::AdjustQuota (bool isPlayerConnection, edict_t *ent) +{ + // this function increases or decreases bot quota amount depending on autovacate variables + + if (!IsDedicatedServer () || !yb_autovacate.GetBool () || GetBot (ent) != NULL) + return; + + m_quotaOption = isPlayerConnection ? QUOTA_DECREMENT : QUOTA_INCREMENT; } void BotManager::MaintainBotQuota (void) @@ -346,12 +357,7 @@ void BotManager::MaintainBotQuota (void) if (g_numWaypoints < 1 || g_waypointsChanged) return; - if (yb_join_after_player.GetInt () > 0 && GetHumansJoinedTeam () == 0) - { - RemoveAll (false); - return; - } - + // bot's creation update if (!m_creationTab.IsEmpty () && m_maintainTime < GetWorldTime ()) { CreateQueue last = m_creationTab.Pop (); @@ -374,6 +380,46 @@ void BotManager::MaintainBotQuota (void) // now keep bot number up to date if (m_maintainTime < GetWorldTime ()) { + // don't allow that quota is below zero + if (yb_quota.GetInt () < 0) + yb_quota.SetInt (0); + + int numBots = GetBotsNum (); + int numHumans = GetHumansJoinedTeam (); + int desiredCount = yb_quota.GetInt (); + + if (yb_join_after_player.GetInt () > 0 && !numHumans) + desiredCount = 0; + + if (m_quotaOption != QUOTA_NONE && numBots > 1 && desiredCount > 1) + { + if (m_quotaOption == QUOTA_INCREMENT) + desiredCount++; + else + desiredCount--; + } + + // quota mode + char mode = yb_quota_mode.GetString ()[0]; + + if (mode == 'f') // fill + desiredCount = max (0, desiredCount - numHumans); + else if (mode == 'm') // match + desiredCount = max (0, yb_quota.GetInt () * numHumans); + + if (yb_autovacate.GetBool ()) + desiredCount = min (desiredCount, GetMaxClients () - (numHumans + 1)); + else + desiredCount = min (desiredCount, GetMaxClients () - numHumans); + + m_quotaOption = QUOTA_NONE; + + if (desiredCount > numBots) + AddRandom (); + else if (desiredCount < numBots) + RemoveRandom (); + +#if 0 int botNumber = GetBotsNum (); int humanNumber = GetHumansNum (); @@ -396,7 +442,7 @@ void BotManager::MaintainBotQuota (void) if (yb_autovacate.GetBool ()) { - if (botNumber < yb_quota.GetInt () && botNumber < GetMaxClients () - 1) + if (botNumber < yb_quota.GetInt () && humanNumber < GetMaxClients () - 1) AddRandom (); if (humanNumber >= GetMaxClients ()) @@ -404,11 +450,11 @@ void BotManager::MaintainBotQuota (void) } else { - if (botNumber < yb_quota.GetInt () && botNumber < GetMaxClients ()) + if (botNumber < yb_quota.GetInt () && humanNumber < GetMaxClients ()) AddRandom (); } - int botQuota = yb_autovacate.GetBool () ? (GetMaxClients () - 1 - (humanNumber + 1)) : GetMaxClients (); + int botQuota = yb_autovacate.GetBool () ? GetMaxClients () - humanNumber : GetMaxClients (); // check valid range of quota if (yb_quota.GetInt () > botQuota) @@ -416,7 +462,7 @@ void BotManager::MaintainBotQuota (void) else if (yb_quota.GetInt () < 0) yb_quota.SetInt (0); - +#endif m_maintainTime = GetWorldTime () + 0.15f; } } @@ -425,6 +471,7 @@ void BotManager::InitQuota (void) { m_maintainTime = GetWorldTime () + 3.0f; m_creationTab.RemoveAll (); + m_quotaOption = QUOTA_NONE; } void BotManager::FillServer (int selection, int personality, int difficulty, int numToAdd) @@ -458,7 +505,6 @@ void BotManager::FillServer (int selection, int personality, int difficulty, int AddBot ("", difficulty, personality, selection, -1); yb_quota.SetInt (toAdd); - yb_quota_match.SetInt (0); CenterPrint ("Fill Server with %s bots...", &teamDesc[selection][0]); }