Allow greater control of Arena team creation

This commit is contained in:
CrypticAvacado
2024-07-29 04:07:10 +12:00
parent a01302f348
commit 5240a2d1ff
6 changed files with 120 additions and 73 deletions

View File

@@ -655,7 +655,19 @@ AiPlayerbot.RandomBotJoinBG = 1
AiPlayerbot.RandomBotAutoJoinBG = 0 AiPlayerbot.RandomBotAutoJoinBG = 0
# Random bot arena team count # Random bot arena team count
AiPlayerbot.RandomBotArenaTeamCount = 20 # Teams are created when bots are initialized on server restart.
# You may need to first delete all arena teams, then reinitialize bots.
# Warning: Reinitializing bots completely resets them (command in game: .playerbots rndbot init)
# Bots only join one arena team to avoid queueing issues. Take that into account when increasing count.
# Default: 2v2: 10 (20 Bots), 3v3: 10 (30 bots), 5v5: 5 (25 bots).
AiPlayerbot.RandomBotArenaTeam2v2Count = 10
AiPlayerbot.RandomBotArenaTeam3v3Count = 10
AiPlayerbot.RandomBotArenaTeam5v5Count = 5
# Arena rating is randomized on team creation.
# Default: Max: 2000, Min: 1000.
AiPlayerbot.RandomBotArenaTeamMaxRating = 2000
AiPlayerbot.RandomBotArenaTeamMinRating = 1000
# Delete all random bot arena teams # Delete all random bot arena teams
AiPlayerbot.DeleteRandomBotArenaTeams = 0 AiPlayerbot.DeleteRandomBotArenaTeams = 0

View File

@@ -335,8 +335,12 @@ bool PlayerbotAIConfig::Initialize()
randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", true); randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", true);
// arena // arena
randomBotArenaTeamCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeamCount", 20); randomBotArenaTeam2v2Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeam2v2Count", 10);
randomBotArenaTeam3v3Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeam3v3Count", 10);
randomBotArenaTeam5v5Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeam5v5Count", 5);
deleteRandomBotArenaTeams = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotArenaTeams", false); deleteRandomBotArenaTeams = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotArenaTeams", false);
randomBotArenaTeamMaxRating = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeamMaxRating", 2000);
randomBotArenaTeamMinRating = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeamMinRating", 1000);
selfBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.SelfBotLevel", 1); selfBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.SelfBotLevel", 1);

View File

@@ -211,6 +211,11 @@ class PlayerbotAIConfig
uint32 tweakValue; //Debugging config uint32 tweakValue; //Debugging config
uint32 randomBotArenaTeamCount; uint32 randomBotArenaTeamCount;
uint32 randomBotArenaTeamMaxRating;
uint32 randomBotArenaTeamMinRating;
uint32 randomBotArenaTeam2v2Count;
uint32 randomBotArenaTeam3v3Count;
uint32 randomBotArenaTeam5v5Count;
bool deleteRandomBotArenaTeams; bool deleteRandomBotArenaTeams;
std::vector<uint32> randomBotArenaTeams; std::vector<uint32> randomBotArenaTeams;

View File

@@ -5,6 +5,7 @@
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "AccountMgr.h" #include "AccountMgr.h"
#include "AiFactory.h" #include "AiFactory.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h" #include "ArenaTeamMgr.h"
#include "DBCStores.h" #include "DBCStores.h"
#include "DBCStructure.h" #include "DBCStructure.h"
@@ -363,14 +364,14 @@ void PlayerbotFactory::Randomize(bool incremental)
//if (pmo) //if (pmo)
// pmo->finish(); // pmo->finish();
// if (bot->GetLevel() >= 70) if (bot->GetLevel() >= 70)
// { {
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas"); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas");
// LOG_INFO("playerbots", "Initializing arena teams..."); LOG_INFO("playerbots", "Initializing arena teams...");
// InitArenaTeam(); InitArenaTeam();
// if (pmo) if (pmo)
// pmo->finish(); pmo->finish();
// } }
if (!incremental) { if (!incremental) {
bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true); bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true);
@@ -3268,8 +3269,39 @@ void PlayerbotFactory::InitArenaTeam()
if (!sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId())) if (!sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId()))
return; return;
// Currently the teams are only remade after a server restart and if deleteRandomBotArenaTeams = 1
// This is because randomBotArenaTeams is only empty on server restart.
// A manual reinitalization (.playerbots rndbot init) is also required after the teams have been deleted.
if (sPlayerbotAIConfig->randomBotArenaTeams.empty()) if (sPlayerbotAIConfig->randomBotArenaTeams.empty())
RandomPlayerbotFactory::CreateRandomArenaTeams(); {
if (sPlayerbotAIConfig->deleteRandomBotArenaTeams)
{
LOG_INFO("playerbots", "Deleting random bot arena teams...");
for (auto it = sArenaTeamMgr->GetArenaTeams().begin(); it != sArenaTeamMgr->GetArenaTeams().end(); ++it) {
ArenaTeam* arenateam = it->second;
if (arenateam->GetCaptain() && arenateam->GetCaptain().IsPlayer())
{
Player* bot = ObjectAccessor::FindPlayer(arenateam->GetCaptain());
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI || botAI->IsRealPlayer())
{
continue;
}
else
{
arenateam->Disband(nullptr);
}
}
}
LOG_INFO("playerbots", "Random bot arena teams deleted");
}
RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_2v2, sPlayerbotAIConfig->randomBotArenaTeam2v2Count);
RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_3v3, sPlayerbotAIConfig->randomBotArenaTeam3v3Count);
RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_5v5, sPlayerbotAIConfig->randomBotArenaTeam5v5Count);
}
std::vector<uint32> arenateams; std::vector<uint32> arenateams;
for (std::vector<uint32>::iterator i = sPlayerbotAIConfig->randomBotArenaTeams.begin(); i != sPlayerbotAIConfig->randomBotArenaTeams.end(); ++i) for (std::vector<uint32>::iterator i = sPlayerbotAIConfig->randomBotArenaTeams.begin(); i != sPlayerbotAIConfig->randomBotArenaTeams.end(); ++i)
@@ -3281,28 +3313,47 @@ void PlayerbotFactory::InitArenaTeam()
return; return;
} }
int index = urand(0, arenateams.size() - 1); while (!arenateams.empty())
uint32 arenateamID = arenateams[index];
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID);
if (!arenateam)
{ {
LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID); int index = urand(0, arenateams.size() - 1);
return; uint32 arenateamID = arenateams[index];
} ArenaTeam *arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID);
if (!arenateam)
if (arenateam->GetMembersSize() < ((uint32)arenateam->GetType() * 2) && bot->GetLevel() >= 70)
{
ObjectGuid capt = arenateam->GetCaptain();
Player* botcaptain = ObjectAccessor::FindPlayer(capt);
if ((bot && bot->GetArenaTeamId(arenateam->GetSlot())) || sCharacterCache->GetCharacterArenaTeamIdByGuid(bot->GetGUID(), arenateam->GetSlot()) != 0)
return;
if (botcaptain && botcaptain->GetTeamId() == bot->GetTeamId()) //need?
{ {
arenateam->AddMember(bot->GetGUID()); LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID);
arenateam->SaveToDB(); arenateams.erase(arenateams.begin() + index);
continue;
} }
if (arenateam->GetMembersSize() < ((uint32)arenateam->GetType()) && bot->GetLevel() >= 70)
{
ObjectGuid capt = arenateam->GetCaptain();
Player* botcaptain = ObjectAccessor::FindPlayer(capt);
// To avoid bots removing each other from groups when queueing, force them to only be in one team
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
uint32 arenaTeamId = bot->GetArenaTeamId(arena_slot);
if (!arenaTeamId)
continue;
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenaTeamId);
if (team){
if (sCharacterCache->GetCharacterArenaTeamIdByGuid(bot->GetGUID(), team->GetSlot()) != 0)
{
return;
}
return;
}
}
if (botcaptain && botcaptain->GetTeamId() == bot->GetTeamId()) // need?
{
arenateam->AddMember(bot->GetGUID());
arenateam->SaveToDB();
}
}
arenateams.erase(arenateams.begin() + index);
} }
bot->SaveToDB(false, false); bot->SaveToDB(false, false);

View File

@@ -618,7 +618,7 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName()
return std::move(guildName); return std::move(guildName);
} }
void RandomPlayerbotFactory::CreateRandomArenaTeams() void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count)
{ {
std::vector<uint32> randomBots; std::vector<uint32> randomBots;
@@ -635,28 +635,12 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams()
while (result->NextRow()); while (result->NextRow());
} }
if (sPlayerbotAIConfig->deleteRandomBotArenaTeams)
{
LOG_INFO("playerbots", "Deleting random bot arena teams...");
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
{
ObjectGuid captain = ObjectGuid::Create<HighGuid::Player>(*i);
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain);
if (arenateam)
//sObjectMgr->RemoveArenaTeam(arenateam->GetId());
arenateam->Disband(nullptr);
}
LOG_INFO("playerbots", "Random bot arena teams deleted");
}
uint32 arenaTeamNumber = 0; uint32 arenaTeamNumber = 0;
GuidVector availableCaptains; GuidVector availableCaptains;
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i) for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
{ {
ObjectGuid captain = ObjectGuid::Create<HighGuid::Player>(*i); ObjectGuid captain = ObjectGuid::Create<HighGuid::Player>(*i);
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain); ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain, type);
if (arenateam) if (arenateam)
{ {
++arenaTeamNumber; ++arenaTeamNumber;
@@ -671,7 +655,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams()
} }
} }
for (; arenaTeamNumber < sPlayerbotAIConfig->randomBotArenaTeamCount; ++arenaTeamNumber) for (; arenaTeamNumber < count; ++arenaTeamNumber)
{ {
std::string const arenaTeamName = CreateRandomArenaTeamName(); std::string const arenaTeamName = CreateRandomArenaTeamName();
if (arenaTeamName.empty()) if (arenaTeamName.empty())
@@ -698,29 +682,17 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams()
continue; continue;
} }
QueryResult results = CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'", arenaTeamName.c_str()); // Below query no longer required as now user has control over the number of each type of arena team they want to create.
if (!results) // Keeping commented for potential future reference.
{ // QueryResult results = CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'", arenaTeamName.c_str());
LOG_ERROR("playerbots", "No valid types for arena teams"); // if (!results)
return; // {
} // LOG_ERROR("playerbots", "No valid types for arena teams");
// return;
// }
Field* fields = results->Fetch(); // Field* fields = results->Fetch();
uint8 slot = fields[0].Get<uint8>(); // uint8 slot = fields[0].Get<uint8>();
ArenaType type;
switch (slot)
{
case 2:
type = ARENA_TYPE_2v2;
break;
case 3:
type = ARENA_TYPE_3v3;
break;
case 5:
type = ARENA_TYPE_5v5;
break;
}
ArenaTeam* arenateam = new ArenaTeam(); ArenaTeam* arenateam = new ArenaTeam();
if (!arenateam->Create(player->GetGUID(), type, arenaTeamName, 0, 0, 0, 0, 0)) if (!arenateam->Create(player->GetGUID(), type, arenaTeamName, 0, 0, 0, 0, 0))
@@ -732,7 +704,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams()
arenateam->SetCaptain(player->GetGUID()); arenateam->SetCaptain(player->GetGUID());
// set random rating // set random rating
arenateam->SetRatingForAll(urand(1500, 2700)); arenateam->SetRatingForAll(urand(sPlayerbotAIConfig->randomBotArenaTeamMinRating, sPlayerbotAIConfig->randomBotArenaTeamMaxRating));
// set random emblem // set random emblem
uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF); uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF);

View File

@@ -10,10 +10,13 @@
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "DBCEnums.h"
class Player; class Player;
class WorldSession; class WorldSession;
enum ArenaType : uint8;
class RandomPlayerbotFactory class RandomPlayerbotFactory
{ {
public: public:
@@ -23,7 +26,7 @@ class RandomPlayerbotFactory
Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<uint8, std::vector<std::string>> names); Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<uint8, std::vector<std::string>> names);
static void CreateRandomBots(); static void CreateRandomBots();
static void CreateRandomGuilds(); static void CreateRandomGuilds();
static void CreateRandomArenaTeams(); static void CreateRandomArenaTeams(ArenaType slot, uint32 count);
static std::string const CreateRandomGuildName(); static std::string const CreateRandomGuildName();
private: private: