2022-02-16 15:32:54 -05:00
|
|
|
|
using Meteor.Common;
|
|
|
|
|
using Meteor.Map.DataObjects;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2022-02-17 13:22:18 -05:00
|
|
|
|
namespace Meteor.Map.Actors.QuestNS
|
2022-02-16 15:32:54 -05:00
|
|
|
|
{
|
|
|
|
|
class QuestStateManager
|
|
|
|
|
{
|
|
|
|
|
private const int SCENARIO_START = 110001;
|
|
|
|
|
private const int SCENARIO_MAX = 2048;
|
|
|
|
|
|
|
|
|
|
private readonly Player player;
|
2022-02-19 01:17:50 -05:00
|
|
|
|
private readonly Bitstream CompletedQuestsBitfield = new Bitstream(SCENARIO_MAX);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
private readonly Bitstream AvailableQuestsBitfield = new Bitstream(SCENARIO_MAX);
|
|
|
|
|
private readonly Bitstream MinLevelBitfield = new Bitstream(SCENARIO_MAX);
|
|
|
|
|
private readonly Bitstream PrereqBitfield = new Bitstream(SCENARIO_MAX, true);
|
|
|
|
|
private readonly Bitstream GCRankBitfield = new Bitstream(SCENARIO_MAX, true);
|
|
|
|
|
|
|
|
|
|
private List<Quest> ActiveQuests = new List<Quest>();
|
2022-02-17 13:22:18 -05:00
|
|
|
|
private Dictionary<uint, QuestState> QuestStateTable = new Dictionary<uint, QuestState>();
|
2022-02-16 15:32:54 -05:00
|
|
|
|
|
|
|
|
|
public QuestStateManager(Player player)
|
|
|
|
|
{
|
|
|
|
|
this.player = player;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 01:17:50 -05:00
|
|
|
|
public void Init(Quest[] journalQuests, bool[] completedQuests)
|
2022-02-16 15:32:54 -05:00
|
|
|
|
{
|
2022-02-17 13:22:18 -05:00
|
|
|
|
// Preload any quests that the player loaded
|
2022-02-19 01:17:50 -05:00
|
|
|
|
if (journalQuests != null)
|
2022-02-17 13:22:18 -05:00
|
|
|
|
{
|
2022-02-19 01:17:50 -05:00
|
|
|
|
foreach (var quest in journalQuests)
|
2022-02-17 13:22:18 -05:00
|
|
|
|
{
|
|
|
|
|
if (quest != null)
|
|
|
|
|
{
|
|
|
|
|
ActiveQuests.Add(quest);
|
|
|
|
|
AvailableQuestsBitfield.Set(quest.GetQuestId() - SCENARIO_START);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-16 15:32:54 -05:00
|
|
|
|
// Init MinLv
|
2022-02-17 13:22:18 -05:00
|
|
|
|
QuestGameData[] minLvl = Server.GetQuestGamedataByMaxLvl(player.GetHighestLevel(), true);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
foreach (var questData in minLvl)
|
|
|
|
|
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
|
|
|
|
|
|
|
|
|
// Init Prereq
|
2022-02-19 01:17:50 -05:00
|
|
|
|
CompletedQuestsBitfield.SetTo(completedQuests);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
foreach (var questData in Server.GetQuestGamedataAllPrerequisite())
|
|
|
|
|
{
|
2022-02-19 01:17:50 -05:00
|
|
|
|
if (CompletedQuestsBitfield.Get(((Quest)Server.GetStaticActors(0xA0F00000 | questData.PrerequisiteQuest)).GetQuestId() - SCENARIO_START))
|
2022-02-16 15:32:54 -05:00
|
|
|
|
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
|
|
|
|
else
|
|
|
|
|
PrereqBitfield.Clear(questData.Id - SCENARIO_START);
|
|
|
|
|
}
|
2022-02-17 13:22:18 -05:00
|
|
|
|
|
2022-02-16 15:32:54 -05:00
|
|
|
|
ComputeAvailable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateLevel(int level)
|
|
|
|
|
{
|
2022-02-17 13:22:18 -05:00
|
|
|
|
QuestGameData[] updated = Server.GetQuestGamedataByMaxLvl(level);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
foreach (var questData in updated)
|
|
|
|
|
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
|
|
|
|
ComputeAvailable();
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-17 13:22:18 -05:00
|
|
|
|
public void UpdateQuestCompleted(Quest quest)
|
2022-02-16 15:32:54 -05:00
|
|
|
|
{
|
2022-02-20 21:30:09 -05:00
|
|
|
|
CompletedQuestsBitfield.Set(quest.GetQuestId() - SCENARIO_START);
|
2022-02-17 13:22:18 -05:00
|
|
|
|
QuestGameData[] updated = Server.GetQuestGamedataByPrerequisite(quest.GetQuestId());
|
2022-02-16 15:32:54 -05:00
|
|
|
|
foreach (var questData in updated)
|
|
|
|
|
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
|
|
|
|
ComputeAvailable();
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-17 13:22:18 -05:00
|
|
|
|
public void UpdateQuestAbandoned()
|
2022-02-16 15:32:54 -05:00
|
|
|
|
{
|
2022-02-17 13:22:18 -05:00
|
|
|
|
ComputeAvailable();
|
2022-02-16 15:32:54 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ComputeAvailable()
|
|
|
|
|
{
|
2022-02-19 01:17:50 -05:00
|
|
|
|
Bitstream result = new Bitstream(SCENARIO_MAX);
|
|
|
|
|
result.OR(CompletedQuestsBitfield);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
result.NOT();
|
|
|
|
|
result.AND(MinLevelBitfield);
|
|
|
|
|
result.AND(PrereqBitfield);
|
|
|
|
|
result.AND(GCRankBitfield);
|
|
|
|
|
|
|
|
|
|
Bitstream difference = AvailableQuestsBitfield.Copy();
|
|
|
|
|
difference.XOR(result);
|
|
|
|
|
byte[] diffBytes = difference.GetBytes();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < diffBytes.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (diffBytes[i] == 0)
|
|
|
|
|
continue;
|
|
|
|
|
for (int shift = 0; shift < 8; shift++)
|
|
|
|
|
{
|
|
|
|
|
if ((diffBytes[i] >> shift & 1) == 1)
|
|
|
|
|
{
|
|
|
|
|
int index = i * 8 + shift;
|
|
|
|
|
Quest quest = (Quest)Server.GetStaticActors(0xA0F00000 | (SCENARIO_START + (uint)index));
|
|
|
|
|
if (!AvailableQuestsBitfield.Get(index))
|
2022-02-17 13:22:18 -05:00
|
|
|
|
AddActiveQuest(quest);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
else
|
2022-02-17 13:22:18 -05:00
|
|
|
|
RemoveActiveQuest(quest);
|
2022-02-16 15:32:54 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AvailableQuestsBitfield.SetTo(result);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-17 13:22:18 -05:00
|
|
|
|
public void ForceAddActiveQuest(Quest questInstance)
|
|
|
|
|
{
|
|
|
|
|
ActiveQuests.Add(questInstance);
|
|
|
|
|
QuestStateTable.Add(questInstance.Id, questInstance.GetQuestState());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddActiveQuest(Quest staticQuest)
|
|
|
|
|
{
|
|
|
|
|
Quest instance = new Quest(player, staticQuest);
|
|
|
|
|
ActiveQuests.Add(instance);
|
|
|
|
|
QuestStateTable.Add(staticQuest.Id, instance.GetQuestState());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RemoveActiveQuest(Quest staticQuest)
|
|
|
|
|
{
|
|
|
|
|
// Do not remove quests in the player's journal
|
|
|
|
|
if (player.HasQuest(staticQuest.GetQuestId()))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ActiveQuests.Remove(staticQuest);
|
|
|
|
|
|
|
|
|
|
if (QuestStateTable.ContainsKey(staticQuest.Id))
|
|
|
|
|
{
|
|
|
|
|
QuestStateTable[staticQuest.Id].DeleteState();
|
|
|
|
|
QuestStateTable.Remove(staticQuest.Id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Quest GetActiveQuest(uint id)
|
|
|
|
|
{
|
|
|
|
|
return ActiveQuests.Find(quest => quest.GetQuestId() == id);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-11 02:17:46 -05:00
|
|
|
|
public Quest[] GetQuestsForNpc(Npc npc, bool isPrivateArea)
|
2022-02-16 15:32:54 -05:00
|
|
|
|
{
|
2022-03-11 02:17:46 -05:00
|
|
|
|
if (isPrivateArea)
|
|
|
|
|
return ActiveQuests.FindAll(quest => quest.IsQuestENPC(player, npc) && quest.GetSequence() != Quest.SEQ_NOT_STARTED).ToArray();
|
|
|
|
|
else
|
|
|
|
|
return ActiveQuests.FindAll(quest => quest.IsQuestENPC(player, npc)).ToArray();
|
2022-02-16 15:32:54 -05:00
|
|
|
|
}
|
2022-02-19 01:17:50 -05:00
|
|
|
|
|
2022-02-20 12:39:34 -05:00
|
|
|
|
public byte[] GetCompletionSliceBytes(ushort from, ushort to)
|
2022-02-19 01:17:50 -05:00
|
|
|
|
{
|
2022-02-20 12:39:34 -05:00
|
|
|
|
return CompletedQuestsBitfield.GetSlice(from, to);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsQuestComplete(uint questId)
|
|
|
|
|
{
|
|
|
|
|
return CompletedQuestsBitfield.Get(questId - SCENARIO_START);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ForceQuestCompleteFlag(uint questId, bool flag)
|
|
|
|
|
{
|
|
|
|
|
if (flag)
|
|
|
|
|
CompletedQuestsBitfield.Set(questId - SCENARIO_START);
|
|
|
|
|
else
|
|
|
|
|
CompletedQuestsBitfield.Clear(questId - SCENARIO_START);
|
2022-02-23 23:10:11 -05:00
|
|
|
|
QuestGameData[] updated = Server.GetQuestGamedataByPrerequisite(questId);
|
|
|
|
|
foreach (var questData in updated)
|
|
|
|
|
{
|
|
|
|
|
if (flag)
|
|
|
|
|
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
|
|
|
|
else
|
|
|
|
|
PrereqBitfield.Clear(questData.Id - SCENARIO_START);
|
|
|
|
|
}
|
2022-02-20 12:39:34 -05:00
|
|
|
|
ComputeAvailable();
|
2022-02-19 01:17:50 -05:00
|
|
|
|
}
|
2022-02-16 15:32:54 -05:00
|
|
|
|
}
|
|
|
|
|
}
|