using System; using System.Collections.Generic; using Server; using Server.Engines.MLQuests.Gumps; using Server.Engines.MLQuests.Objectives; using Server.Engines.MLQuests.Rewards; using Server.Mobiles; namespace Server.Engines.MLQuests { public enum ObjectiveType { All, Any } public class MLQuest { private bool m_Deserialized; private bool m_SaveEnabled; public bool Deserialized { get { return m_Deserialized; } set { m_Deserialized = value; } } public bool SaveEnabled { get { return m_SaveEnabled; } set { m_SaveEnabled = value; } } private bool m_Activated; private List m_Objectives; private ObjectiveType m_ObjectiveType; private List m_Rewards; private List m_Instances; private TextDefinition m_Title; private TextDefinition m_Description; private TextDefinition m_RefuseMessage; private TextDefinition m_InProgressMessage; private TextDefinition m_CompletionMessage; private TextDefinition m_CompletionNotice; // TODO: Flags? (Deserialized, SaveEnabled, Activated) private bool m_OneTimeOnly; private bool m_HasRestartDelay; public bool Activated { get { return m_Activated; } set { m_Activated = value; } } public List Objectives { get { return m_Objectives; } set { m_Objectives = value; } } public ObjectiveType ObjectiveType { get { return m_ObjectiveType; } set { m_ObjectiveType = value; } } public List Rewards { get { return m_Rewards; } set { m_Rewards = value; } } public List Instances { get { return m_Instances; } set { m_Instances = value; } } public bool OneTimeOnly { get { return m_OneTimeOnly; } set { m_OneTimeOnly = value; } } public bool HasRestartDelay { get { return m_HasRestartDelay; } set { m_HasRestartDelay = value; } } public bool HasObjective() where T : BaseObjective { foreach ( BaseObjective obj in m_Objectives ) { if ( obj is T ) return true; } return false; } public bool IsEscort { get { return HasObjective(); } } public bool IsSkillTrainer { get { return HasObjective(); } } public bool RequiresCollection { get { return HasObjective() || HasObjective(); } } public virtual bool RecordCompletion { get { return ( m_OneTimeOnly || m_HasRestartDelay ); } } public virtual bool IsChainTriggered { get { return false; } } public virtual Type NextQuest { get { return null; } } public TextDefinition Title { get { return m_Title; } set { m_Title = value; } } public TextDefinition Description { get { return m_Description; } set { m_Description = value; } } public TextDefinition RefusalMessage { get { return m_RefuseMessage; } set { m_RefuseMessage = value; } } public TextDefinition InProgressMessage { get { return m_InProgressMessage; } set { m_InProgressMessage = value; } } public TextDefinition CompletionMessage { get { return m_CompletionMessage; } set { m_CompletionMessage = value; } } public TextDefinition CompletionNotice { get { return m_CompletionNotice; } set { m_CompletionNotice = value; } } public static readonly TextDefinition CompletionNoticeDefault = new TextDefinition( 1072273 ); // You've completed a quest! Don't forget to collect your reward. public static readonly TextDefinition CompletionNoticeShort = new TextDefinition( 1046258 ); // Your quest is complete. public static readonly TextDefinition CompletionNoticeShortReturn = new TextDefinition( 1073775 ); // Your quest is complete. Return for your reward. public static readonly TextDefinition CompletionNoticeCraft = new TextDefinition( 1073967 ); // You obtained what you seek, now receive your reward. public MLQuest() { m_Activated = false; m_Objectives = new List(); m_ObjectiveType = ObjectiveType.All; m_Rewards = new List(); m_CompletionNotice = CompletionNoticeDefault; m_Instances = new List(); m_SaveEnabled = true; } public virtual void Generate() { if ( MLQuestSystem.Debug ) Console.WriteLine( "INFO: Generating quest: {0}", GetType() ); } #region Generation Methods public void PutSpawner( Spawner s, Point3D loc, Map map ) { string name = String.Format( "MLQS-{0}", GetType().Name ); // Auto cleanup on regeneration List toDelete = new List(); foreach ( Item item in map.GetItemsInRange( loc, 0 ) ) { if ( item is Spawner && item.Name == name ) toDelete.Add( item ); } foreach ( Item item in toDelete ) item.Delete(); s.Name = name; s.MoveToWorld( loc, map ); } public void PutDeco( Item deco, Point3D loc, Map map ) { // Auto cleanup on regeneration List toDelete = new List(); foreach ( Item item in map.GetItemsInRange( loc, 0 ) ) { if ( item.ItemID == deco.ItemID && item.Z == loc.Z ) toDelete.Add( item ); } foreach ( Item item in toDelete ) item.Delete(); deco.MoveToWorld( loc, map ); } #endregion public MLQuestInstance CreateInstance( IQuestGiver quester, PlayerMobile pm ) { return new MLQuestInstance( this, quester, pm ); } public bool CanOffer( IQuestGiver quester, PlayerMobile pm, bool message ) { return CanOffer( quester, pm, MLQuestSystem.GetContext( pm ), message ); } public virtual bool CanOffer( IQuestGiver quester, PlayerMobile pm, MLQuestContext context, bool message ) { if ( !m_Activated || quester.Deleted ) return false; if ( context != null ) { if ( context.IsFull ) { if ( message ) MLQuestSystem.Tell( quester, pm, 1080107 ); // I'm sorry, I have nothing for you at this time. return false; } MLQuest checkQuest = this; while ( checkQuest != null ) { DateTime nextAvailable; if ( context.HasDoneQuest( checkQuest, out nextAvailable ) ) { if ( checkQuest.OneTimeOnly ) { if ( message ) MLQuestSystem.Tell( quester, pm, 1075454 ); // I cannot offer you the quest again. return false; } else if ( nextAvailable > DateTime.UtcNow ) { if ( message ) MLQuestSystem.Tell( quester, pm, 1075575 ); // I'm sorry, but I don't have anything else for you right now. Could you check back with me in a few minutes? return false; } } if ( checkQuest.NextQuest == null ) break; checkQuest = MLQuestSystem.FindQuest( checkQuest.NextQuest ); } } foreach ( BaseObjective obj in m_Objectives ) { if ( !obj.CanOffer( quester, pm, message ) ) return false; } return true; } public virtual void SendOffer( IQuestGiver quester, PlayerMobile pm ) { pm.SendGump( new QuestOfferGump( this, quester, pm ) ); } public virtual void OnAccept( IQuestGiver quester, PlayerMobile pm ) { if ( !CanOffer( quester, pm, true ) ) return; MLQuestInstance instance = CreateInstance( quester, pm ); pm.SendLocalizedMessage( 1049019 ); // You have accepted the Quest. pm.SendSound( 0x2E7 ); // private sound OnAccepted( instance ); foreach ( BaseObjectiveInstance obj in instance.Objectives ) obj.OnQuestAccepted(); } public virtual void OnAccepted( MLQuestInstance instance ) { } public virtual void OnRefuse( IQuestGiver quester, PlayerMobile pm ) { pm.SendGump( new QuestConversationGump( this, pm, RefusalMessage ) ); } public virtual void GetRewards( MLQuestInstance instance ) { instance.SendRewardGump(); } public virtual void OnRewardClaimed( MLQuestInstance instance ) { } public virtual void OnCancel( MLQuestInstance instance ) { } public virtual void OnQuesterDeleted( MLQuestInstance instance ) { } public virtual void OnPlayerDeath( MLQuestInstance instance ) { } public virtual TimeSpan GetRestartDelay() { return TimeSpan.FromSeconds( Utility.Random( 1, 5 ) * 30 ); } public static void Serialize( GenericWriter writer, MLQuest quest ) { MLQuestSystem.WriteQuestRef( writer, quest ); writer.Write( quest.Version ); } public static void Deserialize( GenericReader reader, int version ) { MLQuest quest = MLQuestSystem.ReadQuestRef( reader ); int oldVersion = reader.ReadInt(); if ( quest == null ) return; // not saved or no longer exists quest.Refresh( oldVersion ); quest.m_Deserialized = true; } public virtual int Version { get { return 0; } } public virtual void Refresh( int oldVersion ) { } } }