mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Reinstate cached preferred mounts (#1058)
This commit is contained in:
@@ -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
|
|
||||||
QueryResult result = PlayerbotsDatabase.Query(
|
|
||||||
"SELECT spellid FROM playerbots_preferred_mounts WHERE guid = {} AND type = {}",
|
|
||||||
bot->GetGUID().GetCounter(), GetMountType(master));
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
std::vector<uint32> mounts;
|
preferredMountTableExists = true;
|
||||||
do
|
|
||||||
{
|
|
||||||
mounts.push_back(result->Fetch()[0].Get<uint32>());
|
|
||||||
} while (result->NextRow());
|
|
||||||
|
|
||||||
// Validate spell ID
|
// Cache all mounts of both types globally, for all entries
|
||||||
// TODO: May want to do checks for 'bot riding skill > skill required to ride the mount'
|
QueryResult result = PlayerbotsDatabase.Query("SELECT guid, spellid, type FROM playerbots_preferred_mounts");
|
||||||
if (!mounts.empty())
|
|
||||||
|
if (result)
|
||||||
{
|
{
|
||||||
uint32 index = urand(0, mounts.size() - 1);
|
uint32 totalResults = 0;
|
||||||
if (index < mounts.size() && sSpellMgr->GetSpellInfo(mounts[index]) &&
|
while (auto row = result->Fetch())
|
||||||
botAI->CanCastSpell(mounts[index], bot))
|
|
||||||
{
|
{
|
||||||
botAI->CastSpell(mounts[index], bot);
|
uint32 guid = row[0].Get<uint32>();
|
||||||
return true;
|
uint32 spellId = row[1].Get<uint32>();
|
||||||
|
uint32 mountType = row[2].Get<uint32>();
|
||||||
|
|
||||||
|
if (mountType == 0)
|
||||||
|
mountCache[guid].groundMounts.push_back(spellId);
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
LOG_ERROR("playerbots", "Preferred mounts SQL table playerbots_preferred_mounts does not exist!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pick a random preferred mount from the selection, if available
|
||||||
|
uint32 chosenMountId = 0;
|
||||||
|
|
||||||
|
if (GetMountType(master) == 0 && !mountCache[botGUID].groundMounts.empty())
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
//}
|
||||||
|
|
||||||
|
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))
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user