diff options
| author | Shauren <shauren.trinity@gmail.com> | 2025-06-22 21:56:58 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2025-06-22 21:56:58 +0200 |
| commit | e59059e1bd2f67691e2da0105771b0cb55b123a4 (patch) | |
| tree | 4f4864f8aae63eeafac29f440e0ce64a027c4108 /src/server/game/Entities | |
| parent | 7ca6b226a7420ff38e3a4f17a3758393d68629e3 (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.cpp | 11 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/GossipDef.h | 40 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 68 |
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; |
