aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-06-22 21:56:58 +0200
committerShauren <shauren.trinity@gmail.com>2025-06-22 21:56:58 +0200
commite59059e1bd2f67691e2da0105771b0cb55b123a4 (patch)
tree4f4864f8aae63eeafac29f440e0ce64a027c4108 /src/server/game/Entities
parent7ca6b226a7420ff38e3a4f17a3758393d68629e3 (diff)
Core/Players: PlayerChoice improvements
* Add missing choice properties to database (InfiniteRange, ShowChoicesAsList) * Allow limiiting the number of responses sent at the same time * Fixed duration sent in SMSG_DISPLAY_PLAYER_CHOICE * Remove dynamically generated response identifiers from database * Remove auto rewarding choice responses * Change response scripts to be bound to scriptname
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp11
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h40
-rw-r--r--src/server/game/Entities/Player/Player.cpp68
3 files changed, 80 insertions, 39 deletions
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 20390ce2833..75fc7f8ce87 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -353,6 +353,17 @@ bool QuestMenu::HasItem(uint32 questId) const
return advstd::ranges::contains(_questMenuItems, questId, &QuestMenuItem::QuestId);
}
+Optional<uint32> PlayerChoiceData::FindIdByClientIdentifier(uint16 clientIdentifier) const
+{
+ auto itr = std::ranges::find(_responses, clientIdentifier, &Response::ClientIdentifier);
+ return itr != _responses.end() ? itr->Id : Optional<uint32>();
+}
+
+void PlayerChoiceData::AddResponse(uint32 id, uint16 clientIdentifier)
+{
+ _responses.push_back({ .Id = id, .ClientIdentifier = clientIdentifier });
+}
+
void QuestMenu::ClearMenu()
{
_questMenuItems.clear();
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index b596a3ec5ed..da83b064300 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -19,6 +19,7 @@
#define TRINITYCORE_GOSSIP_H
#include "Common.h"
+#include "Duration.h"
#include "ObjectGuid.h"
#include "Optional.h"
#include <variant>
@@ -232,6 +233,33 @@ class TC_GAME_API QuestMenu
QuestMenuItemList _questMenuItems;
};
+class PlayerChoiceData
+{
+public:
+ PlayerChoiceData() = default;
+ explicit PlayerChoiceData(uint32 choiceId) : _choiceId(choiceId) { }
+
+ uint32 GetChoiceId() const { return _choiceId; }
+ void SetChoiceId(uint32 choiceId) { _choiceId = choiceId; }
+
+ Optional<uint32> FindIdByClientIdentifier(uint16 clientIdentifier) const;
+ void AddResponse(uint32 id, uint16 clientIdentifier);
+
+ Optional<SystemTimePoint> GetExpireTime() const { return _expireTime; }
+ void SetExpireTime(Optional<SystemTimePoint> expireTime) { _expireTime = expireTime; }
+
+private:
+ struct Response
+ {
+ uint32 Id = 0;
+ uint16 ClientIdentifier = 0;
+ };
+
+ uint32 _choiceId = 0;
+ std::vector<Response> _responses;
+ Optional<SystemTimePoint> _expireTime;
+};
+
class InteractionData
{
template <typename>
@@ -246,9 +274,6 @@ class InteractionData
struct TrainerTag;
using TrainerData = TaggedId<TrainerTag>;
- struct PlayerChoiceTag;
- using PlayerChoiceData = TaggedId<PlayerChoiceTag>;
-
public:
void Reset()
{
@@ -262,12 +287,19 @@ public:
Optional<uint32> GetTrainerId() const { return std::holds_alternative<TrainerData>(_data) ? std::get<TrainerData>(_data).Id : Optional<uint32>(); }
void SetTrainerId(uint32 trainerId) { _data.emplace<TrainerData>(trainerId); }
- Optional<uint32> GetPlayerChoiceId() const { return std::holds_alternative<TrainerData>(_data) ? std::get<PlayerChoiceData>(_data).Id : Optional<uint32>(); }
+ PlayerChoiceData* GetPlayerChoice() { return std::holds_alternative<PlayerChoiceData>(_data) ? &std::get<PlayerChoiceData>(_data) : nullptr; }
void SetPlayerChoice(uint32 choiceId) { _data.emplace<PlayerChoiceData>(choiceId); }
+ uint16 AddPlayerChoiceResponse(uint32 responseId)
+ {
+ std::get<PlayerChoiceData>(_data).AddResponse(responseId, ++_playerChoiceResponseIdentifierGenerator);
+ return _playerChoiceResponseIdentifierGenerator;
+ }
+
bool IsLaunchedByQuest = false;
private:
+ uint16 _playerChoiceResponseIdentifierGenerator = 0; // not reset between interactions
std::variant<std::monostate, TrainerData, PlayerChoiceData> _data;
};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 6e37b039fe1..e1fc38f9ab4 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -102,6 +102,7 @@
#include "PoolMgr.h"
#include "PetitionMgr.h"
#include "PhasingHandler.h"
+#include "PlayerChoice.h"
#include "QueryCallback.h"
#include "QueryHolder.h"
#include "QuestDef.h"
@@ -29793,16 +29794,22 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
displayPlayerChoice.ChoiceID = choiceId;
displayPlayerChoice.UiTextureKitID = playerChoice->UiTextureKitId;
displayPlayerChoice.SoundKitID = playerChoice->SoundKitId;
+ displayPlayerChoice.CloseUISoundKitID = playerChoice->CloseSoundKitId;
+ if (playerChoice->Duration > 0s)
+ displayPlayerChoice.ExpireTime = GameTime::GetSystemTime() + playerChoice->Duration;
+
displayPlayerChoice.Question = playerChoice->Question;
if (playerChoiceLocale)
ObjectMgr::GetLocaleString(playerChoiceLocale->Question, locale, displayPlayerChoice.Question);
displayPlayerChoice.Responses.reserve(playerChoice->Responses.size());
- displayPlayerChoice.InfiniteRange = false;
+ displayPlayerChoice.InfiniteRange = playerChoice->InfiniteRange;
displayPlayerChoice.HideWarboardHeader = playerChoice->HideWarboardHeader;
displayPlayerChoice.KeepOpenAfterChoice = playerChoice->KeepOpenAfterChoice;
+ displayPlayerChoice.ShowChoicesAsList = playerChoice->ShowChoicesAsList;
+ displayPlayerChoice.ForceDontShowChoicesAsList = playerChoice->ForceDontShowChoicesAsList;
- for (std::size_t i = 0; i < playerChoice->Responses.size(); ++i)
+ for (std::size_t i = 0; i < playerChoice->Responses.size() && (!playerChoice->MaxResponses || displayPlayerChoice.Responses.size() < *playerChoice->MaxResponses); ++i)
{
PlayerChoiceResponse const& playerChoiceResponseTemplate = playerChoice->Responses[i];
if (!sConditionMgr->IsObjectMeetingPlayerChoiceResponseConditions(choiceId, playerChoiceResponseTemplate.ResponseId, this))
@@ -29810,9 +29817,9 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
WorldPackets::Quest::PlayerChoiceResponse& playerChoiceResponse = displayPlayerChoice.Responses.emplace_back();
playerChoiceResponse.ResponseID = playerChoiceResponseTemplate.ResponseId;
- playerChoiceResponse.ResponseIdentifier = playerChoiceResponseTemplate.ResponseIdentifier;
+ playerChoiceResponse.ResponseIdentifier = PlayerTalkClass->GetInteractionData().AddPlayerChoiceResponse(playerChoiceResponseTemplate.ResponseId);
playerChoiceResponse.ChoiceArtFileID = playerChoiceResponseTemplate.ChoiceArtFileId;
- playerChoiceResponse.Flags = playerChoiceResponseTemplate.Flags;
+ playerChoiceResponse.Flags = playerChoiceResponseTemplate.Flags.AsUnderlyingType();
playerChoiceResponse.WidgetSetID = playerChoiceResponseTemplate.WidgetSetID;
playerChoiceResponse.UiTextureAtlasElementID = playerChoiceResponseTemplate.UiTextureAtlasElementID;
playerChoiceResponse.SoundKitID = playerChoiceResponseTemplate.SoundKitID;
@@ -29848,40 +29855,31 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
playerChoiceResponse.Reward->HonorPointCount = playerChoiceResponseTemplate.Reward->HonorPointCount;
playerChoiceResponse.Reward->Money = playerChoiceResponseTemplate.Reward->Money;
playerChoiceResponse.Reward->Xp = playerChoiceResponseTemplate.Reward->Xp;
- for (PlayerChoiceResponseRewardItem const& item : playerChoiceResponseTemplate.Reward->Items)
- {
- WorldPackets::Quest::PlayerChoiceResponseRewardEntry& rewardEntry = playerChoiceResponse.Reward->Items.emplace_back();
- rewardEntry.Item.ItemID = item.Id;
- rewardEntry.Quantity = item.Quantity;
- if (!item.BonusListIDs.empty())
- {
- rewardEntry.Item.ItemBonus.emplace();
- rewardEntry.Item.ItemBonus->BonusListIDs = item.BonusListIDs;
- }
- }
- for (PlayerChoiceResponseRewardEntry const& currency : playerChoiceResponseTemplate.Reward->Currency)
- {
- WorldPackets::Quest::PlayerChoiceResponseRewardEntry& rewardEntry = playerChoiceResponse.Reward->Items.emplace_back();
- rewardEntry.Item.ItemID = currency.Id;
- rewardEntry.Quantity = currency.Quantity;
- }
- for (PlayerChoiceResponseRewardEntry const& faction : playerChoiceResponseTemplate.Reward->Faction)
- {
- WorldPackets::Quest::PlayerChoiceResponseRewardEntry& rewardEntry = playerChoiceResponse.Reward->Items.emplace_back();
- rewardEntry.Item.ItemID = faction.Id;
- rewardEntry.Quantity = faction.Quantity;
- }
- for (PlayerChoiceResponseRewardItem const& item : playerChoiceResponseTemplate.Reward->ItemChoices)
+
+ auto fillRewardItems = []<typename Src>(std::vector<Src> const& src, std::vector<WorldPackets::Quest::PlayerChoiceResponseRewardEntry>& dest)
{
- WorldPackets::Quest::PlayerChoiceResponseRewardEntry& rewardEntry = playerChoiceResponse.Reward->ItemChoices.emplace_back();
- rewardEntry.Item.ItemID = item.Id;
- rewardEntry.Quantity = item.Quantity;
- if (!item.BonusListIDs.empty())
+ dest.resize(src.size());
+ for (std::size_t j = 0; j < src.size(); ++j)
{
- rewardEntry.Item.ItemBonus.emplace();
- rewardEntry.Item.ItemBonus->BonusListIDs = item.BonusListIDs;
+ Src const& rewardEntryTemplate = src[j];
+ WorldPackets::Quest::PlayerChoiceResponseRewardEntry& rewardEntry = dest[j];
+ rewardEntry.Item.ItemID = rewardEntryTemplate.Id;
+ rewardEntry.Quantity = rewardEntryTemplate.Quantity;
+ if constexpr (std::is_same_v<Src, PlayerChoiceResponseRewardItem>)
+ {
+ if (!rewardEntryTemplate.BonusListIDs.empty())
+ {
+ rewardEntry.Item.ItemBonus.emplace();
+ rewardEntry.Item.ItemBonus->BonusListIDs = rewardEntryTemplate.BonusListIDs;
+ }
+ }
}
- }
+ };
+
+ fillRewardItems(playerChoiceResponseTemplate.Reward->Items, playerChoiceResponse.Reward->Items);
+ fillRewardItems(playerChoiceResponseTemplate.Reward->Currency, playerChoiceResponse.Reward->Currencies);
+ fillRewardItems(playerChoiceResponseTemplate.Reward->Faction, playerChoiceResponse.Reward->Factions);
+ fillRewardItems(playerChoiceResponseTemplate.Reward->ItemChoices, playerChoiceResponse.Reward->ItemChoices);
}
playerChoiceResponse.RewardQuestID = playerChoiceResponseTemplate.RewardQuestID;