HISP/HorseIsleServer/LibHISP/Game/Quest.cs
2022-11-14 23:09:22 +13:00

395 lines
13 KiB
C#
Executable file

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<QuestEntry> questList = new List<QuestEntry>();
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<QuestEntry> sortedQuests = new List<QuestEntry>();
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;
}
}
}