using System; using System.Collections.Generic; using Server.Mobiles; namespace Server.Engines.Quests { public class BaseQuest { public virtual bool AllObjectives { get { return true; } } public virtual bool DoneOnce { get { return false; } } public virtual TimeSpan RestartDelay { get { return TimeSpan.Zero; } } public virtual bool ForceRemember { get { return false; } } public virtual int AcceptSound { get { return 0x5B4; } } public virtual int ResignSound { get { return 0x5B3; } } public virtual int CompleteSound { get { return 0x5B5; } } public virtual int UpdateSound { get { return 0x5B6; } } public virtual int CompleteMessage { get { return 1072273; // You've completed a quest! Don't forget to collect your reward. } } #region Quest Chain public virtual QuestChain ChainID { get { return QuestChain.None; } } public virtual Type NextQuest { get { return null; } } #endregion public virtual object Title { get { return null; } } public virtual object Description { get { return null; } } public virtual object Refuse { get { return null; } } public virtual object Uncomplete { get { return null; } } public virtual object Complete { get { return null; } } public virtual object FailedMsg { get { return null; } } public virtual bool ShowDescription { get { return true; } } public virtual bool ShowRewards { get { return true; } } public virtual bool CanRefuseReward { get { return false; } } private List m_Objectives; private List m_Rewards; private PlayerMobile m_Owner; private object m_Quester; private Type m_QuesterType; private Timer m_Timer; public List Objectives { get { return m_Objectives; } } public List Rewards { get { return m_Rewards; } } public PlayerMobile Owner { get { return m_Owner; } set { m_Owner = value; } } public object Quester { get { return m_Quester; } set { m_Quester = value; if (m_Quester != null) m_QuesterType = m_Quester.GetType(); } } public Type QuesterType { get { return m_QuesterType; } set { m_QuesterType = value; } } public BaseQuestItem StartingItem { get { return m_Quester is BaseQuestItem ? (BaseQuestItem)m_Quester : null; } } public MondainQuester StartingMobile { get { return m_Quester is MondainQuester ? (MondainQuester)m_Quester : null; } } public bool Completed { get { for (int i = 0; i < m_Objectives.Count; i++) { if (m_Objectives[i].Completed) { if (!AllObjectives) return true; } else { if (AllObjectives) return false; } } return AllObjectives; } } public bool Failed { get { for (int i = 0; i < m_Objectives.Count; i++) { if (m_Objectives[i].Failed) { if (AllObjectives) return true; } else { if (!AllObjectives) return false; } } return !AllObjectives; } } public BaseQuest() { m_Objectives = new List(); m_Rewards = new List(); } public void StartTimer() { if (m_Timer != null) return; m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), new TimerCallback(Slice)); } public void StopTimer() { if (m_Timer != null) m_Timer.Stop(); m_Timer = null; } public virtual void Slice() { for (int i = 0; i < m_Objectives.Count; i ++) { BaseObjective obj = m_Objectives[i]; obj.UpdateTime(); } } public virtual void OnObjectiveUpdate(Item item) { } public virtual bool CanOffer() { return true; } public virtual void UpdateChain() { if (ChainID != QuestChain.None && StartingMobile != null) { if (m_Owner.Chains.ContainsKey(ChainID)) { BaseChain chain = m_Owner.Chains[ChainID]; chain.CurrentQuest = GetType(); chain.Quester = StartingMobile.GetType(); } else { m_Owner.Chains.Add(ChainID, new BaseChain(GetType(), StartingMobile.GetType())); } } } public virtual void OnAccept() { m_Owner.PlaySound(AcceptSound); m_Owner.SendLocalizedMessage(1049019); // You have accepted the Quest. m_Owner.Quests.Add(this); // give items if any for (int i = 0; i < m_Objectives.Count; i ++) { BaseObjective objective = m_Objectives[i]; objective.OnAccept(); } if (m_Quester is BaseEscort) { BaseEscort escort = (BaseEscort)m_Quester; if (escort.SetControlMaster(m_Owner)) { escort.Quest = this; escort.LastSeenEscorter = DateTime.UtcNow; escort.StartFollow(); escort.AddHash(Owner); Region region = escort.GetDestination(); if (region != null) escort.Say(1042806, region.Name); // Lead on! Payment will be made when we arrive at ~1_DESTINATION~! else escort.Say(1042806, "destination"); // Lead on! Payment will be made when we arrive at ~1_DESTINATION~! m_Owner.LastEscortTime = DateTime.UtcNow; } } // tick tack StartTimer(); } public virtual void OnRefuse() { if (!QuestHelper.FirstChainQuest(this, Quester)) UpdateChain(); } public virtual void OnResign(bool resignChain) { m_Owner.PlaySound(ResignSound); // update chain if (!resignChain && !QuestHelper.FirstChainQuest(this, Quester)) UpdateChain(); // delete items that were given on quest start for (int i = 0; i < m_Objectives.Count; i ++) { if (m_Objectives[i] is ObtainObjective) { ObtainObjective obtain = (ObtainObjective)m_Objectives[i]; QuestHelper.RemoveStatus(m_Owner, obtain.Obtain); } else if (m_Objectives[i] is DeliverObjective) { DeliverObjective deliver = (DeliverObjective)m_Objectives[i]; QuestHelper.DeleteItems(m_Owner, deliver.Delivery, deliver.MaxProgress, true); } } // delete escorter if (m_Quester is BaseEscort) { BaseEscort escort = (BaseEscort)m_Quester; escort.Say(1005653); // Hmmm. I seem to have lost my master. escort.PlaySound(0x5B3); escort.BeginDelete(m_Owner); } RemoveQuest(resignChain); } public virtual void InProgress() { } public virtual void OnCompleted() { m_Owner.SendLocalizedMessage(CompleteMessage, null, 0x23); // You've completed a quest! Don't forget to collect your reward. m_Owner.PlaySound(CompleteSound); } public virtual void GiveRewards() { // give rewards for (int i = 0; i < m_Rewards.Count; i ++) { Type type = m_Rewards[i].Type; m_Rewards[i].GiveReward(); if (type == null) continue; Item reward; try { reward = Activator.CreateInstance(type) as Item; } catch { reward = null; } if (reward != null) { if (reward.Stackable) { reward.Amount = m_Rewards[i].Amount; m_Rewards[i].Amount = 1; } for (int j = 0; j < m_Rewards[i].Amount; j ++) { if (!m_Owner.PlaceInBackpack(reward)) { reward.MoveToWorld(m_Owner.Location, m_Owner.Map); } if (m_Rewards[i].Name is int) m_Owner.SendLocalizedMessage(1074360, "#" + (int)m_Rewards[i].Name); // You receive a reward: ~1_REWARD~ else if (m_Rewards[i].Name is string) m_Owner.SendLocalizedMessage(1074360, (string)m_Rewards[i].Name); // You receive a reward: ~1_REWARD~ // already marked, we need to see if this gives progress to another quest. if (reward.QuestItem) { QuestHelper.CheckRewardItem(Owner, reward); } } } } // remove quest if (NextQuest == null) RemoveQuest(true); else RemoveQuest(); // offer next quest if present if (NextQuest != null) { BaseQuest quest = QuestHelper.RandomQuest(m_Owner, new Type[] { NextQuest }, StartingMobile); if (quest != null && quest.ChainID == ChainID) m_Owner.SendGump(new MondainQuestGump(quest)); } if (this is ITierQuest) { TierQuestInfo.CompleteQuest(Owner, (ITierQuest)this); } EventSink.InvokeQuestComplete(new QuestCompleteEventArgs(Owner, GetType())); } public virtual void RefuseRewards() { // remove quest if (NextQuest == null) RemoveQuest(true); else RemoveQuest(); // offer next quest if present if (NextQuest != null) { BaseQuest quest = QuestHelper.RandomQuest(m_Owner, new Type[] { NextQuest }, StartingMobile); if (quest != null && quest.ChainID == ChainID) m_Owner.SendGump(new MondainQuestGump(quest)); } } public virtual void AddObjective(BaseObjective objective) { if (m_Objectives == null) m_Objectives = new List(); if (objective != null) { objective.Quest = this; m_Objectives.Add(objective); } } public virtual void AddReward(BaseReward reward) { if (m_Rewards == null) m_Rewards = new List(); if (reward != null) { reward.Quest = this; m_Rewards.Add(reward); } } public virtual void RemoveQuest() { RemoveQuest(false); } public virtual void RemoveQuest(bool removeChain) { StopTimer(); if (removeChain) m_Owner.Chains.Remove(ChainID); if (Completed && (RestartDelay > TimeSpan.Zero || ForceRemember || DoneOnce) && NextQuest == null && Owner.AccessLevel == AccessLevel.Player) { Type type = GetType(); if (ChainID != QuestChain.None) type = QuestHelper.FindFirstChainQuest(this); QuestHelper.Delay(Owner, type, RestartDelay); } QuestHelper.RemoveAcceleratedSkillgain(Owner); if (m_Owner.Quests.Contains(this)) { m_Owner.Quests.Remove(this); } } public virtual bool RenderDescription(MondainQuestGump g, bool offer) { return false; } public virtual bool RenderObjective(MondainQuestGump g, bool offer) { return false; } public virtual void Serialize(GenericWriter writer) { writer.WriteEncodedInt((int)1); // version writer.Write(m_QuesterType == null ? null : m_QuesterType.Name); if (m_Quester == null) writer.Write((int)0x0); else if (m_Quester is Mobile) { writer.Write((int)0x1); writer.Write((Mobile)m_Quester); } else if (m_Quester is Item) { writer.Write((int)0x2); writer.Write((Item)m_Quester); } for (int i = 0; i < m_Objectives.Count; i ++) { BaseObjective objective = m_Objectives[i]; objective.Serialize(writer); } } public virtual void Deserialize(GenericReader reader) { int version = reader.ReadEncodedInt(); if (version > 0) { string questerType = reader.ReadString(); if(questerType != null) m_QuesterType = ScriptCompiler.FindTypeByName(questerType); } switch ( reader.ReadInt() ) { case 0x0: m_Quester = null; break; case 0x1: m_Quester = reader.ReadMobile() as MondainQuester; break; case 0x2: m_Quester = reader.ReadItem() as BaseQuestItem; break; } if (m_Quester is BaseEscort) { BaseEscort escort = (BaseEscort)m_Quester; escort.Quest = this; } else if (m_Quester is BaseQuestItem) { BaseQuestItem item = (BaseQuestItem)m_Quester; item.Quest = this; } if (version == 0 && m_Quester != null) { m_QuesterType = m_Quester.GetType(); } for (int i = 0; i < m_Objectives.Count; i ++) { BaseObjective objective = m_Objectives[i]; objective.Deserialize(reader); } } } }