Core/Loot: Implemented currency loot

This commit is contained in:
Shauren
2024-08-26 15:02:22 +02:00
parent 6b4270850f
commit 3e28ee080a
17 changed files with 576 additions and 237 deletions

View File

@@ -39,6 +39,8 @@ EndScriptData */
#include "Util.h"
#include "WorldSession.h"
using namespace Trinity::ChatCommands;
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
@@ -923,12 +925,9 @@ public:
return true;
}
static bool HandleModifyCurrencyCommand(ChatHandler* handler, const char* args)
static bool HandleModifyCurrencyCommand(ChatHandler* handler, CurrencyTypesEntry const* currency, int32 amount)
{
if (!*args)
return false;
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->PSendSysMessage(LANG_PLAYER_NOT_FOUND);
@@ -936,16 +935,7 @@ public:
return false;
}
uint32 currencyId = atoi(strtok((char*)args, " "));
const CurrencyTypesEntry* currencyType = sCurrencyTypesStore.LookupEntry(currencyId);
if (!currencyType)
return false;
uint32 amount = atoi(strtok(nullptr, " "));
if (!amount)
return false;
target->ModifyCurrency(currencyId, amount, CurrencyGainSource::Cheat, CurrencyDestroyReason::Cheat);
target->ModifyCurrency(currency->ID, amount, CurrencyGainSource::Cheat, CurrencyDestroyReason::Cheat);
return true;
}

View File

@@ -23,12 +23,13 @@ Category: commandscripts
EndScriptData */
#include "ScriptMgr.h"
#include "CharacterCache.h"
#include "Chat.h"
#include "ChatCommand.h"
#include "CreatureAI.h"
#include "CreatureGroups.h"
#include "DatabaseEnv.h"
#include "DB2Stores.h"
#include "DatabaseEnv.h"
#include "FollowMovementGenerator.h"
#include "GameTime.h"
#include "Language.h"
@@ -1165,7 +1166,7 @@ public:
return true;
}
static void _ShowLootEntry(ChatHandler* handler, uint32 itemId, uint8 itemCount, bool alternateString = false)
static void _ShowLootEntry(ChatHandler* handler, uint32 itemId, uint32 itemCount, bool alternateString = false)
{
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
char const* name = nullptr;
@@ -1177,6 +1178,18 @@ public:
itemCount, ItemQualityColors[itemTemplate ? static_cast<ItemQualities>(itemTemplate->GetQuality()) : ITEM_QUALITY_POOR], itemId, name, itemId);
}
static void _ShowLootCurrencyEntry(ChatHandler* handler, uint32 currencyId, uint32 count, bool alternateString = false)
{
CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(currencyId);
char const* name = nullptr;
if (currency)
name = currency->Name[handler->GetSessionDbcLocale()];
if (!name)
name = "Unknown currency";
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_CURRENCY, alternateString ? 6 : 3 /*number of bytes from following string*/, "\u2500\u2500",
count, ItemQualityColors[currency ? static_cast<ItemQualities>(currency->Quality) : ITEM_QUALITY_POOR], currencyId, count, name, currencyId);
}
static void _IterateNotNormalLootMap(ChatHandler* handler, NotNormalLootItemMap const& map, std::vector<LootItem> const& items)
{
for (NotNormalLootItemMap::value_type const& pair : map)
@@ -1189,11 +1202,72 @@ public:
for (auto it = pair.second->cbegin(); it != pair.second->cend(); ++it)
{
LootItem const& item = items[it->LootListId];
if (!(it->is_looted) && !item.is_looted)
_ShowLootEntry(handler, item.itemid, item.count, true);
if (!it->is_looted && !item.is_looted)
{
switch (item.type)
{
case LootItemType::Item:
_ShowLootEntry(handler, item.itemid, item.count, true);
break;
case LootItemType::Currency:
_ShowLootCurrencyEntry(handler, item.itemid, item.count, true);
break;
}
}
}
}
}
static void _ShowLootContents(ChatHandler* handler, bool all, Loot const* loot)
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_MONEY, loot->gold / GOLD, (loot->gold % GOLD) / SILVER, loot->gold % SILVER);
if (!all)
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL, "Standard items", loot->items.size());
for (LootItem const& item : loot->items)
{
if (!item.is_looted)
{
switch (item.type)
{
case LootItemType::Item:
_ShowLootEntry(handler, item.itemid, item.count);
break;
case LootItemType::Currency:
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
break;
}
}
}
}
else
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL, "Standard items", loot->items.size());
for (LootItem const& item : loot->items)
{
if (!item.is_looted && !item.freeforall && item.conditions.IsEmpty())
{
switch (item.type)
{
case LootItemType::Item:
_ShowLootEntry(handler, item.itemid, item.count);
break;
case LootItemType::Currency:
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
break;
}
}
}
if (!loot->GetPlayerFFAItems().empty())
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL_2, "FFA items per allowed player");
_IterateNotNormalLootMap(handler, loot->GetPlayerFFAItems(), loot->items);
}
}
}
static bool HandleNpcShowLootCommand(ChatHandler* handler, Optional<EXACT_SEQUENCE("all")> all)
{
Creature* creatureTarget = handler->getSelectedCreature();
@@ -1204,8 +1278,16 @@ public:
return false;
}
if (!creatureTarget->isDead())
{
handler->PSendSysMessage(LANG_COMMAND_NOT_DEAD_OR_NO_LOOT, creatureTarget->GetName().c_str());
handler->SetSentErrorMessage(true);
return false;
}
Loot const* loot = creatureTarget->m_loot.get();
if (!creatureTarget->isDead() || !loot || loot->isLooted())
if ((!loot || loot->isLooted())
&& !std::ranges::count_if(creatureTarget->m_personalLoot, std::not_fn(&Loot::isLooted), &std::unordered_map<ObjectGuid, std::unique_ptr<Loot>>::value_type::second))
{
handler->PSendSysMessage(LANG_COMMAND_NOT_DEAD_OR_NO_LOOT, creatureTarget->GetName().c_str());
handler->SetSentErrorMessage(true);
@@ -1213,26 +1295,18 @@ public:
}
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_HEADER, creatureTarget->GetName().c_str(), creatureTarget->GetEntry());
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_MONEY, loot->gold / GOLD, (loot->gold % GOLD) / SILVER, loot->gold % SILVER);
if (!all)
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL, "Standard items", loot->items.size());
for (LootItem const& item : loot->items)
if (!item.is_looted)
_ShowLootEntry(handler, item.itemid, item.count);
}
if (loot)
_ShowLootContents(handler, all.has_value(), loot);
else
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL, "Standard items", loot->items.size());
for (LootItem const& item : loot->items)
if (!item.is_looted && !item.freeforall && item.conditions.IsEmpty())
_ShowLootEntry(handler, item.itemid, item.count);
using namespace std::string_view_literals;
if (!loot->GetPlayerFFAItems().empty())
for (auto const& [lootOwner, personalLoot] : creatureTarget->m_personalLoot)
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL_2, "FFA items per allowed player");
_IterateNotNormalLootMap(handler, loot->GetPlayerFFAItems(), loot->items);
CharacterCacheEntry const* character = sCharacterCache->GetCharacterCacheByGuid(lootOwner);
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL_2, Trinity::StringFormat("Personal loot for {}", character ? character->Name : ""sv));
_ShowLootContents(handler, all.has_value(), personalLoot.get());
}
}

View File

@@ -1549,8 +1549,20 @@ struct npc_murloc_spearhunter_watershaper : public ScriptedAI
for (LootItem const& lootItem : loot->items)
{
if (lootItem.itemid == ITEM_STITCHED_CLOTH_SHOES || lootItem.itemid == ITEM_STITCHED_LEATHER_BOOTS || lootItem.itemid == ITEM_LINKED_MAIL_BOOTS || lootItem.itemid == ITEM_DENTED_PLATE_BOOTS)
player->SetRewardedQuest(QUEST_MURLOC_HIDEAWAY_BOOTS_DROPPED);
if (lootItem.type != LootItemType::Item)
continue;
switch (lootItem.itemid)
{
case ITEM_STITCHED_CLOTH_SHOES:
case ITEM_STITCHED_LEATHER_BOOTS:
case ITEM_LINKED_MAIL_BOOTS:
case ITEM_DENTED_PLATE_BOOTS:
player->SetRewardedQuest(QUEST_MURLOC_HIDEAWAY_BOOTS_DROPPED);
break;
default:
break;
}
}
}
}
@@ -4559,10 +4571,19 @@ struct npc_quilboar_warrior : public ScriptedAI
for (LootItem const& lootItem : loot->items)
{
if (lootItem.itemid == ITEM_STITCHED_CLOTH_TUNIC || lootItem.itemid == ITEM_STITCHED_LEATHER_TUNIC || lootItem.itemid == ITEM_LINKED_MAIL_HAUBERK || lootItem.itemid == ITEM_DENTED_CHESTPLATE)
if (lootItem.type != LootItemType::Item)
continue;
switch (lootItem.itemid)
{
player->SetRewardedQuest(QUEST_BRIARPATCH_CHEST_DROPPED);
break;
case ITEM_STITCHED_CLOTH_TUNIC:
case ITEM_STITCHED_LEATHER_TUNIC:
case ITEM_LINKED_MAIL_HAUBERK:
case ITEM_DENTED_CHESTPLATE:
player->SetRewardedQuest(QUEST_BRIARPATCH_CHEST_DROPPED);
break;
default:
break;
}
}
}
@@ -4628,10 +4649,19 @@ struct npc_quilboar_geomancer : public ScriptedAI
for (LootItem const& lootItem : loot->items)
{
if (lootItem.itemid == ITEM_STITCHED_CLOTH_TUNIC || lootItem.itemid == ITEM_STITCHED_LEATHER_TUNIC || lootItem.itemid == ITEM_LINKED_MAIL_HAUBERK || lootItem.itemid == ITEM_DENTED_CHESTPLATE)
if (lootItem.type != LootItemType::Item)
continue;
switch (lootItem.itemid)
{
player->SetRewardedQuest(QUEST_BRIARPATCH_CHEST_DROPPED);
break;
case ITEM_STITCHED_CLOTH_TUNIC:
case ITEM_STITCHED_LEATHER_TUNIC:
case ITEM_LINKED_MAIL_HAUBERK:
case ITEM_DENTED_CHESTPLATE:
player->SetRewardedQuest(QUEST_BRIARPATCH_CHEST_DROPPED);
break;
default:
break;
}
}
}
@@ -4707,7 +4737,7 @@ struct npc_ogre_overseer : public ScriptedAI
for (LootItem const& lootItem : loot->items)
{
if (lootItem.itemid == ITEM_BATTERED_CLOAK)
if (lootItem.type == LootItemType::Item && lootItem.itemid == ITEM_BATTERED_CLOAK)
{
player->SetRewardedQuest(QUEST_BRIARPATCH_OVERSEER_CLOAK_DROPPED);
break;
@@ -6487,7 +6517,7 @@ struct npc_torgok_q55879 : public ScriptedAI
{
for (LootItem const& lootItem : loot->items)
{
if (lootItem.itemid == ITEM_TORGOKS_REAGENT_POUCH)
if (lootItem.type == LootItemType::Item && lootItem.itemid == ITEM_TORGOKS_REAGENT_POUCH)
{
player->SetRewardedQuest(QUEST_TORGOKS_REAGENT_POUCH_DROPPED);
break;