mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-29 05:11:55 +01:00
Core/Commands: Refactor .additem to use typed args
(cherry picked from commit 1f60e76b7f)
This commit is contained in:
@@ -1153,74 +1153,57 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleAddItemCommand(ChatHandler* handler, char const* args)
|
||||
static bool HandleAddItemCommandHelper(ChatHandler* handler, Player* player, Player* playerTarget,
|
||||
Variant<Hyperlink<item>, uint32, std::string_view> const& itemArg, Optional<int32> countArg,
|
||||
Optional<std::string_view> const& bonusListIdString, Optional<uint8> itemContextArg)
|
||||
{
|
||||
if (!*args)
|
||||
return false;
|
||||
|
||||
uint32 itemId = 0;
|
||||
|
||||
if (args[0] == '[') // [name] manual form
|
||||
if (Hyperlink<::item> const* itemLinkData = std::get_if<Hyperlink<::item>>(&itemArg))
|
||||
itemId = (*itemLinkData)->Item->GetId();
|
||||
else if (uint32 const* itemIdPtr = std::get_if<uint32>(&itemArg))
|
||||
itemId = *itemIdPtr;
|
||||
else if (std::string_view const* itemNameText = std::get_if<std::string_view>(&itemArg))
|
||||
{
|
||||
char const* itemNameStr = strtok((char*)args, "]");
|
||||
std::string itemName(*itemNameText);
|
||||
if (itemName.starts_with('['))
|
||||
itemName.erase(0, 1);
|
||||
if (itemName.ends_with(']'))
|
||||
itemName.pop_back();
|
||||
|
||||
if (itemNameStr && itemNameStr[0])
|
||||
auto itr = std::ranges::find_if(sItemSparseStore, [&itemName](ItemSparseEntry const* sparse)
|
||||
{
|
||||
std::string itemName = itemNameStr+1;
|
||||
auto itr = std::find_if(sItemSparseStore.begin(), sItemSparseStore.end(), [&itemName](ItemSparseEntry const* sparse)
|
||||
{
|
||||
for (LocaleConstant i = LOCALE_enUS; i < TOTAL_LOCALES; i = LocaleConstant(i + 1))
|
||||
if (itemName == sparse->Display[i])
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
for (LocaleConstant i = LOCALE_enUS; i < TOTAL_LOCALES; i = LocaleConstant(i + 1))
|
||||
if (itemName == sparse->Display[i])
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (itr == sItemSparseStore.end())
|
||||
{
|
||||
handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, itemNameStr+1);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
itemId = itr->ID;
|
||||
if (itr == sItemSparseStore.end())
|
||||
{
|
||||
handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, itemName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r
|
||||
{
|
||||
char const* id = handler->extractKeyFromLink((char*)args, "Hitem");
|
||||
if (!id)
|
||||
return false;
|
||||
|
||||
itemId = Trinity::StringTo<uint32>(id).value_or(0);
|
||||
itemId = itr->ID;
|
||||
}
|
||||
|
||||
char const* ccount = strtok(nullptr, " ");
|
||||
|
||||
int32 count = 1;
|
||||
|
||||
if (ccount)
|
||||
count = strtol(ccount, nullptr, 10);
|
||||
|
||||
int32 count = countArg.value_or(1);
|
||||
if (count == 0)
|
||||
count = 1;
|
||||
|
||||
std::vector<int32> bonusListIDs;
|
||||
char const* bonuses = strtok(nullptr, " ");
|
||||
|
||||
char const* context = strtok(nullptr, " ");
|
||||
|
||||
// semicolon separated bonuslist ids (parse them after all arguments are extracted by strtok!)
|
||||
if (bonuses)
|
||||
for (std::string_view token : Trinity::Tokenize(bonuses, ';', false))
|
||||
if (bonusListIdString)
|
||||
for (std::string_view token : Trinity::Tokenize(*bonusListIdString, ';', false))
|
||||
if (Optional<int32> bonusListId = Trinity::StringTo<int32>(token); bonusListId && *bonusListId)
|
||||
bonusListIDs.push_back(*bonusListId);
|
||||
|
||||
ItemContext itemContext = ItemContext::NONE;
|
||||
if (context)
|
||||
if (itemContextArg)
|
||||
{
|
||||
itemContext = ItemContext(Trinity::StringTo<uint8>(context).value_or(0));
|
||||
itemContext = ItemContext(*itemContextArg);
|
||||
if (itemContext < ItemContext::Max)
|
||||
{
|
||||
std::vector<int32> contextBonuses = ItemBonusMgr::GetBonusListsForItem(itemId, itemContext);
|
||||
@@ -1228,11 +1211,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
Player* playerTarget = handler->getSelectedPlayer();
|
||||
if (!playerTarget)
|
||||
playerTarget = player;
|
||||
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!itemTemplate)
|
||||
{
|
||||
@@ -1307,164 +1285,29 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleAddItemToCommand(ChatHandler* handler, char const* args)
|
||||
static bool HandleAddItemCommand(ChatHandler* handler,
|
||||
Variant<Hyperlink<::item>, uint32, std::string_view> const& item, Optional<int32> countArg,
|
||||
Optional<std::string_view> const& bonusListIdString, Optional<uint8> itemContextArg)
|
||||
{
|
||||
if (!*args)
|
||||
return false;
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
Player* playerTarget = nullptr;
|
||||
if (!handler->extractPlayerTarget((char*)args, &playerTarget))
|
||||
Player* playerTarget = handler->getSelectedPlayerOrSelf();
|
||||
|
||||
return HandleAddItemCommandHelper(handler, player, playerTarget, item, countArg, bonusListIdString, itemContextArg);
|
||||
}
|
||||
|
||||
static bool HandleAddItemToCommand(ChatHandler* handler, PlayerIdentifier const& target,
|
||||
Variant<Hyperlink<::item>, uint32, std::string_view> const& item, Optional<int32> countArg,
|
||||
Optional<std::string_view> const& bonusListIdString, Optional<uint8> itemContextArg)
|
||||
{
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
if (!target.IsConnected())
|
||||
{
|
||||
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
char* tailArgs = strtok(nullptr, "");
|
||||
if (!tailArgs)
|
||||
return false;
|
||||
|
||||
uint32 itemId = 0;
|
||||
|
||||
if (tailArgs[0] == '[') // [name] manual form
|
||||
{
|
||||
char const* itemNameStr = strtok(tailArgs, "]");
|
||||
|
||||
if (itemNameStr && itemNameStr[0])
|
||||
{
|
||||
std::string itemName = itemNameStr+1;
|
||||
auto itr = std::find_if(sItemSparseStore.begin(), sItemSparseStore.end(), [&itemName](ItemSparseEntry const* sparse)
|
||||
{
|
||||
for (LocaleConstant i = LOCALE_enUS; i < TOTAL_LOCALES; i = LocaleConstant(i + 1))
|
||||
if (itemName == sparse->Display[i])
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (itr == sItemSparseStore.end())
|
||||
{
|
||||
handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, itemNameStr+1);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
itemId = itr->ID;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r
|
||||
{
|
||||
char const* id = handler->extractKeyFromLink(tailArgs, "Hitem");
|
||||
if (!id)
|
||||
return false;
|
||||
|
||||
itemId = Trinity::StringTo<uint32>(id).value_or(0);
|
||||
}
|
||||
|
||||
char const* ccount = strtok(nullptr, " ");
|
||||
|
||||
int32 count = 1;
|
||||
|
||||
if (ccount)
|
||||
count = strtol(ccount, nullptr, 10);
|
||||
|
||||
if (count == 0)
|
||||
count = 1;
|
||||
|
||||
std::vector<int32> bonusListIDs;
|
||||
char const* bonuses = strtok(nullptr, " ");
|
||||
|
||||
char const* context = strtok(nullptr, " ");
|
||||
|
||||
// semicolon separated bonuslist ids (parse them after all arguments are extracted by strtok!)
|
||||
if (bonuses)
|
||||
for (std::string_view token : Trinity::Tokenize(bonuses, ';', false))
|
||||
if (Optional<int32> bonusListId = Trinity::StringTo<int32>(token); bonusListId && *bonusListId)
|
||||
bonusListIDs.push_back(*bonusListId);
|
||||
|
||||
ItemContext itemContext = ItemContext::NONE;
|
||||
if (context)
|
||||
{
|
||||
itemContext = ItemContext(Trinity::StringTo<uint8>(context).value_or(0));
|
||||
if (itemContext < ItemContext::Max)
|
||||
{
|
||||
std::vector<int32> contextBonuses = ItemBonusMgr::GetBonusListsForItem(itemId, itemContext);
|
||||
bonusListIDs.insert(bonusListIDs.begin(), contextBonuses.begin(), contextBonuses.end());
|
||||
}
|
||||
}
|
||||
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!itemTemplate)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Subtract
|
||||
if (count < 0)
|
||||
{
|
||||
uint32 destroyedItemCount = playerTarget->DestroyItemCount(itemId, -count, true, false);
|
||||
|
||||
if (destroyedItemCount > 0)
|
||||
{
|
||||
// output the amount of items successfully destroyed
|
||||
handler->PSendSysMessage(LANG_REMOVEITEM, itemId, destroyedItemCount, handler->GetNameLink(playerTarget).c_str());
|
||||
|
||||
// check to see if we were unable to destroy all of the amount requested.
|
||||
uint32 unableToDestroyItemCount = -count - destroyedItemCount;
|
||||
if (unableToDestroyItemCount > 0)
|
||||
{
|
||||
// output message for the amount of items we couldn't destroy
|
||||
handler->PSendSysMessage(LANG_REMOVEITEM_FAILURE, itemId, unableToDestroyItemCount, handler->GetNameLink(playerTarget).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to destroy items of the amount requested
|
||||
handler->PSendSysMessage(LANG_REMOVEITEM_FAILURE, itemId, -count, handler->GetNameLink(playerTarget).c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Adding items
|
||||
uint32 noSpaceForCount = 0;
|
||||
|
||||
// check space and find places
|
||||
ItemPosCountVec dest;
|
||||
InventoryResult msg = playerTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount);
|
||||
if (msg != EQUIP_ERR_OK) // convert to possible store amount
|
||||
count -= noSpaceForCount;
|
||||
|
||||
if (count == 0 || dest.empty()) // can't add any
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
Item* item = playerTarget->StoreNewItem(dest, itemId, true, GenerateItemRandomBonusListId(itemId), GuidSet(), itemContext,
|
||||
bonusListIDs.empty() ? nullptr : &bonusListIDs);
|
||||
|
||||
// remove binding (let GM give it to another player later)
|
||||
if (player == playerTarget)
|
||||
for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr)
|
||||
if (Item* item1 = player->GetItemByPos(itr->pos))
|
||||
item1->SetBinding(false);
|
||||
|
||||
if (count > 0 && item)
|
||||
{
|
||||
player->SendNewItem(item, count, false, true);
|
||||
if (player != playerTarget)
|
||||
playerTarget->SendNewItem(item, count, true, false);
|
||||
}
|
||||
|
||||
if (noSpaceForCount > 0)
|
||||
handler->PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount);
|
||||
|
||||
return true;
|
||||
return HandleAddItemCommandHelper(handler, player, target.GetConnectedPlayer(), item, countArg, bonusListIdString, itemContextArg);
|
||||
}
|
||||
|
||||
static bool HandleAddItemSetCommand(ChatHandler* handler, Variant<Hyperlink<itemset>, uint32> itemSetId, Optional<std::string_view> bonuses, Optional<uint8> context)
|
||||
|
||||
Reference in New Issue
Block a user