Rogue bots can unlock items in their bags and in the trade window (#1055)

This commit is contained in:
avirar
2025-03-18 01:10:33 +11:00
committed by GitHub
parent c93bf38463
commit c4a4d3a9e6
18 changed files with 437 additions and 57 deletions

View File

@@ -178,6 +178,7 @@ PlayerbotAI::PlayerbotAI(Player* bot)
botOutgoingPacketHandlers.AddHandler(SMSG_RESURRECT_REQUEST, "resurrect request");
botOutgoingPacketHandlers.AddHandler(SMSG_INVENTORY_CHANGE_FAILURE, "cannot equip");
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_ITEM_PUSH_RESULT, "item push result");
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);
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();
targets.SetItemTarget(item);
@@ -3216,6 +3218,20 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
targets.SetGOTarget(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
{
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: {}",
// 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;
}
// 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);
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();
targets.SetItemTarget(item);
@@ -4904,6 +4972,52 @@ Item* PlayerbotAI::FindBandage() const
{ 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,
ELEMENTAL_SHARPENING_DISPLAYID, DENSE_SHARPENING_DISPLAYID,
SOLID_SHARPENING_DISPLAYID, HEAVY_SHARPENING_DISPLAYID,

View File

@@ -467,6 +467,8 @@ public:
Item* FindPoison() const;
Item* FindAmmo() const;
Item* FindBandage() const;
Item* FindOpenableItem() const;
Item* FindLockedItem() const;
Item* FindConsumable(uint32 displayId) const;
Item* FindStoneFor(Item* weapon) const;
Item* FindOilFor(Item* weapon) const;

View File

@@ -75,6 +75,8 @@
#include "WhoAction.h"
#include "WtsAction.h"
#include "OpenItemAction.h"
#include "UnlockItemAction.h"
#include "UnlockTradedItemAction.h"
class ChatActionContext : public NamedObjectContext<Action>
{
@@ -82,6 +84,8 @@ public:
ChatActionContext()
{
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["stats"] = &ChatActionContext::stats;
creators["quests"] = &ChatActionContext::quests;
@@ -184,6 +188,8 @@ public:
private:
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* flag(PlayerbotAI* botAI) { return new FlagAction(botAI); }
static Action* craft(PlayerbotAI* botAI) { return new SetCraftAction(botAI); }

View File

@@ -4,64 +4,23 @@
#include "WorldPacket.h"
#include "Player.h"
#include "ObjectMgr.h"
bool OpenItemAction::Execute(Event event)
{
bool foundOpenable = false;
// Check main inventory slots
for (uint8 slot = EQUIPMENT_SLOT_START; slot < INVENTORY_SLOT_ITEM_END; ++slot)
Item* item = botAI->FindOpenableItem();
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, 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.");
OpenItem(item, bag, slot);
foundOpenable = true;
}
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)
{
WorldPacket packet(CMSG_OPEN_ITEM);

View File

@@ -21,9 +21,6 @@ public:
bool Execute(Event event) override;
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
void OpenItem(Item* item, uint8 bag, uint8 slot);
};

View File

@@ -24,12 +24,17 @@ bool TradeStatusAction::Execute(Event event)
return false;
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);
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)
{
WorldPacket p;
@@ -109,9 +114,9 @@ bool TradeStatusAction::Execute(Event event)
bot->SetFacingToObject(trader);
BeginTrade();
return true;
}
return false;
}

View 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;
}

View 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

View 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.");
}
}

View 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

View 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.");
}
}

View 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

View File

@@ -37,6 +37,7 @@
#include "TellCastFailedAction.h"
#include "TellMasterAction.h"
#include "TradeStatusAction.h"
#include "TradeStatusExtendedAction.h"
#include "UseMeetingStoneAction.h"
#include "NamedObjectContext.h"
@@ -65,6 +66,7 @@ public:
creators["check mount state"] = &WorldPacketActionContext::check_mount_state;
creators["remember taxi"] = &WorldPacketActionContext::remember_taxi;
creators["accept trade"] = &WorldPacketActionContext::accept_trade;
creators["trade status extended"] = &WorldPacketActionContext::trade_status_extended;
creators["store loot"] = &WorldPacketActionContext::store_loot;
// quest
@@ -118,6 +120,7 @@ private:
static Action* party_command(PlayerbotAI* botAI) { return new PartyCommandAction(botAI); }
static Action* store_loot(PlayerbotAI* botAI) { return new StoreLootAction(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* check_mount_state(PlayerbotAI* botAI) { return new CheckMountStateAction(botAI); }
static Action* area_trigger(PlayerbotAI* botAI) { return new AreaTriggerAction(botAI); }

View File

@@ -96,6 +96,10 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
new TriggerNode("open items", NextAction::array(0, new NextAction("open items", relevance), nullptr)));
triggers.push_back(
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)
@@ -172,4 +176,6 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas
supported.push_back("calc");
supported.push_back("open items");
supported.push_back("qi");
supported.push_back("unlock items");
supported.push_back("unlock traded item");
}

View File

@@ -35,12 +35,15 @@ void WorldPacketHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
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 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("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("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("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("guild invite", NextAction::array(0, new NextAction("guild accept", relevance), nullptr)));

View File

@@ -17,6 +17,8 @@ public:
ChatTriggerContext()
{
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["stats"] = &ChatTriggerContext::stats;
creators["leave"] = &ChatTriggerContext::leave;
@@ -133,6 +135,8 @@ public:
private:
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* range(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "range"); }
static Trigger* flag(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "flag"); }

View File

@@ -29,6 +29,7 @@ public:
creators["check mount state"] = &WorldPacketTriggerContext::check_mount_state;
creators["activate taxi"] = &WorldPacketTriggerContext::taxi;
creators["trade status"] = &WorldPacketTriggerContext::trade_status;
creators["trade status extended"] = &WorldPacketTriggerContext::trade_status_extended;
creators["loot response"] = &WorldPacketTriggerContext::loot_response;
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* 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_extended(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status extended"); }
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* area_trigger(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "area trigger"); }

View File

@@ -71,6 +71,9 @@ Item* ItemForSpellValue::Calculate()
if (!strcmpi(spellInfo->SpellName[0], "disenchant"))
return nullptr;
if (!strcmpi(spellInfo->SpellName[0], "pick lock"))
return nullptr;
for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
{
itemForSpell = GetItemFitsToSpellRequirements(slot, spellInfo);