Reinstate cached preferred mounts (#1058)

This commit is contained in:
SaW
2025-03-05 17:24:54 +01:00
committed by GitHub
parent a4fe45afbb
commit b9747fdd69
2 changed files with 92 additions and 35 deletions

View File

@@ -12,6 +12,10 @@
#include "ServerFacade.h" #include "ServerFacade.h"
#include "SpellAuraEffects.h" #include "SpellAuraEffects.h"
// Define the static map / init bool for caching bot preferred mount data globally
std::unordered_map<uint32, PreferredMountCache> CheckMountStateAction::mountCache;
bool CheckMountStateAction::preferredMountTableExists = false;
MountData CollectMountData(const Player* bot) MountData CollectMountData(const Player* bot)
{ {
MountData data; MountData data;
@@ -191,9 +195,8 @@ bool CheckMountStateAction::Mount()
botAI->RemoveAura("tree of life"); botAI->RemoveAura("tree of life");
} }
// Disabled for now until properly implemented if (TryPreferredMount(master))
//if (TryPreferredMount(master)) return true;
// return true;
// Get bot mount data // Get bot mount data
MountData mountData = CollectMountData(bot); MountData mountData = CollectMountData(bot);
@@ -271,59 +274,98 @@ bool CheckMountStateAction::TryForms(Player* master, int32 masterMountType, int3
bool CheckMountStateAction::TryPreferredMount(Player* master) const bool CheckMountStateAction::TryPreferredMount(Player* master) const
{ {
static bool tableExists = false; uint32 botGUID = bot->GetGUID().GetRawValue();
static bool tableChecked = false;
if (!tableChecked) // Build cache (only once)
if (!preferredMountTableExists)
{ {
// Check for preferred mounts table in db // Verify preferred mounts table existance in the database
QueryResult checkTable = PlayerbotsDatabase.Query( QueryResult checkTable = PlayerbotsDatabase.Query(
"SELECT EXISTS(SELECT * FROM information_schema.tables WHERE table_schema = 'acore_playerbots' AND table_name = 'playerbots_preferred_mounts')"); "SELECT EXISTS(SELECT * FROM information_schema.tables WHERE table_schema = 'acore_playerbots' AND table_name = 'playerbots_preferred_mounts')");
tableExists = checkTable && checkTable->Fetch()[0].Get<uint32>() == 1;
tableChecked = true;
}
if (tableExists) if (checkTable && checkTable->Fetch()[0].Get<uint32>() == 1)
{ {
// Check for preferred mount entry preferredMountTableExists = true;
QueryResult result = PlayerbotsDatabase.Query(
"SELECT spellid FROM playerbots_preferred_mounts WHERE guid = {} AND type = {}", // Cache all mounts of both types globally, for all entries
bot->GetGUID().GetCounter(), GetMountType(master)); QueryResult result = PlayerbotsDatabase.Query("SELECT guid, spellid, type FROM playerbots_preferred_mounts");
if (result) if (result)
{ {
std::vector<uint32> mounts; uint32 totalResults = 0;
do while (auto row = result->Fetch())
{ {
mounts.push_back(result->Fetch()[0].Get<uint32>()); uint32 guid = row[0].Get<uint32>();
} while (result->NextRow()); uint32 spellId = row[1].Get<uint32>();
uint32 mountType = row[2].Get<uint32>();
// Validate spell ID if (mountType == 0)
// TODO: May want to do checks for 'bot riding skill > skill required to ride the mount' mountCache[guid].groundMounts.push_back(spellId);
if (!mounts.empty())
else if (mountType == 1)
mountCache[guid].flightMounts.push_back(spellId);
totalResults++;
result->NextRow();
}
LOG_INFO("playerbots", "Preferred mounts initialized | Total records: {}", totalResults);
}
}
else // If the SQL table is missing, return false
{ {
uint32 index = urand(0, mounts.size() - 1); LOG_ERROR("playerbots", "Preferred mounts SQL table playerbots_preferred_mounts does not exist!");
if (index < mounts.size() && sSpellMgr->GetSpellInfo(mounts[index]) && return false;
botAI->CanCastSpell(mounts[index], bot)) }
}
// Pick a random preferred mount from the selection, if available
uint32 chosenMountId = 0;
if (GetMountType(master) == 0 && !mountCache[botGUID].groundMounts.empty())
{ {
botAI->CastSpell(mounts[index], bot); uint32 index = urand(0, mountCache[botGUID].groundMounts.size() - 1);
chosenMountId = mountCache[botGUID].groundMounts[index];
}
else if (GetMountType(master) == 1 && !mountCache[botGUID].flightMounts.empty())
{
uint32 index = urand(0, mountCache[botGUID].flightMounts.size() - 1);
chosenMountId = mountCache[botGUID].flightMounts[index];
}
// No suitable preferred mount found
if (chosenMountId == 0)
return false;
// Check if spell exists
if (!sSpellMgr->GetSpellInfo(chosenMountId))
{
LOG_ERROR("playerbots", "Preferred mount failed: Invalid spell {} | Bot Guid: {}", chosenMountId, botGUID);
return false;
}
// Required here as otherwise bots won't mount in BG's due to them constant moving
if (bot->isMoving())
bot->StopMoving();
// Check if spell can be cast - for now allow all, even if the bot does not have the actual mount
//if (botAI->CanCastSpell(mountId, botAI->GetBot()))
//{
botAI->CastSpell(chosenMountId, botAI->GetBot());
return true; return true;
} //}
}
} LOG_DEBUG("playerbots", "Preferred mount failed! | Bot Guid: {}", botGUID);
}
return false; return false;
} }
bool CheckMountStateAction::TryRandomMountFiltered(const std::map<int32, std::vector<uint32>>& spells, int32 masterSpeed) const bool CheckMountStateAction::TryRandomMountFiltered(const std::map<int32, std::vector<uint32>>& spells, int32 masterSpeed) const
{ {
// Required here as otherwise bots won't mount in BG's due to them constant moving
if (bot->isMoving())
bot->StopMoving();
for (const auto& pair : spells) for (const auto& pair : spells)
{ {
int32 currentSpeed = pair.first; int32 currentSpeed = pair.first;
if ((masterSpeed > 59 && currentSpeed < 99) || (masterSpeed > 149 && currentSpeed < 279)) if ((masterSpeed > 59 && currentSpeed < 99) || (masterSpeed > 149 && currentSpeed < 279))
continue; continue;
@@ -331,6 +373,10 @@ bool CheckMountStateAction::TryRandomMountFiltered(const std::map<int32, std::ve
const auto& ids = pair.second; const auto& ids = pair.second;
if (!ids.empty()) if (!ids.empty())
{ {
// Required here as otherwise bots won't mount in BG's due to them constant moving
if (bot->isMoving())
bot->StopMoving();
uint32 index = urand(0, ids.size() - 1); uint32 index = urand(0, ids.size() - 1);
if (botAI->CanCastSpell(ids[index], bot)) if (botAI->CanCastSpell(ids[index], bot))

View File

@@ -6,6 +6,9 @@
#ifndef _PLAYERBOT_CHECKMOUNTSTATEACTION_H #ifndef _PLAYERBOT_CHECKMOUNTSTATEACTION_H
#define _PLAYERBOT_CHECKMOUNTSTATEACTION_H #define _PLAYERBOT_CHECKMOUNTSTATEACTION_H
#include <unordered_map>
#include <vector>
#include "UseItemAction.h" #include "UseItemAction.h"
const uint16 SPELL_TRAVEL_FORM = 783; const uint16 SPELL_TRAVEL_FORM = 783;
@@ -21,6 +24,12 @@ struct MountData
int32 maxSpeed = 59; int32 maxSpeed = 59;
}; };
struct PreferredMountCache
{
std::vector<uint32> groundMounts;
std::vector<uint32> flightMounts;
};
class PlayerbotAI; class PlayerbotAI;
class CheckMountStateAction : public UseItemAction class CheckMountStateAction : public UseItemAction
@@ -37,6 +46,8 @@ private:
Player* master; Player* master;
ShapeshiftForm masterInShapeshiftForm; ShapeshiftForm masterInShapeshiftForm;
ShapeshiftForm botInShapeshiftForm; ShapeshiftForm botInShapeshiftForm;
static std::unordered_map<uint32, PreferredMountCache> mountCache;
static bool preferredMountTableExists;
float CalculateDismountDistance() const; float CalculateDismountDistance() const;
float CalculateMountDistance() const; float CalculateMountDistance() const;
void Dismount(); void Dismount();