mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-02 19:42:05 -04:00
Refactored quest state system seems to work!
This commit is contained in:
parent
1523ae200b
commit
02cb0a3f43
@ -24,7 +24,6 @@ end
|
|||||||
function onEventStarted(player, npc, eventType, eventName)
|
function onEventStarted(player, npc, eventType, eventName)
|
||||||
local defaultTalk = player:GetDefaultTalkQuest(npc);
|
local defaultTalk = player:GetDefaultTalkQuest(npc);
|
||||||
local tutorialTalk = player:GetTutorialQuest(npc);
|
local tutorialTalk = player:GetTutorialQuest(npc);
|
||||||
local journalQuests = player:GetJournalQuestsForNpc(npc);
|
|
||||||
local activeQuests = player:GetQuestsForNpc(npc);
|
local activeQuests = player:GetQuestsForNpc(npc);
|
||||||
local possibleQuests = {};
|
local possibleQuests = {};
|
||||||
|
|
||||||
@ -35,9 +34,6 @@ function onEventStarted(player, npc, eventType, eventName)
|
|||||||
if (tutorialTalk ~= nil and eventType == ETYPE_TALK) then
|
if (tutorialTalk ~= nil and eventType == ETYPE_TALK) then
|
||||||
table.insert(possibleQuests, tutorialTalk);
|
table.insert(possibleQuests, tutorialTalk);
|
||||||
end
|
end
|
||||||
if (journalQuests ~= nil) then
|
|
||||||
table.insert(possibleQuests, unpack(journalQuests));
|
|
||||||
end
|
|
||||||
if (activeQuests ~= nil) then
|
if (activeQuests ~= nil) then
|
||||||
table.insert(possibleQuests, unpack(activeQuests));
|
table.insert(possibleQuests, unpack(activeQuests));
|
||||||
end
|
end
|
||||||
|
@ -49,17 +49,18 @@ function onFinish(player, quest)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function onStateChange(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
if (sequence == 65536) then
|
if (sequence == 65535) then
|
||||||
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local data = quest:GetData();
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
quest:SetENpc(KINNISON);
|
quest:SetENpc(KINNISON);
|
||||||
quest:SetENpc(SYBELL, (not quest:GetFlag(FLAG_TALKED_SYBELL) and QFLAG_PLATE or QFLAG_NONE));
|
quest:SetENpc(SYBELL, (not data:GetFlag(FLAG_TALKED_SYBELL) and QFLAG_PLATE or QFLAG_NONE));
|
||||||
quest:SetENpc(KHUMA_MOSHROCA, (not quest:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and QFLAG_PLATE or QFLAG_NONE));
|
quest:SetENpc(KHUMA_MOSHROCA, (not data:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and QFLAG_PLATE or QFLAG_NONE));
|
||||||
quest:SetENpc(NELLAURE, (not quest:GetFlag(FLAG_TALKED_NELLAURE) and QFLAG_PLATE or QFLAG_NONE));
|
quest:SetENpc(NELLAURE, (not data:GetFlag(FLAG_TALKED_NELLAURE) and QFLAG_PLATE or QFLAG_NONE));
|
||||||
quest:SetENpc(MESTONNAUX, (not quest:GetFlag(FLAG_TALKED_MESTONNAUX) and QFLAG_PLATE or QFLAG_NONE));
|
quest:SetENpc(MESTONNAUX, (not data:GetFlag(FLAG_TALKED_MESTONNAUX) and QFLAG_PLATE or QFLAG_NONE));
|
||||||
quest:SetENpc(LEFWYNE, (not quest:GetFlag(FLAG_TALKED_LEFWYNE) and QFLAG_PLATE or QFLAG_NONE));
|
quest:SetENpc(LEFWYNE, (not data:GetFlag(FLAG_TALKED_LEFWYNE) and QFLAG_PLATE or QFLAG_NONE));
|
||||||
elseif (sequence == SEQ_001) then
|
elseif (sequence == SEQ_001) then
|
||||||
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
||||||
end
|
end
|
||||||
@ -74,67 +75,66 @@ function onTalk(player, quest, npc, eventName)
|
|||||||
if (npcClassId == KINNISON and not player:HasQuest(quest)) then
|
if (npcClassId == KINNISON and not player:HasQuest(quest)) then
|
||||||
local questAccepted = callClientFunction(player, "delegateEvent", player, quest, "processEventOffersStart");
|
local questAccepted = callClientFunction(player, "delegateEvent", player, quest, "processEventOffersStart");
|
||||||
if (questAccepted) then
|
if (questAccepted) then
|
||||||
player:AddQuest(quest);
|
player:AcceptQuest(quest);
|
||||||
end
|
end
|
||||||
player:EndEvent();
|
player:EndEvent();
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Quest Progress
|
-- Quest Progress
|
||||||
|
local data = quest:GetData();
|
||||||
if (seq == SEQ_000) then
|
if (seq == SEQ_000) then
|
||||||
if (npcClassId == KINNISON) then
|
if (npcClassId == KINNISON) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventOffersAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventOffersAfter");
|
||||||
elseif (npcClassId == SYBELL) then
|
elseif (npcClassId == SYBELL) then
|
||||||
if (not quest:GetFlag(FLAG_TALKED_SYBELL)) then
|
if (not data:GetFlag(FLAG_TALKED_SYBELL)) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventSybellSpeak");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventSybellSpeak");
|
||||||
quest:SetFlag(FLAG_TALKED_SYBELL);
|
data:SetFlag(FLAG_TALKED_SYBELL);
|
||||||
incCounter = true;
|
incCounter = true;
|
||||||
else
|
else
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventSybellSpeakAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventSybellSpeakAfter");
|
||||||
end
|
end
|
||||||
elseif (npcClassId == KHUMA_MOSHROCA) then
|
elseif (npcClassId == KHUMA_MOSHROCA) then
|
||||||
if (not quest:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA)) then
|
if (not data:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA)) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventKhumaSpeak");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventKhumaSpeak");
|
||||||
quest:SetFlag(FLAG_TALKED_KHUMA_MOSHROCA);
|
data:SetFlag(FLAG_TALKED_KHUMA_MOSHROCA);
|
||||||
incCounter = true;
|
incCounter = true;
|
||||||
else
|
else
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventKhumaSpeakAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventKhumaSpeakAfter");
|
||||||
end
|
end
|
||||||
elseif (npcClassId == NELLAURE) then
|
elseif (npcClassId == NELLAURE) then
|
||||||
if (not quest:GetFlag(FLAG_TALKED_NELLAURE)) then
|
if (not data:GetFlag(FLAG_TALKED_NELLAURE)) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventNellaureSpeak");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventNellaureSpeak");
|
||||||
quest:SetFlag(FLAG_TALKED_NELLAURE);
|
data:SetFlag(FLAG_TALKED_NELLAURE);
|
||||||
incCounter = true;
|
incCounter = true;
|
||||||
else
|
else
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventNellaureSpeakAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventNellaureSpeakAfter");
|
||||||
end
|
end
|
||||||
elseif (npcClassId == MESTONNAUX) then
|
elseif (npcClassId == MESTONNAUX) then
|
||||||
if (not quest:GetFlag(FLAG_TALKED_MESTONNAUX)) then
|
if (not data:GetFlag(FLAG_TALKED_MESTONNAUX)) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventMestonnauxSpeak");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventMestonnauxSpeak");
|
||||||
quest:SetFlag(FLAG_TALKED_MESTONNAUX);
|
data:SetFlag(FLAG_TALKED_MESTONNAUX);
|
||||||
incCounter = true;
|
incCounter = true;
|
||||||
else
|
else
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventMestonnauxSpeakAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventMestonnauxSpeakAfter");
|
||||||
end
|
end
|
||||||
elseif (npcClassId == LEFWYNE) then
|
elseif (npcClassId == LEFWYNE) then
|
||||||
if (not quest:GetFlag(FLAG_TALKED_LEFWYNE)) then
|
if (not data:GetFlag(FLAG_TALKED_LEFWYNE)) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventLefwyneSpeak");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventLefwyneSpeak");
|
||||||
quest:SetFlag(FLAG_TALKED_LEFWYNE);
|
data:SetFlag(FLAG_TALKED_LEFWYNE);
|
||||||
incCounter = true;
|
incCounter = true;
|
||||||
else
|
else
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventLefwyneSpeakAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventLefwyneSpeakAfter");
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Increase objective counter & play relevant messages
|
-- Increase objective counter & play relevant messages
|
||||||
if (incCounter == true) then
|
if (incCounter == true) then
|
||||||
quest:IncCounter(COUNTER_TALKED);
|
local counterAmount = data:IncCounter(COUNTER_TALKED);
|
||||||
local counterAmount = quest:GetCounter(COUNTER_TALKED);
|
|
||||||
|
|
||||||
attentionMessage(player, 51061, 0, counterAmount, 5); -- You have heard word of the Seedseers. (... of 5)
|
attentionMessage(player, 51061, 0, counterAmount, 5); -- You have heard word of the Seedseers. (... of 5)
|
||||||
|
|
||||||
if (seq000_checkCondition(quest)) then -- All Seers spoken to
|
if (seq000_checkCondition(data)) then -- All Seers spoken to
|
||||||
attentionMessage(player, 25225, 110674); -- "Seeing the Seers" objectives complete!
|
attentionMessage(player, 25225, 110674); -- "Seeing the Seers" objectives complete!
|
||||||
quest:UpdateENPCs(); -- Band-aid for a QFLAG_PLATE issue
|
quest:UpdateENPCs(); -- Band-aid for a QFLAG_PLATE issue
|
||||||
quest:StartSequence(SEQ_001);
|
quest:StartSequence(SEQ_001);
|
||||||
@ -155,12 +155,12 @@ end
|
|||||||
|
|
||||||
|
|
||||||
-- Check if all seers are talked to
|
-- Check if all seers are talked to
|
||||||
function seq000_checkCondition(quest)
|
function seq000_checkCondition(data)
|
||||||
return (quest:GetFlag(FLAG_TALKED_SYBELL) and
|
return (data:GetFlag(FLAG_TALKED_SYBELL) and
|
||||||
quest:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and
|
data:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and
|
||||||
quest:GetFlag(FLAG_TALKED_NELLAURE) and
|
data:GetFlag(FLAG_TALKED_NELLAURE) and
|
||||||
quest:GetFlag(FLAG_TALKED_MESTONNAUX) and
|
data:GetFlag(FLAG_TALKED_MESTONNAUX) and
|
||||||
quest:GetFlag(FLAG_TALKED_LEFWYNE));
|
data:GetFlag(FLAG_TALKED_LEFWYNE));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -169,11 +169,11 @@ function getJournalMapMarkerList(player, quest)
|
|||||||
local possibleMarkers = {};
|
local possibleMarkers = {};
|
||||||
|
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
if (not quest:GetFlag(FLAG_TALKED_SYBELL)) then table.insert(possibleMarkers, MRKR_SYBELL); end
|
if (not data:GetFlag(FLAG_TALKED_SYBELL)) then table.insert(possibleMarkers, MRKR_SYBELL); end
|
||||||
if (not quest:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA)) then table.insert(possibleMarkers, MRKR_KHUMA_MOSHROCA); end
|
if (not data:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA)) then table.insert(possibleMarkers, MRKR_KHUMA_MOSHROCA); end
|
||||||
if (not quest:GetFlag(FLAG_TALKED_NELLAURE)) then table.insert(possibleMarkers, MRKR_NELLAURE); end
|
if (not data:GetFlag(FLAG_TALKED_NELLAURE)) then table.insert(possibleMarkers, MRKR_NELLAURE); end
|
||||||
if (not quest:GetFlag(FLAG_TALKED_MESTONNAUX)) then table.insert(possibleMarkers, MRKR_MESTONNAUX); end
|
if (not data:GetFlag(FLAG_TALKED_MESTONNAUX)) then table.insert(possibleMarkers, MRKR_MESTONNAUX); end
|
||||||
if (not quest:GetFlag(FLAG_TALKED_LEFWYNE)) then table.insert(possibleMarkers, MRKR_LEFWYNE); end
|
if (not data:GetFlag(FLAG_TALKED_LEFWYNE)) then table.insert(possibleMarkers, MRKR_LEFWYNE); end
|
||||||
elseif (sequence == SEQ_001) then
|
elseif (sequence == SEQ_001) then
|
||||||
table.insert(possibleMarkers, MRKR_KINNISON);
|
table.insert(possibleMarkers, MRKR_KINNISON);
|
||||||
end
|
end
|
||||||
|
@ -37,6 +37,7 @@ using Meteor.Map.actors.chara.ai.controllers;
|
|||||||
using Meteor.Map.actors.chara.ai.utils;
|
using Meteor.Map.actors.chara.ai.utils;
|
||||||
using Meteor.Map.actors.chara.ai.state;
|
using Meteor.Map.actors.chara.ai.state;
|
||||||
using Meteor.Map.actors.chara;
|
using Meteor.Map.actors.chara;
|
||||||
|
using Meteor.Map.Actors.QuestNS;
|
||||||
using Meteor.Map.packets.send;
|
using Meteor.Map.packets.send;
|
||||||
using Meteor.Map.packets.send.actor;
|
using Meteor.Map.packets.send.actor;
|
||||||
using Meteor.Map.packets.send.events;
|
using Meteor.Map.packets.send.events;
|
||||||
@ -277,7 +278,7 @@ namespace Meteor.Map.Actors
|
|||||||
CalculateBaseStats();
|
CalculateBaseStats();
|
||||||
|
|
||||||
questStateManager = new QuestStateManager(this);
|
questStateManager = new QuestStateManager(this);
|
||||||
questStateManager.Init();
|
questStateManager.Init(questScenario);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SubPacket> Create0x132Packets()
|
public List<SubPacket> Create0x132Packets()
|
||||||
@ -806,7 +807,7 @@ namespace Meteor.Map.Actors
|
|||||||
foreach (Quest quest in questScenario)
|
foreach (Quest quest in questScenario)
|
||||||
{
|
{
|
||||||
if (quest != null)
|
if (quest != null)
|
||||||
quest.SaveData();
|
quest.GetData().Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1418,33 +1419,253 @@ namespace Meteor.Map.Actors
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//For Lua calls, cause MoonSharp goes retard with uint
|
#region Quests - Script Related
|
||||||
public void AddQuest(int id, bool isSilent = false)
|
// 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);
|
if (instance == null)
|
||||||
}
|
return false;
|
||||||
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
|
|
||||||
|
|
||||||
|
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)
|
public void AddGuildleve(uint id)
|
||||||
{
|
{
|
||||||
int freeSlot = GetFreeGuildleveSlot();
|
int freeSlot = GetFreeGuildleveSlot();
|
||||||
@ -1491,178 +1712,6 @@ 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)
|
public bool HasGuildleve(uint id)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < work.guildleveId.Length; i++)
|
for (int i = 0; i < work.guildleveId.Length; i++)
|
||||||
@ -1673,17 +1722,7 @@ namespace Meteor.Map.Actors
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Quest GetDefaultTalkQuest(Npc npc)
|
public Quest GetDefaultTalkQuest(Npc npc)
|
||||||
{
|
{
|
||||||
@ -1735,14 +1774,11 @@ namespace Meteor.Map.Actors
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Quest[] GetJournalQuestsForNpc(Npc npc)
|
|
||||||
{
|
|
||||||
return Array.FindAll(questScenario, e => e != null && e.IsQuestENPC(this, npc));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Quest[] GetQuestsForNpc(Npc 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)
|
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]));
|
actionList.Add(new CommandResult(Id, 33909, 0, (ushort)charaWork.battleSave.skillLevel[classId - 1]));
|
||||||
|
|
||||||
EquipAbilitiesAtLevel(classId, GetLevel(), actionList);
|
EquipAbilitiesAtLevel(classId, GetLevel(), actionList);
|
||||||
|
questStateManager.UpdateLevel(GetHighestLevel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,67 +20,125 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using Meteor.Map.lua;
|
using Meteor.Map.lua;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Meteor.Map.Actors
|
namespace Meteor.Map.Actors.QuestNS
|
||||||
{
|
{
|
||||||
class Quest : Actor
|
class Quest : Actor
|
||||||
{
|
{
|
||||||
public const ushort SEQ_NOT_STARTED = 65535;
|
public const ushort SEQ_NOT_STARTED = 65535;
|
||||||
public const ushort SEQ_COMPLETED = 65534;
|
public const ushort SEQ_COMPLETED = 65534;
|
||||||
|
|
||||||
private struct QuestData
|
private Player owner;
|
||||||
{
|
|
||||||
public UInt32 flags;
|
|
||||||
public UInt16 counter1;
|
|
||||||
public UInt16 counter2;
|
|
||||||
public UInt16 counter3;
|
|
||||||
public UInt16 counter4;
|
|
||||||
|
|
||||||
public QuestData(uint flags, ushort counter1, ushort counter2, ushort counter3) : this()
|
|
||||||
{
|
|
||||||
this.flags = flags;
|
|
||||||
this.counter1 = counter1;
|
|
||||||
this.counter2 = counter2;
|
|
||||||
this.counter3 = counter3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is only set on instance quests (non static)
|
|
||||||
private Player Owner;
|
|
||||||
private ushort currentSequence;
|
private ushort currentSequence;
|
||||||
private QuestState QuestState;
|
private QuestState questState = null;
|
||||||
private QuestData Data;
|
private QuestData data = null;
|
||||||
private bool dataDirty = false;
|
private bool dataDirty = false;
|
||||||
|
|
||||||
|
// Creates a Static Quest for the StaticActors list.
|
||||||
|
public Quest(uint actorID, string className, string classPath)
|
||||||
|
: base(actorID)
|
||||||
|
{
|
||||||
|
Name = className;
|
||||||
|
this.className = className;
|
||||||
|
this.classPath = classPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a Static Quest from another Static Quest
|
||||||
|
public Quest(Quest staticQuest)
|
||||||
|
: this(staticQuest.Id, staticQuest.Name, staticQuest.classPath)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
// Creates a Instance Quest that has been started.
|
||||||
|
public Quest(Player owner, Quest staticQuest, ushort sequence) : this(staticQuest)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
currentSequence = sequence;
|
||||||
|
questState = new QuestState(owner, this);
|
||||||
|
questState.UpdateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a Instance Quest that has not been started.
|
||||||
|
public Quest(Player owner, Quest staticQuest) : this(owner, staticQuest, SEQ_NOT_STARTED)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#region Getters
|
||||||
|
public uint GetQuestId()
|
||||||
|
{
|
||||||
|
return Id & 0xFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj != null && obj is Quest quest)
|
||||||
|
return quest.Id == this.Id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return base.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsInstance()
|
||||||
|
{
|
||||||
|
return questState != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMainScenario()
|
||||||
|
{
|
||||||
|
uint id = GetQuestId();
|
||||||
|
return id >= 110001 && id <= 110021;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort GetSequence()
|
||||||
|
{
|
||||||
|
return currentSequence;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Quest Data
|
||||||
|
public void SetData(uint flags, ushort counter1, ushort counter2, ushort counter3, ushort counter4)
|
||||||
|
{
|
||||||
|
data = new QuestData(owner, this, flags, counter1, counter2, counter3, counter4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuestData GetData()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasData()
|
||||||
|
{
|
||||||
|
return data != null;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Quest State
|
||||||
public void SetENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
public void SetENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
||||||
{
|
{
|
||||||
if (QuestState != null)
|
if (questState != null)
|
||||||
QuestState.AddENpc(classId, flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
|
questState.AddENpc(classId, flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateENPCs()
|
public void UpdateENPCs()
|
||||||
{
|
{
|
||||||
if (dataDirty)
|
if (dataDirty)
|
||||||
{
|
{
|
||||||
if (QuestState != null)
|
if (questState != null)
|
||||||
QuestState.UpdateState();
|
questState.UpdateState();
|
||||||
dataDirty = false;
|
dataDirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public QuestState GetQuestState()
|
public QuestState GetQuestState()
|
||||||
{
|
{
|
||||||
return QuestState;
|
return questState;
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsInstance()
|
|
||||||
{
|
|
||||||
return Owner != null;
|
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Script Callbacks
|
||||||
public void OnTalk(Player caller, Npc npc)
|
public void OnTalk(Player caller, Npc npc)
|
||||||
{
|
{
|
||||||
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onTalk", true, npc);
|
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onTalk", true, npc);
|
||||||
@ -106,17 +164,9 @@ namespace Meteor.Map.Actors
|
|||||||
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onNpcLS", true, npcLSId);
|
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onNpcLS", true, npcLSId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsQuestENPC(Player caller, Npc npc)
|
|
||||||
{
|
|
||||||
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(caller, this, "IsQuestENPC", true, npc, this);
|
|
||||||
bool scriptReturned = returned != null && returned.Count != 0 && returned[0].typeID == 3;
|
|
||||||
return scriptReturned || QuestState.HasENpc(npc.GetActorClassId());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public object[] GetJournalInformation()
|
public object[] GetJournalInformation()
|
||||||
{
|
{
|
||||||
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "getJournalInformation", true);
|
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "getJournalInformation", true);
|
||||||
if (returned != null && returned.Count != 0)
|
if (returned != null && returned.Count != 0)
|
||||||
return LuaUtils.CreateLuaParamObjectList(returned);
|
return LuaUtils.CreateLuaParamObjectList(returned);
|
||||||
else
|
else
|
||||||
@ -125,16 +175,19 @@ namespace Meteor.Map.Actors
|
|||||||
|
|
||||||
public object[] GetJournalMapMarkerList()
|
public object[] GetJournalMapMarkerList()
|
||||||
{
|
{
|
||||||
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "getJournalMapMarkerList", true);
|
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "getJournalMapMarkerList", true);
|
||||||
if (returned != null && returned.Count != 0)
|
if (returned != null && returned.Count != 0)
|
||||||
return LuaUtils.CreateLuaParamObjectList(returned);
|
return LuaUtils.CreateLuaParamObjectList(returned);
|
||||||
else
|
else
|
||||||
return new object[0];
|
return new object[0];
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public ushort GetSequence()
|
public bool IsQuestENPC(Player caller, Npc npc)
|
||||||
{
|
{
|
||||||
return currentSequence;
|
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(caller, this, "IsQuestENPC", true, npc, this);
|
||||||
|
bool scriptReturned = returned != null && returned.Count != 0 && returned[0].typeID == 3;
|
||||||
|
return scriptReturned || questState.HasENpc(npc.GetActorClassId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartSequence(ushort sequence)
|
public void StartSequence(ushort sequence)
|
||||||
@ -144,193 +197,37 @@ namespace Meteor.Map.Actors
|
|||||||
|
|
||||||
// Send the message that the journal has been updated
|
// Send the message that the journal has been updated
|
||||||
if (currentSequence != SEQ_NOT_STARTED)
|
if (currentSequence != SEQ_NOT_STARTED)
|
||||||
Owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25116, 0x20, (object)GetQuestId());
|
owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25116, 0x20, (object)GetQuestId());
|
||||||
|
|
||||||
currentSequence = sequence;
|
currentSequence = sequence;
|
||||||
dataDirty = true;
|
dataDirty = true;
|
||||||
UpdateENPCs();
|
questState.UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearData()
|
public void OnAccept()
|
||||||
{
|
|
||||||
Data.flags = Data.counter1 = Data.counter2 = Data.counter3 = Data.counter4 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetFlag(int index)
|
|
||||||
{
|
|
||||||
if (index >= 0 && index < 32)
|
|
||||||
{
|
|
||||||
Data.flags |= (uint)(1 << index);
|
|
||||||
dataDirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearFlag(int index)
|
|
||||||
{
|
|
||||||
if (index >= 0 && index < 32)
|
|
||||||
{
|
|
||||||
Data.flags &= (uint)~(1 << index);
|
|
||||||
dataDirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void IncCounter(int num)
|
|
||||||
{
|
|
||||||
dataDirty = true;
|
|
||||||
|
|
||||||
switch (num)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
Data.counter1++;
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
Data.counter2++;
|
|
||||||
return;
|
|
||||||
case 2:
|
|
||||||
Data.counter3++;
|
|
||||||
return;
|
|
||||||
case 3:
|
|
||||||
Data.counter4++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DecCounter(int num)
|
|
||||||
{
|
|
||||||
dataDirty = true;
|
|
||||||
|
|
||||||
switch (num)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
Data.counter1--;
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
Data.counter2--;
|
|
||||||
return;
|
|
||||||
case 2:
|
|
||||||
Data.counter3--;
|
|
||||||
return;
|
|
||||||
case 3:
|
|
||||||
Data.counter4--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCounter(int num, ushort value)
|
|
||||||
{
|
|
||||||
dataDirty = true;
|
|
||||||
|
|
||||||
switch (num)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
Data.counter1 = value;
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
Data.counter2 = value;
|
|
||||||
return;
|
|
||||||
case 2:
|
|
||||||
Data.counter3 = value;
|
|
||||||
return;
|
|
||||||
case 3:
|
|
||||||
Data.counter4 = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool GetFlag(int index)
|
|
||||||
{
|
|
||||||
if (index >= 0 && index < 32)
|
|
||||||
return (Data.flags & (uint) (1 << index)) != 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetFlags()
|
|
||||||
{
|
|
||||||
return Data.flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort GetCounter(int num)
|
|
||||||
{
|
|
||||||
switch (num)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return Data.counter1;
|
|
||||||
case 1:
|
|
||||||
return Data.counter2;
|
|
||||||
case 2:
|
|
||||||
return Data.counter3;
|
|
||||||
case 3:
|
|
||||||
return Data.counter4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveData()
|
|
||||||
{
|
|
||||||
Database.SaveQuest(Owner, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Quest(uint actorID, string name)
|
|
||||||
: base(actorID)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Quest(Player owner, Quest baseQuest): this(owner, baseQuest, SEQ_NOT_STARTED, 0, 0, 0, 0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public Quest(Player owner, Quest baseQuest, ushort sequence, uint flags, ushort counter1, ushort counter2, ushort counter3)
|
|
||||||
: base(baseQuest.Id)
|
|
||||||
{
|
|
||||||
Owner = owner;
|
|
||||||
Name = baseQuest.Name;
|
|
||||||
className = baseQuest.className;
|
|
||||||
classPath = baseQuest.classPath;
|
|
||||||
currentSequence = sequence;
|
|
||||||
QuestState = new QuestState(owner, this);
|
|
||||||
Data = new QuestData(flags, counter1, counter2, counter3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetQuestId()
|
|
||||||
{
|
|
||||||
return Id & 0xFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DoAccept()
|
|
||||||
{
|
{
|
||||||
|
data = new QuestData(owner, this);
|
||||||
if (currentSequence == SEQ_NOT_STARTED)
|
if (currentSequence == SEQ_NOT_STARTED)
|
||||||
LuaEngine.GetInstance().CallLuaFunction(Owner, this, "onStart", false);
|
LuaEngine.GetInstance().CallLuaFunction(owner, this, "onStart", false);
|
||||||
else
|
else
|
||||||
StartSequence(currentSequence);
|
StartSequence(currentSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoComplete()
|
public void OnComplete()
|
||||||
{
|
{
|
||||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", true);
|
LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "onFinish", true);
|
||||||
Owner.SendDataPacket("attention", Server.GetWorldManager().GetActor(), "", 25225, (object)GetQuestId());
|
|
||||||
Owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25225, 0x20, (object)GetQuestId());
|
|
||||||
currentSequence = SEQ_COMPLETED;
|
currentSequence = SEQ_COMPLETED;
|
||||||
|
data = null;
|
||||||
|
questState.UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoAbandon()
|
public void OnAbandon()
|
||||||
{
|
{
|
||||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", false);
|
LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "onFinish", false);
|
||||||
Owner.SendGameMessage(Owner, Server.GetWorldManager().GetActor(), 25236, 0x20, (object)GetQuestId());
|
|
||||||
currentSequence = SEQ_NOT_STARTED;
|
currentSequence = SEQ_NOT_STARTED;
|
||||||
|
data = null;
|
||||||
|
questState.UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is Quest quest)
|
|
||||||
return quest.Id == this.Id;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
167
Map Server/Actors/Quest/QuestData.cs
Normal file
167
Map Server/Actors/Quest/QuestData.cs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Meteor.Map.Actors.QuestNS
|
||||||
|
{
|
||||||
|
class QuestData
|
||||||
|
{
|
||||||
|
private Player owner;
|
||||||
|
private Quest parent;
|
||||||
|
|
||||||
|
private uint flags;
|
||||||
|
private ushort counter1;
|
||||||
|
private ushort counter2;
|
||||||
|
private ushort counter3;
|
||||||
|
private ushort counter4;
|
||||||
|
private bool dataDirty = false;
|
||||||
|
|
||||||
|
public QuestData(Player owner, Quest parent, uint flags, ushort counter1, ushort counter2, ushort counter3, ushort counter4)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
this.parent = parent;
|
||||||
|
this.flags = flags;
|
||||||
|
this.counter1 = counter1;
|
||||||
|
this.counter2 = counter2;
|
||||||
|
this.counter3 = counter3;
|
||||||
|
this.counter4 = counter4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuestData(Player owner, Quest parent)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
this.parent = parent;
|
||||||
|
flags = counter1 = counter2 = counter3 = counter4 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearData()
|
||||||
|
{
|
||||||
|
flags = counter1 = counter2 = counter3 = counter4 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFlag(int index)
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < 32)
|
||||||
|
{
|
||||||
|
flags |= (uint)(1 << index);
|
||||||
|
dataDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearFlag(int index)
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < 32)
|
||||||
|
{
|
||||||
|
flags &= (uint)~(1 << index);
|
||||||
|
dataDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort IncCounter(int num)
|
||||||
|
{
|
||||||
|
dataDirty = true;
|
||||||
|
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
counter1++;
|
||||||
|
return counter1;
|
||||||
|
case 1:
|
||||||
|
counter2++;
|
||||||
|
return counter2;
|
||||||
|
case 2:
|
||||||
|
counter3++;
|
||||||
|
return counter3;
|
||||||
|
case 3:
|
||||||
|
counter4++;
|
||||||
|
return counter4;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataDirty = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort DecCounter(int num)
|
||||||
|
{
|
||||||
|
dataDirty = true;
|
||||||
|
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
counter1--;
|
||||||
|
return counter1;
|
||||||
|
case 1:
|
||||||
|
counter2--;
|
||||||
|
return counter2;
|
||||||
|
case 2:
|
||||||
|
counter3--;
|
||||||
|
return counter3;
|
||||||
|
case 3:
|
||||||
|
counter4--;
|
||||||
|
return counter4;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataDirty = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCounter(int num, ushort value)
|
||||||
|
{
|
||||||
|
dataDirty = true;
|
||||||
|
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
counter1 = value;
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
counter2 = value;
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
counter3 = value;
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
counter4 = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetFlag(int index)
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < 32)
|
||||||
|
return (flags & (uint)(1 << index)) != 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint GetFlags()
|
||||||
|
{
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort GetCounter(int num)
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return counter1;
|
||||||
|
case 1:
|
||||||
|
return counter2;
|
||||||
|
case 2:
|
||||||
|
return counter3;
|
||||||
|
case 3:
|
||||||
|
return counter4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
Database.SaveQuest(owner, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Meteor.Map.Actors
|
namespace Meteor.Map.Actors.QuestNS
|
||||||
{
|
{
|
||||||
class QuestState
|
class QuestState
|
||||||
{
|
{
|
||||||
@ -49,8 +49,8 @@ namespace Meteor.Map.Actors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Player Owner;
|
private readonly Player Owner;
|
||||||
private Quest Parent;
|
private readonly Quest Parent;
|
||||||
private Dictionary<uint, QuestENpc> CurrentENPCs = new Dictionary<uint, QuestENpc>();
|
private Dictionary<uint, QuestENpc> CurrentENPCs = new Dictionary<uint, QuestENpc>();
|
||||||
private Dictionary<uint, QuestENpc> OldENPCs = new Dictionary<uint, QuestENpc>();
|
private Dictionary<uint, QuestENpc> OldENPCs = new Dictionary<uint, QuestENpc>();
|
||||||
|
|
||||||
@ -58,7 +58,6 @@ namespace Meteor.Map.Actors
|
|||||||
{
|
{
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
UpdateState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
||||||
@ -105,8 +104,15 @@ namespace Meteor.Map.Actors
|
|||||||
CurrentENPCs = new Dictionary<uint, QuestENpc>();
|
CurrentENPCs = new Dictionary<uint, QuestENpc>();
|
||||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, Parent, "onStateChange", false, currentSeq);
|
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, Parent, "onStateChange", false, currentSeq);
|
||||||
foreach (var enpc in OldENPCs)
|
foreach (var enpc in OldENPCs)
|
||||||
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value);
|
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value, true);
|
||||||
OldENPCs = null;
|
OldENPCs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeleteState()
|
||||||
|
{
|
||||||
|
foreach (var enpc in CurrentENPCs)
|
||||||
|
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value, true);
|
||||||
|
CurrentENPCs.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Meteor.Map.Actors
|
namespace Meteor.Map.Actors.QuestNS
|
||||||
{
|
{
|
||||||
class QuestStateManager
|
class QuestStateManager
|
||||||
{
|
{
|
||||||
@ -21,16 +21,30 @@ namespace Meteor.Map.Actors
|
|||||||
private readonly Bitstream GCRankBitfield = new Bitstream(SCENARIO_MAX, true);
|
private readonly Bitstream GCRankBitfield = new Bitstream(SCENARIO_MAX, true);
|
||||||
|
|
||||||
private List<Quest> ActiveQuests = new List<Quest>();
|
private List<Quest> ActiveQuests = new List<Quest>();
|
||||||
|
private Dictionary<uint, QuestState> QuestStateTable = new Dictionary<uint, QuestState>();
|
||||||
|
|
||||||
public QuestStateManager(Player player)
|
public QuestStateManager(Player player)
|
||||||
{
|
{
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init(Quest[] questScenario)
|
||||||
{
|
{
|
||||||
|
// Preload any quests that the player loaded
|
||||||
|
if (questScenario != null)
|
||||||
|
{
|
||||||
|
foreach (var quest in questScenario)
|
||||||
|
{
|
||||||
|
if (quest != null)
|
||||||
|
{
|
||||||
|
ActiveQuests.Add(quest);
|
||||||
|
AvailableQuestsBitfield.Set(quest.GetQuestId() - SCENARIO_START);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Init MinLv
|
// Init MinLv
|
||||||
QuestData[] minLvl = Server.GetQuestGamedataByMaxLvl(player.GetHighestLevel(), true);
|
QuestGameData[] minLvl = Server.GetQuestGamedataByMaxLvl(player.GetHighestLevel(), true);
|
||||||
foreach (var questData in minLvl)
|
foreach (var questData in minLvl)
|
||||||
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
||||||
|
|
||||||
@ -43,28 +57,29 @@ namespace Meteor.Map.Actors
|
|||||||
else
|
else
|
||||||
PrereqBitfield.Clear(questData.Id - SCENARIO_START);
|
PrereqBitfield.Clear(questData.Id - SCENARIO_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeAvailable();
|
ComputeAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateLevel(int level)
|
public void UpdateLevel(int level)
|
||||||
{
|
{
|
||||||
QuestData[] updated = Server.GetQuestGamedataByMaxLvl(level);
|
QuestGameData[] updated = Server.GetQuestGamedataByMaxLvl(level);
|
||||||
foreach (var questData in updated)
|
foreach (var questData in updated)
|
||||||
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
||||||
ComputeAvailable();
|
ComputeAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateQuestComplete(Quest quest)
|
public void UpdateQuestCompleted(Quest quest)
|
||||||
{
|
{
|
||||||
QuestData[] updated = Server.GetQuestGamedataByPrerequisite(quest.GetQuestId());
|
QuestGameData[] updated = Server.GetQuestGamedataByPrerequisite(quest.GetQuestId());
|
||||||
foreach (var questData in updated)
|
foreach (var questData in updated)
|
||||||
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
||||||
ComputeAvailable();
|
ComputeAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QuestAdded(Quest quest)
|
public void UpdateQuestAbandoned()
|
||||||
{
|
{
|
||||||
ActiveQuests.Remove(quest);
|
ComputeAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ComputeAvailable()
|
private void ComputeAvailable()
|
||||||
@ -90,9 +105,9 @@ namespace Meteor.Map.Actors
|
|||||||
int index = i * 8 + shift;
|
int index = i * 8 + shift;
|
||||||
Quest quest = (Quest)Server.GetStaticActors(0xA0F00000 | (SCENARIO_START + (uint)index));
|
Quest quest = (Quest)Server.GetStaticActors(0xA0F00000 | (SCENARIO_START + (uint)index));
|
||||||
if (!AvailableQuestsBitfield.Get(index))
|
if (!AvailableQuestsBitfield.Get(index))
|
||||||
ActiveQuests.Add(new Quest(player, quest));
|
AddActiveQuest(quest);
|
||||||
else
|
else
|
||||||
ActiveQuests.Remove(quest);
|
RemoveActiveQuest(quest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,6 +115,39 @@ namespace Meteor.Map.Actors
|
|||||||
AvailableQuestsBitfield.SetTo(result);
|
AvailableQuestsBitfield.SetTo(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
public Quest[] GetQuestsForNpc(Npc npc)
|
public Quest[] GetQuestsForNpc(Npc npc)
|
||||||
{
|
{
|
||||||
return ActiveQuests.FindAll(quest => quest.IsQuestENPC(player, npc)).ToArray();
|
return ActiveQuests.FindAll(quest => quest.IsQuestENPC(player, npc)).ToArray();
|
||||||
|
@ -20,6 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using Meteor.Common;
|
using Meteor.Common;
|
||||||
|
using Meteor.Map.Actors.QuestNS;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -98,7 +99,7 @@ namespace Meteor.Map.Actors
|
|||||||
if (actorType.Equals("Command"))
|
if (actorType.Equals("Command"))
|
||||||
actor = new Command(id, actorName);
|
actor = new Command(id, actorName);
|
||||||
else if (actorType.Equals("Quest"))
|
else if (actorType.Equals("Quest"))
|
||||||
actor = new Quest(id, actorName);
|
actor = new Quest(id, actorName, output);
|
||||||
//else if (actorType.Equals("Status"))
|
//else if (actorType.Equals("Status"))
|
||||||
//mStaticActors.Add(id, new Status(id, actorName));
|
//mStaticActors.Add(id, new Status(id, actorName));
|
||||||
else if (actorType.Equals("Judge"))
|
else if (actorType.Equals("Judge"))
|
||||||
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Meteor.Map.DataObjects
|
namespace Meteor.Map.DataObjects
|
||||||
{
|
{
|
||||||
class QuestData
|
class QuestGameData
|
||||||
{
|
{
|
||||||
public uint Id { get; }
|
public uint Id { get; }
|
||||||
public string ClassName { get; }
|
public string ClassName { get; }
|
||||||
@ -15,7 +15,7 @@ namespace Meteor.Map.DataObjects
|
|||||||
public int MinLevel { get; }
|
public int MinLevel { get; }
|
||||||
public int MinGCRank { get; }
|
public int MinGCRank { get; }
|
||||||
|
|
||||||
public QuestData(uint id, string className, string name, uint prereq, int minLv, int minGcRank)
|
public QuestGameData(uint id, string className, string name, uint prereq, int minLv, int minGcRank)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
ClassName = className;
|
ClassName = className;
|
@ -25,8 +25,8 @@ using Meteor.Map.Actors;
|
|||||||
using Meteor.Map.packets.send.actor;
|
using Meteor.Map.packets.send.actor;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Meteor.Map.actors.chara.npc;
|
using Meteor.Map.actors.chara.npc;
|
||||||
using static Meteor.Map.Actors.Quest;
|
using Meteor.Map.Actors.QuestNS;
|
||||||
using static Meteor.Map.Actors.QuestState;
|
using static Meteor.Map.Actors.QuestNS.QuestState;
|
||||||
|
|
||||||
namespace Meteor.Map.DataObjects
|
namespace Meteor.Map.DataObjects
|
||||||
{
|
{
|
||||||
|
@ -28,12 +28,13 @@ using Meteor.Map.utils;
|
|||||||
using Meteor.Map.packets.send.player;
|
using Meteor.Map.packets.send.player;
|
||||||
using Meteor.Map.DataObjects;
|
using Meteor.Map.DataObjects;
|
||||||
using Meteor.Map.Actors;
|
using Meteor.Map.Actors;
|
||||||
|
using Meteor.Map.Actors.QuestNS;
|
||||||
using Meteor.Map.actors.chara.player;
|
using Meteor.Map.actors.chara.player;
|
||||||
using Meteor.Map.packets.receive.supportdesk;
|
using Meteor.Map.packets.receive.supportdesk;
|
||||||
using Meteor.Map.actors.chara.npc;
|
using Meteor.Map.actors.chara.npc;
|
||||||
using Meteor.Map.actors.chara.ai;
|
using Meteor.Map.actors.chara.ai;
|
||||||
using Meteor.Map.packets.send.actor.battle;
|
using Meteor.Map.packets.send.actor.battle;
|
||||||
using Meteor.Map.DataObjects;
|
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace Meteor.Map
|
namespace Meteor.Map
|
||||||
@ -72,11 +73,11 @@ namespace Meteor.Map
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<uint, QuestData> GetQuestGamedata()
|
public static Dictionary<uint, QuestGameData> GetQuestGamedata()
|
||||||
{
|
{
|
||||||
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||||
{
|
{
|
||||||
Dictionary<uint, QuestData> gamedataQuests = new Dictionary<uint, QuestData>();
|
Dictionary<uint, QuestGameData> gamedataQuests = new Dictionary<uint, QuestGameData>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -88,8 +89,7 @@ namespace Meteor.Map
|
|||||||
className,
|
className,
|
||||||
questName,
|
questName,
|
||||||
prerequisite,
|
prerequisite,
|
||||||
minLevel,
|
minLevel
|
||||||
minGCRank
|
|
||||||
FROM gamedata_quests
|
FROM gamedata_quests
|
||||||
";
|
";
|
||||||
|
|
||||||
@ -104,8 +104,8 @@ namespace Meteor.Map
|
|||||||
string name = reader.GetString("questName");
|
string name = reader.GetString("questName");
|
||||||
uint prerequisite = reader.GetUInt32("prerequisite");
|
uint prerequisite = reader.GetUInt32("prerequisite");
|
||||||
ushort minLevel = reader.GetUInt16("minLevel");
|
ushort minLevel = reader.GetUInt16("minLevel");
|
||||||
ushort minRank = reader.GetUInt16("minGCRank");
|
//ushort minRank = reader.GetUInt16("minGCRank");
|
||||||
gamedataQuests.Add(questId, new QuestData(questId, code, name, prerequisite, minLevel, minRank));
|
gamedataQuests.Add(questId, new QuestGameData(questId, code, name, prerequisite, minLevel, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -544,6 +544,8 @@ namespace Meteor.Map
|
|||||||
string query;
|
string query;
|
||||||
MySqlCommand cmd;
|
MySqlCommand cmd;
|
||||||
|
|
||||||
|
QuestData qData = quest.GetData();
|
||||||
|
|
||||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -564,10 +566,14 @@ namespace Meteor.Map
|
|||||||
cmd.Parameters.AddWithValue("@slot", slot);
|
cmd.Parameters.AddWithValue("@slot", slot);
|
||||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.Id);
|
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.Id);
|
||||||
cmd.Parameters.AddWithValue("@sequence", quest.GetSequence());
|
cmd.Parameters.AddWithValue("@sequence", quest.GetSequence());
|
||||||
cmd.Parameters.AddWithValue("@flags", quest.GetFlags());
|
|
||||||
cmd.Parameters.AddWithValue("@counter1", quest.GetCounter(1));
|
if (qData != null)
|
||||||
cmd.Parameters.AddWithValue("@counter2", quest.GetCounter(2));
|
{
|
||||||
cmd.Parameters.AddWithValue("@counter3", quest.GetCounter(3));
|
cmd.Parameters.AddWithValue("@flags", qData.GetFlags());
|
||||||
|
cmd.Parameters.AddWithValue("@counter1", qData.GetCounter(1));
|
||||||
|
cmd.Parameters.AddWithValue("@counter2", qData.GetCounter(2));
|
||||||
|
cmd.Parameters.AddWithValue("@counter3", qData.GetCounter(3));
|
||||||
|
}
|
||||||
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
@ -1218,11 +1224,13 @@ namespace Meteor.Map
|
|||||||
ushort counter1 = reader.GetUInt16("counter1");
|
ushort counter1 = reader.GetUInt16("counter1");
|
||||||
ushort counter2 = reader.GetUInt16("counter2");
|
ushort counter2 = reader.GetUInt16("counter2");
|
||||||
ushort counter3 = reader.GetUInt16("counter3");
|
ushort counter3 = reader.GetUInt16("counter3");
|
||||||
|
//ushort counter4 = reader.GetUInt16("counter4");
|
||||||
|
|
||||||
Quest baseQuest = (Quest) Server.GetStaticActors(questId);
|
Quest baseQuest = (Quest) Server.GetStaticActors(questId);
|
||||||
|
|
||||||
player.playerWork.questScenario[index] = questId;
|
player.playerWork.questScenario[index] = questId;
|
||||||
player.questScenario[index] = new Quest(player, baseQuest, sequence, flags, counter1, counter2, counter3);
|
player.questScenario[index] = new Quest(player, baseQuest, sequence);
|
||||||
|
player.questScenario[index].SetData(flags, counter1, counter2, counter3, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ using Meteor.Map.packets.receive.events;
|
|||||||
using Meteor.Map.packets.send;
|
using Meteor.Map.packets.send;
|
||||||
using Meteor.Map.packets.send.events;
|
using Meteor.Map.packets.send.events;
|
||||||
using MoonSharp.Interpreter;
|
using MoonSharp.Interpreter;
|
||||||
using MoonSharp.Interpreter.Interop;
|
|
||||||
using MoonSharp.Interpreter.Loaders;
|
using MoonSharp.Interpreter.Loaders;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -37,11 +36,11 @@ using Meteor.Map.actors.area;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Meteor.Map.actors.chara.ai;
|
using Meteor.Map.actors.chara.ai;
|
||||||
using Meteor.Map.actors.chara.ai.controllers;
|
using Meteor.Map.actors.chara.ai.controllers;
|
||||||
using Meteor.Map.DataObjects;
|
|
||||||
using Meteor.Map.actors.chara.player;
|
using Meteor.Map.actors.chara.player;
|
||||||
using Meteor.Map.Actors.Chara;
|
using Meteor.Map.Actors.Chara;
|
||||||
using Meteor.Map.DataObjects.chara;
|
using Meteor.Map.DataObjects.chara;
|
||||||
using Meteor.Map.actors.chara;
|
using Meteor.Map.actors.chara;
|
||||||
|
using Meteor.Map.Actors.QuestNS;
|
||||||
|
|
||||||
namespace Meteor.Map.lua
|
namespace Meteor.Map.lua
|
||||||
{
|
{
|
||||||
@ -78,6 +77,7 @@ namespace Meteor.Map.lua
|
|||||||
UserData.RegisterType<Command>();
|
UserData.RegisterType<Command>();
|
||||||
UserData.RegisterType<Npc>();
|
UserData.RegisterType<Npc>();
|
||||||
UserData.RegisterType<Quest>();
|
UserData.RegisterType<Quest>();
|
||||||
|
UserData.RegisterType<QuestData>();
|
||||||
UserData.RegisterType<Zone>();
|
UserData.RegisterType<Zone>();
|
||||||
UserData.RegisterType<InventoryItem>();
|
UserData.RegisterType<InventoryItem>();
|
||||||
UserData.RegisterType<ItemPackage>();
|
UserData.RegisterType<ItemPackage>();
|
||||||
|
@ -180,12 +180,13 @@
|
|||||||
<Compile Include="Actors\Group\Work\RelationWork.cs" />
|
<Compile Include="Actors\Group\Work\RelationWork.cs" />
|
||||||
<Compile Include="Actors\Judge\Judge.cs" />
|
<Compile Include="Actors\Judge\Judge.cs" />
|
||||||
<Compile Include="Actors\Quest\Quest.cs" />
|
<Compile Include="Actors\Quest\Quest.cs" />
|
||||||
|
<Compile Include="Actors\Quest\QuestData.cs" />
|
||||||
<Compile Include="Actors\Quest\QuestState.cs" />
|
<Compile Include="Actors\Quest\QuestState.cs" />
|
||||||
<Compile Include="Actors\Quest\QuestStateManager.cs" />
|
<Compile Include="Actors\Quest\QuestStateManager.cs" />
|
||||||
<Compile Include="Actors\StaticActors.cs" />
|
<Compile Include="Actors\StaticActors.cs" />
|
||||||
<Compile Include="Actors\World\WorldMaster.cs" />
|
<Compile Include="Actors\World\WorldMaster.cs" />
|
||||||
<Compile Include="DataObjects\GuildleveData.cs" />
|
<Compile Include="DataObjects\GuildleveData.cs" />
|
||||||
<Compile Include="DataObjects\QuestData.cs" />
|
<Compile Include="DataObjects\QuestGameData.cs" />
|
||||||
<Compile Include="DataObjects\Recipe.cs" />
|
<Compile Include="DataObjects\Recipe.cs" />
|
||||||
<Compile Include="DataObjects\RecipeResolver.cs" />
|
<Compile Include="DataObjects\RecipeResolver.cs" />
|
||||||
<Compile Include="DataObjects\TradeTransaction.cs" />
|
<Compile Include="DataObjects\TradeTransaction.cs" />
|
||||||
|
@ -50,7 +50,7 @@ namespace Meteor.Map
|
|||||||
private static WorldManager WorldManager;
|
private static WorldManager WorldManager;
|
||||||
private static Dictionary<uint, ItemData> GamedataItems;
|
private static Dictionary<uint, ItemData> GamedataItems;
|
||||||
private static Dictionary<uint, GuildleveData> GamedataGuildleves;
|
private static Dictionary<uint, GuildleveData> GamedataGuildleves;
|
||||||
private static Dictionary<uint, QuestData> GamedataQuests;
|
private static Dictionary<uint, QuestGameData> GamedataQuests;
|
||||||
private static StaticActors StaticActors;
|
private static StaticActors StaticActors;
|
||||||
|
|
||||||
private PacketProcessor mProcessor;
|
private PacketProcessor mProcessor;
|
||||||
@ -332,7 +332,7 @@ namespace Meteor.Map
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QuestData GetQuestGamedata(uint id)
|
public static QuestGameData GetQuestGamedata(uint id)
|
||||||
{
|
{
|
||||||
if (GamedataQuests.ContainsKey(id))
|
if (GamedataQuests.ContainsKey(id))
|
||||||
return GamedataQuests[id];
|
return GamedataQuests[id];
|
||||||
@ -341,7 +341,7 @@ namespace Meteor.Map
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static QuestData[] GetQuestGamedataByMaxLvl(int lvl, bool all = false)
|
public static QuestGameData[] GetQuestGamedataByMaxLvl(int lvl, bool all = false)
|
||||||
{
|
{
|
||||||
if (all)
|
if (all)
|
||||||
return GamedataQuests.Values.Where(quest => quest.MinLevel > 0 && quest.MinLevel <= lvl).ToArray();
|
return GamedataQuests.Values.Where(quest => quest.MinLevel > 0 && quest.MinLevel <= lvl).ToArray();
|
||||||
@ -349,17 +349,17 @@ namespace Meteor.Map
|
|||||||
return GamedataQuests.Values.Where(quest => quest.MinLevel > 0 && quest.MinLevel == lvl).ToArray();
|
return GamedataQuests.Values.Where(quest => quest.MinLevel > 0 && quest.MinLevel == lvl).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QuestData[] GetQuestGamedataByPrerequisite(uint questId)
|
public static QuestGameData[] GetQuestGamedataByPrerequisite(uint questId)
|
||||||
{
|
{
|
||||||
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest == questId).ToArray();
|
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest == questId).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QuestData[] GetQuestGamedataAllPrerequisite()
|
public static QuestGameData[] GetQuestGamedataAllPrerequisite()
|
||||||
{
|
{
|
||||||
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest != 0).ToArray();
|
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest != 0).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QuestData[] GetQuestGamedataAllGCRanked()
|
public static QuestGameData[] GetQuestGamedataAllGCRanked()
|
||||||
{
|
{
|
||||||
return GamedataQuests.Values.Where(quest => quest.MinGCRank != 0).ToArray();
|
return GamedataQuests.Values.Where(quest => quest.MinGCRank != 0).ToArray();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user