public static MLQuestInstance Deserialize(GenericReader reader, int version, PlayerMobile pm) { MLQuest quest = MLQuestSystem.ReadQuestRef(reader); // TODO: Serialize quester TYPE too, the quest giver reference then becomes optional (only for escorts) IQuestGiver quester = World.FindEntity(reader.ReadInt()) as IQuestGiver; bool claimReward = reader.ReadBool(); int objectives = reader.ReadInt(); MLQuestInstance instance; if (quest != null && quester != null && pm != null) { instance = quest.CreateInstance(quester, pm); instance.ClaimReward = claimReward; } else { instance = null; } for (int i = 0; i < objectives; ++i) { BaseObjectiveInstance.Deserialize(reader, version, (instance != null && i < instance.Objectives.Length) ? instance.Objectives[i] : null); } if (instance != null) { instance.Slice(); } return(instance); }
public MLQuestInstance(MLQuest quest, IQuestGiver quester, PlayerMobile player) { m_Quest = quest; m_Quester = quester; m_QuesterType = (quester == null) ? null : quester.GetType(); m_Player = player; m_Accepted = DateTime.UtcNow; m_Flags = MLQuestInstanceFlags.None; m_ObjectiveInstances = new BaseObjectiveInstance[quest.Objectives.Count]; BaseObjectiveInstance obj; bool timed = false; for (int i = 0; i < quest.Objectives.Count; ++i) { m_ObjectiveInstances[i] = obj = quest.Objectives[i].CreateInstance(this); if (obj.IsTimed) { timed = true; } } Register(); if (timed) { m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), Slice); } }
public static void Register(MLQuest quest, params Type[] questerTypes) { Register(quest.GetType(), quest); foreach (Type questerType in questerTypes) { RegisterQuestGiver(quest, questerType); } }
private static void RegisterQuestGiver(MLQuest quest, Type questerType) { List <MLQuest> questList; if (!m_QuestGivers.TryGetValue(questerType, out questList)) { m_QuestGivers[questerType] = questList = new List <MLQuest>(); } questList.Add(quest); }
public static MLDoneQuestInfo Deserialize(GenericReader reader, int version) { MLQuest quest = MLQuestSystem.ReadQuestRef(reader); DateTime nextAvailable = reader.ReadDateTime(); if (quest == null || !quest.RecordCompletion) { return(null); // forget about this record } return(new MLDoneQuestInfo(quest, nextAvailable)); }
public MLQuestInstance FindInstance(Type questType) { MLQuest quest = MLQuestSystem.FindQuest(questType); if (quest == null) { return(null); } return(FindInstance(quest)); }
public bool HasDoneQuest(MLQuest quest) { foreach (MLDoneQuestInfo info in m_DoneQuests) { if (info.m_Quest == quest) { return(true); } } return(false); }
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 MLQuestInstance FindInstance(MLQuest quest) { foreach (MLQuestInstance instance in m_QuestInstances) { if (instance.Quest == quest) { return(instance); } } return(null); }
public void RemoveDoneQuest(MLQuest quest) { for (int i = m_DoneQuests.Count - 1; i >= 0; --i) { MLDoneQuestInfo info = m_DoneQuests[i]; if (info.m_Quest == quest) { m_DoneQuests.RemoveAt(i); } } }
public void SetDoneQuest(MLQuest quest, DateTime nextAvailable) { foreach (MLDoneQuestInfo info in m_DoneQuests) { if (info.m_Quest == quest) { info.m_NextAvailable = nextAvailable; return; } } m_DoneQuests.Add(new MLDoneQuestInfo(quest, nextAvailable)); }
public bool HasDoneQuest(MLQuest quest, out DateTime nextAvailable) { nextAvailable = DateTime.MinValue; foreach (MLDoneQuestInfo info in m_DoneQuests) { if (info.m_Quest == quest) { nextAvailable = info.m_NextAvailable; return(true); } } return(false); }
public MLQuestContext(GenericReader reader, int version) { m_Owner = reader.ReadMobile <PlayerMobile>(); m_QuestInstances = new List <MLQuestInstance>(); m_DoneQuests = new List <MLDoneQuestInfo>(); m_ChainOffers = new List <MLQuest>(); int instances = reader.ReadInt(); for (int i = 0; i < instances; ++i) { MLQuestInstance instance = MLQuestInstance.Deserialize(reader, version, m_Owner); if (instance != null) { m_QuestInstances.Add(instance); } } int doneQuests = reader.ReadInt(); for (int i = 0; i < doneQuests; ++i) { MLDoneQuestInfo info = MLDoneQuestInfo.Deserialize(reader, version); if (info != null) { m_DoneQuests.Add(info); } } int chainOffers = reader.ReadInt(); for (int i = 0; i < chainOffers; ++i) { MLQuest quest = MLQuestSystem.ReadQuestRef(reader); if (quest != null && quest.IsChainTriggered) { m_ChainOffers.Add(quest); } } m_Flags = (MLQuestFlag)reader.ReadEncodedInt(); }
public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write((int)2); // version writer.Write(MLQuestSystem.Contexts.Count); foreach (MLQuestContext context in MLQuestSystem.Contexts.Values) { context.Serialize(writer); } writer.Write(MLQuestSystem.Quests.Count); foreach (MLQuest quest in MLQuestSystem.Quests.Values) { MLQuest.Serialize(writer, quest); } }
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)]); }
// TODO: Split next quest stuff from SendRewardGump stuff? public void SendRewardGump() { Type nextQuestType = m_Quest.NextQuest; if (nextQuestType != null) { ClaimRewards(); // skip reward gump if (Removed) // rewards were claimed successfully { MLQuest nextQuest = MLQuestSystem.FindQuest(nextQuestType); if (nextQuest != null) { nextQuest.SendOffer(m_Quester, m_Player); } } } else { m_Player.SendGump(new QuestRewardGump(this)); } }
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); } }
public bool HasDoneQuest(Type questType) { MLQuest quest = MLQuestSystem.FindQuest(questType); return(quest != null && HasDoneQuest(quest)); }
public bool IsDoingQuest(Type questType) { MLQuest quest = MLQuestSystem.FindQuest(questType); return(quest != null && IsDoingQuest(quest)); }
public void SetDoneQuest(MLQuest quest) { SetDoneQuest(quest, DateTime.MinValue); }
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 static void Serialize(GenericWriter writer, MLQuest quest) { MLQuestSystem.WriteQuestRef(writer, quest); writer.Write(quest.Version); }
public bool IsDoingQuest(MLQuest quest) { return(FindInstance(quest) != null); }
public static void WriteQuestRef(GenericWriter writer, MLQuest quest) { writer.Write((quest != null && quest.SaveEnabled) ? quest.GetType().FullName : null); }
static MLQuestSystem() { m_Quests = new Dictionary <Type, MLQuest>(); m_QuestGivers = new Dictionary <Type, List <MLQuest> >(); m_Contexts = new Dictionary <PlayerMobile, MLQuestContext>(); string cfgPath = Path.Combine(Core.BaseDirectory, Path.Combine("Data", "MLQuests.cfg")); Type baseQuestType = typeof(MLQuest); Type baseQuesterType = typeof(IQuestGiver); if (File.Exists(cfgPath)) { using (StreamReader sr = new StreamReader(cfgPath)) { string line; while ((line = sr.ReadLine()) != null) { if (line.Length == 0 || line.StartsWith("#")) { continue; } string[] split = line.Split('\t'); Type type = ScriptCompiler.FindTypeByName(split[0]); if (type == null || !baseQuestType.IsAssignableFrom(type)) { if (Debug) { Console.WriteLine("Warning: {1} quest type '{0}'", split[0], (type == null) ? "Unknown" : "Invalid"); } continue; } MLQuest quest = null; try { quest = Activator.CreateInstance(type) as MLQuest; } catch { } if (quest == null) { continue; } Register(type, quest); for (int i = 1; i < split.Length; ++i) { Type questerType = ScriptCompiler.FindTypeByName(split[i]); if (questerType == null || !baseQuesterType.IsAssignableFrom(questerType)) { if (Debug) { Console.WriteLine("Warning: {1} quester type '{0}'", split[i], (questerType == null) ? "Unknown" : "Invalid"); } continue; } RegisterQuestGiver(quest, questerType); } } } } }
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); }
public MLDoneQuestInfo(MLQuest quest, DateTime nextAvailable) { m_Quest = quest; m_NextAvailable = nextAvailable; }
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(); }
private static void Register(Type type, MLQuest quest) { m_Quests[type] = quest; }