mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Fix arena
This commit is contained in:
parent
fd5910e4b6
commit
3d0fb90c4f
@ -11,6 +11,7 @@
|
||||
#include "AiFactory.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "CharacterCache.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DBCStructure.h"
|
||||
#include "GuildMgr.h"
|
||||
@ -450,7 +451,6 @@ void PlayerbotFactory::Randomize(bool incremental)
|
||||
if (bot->GetLevel() >= 70)
|
||||
{
|
||||
pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas");
|
||||
// LOG_INFO("playerbots", "Initializing arena teams...");
|
||||
InitArenaTeam();
|
||||
if (pmo)
|
||||
pmo->finish();
|
||||
@ -4049,125 +4049,112 @@ void PlayerbotFactory::InitImmersive()
|
||||
|
||||
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())
|
||||
{
|
||||
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)
|
||||
arenateams.push_back(*i);
|
||||
|
||||
if (arenateams.empty())
|
||||
{
|
||||
LOG_ERROR("playerbots", "No random arena team available");
|
||||
return;
|
||||
}
|
||||
|
||||
while (!arenateams.empty())
|
||||
{
|
||||
int index = urand(0, arenateams.size() - 1);
|
||||
uint32 arenateamID = arenateams[index];
|
||||
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID);
|
||||
if (!arenateam)
|
||||
{
|
||||
LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID);
|
||||
arenateams.erase(arenateams.begin() + index);
|
||||
continue;
|
||||
}
|
||||
if (bot->GetLevel() < 70)
|
||||
return;
|
||||
|
||||
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
|
||||
// One team max to avoid queueing conflicts
|
||||
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
|
||||
{
|
||||
uint32 arenaTeamId = bot->GetArenaTeamId(arena_slot);
|
||||
if (!arenaTeamId)
|
||||
if (bot->GetArenaTeamId(arena_slot))
|
||||
return;
|
||||
}
|
||||
|
||||
// If captains are still needed, create a team with this bot as captain.
|
||||
for (auto& [type, needed] : sRandomPlayerbotMgr.arenaCaptainsNeeded)
|
||||
{
|
||||
if (needed > 0)
|
||||
{
|
||||
if (CreateArenaTeamWithCaptain(type))
|
||||
--needed;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sRandomPlayerbotMgr.arenaTeamsFull)
|
||||
AssignToArenaTeam();
|
||||
}
|
||||
|
||||
bool PlayerbotFactory::CreateArenaTeamWithCaptain(ArenaType type)
|
||||
{
|
||||
std::string teamName = RandomPlayerbotFactory::CreateRandomArenaTeamName();
|
||||
if (teamName.empty())
|
||||
return false;
|
||||
|
||||
ArenaTeam* arenateam = new ArenaTeam();
|
||||
if (!arenateam->Create(bot->GetGUID(), type, teamName, 0, 0, 0, 0, 0))
|
||||
{
|
||||
LOG_ERROR("playerbots", "Error creating arena team {}", teamName);
|
||||
delete arenateam;
|
||||
return false;
|
||||
}
|
||||
|
||||
arenateam->SetCaptain(bot->GetGUID());
|
||||
arenateam->SetRatingForAll(
|
||||
urand(sPlayerbotAIConfig.randomBotArenaTeamMinRating, sPlayerbotAIConfig.randomBotArenaTeamMaxRating));
|
||||
|
||||
uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
uint32 emblemStyle = urand(0, 101);
|
||||
uint32 emblemColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
uint32 borderStyle = urand(0, 5);
|
||||
uint32 borderColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
arenateam->SetEmblem(backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor);
|
||||
|
||||
arenateam->SaveToDB();
|
||||
sArenaTeamMgr->AddArenaTeam(arenateam);
|
||||
|
||||
LOG_DEBUG("playerbots", "Created {}v{} arena team '{}' with captain {}",
|
||||
type, type, teamName, bot->GetName());
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerbotFactory::AssignToArenaTeam()
|
||||
{
|
||||
ArenaTeam* arenateam = nullptr;
|
||||
for (auto const& [id, team] : sArenaTeamMgr->GetArenaTeams())
|
||||
{
|
||||
if (team->GetMembersSize() >= static_cast<uint32>(team->GetType()))
|
||||
continue;
|
||||
|
||||
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenaTeamId);
|
||||
if (team)
|
||||
{
|
||||
if (sCharacterCache->GetCharacterArenaTeamIdByGuid(bot->GetGUID(), team->GetSlot()) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!RandomPlayerbotFactory::IsBotArenaTeam(team))
|
||||
continue;
|
||||
|
||||
ObjectGuid captainGuid = team->GetCaptain();
|
||||
CharacterCacheEntry const* captainEntry = sCharacterCache->GetCharacterCacheByGuid(captainGuid);
|
||||
if (!captainEntry || Player::TeamIdForRace(captainEntry->Race) != bot->GetTeamId())
|
||||
continue;
|
||||
|
||||
arenateam = team;
|
||||
break;
|
||||
}
|
||||
|
||||
if (botcaptain && botcaptain->GetTeamId() == bot->GetTeamId()) // need?
|
||||
if (!arenateam)
|
||||
{
|
||||
// Add bot to arena team
|
||||
sRandomPlayerbotMgr.arenaTeamsFull = true;
|
||||
return;
|
||||
}
|
||||
|
||||
arenateam->AddMember(bot->GetGUID());
|
||||
|
||||
// Only synchronize ratings once the team is full (avoid redundant work)
|
||||
// The captain was added with incorrect ratings when the team was created,
|
||||
// so we fix everyone's ratings once the roster is complete
|
||||
if (arenateam->GetMembersSize() >= (uint32)arenateam->GetType())
|
||||
// Synchronize ratings once the team is full
|
||||
if (arenateam->GetMembersSize() >= static_cast<uint32>(arenateam->GetType()))
|
||||
{
|
||||
uint32 teamRating = arenateam->GetRating();
|
||||
|
||||
// Use SetRatingForAll to align all members with team rating
|
||||
arenateam->SetRatingForAll(teamRating);
|
||||
|
||||
// For bot-only teams, keep MMR synchronized with team rating
|
||||
// This ensures matchmaking reflects the artificial team strength (1000-2000 range)
|
||||
// instead of being influenced by the global CONFIG_ARENA_START_MATCHMAKER_RATING
|
||||
for (auto& member : arenateam->GetMembers())
|
||||
{
|
||||
// Set MMR to match personal rating (which already matches team rating)
|
||||
member.MatchMakerRating = member.PersonalRating;
|
||||
member.MaxMMR = std::max(member.MaxMMR, member.PersonalRating);
|
||||
}
|
||||
// Force save all member data to database
|
||||
|
||||
arenateam->SaveToDB(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arenateams.erase(arenateams.begin() + index);
|
||||
}
|
||||
|
||||
// bot->SaveToDB(false, false);
|
||||
}
|
||||
|
||||
void PlayerbotFactory::ApplyEnchantTemplate()
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#ifndef _PLAYERBOT_PLAYERBOTFACTORY_H
|
||||
#define _PLAYERBOT_PLAYERBOTFACTORY_H
|
||||
|
||||
#include "Battleground.h"
|
||||
#include "InventoryAction.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAI.h"
|
||||
@ -119,6 +120,8 @@ private:
|
||||
void InitInventorySkill();
|
||||
Item* StoreItem(uint32 itemId, uint32 count);
|
||||
void InitArenaTeam();
|
||||
bool CreateArenaTeamWithCaptain(ArenaType type);
|
||||
void AssignToArenaTeam();
|
||||
void InitImmersive();
|
||||
static void AddPrevQuests(uint32 questId, std::list<uint32>& questIds);
|
||||
void LoadEnchantContainer();
|
||||
|
||||
@ -7,8 +7,10 @@
|
||||
|
||||
#include "AccountMgr.h"
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "CharacterCache.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "RaceMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SharedDefines.h"
|
||||
@ -782,145 +784,90 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName()
|
||||
return guildName;
|
||||
}
|
||||
|
||||
void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count)
|
||||
bool RandomPlayerbotFactory::IsBotArenaTeam(ArenaTeam const* team)
|
||||
{
|
||||
std::vector<uint32> randomBots;
|
||||
if (!team)
|
||||
return false;
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT);
|
||||
stmt->SetData(0, "add");
|
||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
|
||||
ObjectGuid captainGuid = team->GetCaptain();
|
||||
if (!captainGuid || !captainGuid.IsPlayer())
|
||||
return false;
|
||||
|
||||
uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(captainGuid);
|
||||
return accountId && sPlayerbotAIConfig.IsInRandomAccountList(accountId);
|
||||
}
|
||||
|
||||
void RandomPlayerbotFactory::LoadArenaTeamNames()
|
||||
{
|
||||
_availableArenaTeamNames.clear();
|
||||
|
||||
QueryResult result = CharacterDatabase.Query(
|
||||
"SELECT n.name FROM playerbots_arena_team_names n "
|
||||
"LEFT OUTER JOIN arena_team e ON e.name = n.name "
|
||||
"WHERE e.arenateamid IS NULL");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No arena team names available in playerbots_arena_team_names");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 bot = fields[0].Get<uint32>();
|
||||
randomBots.push_back(bot);
|
||||
_availableArenaTeamNames.push_back(fields[0].Get<std::string>());
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
uint32 arenaTeamNumber = 0;
|
||||
GuidVector availableCaptains;
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
for (size_t i = _availableArenaTeamNames.size() - 1; i > 0; --i)
|
||||
{
|
||||
ObjectGuid captain = ObjectGuid::Create<HighGuid::Player>(*i);
|
||||
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain, type);
|
||||
if (arenateam)
|
||||
{
|
||||
++arenaTeamNumber;
|
||||
sPlayerbotAIConfig.randomBotArenaTeams.push_back(arenateam->GetId());
|
||||
}
|
||||
else
|
||||
{
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(captain);
|
||||
|
||||
if (!arenateam && player && player->GetLevel() >= 70)
|
||||
availableCaptains.push_back(captain);
|
||||
}
|
||||
size_t j = urand(0, i);
|
||||
std::swap(_availableArenaTeamNames[i], _availableArenaTeamNames[j]);
|
||||
}
|
||||
|
||||
for (; arenaTeamNumber < count; ++arenaTeamNumber)
|
||||
{
|
||||
std::string const arenaTeamName = CreateRandomArenaTeamName();
|
||||
if (arenaTeamName.empty())
|
||||
continue;
|
||||
|
||||
if (availableCaptains.empty())
|
||||
{
|
||||
LOG_ERROR("playerbots", "No captains for random arena teams available");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 index = urand(0, availableCaptains.size() - 1);
|
||||
ObjectGuid captain = availableCaptains[index];
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(captain);
|
||||
if (!player)
|
||||
{
|
||||
LOG_ERROR("playerbots", "Cannot find player for captain {}", captain.ToString().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->GetLevel() < 70)
|
||||
{
|
||||
LOG_ERROR("playerbots", "Bot {} must be level 70 to create an arena team", captain.ToString().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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>();
|
||||
|
||||
ArenaTeam* arenateam = new ArenaTeam();
|
||||
if (!arenateam->Create(player->GetGUID(), type, arenaTeamName, 0, 0, 0, 0, 0))
|
||||
{
|
||||
LOG_ERROR("playerbots", "Error creating arena team {}", arenaTeamName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
arenateam->SetCaptain(player->GetGUID());
|
||||
|
||||
// set random rating
|
||||
arenateam->SetRatingForAll(
|
||||
urand(sPlayerbotAIConfig.randomBotArenaTeamMinRating, sPlayerbotAIConfig.randomBotArenaTeamMaxRating));
|
||||
|
||||
// set random emblem
|
||||
uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
uint32 emblemStyle = urand(0, 101);
|
||||
uint32 emblemColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
uint32 borderStyle = urand(0, 5);
|
||||
uint32 borderColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
arenateam->SetEmblem(backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor);
|
||||
|
||||
// set random kills (wip)
|
||||
// arenateam->SetStats(STAT_TYPE_GAMES_WEEK, urand(0, 30));
|
||||
// arenateam->SetStats(STAT_TYPE_WINS_WEEK, urand(0, arenateam->GetStats().games_week));
|
||||
// arenateam->SetStats(STAT_TYPE_GAMES_SEASON, urand(arenateam->GetStats().games_week,
|
||||
// arenateam->GetStats().games_week * 5)); arenateam->SetStats(STAT_TYPE_WINS_SEASON,
|
||||
// urand(arenateam->GetStats().wins_week, arenateam->GetStats().games
|
||||
arenateam->SaveToDB();
|
||||
|
||||
sArenaTeamMgr->AddArenaTeam(arenateam);
|
||||
sPlayerbotAIConfig.randomBotArenaTeams.push_back(arenateam->GetId());
|
||||
}
|
||||
|
||||
LOG_DEBUG("playerbots", "{} random bot {}vs{} arena teams available", arenaTeamNumber, type, type);
|
||||
LOG_INFO("playerbots", "Loaded {} available arena team names", _availableArenaTeamNames.size());
|
||||
}
|
||||
|
||||
std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName()
|
||||
uint32 RandomPlayerbotFactory::GetBotArenaTeamCount(ArenaType type)
|
||||
{
|
||||
std::string arenaTeamName = "";
|
||||
|
||||
QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_arena_team_names");
|
||||
if (!result)
|
||||
uint32 count = 0;
|
||||
for (auto const& [id, arenateam] : sArenaTeamMgr->GetArenaTeams())
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random arena teams");
|
||||
return arenaTeamName;
|
||||
if (arenateam->GetType() == type && IsBotArenaTeam(arenateam))
|
||||
++count;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 maxId = fields[0].Get<uint32>();
|
||||
|
||||
uint32 id = urand(0, maxId);
|
||||
result = CharacterDatabase.Query(
|
||||
"SELECT n.name FROM playerbots_arena_team_names n LEFT OUTER JOIN arena_team e ON e.name = n.name "
|
||||
"WHERE e.arenateamid IS NULL AND n.name_id >= {} LIMIT 1",
|
||||
id);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random arena teams");
|
||||
return arenaTeamName;
|
||||
}
|
||||
|
||||
fields = result->Fetch();
|
||||
arenaTeamName = fields[0].Get<std::string>();
|
||||
|
||||
return arenaTeamName;
|
||||
return count;
|
||||
}
|
||||
|
||||
void RandomPlayerbotFactory::DeleteBotArenaTeams()
|
||||
{
|
||||
LOG_INFO("playerbots", "Deleting random bot arena teams...");
|
||||
|
||||
std::vector<uint32> teamsToDisband;
|
||||
for (auto const& [id, arenateam] : sArenaTeamMgr->GetArenaTeams())
|
||||
{
|
||||
if (IsBotArenaTeam(arenateam))
|
||||
teamsToDisband.push_back(id);
|
||||
}
|
||||
|
||||
for (uint32 teamId : teamsToDisband)
|
||||
{
|
||||
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
|
||||
if (team)
|
||||
team->Disband(nullptr);
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Deleted {} random bot arena teams", teamsToDisband.size());
|
||||
}
|
||||
|
||||
std::string RandomPlayerbotFactory::CreateRandomArenaTeamName()
|
||||
{
|
||||
if (_availableArenaTeamNames.empty())
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random arena teams");
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string name = std::move(_availableArenaTeamNames.back());
|
||||
_availableArenaTeamNames.pop_back();
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -7,17 +7,17 @@
|
||||
#define _PLAYERBOT_RANDOMPLAYERBOTFACTORY_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "ArenaTeam.h"
|
||||
#include "Common.h"
|
||||
#include "DBCEnums.h"
|
||||
|
||||
class Player;
|
||||
class WorldSession;
|
||||
|
||||
enum ArenaType : uint8;
|
||||
|
||||
class RandomPlayerbotFactory
|
||||
{
|
||||
public:
|
||||
@ -51,15 +51,22 @@ public:
|
||||
|
||||
Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<NameRaceAndGender, std::vector<std::string>>& names);
|
||||
static void CreateRandomBots();
|
||||
static void CreateRandomArenaTeams(ArenaType slot, uint32 count);
|
||||
static std::string const CreateRandomGuildName();
|
||||
static uint32 CalculateTotalAccountCount();
|
||||
static uint32 CalculateAvailableCharsPerAccount();
|
||||
|
||||
// Arena team utilities (static — no bot instance needed)
|
||||
static void DeleteBotArenaTeams();
|
||||
static uint32 GetBotArenaTeamCount(ArenaType type);
|
||||
static bool IsBotArenaTeam(ArenaTeam const* team);
|
||||
static void LoadArenaTeamNames();
|
||||
static std::string CreateRandomArenaTeamName();
|
||||
|
||||
private:
|
||||
static bool IsValidRaceClassCombination(uint8 race, uint8 class_, uint32 expansion);
|
||||
std::string const CreateRandomBotName(NameRaceAndGender raceAndGender);
|
||||
static std::string const CreateRandomArenaTeamName();
|
||||
|
||||
static inline std::vector<std::string> _availableArenaTeamNames;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1763,6 +1763,47 @@ void RandomPlayerbotMgr::Init()
|
||||
PlayerbotsDatabase.Execute("DELETE FROM playerbots_random_bots WHERE event = 'add'");
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::InitArenaTeams()
|
||||
{
|
||||
if (sPlayerbotAIConfig.deleteRandomBotArenaTeams)
|
||||
{
|
||||
RandomPlayerbotFactory::DeleteBotArenaTeams();
|
||||
return;
|
||||
}
|
||||
|
||||
RandomPlayerbotFactory::LoadArenaTeamNames();
|
||||
|
||||
uint32 existing2v2 = RandomPlayerbotFactory::GetBotArenaTeamCount(ARENA_TYPE_2v2);
|
||||
uint32 existing3v3 = RandomPlayerbotFactory::GetBotArenaTeamCount(ARENA_TYPE_3v3);
|
||||
uint32 existing5v5 = RandomPlayerbotFactory::GetBotArenaTeamCount(ARENA_TYPE_5v5);
|
||||
|
||||
auto deficit = [](uint32 existing, uint32 target) -> uint32
|
||||
{
|
||||
return existing < target ? target - existing : 0;
|
||||
};
|
||||
|
||||
arenaCaptainsNeeded[ARENA_TYPE_2v2] = deficit(existing2v2, sPlayerbotAIConfig.randomBotArenaTeam2v2Count);
|
||||
arenaCaptainsNeeded[ARENA_TYPE_3v3] = deficit(existing3v3, sPlayerbotAIConfig.randomBotArenaTeam3v3Count);
|
||||
arenaCaptainsNeeded[ARENA_TYPE_5v5] = deficit(existing5v5, sPlayerbotAIConfig.randomBotArenaTeam5v5Count);
|
||||
|
||||
LOG_INFO("playerbots", "Bot arena teams: 2v2={}/{}, 3v3={}/{}, 5v5={}/{} (captains needed: {}/{}/{})",
|
||||
existing2v2, sPlayerbotAIConfig.randomBotArenaTeam2v2Count,
|
||||
existing3v3, sPlayerbotAIConfig.randomBotArenaTeam3v3Count,
|
||||
existing5v5, sPlayerbotAIConfig.randomBotArenaTeam5v5Count,
|
||||
arenaCaptainsNeeded[ARENA_TYPE_2v2],
|
||||
arenaCaptainsNeeded[ARENA_TYPE_3v3],
|
||||
arenaCaptainsNeeded[ARENA_TYPE_5v5]);
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::OnBotLoginArenaTeam(Player* bot)
|
||||
{
|
||||
if (!bot)
|
||||
return;
|
||||
|
||||
PlayerbotFactory factory(bot, bot->GetLevel());
|
||||
factory.InitArenaTeam();
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot)
|
||||
{
|
||||
if (bot->InBattleground())
|
||||
@ -2539,6 +2580,9 @@ void RandomPlayerbotMgr::OnBotLoginInternal(Player* const bot)
|
||||
factory.InitGuild();
|
||||
}
|
||||
|
||||
// Assign bot to an arena team if eligible
|
||||
OnBotLoginArenaTeam(bot);
|
||||
|
||||
if (sPlayerbotAIConfig.randomBotFixedLevel)
|
||||
{
|
||||
bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN);
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#ifndef _PLAYERBOT_RANDOMPLAYERBOTMGR_H
|
||||
#define _PLAYERBOT_RANDOMPLAYERBOTMGR_H
|
||||
|
||||
#include "Battleground.h"
|
||||
#include "NewRpgInfo.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "PlayerbotMgr.h"
|
||||
@ -120,6 +121,10 @@ public:
|
||||
Player* GetRandomPlayer();
|
||||
std::vector<Player*> GetPlayers() { return players; };
|
||||
PlayerBotMap GetAllBots() { return playerBots; };
|
||||
void InitArenaTeams();
|
||||
void OnBotLoginArenaTeam(Player* bot);
|
||||
std::map<ArenaType, uint32> arenaCaptainsNeeded;
|
||||
bool arenaTeamsFull = false;
|
||||
void PrintStats();
|
||||
double GetBuyMultiplier(Player* bot);
|
||||
double GetSellMultiplier(Player* bot);
|
||||
|
||||
@ -681,6 +681,7 @@ bool PlayerbotAIConfig::Initialize()
|
||||
}
|
||||
|
||||
PlayerbotGuildMgr::instance().Init();
|
||||
sRandomPlayerbotMgr.InitArenaTeams();
|
||||
sRandomItemMgr.Init();
|
||||
sRandomItemMgr.InitAfterAhBot();
|
||||
PlayerbotTextMgr::instance().LoadBotTexts();
|
||||
|
||||
@ -375,14 +375,12 @@ public:
|
||||
int32 enableRandomBotTrading;
|
||||
uint32 tweakValue; // Debugging config
|
||||
|
||||
uint32 randomBotArenaTeamCount;
|
||||
uint32 randomBotArenaTeamMaxRating;
|
||||
uint32 randomBotArenaTeamMinRating;
|
||||
uint32 randomBotArenaTeam2v2Count;
|
||||
uint32 randomBotArenaTeam3v3Count;
|
||||
uint32 randomBotArenaTeam5v5Count;
|
||||
bool deleteRandomBotArenaTeams;
|
||||
std::vector<uint32> randomBotArenaTeams;
|
||||
|
||||
uint32 selfBotLevel;
|
||||
bool downgradeMaxLevelBot;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user