Allow bots to enter all TBC dungeons (rep/keys/quest attunements) (#1014)

Update will allow any adequately leveled bot to queue for all random and specific TBC dungeons. Normal and Heroic modes that require attunement or keys will be accessible by bots.

InitReputation: Level 70+ Bots will receive Honored rank for all the required factions needed for Heroic keys to function. I've placed the calls to InitRep before InitMounts, I feel we can do something with that in the future. Randomised rep values might allow bots to obtain other mounts?
InitKeyring: All bots receive all non-rep required keys (Shattered Halls Key, Shadow Labyrinth Key, Key to the Arcatraz), and bots with the required rep (Honored) get the other keys.
InitAttunementQuests: Level 60+ bots complete the Caverns of Time and Magister's Terrace attunement quests.
Updated acore_playerbots SQL; playerbots_dungeon_suggestion_definition; max_level increased to 73 (from 70) for all TBC Heroics and Magister's Terrace nomal. Allows more level appropriate bots to join.
This commit is contained in:
avirar
2025-02-27 01:55:16 +11:00
committed by GitHub
parent 2766d553c7
commit 3a4e8e729b
4 changed files with 191 additions and 2 deletions

View File

@@ -0,0 +1,4 @@
-- Update max_level for TBC Heroic dungeons in `playerbots_dungeon_suggestion_definition`
UPDATE `playerbots_dungeon_suggestion_definition`
SET `max_level` = 73
WHERE `id` IN (40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56);

View File

@@ -33,6 +33,7 @@
#include "Playerbots.h"
#include "RandomItemMgr.h"
#include "RandomPlayerbotFactory.h"
#include "ReputationMgr.h"
#include "SharedDefines.h"
#include "SpellAuraDefines.h"
#include "StatsWeightCalculator.h"
@@ -251,6 +252,14 @@ void PlayerbotFactory::Randomize(bool incremental)
{
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests");
InitInstanceQuests();
InitAttunementQuests();
if (pmo)
pmo->finish();
}
else
{
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests");
InitAttunementQuests();
if (pmo)
pmo->finish();
}
@@ -296,6 +305,12 @@ void PlayerbotFactory::Randomize(bool incremental)
if (pmo)
pmo->finish();
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reputation");
LOG_DEBUG("playerbots", "Initializing reputation...");
InitReputation();
if (pmo)
pmo->finish();
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Mounts");
LOG_DEBUG("playerbots", "Initializing mounts...");
InitMounts();
@@ -360,6 +375,12 @@ void PlayerbotFactory::Randomize(bool incremental)
if (pmo)
pmo->finish();
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Keys");
LOG_DEBUG("playerbots", "Initializing keys...");
InitKeyring();
if (pmo)
pmo->finish();
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EqSets");
LOG_DEBUG("playerbots", "Initializing second equipment set...");
// InitSecondEquipmentSet();
@@ -449,6 +470,7 @@ void PlayerbotFactory::Refresh()
// {
// InitEquipment(true);
// }
InitAttunementQuests();
ClearInventory();
InitAmmo();
InitFood();
@@ -463,7 +485,9 @@ void PlayerbotFactory::Refresh()
InitClassSpells();
InitAvailableSpells();
InitSkills();
InitReputation();
InitMounts();
InitKeyring();
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
{
ApplyEnchantAndGemsNew();
@@ -4223,3 +4247,157 @@ void PlayerbotFactory::IterateItemsInBank(IterateItemsVisitor* visitor)
}
}
}
void PlayerbotFactory::InitKeyring()
{
if (!bot)
return;
ReputationMgr& repMgr = bot->GetReputationMgr(); // Reference, use . instead of ->
std::vector<std::pair<uint32, uint32>> keysToCheck;
// Reputation-based Keys (Honored requirement)
if (repMgr.GetRank(sFactionStore.LookupEntry(1011)) >= REP_HONORED && !bot->HasItemCount(30633, 1))
keysToCheck.emplace_back(1011, 30633); // Lower City - Auchenai Key
if (repMgr.GetRank(sFactionStore.LookupEntry(942)) >= REP_HONORED && !bot->HasItemCount(30623, 1))
keysToCheck.emplace_back(942, 30623); // Cenarion Expedition - Reservoir Key
if (repMgr.GetRank(sFactionStore.LookupEntry(989)) >= REP_HONORED && !bot->HasItemCount(30635, 1))
keysToCheck.emplace_back(989, 30635); // Keepers of Time - Key of Time
if (repMgr.GetRank(sFactionStore.LookupEntry(935)) >= REP_HONORED && !bot->HasItemCount(30634, 1))
keysToCheck.emplace_back(935, 30634); // The Sha'tar - Warpforged Key
// Faction-specific Keys (Honored requirement)
if (bot->GetTeamId() == TEAM_ALLIANCE && repMgr.GetRank(sFactionStore.LookupEntry(946)) >= REP_HONORED && !bot->HasItemCount(30622, 1))
keysToCheck.emplace_back(946, 30622); // Honor Hold - Flamewrought Key (Alliance)
if (bot->GetTeamId() == TEAM_HORDE && repMgr.GetRank(sFactionStore.LookupEntry(947)) >= REP_HONORED && !bot->HasItemCount(30637, 1))
keysToCheck.emplace_back(947, 30637); // Thrallmar - Flamewrought Key (Horde)
// Keys that do not require Rep or Faction
// Shattered Halls Key, Shadow Labyrinth Key, Key to the Arcatraz, Master's Key
std::vector<uint32> nonRepKeys = {28395, 27991, 31084, 24490};
for (uint32 keyId : nonRepKeys)
{
if (!bot->HasItemCount(keyId, 1))
keysToCheck.emplace_back(0, keyId);
}
// Assign keys
for (auto const& keyPair : keysToCheck)
{
uint32 keyId = keyPair.second;
if (keyId > 0)
{
if (Item* newItem = StoreNewItemInInventorySlot(bot,keyId, 1))
{
newItem->AddToUpdateQueueOf(bot);
}
}
}
}
void PlayerbotFactory::InitReputation()
{
if (!bot)
return;
if (bot->GetLevel() < 70)
return; // Only apply for level 70+ bots
ReputationMgr& repMgr = bot->GetReputationMgr();
// List of factions that require Honored reputation for heroic keys
std::vector<uint32> factions = {
1011, // Lower City
942, // Cenarion Expedition
989, // Keepers of Time
935 // The Sha'tar
};
// Add faction-specific reputation
if (bot->GetTeamId() == TEAM_ALLIANCE)
factions.push_back(946); // Honor Hold (Alliance)
else if (bot->GetTeamId() == TEAM_HORDE)
factions.push_back(947); // Thrallmar (Horde)
// Set reputation to Honored for each required faction
for (uint32 factionId : factions)
{
FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
if (!factionEntry)
continue;
// Bottom of Honored rank
int32 honoredRep = ReputationMgr::ReputationRankToStanding(static_cast<ReputationRank>(REP_HONORED - 1)) + 1;
// Get bot's current reputation with this faction
int32 currentRep = repMgr.GetReputation(factionEntry);
// Only set reputation if it's lower than the required Honored value
if (currentRep < honoredRep)
{
repMgr.SetReputation(factionEntry, honoredRep);
}
}
}
void PlayerbotFactory::InitAttunementQuests()
{
uint32 level = bot->GetLevel();
if (level < 55)
return; // Only apply for level 55+ bots
uint32 currentXP = bot->GetUInt32Value(PLAYER_XP);
// List of attunement quest IDs
std::list<uint32> attunementQuestsTBC = {
// Caverns of Time - Part 1
10279, // To The Master's Lair
10277, // The Caverns of Time
// Caverns of Time - Part 2 (Escape from Durnholde Keep)
10282, // Old Hillsbrad
10283, // Taretha's Diversion
10284, // Escape from Durnholde
10285, // Return to Andormu
// Caverns of Time - Part 2 (The Black Morass)
10296, // The Black Morass
10297, // The Opening of the Dark Portal
10298, // Hero of the Brood
// Magister's Terrace Attunement
11481, // Crisis at the Sunwell
11482, // Duty Calls
11488, // Magisters' Terrace
11490, // The Scryer's Scryer
11492 // Hard to Kill
};
// Complete all level-appropriate attunement quests for the bot
if (level >= 60)
{
std::list<uint32> questsToComplete;
// Check each quest status before adding to the completion list
for (uint32 questId : attunementQuestsTBC)
{
QuestStatus questStatus = bot->GetQuestStatus(questId);
if (questStatus == QUEST_STATUS_NONE) // Quest not yet taken/completed
{
questsToComplete.push_back(questId);
}
}
// Only complete quests that haven't been finished yet
if (!questsToComplete.empty())
{
InitQuests(questsToComplete);
}
}
// Reset XP so bot's level remains unchanged
bot->GiveLevel(level);
bot->SetUInt32Value(PLAYER_XP, currentXP);
}

View File

@@ -137,6 +137,9 @@ public:
void ApplyEnchantAndGemsNew(bool destoryOld = true);
void InitInstanceQuests();
void UnbindInstance();
void InitKeyring();
void InitReputation();
void InitAttunementQuests();
private:
void Prepare();

View File

@@ -162,8 +162,10 @@ bool MaintenanceAction::Execute(Event event)
botAI->TellError("maintenance command is not allowed, please check the configuration.");
return false;
}
botAI->TellMaster("I'm maintaining");
PlayerbotFactory factory(bot, bot->GetLevel());
factory.InitAttunementQuests();
factory.InitBags(false);
factory.InitAmmo();
factory.InitFood();
@@ -174,15 +176,17 @@ bool MaintenanceAction::Execute(Event event)
factory.InitClassSpells();
factory.InitAvailableSpells();
factory.InitSkills();
factory.InitReputation();
factory.InitSpecialSpells();
factory.InitMounts();
factory.InitGlyphs(true);
factory.InitKeyring();
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
{
factory.ApplyEnchantAndGemsNew();
}
bot->DurabilityRepairAll(false, 1.0f, false);
bot->SendTalentsInfoData(false);
return true;
}