Refactored quest state system seems to work!

This commit is contained in:
Filip Maj 2022-02-17 13:22:18 -05:00
parent 1523ae200b
commit 02cb0a3f43
14 changed files with 673 additions and 512 deletions

View file

@ -37,6 +37,7 @@ using Meteor.Map.actors.chara.ai.controllers;
using Meteor.Map.actors.chara.ai.utils;
using Meteor.Map.actors.chara.ai.state;
using Meteor.Map.actors.chara;
using Meteor.Map.Actors.QuestNS;
using Meteor.Map.packets.send;
using Meteor.Map.packets.send.actor;
using Meteor.Map.packets.send.events;
@ -277,7 +278,7 @@ namespace Meteor.Map.Actors
CalculateBaseStats();
questStateManager = new QuestStateManager(this);
questStateManager.Init();
questStateManager.Init(questScenario);
}
public List<SubPacket> Create0x132Packets()
@ -806,7 +807,7 @@ namespace Meteor.Map.Actors
foreach (Quest quest in questScenario)
{
if (quest != null)
quest.SaveData();
quest.GetData().Save();
}
}
@ -1418,33 +1419,253 @@ namespace Meteor.Map.Actors
return -1;
}
//For Lua calls, cause MoonSharp goes retard with uint
public void AddQuest(int id, bool isSilent = false)
#region Quests - Script Related
// Add quest from an active quest in the player's quest state. Quest scripts will use this to add a quest.
public bool AcceptQuest(Quest instance, bool isSilent = false)
{
AddQuest((uint)id, isSilent);
}
public void CompleteQuest(int id)
{
CompleteQuest((uint)id);
}
public bool HasQuest(int id)
{
return HasQuest((uint)id);
}
public Quest GetQuest(int id)
{
return GetQuest((uint)id);
}
public bool IsQuestCompleted(int id)
{
return IsQuestCompleted((uint)id);
}
public bool CanAcceptQuest(int id)
{
return CanAcceptQuest((uint)id);
}
//For Lua calls, cause MoonSharp goes retard with uint
if (instance == null)
return false;
int freeSlot = GetFreeQuestSlot();
if (freeSlot == -1)
{
SendGameMessage(Server.GetWorldManager().GetActor(), 25234, 0x20); // "You cannot accept any more quests at this time."
return false;
}
playerWork.questScenario[freeSlot] = instance.Id;
questScenario[freeSlot] = instance;
Database.SaveQuest(this, questScenario[freeSlot]);
SendQuestClientUpdate(freeSlot);
if (!isSilent)
{
SendGameMessage(Server.GetWorldManager().GetActor(), 25224, 0x20, (object)questScenario[freeSlot].GetQuestId()); // "<Quest> accepted."
}
instance.OnAccept();
return true;
}
// Replace a quest with another quest in the player's quest state.
public void ReplaceQuest(Quest oldQuestInstance, Quest newQuestInstance)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Equals(oldQuestInstance))
{
questScenario[i] = newQuestInstance;
playerWork.questScenario[i] = questScenario[i].Id;
Database.SaveQuest(this, questScenario[i]);
SendQuestClientUpdate(i);
break;
}
}
}
public void CompleteQuest(Quest completed)
{
int slot = GetQuestSlot(completed);
if (slot >= 0)
{
// Remove the quest from the DB and update client work values
playerWork.questScenarioComplete[completed.GetQuestId() - 110001] = true;
Database.CompleteQuest(playerSession.GetActor(), completed.Id);
Database.RemoveQuest(this, completed.Id);
questScenario[slot] = null;
playerWork.questScenario[slot] = 0;
SendQuestClientUpdate(slot);
// Reset active quest and quest state
completed.OnComplete();
questStateManager.UpdateQuestCompleted(completed);
// Msg Player
SendGameMessage(Server.GetWorldManager().GetActor(), 25086, 0x20, (object)completed.GetQuestId()); // "<Quest> complete!"
}
}
public bool AbandonQuest(uint questId)
{
// Check if in an instance
if (CurrentArea.IsPrivate())
{
SendGameMessage(Server.GetWorldManager().GetActor(), 25235, 0x20); // "Quests cannot be abandoned while from within an instance."
return false;
}
// Get the quest object
int slot = GetQuestSlot(questId);
Quest abandoned = questScenario[slot];
if (abandoned == null)
return false;
// Check if Main Scenario
if (abandoned.IsMainScenario())
{
SendGameMessage(Server.GetWorldManager().GetActor(), 25233, 0x20); // "Main scenario quests cannot be abandoned."
return false;
}
// Remove the quest from the DB and update client work values
Database.RemoveQuest(this, abandoned.Id);
questScenario[slot] = null;
playerWork.questScenario[slot] = 0;
SendQuestClientUpdate(slot);
// Reset active quest and quest state
abandoned.OnAbandon();
questStateManager.UpdateQuestAbandoned();
// Msg Player
SendGameMessage(this, Server.GetWorldManager().GetActor(), 25236, 0x20, (object)abandoned.GetQuestId()); // "<Quest> abandoned."
return true;
}
public bool HasQuest(Quest questInstance)
{
return GetQuestSlot(questInstance) != -1;
}
#endregion
#region Quests - Debug/Misc Related
// Force-Add a quest by Id. Called be debug scripts.
public void AddQuest(uint id, bool isSilent = false)
{
Actor actor = Server.GetStaticActors((0xA0F00000 | id));
AddQuest(actor.Name, isSilent);
}
// Force-Add a quest by Name. Called be debug scripts. Will try to use an active quest, otherwise adds a new instance.
public void AddQuest(string name, bool isSilent = false)
{
Quest baseQuest = (Quest)Server.GetStaticActors(name);
Quest activeQuest = questStateManager.GetActiveQuest(baseQuest.GetQuestId());
int freeSlot = GetFreeQuestSlot();
if (freeSlot == -1)
return;
playerWork.questScenario[freeSlot] = baseQuest.Id;
questScenario[freeSlot] = activeQuest ?? new Quest(this, baseQuest);
if (activeQuest == null)
questStateManager.ForceAddActiveQuest(questScenario[freeSlot]);
Database.SaveQuest(this, questScenario[freeSlot]);
SendQuestClientUpdate(freeSlot);
if (!isSilent)
{
SendGameMessage(Server.GetWorldManager().GetActor(), 25224, 0x20, (object)questScenario[freeSlot].GetQuestId());
}
questScenario[freeSlot].OnAccept();
}
public void RemoveQuest(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == (0xA0F00000 | id))
{
Database.RemoveQuest(this, questScenario[i].Id);
questScenario[i] = null;
playerWork.questScenario[i] = 0;
SendQuestClientUpdate(i);
break;
}
}
}
public void RemoveQuest(string name)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Name.ToLower().Equals(name.ToLower()))
{
Database.RemoveQuest(this, questScenario[i].Id);
questScenario[i] = null;
playerWork.questScenario[i] = 0;
SendQuestClientUpdate(i);
break;
}
}
}
public bool HasQuest(string name)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Name.ToLower().Equals(name.ToLower()))
return true;
}
return false;
}
public bool HasQuest(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == (0xA0F00000 | id))
return true;
}
return false;
}
public Quest GetQuest(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == (0xA0F00000 | id))
return questScenario[i];
}
return null;
}
public Quest GetQuest(string name)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Name.ToLower().Equals(name.ToLower()))
return questScenario[i];
}
return null;
}
public int GetQuestSlot(Quest quest)
{
for (int slot = 0; slot < questScenario.Length; slot++)
{
if (questScenario[slot] != null && questScenario[slot].Id == quest.Id)
return slot;
}
return -1;
}
public int GetQuestSlot(uint id)
{
for (int slot = 0; slot < questScenario.Length; slot++)
{
if (questScenario[slot] != null && questScenario[slot].GetQuestId() == id)
return slot;
}
return -1;
}
#endregion
#region Guildleves
public void AddGuildleve(uint id)
{
int freeSlot = GetFreeGuildleveSlot();
@ -1489,179 +1710,7 @@ namespace Meteor.Map.Actors
}
}
}
}
public void AddQuest(uint id, bool isSilent = false)
{
Actor actor = Server.GetStaticActors((0xA0F00000 | id));
AddQuest(actor.Name, isSilent);
}
public void AddQuest(string name, bool isSilent = false)
{
Quest baseQuest = (Quest) Server.GetStaticActors(name);
if (baseQuest == null)
return;
int freeSlot = GetFreeQuestSlot();
if (freeSlot == -1)
return;
playerWork.questScenario[freeSlot] = baseQuest.Id;
questScenario[freeSlot] = new Quest(this, baseQuest);
Database.SaveQuest(this, questScenario[freeSlot]);
SendQuestClientUpdate(freeSlot);
if (!isSilent)
{
SendGameMessage(Server.GetWorldManager().GetActor(), 25224, 0x20, (object)questScenario[freeSlot].GetQuestId());
}
}
public void CompleteQuest(uint id)
{
Actor actor = Server.GetStaticActors((0xA0F00000 | id));
CompleteQuest(actor.Name);
}
public void CompleteQuest(string name)
{
Actor actor = Server.GetStaticActors(name);
if (actor == null)
return;
uint id = actor.Id;
if (HasQuest(id))
{
Database.CompleteQuest(playerSession.GetActor(), id);
SendGameMessage(Server.GetWorldManager().GetActor(), 25086, 0x20, (object)GetQuest(id).GetQuestId());
RemoveQuest(id);
}
}
//TODO: Add checks for you being in an instance or main scenario
public void AbandonQuest(uint id)
{
Quest quest = GetQuest(id);
RemoveQuestByQuestId(id);
quest.DoAbandon();
}
public void RemoveQuestByQuestId(uint id)
{
RemoveQuest((0xA0F00000 | id));
}
public void RemoveQuest(uint id)
{
if (HasQuest(id))
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == id)
{
Database.RemoveQuest(this, questScenario[i].Id);
questScenario[i] = null;
playerWork.questScenario[i] = 0;
SendQuestClientUpdate(i);
break;
}
}
}
}
public void ReplaceQuest(Quest oldQuest, string questCode)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Equals(oldQuest))
{
Quest baseQuest = (Quest) Server.GetStaticActors(questCode);
questScenario[i] = new Quest(this, baseQuest);
playerWork.questScenario[i] = questScenario[i].Id;
Database.SaveQuest(this, questScenario[i]);
SendQuestClientUpdate(i);
break;
}
}
}
public bool CanAcceptQuest(string name)
{
if (!IsQuestCompleted(name) && !HasQuest(name))
return true;
else
return false;
}
public bool CanAcceptQuest(uint id)
{
Actor actor = Server.GetStaticActors((0xA0F00000 | id));
return CanAcceptQuest(actor.Name);
}
public bool IsQuestCompleted(string questName)
{
Actor actor = Server.GetStaticActors(questName);
return IsQuestCompleted(actor.Id);
}
public bool IsQuestCompleted(uint questId)
{
return Database.IsQuestCompleted(this, 0xFFFFF & questId);
}
public Quest GetQuest(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == (0xA0F00000 | id))
return questScenario[i];
}
return null;
}
public Quest GetQuest(string name)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Name.ToLower().Equals(name.ToLower()))
return questScenario[i];
}
return null;
}
public bool HasQuest(string name)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Name.ToLower().Equals(name.ToLower()))
return true;
}
return false;
}
public bool HasQuest(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == (0xA0F00000 | id))
return true;
}
return false;
}
public bool HasQuest(Quest quest)
{
return HasQuest(quest.className);
}
}
public bool HasGuildleve(uint id)
{
@ -1673,17 +1722,7 @@ namespace Meteor.Map.Actors
return false;
}
public int GetQuestSlot(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
{
if (questScenario[i] != null && questScenario[i].Id == (0xA0F00000 | id))
return i;
}
return -1;
}
#endregion
public Quest GetDefaultTalkQuest(Npc npc)
{
@ -1735,14 +1774,11 @@ namespace Meteor.Map.Actors
return null;
}
public Quest[] GetJournalQuestsForNpc(Npc npc)
{
return Array.FindAll(questScenario, e => e != null && e.IsQuestENPC(this, npc));
}
public Quest[] GetQuestsForNpc(Npc npc)
{
return questStateManager.GetQuestsForNpc(npc);
Quest[] quests = questStateManager.GetQuestsForNpc(npc);
Array.Sort(quests, (q1, q2) => (q1.HasData() ? 1 : 0) - (q2.HasData() ? 1 : 0));
return quests;
}
public void HandleNpcLS(uint id)
@ -2765,6 +2801,7 @@ namespace Meteor.Map.Actors
actionList.Add(new CommandResult(Id, 33909, 0, (ushort)charaWork.battleSave.skillLevel[classId - 1]));
EquipAbilitiesAtLevel(classId, GetLevel(), actionList);
questStateManager.UpdateLevel(GetHighestLevel());
}
}