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
# 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
AiPlayerbot.DeleteRandomBotArenaTeams = 0

View File

@@ -335,8 +335,12 @@ bool PlayerbotAIConfig::Initialize()
randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", true);
// 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);
randomBotArenaTeamMaxRating = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeamMaxRating", 2000);
randomBotArenaTeamMinRating = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeamMinRating", 1000);
selfBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.SelfBotLevel", 1);

View File

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

View File

@@ -5,6 +5,7 @@
#include "PlayerbotFactory.h"
#include "AccountMgr.h"
#include "AiFactory.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "DBCStores.h"
#include "DBCStructure.h"
@@ -363,14 +364,14 @@ void PlayerbotFactory::Randomize(bool incremental)
//if (pmo)
// pmo->finish();
// if (bot->GetLevel() >= 70)
// {
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas");
// LOG_INFO("playerbots", "Initializing arena teams...");
// InitArenaTeam();
// if (pmo)
// pmo->finish();
// }
if (bot->GetLevel() >= 70)
{
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas");
LOG_INFO("playerbots", "Initializing arena teams...");
InitArenaTeam();
if (pmo)
pmo->finish();
}
if (!incremental) {
bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true);
@@ -3268,8 +3269,39 @@ void PlayerbotFactory::InitArenaTeam()
if (!sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId()))
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())
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;
for (std::vector<uint32>::iterator i = sPlayerbotAIConfig->randomBotArenaTeams.begin(); i != sPlayerbotAIConfig->randomBotArenaTeams.end(); ++i)
@@ -3281,28 +3313,47 @@ void PlayerbotFactory::InitArenaTeam()
return;
}
int index = urand(0, arenateams.size() - 1);
uint32 arenateamID = arenateams[index];
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID);
if (!arenateam)
while (!arenateams.empty())
{
LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID);
return;
}
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?
int index = urand(0, arenateams.size() - 1);
uint32 arenateamID = arenateams[index];
ArenaTeam *arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID);
if (!arenateam)
{
arenateam->AddMember(bot->GetGUID());
arenateam->SaveToDB();
LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID);
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);

View File

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

View File

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