aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Scenarios/Scenario.cpp
diff options
context:
space:
mode:
authorKrudor <erikstrandberg93@hotmail.com>2016-11-06 23:30:49 +0100
committerShauren <shauren.trinity@gmail.com>2016-11-06 23:30:49 +0100
commit8444ab736568667cb6425757ce5f832cb6068379 (patch)
tree375c6a9d25b9d5a4d351f4e3a7c0b52526dd816f /src/server/game/Scenarios/Scenario.cpp
parent9d88e78961cc92c2914ffb25333f35433a0c9682 (diff)
Core/Instances: Implemented base scenario system and objectives in dungeons
Closes #17905 Closes #18034
Diffstat (limited to 'src/server/game/Scenarios/Scenario.cpp')
-rw-r--r--src/server/game/Scenarios/Scenario.cpp311
1 files changed, 311 insertions, 0 deletions
diff --git a/src/server/game/Scenarios/Scenario.cpp b/src/server/game/Scenarios/Scenario.cpp
new file mode 100644
index 00000000000..a4e39b2caa6
--- /dev/null
+++ b/src/server/game/Scenarios/Scenario.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Scenario.h"
+#include "Player.h"
+#include "ScenarioMgr.h"
+#include "InstanceSaveMgr.h"
+#include "ObjectMgr.h"
+#include "ScenarioPackets.h"
+
+Scenario::Scenario(ScenarioData const* scenarioData) : _data(scenarioData), _currentstep(nullptr)
+{
+ ASSERT(_data);
+
+ for (auto step : _data->Steps)
+ SetStepState(step.second, SCENARIO_STEP_NOT_STARTED);
+
+ if (ScenarioStepEntry const* step = GetFirstStep())
+ SetStep(step);
+ else
+ TC_LOG_ERROR("scenario", "Scenario::Scenario: Could not launch Scenario (id: %u), found no valid scenario step", _data->Entry->ID);
+}
+
+Scenario::~Scenario()
+{
+ for (ObjectGuid guid : _players)
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ SendBootPlayer(player);
+
+ _players.clear();
+}
+
+void Scenario::Reset()
+{
+ CriteriaHandler::Reset();
+ SetStep(GetFirstStep());
+}
+
+void Scenario::CompleteStep(ScenarioStepEntry const* step)
+{
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(step->QuestRewardID))
+ for (ObjectGuid guid : _players)
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ player->RewardQuest(quest, 0, nullptr, false);
+
+ if (step->IsBonusObjective())
+ return;
+
+ ScenarioStepEntry const* newStep = nullptr;
+ for (auto _step : _data->Steps)
+ {
+ if (_step.second->IsBonusObjective())
+ continue;
+
+ if (GetStepState(_step.second) == SCENARIO_STEP_DONE)
+ continue;
+
+ if (!newStep || _step.second->Step < newStep->Step)
+ newStep = _step.second;
+ }
+
+ SetStep(newStep);
+ if (IsComplete())
+ CompleteScenario();
+ else
+ TC_LOG_ERROR("scenario", "Scenario::CompleteStep: Scenario (id: %u, step: %u) was completed, but could not determine new step, or validate scenario completion.", step->ScenarioID, step->ID);
+}
+
+void Scenario::CompleteScenario()
+{
+ return SendPacket(WorldPackets::Scenario::ScenarioCompleted(_data->Entry->ID).Write());
+}
+
+void Scenario::SetStep(ScenarioStepEntry const* step)
+{
+ _currentstep = step;
+ if (step)
+ SetStepState(step, SCENARIO_STEP_IN_PROGRESS);
+
+ WorldPackets::Scenario::ScenarioState scenarioState;
+ BuildScenarioState(&scenarioState);
+ SendPacket(scenarioState.Write());
+}
+
+void Scenario::OnPlayerEnter(Player* player)
+{
+ _players.insert(player->GetGUID());
+ SendScenarioState(player);
+}
+
+void Scenario::OnPlayerExit(Player* player)
+{
+ _players.erase(player->GetGUID());
+ SendBootPlayer(player);
+}
+
+bool Scenario::IsComplete()
+{
+ for (auto step : _data->Steps)
+ {
+ if (step.second->IsBonusObjective())
+ continue;
+
+ if (GetStepState(step.second) != SCENARIO_STEP_DONE)
+ return false;
+ }
+
+ return true;
+}
+
+ScenarioStepState Scenario::GetStepState(ScenarioStepEntry const* step)
+{
+ std::map<ScenarioStepEntry const*, ScenarioStepState>::const_iterator itr = _stepStates.find(step);
+ if (itr == _stepStates.end())
+ return SCENARIO_STEP_INVALID;
+
+ return itr->second;
+}
+
+void Scenario::SendCriteriaUpdate(Criteria const * criteria, CriteriaProgress const * progress, uint32 timeElapsed, bool timedCompleted) const
+{
+ WorldPackets::Scenario::ScenarioProgressUpdate progressUpdate;
+ progressUpdate.CriteriaProgress.Id = criteria->ID;
+ progressUpdate.CriteriaProgress.Quantity = progress->Counter;
+ progressUpdate.CriteriaProgress.Player = progress->PlayerGUID;
+ progressUpdate.CriteriaProgress.Date = progress->Date;
+ if (criteria->Entry->StartTimer)
+ progressUpdate.CriteriaProgress.Flags = timedCompleted ? 1 : 0;
+
+ progressUpdate.CriteriaProgress.TimeFromStart = timeElapsed;
+ progressUpdate.CriteriaProgress.TimeFromCreate = 0;
+
+ SendPacket(progressUpdate.Write());
+}
+
+bool Scenario::CanUpdateCriteriaTree(Criteria const * /*criteria*/, CriteriaTree const * tree, Player * /*referencePlayer*/) const
+{
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ return false;
+
+ if (step->ScenarioID != _data->Entry->ID)
+ return false;
+
+ ScenarioStepEntry const* currentStep = GetStep();
+ if (!currentStep)
+ return false;
+
+ if (step->IsBonusObjective())
+ return true;
+
+ return currentStep == step;
+}
+
+bool Scenario::CanCompleteCriteriaTree(CriteriaTree const* tree)
+{
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ return false;
+
+ if (step->ScenarioID != _data->Entry->ID)
+ return false;
+
+ if (step->IsBonusObjective())
+ return !IsComplete();
+
+ if (step != GetStep())
+ return false;
+
+ return true;
+}
+
+void Scenario::CompletedCriteriaTree(CriteriaTree const* tree, Player* /*referencePlayer*/)
+{
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ return;
+
+ if (!step->IsBonusObjective() && step != GetStep())
+ return;
+
+ if (GetStepState(step) == SCENARIO_STEP_DONE)
+ return;
+
+ SetStepState(step, SCENARIO_STEP_DONE);
+ CompleteStep(step);
+}
+
+void Scenario::SendPacket(WorldPacket const* data) const
+{
+ for (ObjectGuid guid : _players)
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ player->SendDirectMessage(data);
+}
+
+void Scenario::BuildScenarioState(WorldPackets::Scenario::ScenarioState* scenarioState)
+{
+ scenarioState->ScenarioID = _data->Entry->ID;
+ if (ScenarioStepEntry const* step = GetStep())
+ scenarioState->CurrentStep = step->ID;
+ scenarioState->CriteriaProgress = GetCriteriasProgress();
+ scenarioState->BonusObjectives = GetBonusObjectivesData();
+ // 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
+ for (auto state : _stepStates)
+ {
+ if (state.first->IsBonusObjective())
+ continue;
+
+ switch (state.second)
+ {
+ case SCENARIO_STEP_IN_PROGRESS:
+ case SCENARIO_STEP_DONE:
+ break;
+ case SCENARIO_STEP_NOT_STARTED:
+ default:
+ continue;
+ }
+
+ scenarioState->PickedSteps.push_back(state.first->ID);
+ }
+ scenarioState->ScenarioComplete = IsComplete();
+}
+
+ScenarioStepEntry const* Scenario::GetFirstStep() const
+{
+ // Do it like this because we don't know what order they're in inside the container.
+ ScenarioStepEntry const* firstStep = nullptr;
+ for (auto scenarioStep : _data->Steps)
+ {
+ if (scenarioStep.second->IsBonusObjective())
+ continue;
+
+ if (!firstStep || scenarioStep.second->Step < firstStep->Step)
+ firstStep = scenarioStep.second;
+ }
+
+ return firstStep;
+}
+
+void Scenario::SendScenarioState(Player* player)
+{
+ WorldPackets::Scenario::ScenarioState scenarioState;
+ BuildScenarioState(&scenarioState);
+ player->SendDirectMessage(scenarioState.Write());
+}
+
+std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObjectivesData()
+{
+ std::vector<WorldPackets::Scenario::BonusObjectiveData> bonusObjectivesData;
+ for (auto itr = _data->Steps.begin(); itr != _data->Steps.end(); ++itr)
+ {
+ if (!itr->second->IsBonusObjective())
+ continue;
+
+ if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(itr->second->CriteriaTreeID))
+ {
+ WorldPackets::Scenario::BonusObjectiveData bonusObjectiveData;
+ bonusObjectiveData.BonusObjectiveID = itr->second->ID;
+ bonusObjectiveData.ObjectiveComplete = GetStepState(itr->second) == SCENARIO_STEP_DONE;
+ bonusObjectivesData.push_back(bonusObjectiveData);
+ }
+ }
+
+ return bonusObjectivesData;
+}
+
+std::vector<WorldPackets::Achievement::CriteriaProgress> Scenario::GetCriteriasProgress()
+{
+ std::vector<WorldPackets::Achievement::CriteriaProgress> criteriasProgress;
+
+ if (!_criteriaProgress.empty())
+ {
+ for (auto critItr = _criteriaProgress.begin(); critItr != _criteriaProgress.end(); ++critItr)
+ {
+ WorldPackets::Achievement::CriteriaProgress criteriaProgress;
+ criteriaProgress.Id = critItr->first;
+ criteriaProgress.Quantity = critItr->second.Counter;
+ criteriaProgress.Date = critItr->second.Date;
+ criteriaProgress.Player = critItr->second.PlayerGUID;
+ criteriasProgress.push_back(criteriaProgress);
+ }
+ }
+
+ return criteriasProgress;
+}
+
+CriteriaList const& Scenario::GetCriteriaByType(CriteriaTypes type) const
+{
+ return sCriteriaMgr->GetScenarioCriteriaByType(type);
+}
+
+void Scenario::SendBootPlayer(Player* player)
+{
+ WorldPackets::Scenario::ScenarioBoot scenarioBoot;
+ scenarioBoot.ScenarioID = _data->Entry->ID;
+ player->SendDirectMessage(scenarioBoot.Write());
+}