mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 13:41:31 +00:00
# Notes - Separate all bot commands into individual files like regular commands. # Images
339 lines
7.9 KiB
C++
339 lines
7.9 KiB
C++
#include "../bot_command.h"
|
|
|
|
void bot_command_inventory(Client *c, const Seperator *sep)
|
|
{
|
|
|
|
std::list<const char*> subcommand_list;
|
|
subcommand_list.push_back("inventorygive");
|
|
subcommand_list.push_back("inventorylist");
|
|
subcommand_list.push_back("inventoryremove");
|
|
subcommand_list.push_back("inventorywindow");
|
|
|
|
if (helper_command_alias_fail(c, "bot_command_inventory", sep->arg[0], "inventory"))
|
|
return;
|
|
|
|
helper_send_available_subcommands(c, "bot inventory", subcommand_list);
|
|
}
|
|
|
|
void bot_command_inventory_give(Client* c, const Seperator* sep)
|
|
{
|
|
if (helper_command_alias_fail(c, "bot_command_inventory_give", sep->arg[0], "inventorygive")) {
|
|
return;
|
|
}
|
|
|
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Usage: {} ([actionable: target | byname] ([actionable_name]))",
|
|
sep->arg[0]
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
|
|
int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
|
|
|
|
std::list<Bot*> sbl;
|
|
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) {
|
|
return;
|
|
}
|
|
|
|
auto my_bot = sbl.front();
|
|
if (!my_bot) {
|
|
c->Message(Chat::White, "ActionableBots returned 'nullptr'");
|
|
return;
|
|
}
|
|
|
|
my_bot->FinishTrade(c, Bot::BotTradeClientNoDropNoTrade);
|
|
}
|
|
|
|
void bot_command_inventory_list(Client* c, const Seperator* sep)
|
|
{
|
|
if (helper_command_alias_fail(c, "bot_command_inventory_list", sep->arg[0], "inventorylist")) {
|
|
return;
|
|
}
|
|
|
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Usage: {} ([actionable: target | byname] ([actionable_name]))",
|
|
sep->arg[0]
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
|
|
int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
|
|
|
|
std::list<Bot*> sbl;
|
|
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) {
|
|
return;
|
|
}
|
|
|
|
auto my_bot = sbl.front();
|
|
if (!my_bot) {
|
|
c->Message(Chat::White, "ActionableBots returned 'nullptr'");
|
|
return;
|
|
}
|
|
|
|
const EQ::ItemInstance* inst = nullptr;
|
|
const EQ::ItemData * item = nullptr;
|
|
bool is_2h_weapon = false;
|
|
|
|
EQ::SayLinkEngine linker;
|
|
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
|
|
|
uint32 inventory_count = 0;
|
|
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
|
if (slot_id == EQ::invslot::slotSecondary && is_2h_weapon) {
|
|
continue;
|
|
}
|
|
|
|
inst = my_bot->CastToBot()->GetBotItem(slot_id);
|
|
if (!inst || !inst->GetItem()) {
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Slot {} ({}) | Empty",
|
|
slot_id,
|
|
EQ::invslot::GetInvPossessionsSlotName(slot_id)
|
|
).c_str()
|
|
);
|
|
continue;
|
|
}
|
|
|
|
item = inst->GetItem();
|
|
if (slot_id == EQ::invslot::slotPrimary && item->IsType2HWeapon()) {
|
|
is_2h_weapon = true;
|
|
}
|
|
|
|
linker.SetItemInst(inst);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Slot {} ({}) | {} | {}",
|
|
slot_id,
|
|
EQ::invslot::GetInvPossessionsSlotName(slot_id),
|
|
linker.GenerateLink(),
|
|
Saylink::Silent(
|
|
fmt::format("^inventoryremove {}", slot_id),
|
|
"Remove"
|
|
)
|
|
).c_str()
|
|
);
|
|
|
|
++inventory_count;
|
|
}
|
|
|
|
uint32 database_count = 0;
|
|
database.botdb.QueryInventoryCount(my_bot->GetBotID(), database_count);
|
|
|
|
if (inventory_count != database_count) {
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Inventory-database item count mismatch, inventory has {} item{} and the database has {} item{}.",
|
|
inventory_count,
|
|
inventory_count != 1 ? "s" : "",
|
|
database_count,
|
|
database_count != 1 ? "s" : ""
|
|
).c_str()
|
|
);
|
|
}
|
|
}
|
|
|
|
void bot_command_inventory_remove(Client* c, const Seperator* sep)
|
|
{
|
|
if (helper_command_alias_fail(c, "bot_command_inventory_remove", sep->arg[0], "inventoryremove")) {
|
|
return;
|
|
}
|
|
|
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Usage: {} [Slot ID: 0-22] ([actionable: target | byname] ([actionable_name]))",
|
|
sep->arg[0]
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
|
|
int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
|
|
|
|
if (c->GetTradeskillObject() || (c->trade->state == Trading)) {
|
|
c->MessageString(Chat::Tell, MERCHANT_BUSY);
|
|
return;
|
|
}
|
|
|
|
std::list<Bot*> sbl;
|
|
if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None) {
|
|
return;
|
|
}
|
|
|
|
auto my_bot = sbl.front();
|
|
if (!my_bot) {
|
|
c->Message(Chat::White, "ActionableBots returned 'nullptr'");
|
|
return;
|
|
}
|
|
|
|
if (!sep->IsNumber(1)) {
|
|
c->Message(Chat::White, "Slot ID must be a number.");
|
|
return;
|
|
}
|
|
|
|
auto slot_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[1]));
|
|
if (slot_id > EQ::invslot::EQUIPMENT_END || slot_id < EQ::invslot::EQUIPMENT_BEGIN) {
|
|
c->Message(Chat::White, "Valid slots are 0 to 22.");
|
|
return;
|
|
}
|
|
|
|
auto* inst = my_bot->GetBotItem(slot_id);
|
|
if (!inst) {
|
|
std::string slot_message = "is";
|
|
switch (slot_id) {
|
|
case EQ::invslot::slotShoulders:
|
|
case EQ::invslot::slotArms:
|
|
case EQ::invslot::slotHands:
|
|
case EQ::invslot::slotLegs:
|
|
case EQ::invslot::slotFeet:
|
|
slot_message = "are";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
my_bot->OwnerMessage(
|
|
fmt::format(
|
|
"My {} (Slot {}) {} already unequipped.",
|
|
EQ::invslot::GetInvPossessionsSlotName(slot_id),
|
|
slot_id,
|
|
slot_message
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
const auto* itm = inst->GetItem();
|
|
|
|
if (inst && itm && c->CheckLoreConflict(itm)) {
|
|
c->MessageString(Chat::White, PICK_LORE);
|
|
return;
|
|
}
|
|
|
|
for (int m = EQ::invaug::SOCKET_BEGIN; m <= EQ::invaug::SOCKET_END; ++m) {
|
|
EQ::ItemInstance* augment = inst->GetAugment(m);
|
|
if (!augment) {
|
|
continue;
|
|
}
|
|
|
|
if (!c->CheckLoreConflict(augment->GetItem())) {
|
|
continue;
|
|
}
|
|
|
|
c->MessageString(Chat::White, PICK_LORE);
|
|
return;
|
|
}
|
|
|
|
if (itm) {
|
|
EQ::SayLinkEngine linker;
|
|
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
|
linker.SetItemInst(inst);
|
|
|
|
c->PushItemOnCursor(*inst, true);
|
|
if (
|
|
slot_id == EQ::invslot::slotRange ||
|
|
slot_id == EQ::invslot::slotAmmo
|
|
) {
|
|
my_bot->SetBotArcherySetting(false, true);
|
|
}
|
|
|
|
my_bot->RemoveBotItemBySlot(slot_id);
|
|
my_bot->BotRemoveEquipItem(slot_id);
|
|
my_bot->CalcBotStats(c->GetBotOption(Client::booStatsUpdate));
|
|
|
|
my_bot->OwnerMessage(
|
|
fmt::format(
|
|
"I have unequipped {} from my {} (Slot {}).",
|
|
linker.GenerateLink(),
|
|
EQ::invslot::GetInvPossessionsSlotName(slot_id),
|
|
slot_id
|
|
)
|
|
);
|
|
|
|
if (parse->BotHasQuestSub(EVENT_UNEQUIP_ITEM_BOT)) {
|
|
const auto& export_string = fmt::format(
|
|
"{} {}",
|
|
inst->IsStackable() ? inst->GetCharges() : 1,
|
|
slot_id
|
|
);
|
|
|
|
std::vector<std::any> args = { inst };
|
|
|
|
parse->EventBot(EVENT_UNEQUIP_ITEM_BOT, my_bot, nullptr, export_string, inst->GetID(), &args);
|
|
}
|
|
}
|
|
}
|
|
|
|
void bot_command_inventory_window(Client* c, const Seperator* sep)
|
|
{
|
|
if (helper_command_alias_fail(c, "bot_command_inventory_window", sep->arg[0], "inventorywindow")) {
|
|
return;
|
|
}
|
|
|
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"Usage: {} [actionable: target]",
|
|
sep->arg[0]
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
|
|
int ab_mask = ActionableBots::ABM_Target;
|
|
|
|
std::list<Bot*> sbl;
|
|
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) {
|
|
return;
|
|
}
|
|
|
|
auto my_bot = sbl.front();
|
|
if (!my_bot) {
|
|
c->Message(Chat::White, "ActionableBots returned 'nullptr'");
|
|
return;
|
|
}
|
|
|
|
std::string window_title = fmt::format(
|
|
"{}'s Inventory",
|
|
my_bot->GetCleanName()
|
|
);
|
|
|
|
std::string window_text = "<table>";
|
|
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
|
const EQ::ItemData * item = nullptr;
|
|
const EQ::ItemInstance* inst = my_bot->CastToBot()->GetBotItem(slot_id);
|
|
if (inst) {
|
|
item = inst->GetItem();
|
|
}
|
|
|
|
window_text.append(
|
|
fmt::format(
|
|
"<tr><td>{}</td><td>{}{}</c></td></tr>",
|
|
EQ::invslot::GetInvPossessionsSlotName(slot_id),
|
|
item ? "<c \"#00FF00\">" : "<c \"#FFFF00\">",
|
|
item ? item->Name : "Empty"
|
|
)
|
|
);
|
|
}
|
|
window_text.append("</table>");
|
|
|
|
c->SendPopupToClient(
|
|
window_title.c_str(),
|
|
window_text.c_str()
|
|
);
|
|
}
|