mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
RPG update travel flight status (#1445)
This commit is contained in:
@@ -212,7 +212,8 @@ PlayerbotAI::PlayerbotAI(Player* bot)
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_PUSHQUESTTOPARTY, "quest share");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_COMPLETE, "quest update complete");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_ADD_KILL, "quest update add kill");
|
||||
// botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_ADD_ITEM, "quest update add item"); // SMSG_QUESTUPDATE_ADD_ITEM no longer used
|
||||
// SMSG_QUESTUPDATE_ADD_ITEM no longer used
|
||||
// botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_ADD_ITEM, "quest update add item");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUEST_CONFIRM_ACCEPT, "confirm quest");
|
||||
}
|
||||
|
||||
@@ -1291,11 +1292,6 @@ void PlayerbotAI::DoNextAction(bool min)
|
||||
return;
|
||||
}
|
||||
|
||||
if (bot->HasUnitState(UNIT_STATE_IN_FLIGHT))
|
||||
{
|
||||
SetNextCheckDelay(sPlayerbotAIConfig->passiveDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
// Change engine if just died
|
||||
bool isBotAlive = bot->IsAlive();
|
||||
@@ -1425,8 +1421,8 @@ void PlayerbotAI::DoNextAction(bool min)
|
||||
master = newMaster;
|
||||
botAI->SetMaster(newMaster);
|
||||
botAI->ResetStrategies();
|
||||
|
||||
if (!bot->InBattleground())
|
||||
|
||||
if (!bot->InBattleground())
|
||||
{
|
||||
botAI->ChangeStrategy("+follow", BOT_STATE_NON_COMBAT);
|
||||
|
||||
@@ -1437,7 +1433,7 @@ void PlayerbotAI::DoNextAction(bool min)
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're in a battleground, stay with the pack and focus on objective
|
||||
// we're in a battleground, stay with the pack and focus on objective
|
||||
botAI->ChangeStrategy("-follow", BOT_STATE_NON_COMBAT);
|
||||
}
|
||||
}
|
||||
@@ -2358,7 +2354,6 @@ std::string PlayerbotAI::GetLocalizedCreatureName(uint32 entry)
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
std::string PlayerbotAI::GetLocalizedGameObjectName(uint32 entry)
|
||||
{
|
||||
std::string name;
|
||||
@@ -3330,13 +3325,14 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
std::ostringstream out;
|
||||
out << "Spell cast failed - ";
|
||||
out << "Spell ID: " << spellId << " (" << ChatHelper::FormatSpell(spellInfo) << "), ";
|
||||
out << "Error Code: " << static_cast<int>(result) << " (0x" << std::hex << static_cast<int>(result) << std::dec << "), ";
|
||||
out << "Error Code: " << static_cast<int>(result) << " (0x" << std::hex << static_cast<int>(result)
|
||||
<< std::dec << "), ";
|
||||
out << "Bot: " << bot->GetName() << ", ";
|
||||
|
||||
|
||||
// Check spell target type
|
||||
if (targets.GetUnitTarget())
|
||||
{
|
||||
out << "Target: Unit (" << targets.GetUnitTarget()->GetName()
|
||||
out << "Target: Unit (" << targets.GetUnitTarget()->GetName()
|
||||
<< ", Low GUID: " << targets.GetUnitTarget()->GetGUID().GetCounter()
|
||||
<< ", High GUID: " << static_cast<uint32>(targets.GetUnitTarget()->GetGUID().GetHigh()) << "), ";
|
||||
}
|
||||
@@ -3352,7 +3348,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
out << "Target: Item (Low GUID: " << targets.GetItemTarget()->GetGUID().GetCounter()
|
||||
<< ", High GUID: " << static_cast<uint32>(targets.GetItemTarget()->GetGUID().GetHigh()) << "), ";
|
||||
}
|
||||
|
||||
|
||||
// Check if bot is in trade mode
|
||||
if (bot->GetTradeData())
|
||||
{
|
||||
@@ -3360,7 +3356,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
Item* tradeItem = bot->GetTradeData()->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED);
|
||||
if (tradeItem)
|
||||
{
|
||||
out << "Trade Item: " << tradeItem->GetEntry()
|
||||
out << "Trade Item: " << tradeItem->GetEntry()
|
||||
<< " (Low GUID: " << tradeItem->GetGUID().GetCounter()
|
||||
<< ", High GUID: " << static_cast<uint32>(tradeItem->GetGUID().GetHigh()) << "), ";
|
||||
}
|
||||
@@ -3373,7 +3369,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
{
|
||||
out << "Trade Mode: Inactive, ";
|
||||
}
|
||||
|
||||
|
||||
TellMasterNoFacing(out);
|
||||
}
|
||||
|
||||
@@ -4312,7 +4308,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType)
|
||||
if (!player || !player->IsInWorld())
|
||||
continue;
|
||||
|
||||
Player* connectedPlayer = ObjectAccessor::FindPlayer(player->GetGUID());
|
||||
Player* connectedPlayer = ObjectAccessor::FindPlayer(player->GetGUID());
|
||||
if (!connectedPlayer)
|
||||
continue;
|
||||
|
||||
@@ -4394,16 +4390,16 @@ uint32 PlayerbotAI::AutoScaleActivity(uint32 mod)
|
||||
// Perfrom binary decision if ceiling <= floor: Either all bots are active or none are
|
||||
return (maxDiff > diffLimitCeiling) ? 0 : mod;
|
||||
}
|
||||
|
||||
|
||||
if (maxDiff > diffLimitCeiling)
|
||||
return 0;
|
||||
|
||||
|
||||
if (maxDiff <= diffLimitFloor)
|
||||
return mod;
|
||||
|
||||
|
||||
// Calculate lag progress from floor to ceiling (0 to 1)
|
||||
double lagProgress = (maxDiff - diffLimitFloor) / (double)(diffLimitCeiling - diffLimitFloor);
|
||||
|
||||
|
||||
// Apply the percentage of active bots (the complement of lag progress) to the mod value
|
||||
return static_cast<uint32>(mod * (1 - lagProgress));
|
||||
}
|
||||
@@ -4434,47 +4430,47 @@ void PlayerbotAI::RemoveShapeshift()
|
||||
// https://wowpedia.fandom.com/wiki/API_GetAverageItemLevel
|
||||
uint32 PlayerbotAI::GetEquipGearScore(Player* player)
|
||||
{
|
||||
constexpr uint8 TOTAL_SLOTS = 17; // every slot except Body & Tabard
|
||||
constexpr uint8 TOTAL_SLOTS = 17; // every slot except Body & Tabard
|
||||
uint32 sumLevel = 0;
|
||||
|
||||
/* ---------- 0. Detect “ignore off-hand” situations --------- */
|
||||
Item* main = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
|
||||
Item* off = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
|
||||
Item* off = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
|
||||
|
||||
bool ignoreOffhand = false; // true → divisor = 16
|
||||
bool ignoreOffhand = false; // true → divisor = 16
|
||||
if (main)
|
||||
{
|
||||
bool twoHand = (main->GetTemplate()->InventoryType == INVTYPE_2HWEAPON);
|
||||
if (twoHand && !player->HasAura(SPELL_TITAN_GRIP))
|
||||
ignoreOffhand = true; // classic 2-hander
|
||||
ignoreOffhand = true; // classic 2-hander
|
||||
}
|
||||
else if (!off) // both hands empty
|
||||
else if (!off) // both hands empty
|
||||
ignoreOffhand = true;
|
||||
|
||||
/* ---------- 1. Sum up item-levels -------------------------- */
|
||||
for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)
|
||||
{
|
||||
if (slot == EQUIPMENT_SLOT_BODY || slot == EQUIPMENT_SLOT_TABARD)
|
||||
continue; // Blizzard never counts these
|
||||
continue; // Blizzard never counts these
|
||||
|
||||
if (ignoreOffhand && slot == EQUIPMENT_SLOT_OFFHAND)
|
||||
continue; // skip off-hand in 2-H case
|
||||
continue; // skip off-hand in 2-H case
|
||||
|
||||
if (Item* it = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
|
||||
sumLevel += it->GetTemplate()->ItemLevel; // missing items add 0
|
||||
sumLevel += it->GetTemplate()->ItemLevel; // missing items add 0
|
||||
}
|
||||
|
||||
/* ---------- 2. Divide by 17 or 16 -------------------------- */
|
||||
const uint8 divisor = ignoreOffhand ? TOTAL_SLOTS - 1 : TOTAL_SLOTS; // 16 or 17
|
||||
const uint8 divisor = ignoreOffhand ? TOTAL_SLOTS - 1 : TOTAL_SLOTS; // 16 or 17
|
||||
return sumLevel / divisor;
|
||||
}
|
||||
|
||||
// NOTE : function rewritten as flags "withBags" and "withBank" not used, and _fillGearScoreData sometimes attribute
|
||||
// one-hand/2H Weapon in wrong slots
|
||||
// one-hand/2H Weapon in wrong slots
|
||||
/*uint32 PlayerbotAI::GetEquipGearScore(Player* player)
|
||||
{
|
||||
// This function aims to calculate the equipped gear score
|
||||
|
||||
|
||||
uint32 sum = 0;
|
||||
uint8 count = EQUIPMENT_SLOT_END - 2; // ignore body and tabard slots
|
||||
uint8 mh_type = 0;
|
||||
@@ -4483,17 +4479,17 @@ uint32 PlayerbotAI::GetEquipGearScore(Player* player)
|
||||
{
|
||||
Item* item =player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (item && i != EQUIPMENT_SLOT_BODY && i != EQUIPMENT_SLOT_TABARD)
|
||||
{
|
||||
{
|
||||
ItemTemplate const* proto = item->GetTemplate();
|
||||
sum += proto->ItemLevel;
|
||||
|
||||
|
||||
// If character is not warfury and have 2 hand weapon equipped, main hand will be counted twice
|
||||
if (i == SLOT_MAIN_HAND)
|
||||
mh_type = item->GetTemplate()->InventoryType;
|
||||
if (!player->HasAura(SPELL_TITAN_GRIP) && mh_type == INVTYPE_2HWEAPON && i == SLOT_MAIN_HAND)
|
||||
sum += item->GetTemplate()->ItemLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 gs = uint32(sum / count);
|
||||
return gs;
|
||||
@@ -4730,7 +4726,7 @@ void PlayerbotAI::_fillGearScoreData(Player* player, Item* item, std::vector<uin
|
||||
case INVTYPE_SHOULDERS:
|
||||
(*gearScore)[EQUIPMENT_SLOT_SHOULDERS] = std::max((*gearScore)[EQUIPMENT_SLOT_SHOULDERS], level);
|
||||
break;
|
||||
case INVTYPE_BODY: //Shouldn't be considered when calculating average ilevel
|
||||
case INVTYPE_BODY: // Shouldn't be considered when calculating average ilevel
|
||||
(*gearScore)[EQUIPMENT_SLOT_BODY] = std::max((*gearScore)[EQUIPMENT_SLOT_BODY], level);
|
||||
break;
|
||||
case INVTYPE_CHEST:
|
||||
@@ -5108,48 +5104,50 @@ Item* PlayerbotAI::FindBandage() const
|
||||
|
||||
Item* PlayerbotAI::FindOpenableItem() const
|
||||
{
|
||||
return FindItemInInventory([this](ItemTemplate const* itemTemplate) -> bool
|
||||
{
|
||||
return (itemTemplate->Flags & ITEM_FLAG_HAS_LOOT) &&
|
||||
(itemTemplate->LockID == 0 || !this->bot->GetItemByEntry(itemTemplate->ItemId)->IsLocked());
|
||||
});
|
||||
return FindItemInInventory(
|
||||
[this](ItemTemplate const* itemTemplate) -> bool
|
||||
{
|
||||
return (itemTemplate->Flags & ITEM_FLAG_HAS_LOOT) &&
|
||||
(itemTemplate->LockID == 0 || !this->bot->GetItemByEntry(itemTemplate->ItemId)->IsLocked());
|
||||
});
|
||||
}
|
||||
|
||||
Item* PlayerbotAI::FindLockedItem() const
|
||||
{
|
||||
return FindItemInInventory([this](ItemTemplate const* itemTemplate) -> bool
|
||||
{
|
||||
if (!this->bot->HasSkill(SKILL_LOCKPICKING)) // Ensure bot has Lockpicking skill
|
||||
return false;
|
||||
|
||||
if (itemTemplate->LockID == 0) // Ensure the item is actually locked
|
||||
return false;
|
||||
|
||||
Item* item = this->bot->GetItemByEntry(itemTemplate->ItemId);
|
||||
if (!item || !item->IsLocked()) // Ensure item instance is locked
|
||||
return false;
|
||||
|
||||
// Check if bot has enough Lockpicking skill
|
||||
LockEntry const* lockInfo = sLockStore.LookupEntry(itemTemplate->LockID);
|
||||
if (!lockInfo)
|
||||
return false;
|
||||
|
||||
for (uint8 j = 0; j < 8; ++j)
|
||||
return FindItemInInventory(
|
||||
[this](ItemTemplate const* itemTemplate) -> bool
|
||||
{
|
||||
if (lockInfo->Type[j] == LOCK_KEY_SKILL)
|
||||
if (!this->bot->HasSkill(SKILL_LOCKPICKING)) // Ensure bot has Lockpicking skill
|
||||
return false;
|
||||
|
||||
if (itemTemplate->LockID == 0) // Ensure the item is actually locked
|
||||
return false;
|
||||
|
||||
Item* item = this->bot->GetItemByEntry(itemTemplate->ItemId);
|
||||
if (!item || !item->IsLocked()) // Ensure item instance is locked
|
||||
return false;
|
||||
|
||||
// Check if bot has enough Lockpicking skill
|
||||
LockEntry const* lockInfo = sLockStore.LookupEntry(itemTemplate->LockID);
|
||||
if (!lockInfo)
|
||||
return false;
|
||||
|
||||
for (uint8 j = 0; j < 8; ++j)
|
||||
{
|
||||
uint32 skillId = SkillByLockType(LockType(lockInfo->Index[j]));
|
||||
if (skillId == SKILL_LOCKPICKING)
|
||||
if (lockInfo->Type[j] == LOCK_KEY_SKILL)
|
||||
{
|
||||
uint32 requiredSkill = lockInfo->Skill[j];
|
||||
uint32 botSkill = this->bot->GetSkillValue(SKILL_LOCKPICKING);
|
||||
return botSkill >= requiredSkill;
|
||||
uint32 skillId = SkillByLockType(LockType(lockInfo->Index[j]));
|
||||
if (skillId == SKILL_LOCKPICKING)
|
||||
{
|
||||
uint32 requiredSkill = lockInfo->Skill[j];
|
||||
uint32 botSkill = this->bot->GetSkillValue(SKILL_LOCKPICKING);
|
||||
return botSkill >= requiredSkill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
static const uint32 uPriorizedSharpStoneIds[8] = {ADAMANTITE_SHARPENING_DISPLAYID, FEL_SHARPENING_DISPLAYID,
|
||||
@@ -6072,6 +6070,35 @@ ChatChannelSource PlayerbotAI::GetChatChannelSource(Player* bot, uint32 type, st
|
||||
return ChatChannelSource::SRC_UNDEFINED;
|
||||
}
|
||||
|
||||
bool PlayerbotAI::CheckLocationDistanceByLevel(Player* player, const WorldLocation& loc, bool fromStartUp)
|
||||
{
|
||||
if (player->GetLevel() > 16)
|
||||
return true;
|
||||
|
||||
float dis = 0.0f;
|
||||
if (fromStartUp)
|
||||
{
|
||||
PlayerInfo const* pInfo = sObjectMgr->GetPlayerInfo(player->getRace(true), player->getClass());
|
||||
if (loc.GetMapId() != pInfo->mapId)
|
||||
return false;
|
||||
dis = loc.GetExactDist(pInfo->positionX, pInfo->positionY, pInfo->positionZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (loc.GetMapId() != player->GetMapId())
|
||||
return false;
|
||||
dis = loc.GetExactDist(player);
|
||||
}
|
||||
|
||||
float bound = 10000.0f;
|
||||
if (player->GetLevel() <= 4)
|
||||
bound = 500.0f;
|
||||
else if (player->GetLevel() <= 10)
|
||||
bound = 2500.0f;
|
||||
|
||||
return dis <= bound;
|
||||
}
|
||||
|
||||
std::vector<const Quest*> PlayerbotAI::GetAllCurrentQuests()
|
||||
{
|
||||
std::vector<const Quest*> result;
|
||||
@@ -6347,17 +6374,16 @@ void PlayerbotAI::AddTimedEvent(std::function<void()> callback, uint32 delayMs)
|
||||
class LambdaEvent final : public BasicEvent
|
||||
{
|
||||
std::function<void()> _cb;
|
||||
|
||||
public:
|
||||
explicit LambdaEvent(std::function<void()> cb) : _cb(std::move(cb)) {}
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
_cb();
|
||||
return true; // remove after execution
|
||||
return true; // remove after execution
|
||||
}
|
||||
};
|
||||
|
||||
// Every Player already owns an EventMap called m_Events
|
||||
bot->m_Events.AddEvent(
|
||||
new LambdaEvent(std::move(callback)),
|
||||
bot->m_Events.CalculateTime(delayMs));
|
||||
bot->m_Events.AddEvent(new LambdaEvent(std::move(callback)), bot->m_Events.CalculateTime(delayMs));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user