mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge branch 'liyunfan1223:master' into login-range
This commit is contained in:
@@ -3970,15 +3970,37 @@ bool IsAlliance(uint8 race)
|
|||||||
|
|
||||||
bool PlayerbotAI::HasRealPlayerMaster()
|
bool PlayerbotAI::HasRealPlayerMaster()
|
||||||
{
|
{
|
||||||
if (master)
|
// if (master)
|
||||||
|
// {
|
||||||
|
// PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master);
|
||||||
|
// return !masterBotAI || masterBotAI->IsRealPlayer();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
// Removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
/* 1) The "master" pointer can be null if the bot was created
|
||||||
|
without a master player or if the master was just removed. */
|
||||||
|
if (!master)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* 2) Is the master player still present in the world?
|
||||||
|
If FindPlayer fails, we invalidate "master" and stop here. */
|
||||||
|
if (!ObjectAccessor::FindPlayer(master->GetGUID()))
|
||||||
{
|
{
|
||||||
PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master);
|
master = nullptr; // avoids repeating the check on the next tick
|
||||||
return !masterBotAI || masterBotAI->IsRealPlayer();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
/* 3) If the master is a bot, we check that it is itself controlled
|
||||||
|
by a real player. Otherwise, it's already a real player → true. */
|
||||||
|
if (PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master))
|
||||||
|
return masterBotAI->IsRealPlayer(); // bot controlled by a player?
|
||||||
|
|
||||||
|
return true; // master = real player
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PlayerbotAI::HasActivePlayerMaster() { return master && !GET_PLAYERBOT_AI(master); }
|
bool PlayerbotAI::HasActivePlayerMaster() { return master && !GET_PLAYERBOT_AI(master); }
|
||||||
|
|
||||||
bool PlayerbotAI::IsAlt() { return HasRealPlayerMaster() && !sRandomPlayerbotMgr->IsRandomBot(bot); }
|
bool PlayerbotAI::IsAlt() { return HasRealPlayerMaster() && !sRandomPlayerbotMgr->IsRandomBot(bot); }
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#include "WorldSessionMgr.h"
|
#include "WorldSessionMgr.h"
|
||||||
#include "DatabaseEnv.h" // Added for gender choice
|
#include "DatabaseEnv.h" // Added for gender choice
|
||||||
#include <algorithm> // Added for gender choice
|
#include <algorithm> // Added for gender choice
|
||||||
|
#include "Log.h" // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
#include <shared_mutex> // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
|
||||||
class BotInitGuard
|
class BotInitGuard
|
||||||
{
|
{
|
||||||
@@ -1726,23 +1728,72 @@ void PlayerbotsMgr::RemovePlayerBotData(ObjectGuid const& guid, bool is_AI)
|
|||||||
|
|
||||||
PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player)
|
PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player)
|
||||||
{
|
{
|
||||||
if (!(sPlayerbotAIConfig->enabled) || !player)
|
// if (!(sPlayerbotAIConfig->enabled) || !player)
|
||||||
{
|
// {
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
// if (player->GetSession()->isLogingOut() || player->IsDuringRemoveFromWorld()) {
|
|
||||||
// return nullptr;
|
// return nullptr;
|
||||||
// }
|
// }
|
||||||
auto itr = _playerbotsAIMap.find(player->GetGUID());
|
// // if (player->GetSession()->isLogingOut() || player->IsDuringRemoveFromWorld()) {
|
||||||
if (itr != _playerbotsAIMap.end())
|
// // return nullptr;
|
||||||
{
|
// // }
|
||||||
if (itr->second->IsBotAI())
|
// auto itr = _playerbotsAIMap.find(player->GetGUID());
|
||||||
return reinterpret_cast<PlayerbotAI*>(itr->second);
|
// if (itr != _playerbotsAIMap.end())
|
||||||
|
// {
|
||||||
|
// if (itr->second->IsBotAI())
|
||||||
|
// return reinterpret_cast<PlayerbotAI*>(itr->second);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return nullptr;
|
||||||
|
|
||||||
|
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
if (!player || !sPlayerbotAIConfig->enabled)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// First read the GUID into a local variable, but ONLY after the check!
|
||||||
|
ObjectGuid guid = player->GetGUID(); // <-- OK here, we know that player != nullptr
|
||||||
|
{
|
||||||
|
std::shared_lock rlock(_aiMutex);
|
||||||
|
auto it = _playerbotsAIMap.find(guid);
|
||||||
|
if (it != _playerbotsAIMap.end() && it->second->IsBotAI())
|
||||||
|
return static_cast<PlayerbotAI*>(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transient state: NEVER break the master ⇄ bots relationship here.
|
||||||
|
if (!ObjectAccessor::FindPlayer(guid))
|
||||||
|
{
|
||||||
|
RemovePlayerbotAI(guid, /*removeMgrEntry=*/false);
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
PlayerbotAI* PlayerbotsMgr::GetPlayerbotAIByGuid(ObjectGuid guid)
|
||||||
|
{
|
||||||
|
if (!sPlayerbotAIConfig->enabled)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::shared_lock rlock(_aiMutex);
|
||||||
|
auto it = _playerbotsAIMap.find(guid);
|
||||||
|
if (it != _playerbotsAIMap.end() && it->second->IsBotAI())
|
||||||
|
return static_cast<PlayerbotAI*>(it->second);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerbotsMgr::RemovePlayerbotAI(ObjectGuid const& guid, bool removeMgrEntry /*= true*/)
|
||||||
|
{
|
||||||
|
std::unique_lock wlock(_aiMutex);
|
||||||
|
|
||||||
|
if (auto it = _playerbotsAIMap.find(guid); it != _playerbotsAIMap.end())
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
_playerbotsAIMap.erase(it);
|
||||||
|
LOG_DEBUG("playerbots", "Removed stale AI for GUID {}",
|
||||||
|
static_cast<uint64>(guid.GetRawValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeMgrEntry)
|
||||||
|
_playerbotsMgrMap.erase(guid); // we NO longer touch the relation in a "soft" purge
|
||||||
|
}
|
||||||
|
|
||||||
PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player)
|
PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player)
|
||||||
{
|
{
|
||||||
if (!(sPlayerbotAIConfig->enabled) || !player)
|
if (!(sPlayerbotAIConfig->enabled) || !player)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "PlayerbotAIBase.h"
|
#include "PlayerbotAIBase.h"
|
||||||
#include "QueryHolder.h"
|
#include "QueryHolder.h"
|
||||||
#include "QueryResult.h"
|
#include "QueryResult.h"
|
||||||
|
#include <shared_mutex> // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
|
||||||
class ChatHandler;
|
class ChatHandler;
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
@@ -114,13 +115,38 @@ public:
|
|||||||
void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI);
|
void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI);
|
||||||
|
|
||||||
PlayerbotAI* GetPlayerbotAI(Player* player);
|
PlayerbotAI* GetPlayerbotAI(Player* player);
|
||||||
|
PlayerbotAI* GetPlayerbotAIByGuid(ObjectGuid guid); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
// void RemovePlayerbotAI(ObjectGuid const& guid); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
// removeMgrEntry = true => "hard" purge (AI + manager relation), for real logouts
|
||||||
|
// removeMgrEntry = false => "soft" purge (AI only), for detected "stale" cases
|
||||||
|
void RemovePlayerbotAI(ObjectGuid const& guid, bool removeMgrEntry = true);
|
||||||
PlayerbotMgr* GetPlayerbotMgr(Player* player);
|
PlayerbotMgr* GetPlayerbotMgr(Player* player);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsAIMap;
|
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsAIMap;
|
||||||
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsMgrMap;
|
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsMgrMap;
|
||||||
|
mutable std::shared_mutex _aiMutex; // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sPlayerbotsMgr PlayerbotsMgr::instance()
|
#define sPlayerbotsMgr PlayerbotsMgr::instance()
|
||||||
|
|
||||||
|
// Temporary addition If it keeps crashing, we will use them.
|
||||||
|
// Like
|
||||||
|
// BEFORE : PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||||
|
// AFTER (safe) : PlayerbotAI* botAI = GET_PLAYERBOT_AI_SAFE(bot);
|
||||||
|
// BEFORE : if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) { ... }
|
||||||
|
// AFTER (safe) : if (PlayerbotAI* botAI = GET_PLAYERBOT_AI_SAFE(player)) { ... }
|
||||||
|
// --- SAFE helpers (append to PlayerbotMgr.h) ---
|
||||||
|
inline PlayerbotAI* GET_PLAYERBOT_AI_SAFE(Player* p)
|
||||||
|
{
|
||||||
|
// Avoid any dereference during transient states (nullptr, teleport, flight, etc.)
|
||||||
|
return p ? sPlayerbotsMgr->GetPlayerbotAI(p) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PlayerbotMgr* GET_PLAYERBOT_MGR_SAFE(Player* p)
|
||||||
|
{
|
||||||
|
return p ? sPlayerbotsMgr->GetPlayerbotMgr(p) : nullptr;
|
||||||
|
}
|
||||||
|
// --- end SAFE helpers ---
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -391,6 +391,10 @@ public:
|
|||||||
|
|
||||||
void OnPlayerbotLogout(Player* player) override
|
void OnPlayerbotLogout(Player* player) override
|
||||||
{
|
{
|
||||||
|
// immediate purge of the bot's AI upon disconnection
|
||||||
|
if (player && player->GetSession()->IsBot())
|
||||||
|
sPlayerbotsMgr->RemovePlayerbotAI(player->GetGUID()); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
|
||||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||||
{
|
{
|
||||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
|
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
|
||||||
|
|||||||
@@ -2258,7 +2258,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot)
|
|||||||
float range = sPlayerbotAIConfig->randomBotTeleportDistance;
|
float range = sPlayerbotAIConfig->randomBotTeleportDistance;
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
|
|
||||||
if (!targets.empty())
|
if (!targets.empty())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -59,10 +59,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
bool sameTarget = oldTarget == target && bot->GetVictim() == target;
|
bool sameTarget = oldTarget == target && bot->GetVictim() == target;
|
||||||
bool inCombat = botAI->GetState() == BOT_STATE_COMBAT;
|
bool inCombat = botAI->GetState() == BOT_STATE_COMBAT;
|
||||||
bool sameAttackMode = bot->HasUnitState(UNIT_STATE_MELEE_ATTACKING) == shouldMelee;
|
bool sameAttackMode = bot->HasUnitState(UNIT_STATE_MELEE_ATTACKING) == shouldMelee;
|
||||||
// there's no reason to do attack again
|
|
||||||
if (sameTarget && inCombat && sameAttackMode)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE ||
|
if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE ||
|
||||||
bot->HasUnitState(UNIT_STATE_IN_FLIGHT))
|
bot->HasUnitState(UNIT_STATE_IN_FLIGHT))
|
||||||
{
|
{
|
||||||
@@ -82,52 +79,53 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
|
|
||||||
if (!target->IsInWorld())
|
if (!target->IsInWorld())
|
||||||
{
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError(std::string(target->GetName()) + " is no longer in the world.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sPlayerbotAIConfig->IsInPvpProhibitedZone(bot->GetZoneId()) ||
|
||||||
|
sPlayerbotAIConfig->IsInPvpProhibitedArea(bot->GetAreaId()))
|
||||||
|
&& (target->IsPlayer() || target->IsPet()))
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError("I cannot attack other players in PvP prohibited areas.");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bot->IsFriendlyTo(target))
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError(std::string(target->GetName()) + " is friendly to me.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->isDead())
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError(std::string(target->GetName()) + " is dead.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bot->IsWithinLOSInMap(target))
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError(std::string(target->GetName()) + " is not in my sight.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sameTarget && inCombat && sameAttackMode)
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError("I am already attacking " + std::string(target->GetName()) + ".");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bot->IsValidAttackTarget(target))
|
if (!bot->IsValidAttackTarget(target))
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError("I cannot attack an invalid target");
|
botAI->TellError("I cannot attack an invalid target.");
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostringstream msg;
|
|
||||||
msg << target->GetName();
|
|
||||||
|
|
||||||
if (bot->IsFriendlyTo(target))
|
|
||||||
{
|
|
||||||
msg << " is friendly to me";
|
|
||||||
if (verbose)
|
|
||||||
botAI->TellError(msg.str());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bot->IsWithinLOSInMap(target))
|
|
||||||
{
|
|
||||||
msg << " is not in my sight";
|
|
||||||
if (verbose)
|
|
||||||
botAI->TellError(msg.str());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target->isDead())
|
|
||||||
{
|
|
||||||
msg << " is dead";
|
|
||||||
if (verbose)
|
|
||||||
botAI->TellError(msg.str());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sPlayerbotAIConfig->IsInPvpProhibitedZone(bot->GetZoneId())
|
|
||||||
&& (target->IsPlayer() || target->IsPet()))
|
|
||||||
{
|
|
||||||
if (verbose)
|
|
||||||
botAI->TellError("I cannot attack others in PvP prohibited zones");
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -141,9 +139,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
ObjectGuid guid = target->GetGUID();
|
ObjectGuid guid = target->GetGUID();
|
||||||
bot->SetSelection(target->GetGUID());
|
bot->SetSelection(target->GetGUID());
|
||||||
|
|
||||||
|
context->GetValue<Unit*>("old target")->Set(oldTarget);
|
||||||
|
|
||||||
context->GetValue<Unit*>("old target")->Set(oldTarget);
|
|
||||||
|
|
||||||
context->GetValue<Unit*>("current target")->Set(target);
|
context->GetValue<Unit*>("current target")->Set(target);
|
||||||
context->GetValue<LootObjectStack*>("available loot")->Get()->Add(guid);
|
context->GetValue<LootObjectStack*>("available loot")->Get()->Add(guid);
|
||||||
@@ -157,7 +153,6 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
bot->StopMoving();
|
bot->StopMoving();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target))
|
if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target))
|
||||||
{
|
{
|
||||||
sServerFacade->SetFacingTo(bot, target);
|
sServerFacade->SetFacingTo(bot, target);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ bool RevealGatheringItemAction::Execute(Event event)
|
|||||||
std::list<GameObject*> targets;
|
std::list<GameObject*> targets;
|
||||||
AnyGameObjectInObjectRangeCheck u_check(bot, sPlayerbotAIConfig->grindDistance);
|
AnyGameObjectInObjectRangeCheck u_check(bot, sPlayerbotAIConfig->grindDistance);
|
||||||
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, sPlayerbotAIConfig->reactDistance);
|
Cell::VisitObjects(bot, searcher, sPlayerbotAIConfig->reactDistance);
|
||||||
|
|
||||||
std::vector<GameObject*> result;
|
std::vector<GameObject*> result;
|
||||||
for (GameObject* go : targets)
|
for (GameObject* go : targets)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ bool TravelAction::Execute(Event event)
|
|||||||
std::list<Unit*> targets;
|
std::list<Unit*> targets;
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, sPlayerbotAIConfig->sightDistance * 2);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, sPlayerbotAIConfig->sightDistance * 2);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, sPlayerbotAIConfig->sightDistance);
|
Cell::VisitObjects(bot, searcher, sPlayerbotAIConfig->sightDistance);
|
||||||
|
|
||||||
for (Unit* unit : targets)
|
for (Unit* unit : targets)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ bool SummonAction::SummonUsingGos(Player* summoner, Player* player)
|
|||||||
std::list<GameObject*> targets;
|
std::list<GameObject*> targets;
|
||||||
AnyGameObjectInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig->sightDistance);
|
AnyGameObjectInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig->sightDistance);
|
||||||
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(summoner, targets, u_check);
|
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(summoner, targets, u_check);
|
||||||
Cell::VisitAllObjects(summoner, searcher, sPlayerbotAIConfig->sightDistance);
|
Cell::VisitObjects(summoner, searcher, sPlayerbotAIConfig->sightDistance);
|
||||||
|
|
||||||
for (GameObject* go : targets)
|
for (GameObject* go : targets)
|
||||||
{
|
{
|
||||||
@@ -130,7 +130,7 @@ bool SummonAction::SummonUsingNpcs(Player* summoner, Player* player)
|
|||||||
std::list<Unit*> targets;
|
std::list<Unit*> targets;
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig->sightDistance);
|
Acore::AnyUnitInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig->sightDistance);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(summoner, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(summoner, targets, u_check);
|
||||||
Cell::VisitAllObjects(summoner, searcher, sPlayerbotAIConfig->sightDistance);
|
Cell::VisitObjects(summoner, searcher, sPlayerbotAIConfig->sightDistance);
|
||||||
|
|
||||||
for (Unit* unit : targets)
|
for (Unit* unit : targets)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6549,7 +6549,7 @@ bool IccSindragosaFrostBombAction::Execute(Event event)
|
|||||||
float range = 200.0f;
|
float range = 200.0f;
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, units, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, units, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
|
|
||||||
for (Unit* unit : units)
|
for (Unit* unit : units)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ bool CollisionValue::Calculate()
|
|||||||
float range = sPlayerbotAIConfig->contactDistance;
|
float range = sPlayerbotAIConfig->contactDistance;
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
|
|
||||||
for (Unit* target : targets)
|
for (Unit* target : targets)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void NearestCorpsesValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
AnyDeadUnitInObjectRangeCheck u_check(bot, range);
|
AnyDeadUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<AnyDeadUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<AnyDeadUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestCorpsesValue::AcceptUnit(Unit* unit) { return true; }
|
bool NearestCorpsesValue::AcceptUnit(Unit* unit) { return true; }
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void NearestFriendlyPlayersValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyFriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
Acore::AnyFriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyFriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyFriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestFriendlyPlayersValue::AcceptUnit(Unit* unit)
|
bool NearestFriendlyPlayersValue::AcceptUnit(Unit* unit)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ GuidVector NearestGameObjects::Calculate()
|
|||||||
std::list<GameObject*> targets;
|
std::list<GameObject*> targets;
|
||||||
AnyGameObjectInObjectRangeCheck u_check(bot, range);
|
AnyGameObjectInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
|
|
||||||
GuidVector result;
|
GuidVector result;
|
||||||
for (GameObject* go : targets)
|
for (GameObject* go : targets)
|
||||||
@@ -34,7 +34,7 @@ GuidVector NearestTrapWithDamageValue::Calculate()
|
|||||||
std::list<GameObject*> targets;
|
std::list<GameObject*> targets;
|
||||||
AnyGameObjectInObjectRangeCheck u_check(bot, range);
|
AnyGameObjectInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
|
|
||||||
GuidVector result;
|
GuidVector result;
|
||||||
for (GameObject* go : targets)
|
for (GameObject* go : targets)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void NearestNonBotPlayersValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestNonBotPlayersValue::AcceptUnit(Unit* unit)
|
bool NearestNonBotPlayersValue::AcceptUnit(Unit* unit)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ void NearestNpcsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestNpcsValue::AcceptUnit(Unit* unit) { return !unit->IsPlayer(); }
|
bool NearestNpcsValue::AcceptUnit(Unit* unit) { return !unit->IsPlayer(); }
|
||||||
@@ -24,7 +24,7 @@ void NearestHostileNpcsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestHostileNpcsValue::AcceptUnit(Unit* unit) { return unit->IsHostileTo(bot) && !unit->IsPlayer(); }
|
bool NearestHostileNpcsValue::AcceptUnit(Unit* unit) { return unit->IsHostileTo(bot) && !unit->IsPlayer(); }
|
||||||
@@ -33,7 +33,7 @@ void NearestVehiclesValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestVehiclesValue::AcceptUnit(Unit* unit)
|
bool NearestVehiclesValue::AcceptUnit(Unit* unit)
|
||||||
@@ -52,7 +52,7 @@ void NearestTriggersValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestTriggersValue::AcceptUnit(Unit* unit) { return !unit->IsPlayer(); }
|
bool NearestTriggersValue::AcceptUnit(Unit* unit) { return !unit->IsPlayer(); }
|
||||||
@@ -61,7 +61,7 @@ void NearestTotemsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestTotemsValue::AcceptUnit(Unit* unit) { return unit->IsTotem(); }
|
bool NearestTotemsValue::AcceptUnit(Unit* unit) { return unit->IsTotem(); }
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void PossibleRpgTargetsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PossibleRpgTargetsValue::AcceptUnit(Unit* unit)
|
bool PossibleRpgTargetsValue::AcceptUnit(Unit* unit)
|
||||||
@@ -141,7 +141,7 @@ void PossibleNewRpgTargetsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
Acore::AnyUnitInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PossibleNewRpgTargetsValue::AcceptUnit(Unit* unit)
|
bool PossibleNewRpgTargetsValue::AcceptUnit(Unit* unit)
|
||||||
@@ -168,7 +168,7 @@ GuidVector PossibleNewRpgGameObjectsValue::Calculate()
|
|||||||
std::list<GameObject*> targets;
|
std::list<GameObject*> targets;
|
||||||
AnyGameObjectInObjectRangeCheck u_check(bot, range);
|
AnyGameObjectInObjectRangeCheck u_check(bot, range);
|
||||||
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::pair<ObjectGuid, float>> guidDistancePairs;
|
std::vector<std::pair<ObjectGuid, float>> guidDistancePairs;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void PossibleTargetsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PossibleTargetsValue::AcceptUnit(Unit* unit) { return AttackersValue::IsPossibleTarget(unit, bot, range); }
|
bool PossibleTargetsValue::AcceptUnit(Unit* unit) { return AttackersValue::IsPossibleTarget(unit, bot, range); }
|
||||||
@@ -30,7 +30,7 @@ void PossibleTriggersValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
{
|
{
|
||||||
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
||||||
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PossibleTriggersValue::AcceptUnit(Unit* unit)
|
bool PossibleTriggersValue::AcceptUnit(Unit* unit)
|
||||||
|
|||||||
@@ -207,7 +207,11 @@ bool WrongPetTrigger::IsActive()
|
|||||||
if (enabledCount != 1)
|
if (enabledCount != 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 3: At this point, we know only one pet strategy is enabled.
|
// Step 3: If there is no pet, do not trigger.
|
||||||
|
if (!pet)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Step 4: At this point, we know only one pet strategy is enabled.
|
||||||
// We check if the currently summoned pet matches the enabled strategy.
|
// We check if the currently summoned pet matches the enabled strategy.
|
||||||
bool correctPet = false;
|
bool correctPet = false;
|
||||||
if (pet)
|
if (pet)
|
||||||
@@ -218,16 +222,16 @@ bool WrongPetTrigger::IsActive()
|
|||||||
correctPet = true;
|
correctPet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: If the correct pet is already summoned, the trigger should not activate.
|
// Step 5: If the correct pet is already summoned, the trigger should not activate.
|
||||||
if (correctPet)
|
if (correctPet)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 5: Finally, check if the bot actually knows the spell to summon the desired pet.
|
// Step 6: Finally, check if the bot actually knows the spell to summon the desired pet.
|
||||||
// If so, the trigger is active (bot should summon the correct pet).
|
// If so, the trigger is active (bot should summon the correct pet).
|
||||||
if (bot->HasSpell(enabledPet->spellId))
|
if (bot->HasSpell(enabledPet->spellId))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Step 6: If we get here, the bot doesn't know the spell required to support the active pet strategy
|
// Step 7: If we get here, the bot doesn't know the spell required to support the active pet strategy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user