aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-08-26 15:02:22 +0200
committerShauren <shauren.trinity@gmail.com>2024-08-26 15:02:22 +0200
commit3e28ee080a1cf3c7cd332a8d1e0808505b4ea9d4 (patch)
tree0be0cc52e53927111501c0b9b31859f2d25c890e /src/server/game/Entities
parent6b4270850f8d93a9f4c67a61c85a62a9d3e7e127 (diff)
Core/Loot: Implemented currency loot
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Player/Player.cpp126
-rw-r--r--src/server/game/Entities/Player/Player.h1
2 files changed, 89 insertions, 38 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 0816202ba2f..2a53a6906bb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -16960,6 +16960,44 @@ QuestObjective const* Player::GetQuestObjectiveForItem(uint32 itemId, bool onlyI
return nullptr;
}
+bool Player::HasQuestForCurrency(uint32 currencyId) const
+{
+ auto isCompletableObjective = [this](QuestObjectiveStatusData const& objectiveStatus)
+ {
+ Quest const* qInfo = sObjectMgr->GetQuestTemplate(objectiveStatus.QuestStatusItr->first);
+ QuestObjective const* objective = sObjectMgr->GetQuestObjective(objectiveStatus.ObjectiveId);
+ if (!qInfo || !objective || !IsQuestObjectiveCompletable(objectiveStatus.QuestStatusItr->second.Slot, qInfo, *objective))
+ return false;
+
+ // hide quest if player is in raid-group and quest is no raid quest
+ if (GetGroup() && GetGroup()->isRaidGroup() && !qInfo->IsAllowedInRaid(GetMap()->GetDifficultyID()))
+ if (!InBattleground()) //there are two ways.. we can make every bg-quest a raidquest, or add this code here.. i don't know if this can be exploited by other quests, but i think all other quests depend on a specific area.. but keep this in mind, if something strange happens later
+ return false;
+
+ if (!IsQuestObjectiveComplete(objectiveStatus.QuestStatusItr->second.Slot, qInfo, *objective))
+ return true;
+
+ return false;
+ };
+
+ auto hasObjectiveTypeForCurrency = [&](QuestObjectiveType type)
+ {
+ return std::ranges::any_of(Trinity::Containers::MapEqualRange(m_questObjectiveStatus, { type, currencyId }),
+ isCompletableObjective, &QuestObjectiveStatusMap::value_type::second);
+ };
+
+ if (hasObjectiveTypeForCurrency(QUEST_OBJECTIVE_CURRENCY))
+ return true;
+
+ if (hasObjectiveTypeForCurrency(QUEST_OBJECTIVE_HAVE_CURRENCY))
+ return true;
+
+ if (hasObjectiveTypeForCurrency(QUEST_OBJECTIVE_OBTAIN_CURRENCY))
+ return true;
+
+ return false;
+}
+
int32 Player::GetQuestObjectiveData(QuestObjective const& objective) const
{
uint16 slot = FindQuestSlot(objective.QuestID);
@@ -26601,53 +26639,65 @@ void Player::StoreLootItem(ObjectGuid lootWorldObjectGuid, uint8 lootSlot, Loot*
return;
}
- ItemPosCountVec dest;
- InventoryResult msg = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count);
- if (msg == EQUIP_ERR_OK)
+ switch (item->type)
{
- Item* newitem = StoreNewItem(dest, item->itemid, true, item->randomBonusListId, item->GetAllowedLooters(), item->context);
-
- if (ffaItem)
+ case LootItemType::Item:
{
- //freeforall case, notify only one player of the removal
- ffaItem->is_looted = true;
- SendNotifyLootItemRemoved(loot->GetGUID(), loot->GetOwnerGUID(), lootSlot);
- }
- else //not freeforall, notify everyone
- loot->NotifyItemRemoved(lootSlot, GetMap());
+ ItemPosCountVec dest;
+ InventoryResult msg = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count);
+ if (msg != EQUIP_ERR_OK)
+ {
+ SendEquipError(msg, nullptr, nullptr, item->itemid);
+ return;
+ }
- //if only one person is supposed to loot the item, then set it to looted
- if (!item->freeforall)
- item->is_looted = true;
+ Item* newitem = StoreNewItem(dest, item->itemid, true, item->randomBonusListId, item->GetAllowedLooters(), item->context);
- --loot->unlootedCount;
+ if (newitem && (newitem->GetQuality() > ITEM_QUALITY_EPIC || (newitem->GetQuality() == ITEM_QUALITY_EPIC && newitem->GetItemLevel(this) >= MinNewsItemLevel)))
+ if (Guild* guild = GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid);
- if (newitem && (newitem->GetQuality() > ITEM_QUALITY_EPIC || (newitem->GetQuality() == ITEM_QUALITY_EPIC && newitem->GetItemLevel(this) >= MinNewsItemLevel)))
- if (Guild* guild = GetGuild())
- guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid);
+ // if aeLooting then we must delay sending out item so that it appears properly stacked in chat
+ if (!aeResult || !newitem)
+ {
+ SendNewItem(newitem, uint32(item->count), false, false, true, loot->GetDungeonEncounterId());
+ UpdateCriteria(CriteriaType::LootItem, item->itemid, item->count);
+ UpdateCriteria(CriteriaType::GetLootByType, item->itemid, item->count, GetLootTypeForClient(loot->loot_type));
+ UpdateCriteria(CriteriaType::LootAnyItem, item->itemid, item->count);
+ }
+ else
+ aeResult->Add(newitem, item->count, GetLootTypeForClient(loot->loot_type), loot->GetDungeonEncounterId());
- // if aeLooting then we must delay sending out item so that it appears properly stacked in chat
- if (!aeResult || !newitem)
- {
- SendNewItem(newitem, uint32(item->count), false, false, true, loot->GetDungeonEncounterId());
- UpdateCriteria(CriteriaType::LootItem, item->itemid, item->count);
- UpdateCriteria(CriteriaType::GetLootByType, item->itemid, item->count, GetLootTypeForClient(loot->loot_type));
- UpdateCriteria(CriteriaType::LootAnyItem, item->itemid, item->count);
- }
- else
- aeResult->Add(newitem, item->count, GetLootTypeForClient(loot->loot_type), loot->GetDungeonEncounterId());
+ if (newitem)
+ ApplyItemLootedSpell(newitem, true);
+ else
+ ApplyItemLootedSpell(sObjectMgr->GetItemTemplate(item->itemid));
- // LootItem is being removed (looted) from the container, delete it from the DB.
- if (loot->loot_type == LOOT_ITEM)
- sLootItemStorage->RemoveStoredLootItemForContainer(lootWorldObjectGuid.GetCounter(), item->itemid, item->count, item->LootListId);
+ break;
+ }
+ case LootItemType::Currency:
+ ModifyCurrency(item->itemid, item->count, CurrencyGainSource::Loot);
+ break;
+ }
- if (newitem)
- ApplyItemLootedSpell(newitem, true);
- else
- ApplyItemLootedSpell(sObjectMgr->GetItemTemplate(item->itemid));
+ if (ffaItem)
+ {
+ //freeforall case, notify only one player of the removal
+ ffaItem->is_looted = true;
+ SendNotifyLootItemRemoved(loot->GetGUID(), loot->GetOwnerGUID(), lootSlot);
}
- else
- SendEquipError(msg, nullptr, nullptr, item->itemid);
+ else //not freeforall, notify everyone
+ loot->NotifyItemRemoved(lootSlot, GetMap());
+
+ //if only one person is supposed to loot the item, then set it to looted
+ if (!item->freeforall)
+ item->is_looted = true;
+
+ --loot->unlootedCount;
+
+ // LootItem is being removed (looted) from the container, delete it from the DB.
+ if (loot->loot_type == LOOT_ITEM)
+ sLootItemStorage->RemoveStoredLootItemForContainer(lootWorldObjectGuid.GetCounter(), item->type, item->itemid, item->count, item->LootListId);
}
void Player::_LoadSkills(PreparedQueryResult result)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 43a42c6ab71..5dbc2e8c305 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1726,6 +1726,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
bool HasQuestForItem(uint32 itemId) const;
QuestObjective const* GetQuestObjectiveForItem(uint32 itemId, bool onlyIncomplete) const;
bool HasQuestForGO(int32 goId) const;
+ bool HasQuestForCurrency(uint32 currencyId) const;
void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects);
bool CanShareQuest(uint32 questId) const;