Merge pull request #22 from liyunfan1223/random_bots

Random bots
This commit is contained in:
Yunfan Li
2023-08-08 17:09:03 +08:00
committed by GitHub
8 changed files with 85 additions and 73 deletions

View File

@@ -124,7 +124,7 @@ void PlayerbotFactory::Randomize(bool incremental)
{ {
ResetQuests(); ResetQuests();
} }
ClearInventory(); ClearAllItems();
bot->SaveToDB(false, false); bot->SaveToDB(false, false);
bot->GiveLevel(level); bot->GiveLevel(level);
@@ -337,10 +337,11 @@ void PlayerbotFactory::Refresh()
InitAmmo(); InitAmmo();
InitFood(); InitFood();
InitReagents(); InitReagents();
InitPotions(); // InitPotions();
InitTalents(true); InitTalentsTree(true);
InitClassSpells(); InitClassSpells();
InitAvailableSpells(); InitAvailableSpells();
InitSkills();
bot->DurabilityRepairAll(false, 1.0f, false); bot->DurabilityRepairAll(false, 1.0f, false);
if (bot->isDead()) if (bot->isDead())
bot->ResurrectPlayer(1.0f, false); bot->ResurrectPlayer(1.0f, false);
@@ -2144,6 +2145,9 @@ void PlayerbotFactory::InitAmmo()
case ITEM_SUBCLASS_WEAPON_CROSSBOW: case ITEM_SUBCLASS_WEAPON_CROSSBOW:
subClass = ITEM_SUBCLASS_ARROW; subClass = ITEM_SUBCLASS_ARROW;
break; break;
case ITEM_SUBCLASS_WEAPON_THROWN:
subClass = ITEM_SUBCLASS_THROWN;
break;
} }
if (!subClass) if (!subClass)
@@ -2292,6 +2296,9 @@ void PlayerbotFactory::InitPotions()
void PlayerbotFactory::InitFood() void PlayerbotFactory::InitFood()
{ {
if (sPlayerbotAIConfig->freeFood) {
return;
}
std::map<uint32, std::vector<uint32> > items; std::map<uint32, std::vector<uint32> > items;
ItemTemplateContainer const* itemTemplateContainer = sObjectMgr->GetItemTemplateStore(); ItemTemplateContainer const* itemTemplateContainer = sObjectMgr->GetItemTemplateStore();
for (ItemTemplateContainer::const_iterator i = itemTemplateContainer->begin(); i != itemTemplateContainer->end(); ++i) for (ItemTemplateContainer::const_iterator i = itemTemplateContainer->begin(); i != itemTemplateContainer->end(); ++i)
@@ -2961,6 +2968,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot)
{ {
score *= 0.8; score *= 0.8;
} }
// double hand
if (proto->Class == ITEM_CLASS_WEAPON) { if (proto->Class == ITEM_CLASS_WEAPON) {
bool isDoubleHand = proto->Class == ITEM_CLASS_WEAPON && bool isDoubleHand = proto->Class == ITEM_CLASS_WEAPON &&
!(ITEM_SUBCLASS_MASK_SINGLE_HAND & (1 << proto->SubClass)) && !(ITEM_SUBCLASS_MASK_SINGLE_HAND & (1 << proto->SubClass)) &&
@@ -2990,6 +2998,11 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot)
score *= 10; score *= 10;
} }
} }
if (proto->Class == ITEM_CLASS_WEAPON) {
if (cls == CLASS_HUNTER && proto->SubClass == ITEM_SUBCLASS_WEAPON_THROWN) {
score *= 0.1;
}
}
return (0.01 + score) * itemLevel * (quality + 1); return (0.01 + score) * itemLevel * (quality + 1);
// return score; // return score;
} }

View File

@@ -533,7 +533,7 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
return "bot not found"; return "bot not found";
if (!isRandomAccount || isRandomBot) { if (!isRandomAccount || isRandomBot) {
return "ERROR: You can not use this command on summoned random bot."; return "ERROR: You can not use this command on non-summoned random bot.";
} }
if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster())

View File

@@ -2179,10 +2179,10 @@ void RandomItemMgr::BuildAmmoCache()
uint32 counter = 0; uint32 counter = 0;
for (uint32 level = 1; level <= maxLevel; level += 1) for (uint32 level = 1; level <= maxLevel; level += 1)
{ {
for (uint32 subClass = ITEM_SUBCLASS_ARROW; subClass <= ITEM_SUBCLASS_BULLET; subClass++) for (uint32 subClass = ITEM_SUBCLASS_ARROW; subClass <= ITEM_SUBCLASS_THROWN; subClass++)
{ {
QueryResult results = WorldDatabase.Query("SELECT entry FROM item_template WHERE class = {} AND subclass = {} AND RequiredLevel <= {} " QueryResult results = WorldDatabase.Query("SELECT entry FROM item_template WHERE class = {} AND subclass = {} AND RequiredLevel <= {} "
"ORDER BY RequiredLevel DESC", ITEM_CLASS_PROJECTILE, subClass, level); "ORDER BY RequiredLevel DESC, Quality DESC, ItemLevel DESC", ITEM_CLASS_PROJECTILE, subClass, level);
if (!results) if (!results)
return; return;

View File

@@ -239,8 +239,8 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
SetEventValue(0, "bot_count", maxAllowedBotCount, urand(sPlayerbotAIConfig->randomBotCountChangeMinInterval, sPlayerbotAIConfig->randomBotCountChangeMaxInterval)); SetEventValue(0, "bot_count", maxAllowedBotCount, urand(sPlayerbotAIConfig->randomBotCountChangeMinInterval, sPlayerbotAIConfig->randomBotCountChangeMaxInterval));
} }
std::list<uint32> availableBots = GetBots(); GetBots();
uint32 availableBotCount = availableBots.size(); uint32 availableBotCount = currentBots.size();
uint32 onlineBotCount = playerBots.size(); uint32 onlineBotCount = playerBots.size();
uint32 onlineBotFocus = 75; uint32 onlineBotFocus = 75;
@@ -262,12 +262,6 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
activateCheckPlayersThread(); activateCheckPlayersThread();
} }
if (sPlayerbotAIConfig->syncLevelWithPlayers && !players.empty())
{
if (time(nullptr) > (PlayersCheckTimer + 60))
activateCheckPlayersThread();
}
if (sPlayerbotAIConfig->randomBotJoinBG/* && !players.empty()*/) if (sPlayerbotAIConfig->randomBotJoinBG/* && !players.empty()*/)
{ {
if (time(nullptr) > (BgCheckTimer + 30)) if (time(nullptr) > (BgCheckTimer + 30))
@@ -278,10 +272,10 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
uint32 maxNewBots = onlineBotCount < maxAllowedBotCount ? maxAllowedBotCount - onlineBotCount : 0; uint32 maxNewBots = onlineBotCount < maxAllowedBotCount ? maxAllowedBotCount - onlineBotCount : 0;
uint32 loginBots = std::min(sPlayerbotAIConfig->randomBotsPerInterval - updateBots, maxNewBots); uint32 loginBots = std::min(sPlayerbotAIConfig->randomBotsPerInterval - updateBots, maxNewBots);
if (!availableBots.empty()) if (!currentBots.empty())
{ {
// Update bots // Update bots
for (auto bot : availableBots) for (auto bot : currentBots)
{ {
if (!GetPlayerBot(bot)) if (!GetPlayerBot(bot))
continue; continue;
@@ -303,7 +297,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
LOG_INFO("playerbots", "{} new bots", loginBots); LOG_INFO("playerbots", "{} new bots", loginBots);
//Log in bots //Log in bots
for (auto bot : availableBots) for (auto bot : currentBots)
{ {
if (GetPlayerBot(bot)) if (GetPlayerBot(bot))
continue; continue;
@@ -833,8 +827,8 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot)
} }
} }
if (botAI->HasPlayerNearby(sPlayerbotAIConfig->grindDistance)) // if (botAI->HasPlayerNearby(sPlayerbotAIConfig->grindDistance))
update = false; // update = false;
} }
if (update) if (update)
@@ -1102,41 +1096,43 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
LOG_INFO("playerbots", "Preparing random teleport caches for {} levels...", maxLevel); LOG_INFO("playerbots", "Preparing random teleport caches for {} levels...", maxLevel);
QueryResult results = WorldDatabase.Query( QueryResult results = WorldDatabase.Query(
"WITH GroupedData AS ( " "SELECT "
"SELECT " "g.map, "
"MIN( c.guid ) guid, " "position_x, "
"(AVG( t.maxlevel ) + AVG( t.minlevel )) / 2 lvl " "position_y, "
"FROM " "position_z, "
"creature c " "t.minlevel "
"INNER JOIN creature_template t ON c.id1 = t.entry "
"WHERE "
"t.npcflag = 0 "
"AND t.lootid != 0 "
"AND t.unit_flags != 768 "
"AND map IN ({}) "
"AND c.id1 != 32820 "
"GROUP BY "
"map, "
"ROUND( position_x / 500 ), "
"ROUND( position_y / 500 ), "
"ROUND( position_z / 50 ) "
"HAVING "
"count(*) > 10 "
"AND MAX( t.maxlevel ) - MIN( t.minlevel ) < 5 "
"ORDER BY "
"lvl "
") "
"SELECT "
"map, "
"position_x, "
"position_y, "
"position_z, "
"t.maxlevel "
"FROM " "FROM "
"GroupedData g " "(SELECT "
"INNER JOIN creature c ON g.guid = c.guid " "map, "
"INNER JOIN creature_template t on c.id1 = t.entry;", sPlayerbotAIConfig->randomBotMapsAsString.c_str()); "MIN( c.guid ) guid, "
"t.entry "
"FROM "
"creature c "
"INNER JOIN creature_template t ON c.id1 = t.entry "
"WHERE "
"t.npcflag = 0 "
"AND t.lootid != 0 "
"AND t.unit_flags != 768 "
"AND t.maxlevel - t.minlevel < 3 "
"AND map IN ({}) "
"AND c.id1 != 32820 "
"AND c.spawntimesecs < 1000 "
"AND t.faction != 188 "
"GROUP BY "
"map, "
"ROUND( position_x / 500 ), "
"ROUND( position_y / 500 ), "
"ROUND( position_z / 50), "
"t.entry "
"HAVING "
"count(*) > 10) AS g "
"INNER JOIN creature c ON g.guid = c.guid "
"INNER JOIN creature_template t on c.id1 = t.entry "
"ORDER BY "
"t.minlevel;", sPlayerbotAIConfig->randomBotMapsAsString.c_str());
uint32 collected_locs = 0; uint32 collected_locs = 0;
if (results) if (results)
{ {
@@ -1147,14 +1143,14 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
float x = fields[1].Get<float>(); float x = fields[1].Get<float>();
float y = fields[2].Get<float>(); float y = fields[2].Get<float>();
float z = fields[3].Get<float>(); float z = fields[3].Get<float>();
uint32 avg_level = fields[4].Get<uint32>(); uint32 level = fields[4].Get<uint32>();
WorldLocation loc(mapId, x, y, z, 0); WorldLocation loc(mapId, x, y, z, 0);
collected_locs++; collected_locs++;
for (int32 level = (int32)avg_level - (int32)sPlayerbotAIConfig->randomBotTeleHigherLevel; level <= (int32)avg_level + (int32)sPlayerbotAIConfig->randomBotTeleLowerLevel; level++) { for (int32 l = (int32)level - (int32)sPlayerbotAIConfig->randomBotTeleHigherLevel; l <= (int32)level + (int32)sPlayerbotAIConfig->randomBotTeleLowerLevel; l++) {
if (level < 1 || level > maxLevel) { if (l < 1 || l > maxLevel) {
continue; continue;
} }
locsPerLevelCache[(uint8)level].push_back(loc); locsPerLevelCache[(uint8)l].push_back(loc);
} }
} while (results->NextRow()); } while (results->NextRow());
} }
@@ -1428,8 +1424,8 @@ void RandomPlayerbotMgr::Refresh(Player* bot)
botAI->ResetStrategies(false); botAI->ResetStrategies(false);
} }
if (sPlayerbotAIConfig->disableRandomLevels) // if (sPlayerbotAIConfig->disableRandomLevels)
return; // return;
if (bot->InBattleground()) if (bot->InBattleground())
return; return;
@@ -1472,9 +1468,6 @@ bool RandomPlayerbotMgr::IsRandomBot(Player* bot)
} }
if (bot) if (bot)
{ {
if (sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId()))
return true;
return IsRandomBot(bot->GetGUID().GetCounter()); return IsRandomBot(bot->GetGUID().GetCounter());
} }
@@ -1486,14 +1479,15 @@ bool RandomPlayerbotMgr::IsRandomBot(ObjectGuid::LowType bot)
ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(bot); ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(bot);
if (!sPlayerbotAIConfig->IsInRandomAccountList(sCharacterCache->GetCharacterAccountIdByGuid(guid))) if (!sPlayerbotAIConfig->IsInRandomAccountList(sCharacterCache->GetCharacterAccountIdByGuid(guid)))
return false; return false;
if (std::find(currentBots.begin(), currentBots.end(), bot) != currentBots.end())
return GetEventValue(bot, "add"); return true;
return false;
} }
std::list<uint32> RandomPlayerbotMgr::GetBots() void RandomPlayerbotMgr::GetBots()
{ {
if (!currentBots.empty()) if (!currentBots.empty())
return currentBots; return;
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BY_OWNER_AND_EVENT); PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BY_OWNER_AND_EVENT);
stmt->SetData(0, 0); stmt->SetData(0, 0);
@@ -1504,12 +1498,11 @@ std::list<uint32> RandomPlayerbotMgr::GetBots()
{ {
Field* fields = result->Fetch(); Field* fields = result->Fetch();
uint32 bot = fields[0].Get<uint32>(); uint32 bot = fields[0].Get<uint32>();
currentBots.push_back(bot); if (GetEventValue(bot, "add"))
currentBots.push_back(bot);
} }
while (result->NextRow()); while (result->NextRow());
} }
return std::move(currentBots);
} }
std::vector<uint32> RandomPlayerbotMgr::GetBgBots(uint32 bracket) std::vector<uint32> RandomPlayerbotMgr::GetBgBots(uint32 bracket)

View File

@@ -105,7 +105,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder
uint32 GetEventValue(uint32 bot, std::string const event); uint32 GetEventValue(uint32 bot, std::string const event);
std::string const GetEventData(uint32 bot, std::string const event); std::string const GetEventData(uint32 bot, std::string const event);
uint32 SetEventValue(uint32 bot, std::string const event, uint32 value, uint32 validIn, std::string const data = ""); uint32 SetEventValue(uint32 bot, std::string const event, uint32 value, uint32 validIn, std::string const data = "");
std::list<uint32> GetBots(); void GetBots();
std::vector<uint32> GetBgBots(uint32 bracket); std::vector<uint32> GetBgBots(uint32 bracket);
time_t BgCheckTimer; time_t BgCheckTimer;
time_t LfgCheckTimer; time_t LfgCheckTimer;

View File

@@ -21,4 +21,5 @@ void AutoTeleportForLevelAction::AutoUpgradeEquip() {
} }
PlayerbotFactory factory(bot, bot->GetLevel(), ITEM_QUALITY_RARE); PlayerbotFactory factory(bot, bot->GetLevel(), ITEM_QUALITY_RARE);
factory.InitEquipment(true); factory.InitEquipment(true);
factory.InitSkills();
} }

View File

@@ -30,8 +30,9 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"party member critical health", "party member critical health",
NextAction::array(0, NextAction::array(0,
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 3), new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4),
new NextAction("wild growth", ACTION_CRITICAL_HEAL + 2), new NextAction("wild growth", ACTION_CRITICAL_HEAL + 3),
new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 2),
new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1), new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0),
NULL))); NULL)));

View File

@@ -97,6 +97,10 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
if (CreatureTemplate->rank > CREATURE_ELITE_NORMAL && !AI_VALUE(bool, "can fight elite")) if (CreatureTemplate->rank > CREATURE_ELITE_NORMAL && !AI_VALUE(bool, "can fight elite"))
continue; continue;
if (!bot->IsWithinLOSInMap(unit)) {
continue;
}
if (group) if (group)
{ {
Group::MemberSlotList const& groupSlot = group->GetMemberSlots(); Group::MemberSlotList const& groupSlot = group->GetMemberSlots();