using System; using System.Collections.Generic; using System.Linq; using HISP.Game.Inventory; using HISP.Player; using HISP.Server; using HISP.Game.Items; namespace HISP.Game { public class Quest { public const string Shovel = "SHOVEL"; public const string Binoculars = "BINOCS"; public const string Rake = "RAKE"; public const string MagnifyingGlass = "MAGNIFY"; public const int CloudIslesQuest = 1373; public struct QuestItemInfo { public int ItemId; public int Quantity; } public struct QuestAltActivation { public string Type; public int ActivateX; public int ActivateY; } public struct QuestEntry { public int Id; public string Notes; public string Title; public int[] RequiresQuestIdCompleteStatsMenu; // Not sure what this is for. public QuestAltActivation AltActivation; public bool Tracked; // Should we track how many times the player has completed this quest. // Fail Settings public int MaxRepeats; public int MoneyCost; public QuestItemInfo[] ItemsRequired; public string FailNpcChat; public int AwardRequired; public int[] RequiresQuestIdCompleted; public int[] RequiresQuestIdNotCompleted; // Success Settings public int MoneyEarned; public QuestItemInfo[] ItemsEarned; public int QuestPointsEarned; public int SetNpcChatpoint; public int GotoNpcChatpoint; public int WarpX; public int WarpY; public string SuccessMessage; public string SuccessNpcChat; public bool HideReplyOnFail; public string Difficulty; public string Author; public int ChainedQuestId; public bool Minigame; } private static List questList = new List(); public static void AddQuestEntry(QuestEntry quest) { questList.Add(quest); } private static QuestEntry[] QuestList { get { return questList.ToArray(); } } public static int GetTotalQuestPoints() { int totalQp = 0; QuestEntry[] quests = GetPublicQuestList(); foreach (QuestEntry quest in quests) { totalQp += quest.QuestPointsEarned; } return totalQp; } public static int GetTotalQuestsComplete(User user) { QuestEntry[] questList = GetPublicQuestList(); int totalComplete = 0; foreach (QuestEntry quest in questList) { if (user.Quests.GetTrackedQuestAmount(quest.Id) > 0) totalComplete++; } return totalComplete; } public static QuestEntry[] GetPublicQuestList() { QuestEntry[] quests = QuestList.OrderBy(o => o.Title).ToArray(); List sortedQuests = new List(); foreach (QuestEntry quest in quests) { if (quest.Title != null) sortedQuests.Add(quest); } return sortedQuests.ToArray(); } public class QuestResult { public QuestResult() { NpcChat = null; SetChatpoint = -1; GotoChatpoint = -1; HideRepliesOnFail = false; QuestCompleted = false; } public string NpcChat; public int SetChatpoint; public int GotoChatpoint; public bool HideRepliesOnFail; public bool QuestCompleted; } public static bool CanComplete(User user, QuestEntry quest) { // Has completed other required quests? foreach (int questId in quest.RequiresQuestIdCompleted) if (user.Quests.GetTrackedQuestAmount(questId) < 1) return false; // Has NOT competed other MUST NOT BE required quests foreach (int questId in quest.RequiresQuestIdNotCompleted) if (user.Quests.GetTrackedQuestAmount(questId) > 1) return false; if (quest.Tracked) { // Has allready tracked this quest? if (user.Quests.GetTrackedQuestAmount(quest.Id) >= quest.MaxRepeats) return false; } // Check if user has award unlocked if (quest.AwardRequired != 0) if (!user.Awards.HasAward(Award.GetAwardById(quest.AwardRequired))) return false; // Check if i have required items foreach (QuestItemInfo itemInfo in quest.ItemsRequired) { bool hasThisItem = false; InventoryItem[] items = user.Inventory.GetItemList(); foreach (InventoryItem item in items) { if (item.ItemId == itemInfo.ItemId && item.ItemInstances.Length >= itemInfo.Quantity) { hasThisItem = true; break; } } if (!hasThisItem) return false; } // Have enough money? if (user.Money < quest.MoneyCost) return false; return true; } public static QuestResult CompleteQuest(User user, QuestEntry quest, bool npcActivation = false, QuestResult res=null) { if(res == null) res = new QuestResult(); // Take Items foreach (QuestItemInfo itemInfo in quest.ItemsRequired) { InventoryItem itm = user.Inventory.GetItemByItemId(itemInfo.ItemId); for (int i = 0; i < itemInfo.Quantity; i++) user.Inventory.Remove(itm.ItemInstances[0]); } // Take Money user.TakeMoney(quest.MoneyCost); // Give money user.AddMoney(quest.MoneyEarned); // Give items foreach (QuestItemInfo itemInfo in quest.ItemsEarned) { for (int i = 0; i < itemInfo.Quantity; i++) { ItemInstance itm = new ItemInstance(itemInfo.ItemId); Item.ItemInformation itemInformation = itm.GetItemInfo(); if (itemInformation.Type == "CONCEPTUAL") Item.ConsumeItem(user, itemInformation); else user.Inventory.AddIgnoringFull(itm); } } if (quest.WarpX != 0 && quest.WarpY != 0) user.Teleport(quest.WarpX, quest.WarpY); // Give quest points user.QuestPoints += quest.QuestPointsEarned; res.QuestCompleted = true; if (npcActivation) { if (quest.SuccessNpcChat != null && quest.SuccessNpcChat.Trim() != "") res.NpcChat = quest.SuccessNpcChat; if(quest.SetNpcChatpoint != -1) res.SetChatpoint = quest.SetNpcChatpoint; if(quest.GotoNpcChatpoint != -1) res.GotoChatpoint = quest.GotoNpcChatpoint; } if (quest.Tracked) user.Quests.TrackQuest(quest.Id); if (quest.ChainedQuestId != 0) res = ActivateQuest(user, Quest.GetQuestById(quest.ChainedQuestId), npcActivation, res); if (quest.SuccessMessage != null) { byte[] ChatPacket = PacketBuilder.CreateChat(quest.SuccessMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(ChatPacket); } if (quest.SuccessNpcChat != null) { if (!npcActivation) { byte[] ChatPacket = PacketBuilder.CreateChat(quest.SuccessNpcChat, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(ChatPacket); } } // Check if award unlocked int questPointsPercent = Convert.ToInt32(Math.Floor(((decimal)user.QuestPoints / (decimal)GetTotalQuestPoints()) * (decimal)100.0)); if (questPointsPercent >= 25) user.Awards.AddAward(Award.GetAwardById(1)); // 25% Quest Completion Award. if (questPointsPercent >= 50) user.Awards.AddAward(Award.GetAwardById(2)); // 50% Quest Completion Award. if (questPointsPercent >= 75) user.Awards.AddAward(Award.GetAwardById(3)); // 75% Quest Completion Award. if (questPointsPercent >= 100) user.Awards.AddAward(Award.GetAwardById(4)); // 100% Quest Completion Award. // Is cloud isles quest? if (quest.Id == CloudIslesQuest) { byte[] swfLoadPacket = PacketBuilder.CreateSwfModule("ballooncutscene", PacketBuilder.PACKET_SWF_MODULE_CUTSCENE); user.LoggedinClient.SendPacket(swfLoadPacket); } return res; } public static QuestResult FailQuest(User user, QuestEntry quest, bool npcActivation = false, QuestResult res=null) { if(res == null) res = new QuestResult(); res.QuestCompleted = false; if(npcActivation) { if(quest.GotoNpcChatpoint != -1) res.GotoChatpoint = quest.GotoNpcChatpoint; if(quest.HideReplyOnFail != false) res.HideRepliesOnFail = quest.HideReplyOnFail; if(res.SetChatpoint != -1) res.SetChatpoint = quest.SetNpcChatpoint; } if (quest.FailNpcChat != null) { if (!npcActivation) { byte[] ChatPacket = PacketBuilder.CreateChat(quest.FailNpcChat, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(ChatPacket); } else { if(quest.FailNpcChat != null) { if(npcActivation) { if (quest.FailNpcChat != "") { res.NpcChat = quest.FailNpcChat; } } } } } return res; } public static QuestResult ActivateQuest(User user, QuestEntry quest, bool npcActivation = false, QuestResult res=null) { if (CanComplete(user, quest)) { return CompleteQuest(user, quest, npcActivation, res); } else { return FailQuest(user, quest, npcActivation, res); } } public static bool DoesQuestExist(int id) { try { GetQuestById(id); return true; } catch(KeyNotFoundException) { return false; } } public static QuestEntry GetQuestById(int id) { foreach(QuestEntry quest in QuestList) { if(quest.Id == id) { return quest; } } throw new KeyNotFoundException("Quest Id: " + id + " Dont exist."); } public static bool UseTool(User user, string tool, int x, int y) { if (tool == Quest.Shovel) { // check Treasures if (Treasure.IsTileTreasure(x, y)) { Treasure treasure = Treasure.GetTreasureAt(x, y); if(treasure.Type == "BURIED") treasure.CollectTreasure(user); return true; } } QuestResult result = null; foreach (QuestEntry quest in QuestList) { if (quest.AltActivation.Type == tool && quest.AltActivation.ActivateX == x && quest.AltActivation.ActivateY == y) { result = ActivateQuest(user, quest, true, result); if(result.QuestCompleted) { if(result.NpcChat != null) { byte[] ChatPacket = PacketBuilder.CreateChat(result.NpcChat, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(ChatPacket); } return true; } } } if(result != null) { if (result.NpcChat != null) { byte[] ChatPacket = PacketBuilder.CreateChat(result.NpcChat, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(ChatPacket); } return true; } return false; } } }