Files
CypherCore/Source/Game/Scenarios/Scenario.cs
T

369 lines
12 KiB
C#

/*
* Copyright (C) 2012-2018 CypherCore <http://github.com/CypherCore>
*
* 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 3 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/>.
*/
using Framework.Constants;
using Game.Achievements;
using Game.DataStorage;
using Game.Entities;
using Game.Network;
using Game.Network.Packets;
using System.Collections.Generic;
namespace Game.Scenarios
{
public class Scenario : CriteriaHandler
{
public Scenario(ScenarioData scenarioData)
{
_data = scenarioData;
_currentstep = null;
//ASSERT(_data);
foreach (var step in _data.Steps)
SetStepState(step.Value, ScenarioStepState.NotStarted);
ScenarioStepRecord firstStep = GetFirstStep();
if (firstStep != null)
SetStep(firstStep);
else
Log.outError(LogFilter.Scenario, "Scenario.Scenario: Could not launch Scenario (id: {0}), found no valid scenario step", _data.Entry.Id);
}
~Scenario()
{
foreach (ObjectGuid guid in _players)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player)
SendBootPlayer(player);
}
_players.Clear();
}
public override void Reset()
{
base.Reset();
SetStep(GetFirstStep());
}
public virtual void CompleteStep(ScenarioStepRecord step)
{
Quest quest = Global.ObjectMgr.GetQuestTemplate(step.RewardQuestID);
if (quest != null)
{
foreach (ObjectGuid guid in _players)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player)
player.RewardQuest(quest, 0, null, false);
}
}
if (step.IsBonusObjective())
return;
ScenarioStepRecord newStep = null;
foreach (var _step in _data.Steps.Values)
{
if (_step.IsBonusObjective())
continue;
if (GetStepState(_step) == ScenarioStepState.Done)
continue;
if (newStep == null || _step.OrderIndex < newStep.OrderIndex)
newStep = _step;
}
SetStep(newStep);
if (IsComplete())
CompleteScenario();
else
Log.outError(LogFilter.Scenario, "Scenario.CompleteStep: Scenario (id: {0}, step: {1}) was completed, but could not determine new step, or validate scenario completion.", step.ScenarioID, step.Id);
}
public virtual void CompleteScenario()
{
SendPacket(new ScenarioCompleted(_data.Entry.Id));
}
void SetStep(ScenarioStepRecord step)
{
_currentstep = step;
if (step != null)
SetStepState(step, ScenarioStepState.InProgress);
ScenarioState scenarioState = new ScenarioState();
BuildScenarioState(scenarioState);
SendPacket(scenarioState);
}
public virtual void OnPlayerEnter(Player player)
{
_players.Add(player.GetGUID());
SendScenarioState(player);
}
public virtual void OnPlayerExit(Player player)
{
_players.Remove(player.GetGUID());
SendBootPlayer(player);
}
bool IsComplete()
{
foreach (var step in _data.Steps.Values)
{
if (step.IsBonusObjective())
continue;
if (GetStepState(step) != ScenarioStepState.Done)
return false;
}
return true;
}
ScenarioStepState GetStepState(ScenarioStepRecord step)
{
if (!_stepStates.ContainsKey(step))
return ScenarioStepState.Invalid;
return _stepStates[step];
}
public override void SendCriteriaUpdate(Criteria criteria, CriteriaProgress progress, uint timeElapsed, bool timedCompleted)
{
ScenarioProgressUpdate progressUpdate = new ScenarioProgressUpdate();
progressUpdate.CriteriaProgress.Id = criteria.ID;
progressUpdate.CriteriaProgress.Quantity = progress.Counter;
progressUpdate.CriteriaProgress.Player = progress.PlayerGUID;
progressUpdate.CriteriaProgress.Date = progress.Date;
if (criteria.Entry.StartTimer != 0)
progressUpdate.CriteriaProgress.Flags = timedCompleted ? 1 : 0u;
progressUpdate.CriteriaProgress.TimeFromStart = timeElapsed;
progressUpdate.CriteriaProgress.TimeFromCreate = 0;
SendPacket(progressUpdate);
}
public override bool CanUpdateCriteriaTree(Criteria criteria, CriteriaTree tree, Player referencePlayer)
{
ScenarioStepRecord step = tree.ScenarioStep;
if (step == null)
return false;
if (step.ScenarioID != _data.Entry.Id)
return false;
ScenarioStepRecord currentStep = GetStep();
if (currentStep == null)
return false;
if (step.IsBonusObjective())
return true;
return currentStep == step;
}
public override bool CanCompleteCriteriaTree(CriteriaTree tree)
{
ScenarioStepRecord step = tree.ScenarioStep;
if (step == null)
return false;
if (step.ScenarioID != _data.Entry.Id)
return false;
if (step.IsBonusObjective())
return !IsComplete();
if (step != GetStep())
return false;
return true;
}
public override void CompletedCriteriaTree(CriteriaTree tree, Player referencePlayer)
{
ScenarioStepRecord step = tree.ScenarioStep;
if (step == null)
return;
if (!step.IsBonusObjective() && step != GetStep())
return;
if (GetStepState(step) == ScenarioStepState.Done)
return;
SetStepState(step, ScenarioStepState.Done);
CompleteStep(step);
}
public override void SendPacket(ServerPacket data)
{
foreach (ObjectGuid guid in _players)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player)
player.SendPacket(data);
}
}
void BuildScenarioState(ScenarioState scenarioState)
{
scenarioState.ScenarioID = (int)_data.Entry.Id;
ScenarioStepRecord step = GetStep();
if (step != null)
scenarioState.CurrentStep = (int)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
foreach (var state in _stepStates)
{
if (state.Key.IsBonusObjective())
continue;
switch (state.Value)
{
case ScenarioStepState.InProgress:
case ScenarioStepState.Done:
break;
case ScenarioStepState.NotStarted:
default:
continue;
}
scenarioState.PickedSteps.Add(state.Key.Id);
}
scenarioState.ScenarioComplete = IsComplete();
}
ScenarioStepRecord GetFirstStep()
{
// Do it like this because we don't know what order they're in inside the container.
ScenarioStepRecord firstStep = null;
foreach (var scenarioStep in _data.Steps.Values)
{
if (scenarioStep.IsBonusObjective())
continue;
if (firstStep == null || scenarioStep.OrderIndex < firstStep.OrderIndex)
firstStep = scenarioStep;
}
return firstStep;
}
public void SendScenarioState(Player player)
{
ScenarioState scenarioState = new ScenarioState();
BuildScenarioState(scenarioState);
player.SendPacket(scenarioState);
}
List<BonusObjectiveData> GetBonusObjectivesData()
{
List<BonusObjectiveData> bonusObjectivesData = new List<BonusObjectiveData>();
foreach (var step in _data.Steps.Values)
{
if (!step.IsBonusObjective())
continue;
if (Global.CriteriaMgr.GetCriteriaTree(step.CriteriaTreeId) != null)
{
BonusObjectiveData bonusObjectiveData;
bonusObjectiveData.BonusObjectiveID = (int)step.Id;
bonusObjectiveData.ObjectiveComplete = GetStepState(step) == ScenarioStepState.Done;
bonusObjectivesData.Add(bonusObjectiveData);
}
}
return bonusObjectivesData;
}
List<CriteriaProgressPkt> GetCriteriasProgress()
{
List<CriteriaProgressPkt> criteriasProgress = new List<CriteriaProgressPkt>();
if (!_criteriaProgress.Empty())
{
foreach (var pair in _criteriaProgress)
{
CriteriaProgressPkt criteriaProgress = new CriteriaProgressPkt();
criteriaProgress.Id = pair.Key;
criteriaProgress.Quantity = pair.Value.Counter;
criteriaProgress.Date = pair.Value.Date;
criteriaProgress.Player = pair.Value.PlayerGUID;
criteriasProgress.Add(criteriaProgress);
}
}
return criteriasProgress;
}
public override List<Criteria> GetCriteriaByType(CriteriaTypes type)
{
return Global.CriteriaMgr.GetScenarioCriteriaByType(type);
}
void SendBootPlayer(Player player)
{
ScenarioBoot scenarioBoot = new ScenarioBoot();
scenarioBoot.ScenarioID = (int)_data.Entry.Id;
player.SendPacket(scenarioBoot);
}
public virtual void Update(uint diff) { }
public void SetStepState(ScenarioStepRecord step, ScenarioStepState state) { _stepStates[step] = state; }
ScenarioStepRecord GetStep()
{
return _currentstep;
}
public override void SendCriteriaProgressRemoved(uint criteriaId) { }
public override void AfterCriteriaTreeUpdate(CriteriaTree tree, Player referencePlayer) { }
public override void SendAllData(Player receiver) { }
List<ObjectGuid> _players = new List<ObjectGuid>();
ScenarioData _data;
ScenarioStepRecord _currentstep;
Dictionary<ScenarioStepRecord, ScenarioStepState> _stepStates = new Dictionary<ScenarioStepRecord, ScenarioStepState>();
}
public enum ScenarioStepState
{
Invalid = 0,
NotStarted = 1,
InProgress = 2,
Done = 3
}
enum ScenarioType
{
Scenario = 0,
ChallengeMode = 1,
Solo = 2,
Dungeon = 10,
}
}