TrinityCore
Loading...
Searching...
No Matches
Scenario.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Scenario.h"
19#include "Log.h"
20#include "Map.h"
21#include "ObjectAccessor.h"
22#include "ObjectMgr.h"
23#include "Player.h"
24#include "ScenarioMgr.h"
25#include "ScenarioPackets.h"
26#include "WorldSession.h"
27
28Scenario::Scenario(Map* map, ScenarioData const* scenarioData) : _map(map), _data(scenarioData),
29 _guid(ObjectGuid::Create<HighGuid::Scenario>(map->GetId(), scenarioData->Entry->ID, map->GenerateLowGuid<HighGuid::Scenario>())),
30 _currentstep(nullptr)
31{
33
34 for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
35 SetStepState(scenarioStep.second, SCENARIO_STEP_NOT_STARTED);
36
37 if (ScenarioStepEntry const* step = GetFirstStep())
38 SetStep(step);
39 else
40 TC_LOG_ERROR("scenario", "Scenario::Scenario: Could not launch Scenario (id: {}), found no valid scenario step", _data->Entry->ID);
41}
42
44{
45 for (ObjectGuid guid : _players)
46 if (Player* player = ObjectAccessor::GetPlayer(_map, guid))
47 SendBootPlayer(player);
48
49 _players.clear();
50}
51
57
59{
60 if (Quest const* quest = sObjectMgr->GetQuestTemplate(step->RewardQuestID))
61 for (ObjectGuid guid : _players)
62 if (Player* player = ObjectAccessor::GetPlayer(_map, guid))
63 player->RewardQuest(quest, LootItemType::Item, 0, nullptr, false);
64
65 if (step->IsBonusObjective())
66 return;
67
68 ScenarioStepEntry const* newStep = nullptr;
69 for (auto const& _step : _data->Steps)
70 {
71 if (_step.second->IsBonusObjective())
72 continue;
73
74 if (GetStepState(_step.second) == SCENARIO_STEP_DONE)
75 continue;
76
77 if (!newStep || _step.second->OrderIndex < newStep->OrderIndex)
78 newStep = _step.second;
79 }
80
81 SetStep(newStep);
82 if (IsComplete())
84 else
85 TC_LOG_ERROR("scenario", "Scenario::CompleteStep: Scenario (id: {}, step: {}) was completed, but could not determine new step, or validate scenario completion.", step->ScenarioID, step->ID);
86}
87
98
100{
101 _currentstep = step;
102 if (step)
103 {
105 for (ObjectGuid const& guid : _players)
106 if (Player* player = ObjectAccessor::GetPlayer(_map, guid))
107 player->StartCriteria(CriteriaStartEvent::BeginScenarioStep, step->ID);
108 }
109
110 DoForAllPlayers([&](Player const* receiver)
111 {
113 BuildScenarioStateFor(receiver, &scenarioState);
114 receiver->SendDirectMessage(scenarioState.Write());
115 });
116}
117
119{
120 _players.insert(player->GetGUID());
121 SendScenarioState(player);
122}
123
125{
126 _players.erase(player->GetGUID());
127 SendBootPlayer(player);
128}
129
131{
132 for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
133 {
134 if (scenarioStep.second->IsBonusObjective())
135 continue;
136
137 if (GetStepState(scenarioStep.second) != SCENARIO_STEP_DONE)
138 return false;
139 }
140
141 return true;
142}
143
145{
146 return _data->Entry;
147}
148
150{
151 auto itr = _stepStates.find(step);
152 if (itr == _stepStates.end())
154
155 return itr->second;
156}
157
158void Scenario::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const
159{
160 DoForAllPlayers([=, this](Player const* receiver)
161 {
163 progressUpdate.CriteriaProgress.Id = criteria->ID;
164 progressUpdate.CriteriaProgress.Quantity = progress->Counter;
165 progressUpdate.CriteriaProgress.Player = _guid;
166 progressUpdate.CriteriaProgress.Date.SetUtcTimeFromUnixTime(progress->Date);
167 progressUpdate.CriteriaProgress.Date += receiver->GetSession()->GetTimezoneOffset();
168 if (criteria->Entry->StartTimer)
169 progressUpdate.CriteriaProgress.Flags = timedCompleted ? 1 : 0;
170
171 progressUpdate.CriteriaProgress.TimeFromStart = timeElapsed;
172 progressUpdate.CriteriaProgress.TimeFromCreate = Seconds::zero();
173
174 receiver->SendDirectMessage(progressUpdate.Write());
175 });
176}
177
178bool Scenario::CanUpdateCriteriaTree(Criteria const * /*criteria*/, CriteriaTree const * tree, Player * /*referencePlayer*/) const
179{
180 ScenarioStepEntry const* step = tree->ScenarioStep;
181 if (!step)
182 return false;
183
184 if (step->ScenarioID != _data->Entry->ID)
185 return false;
186
187 ScenarioStepEntry const* currentStep = GetStep();
188 if (!currentStep)
189 return false;
190
191 if (step->IsBonusObjective())
192 return true;
193
194 return currentStep == step;
195}
196
198{
199 ScenarioStepEntry const* step = tree->ScenarioStep;
200 if (!step)
201 return false;
202
203 ScenarioStepState const state = GetStepState(step);
204 if (state == SCENARIO_STEP_DONE)
205 return false;
206
207 ScenarioStepEntry const* currentStep = GetStep();
208 if (!currentStep)
209 return false;
210
211 if (!step->IsBonusObjective())
212 if (step != currentStep)
213 return false;
214
216}
217
218void Scenario::CompletedCriteriaTree(CriteriaTree const* tree, Player* /*referencePlayer*/)
219{
220 ScenarioStepEntry const* step = ASSERT_NOTNULL(tree->ScenarioStep);
221 if (!IsCompletedStep(step))
222 return;
223
225 CompleteStep(step);
226}
227
229{
230 CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(step->Criteriatreeid);
231 if (!tree)
232 return false;
233
234 return IsCompletedCriteriaTree(tree);
235}
236
237void Scenario::DoForAllPlayers(std::function<void(Player*)> const& worker) const
238{
239 for (ObjectGuid guid : _players)
240 if (Player* player = ObjectAccessor::GetPlayer(_map, guid))
241 worker(player);
242}
243
244void Scenario::SendPacket(WorldPacket const* data) const
245{
246 DoForAllPlayers([data](Player const* player)
247 {
248 player->SendDirectMessage(data);
249 });
250}
251
253{
254 scenarioState->ScenarioGUID = _guid;
255 scenarioState->ScenarioID = _data->Entry->ID;
256 if (ScenarioStepEntry const* step = GetStep())
257 scenarioState->CurrentStep = step->ID;
258 scenarioState->CriteriaProgress = GetCriteriasProgressFor(player);
259 scenarioState->BonusObjectives = GetBonusObjectivesData();
260 // Don't know exactly what this is for, but seems to contain list of scenario steps that we're either on or that are completed
261 for (std::pair<ScenarioStepEntry const* const, ScenarioStepState> const& state : _stepStates)
262 {
263 if (state.first->IsBonusObjective())
264 continue;
265
266 switch (state.second)
267 {
270 break;
272 default:
273 continue;
274 }
275
276 scenarioState->PickedSteps.push_back(state.first->ID);
277 }
278 scenarioState->ScenarioComplete = IsComplete();
279}
280
282{
283 // Do it like this because we don't know what order they're in inside the container.
284 ScenarioStepEntry const* firstStep = nullptr;
285 for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
286 {
287 if (scenarioStep.second->IsBonusObjective())
288 continue;
289
290 if (!firstStep || scenarioStep.second->OrderIndex < firstStep->OrderIndex)
291 firstStep = scenarioStep.second;
292 }
293
294 return firstStep;
295}
296
298{
299 // Do it like this because we don't know what order they're in inside the container.
300 ScenarioStepEntry const* lastStep = nullptr;
301 for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
302 {
303 if (scenarioStep.second->IsBonusObjective())
304 continue;
305
306 if (!lastStep || scenarioStep.second->OrderIndex > lastStep->OrderIndex)
307 lastStep = scenarioStep.second;
308 }
309
310 return lastStep;
311}
312
313void Scenario::SendScenarioState(Player const* player) const
314{
316 BuildScenarioStateFor(player, &scenarioState);
317 player->SendDirectMessage(scenarioState.Write());
318}
319
320std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObjectivesData() const
321{
322 std::vector<WorldPackets::Scenario::BonusObjectiveData> bonusObjectivesData;
323 for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
324 {
325 if (!scenarioStep.second->IsBonusObjective())
326 continue;
327
328 if (sCriteriaMgr->GetCriteriaTree(scenarioStep.second->Criteriatreeid))
329 {
331 bonusObjectiveData.BonusObjectiveID = scenarioStep.second->ID;
332 bonusObjectiveData.ObjectiveComplete = GetStepState(scenarioStep.second) == SCENARIO_STEP_DONE;
333 bonusObjectivesData.push_back(bonusObjectiveData);
334 }
335 }
336
337 return bonusObjectivesData;
338}
339
340std::vector<WorldPackets::Achievement::CriteriaProgress> Scenario::GetCriteriasProgressFor(Player const* player) const
341{
342 std::vector<WorldPackets::Achievement::CriteriaProgress> criteriasProgress;
343
344 for (auto const& [criteriaId, progress] : _criteriaProgress)
345 {
346 WorldPackets::Achievement::CriteriaProgress& criteriaProgress = criteriasProgress.emplace_back();
347 criteriaProgress.Id = criteriaId;
348 criteriaProgress.Quantity = progress.Counter;
349 criteriaProgress.Date.SetUtcTimeFromUnixTime(progress.Date);
350 criteriaProgress.Date += player->GetSession()->GetTimezoneOffset();
351 criteriaProgress.Player = _guid;
352 }
353
354 return criteriasProgress;
355}
356
358{
359 return sCriteriaMgr->GetScenarioCriteriaByTypeAndScenario(type, _data->Entry->ID);
360}
361
362void Scenario::SendBootPlayer(Player const* player) const
363{
365 scenarioBoot.ScenarioGUID = _guid;
366 scenarioBoot.ScenarioID = _data->Entry->ID;
367 player->SendDirectMessage(scenarioBoot.Write());
368}
#define sCriteriaMgr
std::vector< Criteria const * > CriteriaList
CriteriaType
Definition DBCEnums.h:546
uint32_t uint32
Definition Define.h:154
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
#define ASSERT
Definition Errors.h:80
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
HighGuid
Definition ObjectGuid.h:109
#define sObjectMgr
Definition ObjectMgr.h:1885
ScenarioStepState
Definition Scenario.h:45
@ SCENARIO_STEP_IN_PROGRESS
Definition Scenario.h:48
@ SCENARIO_STEP_INVALID
Definition Scenario.h:46
@ SCENARIO_STEP_DONE
Definition Scenario.h:49
@ SCENARIO_STEP_NOT_STARTED
Definition Scenario.h:47
uint32 const Entry[5]
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
virtual void Reset()
CriteriaProgressMap _criteriaProgress
virtual bool CanCompleteCriteriaTree(CriteriaTree const *tree)
bool IsCompletedCriteriaTree(CriteriaTree const *tree)
Definition Map.h:225
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
WorldSession * GetSession() const
Definition Player.h:2272
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition Player.cpp:27588
void SendScenarioState(Player const *player) const
Definition Scenario.cpp:313
ScenarioEntry const * GetEntry() const
Definition Scenario.cpp:144
std::vector< WorldPackets::Achievement::CriteriaProgress > GetCriteriasProgressFor(Player const *player) const
Definition Scenario.cpp:340
virtual void OnPlayerExit(Player *player)
Definition Scenario.cpp:124
void SendPacket(WorldPacket const *data) const override
Definition Scenario.cpp:244
void SendBootPlayer(Player const *player) const
Definition Scenario.cpp:362
ScenarioData const * _data
Definition Scenario.h:103
virtual void OnPlayerEnter(Player *player)
Definition Scenario.cpp:118
ScenarioStepEntry const * GetLastStep() const
Definition Scenario.cpp:297
ScenarioStepEntry const * GetFirstStep() const
Definition Scenario.cpp:281
bool IsComplete() const
Definition Scenario.cpp:130
void Reset() override
Definition Scenario.cpp:52
std::vector< WorldPackets::Scenario::BonusObjectiveData > GetBonusObjectivesData() const
Definition Scenario.cpp:320
bool CanUpdateCriteriaTree(Criteria const *criteria, CriteriaTree const *tree, Player *referencePlayer) const override
Definition Scenario.cpp:178
virtual void CompleteStep(ScenarioStepEntry const *step)
Definition Scenario.cpp:58
Map const * _map
Definition Scenario.h:81
ScenarioStepState GetStepState(ScenarioStepEntry const *step) const
Definition Scenario.cpp:149
std::map< ScenarioStepEntry const *, ScenarioStepState > _stepStates
Definition Scenario.h:108
Scenario(Map *map, ScenarioData const *scenarioData)
Definition Scenario.cpp:28
ObjectGuid const _guid
Definition Scenario.h:106
bool CanCompleteCriteriaTree(CriteriaTree const *tree) override
Definition Scenario.cpp:197
GuidUnorderedSet _players
Definition Scenario.h:82
void DoForAllPlayers(std::function< void(Player *)> const &worker) const
Definition Scenario.cpp:237
void BuildScenarioStateFor(Player const *player, WorldPackets::Scenario::ScenarioState *scenarioState) const
Definition Scenario.cpp:252
ScenarioStepEntry const * _currentstep
Definition Scenario.h:107
virtual void CompleteScenario()
Definition Scenario.cpp:88
void SetStepState(ScenarioStepEntry const *step, ScenarioStepState state)
Definition Scenario.h:70
ScenarioStepEntry const * GetStep() const
Definition Scenario.h:73
void SetStep(ScenarioStepEntry const *step)
Definition Scenario.cpp:99
bool IsCompletedStep(ScenarioStepEntry const *step)
Definition Scenario.cpp:228
CriteriaList const & GetCriteriaByType(CriteriaType type, uint32 asset) const override
Definition Scenario.cpp:357
void CompletedCriteriaTree(CriteriaTree const *tree, Player *referencePlayer) override
Definition Scenario.cpp:218
void SendCriteriaUpdate(Criteria const *criteria, CriteriaProgress const *progress, Seconds timeElapsed, bool timedCompleted) const override
Definition Scenario.cpp:158
WorldPacket const * Write() override
Achievement::CriteriaProgress CriteriaProgress
std::vector< Achievement::CriteriaProgress > CriteriaProgress
WorldPacket const * Write() override
std::vector< BonusObjectiveData > BonusObjectives
WorldPacket const * Write() override
Minutes GetTimezoneOffset() const
void SetUtcTimeFromUnixTime(std::time_t unixTime)
Definition WowTime.cpp:86
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
ScenarioStepEntry const * ScenarioStep
CriteriaEntry const * Entry
std::map< uint8, ScenarioStepEntry const * > Steps
Definition ScenarioMgr.h:37
ScenarioEntry const * Entry
Definition ScenarioMgr.h:36
bool IsBonusObjective() const