mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-25 14:17:46 +00:00
Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system
This commit is contained in:
commit
594e08f990
84 changed files with 2660 additions and 1279 deletions
204
Common Class Lib/Bitstream.cs
Normal file
204
Common Class Lib/Bitstream.cs
Normal file
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Meteor.Common
|
||||
{
|
||||
public class Bitstream
|
||||
{
|
||||
private byte[] Data;
|
||||
|
||||
public Bitstream(uint numBits, bool setAllTrue = false)
|
||||
{
|
||||
Debug.Assert(numBits % 8 == 0);
|
||||
Debug.Assert(numBits % 4 == 0);
|
||||
Data = new byte[numBits / 8];
|
||||
|
||||
if (setAllTrue)
|
||||
SetAll(true);
|
||||
}
|
||||
|
||||
public Bitstream(bool[] boolArray)
|
||||
{
|
||||
Data = Utils.ConvertBoolArrayToBinaryStream(boolArray);
|
||||
}
|
||||
|
||||
private Bitstream(byte[] byteArray)
|
||||
{
|
||||
Data = byteArray;
|
||||
}
|
||||
|
||||
public void SetAll(bool to)
|
||||
{
|
||||
for (int i = 0; i < Data.Length; i += 4)
|
||||
{
|
||||
Data[i] = Data[i + 1] = Data[i + 2] = Data[i + 3] = (byte)(to ? 0xFF : 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTo(Bitstream result)
|
||||
{
|
||||
Debug.Assert(Data.Length == result.Data.Length);
|
||||
for (int i = 0; i < result.Data.Length; i += 4)
|
||||
{
|
||||
Data[i] = result.Data[i];
|
||||
Data[i + 1] = result.Data[i + 1];
|
||||
Data[i + 2] = result.Data[i + 2];
|
||||
Data[i + 3] = result.Data[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTo(bool[] result)
|
||||
{
|
||||
Debug.Assert(Data.Length == result.Length / 8);
|
||||
Data = Utils.ConvertBoolArrayToBinaryStream(result);
|
||||
}
|
||||
|
||||
public bool Get(uint at)
|
||||
{
|
||||
return Get((int)at);
|
||||
}
|
||||
|
||||
public bool Get(int at)
|
||||
{
|
||||
int bytePos = at / 8;
|
||||
int bitPos = at % 8;
|
||||
|
||||
return (Data[bytePos] & (1 << bitPos)) != 0;
|
||||
}
|
||||
|
||||
public void Set(uint at)
|
||||
{
|
||||
Set((int)at);
|
||||
}
|
||||
|
||||
public void Set(int at)
|
||||
{
|
||||
int bytePos = at / 8;
|
||||
int bitPos = at % 8;
|
||||
Data[bytePos] |= (byte)(1 << bitPos);
|
||||
}
|
||||
|
||||
public void Clear(uint at)
|
||||
{
|
||||
Clear((int)at);
|
||||
}
|
||||
|
||||
public void Clear(int at)
|
||||
{
|
||||
int bytePos = at / 8;
|
||||
int bitPos = at % 8;
|
||||
Data[bytePos] &= (byte)~(1 << bitPos);
|
||||
}
|
||||
|
||||
public void NOT()
|
||||
{
|
||||
for (int i = 0; i < Data.Length; i += 4)
|
||||
{
|
||||
Data[i] = (byte)~Data[i];
|
||||
Data[i + 1] = (byte)~Data[i + 1];
|
||||
Data[i + 2] = (byte)~Data[i + 2];
|
||||
Data[i + 3] = (byte)~Data[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
public void OR(Bitstream other)
|
||||
{
|
||||
Debug.Assert(Data.Length == other.Data.Length);
|
||||
for (int i = 0; i < Data.Length; i += 4)
|
||||
{
|
||||
Data[i] |= other.Data[i];
|
||||
Data[i + 1] |= other.Data[i + 1];
|
||||
Data[i + 2] |= other.Data[i + 2];
|
||||
Data[i + 3] |= other.Data[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
public void AND(Bitstream other)
|
||||
{
|
||||
Debug.Assert(Data.Length == other.Data.Length);
|
||||
for (int i = 0; i < Data.Length; i += 4)
|
||||
{
|
||||
Data[i] &= other.Data[i];
|
||||
Data[i + 1] &= other.Data[i + 1];
|
||||
Data[i + 2] &= other.Data[i + 2];
|
||||
Data[i + 3] &= other.Data[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
public void XOR(Bitstream other)
|
||||
{
|
||||
Debug.Assert(Data.Length == other.Data.Length);
|
||||
for (int i = 0; i < Data.Length; i += 4)
|
||||
{
|
||||
Data[i] ^= other.Data[i];
|
||||
Data[i + 1] ^= other.Data[i + 1];
|
||||
Data[i + 2] ^= other.Data[i + 2];
|
||||
Data[i + 3] ^= other.Data[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
public Bitstream Copy()
|
||||
{
|
||||
byte[] copy = new byte[Data.Length];
|
||||
Array.Copy(Data, copy, Data.Length);
|
||||
return new Bitstream(copy);
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
public byte[] GetSlice(ushort from, ushort to)
|
||||
{
|
||||
int remainder = ((to - from) % 8 != 0) ? 1 : 0;
|
||||
byte[] toReturn = new byte[((to - from) / 8) + remainder + 1];
|
||||
toReturn[toReturn.Length - 1] = 0x3;
|
||||
|
||||
|
||||
byte curByte = 0;
|
||||
|
||||
int destByteIndx = 0;
|
||||
int destShiftIndx = 0;
|
||||
int srcByteIndx = from / 8;
|
||||
int srcShiftIndx = from % 8;
|
||||
|
||||
for (int i = from; i <= to; i++)
|
||||
{
|
||||
// Skip Zeros
|
||||
if (Data[srcByteIndx] == 0)
|
||||
{
|
||||
srcByteIndx++;
|
||||
srcShiftIndx = 0;
|
||||
destByteIndx++;
|
||||
i += 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool val = (Data[srcByteIndx] & (1 << srcShiftIndx++)) != 0;
|
||||
|
||||
curByte |= (byte)((val ? 1 : 0) << destShiftIndx++);
|
||||
if (srcShiftIndx == 8)
|
||||
{
|
||||
srcShiftIndx = 0;
|
||||
srcByteIndx++;
|
||||
}
|
||||
if (destShiftIndx == 8)
|
||||
{
|
||||
toReturn[destByteIndx++] = curByte;
|
||||
destShiftIndx = 0;
|
||||
curByte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (destByteIndx == toReturn.Length - 2)
|
||||
toReturn[destByteIndx] = curByte;
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -87,6 +87,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="BasePacket.cs" />
|
||||
<Compile Include="Bitfield.cs" />
|
||||
<Compile Include="Bitstream.cs" />
|
||||
<Compile Include="Blowfish.cs" />
|
||||
<Compile Include="EfficientHashTables.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -245,7 +245,7 @@ namespace Meteor.Common
|
|||
{
|
||||
for (var bitCount = 0; bitCount < 8; bitCount++)
|
||||
{
|
||||
if (i + bitCount >= array.Length)
|
||||
if (i + bitCount >= array.Length - 1)
|
||||
break;
|
||||
data[dataCounter] = (byte)(((array[i + bitCount] ? 1 : 0) << 7 - bitCount) | data[dataCounter]);
|
||||
}
|
||||
|
@ -255,6 +255,26 @@ namespace Meteor.Common
|
|||
return data;
|
||||
}
|
||||
|
||||
public static bool[] ConvertBinaryStreamToBoolArray(byte[] bytes)
|
||||
{
|
||||
bool[] data = new bool[bytes.Length * 8];
|
||||
|
||||
int boolCounter = 0;
|
||||
for (int i = 0; i < bytes.Length; i ++)
|
||||
{
|
||||
if (bytes[i] == 0)
|
||||
{
|
||||
boolCounter += 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int bitCount = 0; bitCount < 8; bitCount++)
|
||||
data[boolCounter++] = (bytes[i] >> bitCount & 1) == 1;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string ToStringBase63(int number)
|
||||
{
|
||||
var lookup = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
|
58
Data/scripts/commands/gm/completedQuest.lua
Normal file
58
Data/scripts/commands/gm/completedQuest.lua
Normal file
|
@ -0,0 +1,58 @@
|
|||
require("global");
|
||||
|
||||
properties = {
|
||||
permissions = 0,
|
||||
parameters = "dd",
|
||||
description =
|
||||
[[
|
||||
Sets if a quest is completed.
|
||||
!completedQuest <questId> true/false
|
||||
]],
|
||||
}
|
||||
|
||||
function onTrigger(player, argc, questId, flag)
|
||||
|
||||
print("HEY");
|
||||
local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
|
||||
local sender = "[completedQuest] ";
|
||||
local message = "Error";
|
||||
|
||||
if (argc < 1) then
|
||||
return;
|
||||
end
|
||||
|
||||
local questId = tonumber(questId);
|
||||
local flag = flag or nil;
|
||||
|
||||
-- Fail if not valid questId
|
||||
if (questId < 110001 or questId > 110001 + 2048) then
|
||||
player:SendMessage(messageID, sender, "Invalid questId entered");
|
||||
return;
|
||||
end
|
||||
|
||||
-- Getting
|
||||
if (arc == 1) then
|
||||
player:SendMessage(messageID, sender, string.format("Quest %d completion is set to: %s", questId, tostring(player:IsQuestCompleted(questId))));
|
||||
return;
|
||||
-- Setting
|
||||
else
|
||||
-- Fail if not valid flag
|
||||
if (not flag == nil) then
|
||||
player:SendMessage(messageID, sender, "Invalid flag entered");
|
||||
else
|
||||
local boolFlag = false;
|
||||
|
||||
if (flag == "true" or flag == "1" or flag == "on" or flag == "O") then
|
||||
boolFlag = true;
|
||||
elseif (flag == "false" or flag == "0" or flag == "off" or flag == "X") then
|
||||
boolFlag = false;
|
||||
elseif flag == "flip" or flag == "toggle" then
|
||||
boolFlag = not player:IsQuestCompleted(questId);
|
||||
end
|
||||
|
||||
player:SetQuestComplete(questId, boolFlag);
|
||||
player:SendMessage(messageID, sender, string.format("Quest %d completion set to: %s", questId, tostring(player:IsQuestCompleted(questId))));
|
||||
return;
|
||||
end
|
||||
end
|
||||
end
|
|
@ -66,7 +66,7 @@ function onTrigger(player, argc, command, var1, var2, var3)
|
|||
|
||||
local flagStr = "";
|
||||
for i=0,31,1 do
|
||||
if (quest:GetFlag(i)) then
|
||||
if (quest:GetData():GetFlag(i)) then
|
||||
flagStr = flagStr .. "O";
|
||||
else
|
||||
flagStr = flagStr .. "X";
|
||||
|
@ -76,10 +76,12 @@ function onTrigger(player, argc, command, var1, var2, var3)
|
|||
end
|
||||
end
|
||||
|
||||
local data = quest:GetData();
|
||||
|
||||
message = string.format("\nInfo for quest %s [%d]\n", quest.Name, quest:GetQuestId());
|
||||
message = message .. string.format("Current Sequence: %d\n", quest:getSequence());
|
||||
message = message .. string.format("Flags: \n%s\n", flagStr)
|
||||
message = message .. string.format("Counters: %d,%d,%d,%d", quest:getCounter(0), quest:getCounter(1), quest:getCounter(2), quest:getCounter(3));
|
||||
message = message .. string.format("Counters: %d,%d,%d,%d", data:getCounter(0), data:getCounter(1), data:getCounter(2), data:getCounter(3));
|
||||
else
|
||||
message = ("Quest not active: "..var1);
|
||||
end
|
||||
|
@ -118,7 +120,7 @@ function onTrigger(player, argc, command, var1, var2, var3)
|
|||
boolvar = false;
|
||||
elseif var3 == "flip" or var3 == "toggle" then
|
||||
if player:HasQuest(questvar) == true then
|
||||
boolvar = not player:GetQuest(questvar):GetFlag(flagvar);
|
||||
boolvar = not player:GetQuest(questvar):GetData():GetFlag(flagvar);
|
||||
end
|
||||
else
|
||||
message = ("error: flag: boolean not recognized");
|
||||
|
@ -126,13 +128,13 @@ function onTrigger(player, argc, command, var1, var2, var3)
|
|||
return;
|
||||
end
|
||||
|
||||
var4 = player:GetQuest(questvar):GetFlag(flagvar);
|
||||
var4 = player:GetQuest(questvar):GetData():GetFlag(flagvar);
|
||||
|
||||
if var4 ~= boolvar then
|
||||
if (boolvar == true) then
|
||||
player:GetQuest(questvar):SetFlag(flagvar);
|
||||
player:GetQuest(questvar):GetData():SetFlag(flagvar);
|
||||
else
|
||||
player:GetQuest(questvar):ClearFlag(flagvar);
|
||||
player:GetQuest(questvar):GetData():ClearFlag(flagvar);
|
||||
end
|
||||
player:GetQuest(questvar):UpdateENPCs();
|
||||
player:GetQuest(questvar):SaveData();
|
||||
|
@ -152,7 +154,7 @@ function onTrigger(player, argc, command, var1, var2, var3)
|
|||
questvar = tonumber(var1);
|
||||
index = (tonumber(var2));
|
||||
|
||||
player:GetQuest(questvar):SetCounter(index, tonumber(var3));
|
||||
player:GetQuest(questvar):GetData():SetCounter(index, tonumber(var3));
|
||||
player:GetQuest(questvar):UpdateENPCs();
|
||||
player:GetQuest(questvar):SaveData();
|
||||
message = ("changing counter "..tonumber(var2).." to "..var3);
|
||||
|
|
|
@ -41,8 +41,6 @@ FLAG_TALKED_LEFWYNE = 4;
|
|||
-- Quest Counters
|
||||
COUNTER_TALKED = 0;
|
||||
|
||||
--offerQuestResult = callClientFunction(player, "delegateEvent", player, quest, "processEventOffersStart");
|
||||
|
||||
function onStart(player, quest)
|
||||
quest:StartSequence(SEQ_000);
|
||||
end
|
||||
|
@ -50,79 +48,93 @@ end
|
|||
function onFinish(player, quest)
|
||||
end
|
||||
|
||||
function onSequence(player, quest, sequence)
|
||||
function onStateChange(player, quest, sequence)
|
||||
if (sequence == 65535) then
|
||||
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
||||
end
|
||||
|
||||
local data = quest:GetData();
|
||||
if (sequence == SEQ_000) then
|
||||
quest:AddENpc(KINNISON);
|
||||
quest:AddENpc(SYBELL, (not quest:GetFlag(FLAG_TALKED_SYBELL) and QFLAG_PLATE or QFLAG_NONE));
|
||||
quest:AddENpc(KHUMA_MOSHROCA, (not quest:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and QFLAG_PLATE or QFLAG_NONE));
|
||||
quest:AddENpc(NELLAURE, (not quest:GetFlag(FLAG_TALKED_NELLAURE) and QFLAG_PLATE or QFLAG_NONE));
|
||||
quest:AddENpc(MESTONNAUX, (not quest:GetFlag(FLAG_TALKED_MESTONNAUX) and QFLAG_PLATE or QFLAG_NONE));
|
||||
quest:AddENpc(LEFWYNE, (not quest:GetFlag(FLAG_TALKED_LEFWYNE) and QFLAG_PLATE or QFLAG_NONE));
|
||||
quest:SetENpc(KINNISON);
|
||||
quest:SetENpc(SYBELL, (not data:GetFlag(FLAG_TALKED_SYBELL) 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 data:GetFlag(FLAG_TALKED_NELLAURE) 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 data:GetFlag(FLAG_TALKED_LEFWYNE) and QFLAG_PLATE or QFLAG_NONE));
|
||||
elseif (sequence == SEQ_001) then
|
||||
quest:AddENpc(KINNISON, QFLAG_PLATE);
|
||||
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function onTalk(player, quest, npc, eventName)
|
||||
local npcClassId = npc.GetActorClassId();
|
||||
local seq = quest:GetSequence();
|
||||
local incCounter = false;
|
||||
|
||||
-- Offer the quest
|
||||
if (npcClassId == KINNISON and not player:HasQuest(quest)) then
|
||||
local questAccepted = callClientFunction(player, "delegateEvent", player, quest, "processEventOffersStart");
|
||||
if (questAccepted == 1) then
|
||||
player:AcceptQuest(quest);
|
||||
end
|
||||
player:EndEvent();
|
||||
return;
|
||||
end
|
||||
|
||||
-- Quest Progress
|
||||
local data = quest:GetData();
|
||||
if (seq == SEQ_000) then
|
||||
if (npcClassId == KINNISON) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventOffersAfter");
|
||||
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");
|
||||
quest:SetFlag(FLAG_TALKED_SYBELL);
|
||||
data:SetFlag(FLAG_TALKED_SYBELL);
|
||||
incCounter = true;
|
||||
else
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventSybellSpeakAfter");
|
||||
end
|
||||
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");
|
||||
quest:SetFlag(FLAG_TALKED_KHUMA_MOSHROCA);
|
||||
data:SetFlag(FLAG_TALKED_KHUMA_MOSHROCA);
|
||||
incCounter = true;
|
||||
else
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventKhumaSpeakAfter");
|
||||
end
|
||||
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");
|
||||
quest:SetFlag(FLAG_TALKED_NELLAURE);
|
||||
data:SetFlag(FLAG_TALKED_NELLAURE);
|
||||
incCounter = true;
|
||||
else
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventNellaureSpeakAfter");
|
||||
end
|
||||
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");
|
||||
quest:SetFlag(FLAG_TALKED_MESTONNAUX);
|
||||
data:SetFlag(FLAG_TALKED_MESTONNAUX);
|
||||
incCounter = true;
|
||||
else
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventMestonnauxSpeakAfter");
|
||||
end
|
||||
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");
|
||||
quest:SetFlag(FLAG_TALKED_LEFWYNE);
|
||||
data:SetFlag(FLAG_TALKED_LEFWYNE);
|
||||
incCounter = true;
|
||||
else
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventLefwyneSpeakAfter");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Increase objective counter & play relevant messages
|
||||
if (incCounter == true) then
|
||||
quest:IncCounter(COUNTER_TALKED);
|
||||
local counterAmount = quest:GetCounter(COUNTER_TALKED);
|
||||
local counterAmount = data:IncCounter(COUNTER_TALKED);
|
||||
|
||||
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!
|
||||
quest:UpdateENPCs(); -- Band-aid for a QFLAG_PLATE issue
|
||||
quest:StartSequence(SEQ_001);
|
||||
|
@ -134,7 +146,7 @@ function onTalk(player, quest, npc, eventName)
|
|||
if (npcClassId == KINNISON) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEventClear");
|
||||
callClientFunction(player, "delegateEvent", player, quest, "sqrwa", 200, 1, 1, 9);
|
||||
player:CompleteQuest(quest:GetQuestId());
|
||||
player:CompleteQuest(quest);
|
||||
end
|
||||
end
|
||||
quest:UpdateENPCs();
|
||||
|
@ -143,12 +155,12 @@ end
|
|||
|
||||
|
||||
-- Check if all seers are talked to
|
||||
function seq000_checkCondition(quest)
|
||||
return (quest:GetFlag(FLAG_TALKED_SYBELL) and
|
||||
quest:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and
|
||||
quest:GetFlag(FLAG_TALKED_NELLAURE) and
|
||||
quest:GetFlag(FLAG_TALKED_MESTONNAUX) and
|
||||
quest:GetFlag(FLAG_TALKED_LEFWYNE));
|
||||
function seq000_checkCondition(data)
|
||||
return (data:GetFlag(FLAG_TALKED_SYBELL) and
|
||||
data:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA) and
|
||||
data:GetFlag(FLAG_TALKED_NELLAURE) and
|
||||
data:GetFlag(FLAG_TALKED_MESTONNAUX) and
|
||||
data:GetFlag(FLAG_TALKED_LEFWYNE));
|
||||
end
|
||||
|
||||
|
||||
|
@ -157,11 +169,11 @@ function getJournalMapMarkerList(player, quest)
|
|||
local possibleMarkers = {};
|
||||
|
||||
if (sequence == SEQ_000) then
|
||||
if (not quest: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 quest: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 quest:GetFlag(FLAG_TALKED_LEFWYNE)) then table.insert(possibleMarkers, MRKR_LEFWYNE); end
|
||||
if (not data:GetFlag(FLAG_TALKED_SYBELL)) then table.insert(possibleMarkers, MRKR_SYBELL); end
|
||||
if (not data:GetFlag(FLAG_TALKED_KHUMA_MOSHROCA)) then table.insert(possibleMarkers, MRKR_KHUMA_MOSHROCA); end
|
||||
if (not data:GetFlag(FLAG_TALKED_NELLAURE)) then table.insert(possibleMarkers, MRKR_NELLAURE); end
|
||||
if (not data:GetFlag(FLAG_TALKED_MESTONNAUX)) then table.insert(possibleMarkers, MRKR_MESTONNAUX); end
|
||||
if (not data:GetFlag(FLAG_TALKED_LEFWYNE)) then table.insert(possibleMarkers, MRKR_LEFWYNE); end
|
||||
elseif (sequence == SEQ_001) then
|
||||
table.insert(possibleMarkers, MRKR_KINNISON);
|
||||
end
|
||||
|
|
|
@ -40,13 +40,13 @@ end
|
|||
|
||||
|
||||
|
||||
function onSequence(player, quest, sequence)
|
||||
function onStateChange(player, quest, sequence)
|
||||
if (sequence == SEQ_000) then
|
||||
quest:AddENpc(VKOROLON);
|
||||
quest:AddENpc(PFARAHR, QFLAG_PLATE);
|
||||
quest:SetENpc(VKOROLON);
|
||||
quest:SetENpc(PFARAHR, QFLAG_PLATE);
|
||||
elseif (sequence == SEQ_001) then
|
||||
quest:AddENpc(VKOROLON, QFLAG_PLATE);
|
||||
quest:AddENpc(PFARAHR);
|
||||
quest:SetENpc(VKOROLON, QFLAG_PLATE);
|
||||
quest:SetENpc(PFARAHR);
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ end
|
|||
function onFinish(player, quest)
|
||||
end
|
||||
|
||||
function onSequence(player, quest, sequence)
|
||||
function onStateChange(player, quest, sequence)
|
||||
if (sequence == SEQ_000) then
|
||||
-- Setup states incase we loaded in.
|
||||
local rostnsthalFlag = quest:GetFlag(FLAG_SEQ000_MINITUT1) and QFLAG_NONE or QFLAG_PLATE;
|
||||
|
@ -72,34 +72,34 @@ function onSequence(player, quest, sequence)
|
|||
local exitCanPush = quest:GetFlags() == 0xF;
|
||||
local exitFlag = quest:GetFlags() == 0xF and QFLAG_MAP or QFLAG_NONE;
|
||||
|
||||
quest:AddENpc(WELLTRAVELED_MERCHANT);
|
||||
quest:AddENpc(TIPSY_ADVENTURER);
|
||||
quest:AddENpc(CULTIVATED_TENDER);
|
||||
quest:AddENpc(ANXIOUS_ADVENTURER);
|
||||
quest:AddENpc(BABYFACED_ADVENTURER, babyfaceFlag);
|
||||
quest:AddENpc(AUSTERE_ADVENTURER);
|
||||
quest:AddENpc(UNDIGNIFIED_ADVENTURER);
|
||||
quest:AddENpc(SHADOWY_TRAVELER);
|
||||
quest:AddENpc(ASTUTE_MERCHANT);
|
||||
quest:AddENpc(VOLUPTUOUS_VIXEN, vixenFlag);
|
||||
quest:AddENpc(INDIFFERENT_PASSERBY);
|
||||
quest:AddENpc(PRATTLING_ADVENTURER);
|
||||
quest:AddENpc(LANKY_TRAVELER);
|
||||
quest:AddENpc(GRINNING_ADVENTURER);
|
||||
quest:AddENpc(ROSTNSTHAL, rostnsthalFlag, true, rostnsthalCanPush);
|
||||
quest:AddENpc(EXIT_TRIGGER, exitFlag, false, exitCanPush);
|
||||
quest:SetENpc(WELLTRAVELED_MERCHANT);
|
||||
quest:SetENpc(TIPSY_ADVENTURER);
|
||||
quest:SetENpc(CULTIVATED_TENDER);
|
||||
quest:SetENpc(ANXIOUS_ADVENTURER);
|
||||
quest:SetENpc(BABYFACED_ADVENTURER, babyfaceFlag);
|
||||
quest:SetENpc(AUSTERE_ADVENTURER);
|
||||
quest:SetENpc(UNDIGNIFIED_ADVENTURER);
|
||||
quest:SetENpc(SHADOWY_TRAVELER);
|
||||
quest:SetENpc(ASTUTE_MERCHANT);
|
||||
quest:SetENpc(VOLUPTUOUS_VIXEN, vixenFlag);
|
||||
quest:SetENpc(INDIFFERENT_PASSERBY);
|
||||
quest:SetENpc(PRATTLING_ADVENTURER);
|
||||
quest:SetENpc(LANKY_TRAVELER);
|
||||
quest:SetENpc(GRINNING_ADVENTURER);
|
||||
quest:SetENpc(ROSTNSTHAL, rostnsthalFlag, true, rostnsthalCanPush);
|
||||
quest:SetENpc(EXIT_TRIGGER, exitFlag, false, exitCanPush);
|
||||
elseif (sequence == SEQ_005) then
|
||||
elseif (sequence == SEQ_010) then
|
||||
quest:AddENpc(HOB);
|
||||
quest:AddENpc(GERT);
|
||||
quest:AddENpc(LORHZANT);
|
||||
quest:AddENpc(MUSCLEBOUND_DECKHAND);
|
||||
quest:AddENpc(PEARLYTOOTHED_PORTER);
|
||||
quest:AddENpc(UNDIGNIFIED_ADVENTURER);
|
||||
quest:AddENpc(WELLTRAVELED_MERCHANT);
|
||||
quest:AddENpc(VOLUPTUOUS_VIXEN);
|
||||
quest:AddENpc(LANKY_TRAVELER);
|
||||
quest:AddENpc(PRIVAREA_PAST_EXIT, QFLAG_NONE, false, true);
|
||||
quest:SetENpc(HOB);
|
||||
quest:SetENpc(GERT);
|
||||
quest:SetENpc(LORHZANT);
|
||||
quest:SetENpc(MUSCLEBOUND_DECKHAND);
|
||||
quest:SetENpc(PEARLYTOOTHED_PORTER);
|
||||
quest:SetENpc(UNDIGNIFIED_ADVENTURER);
|
||||
quest:SetENpc(WELLTRAVELED_MERCHANT);
|
||||
quest:SetENpc(VOLUPTUOUS_VIXEN);
|
||||
quest:SetENpc(LANKY_TRAVELER);
|
||||
quest:SetENpc(PRIVAREA_PAST_EXIT, QFLAG_NONE, false, true);
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -85,56 +85,56 @@ end
|
|||
function onFinish(player, quest)
|
||||
end
|
||||
|
||||
function onSequence(player, quest, sequence)
|
||||
function onStateChange(player, quest, sequence)
|
||||
|
||||
if (sequence == SEQ_000) then
|
||||
quest:AddENpc(YSHTOLA);
|
||||
quest:AddENpc(CRAPULOUS_ADVENTURER);
|
||||
quest:AddENpc(DUPLICITOUS_TRADER);
|
||||
quest:AddENpc(DEBONAIR_PIRATE);
|
||||
quest:AddENpc(ONYXHAIRED_ADVENTURER);
|
||||
quest:AddENpc(SKITTISH_ADVENTURER);
|
||||
quest:AddENpc(RELAXING_ADVENTURER);
|
||||
quest:AddENpc(BADERON, QFLAG_PLATE);
|
||||
quest:AddENpc(MYTESYN);
|
||||
quest:AddENpc(COCKAHOOP_COCKSWAIN);
|
||||
quest:AddENpc(SENTENIOUS_SELLSWORD);
|
||||
quest:AddENpc(SOLICITOUS_SELLSWORD);
|
||||
quest:SetENpc(YSHTOLA);
|
||||
quest:SetENpc(CRAPULOUS_ADVENTURER);
|
||||
quest:SetENpc(DUPLICITOUS_TRADER);
|
||||
quest:SetENpc(DEBONAIR_PIRATE);
|
||||
quest:SetENpc(ONYXHAIRED_ADVENTURER);
|
||||
quest:SetENpc(SKITTISH_ADVENTURER);
|
||||
quest:SetENpc(RELAXING_ADVENTURER);
|
||||
quest:SetENpc(BADERON, QFLAG_PLATE);
|
||||
quest:SetENpc(MYTESYN);
|
||||
quest:SetENpc(COCKAHOOP_COCKSWAIN);
|
||||
quest:SetENpc(SENTENIOUS_SELLSWORD);
|
||||
quest:SetENpc(SOLICITOUS_SELLSWORD);
|
||||
elseif (sequence == SEQ_003) then
|
||||
quest:AddENpc(BADERON);
|
||||
quest:SetENpc(BADERON);
|
||||
elseif (sequence == SEQ_005) then
|
||||
quest:AddENpc(BADERON, QFLAG_PLATE);
|
||||
quest:SetENpc(BADERON, QFLAG_PLATE);
|
||||
elseif (sequence == SEQ_006) then
|
||||
quest:AddENpc(BADERON, QFLAG_PLATE);
|
||||
quest:SetENpc(BADERON, QFLAG_PLATE);
|
||||
elseif (sequence == SEQ_007) then
|
||||
local subseqCUL = quest:GetCounter(CNTR_SEQ7_CUL);
|
||||
local subseqMRD = quest:GetCounter(CNTR_SEQ7_MRD);
|
||||
|
||||
-- Always active in this seqence
|
||||
quest:AddENpc(BADERON);
|
||||
quest:AddENpc(CHARLYS, subseqCUL == 0 and QFLAG_PLATE or QFLAG_NONE);
|
||||
quest:SetENpc(BADERON);
|
||||
quest:SetENpc(CHARLYS, subseqCUL == 0 and QFLAG_PLATE or QFLAG_NONE);
|
||||
|
||||
-- Down and Up the MSK guild
|
||||
quest:AddENpc(ISANDOREL, (subseqMRD == 0 or subseqMRD == 2) and QFLAG_PLATE or QFLAG_NONE);
|
||||
quest:SetENpc(ISANDOREL, (subseqMRD == 0 or subseqMRD == 2) and QFLAG_PLATE or QFLAG_NONE);
|
||||
|
||||
if (subseqMRD == 1) then
|
||||
quest:AddENpc(MSK_TRIGGER, QFLAG_MAP, false, true);
|
||||
quest:SetENpc(MSK_TRIGGER, QFLAG_MAP, false, true);
|
||||
elseif (subseqMRD == 2) then
|
||||
quest:AddENpc(MERLZIRN);
|
||||
quest:SetENpc(MERLZIRN);
|
||||
end
|
||||
|
||||
-- In Echo
|
||||
quest:AddENpc(NERVOUS_BARRACUDA);
|
||||
quest:AddENpc(INTIMIDATING_BARRACUDA);
|
||||
quest:AddENpc(OVEREAGER_BARRACUDA);
|
||||
quest:AddENpc(SOPHISTICATED_BARRACUDA);
|
||||
quest:AddENpc(SMIRKING_BARRACUDA);
|
||||
quest:AddENpc(MANNSKOEN);
|
||||
quest:AddENpc(TOTORUTO);
|
||||
quest:AddENpc(ADVENTURER1);
|
||||
quest:AddENpc(ADVENTURER2);
|
||||
quest:AddENpc(ADVENTURER3);
|
||||
quest:AddENpc(ECHO_EXIT_TRIGGER, subseqMRD == 3 and QFLAG_MAP or QFLAG_NONE, false, subseqMRD == 3);
|
||||
quest:SetENpc(NERVOUS_BARRACUDA);
|
||||
quest:SetENpc(INTIMIDATING_BARRACUDA);
|
||||
quest:SetENpc(OVEREAGER_BARRACUDA);
|
||||
quest:SetENpc(SOPHISTICATED_BARRACUDA);
|
||||
quest:SetENpc(SMIRKING_BARRACUDA);
|
||||
quest:SetENpc(MANNSKOEN);
|
||||
quest:SetENpc(TOTORUTO);
|
||||
quest:SetENpc(ADVENTURER1);
|
||||
quest:SetENpc(ADVENTURER2);
|
||||
quest:SetENpc(ADVENTURER3);
|
||||
quest:SetENpc(ECHO_EXIT_TRIGGER, subseqMRD == 3 and QFLAG_MAP or QFLAG_NONE, false, subseqMRD == 3);
|
||||
|
||||
if (subseqCUL == 1 and subseqMRD == 4) then
|
||||
player:SetNpcLS(1, 1);
|
||||
|
|
|
@ -103,7 +103,7 @@ end
|
|||
function onFinish(player, quest)
|
||||
end
|
||||
|
||||
function onSequence(player, quest, sequence)
|
||||
function onStateChange(player, quest, sequence)
|
||||
|
||||
if (sequence == SEQ_000) then
|
||||
-- Setup states incase we loaded in.
|
||||
|
@ -119,34 +119,34 @@ function onSequence(player, quest, sequence)
|
|||
gildiggingmistressFlag = QFLAG_NONE;
|
||||
end
|
||||
|
||||
--AddENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
||||
quest:AddENpc(ASCILIA, asciliaFlag, true, asciliaCanPush);
|
||||
quest:AddENpc(WARBURTON);
|
||||
quest:AddENpc(RURURAJI);
|
||||
quest:AddENpc(BIG_BELLIED_BARKER);
|
||||
quest:AddENpc(FRETFUL_FARMHAND, fretfulfarmhandFlag);
|
||||
quest:AddENpc(DEBAUCHED_DEMONESS);
|
||||
quest:AddENpc(DAPPER_DAN);
|
||||
quest:AddENpc(LOUTISH_LAD);
|
||||
quest:AddENpc(GIL_DIGGING_MISTRESS, gildiggingmistressFlag);
|
||||
quest:AddENpc(TWITTERING_TOMBOY);
|
||||
quest:AddENpc(STOCKY_STRANGER);
|
||||
quest:AddENpc(EXIT_TRIGGER, exitFlag, false, true);
|
||||
quest:AddENpc(OPENING_STOPER_ULDAH, QFLAG_NONE, false, false, true);
|
||||
--SetENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
||||
quest:SetENpc(ASCILIA, asciliaFlag, true, asciliaCanPush);
|
||||
quest:SetENpc(WARBURTON);
|
||||
quest:SetENpc(RURURAJI);
|
||||
quest:SetENpc(BIG_BELLIED_BARKER);
|
||||
quest:SetENpc(FRETFUL_FARMHAND, fretfulfarmhandFlag);
|
||||
quest:SetENpc(DEBAUCHED_DEMONESS);
|
||||
quest:SetENpc(DAPPER_DAN);
|
||||
quest:SetENpc(LOUTISH_LAD);
|
||||
quest:SetENpc(GIL_DIGGING_MISTRESS, gildiggingmistressFlag);
|
||||
quest:SetENpc(TWITTERING_TOMBOY);
|
||||
quest:SetENpc(STOCKY_STRANGER);
|
||||
quest:SetENpc(EXIT_TRIGGER, exitFlag, false, true);
|
||||
quest:SetENpc(OPENING_STOPER_ULDAH, QFLAG_NONE, false, false, true);
|
||||
|
||||
elseif (sequence == SEQ_010) then
|
||||
local yayatokiFlag = quest:GetFlag(FLAG_SEQ010_TALK0) and QFLAG_NONE or QFLAG_PLATE;
|
||||
local uldahopeningexitFlag = QFLAG_MAP;
|
||||
quest:AddENpc(KEEN_EYED_MERCHANT);
|
||||
quest:AddENpc(HIGH_SPIRITED_FELLOW);
|
||||
quest:AddENpc(DISREPUTABLE_MIDLANDER);
|
||||
quest:AddENpc(LONG_LEGGED_LADY);
|
||||
quest:AddENpc(LARGE_LUNGED_LABORER);
|
||||
quest:AddENpc(TOOTH_GRINDING_TRAVELER);
|
||||
quest:AddENpc(FULL_LIPPED_FILLE);
|
||||
quest:AddENpc(YAYATOKI, yayatokiFlag);
|
||||
quest:AddENpc(BLOCKER, QFLAG_NONE, false, true);
|
||||
quest:AddENpc(ULDAH_OPENING_EXIT, uldahopeningexitFlag, false, true);
|
||||
quest:SetENpc(KEEN_EYED_MERCHANT);
|
||||
quest:SetENpc(HIGH_SPIRITED_FELLOW);
|
||||
quest:SetENpc(DISREPUTABLE_MIDLANDER);
|
||||
quest:SetENpc(LONG_LEGGED_LADY);
|
||||
quest:SetENpc(LARGE_LUNGED_LABORER);
|
||||
quest:SetENpc(TOOTH_GRINDING_TRAVELER);
|
||||
quest:SetENpc(FULL_LIPPED_FILLE);
|
||||
quest:SetENpc(YAYATOKI, yayatokiFlag);
|
||||
quest:SetENpc(BLOCKER, QFLAG_NONE, false, true);
|
||||
quest:SetENpc(ULDAH_OPENING_EXIT, uldahopeningexitFlag, false, true);
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -127,17 +127,17 @@ end
|
|||
function onFinish(player, quest)
|
||||
end
|
||||
|
||||
function onSequence(player, quest, sequence)
|
||||
function onStateChange(player, quest, sequence)
|
||||
|
||||
if (sequence == SEQ_000) then
|
||||
-- Setup states incase we loaded in.
|
||||
|
||||
--AddENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
||||
quest:AddENpc(MOMODI, QFLAG_PLATE);
|
||||
quest:AddENpc(OTOPA_POTTOPA);
|
||||
--SetENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
||||
quest:SetENpc(MOMODI, QFLAG_PLATE);
|
||||
quest:SetENpc(OTOPA_POTTOPA);
|
||||
|
||||
elseif (sequence == SEQ_005) then
|
||||
quest:AddENpc(MOMODI);
|
||||
quest:SetENpc(MOMODI);
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ end
|
|||
function onFinish(player, quest)
|
||||
end
|
||||
|
||||
function onSequence(player, quest, seqNum)
|
||||
function onStateChange(player, quest, seqNum)
|
||||
quest:ClearENpcs();
|
||||
end
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
require ("global")
|
||||
|
||||
--[[
|
||||
|
||||
Quest Script
|
||||
|
||||
Name: Getting Started (Mother Miounne)
|
||||
Code: Trl0g1
|
||||
Id: 110141
|
||||
|
||||
Enables the "Getting Started" option on Miounne.
|
||||
* NOTE: This quest is active for all players at all times.
|
||||
]]
|
||||
|
||||
function onTalk(player, quest, npc, eventName)
|
||||
local choice = callClientFunction(player, "delegateEvent", player, quest, "processEventMiounneStart");
|
||||
|
||||
if (choice == 1) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEvent225");
|
||||
elseif (choice == 2) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEvent230");
|
||||
end
|
||||
|
||||
player:EndEvent();
|
||||
end
|
||||
|
||||
function IsQuestENPC(player, quest, npc)
|
||||
return npc:GetActorClassId()] == 1000230;
|
||||
end
|
|
@ -1,29 +0,0 @@
|
|||
require ("global")
|
||||
|
||||
--[[
|
||||
|
||||
Quest Script
|
||||
|
||||
Name: Getting Started (Baderon)
|
||||
Code: Trl0l1
|
||||
Id: 110140
|
||||
|
||||
Enables the "Getting Started" option on Baderon.
|
||||
* NOTE: This quest is active for all players at all times.
|
||||
]]
|
||||
|
||||
function onTalk(player, quest, npc, eventName)
|
||||
local choice = callClientFunction(player, "delegateEvent", player, quest, "processEventBaderonStart");
|
||||
|
||||
if (choice == 1) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEvent640");
|
||||
elseif (choice == 2) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEvent650");
|
||||
end
|
||||
|
||||
player:EndEvent();
|
||||
end
|
||||
|
||||
function IsQuestENPC(player, quest, npc)
|
||||
return npc:GetActorClassId()] == 1000137;
|
||||
end
|
|
@ -1,29 +0,0 @@
|
|||
require ("global")
|
||||
|
||||
--[[
|
||||
|
||||
Quest Script
|
||||
|
||||
Name: Getting Started (Momodi)
|
||||
Code: Trl0u1
|
||||
Id: 110142
|
||||
|
||||
Enables the "Getting Started" option on Momodi.
|
||||
* NOTE: This quest is active for all players at all times.
|
||||
]]
|
||||
|
||||
function onTalk(player, quest, npc, eventName)
|
||||
local choice = callClientFunction(player, "delegateEvent", player, quest, "processEventMomodiStart");
|
||||
|
||||
if (choice == 1) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEvent235");
|
||||
elseif (choice == 2) then
|
||||
callClientFunction(player, "delegateEvent", player, quest, "processEvent240");
|
||||
end
|
||||
|
||||
player:EndEvent();
|
||||
end
|
||||
|
||||
function IsQuestENPC(player, quest, npc)
|
||||
return npc:GetActorClassId() == 1000841;
|
||||
end
|
|
@ -1,51 +1,29 @@
|
|||
-- MySQL dump 10.13 Distrib 5.7.10, for Win64 (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: ffxiv_database
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 5.7.10-log
|
||||
-- --------------------------------------------------------
|
||||
-- Host: 127.0.0.1
|
||||
-- Server version: 5.6.17 - MySQL Community Server (GPL)
|
||||
-- Server OS: Win64
|
||||
-- HeidiSQL Version: 10.1.0.5464
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `characters_quest_completed`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `characters_quest_completed`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `characters_quest_completed` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
-- Dumping database structure for ffxiv_server
|
||||
CREATE DATABASE IF NOT EXISTS `ffxiv_server` /*!40100 DEFAULT CHARACTER SET latin1 */;
|
||||
USE `ffxiv_server`;
|
||||
|
||||
-- Dumping structure for table ffxiv_server.characters_quest_completed
|
||||
CREATE TABLE IF NOT EXISTS `characters_quest_completed` (
|
||||
`characterId` int(10) unsigned NOT NULL,
|
||||
`questId` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
`completedQuests` varbinary(2048) DEFAULT NULL,
|
||||
PRIMARY KEY (`characterId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `characters_quest_completed`
|
||||
--
|
||||
|
||||
LOCK TABLES `characters_quest_completed` WRITE;
|
||||
/*!40000 ALTER TABLE `characters_quest_completed` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `characters_quest_completed` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
-- Data exporting was unselected.
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2016-06-07 22:54:47
|
||||
|
|
560
Data/sql/gamedata_quests.sql
Normal file
560
Data/sql/gamedata_quests.sql
Normal file
|
@ -0,0 +1,560 @@
|
|||
-- --------------------------------------------------------
|
||||
-- Host: 127.0.0.1
|
||||
-- Server version: 5.6.17 - MySQL Community Server (GPL)
|
||||
-- Server OS: Win64
|
||||
-- HeidiSQL Version: 10.1.0.5464
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
|
||||
|
||||
-- Dumping database structure for ffxiv_server
|
||||
CREATE DATABASE IF NOT EXISTS `ffxiv_server` /*!40100 DEFAULT CHARACTER SET latin1 */;
|
||||
USE `ffxiv_server`;
|
||||
|
||||
-- Dumping structure for table ffxiv_server.gamedata_quests
|
||||
DROP TABLE IF EXISTS `gamedata_quests`;
|
||||
CREATE TABLE IF NOT EXISTS `gamedata_quests` (
|
||||
`id` int(11) unsigned NOT NULL,
|
||||
`questName` varchar(50) NOT NULL,
|
||||
`className` varchar(10) NOT NULL,
|
||||
`prerequisite` int(11) unsigned NOT NULL,
|
||||
`minLevel` smallint(5) unsigned NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Dumping data for table ffxiv_server.gamedata_quests: ~524 rows (approximately)
|
||||
/*!40000 ALTER TABLE `gamedata_quests` DISABLE KEYS */;
|
||||
REPLACE INTO `gamedata_quests` (`id`, `questName`, `className`, `prerequisite`, `minLevel`) VALUES
|
||||
(110001, 'Shapeless Melody', 'Man0l0', 0, 1),
|
||||
(110002, 'Treasures of the Main', 'Man0l1', 0, 1),
|
||||
(110003, 'Legends Adrift', 'Man1l0', 0, 8),
|
||||
(110004, 'Never the Twain Shall Meet', 'Man2l0', 0, 13),
|
||||
(110005, 'Sundered Skies', 'Man0g0', 0, 1),
|
||||
(110006, 'Souls Gone Wild', 'Man0g1', 0, 1),
|
||||
(110007, 'Whispers in the Wood', 'Man1g0', 0, 8),
|
||||
(110008, 'Beckon of the Elementals', 'Man2g0', 0, 13),
|
||||
(110009, 'Flowers for All', 'Man0u0', 0, 1),
|
||||
(110010, 'Court in the Sands', 'Man0u1', 0, 1),
|
||||
(110011, 'Golden Sacrifices', 'Man1u0', 0, 8),
|
||||
(110012, 'Calamity Cometh', 'Man2u0', 0, 13),
|
||||
(110013, 'Fade to White', 'Man200', 0, 18),
|
||||
(110014, 'Together We Stand', 'Man206', 0, 22),
|
||||
(110015, 'Toll of the Warden', 'Man300', 0, 30),
|
||||
(110016, 'Forever Taken', 'Man304', 0, 34),
|
||||
(110017, 'Lord Errant', 'Man308', 0, 38),
|
||||
(110018, 'Of Men They Sing', 'Man402', 0, 42),
|
||||
(110019, 'Futures Perfect', 'Man406', 0, 46),
|
||||
(110020, '[en]', 'Man502', 0, 52),
|
||||
(110021, '[en]', 'Man504', 0, 54),
|
||||
(110060, 'The House Always Wins', 'Pgl200', 0, 20),
|
||||
(110061, 'Here There Be Pirates', 'Pgl300', 0, 30),
|
||||
(110062, 'Two Sides to Every Chip', 'Pgl306', 0, 36),
|
||||
(110063, '[en]', 'Pgl400', 0, 40),
|
||||
(110080, 'All Bark and No Bite', 'Gla200', 0, 20),
|
||||
(110081, 'Unalienable Rights', 'Gla300', 0, 30),
|
||||
(110082, 'Thrill of the Fight', 'Gla306', 0, 36),
|
||||
(110083, '[en]', 'Gla400', 0, 40),
|
||||
(110100, 'Bloody Baptism', 'Exc200', 0, 20),
|
||||
(110101, 'Two-man Crew', 'Exc300', 0, 30),
|
||||
(110102, 'Captain\'s Orders', 'Exc306', 0, 36),
|
||||
(110103, '[en]', 'Exc400', 0, 40),
|
||||
(110104, '[en]', 'Exc500', 0, 50),
|
||||
(110105, '[en]', 'Exc506', 0, 56),
|
||||
(110140, 'Getting Started', 'Trl0l1', 0, 20),
|
||||
(110141, 'Getting Started', 'Trl0g1', 0, 30),
|
||||
(110142, '[en]', 'Trl0u1', 0, 36),
|
||||
(110143, '[en]', 'Trl0l2', 0, 20),
|
||||
(110144, 'Selecting a Different Path Companion', 'Trl0l3', 0, 50),
|
||||
(110145, '[en]', 'Trl0l4', 0, 56),
|
||||
(110160, 'Filling the Quiver', 'Arc200', 0, 20),
|
||||
(110161, 'The Foreboding Forest', 'Arc300', 110160, 30),
|
||||
(110162, 'There Can Be Only One', 'Arc306', 110161, 36),
|
||||
(110163, '[en]', 'Arc400', 0, 40),
|
||||
(110164, '[en]', 'Arc500', 0, 50),
|
||||
(110165, '[en]', 'Arc506', 0, 56),
|
||||
(110180, 'A Wailing Welcome', 'Lnc200', 0, 20),
|
||||
(110181, 'Culture Shock', 'Lnc300', 110180, 30),
|
||||
(110182, 'Necessary Evils', 'Lnc306', 110181, 36),
|
||||
(110183, '[en]', 'Lnc400', 0, 40),
|
||||
(110184, '[en]', 'Lnc500', 0, 50),
|
||||
(110185, '[en]', 'Lnc506', 0, 56),
|
||||
(110240, 'The Big Payback', 'Thm200', 0, 20),
|
||||
(110241, 'Revelry in Rivalry', 'Thm300', 0, 30),
|
||||
(110242, 'Law and the Order', 'Thm306', 0, 36),
|
||||
(110243, '[en]', 'Thm400', 0, 40),
|
||||
(110260, 'Dendrological Duties', 'Cnj200', 0, 20),
|
||||
(110261, 'Good Knight, Sweet Dreams', 'Cnj300', 110260, 30),
|
||||
(110262, 'The Call of Nature', 'Cnj306', 110261, 36),
|
||||
(110263, '[en]', 'Cnj400', 0, 40),
|
||||
(110264, '[en]', 'Cnj500', 0, 50),
|
||||
(110265, '[en]', 'Cnj506', 0, 56),
|
||||
(110280, '[en]', 'Acn200', 0, 20),
|
||||
(110281, '[en]', 'Acn300', 0, 30),
|
||||
(110282, '[en]', 'Acn306', 0, 36),
|
||||
(110283, '[en]', 'Acn400', 0, 40),
|
||||
(110284, '[en]', 'Acn500', 0, 50),
|
||||
(110285, '[en]', 'Acn506', 0, 56),
|
||||
(110300, 'The Mouths of Babes', 'Wdk200', 0, 20),
|
||||
(110301, 'Hide and Seek Shenanigans', 'Wdk300', 110300, 30),
|
||||
(110302, 'Spanning the Spectrum', 'Wdk306', 110301, 36),
|
||||
(110303, '[en]', 'Wdk400', 0, 40),
|
||||
(110304, '[en]', 'Wdk500', 0, 50),
|
||||
(110305, '[en]', 'Wdk506', 0, 56),
|
||||
(110320, 'An Ear for Quality', 'Bsm200', 0, 20),
|
||||
(110321, 'Song of the Sirens', 'Bsm300', 0, 30),
|
||||
(110322, 'The Sound of Silence', 'Bsm306', 0, 36),
|
||||
(110323, '[en]', 'Bsm400', 0, 40),
|
||||
(110324, '[en]', 'Bsm500', 0, 50),
|
||||
(110325, '[en]', 'Bsm506', 0, 56),
|
||||
(110360, 'She Walks in Beauty', 'Gld200', 0, 20),
|
||||
(110361, 'F\'lhaminn\'s Flower', 'Gld300', 0, 30),
|
||||
(110362, 'Struck Through the Heart', 'Gld306', 0, 36),
|
||||
(110363, '[en]', 'Gld400', 0, 40),
|
||||
(110364, '[en]', 'Gld500', 0, 50),
|
||||
(110365, '[en]', 'Gld506', 0, 56),
|
||||
(110380, 'The Silent Partners', 'Tan200', 0, 20),
|
||||
(110381, 'Design Imposters', 'Tan300', 110380, 30),
|
||||
(110382, 'Head of the Class', 'Tan306', 110381, 36),
|
||||
(110383, '[en]', 'Tan400', 0, 40),
|
||||
(110384, '[en]', 'Tan500', 0, 50),
|
||||
(110385, '[en]', 'Tan506', 0, 56),
|
||||
(110400, 'Hoodwinked', 'Wvr200', 0, 20),
|
||||
(110401, 'Dance the Night Away', 'Wvr300', 0, 30),
|
||||
(110402, 'A Fruitful Murder', 'Wvr306', 0, 36),
|
||||
(110403, '[en]', 'Wvr400', 0, 40),
|
||||
(110404, '[en]', 'Wvr500', 0, 50),
|
||||
(110405, '[en]', 'Wvr506', 0, 56),
|
||||
(110420, 'Sleep, Cousin of Death', 'Alc200', 0, 20),
|
||||
(110421, 'The Boy and the Dragon Gay', 'Alc300', 110420, 30),
|
||||
(110422, 'Dream On, Dream Away', 'Alc306', 110421, 36),
|
||||
(110423, '[en]', 'Alc400', 0, 40),
|
||||
(110424, '[en]', 'Alc500', 0, 50),
|
||||
(110425, '[en]', 'Alc506', 0, 56),
|
||||
(110440, 'Showdown', 'Cul200', 0, 20),
|
||||
(110441, 'Mystery of the Gastronome Gone Home', 'Cul300', 0, 30),
|
||||
(110442, 'Something in the Soup', 'Cul306', 0, 36),
|
||||
(110443, '[en]', 'Cul400', 0, 40),
|
||||
(110444, '[en]', 'Cul500', 0, 50),
|
||||
(110445, '[en]', 'Cul506', 0, 56),
|
||||
(110460, 'A Piece of History', 'Min200', 0, 20),
|
||||
(110461, 'Little Saboteurs', 'Min300', 0, 30),
|
||||
(110462, 'Runaway Little Girl', 'Min306', 0, 36),
|
||||
(110463, '[en]', 'Min400', 0, 40),
|
||||
(110464, '[en]', 'Min500', 0, 50),
|
||||
(110465, '[en]', 'Min506', 0, 56),
|
||||
(110480, 'Gridanian Roots', 'Hrv200', 0, 20),
|
||||
(110481, 'The Grass is Always Greener', 'Hrv300', 110480, 30),
|
||||
(110482, 'A Moogle Bouquet', 'Hrv306', 110481, 36),
|
||||
(110483, '[en]', 'Hrv400', 0, 40),
|
||||
(110484, '[en]', 'Hrv500', 0, 50),
|
||||
(110485, '[en]', 'Hrv506', 0, 56),
|
||||
(110500, 'To Fight a Fishback', 'Fsh200', 0, 20),
|
||||
(110501, 'The Beast of the Barrel', 'Fsh300', 0, 30),
|
||||
(110502, 'Polishing the Mast', 'Fsh306', 0, 36),
|
||||
(110503, '[en]', 'Fsh400', 0, 40),
|
||||
(110504, '[en]', 'Fsh500', 0, 50),
|
||||
(110505, '[en]', 'Fsh506', 0, 56),
|
||||
(110540, 'Small Talk', 'Dftsea', 0, 0),
|
||||
(110541, 'Small Talk', 'Dftfst', 0, 0),
|
||||
(110542, 'Small Talk', 'Dftroc', 0, 0),
|
||||
(110543, 'Small Talk', 'Dftwil', 0, 0),
|
||||
(110544, 'Small Talk', 'Dftsrt', 0, 0),
|
||||
(110545, 'Small Talk', 'Dftlak', 0, 0),
|
||||
(110600, '[en]', 'Etc0l1', 0, 0),
|
||||
(110601, '[en]', 'Etc0l2', 0, 0),
|
||||
(110602, '[en]', 'Etc0l3', 0, 0),
|
||||
(110603, '[en]', 'Etc0l4', 0, 0),
|
||||
(110604, '[en]', 'Etc0l5', 0, 0),
|
||||
(110605, '[en]', 'Etc0l6', 0, 0),
|
||||
(110606, '[en]', 'Etc0l7', 0, 0),
|
||||
(110607, '[en]', 'Etc0l8', 0, 0),
|
||||
(110608, '[en]', 'Etc0l9', 0, 0),
|
||||
(110609, '[en]', 'Etc0g1', 0, 0),
|
||||
(110610, '[en]', 'Etc0g2', 0, 0),
|
||||
(110611, '[en]', 'Etc0g3', 0, 0),
|
||||
(110612, '[en]', 'Etc0g4', 0, 0),
|
||||
(110613, '[en]', 'Etc0g5', 0, 0),
|
||||
(110614, '[en]', 'Etc0g6', 0, 0),
|
||||
(110615, '[en]', 'Etc0g7', 0, 0),
|
||||
(110616, '[en]', 'Etc0g8', 0, 0),
|
||||
(110617, '[en]', 'Etc0g9', 0, 0),
|
||||
(110618, '[en]', 'Etc0u1', 0, 0),
|
||||
(110619, '[en]', 'Etc0u2', 0, 0),
|
||||
(110620, '[en]', 'Etc0u3', 0, 0),
|
||||
(110621, '[en]', 'Etc0u4', 0, 0),
|
||||
(110622, '[en]', 'Etc0u5', 0, 0),
|
||||
(110623, '[en]', 'Etc0u6', 0, 0),
|
||||
(110624, '[en]', 'Etc0u7', 0, 0),
|
||||
(110625, '[en]', 'Etc0u8', 0, 0),
|
||||
(110626, '[en]', 'Etc0u9', 0, 0),
|
||||
(110627, 'Ifrit Bleeds, We Can Kill It', 'Sum6a0', 0, 45),
|
||||
(110628, '[en]', 'Sum7l0', 0, 0),
|
||||
(110629, '[en]', 'Sum7t0', 0, 0),
|
||||
(110630, '[en]', 'Sum8a0', 0, 0),
|
||||
(110631, '[en]', 'Sum8l0', 0, 0),
|
||||
(110632, '[en]', 'Sum8t0', 0, 0),
|
||||
(110633, 'Assessing the Damage', 'Etc1l0', 0, 20),
|
||||
(110634, 'Bridging the Gap', 'Etc1l1', 0, 10),
|
||||
(110635, '[en]', 'Etc1l2', 0, 0),
|
||||
(110636, 'Revenge on the Reavers', 'Etc1l3', 0, 45),
|
||||
(110637, '[en]', 'Etc1l4', 0, 0),
|
||||
(110638, 'Till Death Do Us Part', 'Etc1l5', 0, 20),
|
||||
(110639, 'Beryl Overboard', 'Etc1l6', 110638, 20),
|
||||
(110640, 'Have You Seen My Son', 'Etc1l7', 0, 30),
|
||||
(110641, 'Food for Thought', 'Etc1l8', 0, 20),
|
||||
(110642, 'Seashells by the Seashore', 'Etc1l9', 0, 20),
|
||||
(110643, 'Fishing for Answers', 'Etc2l0', 0, 25),
|
||||
(110644, 'Moonstruck', 'Etc2l1', 0, 20),
|
||||
(110645, '[en]', 'Etc2l2', 0, 0),
|
||||
(110646, 'A Misty Past', 'Etc2l3', 0, 17),
|
||||
(110647, '[en]', 'Etc2l4', 0, 0),
|
||||
(110648, 'Carving a Name', 'Etc2l5', 0, 47),
|
||||
(110649, '[en]', 'Etc2l6', 0, 0),
|
||||
(110650, '[en]', 'Etc2l7', 0, 0),
|
||||
(110651, '[en]', 'Etc2l8', 0, 0),
|
||||
(110652, '[en]', 'Etc2l9', 0, 0),
|
||||
(110653, 'The Tug of the Whorl', 'Etc3l0', 0, 5),
|
||||
(110654, 'Proceed with Caution', 'Etc1g0', 0, 10),
|
||||
(110655, 'Playing with Fire', 'Etc1g1', 0, 15),
|
||||
(110656, 'A Well-Balanced Diet', 'Etc1g2', 0, 25),
|
||||
(110657, '[en]', 'Etc1g3', 0, 0),
|
||||
(110658, 'The Penultimate Prank', 'Etc1g4', 0, 30),
|
||||
(110659, 'The Search for Sicksa', 'Etc1g5', 0, 10),
|
||||
(110660, 'The Ultimate Prank', 'Etc1g6', 110658, 35),
|
||||
(110661, '[en]', 'Etc1g7', 0, 0),
|
||||
(110662, 'Say it with Wolf Tails', 'Etc1g8', 110640, 30),
|
||||
(110663, 'Embarrassing Excerpts', 'Etc1g9', 0, 30),
|
||||
(110664, 'A Forbidden Love', 'Etc2g0', 110663, 30),
|
||||
(110665, 'Last Respects', 'Etc2g1', 0, 40),
|
||||
(110666, 'Stone Deaf', 'Etc2g2', 0, 18),
|
||||
(110667, 'Hunting the Hunters', 'Etc2g3', 0, 24),
|
||||
(110668, 'To Deskunk A Beer', 'Etc2g4', 0, 31),
|
||||
(110669, 'Losing One\'s Thread', 'Etc2g5', 0, 25),
|
||||
(110670, '[en]', 'Etc2g6', 0, 0),
|
||||
(110671, '[en]', 'Etc2g7', 0, 0),
|
||||
(110672, '[en]', 'Etc2g8', 0, 0),
|
||||
(110673, '[en]', 'Etc2g9', 0, 0),
|
||||
(110674, 'Seeing the Seers', 'Etc3g0', 0, 5),
|
||||
(110675, 'A Knock in the Night', 'Etc1u0', 0, 35),
|
||||
(110676, 'Sleepless in Eorzea', 'Etc1u1', 0, 10),
|
||||
(110677, 'Dressed to Be Killed', 'Etc1u2', 0, 45),
|
||||
(110678, '[en]', 'Etc1u3', 0, 0),
|
||||
(110679, 'The Customer Comes First', 'Etc1u4', 0, 30),
|
||||
(110680, 'An Inconvenient Dodo', 'Etc1u5', 0, 15),
|
||||
(110681, 'Besmitten and Besmirched', 'Etc1u6', 0, 15),
|
||||
(110682, 'Clasping to Hope', 'Etc1u7', 0, 34),
|
||||
(110683, 'Traumaturgy', 'Etc1u8', 110682, 36),
|
||||
(110684, 'Best Flower Ever', 'Etc1u9', 0, 10),
|
||||
(110685, 'The Unheard Horizon', 'Etc2u0', 0, 20),
|
||||
(110686, 'Freedom Isn\'t Free', 'Etc2u1', 0, 32),
|
||||
(110687, 'Ore for an Ore', 'Etc2u2', 0, 28),
|
||||
(110688, '[en]', 'Etc2u3', 0, 0),
|
||||
(110689, '[en]', 'Etc2u4', 0, 0),
|
||||
(110690, 'No Other Dodo Will Do', 'Etc2u5', 0, 15),
|
||||
(110691, '[en]', 'Etc2u6', 0, 0),
|
||||
(110692, '[en]', 'Etc2u7', 0, 0),
|
||||
(110693, '[en]', 'Etc2u8', 0, 0),
|
||||
(110694, '[en]', 'Etc2u9', 0, 0),
|
||||
(110695, 'A Call to Arms', 'Etc3u0', 0, 5),
|
||||
(110696, '[en]', 'Etc1i0', 0, 0),
|
||||
(110697, '[en]', 'Etc1i1', 0, 0),
|
||||
(110698, '[en]', 'Etc1i2', 0, 0),
|
||||
(110699, '[en]', 'Etc1i3', 0, 0),
|
||||
(110700, '[en]', 'Etc1i4', 0, 0),
|
||||
(110701, '[en]', 'Etc1i5', 0, 0),
|
||||
(110702, '[en]', 'Etc1i6', 0, 0),
|
||||
(110703, '[en]', 'Etc1i7', 0, 0),
|
||||
(110704, '[en]', 'Etc1i8', 0, 0),
|
||||
(110705, '[en]', 'Etc1i9', 0, 0),
|
||||
(110706, 'Counting Sheep', 'Etc2i0', 0, 25),
|
||||
(110707, 'A Hypocritical Oath', 'Etc2i1', 0, 25),
|
||||
(110708, 'Blood Price', 'Etc2i2', 0, 45),
|
||||
(110709, '[en]', 'Etc2i3', 0, 0),
|
||||
(110710, '[en]', 'Etc2i4', 0, 0),
|
||||
(110711, '[en]', 'Etc2i5', 0, 0),
|
||||
(110712, '[en]', 'Etc2i6', 0, 0),
|
||||
(110713, '[en]', 'Etc2i7', 0, 0),
|
||||
(110714, '[en]', 'Etc2i8', 0, 0),
|
||||
(110715, '[en]', 'Etc2i9', 0, 0),
|
||||
(110716, '[en]', 'Etc3i0', 0, 0),
|
||||
(110717, '[en]', 'Etc3i1', 0, 0),
|
||||
(110718, '[en]', 'Etc3i2', 0, 0),
|
||||
(110719, '[en]', 'Etc3i3', 0, 0),
|
||||
(110720, '[en]', 'Etc3i4', 0, 0),
|
||||
(110721, '[en]', 'Etc3i5', 0, 0),
|
||||
(110722, '[en]', 'Etc3i6', 0, 0),
|
||||
(110723, '[en]', 'Etc3i7', 0, 0),
|
||||
(110724, '[en]', 'Etc3i8', 0, 0),
|
||||
(110725, '[en]', 'Etc3i9', 0, 0),
|
||||
(110726, 'Quid Pro Quo', 'Etc3u1', 0, 15),
|
||||
(110727, 'There Might Be Blood', 'Etc3u2', 0, 21),
|
||||
(110728, 'Cutthroat Prices', 'Etc3u3', 0, 15),
|
||||
(110729, '[en]', 'Etc3u4', 0, 0),
|
||||
(110730, '[en]', 'Etc3u5', 0, 0),
|
||||
(110731, '[en]', 'Etc3u6', 0, 0),
|
||||
(110732, '[en]', 'Etc3u7', 0, 0),
|
||||
(110733, '[en]', 'Etc3u8', 0, 0),
|
||||
(110734, 'Monster of Maw Most Massive', 'Etc3u9', 0, 45),
|
||||
(110735, 'Scrubbing the Soul', 'Etc3g1', 0, 15),
|
||||
(110736, 'Disorganized Crime', 'Etc3g2', 0, 21),
|
||||
(110737, 'A Slippery Stone', 'Etc3g3', 0, 15),
|
||||
(110738, '[en]', 'Etc3g4', 0, 0),
|
||||
(110739, '[en]', 'Etc3g5', 0, 0),
|
||||
(110740, '[en]', 'Etc3g6', 0, 0),
|
||||
(110741, '[en]', 'Etc3g7', 0, 0),
|
||||
(110742, '[en]', 'Etc3g8', 0, 0),
|
||||
(110743, '[en]', 'Etc3g9', 0, 0),
|
||||
(110744, 'Winds of Change', 'Etc3l1', 0, 15),
|
||||
(110745, 'Shot Through the Heart', 'Etc3l2', 0, 21),
|
||||
(110746, 'What a Pirate Wants', 'Etc3l3', 0, 15),
|
||||
(110747, '[en]', 'Etc3l4', 0, 0),
|
||||
(110748, '[en]', 'Etc3l5', 0, 0),
|
||||
(110749, '[en]', 'Etc3l6', 0, 0),
|
||||
(110750, '[en]', 'Etc3l7', 0, 0),
|
||||
(110751, '[en]', 'Etc3l8', 0, 0),
|
||||
(110752, '[en]', 'Etc3l9', 0, 0),
|
||||
(110753, 'Of Archons and Muses', 'Wld0u1', 0, 10),
|
||||
(110754, 'Sanguine Studies', 'Wld0u2', 0, 27),
|
||||
(110755, 'Secrets Unearthed', 'Wld0u3', 0, 17),
|
||||
(110756, 'Rustproof', 'Wld0u4', 0, 28),
|
||||
(110757, '[en]', 'Wld0u5', 0, 0),
|
||||
(110758, '[en]', 'Wld0u6', 0, 0),
|
||||
(110759, '[en]', 'Wld0u7', 0, 0),
|
||||
(110760, '[en]', 'Wld0u8', 0, 0),
|
||||
(110761, '[en]', 'Wld0u9', 0, 0),
|
||||
(110762, 'In the Name of Science', 'Wld0g1', 0, 10),
|
||||
(110763, 'Hearing Confession', 'Wld0g2', 0, 10),
|
||||
(110764, 'A Bitter Oil to Swallow', 'Wld0g3', 0, 17),
|
||||
(110765, 'Spores on the Brain', 'Wld0g4', 110762, 11),
|
||||
(110766, '[en]', 'Wld0g5', 0, 0),
|
||||
(110767, '[en]', 'Wld0g6', 0, 0),
|
||||
(110768, '[en]', 'Wld0g7', 0, 0),
|
||||
(110769, '[en]', 'Wld0g8', 0, 0),
|
||||
(110770, '[en]', 'Wld0g9', 0, 0),
|
||||
(110771, 'Trading Tongueflaps', 'Wld0l1', 0, 5),
|
||||
(110772, 'Letting Out Orion\'s Belt', 'Wld0l2', 0, 10),
|
||||
(110773, 'Sour Grapes', 'Wld0l3', 0, 17),
|
||||
(110774, 'Sniffing Out a Profit', 'Wld0l4', 0, 37),
|
||||
(110775, '[en]', 'Wld0l5', 0, 0),
|
||||
(110776, '[en]', 'Wld0l6', 0, 0),
|
||||
(110777, '[en]', 'Wld0l7', 0, 0),
|
||||
(110778, '[en]', 'Wld0l8', 0, 0),
|
||||
(110779, '[en]', 'Wld0l9', 0, 0),
|
||||
(110780, '[en]', 'Wld0i1', 0, 0),
|
||||
(110781, '[en]', 'Wld0i2', 0, 0),
|
||||
(110782, '[en]', 'Wld0i3', 0, 0),
|
||||
(110783, '[en]', 'Wld0i4', 0, 0),
|
||||
(110784, '[en]', 'Wld0i5', 0, 0),
|
||||
(110785, '[en]', 'Wld0i6', 0, 0),
|
||||
(110786, '[en]', 'Wld0i7', 0, 0),
|
||||
(110787, '[en]', 'Wld0i8', 0, 0),
|
||||
(110788, '[en]', 'Wld0i9', 0, 0),
|
||||
(110789, 'The Dreamer\'s Gospel (Ul\'dah)', 'Spl0u1', 0, 5),
|
||||
(110790, 'The Dreamer\'s Dilemma (Ul\'dah)', 'Spl0u2', 0, 5),
|
||||
(110791, '[en]', 'Spl0u3', 0, 0),
|
||||
(110792, '[en]', 'Spl0u4', 0, 0),
|
||||
(110793, '[en]', 'Spl0u5', 0, 0),
|
||||
(110794, 'The Dreamer\'s Gospel (Gridania)', 'Spl0g1', 0, 5),
|
||||
(110795, 'The Dreamer\'s Dilemma (Gridania)', 'Spl0g2', 0, 5),
|
||||
(110796, '[en]', 'Spl0g3', 0, 0),
|
||||
(110797, '[en]', 'Spl0g4', 0, 0),
|
||||
(110798, '[en]', 'Spl0g5', 0, 0),
|
||||
(110799, 'The Heat Is On', 'Spl0i1', 0, 1),
|
||||
(110800, 'Impish Impositions', 'Spl0i2', 0, 1),
|
||||
(110801, 'Winter Is Not Coming', 'Spl0i3', 0, 1),
|
||||
(110802, 'Gone with the Snow', 'Spl0i4', 0, 1),
|
||||
(110803, '[en]', 'Spl0i5', 0, 0),
|
||||
(110804, 'The Dreamer\'s Gospel (Limsa Lominsa)', 'Spl0l1', 0, 5),
|
||||
(110805, 'The Dreamer\'s Dilemma (Limsa Lominsa)', 'Spl0l2', 0, 5),
|
||||
(110806, '[en]', 'Spl0l3', 0, 0),
|
||||
(110807, '[en]', 'Spl0l4', 0, 0),
|
||||
(110808, '[en]', 'Spl0l5', 0, 0),
|
||||
(110809, 'Guild Tasks', 'Noc000', 0, 0),
|
||||
(110810, 'Call of Booty', 'Etc303', 110737, 15),
|
||||
(110811, 'Risky Business', 'Etc101', 0, 18),
|
||||
(110812, 'Forging the Spirit', 'Etc102', 0, 18),
|
||||
(110813, 'Joining the Spirit', 'Etc103', 0, 18),
|
||||
(110814, 'Waking the Spirit', 'Etc104', 0, 18),
|
||||
(110815, '[en]', 'Etc105', 0, 0),
|
||||
(110816, 'A Feast of Fools', 'Sum6m0', 0, 45),
|
||||
(110817, 'Provisioning & Supply Missions', 'Noc001', 0, 0),
|
||||
(110818, 'A Light in the Dark', 'Etc200', 0, 45),
|
||||
(110819, 'What Glitters Always Isn\'t Gold', 'Etc201', 0, 45),
|
||||
(110820, '[en]', 'Etc202', 0, 1),
|
||||
(110821, 'the Thousand Maws of Toto’Rak', 'Etc202', 0, 1),
|
||||
(110822, 'Dzemael Darkhold', 'Etc202', 0, 1),
|
||||
(110823, 'Aurum Vale', 'Etc202', 0, 1),
|
||||
(110824, 'Cutter\'s Cry', 'Etc202', 0, 1),
|
||||
(110828, 'Waste Not Want Not', 'Etc5g0', 110006, 1),
|
||||
(110829, 'In Plain Sight', 'Etc5g1', 0, 15),
|
||||
(110838, 'The Ink Thief', 'Etc5l0', 110002, 1),
|
||||
(110839, 'Private Eyes', 'Etc5l1', 0, 15),
|
||||
(110840, 'Mysteries of the Red Moon', 'Etc5l2', 110839, 20),
|
||||
(110841, 'Prophecy Inspection', 'Etc5l3', 110840, 20),
|
||||
(110848, 'Ring of Deceit', 'Etc5u0', 110010, 1),
|
||||
(110849, 'The Usual Suspect', 'Etc5u1', 0, 15),
|
||||
(110850, '[en]', 'Etc5u2', 0, 1),
|
||||
(110851, '[en]', 'Etc5u3', 0, 1),
|
||||
(110858, 'Seasonal Event', 'Spl000', 0, 1),
|
||||
(110859, 'Scrambled Eggs', 'Spl101', 0, 1),
|
||||
(110860, 'Bombard Backlash', 'Spl102', 0, 1),
|
||||
(110861, 'Seasonal Event (All City-states)', 'Spl103', 0, 1),
|
||||
(110862, 'Hamlet Defense', 'Noc002', 0, 1),
|
||||
(110863, 'Class is in Session', 'Noc003', 0, 1),
|
||||
(110867, 'Taming the Tempest', 'Sum6g0', 0, 45),
|
||||
(110868, 'A Relic Reborn', 'Etc106', 0, 50),
|
||||
(110869, 'Living on a Prayer', 'Etc304', 0, 45),
|
||||
(110870, 'The Raven, Nevermore', 'Sum6w0', 0, 45),
|
||||
(111201, 'Pride and Duty (Will Take You from the Mountain)', 'War0j1', 0, 15),
|
||||
(111202, 'Embracing the Beast', 'War0j2', 0, 15),
|
||||
(111203, 'Curious Gorge Goes to the Bazaar', 'War0j3', 0, 15),
|
||||
(111204, 'Looking the Part', 'War0j4', 0, 15),
|
||||
(111205, 'Proof is in the Pudding', 'War0j5', 0, 15),
|
||||
(111206, 'How to Quit You', 'War0j6', 0, 15),
|
||||
(111221, 'Brother from Another Mother', 'Mnk0j1', 0, 15),
|
||||
(111222, 'Insulted Intelligence', 'Mnk0j2', 0, 15),
|
||||
(111223, 'The Pursuit of Power', 'Mnk0j3', 0, 15),
|
||||
(111224, 'Good Vibrations', 'Mnk0j4', 0, 15),
|
||||
(111225, 'Five Easy Pieces', 'Mnk0j5', 0, 15),
|
||||
(111226, 'Return of the King...of Ruin', 'Mnk0j6', 0, 15),
|
||||
(111241, 'Seeds of Initiative', 'Whm0j1', 0, 15),
|
||||
(111242, 'When Sheep Attack', 'Whm0j2', 0, 15),
|
||||
(111243, 'Lost in Rage', 'Whm0j3', 0, 15),
|
||||
(111244, 'The Wheel of Disaster', 'Whm0j4', 0, 15),
|
||||
(111245, 'In Search of Succor', 'Whm0j5', 0, 15),
|
||||
(111246, 'The Chorus of Cataclysm', 'Whm0j6', 0, 15),
|
||||
(111261, 'Hearing Voices', 'Blm0j1', 0, 15),
|
||||
(111262, 'A Time to Kill', 'Blm0j2', 0, 15),
|
||||
(111263, 'International Relations', 'Blm0j3', 0, 15),
|
||||
(111264, 'The Voidgate Breathes Gloomy', 'Blm0j4', 0, 15),
|
||||
(111265, 'Gearing Up', 'Blm0j5', 0, 15),
|
||||
(111266, 'Always Bet on Black', 'Blm0j6', 0, 15),
|
||||
(111281, 'Paladin\'s Pledge', 'Pld0j1', 0, 15),
|
||||
(111282, 'Honor Lost', 'Pld0j2', 0, 15),
|
||||
(111283, 'Power Struggles', 'Pld0j3', 0, 15),
|
||||
(111284, 'Poisoned Hearts', 'Pld0j4', 0, 15),
|
||||
(111285, 'Parley on High Ground', 'Pld0j5', 0, 15),
|
||||
(111286, 'Keeping the Oath', 'Pld0j6', 0, 15),
|
||||
(111301, 'A Song of Bards and Bowmen', 'Brd0j1', 0, 15),
|
||||
(111302, 'The Archer\'s Anthem', 'Brd0j2', 0, 15),
|
||||
(111303, 'Bard\'s-Eye View', 'Brd0j3', 0, 15),
|
||||
(111304, 'Doing It the Bard Way', 'Brd0j4', 0, 15),
|
||||
(111305, 'Pieces of the Past', 'Brd0j5', 0, 15),
|
||||
(111306, 'Requiem for the Fallen', 'Brd0j6', 0, 15),
|
||||
(111321, 'Eye of the Dragon', 'Drg0j1', 0, 15),
|
||||
(111322, 'Lance of Fury', 'Drg0j2', 0, 15),
|
||||
(111323, 'Unfading Scars', 'Drg0j3', 0, 15),
|
||||
(111324, 'Double Dragoon', 'Drg0j4', 0, 15),
|
||||
(111325, 'Fatal Seduction', 'Drg0j5', 0, 15),
|
||||
(111326, 'Into the Dragon\'s Maw', 'Drg0j6', 0, 15),
|
||||
(111401, 'The Price of Integrity', 'Com0l1', 0, 22),
|
||||
(111402, 'Testing the Waters', 'Com0l2', 0, 22),
|
||||
(111403, 'Seals for the Whorl', 'Com0l3', 0, 22),
|
||||
(111404, 'Engineering Victory', 'Com0l4', 0, 22),
|
||||
(111405, 'An Officer and a Wise Man', 'Com0l5', 0, 25),
|
||||
(111406, 'Ceruleum Shock', 'Com0l6', 0, 25),
|
||||
(111407, 'Till Sea Swallows All', 'Com0l7', 0, 25),
|
||||
(111408, '[en]', 'Com0l8', 0, 0),
|
||||
(111409, '[en]', 'Com0l9', 0, 0),
|
||||
(111410, 'Imperial Devices (Limsa Lominsa)', 'Com5l0', 0, 25),
|
||||
(111411, 'Into the Dark (Limsa Lominsa)', 'Com5l1', 0, 45),
|
||||
(111412, '[en]', 'Com5l2', 0, 0),
|
||||
(111413, '[en]', 'Com5l3', 0, 0),
|
||||
(111414, '[en]', 'Com5l4', 0, 0),
|
||||
(111415, '[en]', 'Com5l5', 0, 0),
|
||||
(111416, 'It Kills with Fire (Limsa Lominsa)', 'Gcl101', 0, 30),
|
||||
(111417, 'The Cove', 'Gcl301', 0, 25),
|
||||
(111418, 'Saving the Stead Instead', 'Gcl302', 0, 25),
|
||||
(111419, 'It\'s a Piece of Cake to Bake a Poison Cake', 'Gcl303', 0, 40),
|
||||
(111420, 'Kobold and the Beautiful', 'Gcl304', 0, 45),
|
||||
(111421, '[en]', 'Gcl501', 0, 0),
|
||||
(111422, '[en]', 'Gcl502', 0, 0),
|
||||
(111423, '[en]', 'Gcl601', 0, 0),
|
||||
(111424, '[en]', 'Gcl602', 0, 0),
|
||||
(111425, '[en]', 'Gcl603', 0, 0),
|
||||
(111426, 'Oil Crisis', 'Gcl305', 0, 50),
|
||||
(111427, 'Alive', 'Gcl102', 0, 40),
|
||||
(111428, 'The Weakest Link', 'Gcl701', 0, 45),
|
||||
(111429, 'Deus ex Machina', 'Gcl103', 0, 45),
|
||||
(111430, 'In for Garuda Wakening (Limsa Lominsa)', 'Gcl104', 0, 45),
|
||||
(111431, 'Don\'t Hate the Messenger (Limsa Lominsa)', 'Gcl105', 0, 45),
|
||||
(111432, 'United We Stand (Limsa Lominsa)', 'Gcl106', 0, 45),
|
||||
(111433, 'To Kill a Raven (Limsa Lominsa)', 'Gcl107', 0, 45),
|
||||
(111434, 'Patrol, Interrupted', 'Gcl702', 0, 50),
|
||||
(111601, 'Breaking the Seals', 'Com0g1', 0, 22),
|
||||
(111602, 'Why Did It Have to Be Snakes', 'Com0g2', 0, 22),
|
||||
(111603, 'Adder\'s Nest Egg', 'Com0g3', 0, 22),
|
||||
(111604, 'The Mail Must Get Through', 'Com0g4', 0, 22),
|
||||
(111605, 'Their Finest Hour', 'Com0g5', 0, 25),
|
||||
(111606, 'Appetite for Destruction', 'Com0g6', 0, 25),
|
||||
(111607, 'Serenity, Purity, Sanctity', 'Com0g7', 0, 25),
|
||||
(111608, '[en]', 'Com0g8', 0, 0),
|
||||
(111609, '[en]', 'Com0g9', 0, 0),
|
||||
(111610, 'Imperial Devices (Gridania)', 'Com5g0', 0, 25),
|
||||
(111611, 'Into the Dark (Gridania)', 'Com5g1', 0, 45),
|
||||
(111612, '[en]', 'Com5g2', 0, 0),
|
||||
(111613, '[en]', 'Com5g3', 0, 0),
|
||||
(111614, '[en]', 'Com5g4', 0, 0),
|
||||
(111615, '[en]', 'Com5g5', 0, 0),
|
||||
(111616, 'It Kills with Fire (Gridania)', 'Gcg101', 0, 30),
|
||||
(111617, 'Eternal Recurrence', 'Gcg301', 0, 25),
|
||||
(111618, 'The Pen Is Mightier Than the Spear', 'Gcg302', 0, 25),
|
||||
(111619, 'Woes of the Botanist', 'Gcg303', 0, 40),
|
||||
(111620, 'Gone with the Wind', 'Gcg304', 0, 45),
|
||||
(111621, '[en]', 'Gcg501', 0, 0),
|
||||
(111622, '[en]', 'Gcg502', 0, 0),
|
||||
(111623, '[en]', 'Gcg601', 0, 0),
|
||||
(111624, '[en]', 'Gcg602', 0, 0),
|
||||
(111625, '[en]', 'Gcg603', 0, 0),
|
||||
(111626, 'A Taste for Death', 'Gcg305', 0, 50),
|
||||
(111627, 'Two Vans are Better than One', 'Gcg102', 0, 40),
|
||||
(111628, 'You Don\'t Have the Rite', 'Gcg701', 0, 45),
|
||||
(111629, 'Shadow of the Raven', 'Gcg103', 0, 45),
|
||||
(111630, 'In for Garuda Wakening (Gridania)', 'Gcg104', 0, 45),
|
||||
(111631, 'Don\'t Hate the Messenger (Gridania)', 'Gcg105', 0, 45),
|
||||
(111632, 'United We Stand (Gridania)', 'Gcg106', 0, 45),
|
||||
(111633, 'To Kill a Raven (Gridania)', 'Gcg107', 0, 45),
|
||||
(111634, 'Cure for the Common Pox', 'Gcg702', 0, 50),
|
||||
(111801, 'Career Opportunities', 'Com0u1', 0, 22),
|
||||
(111802, 'Kindling a Flame', 'Com0u2', 0, 22),
|
||||
(111803, 'Burning a Hole in One\'s Pocket', 'Com0u3', 0, 22),
|
||||
(111804, 'Arms Race', 'Com0u4', 0, 22),
|
||||
(111805, 'Burning Man', 'Com0u5', 0, 25),
|
||||
(111806, 'Know Your Enemy', 'Com0u6', 0, 25),
|
||||
(111807, 'By Fire Reborn', 'Com0u7', 0, 25),
|
||||
(111808, '[en]', 'Com0u8', 0, 0),
|
||||
(111809, '[en]', 'Com0u9', 0, 0),
|
||||
(111810, 'Imperial Devices (Ul\'dah)', 'Com5u0', 0, 25),
|
||||
(111811, 'Into the Dark (Ul\'dah)', 'Com5u1', 0, 45),
|
||||
(111812, '[en]', 'Com5u2', 0, 0),
|
||||
(111813, '[en]', 'Com5u3', 0, 0),
|
||||
(111814, '[en]', 'Com5u4', 0, 0),
|
||||
(111815, '[en]', 'Com5u5', 0, 0),
|
||||
(111816, 'It Kills with Fire (Ul\'dah)', 'Gcu101', 0, 30),
|
||||
(111817, 'Prying Eyes', 'Gcu301', 0, 25),
|
||||
(111818, 'Different Strokes', 'Gcu302', 0, 25),
|
||||
(111819, 'A Weaver and a Mummer', 'Gcu303', 0, 40),
|
||||
(111820, 'When Alchemists Cry', 'Gcu304', 0, 45),
|
||||
(111821, '[en]', 'Gcu501', 0, 0),
|
||||
(111822, '[en]', 'Gcu502', 0, 0),
|
||||
(111823, '[en]', 'Gcu601', 0, 0),
|
||||
(111824, '[en]', 'Gcu602', 0, 0),
|
||||
(111825, '[en]', 'Gcu603', 0, 0),
|
||||
(111826, 'Challenge Accepted', 'Gcu305', 0, 50),
|
||||
(111827, 'Like Father, Like Son', 'Gcu102', 0, 40),
|
||||
(111828, 'Gore a Lizard, Hurry', 'Gcu701', 0, 45),
|
||||
(111829, 'Careless Whispers', 'Gcu103', 0, 45),
|
||||
(111830, 'In for Garuda Wakening (Ul\'dah)', 'Gcu104', 0, 45),
|
||||
(111831, 'Don\'t Hate the Messenger (Ul\'dah)', 'Gcu105', 0, 45),
|
||||
(111832, 'United We Stand (Ul\'dah)', 'Gcu106', 0, 45),
|
||||
(111833, 'To Kill a Raven (Ul\'dah)', 'Gcu107', 0, 45),
|
||||
(111834, 'Mess with the Goat, Get the Horns', 'Gcu702', 0, 50);
|
||||
/*!40000 ALTER TABLE `gamedata_quests` ENABLE KEYS */;
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
|
||||
namespace Meteor.Map.actors.chara.ai.state
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ using Meteor.Common;
|
|||
using Meteor.Map.actors.chara.player;
|
||||
using Meteor.Map.actors.group;
|
||||
using Meteor.Map.Actors.Chara;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.actor;
|
||||
using Meteor.Map.packets.send.actor.inventory;
|
||||
using Meteor.Map.utils;
|
||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
using Meteor.Common;
|
||||
using Meteor.Map.actors.chara.npc;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.actor.inventory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -23,8 +23,8 @@ using Meteor.Common;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MoonSharp.Interpreter;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.dataobjects.chara;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.DataObjects.chara;
|
||||
using Meteor.Map.lua;
|
||||
using Meteor.Map.packets.WorldPackets.Send.Group;
|
||||
using Meteor.Map.utils;
|
||||
|
@ -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;
|
||||
|
@ -46,6 +47,7 @@ using Meteor.Map.packets.send.actor.battle;
|
|||
using Meteor.Map.packets.receive.events;
|
||||
using static Meteor.Map.LuaUtils;
|
||||
using Meteor.Map.packets.send.actor.events;
|
||||
using System.Text;
|
||||
|
||||
namespace Meteor.Map.Actors
|
||||
{
|
||||
|
@ -147,6 +149,7 @@ namespace Meteor.Map.Actors
|
|||
//Quest Actors (MUST MATCH playerWork.questScenario/questGuildleve)
|
||||
public Quest[] questScenario = new Quest[16];
|
||||
public uint[] questGuildleve = new uint[8];
|
||||
public QuestStateManager questStateManager;
|
||||
|
||||
//Aetheryte
|
||||
public uint homepoint = 0;
|
||||
|
@ -242,7 +245,6 @@ namespace Meteor.Map.Actors
|
|||
|
||||
charaWork.commandAcquired[27150 - 26000] = true;
|
||||
|
||||
playerWork.questScenarioComplete[110001 - 110001] = true;
|
||||
playerWork.questGuildleveComplete[120050 - 120001] = true;
|
||||
|
||||
for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++ )
|
||||
|
@ -274,6 +276,9 @@ namespace Meteor.Map.Actors
|
|||
this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this));
|
||||
allegiance = CharacterTargetingAllegiance.Player;
|
||||
CalculateBaseStats();
|
||||
|
||||
questStateManager = new QuestStateManager(this);
|
||||
questStateManager.Init(questScenario, playerWork.questScenarioComplete);
|
||||
}
|
||||
|
||||
public List<SubPacket> Create0x132Packets()
|
||||
|
@ -400,9 +405,10 @@ namespace Meteor.Map.Actors
|
|||
if (CurrentArea.isInn)
|
||||
{
|
||||
SetCutsceneBookPacket cutsceneBookPacket = new SetCutsceneBookPacket();
|
||||
bool[] testComplete = new bool[2048]; //TODO: Change to playerwork.scenarioComplete
|
||||
for (int i = 0; i < 2048; i++)
|
||||
cutsceneBookPacket.cutsceneFlags[i] = true;
|
||||
QueuePacket(cutsceneBookPacket.BuildPacket(Id, "<Path Companion>", 11, 1, 1));
|
||||
testComplete[i] = true;
|
||||
QueuePacket(cutsceneBookPacket.BuildPacket(Id, "<Path Companion>", 11, 1, 1, testComplete));
|
||||
QueuePacket(SetPlayerDreamPacket.BuildPacket(Id, 0x16, GetInnCode()));
|
||||
}
|
||||
|
||||
|
@ -801,7 +807,7 @@ namespace Meteor.Map.Actors
|
|||
foreach (Quest quest in questScenario)
|
||||
{
|
||||
if (quest != null)
|
||||
quest.SaveData();
|
||||
quest.GetData().Save();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1151,6 +1157,42 @@ namespace Meteor.Map.Actors
|
|||
|
||||
}
|
||||
|
||||
private void SendAchievedAetheryte(ushort from, ushort to)
|
||||
{
|
||||
Bitstream fakeAetheryte = new Bitstream(512, true);
|
||||
|
||||
SetActorPropetyPacket completedQuestWorkUpdate = new SetActorPropetyPacket(from, to, "work/achieveAetheryte");
|
||||
completedQuestWorkUpdate.AddBitfield(Utils.MurmurHash2("work.event_achieve_aetheryte", 0), fakeAetheryte.GetSlice(from, to));
|
||||
completedQuestWorkUpdate.AddTarget();
|
||||
QueuePacket(completedQuestWorkUpdate.BuildPacket(Id));
|
||||
}
|
||||
|
||||
private void SendCompletedQuests(ushort from, ushort to)
|
||||
{
|
||||
byte[] data = questStateManager.GetCompletionSliceBytes(from, to);
|
||||
|
||||
SetActorPropetyPacket completedQuestWorkUpdate = new SetActorPropetyPacket(from, to, "playerWork/journal");
|
||||
completedQuestWorkUpdate.AddBitfield(Utils.MurmurHash2("playerWork.questScenarioComplete", 0), data);
|
||||
completedQuestWorkUpdate.AddTarget();
|
||||
QueuePacket(completedQuestWorkUpdate.BuildPacket(Id));
|
||||
}
|
||||
|
||||
public void OnWorkSyncRequest(string propertyName, ushort from = 0, ushort to = 0)
|
||||
{
|
||||
switch (propertyName)
|
||||
{
|
||||
case "charaWork/exp":
|
||||
SendCharaExpInfo();
|
||||
break;
|
||||
case "work/achieveAetheryte":
|
||||
SendAchievedAetheryte(from, to);
|
||||
break;
|
||||
case "playerWork/questCompleteS":
|
||||
SendCompletedQuests(from, to);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetHighestLevel()
|
||||
{
|
||||
int max = 0;
|
||||
|
@ -1413,33 +1455,276 @@ 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;
|
||||
SendQuestClientUpdate(freeSlot);
|
||||
|
||||
if (!isSilent)
|
||||
{
|
||||
SendGameMessage(Server.GetWorldManager().GetActor(), 25224, 0x20, (object)questScenario[freeSlot].GetQuestId()); // "<Quest> accepted."
|
||||
}
|
||||
|
||||
instance.OnAccept();
|
||||
|
||||
Database.SaveQuest(this, questScenario[freeSlot], freeSlot);
|
||||
|
||||
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;
|
||||
SendQuestClientUpdate(i);
|
||||
oldQuestInstance.OnComplete();
|
||||
questStateManager.UpdateQuestCompleted(oldQuestInstance);
|
||||
newQuestInstance.OnAccept();
|
||||
Database.SaveQuest(this, questScenario[i], 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;
|
||||
questScenario[slot] = null;
|
||||
playerWork.questScenario[slot] = 0;
|
||||
SendQuestClientUpdate(slot);
|
||||
|
||||
// Reset active quest and quest state
|
||||
completed.OnComplete();
|
||||
Database.SaveCompletedQuests(playerSession.GetActor());
|
||||
Database.RemoveQuest(this, completed.Id);
|
||||
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
|
||||
questScenario[slot] = null;
|
||||
playerWork.questScenario[slot] = 0;
|
||||
SendQuestClientUpdate(slot);
|
||||
|
||||
// Reset active quest and quest state
|
||||
abandoned.OnAbandon();
|
||||
Database.RemoveQuest(this, abandoned.Id);
|
||||
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], 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 bool IsQuestCompleted(uint id)
|
||||
{
|
||||
return questStateManager.IsQuestComplete(id);
|
||||
}
|
||||
|
||||
public void SetQuestComplete(uint id, bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
Quest currentQuest = GetQuest(id);
|
||||
if (currentQuest != null)
|
||||
{
|
||||
CompleteQuest(currentQuest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
questStateManager.ForceQuestCompleteFlag(id, flag);
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -1486,178 +1771,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)
|
||||
{
|
||||
for (int i = 0; i < work.guildleveId.Length; i++)
|
||||
|
@ -1668,17 +1781,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)
|
||||
{
|
||||
|
@ -1732,7 +1835,9 @@ namespace Meteor.Map.Actors
|
|||
|
||||
public Quest[] GetQuestsForNpc(Npc npc)
|
||||
{
|
||||
return Array.FindAll(questScenario, e => e != null && e.IsQuestENPC(this, 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)
|
||||
|
@ -2755,6 +2860,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
namespace Meteor.Map.dataobjects.chara
|
||||
namespace Meteor.Map.DataObjects.chara
|
||||
{
|
||||
class PlayerWork
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
|
||||
using Meteor.Map.actors.chara.player;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.actor.inventory;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
using Meteor.Common;
|
||||
using Meteor.Map.actors.director.Work;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -23,7 +23,7 @@ using Meteor.Common;
|
|||
using Meteor.Map.actors.director;
|
||||
using Meteor.Map.actors.group.Work;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.group;
|
||||
using Meteor.Map.packets.send.groups;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.group;
|
||||
using Meteor.Map.packets.send.groups;
|
||||
using System;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.group;
|
||||
using Meteor.Map.packets.send.groups;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -21,7 +21,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.actors.group.Work;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.group;
|
||||
using Meteor.Map.packets.send.groups;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
using Meteor.Common;
|
||||
using Meteor.Map.actors.chara.npc;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.group;
|
||||
using Meteor.Map.packets.send.groups;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -21,7 +21,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.actors.group.Work;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.send.group;
|
||||
using Meteor.Map.packets.send.groups;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -20,113 +20,124 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Map.lua;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Meteor.Map.Actors
|
||||
namespace Meteor.Map.Actors.QuestNS
|
||||
{
|
||||
class Quest : Actor
|
||||
{
|
||||
public const ushort SEQ_NOT_STARTED = ushort.MaxValue;
|
||||
public const ushort SEQ_NOT_STARTED = 65535;
|
||||
public const ushort SEQ_COMPLETED = 65534;
|
||||
|
||||
public enum QuestFlag { None = 0, Map = 1, Plate = 2 }
|
||||
public enum ENpcProperty { QuestFlag = 0, CanTalk = 1, CanPush = 2, CanEmote = 3, CanNotice = 4}
|
||||
|
||||
public class ENpcQuestInstance
|
||||
{
|
||||
public readonly uint actorClassId;
|
||||
public byte questFlagType { set; get; }
|
||||
public bool isSpawned { set; get; }
|
||||
public bool isTalkEnabled { set; get; }
|
||||
public bool isEmoteEnabled { set; get; }
|
||||
public bool isPushEnabled { set; get; }
|
||||
|
||||
public ENpcQuestInstance(uint actorClassId, byte questFlagType, bool isSpawned, bool isTalkEnabled, bool isEmoteEnabled, bool isPushEnabled)
|
||||
{
|
||||
this.actorClassId = actorClassId;
|
||||
this.questFlagType = questFlagType;
|
||||
this.isSpawned = isSpawned;
|
||||
this.isTalkEnabled = isTalkEnabled;
|
||||
this.isEmoteEnabled = isEmoteEnabled;
|
||||
this.isPushEnabled = isPushEnabled;
|
||||
}
|
||||
|
||||
public bool IsChanged(byte flagType, bool isTalkEnabled, bool isPushEnabled, bool isEmoteEnabled, bool isSpawned)
|
||||
{
|
||||
return flagType != this.questFlagType
|
||||
|| isTalkEnabled != this.isTalkEnabled
|
||||
|| isPushEnabled != this.isPushEnabled
|
||||
|| isEmoteEnabled != this.isEmoteEnabled
|
||||
|| isSpawned != this.isSpawned;
|
||||
}
|
||||
|
||||
public void Update(byte flagType, bool isTalkEnabled, bool isPushEnabled, bool isEmoteEnabled, bool isSpawned)
|
||||
{
|
||||
this.questFlagType = flagType;
|
||||
this.isSpawned = isSpawned;
|
||||
this.isTalkEnabled = isTalkEnabled;
|
||||
this.isEmoteEnabled = isEmoteEnabled;
|
||||
this.isPushEnabled = isPushEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
private struct QuestData
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private Player Owner;
|
||||
private Player owner;
|
||||
private ushort currentSequence;
|
||||
private QuestData data = new QuestData();
|
||||
private bool dataDirty = false;
|
||||
private Dictionary<uint, ENpcQuestInstance> CurrentENPCs = new Dictionary<uint, ENpcQuestInstance>();
|
||||
private Dictionary<uint, ENpcQuestInstance> OldENPCs = new Dictionary<uint, ENpcQuestInstance>();
|
||||
private QuestState questState = null;
|
||||
private QuestData data = null;
|
||||
|
||||
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
||||
// Creates a Static Quest for the StaticActors list.
|
||||
public Quest(uint actorID, string className, string classPath)
|
||||
: base(actorID)
|
||||
{
|
||||
ENpcQuestInstance instanceUpdated = null;
|
||||
|
||||
if (OldENPCs.ContainsKey(classId))
|
||||
{
|
||||
if (OldENPCs[classId].IsChanged(flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned))
|
||||
{
|
||||
OldENPCs[classId].Update(flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
|
||||
instanceUpdated = OldENPCs[classId];
|
||||
Name = className;
|
||||
this.className = className;
|
||||
this.classPath = classPath;
|
||||
}
|
||||
|
||||
CurrentENPCs.Add(classId, OldENPCs[classId]);
|
||||
OldENPCs.Remove(classId);
|
||||
}
|
||||
else
|
||||
// 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)
|
||||
{
|
||||
instanceUpdated = new ENpcQuestInstance(classId, flagType, isSpawned, isTalkEnabled, isEmoteEnabled, isPushEnabled);
|
||||
CurrentENPCs.Add(classId, instanceUpdated);
|
||||
this.owner = owner;
|
||||
currentSequence = sequence;
|
||||
questState = new QuestState(owner, this);
|
||||
questState.UpdateState();
|
||||
}
|
||||
|
||||
if (instanceUpdated != null)
|
||||
Owner.playerSession.UpdateQuestNpcInInstance(instanceUpdated);
|
||||
}
|
||||
// Creates a Instance Quest that has not been started.
|
||||
public Quest(Player owner, Quest staticQuest) : this(owner, staticQuest, SEQ_NOT_STARTED)
|
||||
{ }
|
||||
|
||||
public ENpcQuestInstance GetENpcInstance(uint classId)
|
||||
#region Getters
|
||||
public uint GetQuestId()
|
||||
{
|
||||
if (CurrentENPCs.ContainsKey(classId))
|
||||
return CurrentENPCs[classId];
|
||||
return null;
|
||||
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)
|
||||
{
|
||||
if (questState != null)
|
||||
questState.AddENpc(classId, flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
|
||||
}
|
||||
|
||||
public void UpdateENPCs()
|
||||
{
|
||||
if (data.Dirty)
|
||||
{
|
||||
if (questState != null)
|
||||
questState.UpdateState();
|
||||
data.ClearDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public QuestState GetQuestState()
|
||||
{
|
||||
return questState;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Script Callbacks
|
||||
public void OnTalk(Player caller, Npc npc)
|
||||
{
|
||||
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onTalk", true, npc);
|
||||
|
@ -152,31 +163,9 @@ namespace Meteor.Map.Actors
|
|||
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onNpcLS", true, npcLSId);
|
||||
}
|
||||
|
||||
public void UpdateENPCs()
|
||||
{
|
||||
if (dataDirty)
|
||||
{
|
||||
OldENPCs = CurrentENPCs;
|
||||
CurrentENPCs = new Dictionary<uint, ENpcQuestInstance>();
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onSequence", false, currentSequence);
|
||||
foreach (var enpc in OldENPCs)
|
||||
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value);
|
||||
OldENPCs = null;
|
||||
dataDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
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 || CurrentENPCs.ContainsKey(npc.GetActorClassId());
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
return LuaUtils.CreateLuaParamObjectList(returned);
|
||||
else
|
||||
|
@ -185,16 +174,19 @@ namespace Meteor.Map.Actors
|
|||
|
||||
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)
|
||||
return LuaUtils.CreateLuaParamObjectList(returned);
|
||||
else
|
||||
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)
|
||||
|
@ -204,180 +196,36 @@ namespace Meteor.Map.Actors
|
|||
|
||||
// Send the message that the journal has been updated
|
||||
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;
|
||||
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;
|
||||
data = new QuestData(flags, counter1, counter2, counter3);
|
||||
|
||||
data = new QuestData(owner, this);
|
||||
if (currentSequence == SEQ_NOT_STARTED)
|
||||
LuaEngine.GetInstance().CallLuaFunction(Owner, this, "onStart", false);
|
||||
LuaEngine.GetInstance().CallLuaFunction(owner, this, "onStart", false);
|
||||
else
|
||||
StartSequence(currentSequence);
|
||||
}
|
||||
|
||||
public uint GetQuestId()
|
||||
public void OnComplete()
|
||||
{
|
||||
return Id & 0xFFFFF;
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "onFinish", true);
|
||||
currentSequence = SEQ_COMPLETED;
|
||||
data = null;
|
||||
questState.UpdateState();
|
||||
}
|
||||
|
||||
public void DoComplete()
|
||||
public void OnAbandon()
|
||||
{
|
||||
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());
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "onFinish", false);
|
||||
currentSequence = SEQ_NOT_STARTED;
|
||||
data = null;
|
||||
questState.UpdateState();
|
||||
}
|
||||
|
||||
public void DoAbandon()
|
||||
{
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", false);
|
||||
Owner.SendGameMessage(Owner, Server.GetWorldManager().GetActor(), 25236, 0x20, (object)GetQuestId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
173
Map Server/Actors/Quest/QuestData.cs
Normal file
173
Map Server/Actors/Quest/QuestData.cs
Normal file
|
@ -0,0 +1,173 @@
|
|||
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;
|
||||
|
||||
public bool Dirty { get; private set; } = 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);
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearFlag(int index)
|
||||
{
|
||||
if (index >= 0 && index < 32)
|
||||
{
|
||||
flags &= (uint)~(1 << index);
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort IncCounter(int num)
|
||||
{
|
||||
Dirty = true;
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
counter1++;
|
||||
return counter1;
|
||||
case 1:
|
||||
counter2++;
|
||||
return counter2;
|
||||
case 2:
|
||||
counter3++;
|
||||
return counter3;
|
||||
case 3:
|
||||
counter4++;
|
||||
return counter4;
|
||||
}
|
||||
|
||||
Dirty = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ushort DecCounter(int num)
|
||||
{
|
||||
Dirty = true;
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
counter1--;
|
||||
return counter1;
|
||||
case 1:
|
||||
counter2--;
|
||||
return counter2;
|
||||
case 2:
|
||||
counter3--;
|
||||
return counter3;
|
||||
case 3:
|
||||
counter4--;
|
||||
return counter4;
|
||||
}
|
||||
|
||||
Dirty = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetCounter(int num, ushort value)
|
||||
{
|
||||
Dirty = true;
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
counter1 = value;
|
||||
return;
|
||||
case 1:
|
||||
counter2 = value;
|
||||
return;
|
||||
case 2:
|
||||
counter3 = value;
|
||||
return;
|
||||
case 3:
|
||||
counter4 = value;
|
||||
return;
|
||||
}
|
||||
|
||||
Dirty = 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 ClearDirty()
|
||||
{
|
||||
Dirty = false;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
Database.UpdateQuest(owner, parent);
|
||||
}
|
||||
}
|
||||
}
|
118
Map Server/Actors/Quest/QuestState.cs
Normal file
118
Map Server/Actors/Quest/QuestState.cs
Normal file
|
@ -0,0 +1,118 @@
|
|||
using Meteor.Map.lua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Meteor.Map.Actors.QuestNS
|
||||
{
|
||||
class QuestState
|
||||
{
|
||||
public enum QuestFlag { None = 0, Map = 1, Plate = 2 }
|
||||
|
||||
public class QuestENpc
|
||||
{
|
||||
public readonly uint actorClassId;
|
||||
public byte questFlagType { set; get; }
|
||||
public bool isSpawned { set; get; }
|
||||
public bool isTalkEnabled { set; get; }
|
||||
public bool isEmoteEnabled { set; get; }
|
||||
public bool isPushEnabled { set; get; }
|
||||
|
||||
public QuestENpc(uint actorClassId, byte questFlagType, bool isSpawned, bool isTalkEnabled, bool isEmoteEnabled, bool isPushEnabled)
|
||||
{
|
||||
this.actorClassId = actorClassId;
|
||||
this.questFlagType = questFlagType;
|
||||
this.isSpawned = isSpawned;
|
||||
this.isTalkEnabled = isTalkEnabled;
|
||||
this.isEmoteEnabled = isEmoteEnabled;
|
||||
this.isPushEnabled = isPushEnabled;
|
||||
}
|
||||
|
||||
public bool IsChanged(byte flagType, bool isTalkEnabled, bool isPushEnabled, bool isEmoteEnabled, bool isSpawned)
|
||||
{
|
||||
return flagType != this.questFlagType
|
||||
|| isTalkEnabled != this.isTalkEnabled
|
||||
|| isPushEnabled != this.isPushEnabled
|
||||
|| isEmoteEnabled != this.isEmoteEnabled
|
||||
|| isSpawned != this.isSpawned;
|
||||
}
|
||||
|
||||
public void Update(byte flagType, bool isTalkEnabled, bool isPushEnabled, bool isEmoteEnabled, bool isSpawned)
|
||||
{
|
||||
this.questFlagType = flagType;
|
||||
this.isSpawned = isSpawned;
|
||||
this.isTalkEnabled = isTalkEnabled;
|
||||
this.isEmoteEnabled = isEmoteEnabled;
|
||||
this.isPushEnabled = isPushEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Player Owner;
|
||||
private readonly Quest Parent;
|
||||
private Dictionary<uint, QuestENpc> CurrentENPCs = new Dictionary<uint, QuestENpc>();
|
||||
private Dictionary<uint, QuestENpc> OldENPCs = new Dictionary<uint, QuestENpc>();
|
||||
|
||||
public QuestState(Player owner, Quest parent)
|
||||
{
|
||||
Owner = owner;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
||||
{
|
||||
QuestENpc instanceUpdated = null;
|
||||
|
||||
if (OldENPCs.ContainsKey(classId))
|
||||
{
|
||||
if (OldENPCs[classId].IsChanged(flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned))
|
||||
{
|
||||
OldENPCs[classId].Update(flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
|
||||
instanceUpdated = OldENPCs[classId];
|
||||
}
|
||||
|
||||
CurrentENPCs.Add(classId, OldENPCs[classId]);
|
||||
OldENPCs.Remove(classId);
|
||||
}
|
||||
else
|
||||
{
|
||||
instanceUpdated = new QuestENpc(classId, flagType, isSpawned, isTalkEnabled, isEmoteEnabled, isPushEnabled);
|
||||
CurrentENPCs.Add(classId, instanceUpdated);
|
||||
}
|
||||
|
||||
if (instanceUpdated != null)
|
||||
Owner.playerSession.UpdateQuestNpcInInstance(instanceUpdated);
|
||||
}
|
||||
|
||||
public QuestENpc GetENpc(uint classId)
|
||||
{
|
||||
if (CurrentENPCs.ContainsKey(classId))
|
||||
return CurrentENPCs[classId];
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool HasENpc(uint classId)
|
||||
{
|
||||
return CurrentENPCs.ContainsKey(classId);
|
||||
}
|
||||
|
||||
public void UpdateState()
|
||||
{
|
||||
ushort currentSeq = Parent.GetSequence();
|
||||
OldENPCs = CurrentENPCs;
|
||||
CurrentENPCs = new Dictionary<uint, QuestENpc>();
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, Parent, "onStateChange", false, currentSeq);
|
||||
foreach (var enpc in OldENPCs)
|
||||
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value, true);
|
||||
OldENPCs = null;
|
||||
}
|
||||
|
||||
public void DeleteState()
|
||||
{
|
||||
foreach (var enpc in CurrentENPCs)
|
||||
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value, true);
|
||||
CurrentENPCs.Clear();
|
||||
}
|
||||
}
|
||||
}
|
178
Map Server/Actors/Quest/QuestStateManager.cs
Normal file
178
Map Server/Actors/Quest/QuestStateManager.cs
Normal file
|
@ -0,0 +1,178 @@
|
|||
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;
|
||||
|
||||
namespace Meteor.Map.Actors.QuestNS
|
||||
{
|
||||
class QuestStateManager
|
||||
{
|
||||
private const int SCENARIO_START = 110001;
|
||||
private const int SCENARIO_MAX = 2048;
|
||||
|
||||
private readonly Player player;
|
||||
private readonly Bitstream CompletedQuestsBitfield = new Bitstream(SCENARIO_MAX);
|
||||
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>();
|
||||
private Dictionary<uint, QuestState> QuestStateTable = new Dictionary<uint, QuestState>();
|
||||
|
||||
public QuestStateManager(Player player)
|
||||
{
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void Init(Quest[] journalQuests, bool[] completedQuests)
|
||||
{
|
||||
// Preload any quests that the player loaded
|
||||
if (journalQuests != null)
|
||||
{
|
||||
foreach (var quest in journalQuests)
|
||||
{
|
||||
if (quest != null)
|
||||
{
|
||||
ActiveQuests.Add(quest);
|
||||
AvailableQuestsBitfield.Set(quest.GetQuestId() - SCENARIO_START);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init MinLv
|
||||
QuestGameData[] minLvl = Server.GetQuestGamedataByMaxLvl(player.GetHighestLevel(), true);
|
||||
foreach (var questData in minLvl)
|
||||
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
||||
|
||||
// Init Prereq
|
||||
CompletedQuestsBitfield.SetTo(completedQuests);
|
||||
foreach (var questData in Server.GetQuestGamedataAllPrerequisite())
|
||||
{
|
||||
if (CompletedQuestsBitfield.Get(((Quest)Server.GetStaticActors(0xA0F00000 | questData.PrerequisiteQuest)).GetQuestId() - SCENARIO_START))
|
||||
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
||||
else
|
||||
PrereqBitfield.Clear(questData.Id - SCENARIO_START);
|
||||
}
|
||||
|
||||
ComputeAvailable();
|
||||
}
|
||||
|
||||
public void UpdateLevel(int level)
|
||||
{
|
||||
QuestGameData[] updated = Server.GetQuestGamedataByMaxLvl(level);
|
||||
foreach (var questData in updated)
|
||||
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
||||
ComputeAvailable();
|
||||
}
|
||||
|
||||
public void UpdateQuestCompleted(Quest quest)
|
||||
{
|
||||
CompletedQuestsBitfield.Set(quest.Id - SCENARIO_START);
|
||||
QuestGameData[] updated = Server.GetQuestGamedataByPrerequisite(quest.GetQuestId());
|
||||
foreach (var questData in updated)
|
||||
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
||||
ComputeAvailable();
|
||||
}
|
||||
|
||||
public void UpdateQuestAbandoned()
|
||||
{
|
||||
ComputeAvailable();
|
||||
}
|
||||
|
||||
private void ComputeAvailable()
|
||||
{
|
||||
Bitstream result = new Bitstream(SCENARIO_MAX);
|
||||
result.OR(CompletedQuestsBitfield);
|
||||
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))
|
||||
AddActiveQuest(quest);
|
||||
else
|
||||
RemoveActiveQuest(quest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return ActiveQuests.FindAll(quest => quest.IsQuestENPC(player, npc)).ToArray();
|
||||
}
|
||||
|
||||
public byte[] GetCompletionSliceBytes(ushort from, ushort to)
|
||||
{
|
||||
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);
|
||||
ComputeAvailable();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.Actors.QuestNS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -98,7 +99,7 @@ namespace Meteor.Map.Actors
|
|||
if (actorType.Equals("Command"))
|
||||
actor = new Command(id, actorName);
|
||||
else if (actorType.Equals("Quest"))
|
||||
actor = new Quest(id, actorName);
|
||||
actor = new Quest(id, actorName, output);
|
||||
//else if (actorType.Equals("Status"))
|
||||
//mStaticActors.Add(id, new Status(id, actorName));
|
||||
else if (actorType.Equals("Judge"))
|
||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
|
||||
using System.IO;
|
||||
using Meteor.Map.packets.send;
|
||||
|
|
|
@ -21,7 +21,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class GuildleveData
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ using MySql.Data.MySqlClient;
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class InventoryItem
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
using MySql.Data.MySqlClient;
|
||||
using System;
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class ItemData
|
||||
{
|
||||
|
|
28
Map Server/DataObjects/QuestGameData.cs
Normal file
28
Map Server/DataObjects/QuestGameData.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class QuestGameData
|
||||
{
|
||||
public uint Id { get; }
|
||||
public string ClassName { get; }
|
||||
public string Name { get; }
|
||||
public uint PrerequisiteQuest { get; }
|
||||
public int MinLevel { get; }
|
||||
public int MinGCRank { get; }
|
||||
|
||||
public QuestGameData(uint id, string className, string name, uint prereq, int minLv, int minGcRank)
|
||||
{
|
||||
Id = id;
|
||||
ClassName = className;
|
||||
Name = Name;
|
||||
PrerequisiteQuest = prereq;
|
||||
MinLevel = minLv;
|
||||
MinGCRank = minGcRank;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class RecruitmentDetails
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class SeamlessBoundry
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ using System;
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class SearchEntry
|
||||
{
|
||||
|
|
|
@ -25,9 +25,10 @@ using Meteor.Map.Actors;
|
|||
using Meteor.Map.packets.send.actor;
|
||||
using System.Collections.Generic;
|
||||
using Meteor.Map.actors.chara.npc;
|
||||
using static Meteor.Map.Actors.Quest;
|
||||
using Meteor.Map.Actors.QuestNS;
|
||||
using static Meteor.Map.Actors.QuestNS.QuestState;
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class Session
|
||||
{
|
||||
|
@ -167,7 +168,7 @@ namespace Meteor.Map.dataobjects
|
|||
Quest[] quests = playerActor.GetQuestsForNpc(npc);
|
||||
if (quests.Length != 0)
|
||||
{
|
||||
ENpcQuestInstance questInstance = quests[0].GetENpcInstance(npc.GetActorClassId());
|
||||
QuestENpc questInstance = quests[0].GetQuestState().GetENpc(npc.GetActorClassId());
|
||||
QueuePacket(npc.GetSetEventStatusPackets());
|
||||
QueuePacket(SetActorQuestGraphicPacket.BuildPacket(npc.Id, questInstance.questFlagType));
|
||||
}
|
||||
|
@ -179,7 +180,7 @@ namespace Meteor.Map.dataobjects
|
|||
}
|
||||
}
|
||||
|
||||
public void UpdateQuestNpcInInstance(ENpcQuestInstance questInstance, bool clearInstance = false)
|
||||
public void UpdateQuestNpcInInstance(QuestENpc questInstance, bool clearInstance = false)
|
||||
{
|
||||
LockUpdates(true);
|
||||
Actor actor = actorInstanceList.Find(x => x is Npc npc && npc.GetActorClassId().Equals(questInstance.actorClassId));
|
||||
|
|
|
@ -19,6 +19,6 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ using System.Collections.Concurrent;
|
|||
using System.Net;
|
||||
using Meteor.Map.packets.WorldPackets.Send;
|
||||
|
||||
namespace Meteor.Map.dataobjects
|
||||
namespace Meteor.Map.DataObjects
|
||||
{
|
||||
class ZoneConnection
|
||||
{
|
||||
|
|
|
@ -26,14 +26,15 @@ using Meteor.Common;
|
|||
using Meteor.Map.utils;
|
||||
|
||||
using Meteor.Map.packets.send.player;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.Actors.QuestNS;
|
||||
using Meteor.Map.actors.chara.player;
|
||||
using Meteor.Map.packets.receive.supportdesk;
|
||||
using Meteor.Map.actors.chara.npc;
|
||||
using Meteor.Map.actors.chara.ai;
|
||||
using Meteor.Map.packets.send.actor.battle;
|
||||
using Meteor.Map.DataObjects;
|
||||
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Meteor.Map
|
||||
|
@ -72,6 +73,55 @@ namespace Meteor.Map
|
|||
return id;
|
||||
}
|
||||
|
||||
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)))
|
||||
{
|
||||
Dictionary<uint, QuestGameData> gamedataQuests = new Dictionary<uint, QuestGameData>();
|
||||
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
string query = @"
|
||||
SELECT
|
||||
id,
|
||||
className,
|
||||
questName,
|
||||
prerequisite,
|
||||
minLevel
|
||||
FROM gamedata_quests
|
||||
";
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||
|
||||
using (MySqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
uint questId = reader.GetUInt32("id");
|
||||
string code = reader.GetString("className");
|
||||
string name = reader.GetString("questName");
|
||||
uint prerequisite = reader.GetUInt32("prerequisite");
|
||||
ushort minLevel = reader.GetUInt16("minLevel");
|
||||
//ushort minRank = reader.GetUInt16("minGCRank");
|
||||
gamedataQuests.Add(questId, new QuestGameData(questId, code, name, prerequisite, minLevel, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
|
||||
return gamedataQuests;
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<uint, ItemData> GetItemGamedata()
|
||||
{
|
||||
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)))
|
||||
|
@ -477,23 +527,13 @@ namespace Meteor.Map
|
|||
}
|
||||
}
|
||||
|
||||
public static void SaveQuest(Player player, Quest quest)
|
||||
{
|
||||
int slot = player.GetQuestSlot(quest.Id);
|
||||
if (slot == -1)
|
||||
{
|
||||
Program.Log.Error("Tried saving quest player didn't have: Player: {0:x}, QuestId: {0:x}", player.Id, quest.Id);
|
||||
return;
|
||||
}
|
||||
else
|
||||
SaveQuest(player, quest, slot);
|
||||
}
|
||||
|
||||
public static void SaveQuest(Player player, Quest quest, int slot)
|
||||
{
|
||||
string query;
|
||||
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)))
|
||||
{
|
||||
try
|
||||
|
@ -514,10 +554,59 @@ namespace Meteor.Map
|
|||
cmd.Parameters.AddWithValue("@slot", slot);
|
||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.Id);
|
||||
cmd.Parameters.AddWithValue("@sequence", quest.GetSequence());
|
||||
cmd.Parameters.AddWithValue("@flags", quest.GetFlags());
|
||||
cmd.Parameters.AddWithValue("@counter1", quest.GetCounter(1));
|
||||
cmd.Parameters.AddWithValue("@counter2", quest.GetCounter(2));
|
||||
cmd.Parameters.AddWithValue("@counter3", quest.GetCounter(3));
|
||||
|
||||
if (qData != null)
|
||||
{
|
||||
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();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateQuest(Player player, Quest quest)
|
||||
{
|
||||
string query;
|
||||
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)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
UPDATE characters_quest_scenario
|
||||
SET sequence = @sequence, flags = @flags, counter1 = @counter1, counter2 = @counter2, counter3 = @counter3
|
||||
WHERE characterId = @charaId and questId = @questId
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.Id);
|
||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.Id);
|
||||
cmd.Parameters.AddWithValue("@sequence", quest.GetSequence());
|
||||
|
||||
if (qData != null)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
@ -674,7 +763,7 @@ namespace Meteor.Map
|
|||
}
|
||||
}
|
||||
|
||||
public static void CompleteQuest(Player player, uint questId)
|
||||
public static void SaveCompletedQuests(Player player)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
@ -687,15 +776,15 @@ namespace Meteor.Map
|
|||
|
||||
query = @"
|
||||
INSERT INTO characters_quest_completed
|
||||
(characterId, questId)
|
||||
(characterId, completedQuests)
|
||||
VALUES
|
||||
(@charaId, @questId)
|
||||
ON DUPLICATE KEY UPDATE characterId=characterId
|
||||
(@charaId, @completedQuests)
|
||||
ON DUPLICATE KEY UPDATE completedQuests=completedQuests
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.Id);
|
||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & questId);
|
||||
cmd.Parameters.AddWithValue("@completedQuests", Utils.ConvertBoolArrayToBinaryStream(player.playerWork.questScenarioComplete));
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
@ -710,31 +799,6 @@ namespace Meteor.Map
|
|||
}
|
||||
}
|
||||
|
||||
public static bool IsQuestCompleted(Player player, uint questId)
|
||||
{
|
||||
bool isCompleted = false;
|
||||
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
|
||||
{
|
||||
conn.Open();
|
||||
MySqlCommand cmd = new MySqlCommand("SELECT * FROM characters_quest_completed WHERE characterId = @charaId and questId = @questId", conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.Id);
|
||||
cmd.Parameters.AddWithValue("@questId", questId);
|
||||
isCompleted = cmd.ExecuteScalar() != null;
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
return isCompleted;
|
||||
}
|
||||
|
||||
public static void LoadPlayerCharacter(Player player)
|
||||
{
|
||||
string query;
|
||||
|
@ -1168,11 +1232,32 @@ namespace Meteor.Map
|
|||
ushort counter1 = reader.GetUInt16("counter1");
|
||||
ushort counter2 = reader.GetUInt16("counter2");
|
||||
ushort counter3 = reader.GetUInt16("counter3");
|
||||
//ushort counter4 = reader.GetUInt16("counter4");
|
||||
|
||||
Quest baseQuest = (Quest) Server.GetStaticActors(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);
|
||||
}
|
||||
}
|
||||
|
||||
//Load Completed Quests bitstream
|
||||
query = @"
|
||||
SELECT
|
||||
completedQuests
|
||||
FROM characters_quest_completed WHERE characterId = @charaId";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.Id);
|
||||
using (MySqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
// Replace the bool stream or use the default empty one.
|
||||
if (reader.Read())
|
||||
{
|
||||
byte[] bytes = new byte[256];
|
||||
reader.GetBytes(reader.GetOrdinal("completedQuests"), 0, bytes, 0, 256);
|
||||
player.playerWork.questScenarioComplete = Utils.ConvertBinaryStreamToBoolArray(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,11 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
|
||||
using Meteor.Map.actors.director;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.receive.events;
|
||||
using Meteor.Map.packets.send;
|
||||
using Meteor.Map.packets.send.events;
|
||||
using MoonSharp.Interpreter;
|
||||
using MoonSharp.Interpreter.Interop;
|
||||
using MoonSharp.Interpreter.Loaders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -37,11 +36,11 @@ using Meteor.Map.actors.area;
|
|||
using System.Threading;
|
||||
using Meteor.Map.actors.chara.ai;
|
||||
using Meteor.Map.actors.chara.ai.controllers;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.actors.chara.player;
|
||||
using Meteor.Map.Actors.Chara;
|
||||
using Meteor.Map.dataobjects.chara;
|
||||
using Meteor.Map.DataObjects.chara;
|
||||
using Meteor.Map.actors.chara;
|
||||
using Meteor.Map.Actors.QuestNS;
|
||||
|
||||
namespace Meteor.Map.lua
|
||||
{
|
||||
|
@ -78,6 +77,7 @@ namespace Meteor.Map.lua
|
|||
UserData.RegisterType<Command>();
|
||||
UserData.RegisterType<Npc>();
|
||||
UserData.RegisterType<Quest>();
|
||||
UserData.RegisterType<QuestData>();
|
||||
UserData.RegisterType<Zone>();
|
||||
UserData.RegisterType<InventoryItem>();
|
||||
UserData.RegisterType<ItemPackage>();
|
||||
|
|
|
@ -180,9 +180,13 @@
|
|||
<Compile Include="Actors\Group\Work\RelationWork.cs" />
|
||||
<Compile Include="Actors\Judge\Judge.cs" />
|
||||
<Compile Include="Actors\Quest\Quest.cs" />
|
||||
<Compile Include="Actors\Quest\QuestData.cs" />
|
||||
<Compile Include="Actors\Quest\QuestState.cs" />
|
||||
<Compile Include="Actors\Quest\QuestStateManager.cs" />
|
||||
<Compile Include="Actors\StaticActors.cs" />
|
||||
<Compile Include="Actors\World\WorldMaster.cs" />
|
||||
<Compile Include="DataObjects\GuildleveData.cs" />
|
||||
<Compile Include="DataObjects\QuestGameData.cs" />
|
||||
<Compile Include="DataObjects\Recipe.cs" />
|
||||
<Compile Include="DataObjects\RecipeResolver.cs" />
|
||||
<Compile Include="DataObjects\TradeTransaction.cs" />
|
||||
|
@ -223,7 +227,7 @@
|
|||
<Compile Include="Packets\Receive\CountdownRequestPacket.cs" />
|
||||
<Compile Include="Packets\Receive\LangaugeCodePacket.cs" />
|
||||
<Compile Include="Packets\Receive\UpdateItemPackagePacket.cs" />
|
||||
<Compile Include="Packets\Receive\ParameterDataRequestPacket.cs" />
|
||||
<Compile Include="Packets\Receive\WorkSyncRequestPacket.cs" />
|
||||
<Compile Include="Packets\Receive\Recruitment\RecruitmentDetailsRequestPacket.cs" />
|
||||
<Compile Include="Packets\Receive\Recruitment\RecruitmentSearchRequestPacket.cs" />
|
||||
<Compile Include="Packets\Receive\Recruitment\StartRecruitingRequestPacket.cs" />
|
||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
using Meteor.Common;
|
||||
|
||||
using System;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.packets.receive;
|
||||
using Meteor.Map.packets.send;
|
||||
using Meteor.Map.packets.send.login;
|
||||
|
@ -39,6 +39,7 @@ using Meteor.Map.Actors;
|
|||
using Meteor.Map.packets.WorldPackets.Send;
|
||||
using Meteor.Map.packets.WorldPackets.Receive;
|
||||
using Meteor.Map.actors.director;
|
||||
using System.Text;
|
||||
|
||||
namespace Meteor.Map
|
||||
{
|
||||
|
@ -260,9 +261,8 @@ namespace Meteor.Map
|
|||
break;
|
||||
case 0x012F:
|
||||
subpacket.DebugPrintSubPacket();
|
||||
ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
|
||||
if (paramRequest.paramName.Equals("charaWork/exp"))
|
||||
session.GetActor().SendCharaExpInfo();
|
||||
WorkSyncRequestPacket workSyncRequest = new WorkSyncRequestPacket(subpacket.data);
|
||||
session.GetActor().OnWorkSyncRequest(workSyncRequest.propertyName, workSyncRequest.from, workSyncRequest.to);
|
||||
break;
|
||||
//Item Package Request
|
||||
case 0x0131:
|
||||
|
|
|
@ -26,7 +26,7 @@ using System.Text;
|
|||
|
||||
namespace Meteor.Map.packets.receive
|
||||
{
|
||||
class ParameterDataRequestPacket
|
||||
class WorkSyncRequestPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x012F;
|
||||
public const uint PACKET_SIZE = 0x48;
|
||||
|
@ -34,9 +34,11 @@ namespace Meteor.Map.packets.receive
|
|||
public bool invalidPacket = false;
|
||||
|
||||
public uint actorID;
|
||||
public string paramName;
|
||||
public string propertyName;
|
||||
public ushort from, to;
|
||||
public bool requestingBitfield = false;
|
||||
|
||||
public ParameterDataRequestPacket(byte[] data)
|
||||
public WorkSyncRequestPacket(byte[] data)
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
|
@ -44,13 +46,22 @@ namespace Meteor.Map.packets.receive
|
|||
{
|
||||
try{
|
||||
actorID = binReader.ReadUInt32();
|
||||
List<byte> strList = new List<byte>();
|
||||
byte curByte;
|
||||
while ((curByte = binReader.ReadByte()) != 0 && strList.Count<=0x20)
|
||||
if (binReader.PeekChar() == 9)
|
||||
{
|
||||
strList.Add(curByte);
|
||||
binReader.ReadByte();
|
||||
from = binReader.ReadUInt16();
|
||||
to = binReader.ReadUInt16();
|
||||
}
|
||||
paramName = Encoding.ASCII.GetString(strList.ToArray());
|
||||
|
||||
byte currentByte;
|
||||
int size = 0;
|
||||
long strPos = binReader.BaseStream.Position;
|
||||
while ((currentByte = binReader.ReadByte()) != 0 && size <= 0x20)
|
||||
size++;
|
||||
|
||||
binReader.BaseStream.Seek(strPos, SeekOrigin.Begin);
|
||||
byte[] str = binReader.ReadBytes(size);
|
||||
propertyName = Encoding.ASCII.GetString(str);
|
||||
}
|
||||
catch (Exception){
|
||||
invalidPacket = true;
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.IO;
|
||||
|
||||
using Meteor.Common;
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ using System;
|
|||
using System.IO;
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
|
||||
namespace Meteor.Map.packets.send.actor.inventory
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -44,6 +44,10 @@ namespace Meteor.Map.packets.send.actor
|
|||
|
||||
string currentTarget;
|
||||
|
||||
bool isBitfield = false;
|
||||
ushort from;
|
||||
ushort to;
|
||||
|
||||
private MemoryStream mem;
|
||||
private BinaryWriter binWriter;
|
||||
|
||||
|
@ -54,6 +58,16 @@ namespace Meteor.Map.packets.send.actor
|
|||
binWriter.Seek(1, SeekOrigin.Begin);
|
||||
currentTarget = startingTarget;
|
||||
}
|
||||
public SetActorPropetyPacket(ushort from, ushort to, string startingTarget)
|
||||
{
|
||||
mem = new MemoryStream(data);
|
||||
binWriter = new BinaryWriter(mem);
|
||||
binWriter.Seek(1, SeekOrigin.Begin);
|
||||
currentTarget = startingTarget;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
isBitfield = true;
|
||||
}
|
||||
|
||||
public void CloseStreams()
|
||||
{
|
||||
|
@ -100,6 +114,19 @@ namespace Meteor.Map.packets.send.actor
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool AddBitfield(uint id, byte[] data)
|
||||
{
|
||||
if (runningByteTotal + 5 + data.Length + 1 + (1 + 5 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES)
|
||||
return false;
|
||||
|
||||
binWriter.Write((byte) (data.Length));
|
||||
binWriter.Write((UInt32)id);
|
||||
binWriter.Write(data);
|
||||
runningByteTotal += (ushort)(5 + data.Length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool AddBuffer(uint id, byte[] buffer)
|
||||
{
|
||||
if (runningByteTotal + 5 + buffer.Length + (1 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES)
|
||||
|
@ -208,10 +235,22 @@ namespace Meteor.Map.packets.send.actor
|
|||
public void SetTarget(string target)
|
||||
{
|
||||
currentTarget = target;
|
||||
isBitfield = false;
|
||||
}
|
||||
|
||||
public void AddTarget()
|
||||
{
|
||||
if (isBitfield)
|
||||
{
|
||||
binWriter.Write((byte)(isMore ? 0x60 + currentTarget.Length + 5 : 0x82 + currentTarget.Length + 5));
|
||||
binWriter.Write((byte)9);
|
||||
binWriter.Write(from);
|
||||
binWriter.Write(to);
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(currentTarget));
|
||||
runningByteTotal += (ushort)(6 + Encoding.ASCII.GetByteCount(currentTarget));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isArrayMode)
|
||||
binWriter.Write((byte)(0xA4 + currentTarget.Length));
|
||||
else
|
||||
|
@ -236,6 +275,7 @@ namespace Meteor.Map.packets.send.actor
|
|||
CloseStreams();
|
||||
|
||||
SubPacket packet = new SubPacket(OPCODE, sourceActorId, data);
|
||||
packet.DebugPrintSubPacket();
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,9 +79,7 @@ namespace Meteor.Map.packets.send.player
|
|||
public const ushort OPCODE = 0x01A3;
|
||||
public const uint PACKET_SIZE = 0x150;
|
||||
|
||||
public bool[] cutsceneFlags = new bool[2048];
|
||||
|
||||
public SubPacket BuildPacket(uint sourceActorId, string sNpcName, short sNpcActorIdOffset, byte sNpcSkin, byte sNpcPersonality)
|
||||
public SubPacket BuildPacket(uint sourceActorId, string sNpcName, short sNpcActorIdOffset, byte sNpcSkin, byte sNpcPersonality, bool[] completedQuests)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
|
||||
|
@ -89,7 +87,7 @@ namespace Meteor.Map.packets.send.player
|
|||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
byte[] binStream = Utils.ConvertBoolArrayToBinaryStream(cutsceneFlags);
|
||||
byte[] binStream = Utils.ConvertBoolArrayToBinaryStream(completedQuests);
|
||||
|
||||
//Temp Path Companion SNPC Stuff
|
||||
binWriter.Seek(0x01 ,SeekOrigin.Begin);
|
||||
|
|
|
@ -19,7 +19,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
|
||||
namespace Meteor.Map.packets.WorldPackets.Send.Group
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
|||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Meteor.Common;
|
||||
using MySql.Data.MySqlClient;
|
||||
using NLog;
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
|
||||
using Meteor.Common;
|
||||
using Meteor.Map.Actors;
|
||||
using System.Linq;
|
||||
|
||||
namespace Meteor.Map
|
||||
{
|
||||
|
@ -38,52 +39,56 @@ namespace Meteor.Map
|
|||
|
||||
public const string STATIC_ACTORS_PATH = "./staticactors.bin";
|
||||
|
||||
private static Server mSelf;
|
||||
private static Server _Self;
|
||||
|
||||
private Socket mServerSocket;
|
||||
private Socket ServerSocket;
|
||||
|
||||
private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();
|
||||
private Dictionary<uint, Session> SessionList = new Dictionary<uint, Session>();
|
||||
|
||||
private static CommandProcessor mCommandProcessor = new CommandProcessor();
|
||||
private static ZoneConnection mWorldConnection = new ZoneConnection();
|
||||
private static WorldManager mWorldManager;
|
||||
private static Dictionary<uint, ItemData> mGamedataItems;
|
||||
private static Dictionary<uint, GuildleveData> mGamedataGuildleves;
|
||||
private static StaticActors mStaticActors;
|
||||
private static CommandProcessor CommandProcessor = new CommandProcessor();
|
||||
private static ZoneConnection WorldConnection = new ZoneConnection();
|
||||
private static WorldManager WorldManager;
|
||||
private static Dictionary<uint, ItemData> GamedataItems;
|
||||
private static Dictionary<uint, GuildleveData> GamedataGuildleves;
|
||||
private static Dictionary<uint, QuestGameData> GamedataQuests;
|
||||
private static StaticActors StaticActors;
|
||||
|
||||
private PacketProcessor mProcessor;
|
||||
|
||||
public Server()
|
||||
{
|
||||
mSelf = this;
|
||||
_Self = this;
|
||||
}
|
||||
|
||||
public bool StartServer()
|
||||
{
|
||||
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
|
||||
StaticActors = new StaticActors(STATIC_ACTORS_PATH);
|
||||
|
||||
mGamedataItems = Database.GetItemGamedata();
|
||||
Program.Log.Info("Loaded {0} items.", mGamedataItems.Count);
|
||||
mGamedataGuildleves = Database.GetGuildleveGamedata();
|
||||
Program.Log.Info("Loaded {0} guildleves.", mGamedataGuildleves.Count);
|
||||
Program.Log.Info("Loading gamedata...");
|
||||
GamedataItems = Database.GetItemGamedata();
|
||||
Program.Log.Info("Loaded {0} items.", GamedataItems.Count);
|
||||
GamedataGuildleves = Database.GetGuildleveGamedata();
|
||||
Program.Log.Info("Loaded {0} guildleves.", GamedataGuildleves.Count);
|
||||
GamedataQuests = Database.GetQuestGamedata();
|
||||
Program.Log.Info("Loaded {0} quests.", GamedataQuests.Count);
|
||||
|
||||
mWorldManager = new WorldManager(this);
|
||||
mWorldManager.LoadZoneList();
|
||||
mWorldManager.LoadSeamlessBoundryList();
|
||||
mWorldManager.LoadActorClasses();
|
||||
mWorldManager.LoadENPCs();
|
||||
mWorldManager.LoadBattleNpcs();
|
||||
mWorldManager.LoadStatusEffects();
|
||||
mWorldManager.LoadBattleCommands();
|
||||
mWorldManager.LoadBattleTraits();
|
||||
mWorldManager.SpawnAllActors();
|
||||
mWorldManager.StartZoneThread();
|
||||
WorldManager = new WorldManager(this);
|
||||
WorldManager.LoadZoneList();
|
||||
WorldManager.LoadSeamlessBoundryList();
|
||||
WorldManager.LoadActorClasses();
|
||||
WorldManager.LoadENPCs();
|
||||
WorldManager.LoadBattleNpcs();
|
||||
WorldManager.LoadStatusEffects();
|
||||
WorldManager.LoadBattleCommands();
|
||||
WorldManager.LoadBattleTraits();
|
||||
WorldManager.SpawnAllActors();
|
||||
WorldManager.StartZoneThread();
|
||||
|
||||
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT));
|
||||
|
||||
try
|
||||
{
|
||||
mServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
ServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -91,8 +96,8 @@ namespace Meteor.Map
|
|||
}
|
||||
try
|
||||
{
|
||||
mServerSocket.Bind(serverEndPoint);
|
||||
mServerSocket.Listen(BACKLOG);
|
||||
ServerSocket.Bind(serverEndPoint);
|
||||
ServerSocket.Listen(BACKLOG);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -100,7 +105,7 @@ namespace Meteor.Map
|
|||
}
|
||||
try
|
||||
{
|
||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -108,7 +113,7 @@ namespace Meteor.Map
|
|||
}
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
|
||||
Program.Log.Info("Map Server has started @ {0}:{1}", (ServerSocket.LocalEndPoint as IPEndPoint).Address, (ServerSocket.LocalEndPoint as IPEndPoint).Port);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
|
||||
mProcessor = new PacketProcessor(this);
|
||||
|
@ -122,36 +127,36 @@ namespace Meteor.Map
|
|||
|
||||
public Session AddSession(uint id)
|
||||
{
|
||||
if (mSessionList.ContainsKey(id))
|
||||
if (SessionList.ContainsKey(id))
|
||||
{
|
||||
mSessionList[id].ClearInstance();
|
||||
return mSessionList[id];
|
||||
SessionList[id].ClearInstance();
|
||||
return SessionList[id];
|
||||
}
|
||||
|
||||
Session session = new Session(id);
|
||||
mSessionList.Add(id, session);
|
||||
SessionList.Add(id, session);
|
||||
return session;
|
||||
}
|
||||
|
||||
public void RemoveSession(uint id)
|
||||
{
|
||||
if (mSessionList.ContainsKey(id))
|
||||
if (SessionList.ContainsKey(id))
|
||||
{
|
||||
mSessionList.Remove(id);
|
||||
SessionList.Remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
public Session GetSession(uint id)
|
||||
{
|
||||
if (mSessionList.ContainsKey(id))
|
||||
return mSessionList[id];
|
||||
if (SessionList.ContainsKey(id))
|
||||
return SessionList[id];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Session GetSession(string name)
|
||||
{
|
||||
foreach (Session s in mSessionList.Values)
|
||||
foreach (Session s in SessionList.Values)
|
||||
{
|
||||
if (s.GetActor().DisplayName.ToLower().Equals(name.ToLower()))
|
||||
return s;
|
||||
|
@ -161,7 +166,7 @@ namespace Meteor.Map
|
|||
|
||||
public Dictionary<uint, Session> GetSessionList()
|
||||
{
|
||||
return mSessionList;
|
||||
return SessionList;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -179,29 +184,29 @@ namespace Meteor.Map
|
|||
conn.socket = socket.EndAccept(result);
|
||||
conn.buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
mWorldConnection = conn;
|
||||
WorldConnection = conn;
|
||||
|
||||
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port);
|
||||
//Queue recieving of data from the connection
|
||||
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
|
||||
//Queue the accept of the next incomming connection
|
||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
if (conn != null)
|
||||
{
|
||||
mWorldConnection = null;
|
||||
WorldConnection = null;
|
||||
}
|
||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (conn != null)
|
||||
{
|
||||
mWorldConnection = null;
|
||||
WorldConnection = null;
|
||||
}
|
||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +221,7 @@ namespace Meteor.Map
|
|||
//Check if disconnected
|
||||
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
|
||||
{
|
||||
mWorldConnection = null;
|
||||
WorldConnection = null;
|
||||
Program.Log.Info("Disconnected from world server!");
|
||||
}
|
||||
|
||||
|
@ -260,7 +265,7 @@ namespace Meteor.Map
|
|||
}
|
||||
else
|
||||
{
|
||||
mWorldConnection = null;
|
||||
WorldConnection = null;
|
||||
Program.Log.Info("Disconnected from world server!");
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +273,7 @@ namespace Meteor.Map
|
|||
{
|
||||
if (conn.socket != null)
|
||||
{
|
||||
mWorldConnection = null;
|
||||
WorldConnection = null;
|
||||
Program.Log.Info("Disconnected from world server!");
|
||||
}
|
||||
}
|
||||
|
@ -278,54 +283,90 @@ namespace Meteor.Map
|
|||
|
||||
public static ZoneConnection GetWorldConnection()
|
||||
{
|
||||
return mWorldConnection;
|
||||
return WorldConnection;
|
||||
}
|
||||
|
||||
public static Server GetServer()
|
||||
{
|
||||
return mSelf;
|
||||
return _Self;
|
||||
}
|
||||
|
||||
public static CommandProcessor GetCommandProcessor()
|
||||
{
|
||||
return mCommandProcessor;
|
||||
return CommandProcessor;
|
||||
}
|
||||
|
||||
public static WorldManager GetWorldManager()
|
||||
{
|
||||
return mWorldManager;
|
||||
return WorldManager;
|
||||
}
|
||||
|
||||
public static Dictionary<uint, ItemData> GetGamedataItems()
|
||||
{
|
||||
return mGamedataItems;
|
||||
return GamedataItems;
|
||||
}
|
||||
|
||||
public static Actor GetStaticActors(uint id)
|
||||
{
|
||||
return mStaticActors.GetActor(id);
|
||||
return StaticActors.GetActor(id);
|
||||
}
|
||||
|
||||
public static Actor GetStaticActors(string name)
|
||||
{
|
||||
return mStaticActors.FindStaticActor(name);
|
||||
return StaticActors.FindStaticActor(name);
|
||||
}
|
||||
|
||||
public static ItemData GetItemGamedata(uint id)
|
||||
{
|
||||
if (mGamedataItems.ContainsKey(id))
|
||||
return mGamedataItems[id];
|
||||
if (GamedataItems.ContainsKey(id))
|
||||
return GamedataItems[id];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GuildleveData GetGuildleveGamedata(uint id)
|
||||
{
|
||||
if (mGamedataGuildleves.ContainsKey(id))
|
||||
return mGamedataGuildleves[id];
|
||||
if (GamedataGuildleves.ContainsKey(id))
|
||||
return GamedataGuildleves[id];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static QuestGameData GetQuestGamedata(uint id)
|
||||
{
|
||||
if (GamedataQuests.ContainsKey(id))
|
||||
return GamedataQuests[id];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static QuestGameData[] GetQuestGamedataByMaxLvl(int lvl, bool all = false)
|
||||
{
|
||||
if (all)
|
||||
return GamedataQuests.Values.Where(quest => quest.MinLevel > 0 && quest.MinLevel <= lvl).ToArray();
|
||||
else
|
||||
return GamedataQuests.Values.Where(quest => quest.MinLevel > 0 && quest.MinLevel == lvl).ToArray();
|
||||
}
|
||||
|
||||
public static QuestGameData[] GetQuestGamedataByPrerequisite(uint questId)
|
||||
{
|
||||
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest == questId).ToArray();
|
||||
}
|
||||
|
||||
public static QuestGameData[] GetQuestGamedataAllPrerequisite()
|
||||
{
|
||||
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest != 0).ToArray();
|
||||
}
|
||||
|
||||
public static QuestGameData[] GetQuestGamedataAllGCRanked()
|
||||
{
|
||||
return GamedataQuests.Values.Where(quest => quest.MinGCRank != 0).ToArray();
|
||||
}
|
||||
|
||||
//public static QuestData[] GetQuestGamedataByGCRank(int gc, int rank, bool all = false)
|
||||
//{
|
||||
// return GamedataQuests.Values.Where(quest => all ? quest.MinLevel == lvl : quest.MinLevel <= lvl).ToArray();
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ using Meteor.Common;
|
|||
using Meteor.Map.actors.area;
|
||||
using Meteor.Map.actors.chara.npc;
|
||||
using Meteor.Map.Actors;
|
||||
using Meteor.Map.dataobjects;
|
||||
using Meteor.Map.DataObjects;
|
||||
using Meteor.Map.lua;
|
||||
using Meteor.Map.packets.send;
|
||||
using Meteor.Map.packets.send.actor;
|
||||
|
|
Loading…
Add table
Reference in a new issue