コード例 #1
0
        private static void OnMarkQuestItem(PlayerMobile pm, Item item, Type type)
        {
            MLQuestContext context = GetContext(pm);

            if (context == null)
            {
                return;
            }

            List <MLQuestInstance> instances = context.QuestInstances;

            // We don't foreach because CheckComplete() can potentially modify the MLQuests list
            for (int i = instances.Count - 1; i >= 0; --i)
            {
                MLQuestInstance instance = instances[i];

                if (instance.ClaimReward)
                {
                    continue;
                }

                foreach (BaseObjectiveInstance objective in instance.Objectives)
                {
                    if (!objective.Expired && objective.AllowsQuestItem(item, type))
                    {
                        objective.CheckComplete(); // yes, this can happen multiple times (for multiple quests)
                        break;
                    }
                }
            }
        }
コード例 #2
0
        public static void HandleSkillGain(PlayerMobile pm, SkillName skill)
        {
            MLQuestContext context = GetContext(pm);

            if (context == null)
            {
                return;
            }

            List <MLQuestInstance> instances = context.QuestInstances;

            for (int i = instances.Count - 1; i >= 0; --i)
            {
                MLQuestInstance instance = instances[i];

                if (instance.ClaimReward)
                {
                    continue;
                }

                foreach (BaseObjectiveInstance objective in instance.Objectives)
                {
                    if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance &&
                        objectiveInstance.Handles(skill))
                    {
                        objectiveInstance.CheckComplete();
                        break;
                    }
                }
            }
        }
コード例 #3
0
        public static void HandleDeath(PlayerMobile pm)
        {
            MLQuestContext context = GetContext(pm);

            if (context != null)
            {
                context.HandleDeath();
            }
        }
コード例 #4
0
        public static MLQuestContext GetOrCreateContext(PlayerMobile pm)
        {
            if (!Contexts.TryGetValue(pm, out MLQuestContext context))
            {
                Contexts[pm] = context = new MLQuestContext(pm);
            }

            return(context);
        }
コード例 #5
0
        public static void HandleDeletion(PlayerMobile pm)
        {
            MLQuestContext context = GetContext(pm);

            if (context != null)
            {
                context.HandleDeletion();
                Contexts.Remove(pm);
            }
        }
コード例 #6
0
        private static bool FindQuest(
            IQuestGiver quester, PlayerMobile pm, MLQuestContext context, out MLQuest quest,
            out MLQuestInstance entry
            )
        {
            quest = null;
            entry = null;

            var quests      = quester.MLQuests;
            var questerType = quester.GetType();

            // 1. Check quests in progress with this NPC (overriding deliveries is intended)
            if (context != null)
            {
                foreach (var questEntry in quests)
                {
                    var instance = context.FindInstance(questEntry);

                    if (instance != null && (instance.Quester == quester ||
                                             !questEntry.IsEscort && instance.QuesterType == questerType))
                    {
                        entry = instance;
                        quest = questEntry;
                        return(true);
                    }
                }
            }

            // 2. Check deliveries (overriding chain offers is intended)
            if ((entry = HandleDelivery(pm, quester, questerType)) != null)
            {
                quest = entry.Quest;
                return(true);
            }

            // 3. Check chain quest offers
            if (context != null)
            {
                foreach (var questEntry in quests)
                {
                    if (questEntry.IsChainTriggered && context.ChainOffers.Contains(questEntry))
                    {
                        quest = questEntry;
                        return(true);
                    }
                }
            }

            // 4. Random quest
            quest = RandomStarterQuest(quester, pm, context);

            return(quest != null);
        }
コード例 #7
0
        public static MLQuestInstance HandleDelivery(PlayerMobile pm, IQuestGiver quester, Type questerType)
        {
            MLQuestContext context = GetContext(pm);

            if (context == null)
            {
                return(null);
            }

            List <MLQuestInstance> instances       = context.QuestInstances;
            MLQuestInstance        deliverInstance = null;

            for (int i = instances.Count - 1; i >= 0; --i)
            {
                MLQuestInstance instance = instances[i];

                // Do NOT skip quests on ClaimReward, because the quester still needs the quest ref!
                //if ( instance.ClaimReward )
                //	continue;

                foreach (BaseObjectiveInstance objective in instance.Objectives)
                {
                    // Note: On OSI, expired deliveries can still be completed. Bug?
                    if (!objective.Expired && objective is DeliverObjectiveInstance)
                    {
                        DeliverObjectiveInstance deliver = (DeliverObjectiveInstance)objective;

                        if (deliver.IsDestination(quester, questerType))
                        {
                            if (!deliver.HasCompleted)                             // objective completes only once
                            {
                                deliver.HasCompleted = true;
                                deliver.CheckComplete();

                                // The quest is continued with this NPC (important for chains)
                                instance.Quester = quester;
                            }

                            if (deliverInstance == null)
                            {
                                deliverInstance = instance;
                            }

                            break;                             // don't return, we may have to complete more deliveries
                        }
                    }
                }
            }

            return(deliverInstance);
        }
コード例 #8
0
        public static bool CanMarkQuestItem(PlayerMobile pm, Item item, Type type)
        {
            MLQuestContext context = GetContext(pm);

            if (context != null)
            {
                foreach (MLQuestInstance quest in context.QuestInstances)
                {
                    if (!quest.ClaimReward && quest.AllowsQuestItem(item, type))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #9
0
        public static void HandleKill(PlayerMobile pm, Mobile mob)
        {
            MLQuestContext context = GetContext(pm);

            if (context == null)
            {
                return;
            }

            List <MLQuestInstance> instances = context.QuestInstances;

            Type type = null;

            for (int i = instances.Count - 1; i >= 0; --i)
            {
                MLQuestInstance instance = instances[i];

                if (instance.ClaimReward)
                {
                    continue;
                }

                /* A kill only counts for a single objective within a quest,
                 * but it can count for multiple quests. This is something not
                 * currently observable on OSI, so it is assumed behavior.
                 */
                foreach (BaseObjectiveInstance objective in instance.Objectives)
                {
                    if (!objective.Expired && objective is KillObjectiveInstance)
                    {
                        KillObjectiveInstance kill = (KillObjectiveInstance)objective;

                        if (type == null)
                        {
                            type = mob.GetType();
                        }

                        if (kill.AddKill(mob, type))
                        {
                            kill.CheckComplete();
                            break;
                        }
                    }
                }
            }
        }
コード例 #10
0
        public static void OnDoubleClick(IQuestGiver quester, PlayerMobile pm)
        {
            if (quester.Deleted || !pm.Alive)
            {
                return;
            }

            MLQuestContext context = GetContext(pm);

            MLQuest         quest;
            MLQuestInstance entry;

            if (!FindQuest(quester, pm, context, out quest, out entry))
            {
                Tell(quester, pm, 1080107);                   // I'm sorry, I have nothing for you at this time.
                return;
            }

            if (entry != null)
            {
                TurnToFace(quester, pm);

                if (entry.Failed)
                {
                    return;                     // Note: OSI sends no gump at all for failed quests, they have to be cancelled in the quest overview
                }
                else if (entry.ClaimReward)
                {
                    entry.SendRewardOffer();
                }
                else if (entry.IsCompleted())
                {
                    entry.SendReportBackGump();
                }
                else
                {
                    entry.SendProgressGump();
                }
            }
            else if (quest.CanOffer(quester, pm, context, true))
            {
                TurnToFace(quester, pm);

                quest.SendOffer(quester, pm);
            }
        }
コード例 #11
0
		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();
			int contexts = reader.ReadInt();

			for ( int i = 0; i < contexts; ++i )
			{
				MLQuestContext context = new MLQuestContext( reader, version );

				if ( context.Owner != null )
					MLQuestSystem.Contexts[context.Owner] = context;
			}

			int quests = reader.ReadInt();

			for ( int i = 0; i < quests; ++i )
				MLQuest.Deserialize( reader, version );
		}
コード例 #12
0
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version  = reader.ReadInt();
            int contexts = reader.ReadInt();

            for (int i = 0; i < contexts; ++i)
            {
                MLQuestContext context = new MLQuestContext(reader, version);

                if (context.Owner != null)
                {
                    MLQuestSystem.Contexts[context.Owner] = context;
                }
            }

            int quests = reader.ReadInt();

            for (int i = 0; i < quests; ++i)
            {
                MLQuest.Deserialize(reader, version);
            }
        }
コード例 #13
0
		public static MLQuest RandomStarterQuest( IQuestGiver quester, PlayerMobile pm, MLQuestContext context )
		{
			List<MLQuest> quests = quester.MLQuests;

			if ( quests.Count == 0 )
				return null;

			m_EligiblePool.Clear();
			MLQuest fallback = null;

			foreach ( MLQuest quest in quests )
			{
				if ( quest.IsChainTriggered || ( context != null && context.IsDoingQuest( quest ) ) )
					continue;

				/*
				 * Save first quest that reaches the CanOffer call.
				 * If no quests are valid at all, return this quest for displaying the CanOffer error message.
				 */
				if ( fallback == null )
					fallback = quest;

				if ( quest.CanOffer( quester, pm, context, false ) )
					m_EligiblePool.Add( quest );
			}

			if ( m_EligiblePool.Count == 0 )
				return fallback;

			return m_EligiblePool[Utility.Random( m_EligiblePool.Count )];
		}
コード例 #14
0
		public static MLQuestContext GetOrCreateContext( PlayerMobile pm )
		{
			MLQuestContext context;

			if ( !m_Contexts.TryGetValue( pm, out context ) )
				m_Contexts[pm] = context = new MLQuestContext( pm );

			return context;
		}
コード例 #15
0
ファイル: MLQuestEntry.cs プロジェクト: nogu3ira/runuo-1
        public void ClaimRewards()
        {
            if (m_Quest == null || m_Player == null || m_Player.Deleted || !ClaimReward || Removed)
            {
                return;
            }

            List <Item> rewards = new List <Item>();

            foreach (BaseReward reward in m_Quest.Rewards)
            {
                reward.AddRewardItems(m_Player, rewards);
            }

            if (rewards.Count != 0)
            {
                // On OSI a more naive method of checking is used.
                // For containers, only the actual container item counts.
                bool canFit = true;

                foreach (Item rewardItem in rewards)
                {
                    if (!m_Player.AddToBackpack(rewardItem))
                    {
                        canFit = false;
                        break;
                    }
                }

                if (!canFit)
                {
                    foreach (Item rewardItem in rewards)
                    {
                        rewardItem.Delete();
                    }

                    m_Player.SendLocalizedMessage(1078524);                       // Your backpack is full. You cannot complete the quest and receive your reward.
                    return;
                }

                foreach (Item rewardItem in rewards)
                {
                    string rewardName = (rewardItem.Name != null) ? rewardItem.Name : String.Concat("#", rewardItem.LabelNumber);

                    if (rewardItem.Stackable)
                    {
                        m_Player.SendLocalizedMessage(1115917, String.Concat(rewardItem.Amount, "\t", rewardName));                             // You receive a reward: ~1_QUANTITY~ ~2_ITEM~
                    }
                    else
                    {
                        m_Player.SendLocalizedMessage(1074360, rewardName);                           // You receive a reward: ~1_REWARD~
                    }
                }
            }

            foreach (BaseObjectiveInstance objective in m_ObjectiveInstances)
            {
                objective.OnRewardClaimed();
            }

            m_Quest.OnRewardClaimed(this);

            MLQuestContext context = PlayerContext;

            if (m_Quest.RecordCompletion && !m_Quest.HasRestartDelay)               // Quests with restart delays are logged earlier as per OSI
            {
                context.SetDoneQuest(m_Quest);
            }

            if (m_Quest.IsChainTriggered)
            {
                context.ChainOffers.Remove(m_Quest);
            }

            Type nextQuestType = m_Quest.NextQuest;

            if (nextQuestType != null)
            {
                MLQuest nextQuest = MLQuestSystem.FindQuest(nextQuestType);

                if (nextQuest != null && !context.ChainOffers.Contains(nextQuest))
                {
                    context.ChainOffers.Add(nextQuest);
                }
            }

            Remove();
        }
コード例 #16
0
        public static void HandleDeath(PlayerMobile pm)
        {
            MLQuestContext context = GetContext(pm);

            context?.HandleDeath();
        }
コード例 #17
0
ファイル: MLQuest.cs プロジェクト: nogu3ira/runuo-1
        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);
        }
コード例 #18
0
        public static MLQuest RandomStarterQuest(IQuestGiver quester, PlayerMobile pm, MLQuestContext context)
        {
            List <MLQuest> quests = quester.MLQuests;

            if (quests.Count == 0)
            {
                return(null);
            }

            m_EligiblePool.Clear();
            MLQuest fallback = null;

            foreach (MLQuest quest in quests)
            {
                if (quest.IsChainTriggered || context?.IsDoingQuest(quest) == true)
                {
                    continue;
                }

                /*
                 * Save first quest that reaches the CanOffer call.
                 * If no quests are valid at all, return this quest for displaying the CanOffer error message.
                 */
                fallback ??= quest;

                if (quest.CanOffer(quester, pm, context, false))
                {
                    m_EligiblePool.Add(quest);
                }
            }

            return(m_EligiblePool.Count == 0 ? fallback : m_EligiblePool[Utility.Random(m_EligiblePool.Count)]);
        }
コード例 #19
0
		private static bool FindQuest( IQuestGiver quester, PlayerMobile pm, MLQuestContext context, out MLQuest quest, out MLQuestInstance entry )
		{
			quest = null;
			entry = null;

			List<MLQuest> quests = quester.MLQuests;
			Type questerType = quester.GetType();

			// 1. Check quests in progress with this NPC (overriding deliveries is intended)
			if ( context != null )
			{
				foreach ( MLQuest questEntry in quests )
				{
					MLQuestInstance instance = context.FindInstance( questEntry );

					if ( instance != null && ( instance.Quester == quester || ( !questEntry.IsEscort && instance.QuesterType == questerType ) ) )
					{
						entry = instance;
						quest = questEntry;
						return true;
					}
				}
			}

			// 2. Check deliveries (overriding chain offers is intended)
			if ( ( entry = HandleDelivery( pm, quester, questerType ) ) != null )
			{
				quest = entry.Quest;
				return true;
			}

			// 3. Check chain quest offers
			if ( context != null )
			{
				foreach ( MLQuest questEntry in quests )
				{
					if ( questEntry.IsChainTriggered && context.ChainOffers.Contains( questEntry ) )
					{
						quest = questEntry;
						return true;
					}
				}
			}

			// 4. Random quest
			quest = RandomStarterQuest( quester, pm, context );

			return ( quest != null );
		}