mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-02-20 18:10:02 +01:00
Rogue bots can unlock items in their bags and in the trade window (#1055)
This commit is contained in:
parent
c93bf38463
commit
c4a4d3a9e6
@ -178,6 +178,7 @@ PlayerbotAI::PlayerbotAI(Player* bot)
|
|||||||
botOutgoingPacketHandlers.AddHandler(SMSG_RESURRECT_REQUEST, "resurrect request");
|
botOutgoingPacketHandlers.AddHandler(SMSG_RESURRECT_REQUEST, "resurrect request");
|
||||||
botOutgoingPacketHandlers.AddHandler(SMSG_INVENTORY_CHANGE_FAILURE, "cannot equip");
|
botOutgoingPacketHandlers.AddHandler(SMSG_INVENTORY_CHANGE_FAILURE, "cannot equip");
|
||||||
botOutgoingPacketHandlers.AddHandler(SMSG_TRADE_STATUS, "trade status");
|
botOutgoingPacketHandlers.AddHandler(SMSG_TRADE_STATUS, "trade status");
|
||||||
|
botOutgoingPacketHandlers.AddHandler(SMSG_TRADE_STATUS_EXTENDED, "trade status extended");
|
||||||
botOutgoingPacketHandlers.AddHandler(SMSG_LOOT_RESPONSE, "loot response");
|
botOutgoingPacketHandlers.AddHandler(SMSG_LOOT_RESPONSE, "loot response");
|
||||||
botOutgoingPacketHandlers.AddHandler(SMSG_ITEM_PUSH_RESULT, "item push result");
|
botOutgoingPacketHandlers.AddHandler(SMSG_ITEM_PUSH_RESULT, "item push result");
|
||||||
botOutgoingPacketHandlers.AddHandler(SMSG_PARTY_COMMAND_RESULT, "party command");
|
botOutgoingPacketHandlers.AddHandler(SMSG_PARTY_COMMAND_RESULT, "party command");
|
||||||
@ -3173,7 +3174,8 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
|||||||
Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE);
|
Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE);
|
||||||
|
|
||||||
SpellCastTargets targets;
|
SpellCastTargets targets;
|
||||||
if (spellInfo->Targets & TARGET_FLAG_ITEM)
|
if (spellInfo->Effects[0].Effect != SPELL_EFFECT_OPEN_LOCK &&
|
||||||
|
(spellInfo->Targets & TARGET_FLAG_ITEM || spellInfo->Targets & TARGET_FLAG_GAMEOBJECT_ITEM))
|
||||||
{
|
{
|
||||||
Item* item = itemTarget ? itemTarget : aiObjectContext->GetValue<Item*>("item for spell", spellId)->Get();
|
Item* item = itemTarget ? itemTarget : aiObjectContext->GetValue<Item*>("item for spell", spellId)->Get();
|
||||||
targets.SetItemTarget(item);
|
targets.SetItemTarget(item);
|
||||||
@ -3216,6 +3218,20 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
|||||||
targets.SetGOTarget(go);
|
targets.SetGOTarget(go);
|
||||||
faceTo = go;
|
faceTo = go;
|
||||||
}
|
}
|
||||||
|
else if (itemTarget)
|
||||||
|
{
|
||||||
|
Player* trader = bot->GetTrader();
|
||||||
|
if (trader)
|
||||||
|
{
|
||||||
|
targets.SetTradeItemTarget(bot);
|
||||||
|
targets.SetUnitTarget(bot);
|
||||||
|
faceTo = trader;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targets.SetItemTarget(itemTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Unit* creature = GetUnit(loot.guid))
|
if (Unit* creature = GetUnit(loot.guid))
|
||||||
@ -3252,6 +3268,58 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
|||||||
// LOG_DEBUG("playerbots", "Spell cast failed. - target name: {}, spellid: {}, bot name: {}, result: {}",
|
// LOG_DEBUG("playerbots", "Spell cast failed. - target name: {}, spellid: {}, bot name: {}, result: {}",
|
||||||
// target->GetName(), spellId, bot->GetName(), result);
|
// target->GetName(), spellId, bot->GetName(), result);
|
||||||
// }
|
// }
|
||||||
|
if (HasStrategy("debug spell", BOT_STATE_NON_COMBAT))
|
||||||
|
{
|
||||||
|
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 << "Bot: " << bot->GetName() << ", ";
|
||||||
|
|
||||||
|
// Check spell target type
|
||||||
|
if (targets.GetUnitTarget())
|
||||||
|
{
|
||||||
|
out << "Target: Unit (" << targets.GetUnitTarget()->GetName()
|
||||||
|
<< ", Low GUID: " << targets.GetUnitTarget()->GetGUID().GetCounter()
|
||||||
|
<< ", High GUID: " << static_cast<uint32>(targets.GetUnitTarget()->GetGUID().GetHigh()) << "), ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targets.GetGOTarget())
|
||||||
|
{
|
||||||
|
out << "Target: GameObject (Low GUID: " << targets.GetGOTarget()->GetGUID().GetCounter()
|
||||||
|
<< ", High GUID: " << static_cast<uint32>(targets.GetGOTarget()->GetGUID().GetHigh()) << "), ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targets.GetItemTarget())
|
||||||
|
{
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
out << "Trade Mode: Active, ";
|
||||||
|
Item* tradeItem = bot->GetTradeData()->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED);
|
||||||
|
if (tradeItem)
|
||||||
|
{
|
||||||
|
out << "Trade Item: " << tradeItem->GetEntry()
|
||||||
|
<< " (Low GUID: " << tradeItem->GetGUID().GetCounter()
|
||||||
|
<< ", High GUID: " << static_cast<uint32>(tradeItem->GetGUID().GetHigh()) << "), ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "Trade Item: None, ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "Trade Mode: Inactive, ";
|
||||||
|
}
|
||||||
|
|
||||||
|
TellMasterNoFacing(out);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// if (spellInfo->Effects[0].Effect == SPELL_EFFECT_OPEN_LOCK || spellInfo->Effects[0].Effect ==
|
// if (spellInfo->Effects[0].Effect == SPELL_EFFECT_OPEN_LOCK || spellInfo->Effects[0].Effect ==
|
||||||
@ -3348,7 +3416,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite
|
|||||||
Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE);
|
Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE);
|
||||||
|
|
||||||
SpellCastTargets targets;
|
SpellCastTargets targets;
|
||||||
if (spellInfo->Targets & TARGET_FLAG_ITEM)
|
if (spellInfo->Targets & TARGET_FLAG_ITEM || spellInfo->Targets & TARGET_FLAG_GAMEOBJECT_ITEM)
|
||||||
{
|
{
|
||||||
Item* item = itemTarget ? itemTarget : aiObjectContext->GetValue<Item*>("item for spell", spellId)->Get();
|
Item* item = itemTarget ? itemTarget : aiObjectContext->GetValue<Item*>("item for spell", spellId)->Get();
|
||||||
targets.SetItemTarget(item);
|
targets.SetItemTarget(item);
|
||||||
@ -4904,6 +4972,52 @@ Item* PlayerbotAI::FindBandage() const
|
|||||||
{ return pItemProto->Class == ITEM_CLASS_CONSUMABLE && pItemProto->SubClass == ITEM_SUBCLASS_BANDAGE; });
|
{ return pItemProto->Class == ITEM_CLASS_CONSUMABLE && pItemProto->SubClass == ITEM_SUBCLASS_BANDAGE; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (lockInfo->Type[j] == LOCK_KEY_SKILL)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static const uint32 uPriorizedSharpStoneIds[8] = {ADAMANTITE_SHARPENING_DISPLAYID, FEL_SHARPENING_DISPLAYID,
|
static const uint32 uPriorizedSharpStoneIds[8] = {ADAMANTITE_SHARPENING_DISPLAYID, FEL_SHARPENING_DISPLAYID,
|
||||||
ELEMENTAL_SHARPENING_DISPLAYID, DENSE_SHARPENING_DISPLAYID,
|
ELEMENTAL_SHARPENING_DISPLAYID, DENSE_SHARPENING_DISPLAYID,
|
||||||
SOLID_SHARPENING_DISPLAYID, HEAVY_SHARPENING_DISPLAYID,
|
SOLID_SHARPENING_DISPLAYID, HEAVY_SHARPENING_DISPLAYID,
|
||||||
|
|||||||
@ -467,6 +467,8 @@ public:
|
|||||||
Item* FindPoison() const;
|
Item* FindPoison() const;
|
||||||
Item* FindAmmo() const;
|
Item* FindAmmo() const;
|
||||||
Item* FindBandage() const;
|
Item* FindBandage() const;
|
||||||
|
Item* FindOpenableItem() const;
|
||||||
|
Item* FindLockedItem() const;
|
||||||
Item* FindConsumable(uint32 displayId) const;
|
Item* FindConsumable(uint32 displayId) const;
|
||||||
Item* FindStoneFor(Item* weapon) const;
|
Item* FindStoneFor(Item* weapon) const;
|
||||||
Item* FindOilFor(Item* weapon) const;
|
Item* FindOilFor(Item* weapon) const;
|
||||||
|
|||||||
@ -75,6 +75,8 @@
|
|||||||
#include "WhoAction.h"
|
#include "WhoAction.h"
|
||||||
#include "WtsAction.h"
|
#include "WtsAction.h"
|
||||||
#include "OpenItemAction.h"
|
#include "OpenItemAction.h"
|
||||||
|
#include "UnlockItemAction.h"
|
||||||
|
#include "UnlockTradedItemAction.h"
|
||||||
|
|
||||||
class ChatActionContext : public NamedObjectContext<Action>
|
class ChatActionContext : public NamedObjectContext<Action>
|
||||||
{
|
{
|
||||||
@ -82,6 +84,8 @@ public:
|
|||||||
ChatActionContext()
|
ChatActionContext()
|
||||||
{
|
{
|
||||||
creators["open items"] = &ChatActionContext::open_items;
|
creators["open items"] = &ChatActionContext::open_items;
|
||||||
|
creators["unlock items"] = &ChatActionContext::unlock_items;
|
||||||
|
creators["unlock traded item"] = &ChatActionContext::unlock_traded_item;
|
||||||
creators["range"] = &ChatActionContext::range;
|
creators["range"] = &ChatActionContext::range;
|
||||||
creators["stats"] = &ChatActionContext::stats;
|
creators["stats"] = &ChatActionContext::stats;
|
||||||
creators["quests"] = &ChatActionContext::quests;
|
creators["quests"] = &ChatActionContext::quests;
|
||||||
@ -184,6 +188,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Action* open_items(PlayerbotAI* botAI) { return new OpenItemAction(botAI); }
|
static Action* open_items(PlayerbotAI* botAI) { return new OpenItemAction(botAI); }
|
||||||
|
static Action* unlock_items(PlayerbotAI* botAI) { return new UnlockItemAction(botAI); }
|
||||||
|
static Action* unlock_traded_item(PlayerbotAI* botAI) { return new UnlockTradedItemAction(botAI); }
|
||||||
static Action* range(PlayerbotAI* botAI) { return new RangeAction(botAI); }
|
static Action* range(PlayerbotAI* botAI) { return new RangeAction(botAI); }
|
||||||
static Action* flag(PlayerbotAI* botAI) { return new FlagAction(botAI); }
|
static Action* flag(PlayerbotAI* botAI) { return new FlagAction(botAI); }
|
||||||
static Action* craft(PlayerbotAI* botAI) { return new SetCraftAction(botAI); }
|
static Action* craft(PlayerbotAI* botAI) { return new SetCraftAction(botAI); }
|
||||||
|
|||||||
@ -4,64 +4,23 @@
|
|||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
|
|
||||||
bool OpenItemAction::Execute(Event event)
|
bool OpenItemAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
bool foundOpenable = false;
|
bool foundOpenable = false;
|
||||||
|
|
||||||
// Check main inventory slots
|
Item* item = botAI->FindOpenableItem();
|
||||||
for (uint8 slot = EQUIPMENT_SLOT_START; slot < INVENTORY_SLOT_ITEM_END; ++slot)
|
if (item)
|
||||||
{
|
{
|
||||||
Item* item = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
|
uint8 bag = item->GetBagSlot(); // Retrieves the bag slot (0 for main inventory)
|
||||||
|
uint8 slot = item->GetSlot(); // Retrieves the actual slot inside the bag
|
||||||
|
|
||||||
if (item && CanOpenItem(item))
|
OpenItem(item, bag, slot);
|
||||||
{
|
foundOpenable = true;
|
||||||
OpenItem(item, INVENTORY_SLOT_BAG_0, slot);
|
|
||||||
foundOpenable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check items in the bags
|
|
||||||
for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag)
|
|
||||||
{
|
|
||||||
Bag* bagItem = bot->GetBagByPos(bag);
|
|
||||||
if (!bagItem)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (uint32 slot = 0; slot < bagItem->GetBagSize(); ++slot)
|
|
||||||
{
|
|
||||||
Item* item = bot->GetItemByPos(bag, slot);
|
|
||||||
|
|
||||||
if (item && CanOpenItem(item))
|
|
||||||
{
|
|
||||||
OpenItem(item, bag, slot);
|
|
||||||
foundOpenable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no openable items found
|
|
||||||
if (!foundOpenable)
|
|
||||||
{
|
|
||||||
botAI->TellError("No openable items in inventory.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundOpenable;
|
return foundOpenable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenItemAction::CanOpenItem(Item* item)
|
|
||||||
{
|
|
||||||
if (!item)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ItemTemplate const* itemTemplate = item->GetTemplate();
|
|
||||||
if (!itemTemplate)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check if the item has the openable flag
|
|
||||||
return itemTemplate->Flags & ITEM_FLAG_HAS_LOOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenItemAction::OpenItem(Item* item, uint8 bag, uint8 slot)
|
void OpenItemAction::OpenItem(Item* item, uint8 bag, uint8 slot)
|
||||||
{
|
{
|
||||||
WorldPacket packet(CMSG_OPEN_ITEM);
|
WorldPacket packet(CMSG_OPEN_ITEM);
|
||||||
|
|||||||
@ -21,9 +21,6 @@ public:
|
|||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Checks if the given item can be opened (i.e., has the openable flag)
|
|
||||||
bool CanOpenItem(Item* item);
|
|
||||||
|
|
||||||
// Performs the action of opening the item
|
// Performs the action of opening the item
|
||||||
void OpenItem(Item* item, uint8 bag, uint8 slot);
|
void OpenItem(Item* item, uint8 bag, uint8 slot);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -24,12 +24,17 @@ bool TradeStatusAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
PlayerbotAI* traderBotAI = GET_PLAYERBOT_AI(trader);
|
PlayerbotAI* traderBotAI = GET_PLAYERBOT_AI(trader);
|
||||||
if (trader != master && !traderBotAI)
|
|
||||||
|
// Allow the master and group members to trade
|
||||||
|
if (trader != master && !traderBotAI && (!bot->GetGroup() || !bot->GetGroup()->IsMember(trader->GetGUID())))
|
||||||
{
|
{
|
||||||
bot->Whisper("I'm kind of busy now", LANG_UNIVERSAL, trader);
|
bot->Whisper("I'm kind of busy now", LANG_UNIVERSAL, trader);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((trader != master || !botAI->GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, true, master)) &&
|
// Allow trades from group members or bots
|
||||||
|
if ((!bot->GetGroup() || !bot->GetGroup()->IsMember(trader->GetGUID())) &&
|
||||||
|
(trader != master || !botAI->GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, true, master)) &&
|
||||||
!traderBotAI)
|
!traderBotAI)
|
||||||
{
|
{
|
||||||
WorldPacket p;
|
WorldPacket p;
|
||||||
@ -109,9 +114,9 @@ bool TradeStatusAction::Execute(Event event)
|
|||||||
bot->SetFacingToObject(trader);
|
bot->SetFacingToObject(trader);
|
||||||
|
|
||||||
BeginTrade();
|
BeginTrade();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
84
src/strategy/actions/TradeStatusExtendedAction.cpp
Normal file
84
src/strategy/actions/TradeStatusExtendedAction.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "TradeStatusExtendedAction.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "WorldPacket.h"
|
||||||
|
#include "TradeData.h"
|
||||||
|
|
||||||
|
bool TradeStatusExtendedAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Player* trader = bot->GetTrader();
|
||||||
|
if (!trader)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TradeData* tradeData = trader->GetTradeData();
|
||||||
|
if (!tradeData)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WorldPacket p(event.getPacket());
|
||||||
|
p.rpos(0);
|
||||||
|
|
||||||
|
uint8 isTraderData;
|
||||||
|
uint32 unknown1, slotCount1, slotCount2, tradeGold, spellCast;
|
||||||
|
p >> isTraderData;
|
||||||
|
p >> unknown1;
|
||||||
|
p >> slotCount1;
|
||||||
|
p >> slotCount2;
|
||||||
|
p >> tradeGold;
|
||||||
|
p >> spellCast;
|
||||||
|
|
||||||
|
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
|
||||||
|
{
|
||||||
|
uint8 tradeSlot;
|
||||||
|
p >> tradeSlot;
|
||||||
|
|
||||||
|
if (tradeSlot >= TRADE_SLOT_COUNT)
|
||||||
|
break; // End of packet
|
||||||
|
|
||||||
|
uint32 itemId, displayId, count, wrapped, lockId;
|
||||||
|
uint64 giftCreator, creator;
|
||||||
|
uint32 permEnchant, gem1, gem2, gem3;
|
||||||
|
uint32 spellCharges, suffixFactor, randomProp, maxDurability, durability;
|
||||||
|
|
||||||
|
p >> itemId;
|
||||||
|
p >> displayId;
|
||||||
|
p >> count;
|
||||||
|
p >> wrapped;
|
||||||
|
p >> giftCreator;
|
||||||
|
p >> permEnchant;
|
||||||
|
p >> gem1;
|
||||||
|
p >> gem2;
|
||||||
|
p >> gem3;
|
||||||
|
p >> creator;
|
||||||
|
p >> spellCharges;
|
||||||
|
p >> suffixFactor;
|
||||||
|
p >> randomProp;
|
||||||
|
p >> lockId;
|
||||||
|
p >> maxDurability;
|
||||||
|
p >> durability;
|
||||||
|
|
||||||
|
// Check for locked items in "Do Not Trade" slot
|
||||||
|
if (tradeSlot == TRADE_SLOT_NONTRADED && lockId > 0)
|
||||||
|
{
|
||||||
|
// Get the actual item reference from TradeData
|
||||||
|
Item* lockbox = tradeData->GetItem(TRADE_SLOT_NONTRADED);
|
||||||
|
if (!lockbox)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bot->getClass() == CLASS_ROGUE && bot->HasSpell(1804) && lockbox->IsLocked()) // Pick Lock spell
|
||||||
|
{
|
||||||
|
// botAI->CastSpell(1804, bot, lockbox); // Attempt to cast Pick Lock on the lockbox
|
||||||
|
botAI->DoSpecificAction("unlock traded item");
|
||||||
|
botAI->SetNextCheckDelay(4000); // Delay before accepting trade
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
botAI->TellMaster("I can't unlock this item.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
17
src/strategy/actions/TradeStatusExtendedAction.h
Normal file
17
src/strategy/actions/TradeStatusExtendedAction.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _PLAYERBOT_TRADESTATUSEXTENDEDACTION_H
|
||||||
|
#define _PLAYERBOT_TRADESTATUSEXTENDEDACTION_H
|
||||||
|
|
||||||
|
#include "QueryItemUsageAction.h"
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
class PlayerbotAI;
|
||||||
|
|
||||||
|
class TradeStatusExtendedAction : public QueryItemUsageAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TradeStatusExtendedAction(PlayerbotAI* botAI) : QueryItemUsageAction(botAI, "trade status extended") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
38
src/strategy/actions/UnlockItemAction.cpp
Normal file
38
src/strategy/actions/UnlockItemAction.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "UnlockItemAction.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "ItemTemplate.h"
|
||||||
|
#include "WorldPacket.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "ObjectMgr.h"
|
||||||
|
#include "SpellInfo.h"
|
||||||
|
|
||||||
|
#define PICK_LOCK_SPELL_ID 1804
|
||||||
|
|
||||||
|
bool UnlockItemAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
bool foundLockedItem = false;
|
||||||
|
|
||||||
|
Item* item = botAI->FindLockedItem();
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
UnlockItem(item);
|
||||||
|
foundLockedItem = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundLockedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnlockItemAction::UnlockItem(Item* item)
|
||||||
|
{
|
||||||
|
// Use CastSpell to unlock the item
|
||||||
|
if (botAI->CastSpell(PICK_LOCK_SPELL_ID, bot, item))
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "Used Pick Lock on: " << item->GetTemplate()->Name1;
|
||||||
|
botAI->TellMaster(out.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
botAI->TellError("Failed to cast Pick Lock.");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/strategy/actions/UnlockItemAction.h
Normal file
19
src/strategy/actions/UnlockItemAction.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _PLAYERBOT_UNLOCKITEMACTION_H
|
||||||
|
#define _PLAYERBOT_UNLOCKITEMACTION_H
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
|
||||||
|
class PlayerbotAI;
|
||||||
|
|
||||||
|
class UnlockItemAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnlockItemAction(PlayerbotAI* botAI) : Action(botAI, "unlock item") { }
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UnlockItem(Item* item);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
98
src/strategy/actions/UnlockTradedItemAction.cpp
Normal file
98
src/strategy/actions/UnlockTradedItemAction.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include "UnlockTradedItemAction.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
#include "TradeData.h"
|
||||||
|
#include "SpellInfo.h"
|
||||||
|
|
||||||
|
#define PICK_LOCK_SPELL_ID 1804
|
||||||
|
|
||||||
|
bool UnlockTradedItemAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Player* trader = bot->GetTrader();
|
||||||
|
if (!trader)
|
||||||
|
return false; // No active trade session
|
||||||
|
|
||||||
|
TradeData* tradeData = trader->GetTradeData();
|
||||||
|
if (!tradeData)
|
||||||
|
return false; // No trade data available
|
||||||
|
|
||||||
|
Item* lockbox = tradeData->GetItem(TRADE_SLOT_NONTRADED);
|
||||||
|
if (!lockbox)
|
||||||
|
{
|
||||||
|
botAI->TellError("No item in the Do Not Trade slot.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CanUnlockItem(lockbox))
|
||||||
|
{
|
||||||
|
botAI->TellError("Cannot unlock this item.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockItem(lockbox);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnlockTradedItemAction::CanUnlockItem(Item* item)
|
||||||
|
{
|
||||||
|
if (!item)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ItemTemplate const* itemTemplate = item->GetTemplate();
|
||||||
|
if (!itemTemplate)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Ensure the bot is a rogue and has Lockpicking skill
|
||||||
|
if (bot->getClass() != CLASS_ROGUE || !botAI->HasSkill(SKILL_LOCKPICKING))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Ensure the item is actually locked
|
||||||
|
if (itemTemplate->LockID == 0 || !item->IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if the bot's Lockpicking skill is high enough
|
||||||
|
uint32 lockId = itemTemplate->LockID;
|
||||||
|
LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);
|
||||||
|
if (!lockInfo)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint32 botSkill = bot->GetSkillValue(SKILL_LOCKPICKING);
|
||||||
|
for (uint8 j = 0; j < 8; ++j)
|
||||||
|
{
|
||||||
|
if (lockInfo->Type[j] == LOCK_KEY_SKILL && SkillByLockType(LockType(lockInfo->Index[j])) == SKILL_LOCKPICKING)
|
||||||
|
{
|
||||||
|
uint32 requiredSkill = lockInfo->Skill[j];
|
||||||
|
if (botSkill >= requiredSkill)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "Lockpicking skill too low (" << botSkill << "/" << requiredSkill << ") to unlock: "
|
||||||
|
<< item->GetTemplate()->Name1;
|
||||||
|
botAI->TellMaster(out.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnlockTradedItemAction::UnlockItem(Item* item)
|
||||||
|
{
|
||||||
|
if (!bot->HasSpell(PICK_LOCK_SPELL_ID))
|
||||||
|
{
|
||||||
|
botAI->TellError("Cannot unlock, Pick Lock spell is missing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use CastSpell to unlock the item
|
||||||
|
if (botAI->CastSpell(PICK_LOCK_SPELL_ID, bot->GetTrader(), item)) // Unit target is trader
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "Picking Lock on traded item: " << item->GetTemplate()->Name1;
|
||||||
|
botAI->TellMaster(out.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
botAI->TellError("Failed to cast Pick Lock.");
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/strategy/actions/UnlockTradedItemAction.h
Normal file
20
src/strategy/actions/UnlockTradedItemAction.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _PLAYERBOT_UNLOCKTRADEDITEMACTION_H
|
||||||
|
#define _PLAYERBOT_UNLOCKTRADEDITEMACTION_H
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
|
||||||
|
class PlayerbotAI;
|
||||||
|
|
||||||
|
class UnlockTradedItemAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnlockTradedItemAction(PlayerbotAI* botAI) : Action(botAI, "unlock traded item") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CanUnlockItem(Item* item);
|
||||||
|
void UnlockItem(Item* item);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -37,6 +37,7 @@
|
|||||||
#include "TellCastFailedAction.h"
|
#include "TellCastFailedAction.h"
|
||||||
#include "TellMasterAction.h"
|
#include "TellMasterAction.h"
|
||||||
#include "TradeStatusAction.h"
|
#include "TradeStatusAction.h"
|
||||||
|
#include "TradeStatusExtendedAction.h"
|
||||||
#include "UseMeetingStoneAction.h"
|
#include "UseMeetingStoneAction.h"
|
||||||
#include "NamedObjectContext.h"
|
#include "NamedObjectContext.h"
|
||||||
|
|
||||||
@ -65,6 +66,7 @@ public:
|
|||||||
creators["check mount state"] = &WorldPacketActionContext::check_mount_state;
|
creators["check mount state"] = &WorldPacketActionContext::check_mount_state;
|
||||||
creators["remember taxi"] = &WorldPacketActionContext::remember_taxi;
|
creators["remember taxi"] = &WorldPacketActionContext::remember_taxi;
|
||||||
creators["accept trade"] = &WorldPacketActionContext::accept_trade;
|
creators["accept trade"] = &WorldPacketActionContext::accept_trade;
|
||||||
|
creators["trade status extended"] = &WorldPacketActionContext::trade_status_extended;
|
||||||
creators["store loot"] = &WorldPacketActionContext::store_loot;
|
creators["store loot"] = &WorldPacketActionContext::store_loot;
|
||||||
|
|
||||||
// quest
|
// quest
|
||||||
@ -118,6 +120,7 @@ private:
|
|||||||
static Action* party_command(PlayerbotAI* botAI) { return new PartyCommandAction(botAI); }
|
static Action* party_command(PlayerbotAI* botAI) { return new PartyCommandAction(botAI); }
|
||||||
static Action* store_loot(PlayerbotAI* botAI) { return new StoreLootAction(botAI); }
|
static Action* store_loot(PlayerbotAI* botAI) { return new StoreLootAction(botAI); }
|
||||||
static Action* accept_trade(PlayerbotAI* botAI) { return new TradeStatusAction(botAI); }
|
static Action* accept_trade(PlayerbotAI* botAI) { return new TradeStatusAction(botAI); }
|
||||||
|
static Action* trade_status_extended(PlayerbotAI* botAI) { return new TradeStatusExtendedAction(botAI); }
|
||||||
static Action* remember_taxi(PlayerbotAI* botAI) { return new RememberTaxiAction(botAI); }
|
static Action* remember_taxi(PlayerbotAI* botAI) { return new RememberTaxiAction(botAI); }
|
||||||
static Action* check_mount_state(PlayerbotAI* botAI) { return new CheckMountStateAction(botAI); }
|
static Action* check_mount_state(PlayerbotAI* botAI) { return new CheckMountStateAction(botAI); }
|
||||||
static Action* area_trigger(PlayerbotAI* botAI) { return new AreaTriggerAction(botAI); }
|
static Action* area_trigger(PlayerbotAI* botAI) { return new AreaTriggerAction(botAI); }
|
||||||
|
|||||||
@ -96,6 +96,10 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
|||||||
new TriggerNode("open items", NextAction::array(0, new NextAction("open items", relevance), nullptr)));
|
new TriggerNode("open items", NextAction::array(0, new NextAction("open items", relevance), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("qi", NextAction::array(0, new NextAction("query item usage", relevance), nullptr)));
|
new TriggerNode("qi", NextAction::array(0, new NextAction("query item usage", relevance), nullptr)));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("unlock items", NextAction::array(0, new NextAction("unlock items", relevance), nullptr)));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("unlock traded item", NextAction::array(0, new NextAction("unlock traded item", relevance), nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)
|
ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)
|
||||||
@ -172,4 +176,6 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas
|
|||||||
supported.push_back("calc");
|
supported.push_back("calc");
|
||||||
supported.push_back("open items");
|
supported.push_back("open items");
|
||||||
supported.push_back("qi");
|
supported.push_back("qi");
|
||||||
|
supported.push_back("unlock items");
|
||||||
|
supported.push_back("unlock traded item");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,12 +35,15 @@ void WorldPacketHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
|||||||
new NextAction("taxi", relevance), nullptr)));
|
new NextAction("taxi", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("taxi done", NextAction::array(0, new NextAction("taxi", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("taxi done", NextAction::array(0, new NextAction("taxi", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("trade status", NextAction::array(0, new NextAction("accept trade", relevance), new NextAction("equip upgrades", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("trade status", NextAction::array(0, new NextAction("accept trade", relevance), new NextAction("equip upgrades", relevance), nullptr)));
|
||||||
|
triggers.push_back(new TriggerNode("trade status extended", NextAction::array(0, new NextAction("trade status extended", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("area trigger", NextAction::array(0, new NextAction("reach area trigger", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("area trigger", NextAction::array(0, new NextAction("reach area trigger", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("within area trigger", NextAction::array(0, new NextAction("area trigger", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("within area trigger", NextAction::array(0, new NextAction("area trigger", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("loot response", NextAction::array(0, new NextAction("store loot", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("loot response", NextAction::array(0, new NextAction("store loot", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("item push result", NextAction::array(0, new NextAction("query item usage", relevance), new NextAction("equip upgrades", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("item push result", NextAction::array(0, new NextAction("unlock items", relevance),
|
||||||
|
new NextAction("open items", relevance),
|
||||||
|
new NextAction("query item usage", relevance),
|
||||||
|
new NextAction("equip upgrades", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("item push result", NextAction::array(0, new NextAction("quest item push result", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("item push result", NextAction::array(0, new NextAction("quest item push result", relevance), nullptr)));
|
||||||
|
|
||||||
triggers.push_back(new TriggerNode("ready check finished", NextAction::array(0, new NextAction("finish ready check", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("ready check finished", NextAction::array(0, new NextAction("finish ready check", relevance), nullptr)));
|
||||||
// triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("security check", relevance), new NextAction("check mail", relevance), nullptr)));
|
// triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("security check", relevance), new NextAction("check mail", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("guild invite", NextAction::array(0, new NextAction("guild accept", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("guild invite", NextAction::array(0, new NextAction("guild accept", relevance), nullptr)));
|
||||||
|
|||||||
@ -17,6 +17,8 @@ public:
|
|||||||
ChatTriggerContext()
|
ChatTriggerContext()
|
||||||
{
|
{
|
||||||
creators["open items"] = &ChatTriggerContext::open_items;
|
creators["open items"] = &ChatTriggerContext::open_items;
|
||||||
|
creators["unlock items"] = &ChatTriggerContext::unlock_items;
|
||||||
|
creators["unlock traded item"] = &ChatTriggerContext::unlock_traded_item;
|
||||||
creators["quests"] = &ChatTriggerContext::quests;
|
creators["quests"] = &ChatTriggerContext::quests;
|
||||||
creators["stats"] = &ChatTriggerContext::stats;
|
creators["stats"] = &ChatTriggerContext::stats;
|
||||||
creators["leave"] = &ChatTriggerContext::leave;
|
creators["leave"] = &ChatTriggerContext::leave;
|
||||||
@ -133,6 +135,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Trigger* open_items(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "open items"); }
|
static Trigger* open_items(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "open items"); }
|
||||||
|
static Trigger* unlock_items(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "unlock items"); }
|
||||||
|
static Trigger* unlock_traded_item(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "unlock traded item"); }
|
||||||
static Trigger* ra(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ra"); }
|
static Trigger* ra(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ra"); }
|
||||||
static Trigger* range(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "range"); }
|
static Trigger* range(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "range"); }
|
||||||
static Trigger* flag(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "flag"); }
|
static Trigger* flag(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "flag"); }
|
||||||
|
|||||||
@ -29,6 +29,7 @@ public:
|
|||||||
creators["check mount state"] = &WorldPacketTriggerContext::check_mount_state;
|
creators["check mount state"] = &WorldPacketTriggerContext::check_mount_state;
|
||||||
creators["activate taxi"] = &WorldPacketTriggerContext::taxi;
|
creators["activate taxi"] = &WorldPacketTriggerContext::taxi;
|
||||||
creators["trade status"] = &WorldPacketTriggerContext::trade_status;
|
creators["trade status"] = &WorldPacketTriggerContext::trade_status;
|
||||||
|
creators["trade status extended"] = &WorldPacketTriggerContext::trade_status_extended;
|
||||||
creators["loot response"] = &WorldPacketTriggerContext::loot_response;
|
creators["loot response"] = &WorldPacketTriggerContext::loot_response;
|
||||||
creators["out of react range"] = &WorldPacketTriggerContext::out_of_react_range;
|
creators["out of react range"] = &WorldPacketTriggerContext::out_of_react_range;
|
||||||
|
|
||||||
@ -108,6 +109,7 @@ private:
|
|||||||
static Trigger* out_of_react_range(PlayerbotAI* botAI) { return new OutOfReactRangeTrigger(botAI); }
|
static Trigger* out_of_react_range(PlayerbotAI* botAI) { return new OutOfReactRangeTrigger(botAI); }
|
||||||
static Trigger* loot_response(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot response"); }
|
static Trigger* loot_response(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot response"); }
|
||||||
static Trigger* trade_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status"); }
|
static Trigger* trade_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status"); }
|
||||||
|
static Trigger* trade_status_extended(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status extended"); }
|
||||||
static Trigger* cannot_equip(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cannot equip"); }
|
static Trigger* cannot_equip(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cannot equip"); }
|
||||||
static Trigger* check_mount_state(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "check mount state"); }
|
static Trigger* check_mount_state(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "check mount state"); }
|
||||||
static Trigger* area_trigger(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "area trigger"); }
|
static Trigger* area_trigger(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "area trigger"); }
|
||||||
|
|||||||
@ -71,6 +71,9 @@ Item* ItemForSpellValue::Calculate()
|
|||||||
if (!strcmpi(spellInfo->SpellName[0], "disenchant"))
|
if (!strcmpi(spellInfo->SpellName[0], "disenchant"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
if (!strcmpi(spellInfo->SpellName[0], "pick lock"))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
|
for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
|
||||||
{
|
{
|
||||||
itemForSpell = GetItemFitsToSpellRequirements(slot, spellInfo);
|
itemForSpell = GetItemFitsToSpellRequirements(slot, spellInfo);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user