diff --git a/src/LootObjectStack.cpp b/src/LootObjectStack.cpp index e1d2bc462..adce7f397 100644 --- a/src/LootObjectStack.cpp +++ b/src/LootObjectStack.cpp @@ -6,6 +6,8 @@ #include "LootObjectStack.h" #include "LootMgr.h" +#include "Object.h" +#include "ObjectAccessor.h" #include "Playerbots.h" #include "Unit.h" @@ -287,7 +289,7 @@ bool LootObject::IsLootPossible(Player* bot) if (reqItem && !bot->HasItemCount(reqItem, 1)) return false; - if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE -2.0f) + if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE - 2.0f) return false; Creature* creature = botAI->GetCreature(guid); @@ -299,7 +301,7 @@ bool LootObject::IsLootPossible(Player* bot) // Prevent bot from running to chests that are unlootable (e.g. Gunship Armory before completing the event) GameObject* go = botAI->GetGameObject(guid); - if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE)) + if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE)) return false; if (skillId == SKILL_NONE) @@ -317,29 +319,17 @@ bool LootObject::IsLootPossible(Player* bot) uint32 skillValue = uint32(bot->GetSkillValue(skillId)); if (reqSkillValue > skillValue) return false; - - if (skillId == SKILL_MINING && - !bot->HasItemCount(756, 1) && - !bot->HasItemCount(778, 1) && - !bot->HasItemCount(1819, 1) && - !bot->HasItemCount(1893, 1) && - !bot->HasItemCount(1959, 1) && - !bot->HasItemCount(2901, 1) && - !bot->HasItemCount(9465, 1) && - !bot->HasItemCount(20723, 1) && - !bot->HasItemCount(40772, 1) && - !bot->HasItemCount(40892, 1) && - !bot->HasItemCount(40893, 1)) + + if (skillId == SKILL_MINING && !bot->HasItemCount(756, 1) && !bot->HasItemCount(778, 1) && + !bot->HasItemCount(1819, 1) && !bot->HasItemCount(1893, 1) && !bot->HasItemCount(1959, 1) && + !bot->HasItemCount(2901, 1) && !bot->HasItemCount(9465, 1) && !bot->HasItemCount(20723, 1) && + !bot->HasItemCount(40772, 1) && !bot->HasItemCount(40892, 1) && !bot->HasItemCount(40893, 1)) { return false; // Bot is missing a mining pick } - - if (skillId == SKILL_SKINNING && - !bot->HasItemCount(7005, 1) && - !bot->HasItemCount(40772, 1) && - !bot->HasItemCount(40893, 1) && - !bot->HasItemCount(12709, 1) && - !bot->HasItemCount(19901, 1)) + + if (skillId == SKILL_SKINNING && !bot->HasItemCount(7005, 1) && !bot->HasItemCount(40772, 1) && + !bot->HasItemCount(40893, 1) && !bot->HasItemCount(12709, 1) && !bot->HasItemCount(19901, 1)) { return false; // Bot is missing a skinning knife } @@ -376,42 +366,45 @@ void LootObjectStack::Clear() { availableLoot.clear(); } bool LootObjectStack::CanLoot(float maxDistance) { - std::vector ordered = OrderByDistance(maxDistance); - return !ordered.empty(); + LootObject nearest = GetNearest(maxDistance); + return !nearest.IsEmpty(); } LootObject LootObjectStack::GetLoot(float maxDistance) { - std::vector ordered = OrderByDistance(maxDistance); - return ordered.empty() ? LootObject() : *ordered.begin(); + LootObject nearest = GetNearest(maxDistance); + return nearest.IsEmpty() ? LootObject() : nearest; } -std::vector LootObjectStack::OrderByDistance(float maxDistance) + +LootObject LootObjectStack::GetNearest(float maxDistance) { availableLoot.shrink(time(nullptr) - 30); - std::map sortedMap; + LootObject nearest; + float nearestDistance = std::numeric_limits::max(); + LootTargetList safeCopy(availableLoot); for (LootTargetList::iterator i = safeCopy.begin(); i != safeCopy.end(); i++) { ObjectGuid guid = i->guid; - LootObject lootObject(bot, guid); - if (!lootObject.IsLootPossible(bot)) // Ensure loot object is valid - continue; - WorldObject* worldObj = lootObject.GetWorldObject(bot); - if (!worldObj) // Prevent null pointer dereference - { + WorldObject* worldObj = ObjectAccessor::GetWorldObject(*bot, guid); + if (!worldObj) continue; - } float distance = bot->GetDistance(worldObj); - if (!maxDistance || distance <= maxDistance) - sortedMap[distance] = lootObject; + + if (distance >= nearestDistance || (maxDistance && distance > maxDistance)) + continue; + + LootObject lootObject(bot, guid); + + if (!lootObject.IsLootPossible(bot)) + continue; + + nearestDistance = distance; + nearest = lootObject; } - std::vector result; - for (auto& [_, lootObject] : sortedMap) - result.push_back(lootObject); - - return result; -} + return nearest; +} \ No newline at end of file diff --git a/src/LootObjectStack.h b/src/LootObjectStack.h index b17e7fcc9..9ff7dd997 100644 --- a/src/LootObjectStack.h +++ b/src/LootObjectStack.h @@ -78,7 +78,7 @@ public: LootObject GetLoot(float maxDistance = 0); private: - std::vector OrderByDistance(float maxDistance = 0); + LootObject GetNearest(float maxDistance = 0); Player* bot; LootTargetList availableLoot;