using System; using System.Linq; using Server.Gumps; using Server.Items; using Server.Mobiles; namespace Server.Engines.MLQuests.Objectives { public class CollectObjective : BaseObjective { public CollectObjective(int amount = 0, Type type = null, TextDefinition name = null) { DesiredAmount = amount; AcceptedType = type; Name = name; if (MLQuestSystem.Debug && ShowDetailed && name.Number > 0) { int itemid = LabelToItemID(name.Number); if (itemid <= 0 || itemid > 0x4000) Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number); } } public int DesiredAmount{ get; set; } public Type AcceptedType{ get; set; } public TextDefinition Name{ get; set; } public virtual bool ShowDetailed => true; public bool CheckType(Type type) => AcceptedType?.IsAssignableFrom(type) == true; public virtual bool CheckItem(Item item) => true; public static int LabelToItemID(int label) { if (label < 1078872) return label - 1020000; return label - 1078872; } public override void WriteToGump(Gump g, ref int y) { if (ShowDetailed) { string amount = DesiredAmount.ToString(); g.AddHtmlLocalized(98, y, 350, 16, 1072205, 0x15F90); // Obtain g.AddLabel(143, y, 0x481, amount); if (Name.Number > 0) { g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); g.AddItem(350, y, LabelToItemID(Name.Number)); } else if (Name.String != null) { g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String); } } else { if (Name.Number > 0) g.AddHtmlLocalized(98, y, 312, 32, Name.Number, 0x15F90); else if (Name.String != null) g.AddLabel(98, y, 0x481, Name.String); } y += 32; } public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => new CollectObjectiveInstance(this, instance); } #region Timed public class TimedCollectObjective : CollectObjective { public TimedCollectObjective(TimeSpan duration, int amount, Type type, TextDefinition name) : base(amount, type, name) => Duration = duration; public override bool IsTimed => true; public override TimeSpan Duration{ get; } } #endregion public class CollectObjectiveInstance : BaseObjectiveInstance { public CollectObjectiveInstance(CollectObjective objective, MLQuestInstance instance) : base(instance, objective) => Objective = objective; public CollectObjective Objective{ get; set; } private int GetCurrentTotal() { Container pack = Instance.Player.Backpack; if (pack == null) return 0; Item[] items = pack.FindItemsByType(Objective.AcceptedType, false); // Note: subclasses are included return items.Where(item => item.QuestItem && Objective.CheckItem(item)).Sum(item => item.Amount); } public override bool AllowsQuestItem(Item item, Type type) => Objective.CheckType(type) && Objective.CheckItem(item); public override bool IsCompleted() => GetCurrentTotal() >= Objective.DesiredAmount; public override void OnQuestCancelled() { PlayerMobile pm = Instance.Player; Container pack = pm.Backpack; if (pack == null) return; Type checkType = Objective.AcceptedType; Item[] items = pack.FindItemsByType(checkType, false); foreach (Item item in items) if (item.QuestItem && !MLQuestSystem.CanMarkQuestItem(pm, item, checkType) ) // does another quest still need this item? (OSI just unmarks everything) item.QuestItem = false; } // Should only be called after IsComplete() is checked to be true public override void OnClaimReward() { Container pack = Instance.Player.Backpack; if (pack == null) return; // TODO: OSI also counts the item in the cursor? Item[] items = pack.FindItemsByType(Objective.AcceptedType, false); int left = Objective.DesiredAmount; foreach (Item item in items) if (item.QuestItem && Objective.CheckItem(item)) { if (left == 0) return; if (item.Amount > left) { item.Consume(left); left = 0; } else { item.Delete(); left -= item.Amount; } } } public override void OnAfterClaimReward() { OnQuestCancelled(); // same thing, clear other quest items } public override void OnExpire() { OnQuestCancelled(); // No message } public override void WriteToGump(Gump g, ref int y) { Objective.WriteToGump(g, ref y); y -= 16; if (Objective.ShowDetailed) { base.WriteToGump(g, ref y); g.AddHtmlLocalized(103, y, 120, 16, 3000087, 0x15F90); // Total g.AddLabel(223, y, 0x481, GetCurrentTotal().ToString()); y += 16; g.AddHtmlLocalized(103, y, 120, 16, 1074782, 0x15F90); // Return to g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Instance.QuesterType)); y += 16; } } } }