Speed up addclass with pre calculation

This commit is contained in:
Yunfan Li
2024-08-31 19:58:28 +08:00
parent f48bf2351a
commit f804ba2d65
4 changed files with 61 additions and 69 deletions

View File

@@ -80,6 +80,7 @@ AiPlayerbot.Enabled = 1
AiPlayerbot.RandomBotAutologin = 1 AiPlayerbot.RandomBotAutologin = 1
# Random bot account # Random bot account
# Please ensure that RandomBotAccountCount is greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
AiPlayerbot.RandomBotAccountCount = 200 AiPlayerbot.RandomBotAccountCount = 200
# Random bot count # Random bot count
@@ -108,12 +109,16 @@ AiPlayerbot.DeleteRandomBotAccounts = 0
AiPlayerbot.MaxAddedBots = 40 AiPlayerbot.MaxAddedBots = 40
# Maximum number of bots per class added by one account # Maximum number of bots per class added by one account
AiPlayerbot.MaxAddedBotsPerClass = 10 AiPlayerbot.MaxAddedBotsPerClass = 40
# Enable/Disable create bot by addclass command (0 = GM only, 1 = enable) # Enable/Disable create bot by addclass command (0 = GM only, 1 = enable)
# default: 1 (enable) # default: 1 (enable)
AiPlayerbot.AddClassCommand = 1 AiPlayerbot.AddClassCommand = 1
# Set the addclass command account pool size
# Addclass command uses a subset of accounts from RandomBotAccountCount
AiPlayerbot.AddClassAccountPoolSize = 50
# Bot group invitation permission level (0 = GM only, 1 = accept based on level, 2 = always accept) # Bot group invitation permission level (0 = GM only, 1 = accept based on level, 2 = always accept)
# default: 1 (accept based on level) # default: 1 (accept based on level)
AiPlayerbot.GroupInvitationPermission = 1 AiPlayerbot.GroupInvitationPermission = 1

View File

@@ -18,12 +18,14 @@
#include "Group.h" #include "Group.h"
#include "GroupMgr.h" #include "GroupMgr.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "ObjectGuid.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "PlayerbotDbStore.h" #include "PlayerbotDbStore.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "PlayerbotSecurity.h" #include "PlayerbotSecurity.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RandomPlayerbotMgr.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "WorldSession.h" #include "WorldSession.h"
#include "ChannelMgr.h" #include "ChannelMgr.h"
@@ -1003,44 +1005,20 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
messages.push_back("Error: Invalid Class. Try again."); messages.push_back("Error: Invalid Class. Try again.");
return messages; return messages;
} }
uint8 master_race = master->getRace(); uint8 teamId = master->GetTeamId(true);
std::string race_limit; std::vector<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)];
switch (master_race) for (size_t i = 0; i < guidCache.size(); i++)
{ {
case 1: ObjectGuid guid = guidCache[i];
case 3: if (botLoading.find(guid) != botLoading.end())
case 4: continue;
case 7: if (ObjectAccessor::FindConnectedPlayer(guid))
case 11: continue;
race_limit = "1, 3, 4, 7, 11";
break;
case 2:
case 5:
case 6:
case 8:
case 10:
race_limit = "2, 5, 6, 8, 10";
break;
}
uint32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back();
// find a bot fit conditions and not in any guild
QueryResult results = CharacterDatabase.Query(
"SELECT guid FROM characters "
"WHERE name IN (SELECT name FROM playerbots_names) AND class = '{}' AND online = 0 AND race IN ({}) AND "
"guid NOT IN ( SELECT guid FROM guild_member ) "
"AND account <= {} "
"ORDER BY account DESC LIMIT 1",
claz, race_limit, maxAccountId);
if (results)
{
Field* fields = results->Fetch();
ObjectGuid guid = ObjectGuid(HighGuid::Player, fields[0].Get<uint32>());
AddPlayerBot(guid, master->GetSession()->GetAccountId()); AddPlayerBot(guid, master->GetSession()->GetAccountId());
messages.push_back("Add class " + std::string(charname)); messages.push_back("Add class " + std::string(charname));
return messages; return messages;
} }
messages.push_back("Add class failed."); messages.push_back("Add class failed, no available characters!");
return messages; return messages;
} }

View File

@@ -162,6 +162,8 @@ RandomPlayerbotMgr::RandomPlayerbotMgr() : PlayerbotHolder(), processTicks(0)
{ {
sPlayerbotCommandServer->Start(); sPlayerbotCommandServer->Start();
PrepareTeleportCache(); PrepareTeleportCache();
if (sPlayerbotAIConfig->addClassCommand)
PrepareAddclassCache();
} }
BattlegroundData.clear(); BattlegroundData.clear();
@@ -1473,40 +1475,44 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
} while (results->NextRow()); } while (results->NextRow());
} }
LOG_INFO("playerbots", "{} banker locations for level collected.", collected_locs); LOG_INFO("playerbots", "{} banker locations for level collected.", collected_locs);
}
// temporary only use locsPerLevelCache, so disable rpgLocsCacheLevel cache void RandomPlayerbotMgr::PrepareAddclassCache()
{
// LOG_INFO("playerbots", "Preparing RPG teleport caches for {} factions...", sFactionTemplateStore.GetNumRows()); int32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back();
// results = WorldDatabase.Query("SELECT map, position_x, position_y, position_z, r.race, r.minl, r.maxl FROM int32 minIdx =
// creature c INNER JOIN playerbots_rpg_races r ON c.id1 = r.entry " sPlayerbotAIConfig->randomBotAccounts.size() - 1 >= sPlayerbotAIConfig->addClassAccountPoolSize
// "WHERE r.race < 15"); ? sPlayerbotAIConfig->randomBotAccounts.size() - sPlayerbotAIConfig->addClassAccountPoolSize : 0;
// if (results) int32 minAccountId = sPlayerbotAIConfig->randomBotAccounts[minIdx];
// { if (minAccountId < 0)
// do {
// { LOG_ERROR("playerbots", "No available account for add class!");
// Field* fields = results->Fetch(); }
// uint16 mapId = fields[0].Get<uint16>(); int32 collected = 0;
// float x = fields[1].Get<float>(); for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++)
// float y = fields[2].Get<float>(); {
// float z = fields[3].Get<float>(); if (claz == 10)
// uint32 race = fields[4].Get<uint32>(); continue;
// uint32 minl = fields[5].Get<uint32>(); QueryResult results = CharacterDatabase.Query(
// uint32 maxl = fields[6].Get<uint32>(); "SELECT guid, race FROM characters "
"WHERE account >= {} AND account <= {} AND class = '{}' AND online = 0 AND "
// for (uint32 level = 1; level < sPlayerbotAIConfig->randomBotMaxLevel + 1; level++) "guid NOT IN ( SELECT guid FROM guild_member ) "
// { "ORDER BY account DESC",
// if (level > maxl || level < minl) minAccountId, maxAccountId, claz);
// continue; if (results)
{
// WorldLocation loc(mapId, x, y, z, 0); do
// for (uint32 r = 1; r < MAX_RACES; r++) {
// { Field* fields = results->Fetch();
// if (race == r || race == 0) ObjectGuid guid = ObjectGuid(HighGuid::Player, fields[0].Get<uint32>());
// rpgLocsCacheLevel[r][level].push_back(loc); uint32 race = fields[1].Get<uint32>();
// } bool isAlliance = race == 1 || race == 3 || race == 4 || race == 7 || race == 11;
// } addclassCache[GetTeamClassIdx(isAlliance, claz)].push_back(guid);
// } while (results->NextRow()); collected++;
// } } while (results->NextRow());
}
}
LOG_INFO("playerbots", "{} characters collected for addclass command.", collected);
} }
void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot) void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot)
@@ -2395,7 +2401,7 @@ void RandomPlayerbotMgr::PrintStats()
++engine_combat; ++engine_combat;
else else
++engine_dead; ++engine_dead;
uint8 spec = AiFactory::GetPlayerSpecTab(bot); uint8 spec = AiFactory::GetPlayerSpecTab(bot);
switch (bot->getClass()) switch (bot->getClass())
{ {
@@ -2779,4 +2785,3 @@ ObjectGuid const RandomPlayerbotMgr::GetBattleMasterGUID(Player* bot, Battlegrou
return battleMasterGUID; return battleMasterGUID;
} }

View File

@@ -6,6 +6,7 @@
#ifndef _PLAYERBOT_RANDOMPLAYERBOTMGR_H #ifndef _PLAYERBOT_RANDOMPLAYERBOTMGR_H
#define _PLAYERBOT_RANDOMPLAYERBOTMGR_H #define _PLAYERBOT_RANDOMPLAYERBOTMGR_H
#include "ObjectGuid.h"
#include "PlayerbotMgr.h" #include "PlayerbotMgr.h"
struct BattlegroundInfo struct BattlegroundInfo
@@ -166,7 +167,9 @@ public:
float getActivityMod() { return activityMod; } float getActivityMod() { return activityMod; }
float getActivityPercentage() { return activityMod * 100.0f; } float getActivityPercentage() { return activityMod * 100.0f; }
void setActivityPercentage(float percentage) { activityMod = percentage / 100.0f; } void setActivityPercentage(float percentage) { activityMod = percentage / 100.0f; }
static uint8 GetTeamClassIdx(bool isAlliance, uint8 claz) { return isAlliance * 20 + claz; }
std::map<uint8, std::vector<ObjectGuid>> addclassCache;
protected: protected:
void OnBotLoginInternal(Player* const bot) override; void OnBotLoginInternal(Player* const bot) override;
@@ -190,6 +193,7 @@ private:
void RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth = false); void RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth = false);
uint32 GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ); uint32 GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ);
void PrepareTeleportCache(); void PrepareTeleportCache();
void PrepareAddclassCache();
typedef void (RandomPlayerbotMgr::*ConsoleCommandHandler)(Player*); typedef void (RandomPlayerbotMgr::*ConsoleCommandHandler)(Player*);
std::vector<Player*> players; std::vector<Player*> players;