mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-22 04:37:47 +00:00
Finished quest state system idea
This commit is contained in:
parent
aae051d73f
commit
1523ae200b
21 changed files with 720 additions and 373 deletions
150
Common Class Lib/Bitstream.cs
Normal file
150
Common Class Lib/Bitstream.cs
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
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 readonly 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,6 +87,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BasePacket.cs" />
|
<Compile Include="BasePacket.cs" />
|
||||||
<Compile Include="Bitfield.cs" />
|
<Compile Include="Bitfield.cs" />
|
||||||
|
<Compile Include="Bitstream.cs" />
|
||||||
<Compile Include="Blowfish.cs" />
|
<Compile Include="Blowfish.cs" />
|
||||||
<Compile Include="EfficientHashTables.cs" />
|
<Compile Include="EfficientHashTables.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|
|
@ -24,6 +24,7 @@ end
|
||||||
function onEventStarted(player, npc, eventType, eventName)
|
function onEventStarted(player, npc, eventType, eventName)
|
||||||
local defaultTalk = player:GetDefaultTalkQuest(npc);
|
local defaultTalk = player:GetDefaultTalkQuest(npc);
|
||||||
local tutorialTalk = player:GetTutorialQuest(npc);
|
local tutorialTalk = player:GetTutorialQuest(npc);
|
||||||
|
local journalQuests = player:GetJournalQuestsForNpc(npc);
|
||||||
local activeQuests = player:GetQuestsForNpc(npc);
|
local activeQuests = player:GetQuestsForNpc(npc);
|
||||||
local possibleQuests = {};
|
local possibleQuests = {};
|
||||||
|
|
||||||
|
@ -34,6 +35,9 @@ function onEventStarted(player, npc, eventType, eventName)
|
||||||
if (tutorialTalk ~= nil and eventType == ETYPE_TALK) then
|
if (tutorialTalk ~= nil and eventType == ETYPE_TALK) then
|
||||||
table.insert(possibleQuests, tutorialTalk);
|
table.insert(possibleQuests, tutorialTalk);
|
||||||
end
|
end
|
||||||
|
if (journalQuests ~= nil) then
|
||||||
|
table.insert(possibleQuests, unpack(journalQuests));
|
||||||
|
end
|
||||||
if (activeQuests ~= nil) then
|
if (activeQuests ~= nil) then
|
||||||
table.insert(possibleQuests, unpack(activeQuests));
|
table.insert(possibleQuests, unpack(activeQuests));
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,8 +41,6 @@ FLAG_TALKED_LEFWYNE = 4;
|
||||||
-- Quest Counters
|
-- Quest Counters
|
||||||
COUNTER_TALKED = 0;
|
COUNTER_TALKED = 0;
|
||||||
|
|
||||||
--offerQuestResult = callClientFunction(player, "delegateEvent", player, quest, "processEventOffersStart");
|
|
||||||
|
|
||||||
function onStart(player, quest)
|
function onStart(player, quest)
|
||||||
quest:StartSequence(SEQ_000);
|
quest:StartSequence(SEQ_000);
|
||||||
end
|
end
|
||||||
|
@ -50,25 +48,39 @@ end
|
||||||
function onFinish(player, quest)
|
function onFinish(player, quest)
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSequence(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
|
if (sequence == 65536) then
|
||||||
|
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
||||||
|
end
|
||||||
|
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
quest:AddENpc(KINNISON);
|
quest:SetENpc(KINNISON);
|
||||||
quest:AddENpc(SYBELL, (not quest:GetFlag(FLAG_TALKED_SYBELL) and QFLAG_PLATE or QFLAG_NONE));
|
quest:SetENpc(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:SetENpc(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:SetENpc(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:SetENpc(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(LEFWYNE, (not quest:GetFlag(FLAG_TALKED_LEFWYNE) and QFLAG_PLATE or QFLAG_NONE));
|
||||||
elseif (sequence == SEQ_001) then
|
elseif (sequence == SEQ_001) then
|
||||||
quest:AddENpc(KINNISON, QFLAG_PLATE);
|
quest:SetENpc(KINNISON, QFLAG_PLATE);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function onTalk(player, quest, npc, eventName)
|
function onTalk(player, quest, npc, eventName)
|
||||||
local npcClassId = npc.GetActorClassId();
|
local npcClassId = npc.GetActorClassId();
|
||||||
local seq = quest:GetSequence();
|
local seq = quest:GetSequence();
|
||||||
local incCounter = false;
|
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) then
|
||||||
|
player:AddQuest(quest);
|
||||||
|
end
|
||||||
|
player:EndEvent();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Quest Progress
|
||||||
if (seq == SEQ_000) then
|
if (seq == SEQ_000) then
|
||||||
if (npcClassId == KINNISON) then
|
if (npcClassId == KINNISON) then
|
||||||
callClientFunction(player, "delegateEvent", player, quest, "processEventOffersAfter");
|
callClientFunction(player, "delegateEvent", player, quest, "processEventOffersAfter");
|
||||||
|
|
|
@ -40,13 +40,13 @@ end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function onSequence(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
quest:AddENpc(VKOROLON);
|
quest:SetENpc(VKOROLON);
|
||||||
quest:AddENpc(PFARAHR, QFLAG_PLATE);
|
quest:SetENpc(PFARAHR, QFLAG_PLATE);
|
||||||
elseif (sequence == SEQ_001) then
|
elseif (sequence == SEQ_001) then
|
||||||
quest:AddENpc(VKOROLON, QFLAG_PLATE);
|
quest:SetENpc(VKOROLON, QFLAG_PLATE);
|
||||||
quest:AddENpc(PFARAHR);
|
quest:SetENpc(PFARAHR);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ end
|
||||||
function onFinish(player, quest)
|
function onFinish(player, quest)
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSequence(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
-- Setup states incase we loaded in.
|
-- Setup states incase we loaded in.
|
||||||
local rostnsthalFlag = quest:GetFlag(FLAG_SEQ000_MINITUT1) and QFLAG_NONE or QFLAG_PLATE;
|
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 exitCanPush = quest:GetFlags() == 0xF;
|
||||||
local exitFlag = quest:GetFlags() == 0xF and QFLAG_MAP or QFLAG_NONE;
|
local exitFlag = quest:GetFlags() == 0xF and QFLAG_MAP or QFLAG_NONE;
|
||||||
|
|
||||||
quest:AddENpc(WELLTRAVELED_MERCHANT);
|
quest:SetENpc(WELLTRAVELED_MERCHANT);
|
||||||
quest:AddENpc(TIPSY_ADVENTURER);
|
quest:SetENpc(TIPSY_ADVENTURER);
|
||||||
quest:AddENpc(CULTIVATED_TENDER);
|
quest:SetENpc(CULTIVATED_TENDER);
|
||||||
quest:AddENpc(ANXIOUS_ADVENTURER);
|
quest:SetENpc(ANXIOUS_ADVENTURER);
|
||||||
quest:AddENpc(BABYFACED_ADVENTURER, babyfaceFlag);
|
quest:SetENpc(BABYFACED_ADVENTURER, babyfaceFlag);
|
||||||
quest:AddENpc(AUSTERE_ADVENTURER);
|
quest:SetENpc(AUSTERE_ADVENTURER);
|
||||||
quest:AddENpc(UNDIGNIFIED_ADVENTURER);
|
quest:SetENpc(UNDIGNIFIED_ADVENTURER);
|
||||||
quest:AddENpc(SHADOWY_TRAVELER);
|
quest:SetENpc(SHADOWY_TRAVELER);
|
||||||
quest:AddENpc(ASTUTE_MERCHANT);
|
quest:SetENpc(ASTUTE_MERCHANT);
|
||||||
quest:AddENpc(VOLUPTUOUS_VIXEN, vixenFlag);
|
quest:SetENpc(VOLUPTUOUS_VIXEN, vixenFlag);
|
||||||
quest:AddENpc(INDIFFERENT_PASSERBY);
|
quest:SetENpc(INDIFFERENT_PASSERBY);
|
||||||
quest:AddENpc(PRATTLING_ADVENTURER);
|
quest:SetENpc(PRATTLING_ADVENTURER);
|
||||||
quest:AddENpc(LANKY_TRAVELER);
|
quest:SetENpc(LANKY_TRAVELER);
|
||||||
quest:AddENpc(GRINNING_ADVENTURER);
|
quest:SetENpc(GRINNING_ADVENTURER);
|
||||||
quest:AddENpc(ROSTNSTHAL, rostnsthalFlag, true, rostnsthalCanPush);
|
quest:SetENpc(ROSTNSTHAL, rostnsthalFlag, true, rostnsthalCanPush);
|
||||||
quest:AddENpc(EXIT_TRIGGER, exitFlag, false, exitCanPush);
|
quest:SetENpc(EXIT_TRIGGER, exitFlag, false, exitCanPush);
|
||||||
elseif (sequence == SEQ_005) then
|
elseif (sequence == SEQ_005) then
|
||||||
elseif (sequence == SEQ_010) then
|
elseif (sequence == SEQ_010) then
|
||||||
quest:AddENpc(HOB);
|
quest:SetENpc(HOB);
|
||||||
quest:AddENpc(GERT);
|
quest:SetENpc(GERT);
|
||||||
quest:AddENpc(LORHZANT);
|
quest:SetENpc(LORHZANT);
|
||||||
quest:AddENpc(MUSCLEBOUND_DECKHAND);
|
quest:SetENpc(MUSCLEBOUND_DECKHAND);
|
||||||
quest:AddENpc(PEARLYTOOTHED_PORTER);
|
quest:SetENpc(PEARLYTOOTHED_PORTER);
|
||||||
quest:AddENpc(UNDIGNIFIED_ADVENTURER);
|
quest:SetENpc(UNDIGNIFIED_ADVENTURER);
|
||||||
quest:AddENpc(WELLTRAVELED_MERCHANT);
|
quest:SetENpc(WELLTRAVELED_MERCHANT);
|
||||||
quest:AddENpc(VOLUPTUOUS_VIXEN);
|
quest:SetENpc(VOLUPTUOUS_VIXEN);
|
||||||
quest:AddENpc(LANKY_TRAVELER);
|
quest:SetENpc(LANKY_TRAVELER);
|
||||||
quest:AddENpc(PRIVAREA_PAST_EXIT, QFLAG_NONE, false, true);
|
quest:SetENpc(PRIVAREA_PAST_EXIT, QFLAG_NONE, false, true);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -85,56 +85,56 @@ end
|
||||||
function onFinish(player, quest)
|
function onFinish(player, quest)
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSequence(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
|
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
quest:AddENpc(YSHTOLA);
|
quest:SetENpc(YSHTOLA);
|
||||||
quest:AddENpc(CRAPULOUS_ADVENTURER);
|
quest:SetENpc(CRAPULOUS_ADVENTURER);
|
||||||
quest:AddENpc(DUPLICITOUS_TRADER);
|
quest:SetENpc(DUPLICITOUS_TRADER);
|
||||||
quest:AddENpc(DEBONAIR_PIRATE);
|
quest:SetENpc(DEBONAIR_PIRATE);
|
||||||
quest:AddENpc(ONYXHAIRED_ADVENTURER);
|
quest:SetENpc(ONYXHAIRED_ADVENTURER);
|
||||||
quest:AddENpc(SKITTISH_ADVENTURER);
|
quest:SetENpc(SKITTISH_ADVENTURER);
|
||||||
quest:AddENpc(RELAXING_ADVENTURER);
|
quest:SetENpc(RELAXING_ADVENTURER);
|
||||||
quest:AddENpc(BADERON, QFLAG_PLATE);
|
quest:SetENpc(BADERON, QFLAG_PLATE);
|
||||||
quest:AddENpc(MYTESYN);
|
quest:SetENpc(MYTESYN);
|
||||||
quest:AddENpc(COCKAHOOP_COCKSWAIN);
|
quest:SetENpc(COCKAHOOP_COCKSWAIN);
|
||||||
quest:AddENpc(SENTENIOUS_SELLSWORD);
|
quest:SetENpc(SENTENIOUS_SELLSWORD);
|
||||||
quest:AddENpc(SOLICITOUS_SELLSWORD);
|
quest:SetENpc(SOLICITOUS_SELLSWORD);
|
||||||
elseif (sequence == SEQ_003) then
|
elseif (sequence == SEQ_003) then
|
||||||
quest:AddENpc(BADERON);
|
quest:SetENpc(BADERON);
|
||||||
elseif (sequence == SEQ_005) then
|
elseif (sequence == SEQ_005) then
|
||||||
quest:AddENpc(BADERON, QFLAG_PLATE);
|
quest:SetENpc(BADERON, QFLAG_PLATE);
|
||||||
elseif (sequence == SEQ_006) then
|
elseif (sequence == SEQ_006) then
|
||||||
quest:AddENpc(BADERON, QFLAG_PLATE);
|
quest:SetENpc(BADERON, QFLAG_PLATE);
|
||||||
elseif (sequence == SEQ_007) then
|
elseif (sequence == SEQ_007) then
|
||||||
local subseqCUL = quest:GetCounter(CNTR_SEQ7_CUL);
|
local subseqCUL = quest:GetCounter(CNTR_SEQ7_CUL);
|
||||||
local subseqMRD = quest:GetCounter(CNTR_SEQ7_MRD);
|
local subseqMRD = quest:GetCounter(CNTR_SEQ7_MRD);
|
||||||
|
|
||||||
-- Always active in this seqence
|
-- Always active in this seqence
|
||||||
quest:AddENpc(BADERON);
|
quest:SetENpc(BADERON);
|
||||||
quest:AddENpc(CHARLYS, subseqCUL == 0 and QFLAG_PLATE or QFLAG_NONE);
|
quest:SetENpc(CHARLYS, subseqCUL == 0 and QFLAG_PLATE or QFLAG_NONE);
|
||||||
|
|
||||||
-- Down and Up the MSK guild
|
-- 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
|
if (subseqMRD == 1) then
|
||||||
quest:AddENpc(MSK_TRIGGER, QFLAG_MAP, false, true);
|
quest:SetENpc(MSK_TRIGGER, QFLAG_MAP, false, true);
|
||||||
elseif (subseqMRD == 2) then
|
elseif (subseqMRD == 2) then
|
||||||
quest:AddENpc(MERLZIRN);
|
quest:SetENpc(MERLZIRN);
|
||||||
end
|
end
|
||||||
|
|
||||||
-- In Echo
|
-- In Echo
|
||||||
quest:AddENpc(NERVOUS_BARRACUDA);
|
quest:SetENpc(NERVOUS_BARRACUDA);
|
||||||
quest:AddENpc(INTIMIDATING_BARRACUDA);
|
quest:SetENpc(INTIMIDATING_BARRACUDA);
|
||||||
quest:AddENpc(OVEREAGER_BARRACUDA);
|
quest:SetENpc(OVEREAGER_BARRACUDA);
|
||||||
quest:AddENpc(SOPHISTICATED_BARRACUDA);
|
quest:SetENpc(SOPHISTICATED_BARRACUDA);
|
||||||
quest:AddENpc(SMIRKING_BARRACUDA);
|
quest:SetENpc(SMIRKING_BARRACUDA);
|
||||||
quest:AddENpc(MANNSKOEN);
|
quest:SetENpc(MANNSKOEN);
|
||||||
quest:AddENpc(TOTORUTO);
|
quest:SetENpc(TOTORUTO);
|
||||||
quest:AddENpc(ADVENTURER1);
|
quest:SetENpc(ADVENTURER1);
|
||||||
quest:AddENpc(ADVENTURER2);
|
quest:SetENpc(ADVENTURER2);
|
||||||
quest:AddENpc(ADVENTURER3);
|
quest:SetENpc(ADVENTURER3);
|
||||||
quest:AddENpc(ECHO_EXIT_TRIGGER, subseqMRD == 3 and QFLAG_MAP or QFLAG_NONE, false, subseqMRD == 3);
|
quest:SetENpc(ECHO_EXIT_TRIGGER, subseqMRD == 3 and QFLAG_MAP or QFLAG_NONE, false, subseqMRD == 3);
|
||||||
|
|
||||||
if (subseqCUL == 1 and subseqMRD == 4) then
|
if (subseqCUL == 1 and subseqMRD == 4) then
|
||||||
player:SetNpcLS(1, 1);
|
player:SetNpcLS(1, 1);
|
||||||
|
|
|
@ -103,7 +103,7 @@ end
|
||||||
function onFinish(player, quest)
|
function onFinish(player, quest)
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSequence(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
|
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
-- Setup states incase we loaded in.
|
-- Setup states incase we loaded in.
|
||||||
|
@ -119,34 +119,34 @@ function onSequence(player, quest, sequence)
|
||||||
gildiggingmistressFlag = QFLAG_NONE;
|
gildiggingmistressFlag = QFLAG_NONE;
|
||||||
end
|
end
|
||||||
|
|
||||||
--AddENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
--SetENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
||||||
quest:AddENpc(ASCILIA, asciliaFlag, true, asciliaCanPush);
|
quest:SetENpc(ASCILIA, asciliaFlag, true, asciliaCanPush);
|
||||||
quest:AddENpc(WARBURTON);
|
quest:SetENpc(WARBURTON);
|
||||||
quest:AddENpc(RURURAJI);
|
quest:SetENpc(RURURAJI);
|
||||||
quest:AddENpc(BIG_BELLIED_BARKER);
|
quest:SetENpc(BIG_BELLIED_BARKER);
|
||||||
quest:AddENpc(FRETFUL_FARMHAND, fretfulfarmhandFlag);
|
quest:SetENpc(FRETFUL_FARMHAND, fretfulfarmhandFlag);
|
||||||
quest:AddENpc(DEBAUCHED_DEMONESS);
|
quest:SetENpc(DEBAUCHED_DEMONESS);
|
||||||
quest:AddENpc(DAPPER_DAN);
|
quest:SetENpc(DAPPER_DAN);
|
||||||
quest:AddENpc(LOUTISH_LAD);
|
quest:SetENpc(LOUTISH_LAD);
|
||||||
quest:AddENpc(GIL_DIGGING_MISTRESS, gildiggingmistressFlag);
|
quest:SetENpc(GIL_DIGGING_MISTRESS, gildiggingmistressFlag);
|
||||||
quest:AddENpc(TWITTERING_TOMBOY);
|
quest:SetENpc(TWITTERING_TOMBOY);
|
||||||
quest:AddENpc(STOCKY_STRANGER);
|
quest:SetENpc(STOCKY_STRANGER);
|
||||||
quest:AddENpc(EXIT_TRIGGER, exitFlag, false, true);
|
quest:SetENpc(EXIT_TRIGGER, exitFlag, false, true);
|
||||||
quest:AddENpc(OPENING_STOPER_ULDAH, QFLAG_NONE, false, false, true);
|
quest:SetENpc(OPENING_STOPER_ULDAH, QFLAG_NONE, false, false, true);
|
||||||
|
|
||||||
elseif (sequence == SEQ_010) then
|
elseif (sequence == SEQ_010) then
|
||||||
local yayatokiFlag = quest:GetFlag(FLAG_SEQ010_TALK0) and QFLAG_NONE or QFLAG_PLATE;
|
local yayatokiFlag = quest:GetFlag(FLAG_SEQ010_TALK0) and QFLAG_NONE or QFLAG_PLATE;
|
||||||
local uldahopeningexitFlag = QFLAG_MAP;
|
local uldahopeningexitFlag = QFLAG_MAP;
|
||||||
quest:AddENpc(KEEN_EYED_MERCHANT);
|
quest:SetENpc(KEEN_EYED_MERCHANT);
|
||||||
quest:AddENpc(HIGH_SPIRITED_FELLOW);
|
quest:SetENpc(HIGH_SPIRITED_FELLOW);
|
||||||
quest:AddENpc(DISREPUTABLE_MIDLANDER);
|
quest:SetENpc(DISREPUTABLE_MIDLANDER);
|
||||||
quest:AddENpc(LONG_LEGGED_LADY);
|
quest:SetENpc(LONG_LEGGED_LADY);
|
||||||
quest:AddENpc(LARGE_LUNGED_LABORER);
|
quest:SetENpc(LARGE_LUNGED_LABORER);
|
||||||
quest:AddENpc(TOOTH_GRINDING_TRAVELER);
|
quest:SetENpc(TOOTH_GRINDING_TRAVELER);
|
||||||
quest:AddENpc(FULL_LIPPED_FILLE);
|
quest:SetENpc(FULL_LIPPED_FILLE);
|
||||||
quest:AddENpc(YAYATOKI, yayatokiFlag);
|
quest:SetENpc(YAYATOKI, yayatokiFlag);
|
||||||
quest:AddENpc(BLOCKER, QFLAG_NONE, false, true);
|
quest:SetENpc(BLOCKER, QFLAG_NONE, false, true);
|
||||||
quest:AddENpc(ULDAH_OPENING_EXIT, uldahopeningexitFlag, false, true);
|
quest:SetENpc(ULDAH_OPENING_EXIT, uldahopeningexitFlag, false, true);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -127,17 +127,17 @@ end
|
||||||
function onFinish(player, quest)
|
function onFinish(player, quest)
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSequence(player, quest, sequence)
|
function onStateChange(player, quest, sequence)
|
||||||
|
|
||||||
if (sequence == SEQ_000) then
|
if (sequence == SEQ_000) then
|
||||||
-- Setup states incase we loaded in.
|
-- Setup states incase we loaded in.
|
||||||
|
|
||||||
--AddENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
--SetENpc(classId, byte flagType=0,isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned)
|
||||||
quest:AddENpc(MOMODI, QFLAG_PLATE);
|
quest:SetENpc(MOMODI, QFLAG_PLATE);
|
||||||
quest:AddENpc(OTOPA_POTTOPA);
|
quest:SetENpc(OTOPA_POTTOPA);
|
||||||
|
|
||||||
elseif (sequence == SEQ_005) then
|
elseif (sequence == SEQ_005) then
|
||||||
quest:AddENpc(MOMODI);
|
quest:SetENpc(MOMODI);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ end
|
||||||
function onFinish(player, quest)
|
function onFinish(player, quest)
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSequence(player, quest, seqNum)
|
function onStateChange(player, quest, seqNum)
|
||||||
quest:ClearENpcs();
|
quest:ClearENpcs();
|
||||||
end
|
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
|
|
|
@ -28,48 +28,8 @@ namespace Meteor.Map.Actors
|
||||||
{
|
{
|
||||||
class Quest : Actor
|
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
|
private struct QuestData
|
||||||
{
|
{
|
||||||
|
@ -88,43 +48,37 @@ namespace Meteor.Map.Actors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is only set on instance quests (non static)
|
||||||
private Player Owner;
|
private Player Owner;
|
||||||
private ushort currentSequence;
|
private ushort currentSequence;
|
||||||
private QuestData data = new QuestData();
|
private QuestState QuestState;
|
||||||
|
private QuestData Data;
|
||||||
private bool dataDirty = false;
|
private bool dataDirty = false;
|
||||||
private Dictionary<uint, ENpcQuestInstance> CurrentENPCs = new Dictionary<uint, ENpcQuestInstance>();
|
|
||||||
private Dictionary<uint, ENpcQuestInstance> OldENPCs = new Dictionary<uint, ENpcQuestInstance>();
|
|
||||||
|
|
||||||
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
public void SetENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
|
||||||
{
|
{
|
||||||
ENpcQuestInstance instanceUpdated = null;
|
if (QuestState != null)
|
||||||
|
QuestState.AddENpc(classId, flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
|
||||||
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]);
|
public void UpdateENPCs()
|
||||||
OldENPCs.Remove(classId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
instanceUpdated = new ENpcQuestInstance(classId, flagType, isSpawned, isTalkEnabled, isEmoteEnabled, isPushEnabled);
|
if (dataDirty)
|
||||||
CurrentENPCs.Add(classId, instanceUpdated);
|
{
|
||||||
|
if (QuestState != null)
|
||||||
|
QuestState.UpdateState();
|
||||||
|
dataDirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instanceUpdated != null)
|
public QuestState GetQuestState()
|
||||||
Owner.playerSession.UpdateQuestNpcInInstance(instanceUpdated);
|
{
|
||||||
|
return QuestState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ENpcQuestInstance GetENpcInstance(uint classId)
|
public bool IsInstance()
|
||||||
{
|
{
|
||||||
if (CurrentENPCs.ContainsKey(classId))
|
return Owner != null;
|
||||||
return CurrentENPCs[classId];
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnTalk(Player caller, Npc npc)
|
public void OnTalk(Player caller, Npc npc)
|
||||||
|
@ -152,25 +106,11 @@ namespace Meteor.Map.Actors
|
||||||
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onNpcLS", true, npcLSId);
|
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)
|
public bool IsQuestENPC(Player caller, Npc npc)
|
||||||
{
|
{
|
||||||
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(caller, this, "IsQuestENPC", true, npc, this);
|
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(caller, this, "IsQuestENPC", true, npc, this);
|
||||||
bool scriptReturned = returned != null && returned.Count != 0 && returned[0].typeID == 3;
|
bool scriptReturned = returned != null && returned.Count != 0 && returned[0].typeID == 3;
|
||||||
return scriptReturned || CurrentENPCs.ContainsKey(npc.GetActorClassId());
|
return scriptReturned || QuestState.HasENpc(npc.GetActorClassId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,14 +153,14 @@ namespace Meteor.Map.Actors
|
||||||
|
|
||||||
public void ClearData()
|
public void ClearData()
|
||||||
{
|
{
|
||||||
data.flags = data.counter1 = data.counter2 = data.counter3 = data.counter4 = 0;
|
Data.flags = Data.counter1 = Data.counter2 = Data.counter3 = Data.counter4 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFlag(int index)
|
public void SetFlag(int index)
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < 32)
|
if (index >= 0 && index < 32)
|
||||||
{
|
{
|
||||||
data.flags |= (uint)(1 << index);
|
Data.flags |= (uint)(1 << index);
|
||||||
dataDirty = true;
|
dataDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +169,7 @@ namespace Meteor.Map.Actors
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < 32)
|
if (index >= 0 && index < 32)
|
||||||
{
|
{
|
||||||
data.flags &= (uint)~(1 << index);
|
Data.flags &= (uint)~(1 << index);
|
||||||
dataDirty = true;
|
dataDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,16 +181,16 @@ namespace Meteor.Map.Actors
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
data.counter1++;
|
Data.counter1++;
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
data.counter2++;
|
Data.counter2++;
|
||||||
return;
|
return;
|
||||||
case 2:
|
case 2:
|
||||||
data.counter3++;
|
Data.counter3++;
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 3:
|
||||||
data.counter4++;
|
Data.counter4++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,16 +204,16 @@ namespace Meteor.Map.Actors
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
data.counter1--;
|
Data.counter1--;
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
data.counter2--;
|
Data.counter2--;
|
||||||
return;
|
return;
|
||||||
case 2:
|
case 2:
|
||||||
data.counter3--;
|
Data.counter3--;
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 3:
|
||||||
data.counter4--;
|
Data.counter4--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,16 +227,16 @@ namespace Meteor.Map.Actors
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
data.counter1 = value;
|
Data.counter1 = value;
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
data.counter2 = value;
|
Data.counter2 = value;
|
||||||
return;
|
return;
|
||||||
case 2:
|
case 2:
|
||||||
data.counter3 = value;
|
Data.counter3 = value;
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 3:
|
||||||
data.counter4 = value;
|
Data.counter4 = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,13 +246,13 @@ namespace Meteor.Map.Actors
|
||||||
public bool GetFlag(int index)
|
public bool GetFlag(int index)
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < 32)
|
if (index >= 0 && index < 32)
|
||||||
return (data.flags & (uint) (1 << index)) != 0;
|
return (Data.flags & (uint) (1 << index)) != 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetFlags()
|
public uint GetFlags()
|
||||||
{
|
{
|
||||||
return data.flags;
|
return Data.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort GetCounter(int num)
|
public ushort GetCounter(int num)
|
||||||
|
@ -320,13 +260,13 @@ namespace Meteor.Map.Actors
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return data.counter1;
|
return Data.counter1;
|
||||||
case 1:
|
case 1:
|
||||||
return data.counter2;
|
return Data.counter2;
|
||||||
case 2:
|
case 2:
|
||||||
return data.counter3;
|
return Data.counter3;
|
||||||
case 3:
|
case 3:
|
||||||
return data.counter4;
|
return Data.counter4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -354,12 +294,8 @@ namespace Meteor.Map.Actors
|
||||||
className = baseQuest.className;
|
className = baseQuest.className;
|
||||||
classPath = baseQuest.classPath;
|
classPath = baseQuest.classPath;
|
||||||
currentSequence = sequence;
|
currentSequence = sequence;
|
||||||
data = new QuestData(flags, counter1, counter2, counter3);
|
QuestState = new QuestState(owner, this);
|
||||||
|
Data = new QuestData(flags, counter1, counter2, counter3);
|
||||||
if (currentSequence == SEQ_NOT_STARTED)
|
|
||||||
LuaEngine.GetInstance().CallLuaFunction(Owner, this, "onStart", false);
|
|
||||||
else
|
|
||||||
StartSequence(currentSequence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetQuestId()
|
public uint GetQuestId()
|
||||||
|
@ -367,17 +303,34 @@ namespace Meteor.Map.Actors
|
||||||
return Id & 0xFFFFF;
|
return Id & 0xFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DoAccept()
|
||||||
|
{
|
||||||
|
if (currentSequence == SEQ_NOT_STARTED)
|
||||||
|
LuaEngine.GetInstance().CallLuaFunction(Owner, this, "onStart", false);
|
||||||
|
else
|
||||||
|
StartSequence(currentSequence);
|
||||||
|
}
|
||||||
|
|
||||||
public void DoComplete()
|
public void DoComplete()
|
||||||
{
|
{
|
||||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", true);
|
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", true);
|
||||||
Owner.SendDataPacket("attention", Server.GetWorldManager().GetActor(), "", 25225, (object)GetQuestId());
|
Owner.SendDataPacket("attention", Server.GetWorldManager().GetActor(), "", 25225, (object)GetQuestId());
|
||||||
Owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25225, 0x20, (object)GetQuestId());
|
Owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25225, 0x20, (object)GetQuestId());
|
||||||
|
currentSequence = SEQ_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoAbandon()
|
public void DoAbandon()
|
||||||
{
|
{
|
||||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", false);
|
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onFinish", false);
|
||||||
Owner.SendGameMessage(Owner, Server.GetWorldManager().GetActor(), 25236, 0x20, (object)GetQuestId());
|
Owner.SendGameMessage(Owner, Server.GetWorldManager().GetActor(), 25236, 0x20, (object)GetQuestId());
|
||||||
|
currentSequence = SEQ_NOT_STARTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is Quest quest)
|
||||||
|
return quest.Id == this.Id;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
112
Map Server/Actors/Quest/QuestState.cs
Normal file
112
Map Server/Actors/Quest/QuestState.cs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
using Meteor.Map.lua;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Meteor.Map.Actors
|
||||||
|
{
|
||||||
|
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 Player Owner;
|
||||||
|
private 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;
|
||||||
|
UpdateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
OldENPCs = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
Map Server/Actors/Quest/QuestStateManager.cs
Normal file
108
Map Server/Actors/Quest/QuestStateManager.cs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
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
|
||||||
|
{
|
||||||
|
class QuestStateManager
|
||||||
|
{
|
||||||
|
private const int SCENARIO_START = 110001;
|
||||||
|
private const int SCENARIO_MAX = 2048;
|
||||||
|
|
||||||
|
private readonly Player player;
|
||||||
|
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>();
|
||||||
|
|
||||||
|
public QuestStateManager(Player player)
|
||||||
|
{
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
// Init MinLv
|
||||||
|
QuestData[] minLvl = Server.GetQuestGamedataByMaxLvl(player.GetHighestLevel(), true);
|
||||||
|
foreach (var questData in minLvl)
|
||||||
|
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
||||||
|
|
||||||
|
// Init Prereq
|
||||||
|
Bitstream completed = new Bitstream(player.playerWork.questScenarioComplete);
|
||||||
|
foreach (var questData in Server.GetQuestGamedataAllPrerequisite())
|
||||||
|
{
|
||||||
|
if (completed.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)
|
||||||
|
{
|
||||||
|
QuestData[] updated = Server.GetQuestGamedataByMaxLvl(level);
|
||||||
|
foreach (var questData in updated)
|
||||||
|
MinLevelBitfield.Set(questData.Id - SCENARIO_START);
|
||||||
|
ComputeAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateQuestComplete(Quest quest)
|
||||||
|
{
|
||||||
|
QuestData[] updated = Server.GetQuestGamedataByPrerequisite(quest.GetQuestId());
|
||||||
|
foreach (var questData in updated)
|
||||||
|
PrereqBitfield.Set(questData.Id - SCENARIO_START);
|
||||||
|
ComputeAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QuestAdded(Quest quest)
|
||||||
|
{
|
||||||
|
ActiveQuests.Remove(quest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ComputeAvailable()
|
||||||
|
{
|
||||||
|
Bitstream result = new Bitstream(player.playerWork.questScenarioComplete);
|
||||||
|
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))
|
||||||
|
ActiveQuests.Add(new Quest(player, quest));
|
||||||
|
else
|
||||||
|
ActiveQuests.Remove(quest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AvailableQuestsBitfield.SetTo(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quest[] GetQuestsForNpc(Npc npc)
|
||||||
|
{
|
||||||
|
return ActiveQuests.FindAll(quest => quest.IsQuestENPC(player, npc)).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ using Meteor.Common;
|
||||||
using Meteor.Map.utils;
|
using Meteor.Map.utils;
|
||||||
|
|
||||||
using Meteor.Map.packets.send.player;
|
using Meteor.Map.packets.send.player;
|
||||||
using Meteor.Map.dataobjects;
|
using Meteor.Map.DataObjects;
|
||||||
using Meteor.Map.Actors;
|
using Meteor.Map.Actors;
|
||||||
using Meteor.Map.actors.chara.player;
|
using Meteor.Map.actors.chara.player;
|
||||||
using Meteor.Map.packets.receive.supportdesk;
|
using Meteor.Map.packets.receive.supportdesk;
|
||||||
|
@ -72,6 +72,56 @@ namespace Meteor.Map
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Dictionary<uint, QuestData> 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, QuestData> gamedataQuests = new Dictionary<uint, QuestData>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
string query = @"
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
className,
|
||||||
|
questName,
|
||||||
|
prerequisite,
|
||||||
|
minLevel,
|
||||||
|
minGCRank
|
||||||
|
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 QuestData(questId, code, name, prerequisite, minLevel, minRank));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
Program.Log.Error(e.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
conn.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return gamedataQuests;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Dictionary<uint, ItemData> GetItemGamedata()
|
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)))
|
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)))
|
||||||
|
|
|
@ -180,9 +180,12 @@
|
||||||
<Compile Include="Actors\Group\Work\RelationWork.cs" />
|
<Compile Include="Actors\Group\Work\RelationWork.cs" />
|
||||||
<Compile Include="Actors\Judge\Judge.cs" />
|
<Compile Include="Actors\Judge\Judge.cs" />
|
||||||
<Compile Include="Actors\Quest\Quest.cs" />
|
<Compile Include="Actors\Quest\Quest.cs" />
|
||||||
|
<Compile Include="Actors\Quest\QuestState.cs" />
|
||||||
|
<Compile Include="Actors\Quest\QuestStateManager.cs" />
|
||||||
<Compile Include="Actors\StaticActors.cs" />
|
<Compile Include="Actors\StaticActors.cs" />
|
||||||
<Compile Include="Actors\World\WorldMaster.cs" />
|
<Compile Include="Actors\World\WorldMaster.cs" />
|
||||||
<Compile Include="DataObjects\GuildleveData.cs" />
|
<Compile Include="DataObjects\GuildleveData.cs" />
|
||||||
|
<Compile Include="DataObjects\QuestData.cs" />
|
||||||
<Compile Include="DataObjects\Recipe.cs" />
|
<Compile Include="DataObjects\Recipe.cs" />
|
||||||
<Compile Include="DataObjects\RecipeResolver.cs" />
|
<Compile Include="DataObjects\RecipeResolver.cs" />
|
||||||
<Compile Include="DataObjects\TradeTransaction.cs" />
|
<Compile Include="DataObjects\TradeTransaction.cs" />
|
||||||
|
|
|
@ -22,7 +22,7 @@ along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
|
||||||
using Meteor.Common;
|
using Meteor.Common;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Meteor.Map.dataobjects;
|
using Meteor.Map.DataObjects;
|
||||||
using Meteor.Map.packets.receive;
|
using Meteor.Map.packets.receive;
|
||||||
using Meteor.Map.packets.send;
|
using Meteor.Map.packets.send;
|
||||||
using Meteor.Map.packets.send.login;
|
using Meteor.Map.packets.send.login;
|
||||||
|
|
|
@ -23,10 +23,11 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using Meteor.Map.dataobjects;
|
using Meteor.Map.DataObjects;
|
||||||
|
|
||||||
using Meteor.Common;
|
using Meteor.Common;
|
||||||
using Meteor.Map.Actors;
|
using Meteor.Map.Actors;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Meteor.Map
|
namespace Meteor.Map
|
||||||
{
|
{
|
||||||
|
@ -38,52 +39,56 @@ namespace Meteor.Map
|
||||||
|
|
||||||
public const string STATIC_ACTORS_PATH = "./staticactors.bin";
|
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 CommandProcessor CommandProcessor = new CommandProcessor();
|
||||||
private static ZoneConnection mWorldConnection = new ZoneConnection();
|
private static ZoneConnection WorldConnection = new ZoneConnection();
|
||||||
private static WorldManager mWorldManager;
|
private static WorldManager WorldManager;
|
||||||
private static Dictionary<uint, ItemData> mGamedataItems;
|
private static Dictionary<uint, ItemData> GamedataItems;
|
||||||
private static Dictionary<uint, GuildleveData> mGamedataGuildleves;
|
private static Dictionary<uint, GuildleveData> GamedataGuildleves;
|
||||||
private static StaticActors mStaticActors;
|
private static Dictionary<uint, QuestData> GamedataQuests;
|
||||||
|
private static StaticActors StaticActors;
|
||||||
|
|
||||||
private PacketProcessor mProcessor;
|
private PacketProcessor mProcessor;
|
||||||
|
|
||||||
public Server()
|
public Server()
|
||||||
{
|
{
|
||||||
mSelf = this;
|
_Self = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool StartServer()
|
public bool StartServer()
|
||||||
{
|
{
|
||||||
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
|
StaticActors = new StaticActors(STATIC_ACTORS_PATH);
|
||||||
|
|
||||||
mGamedataItems = Database.GetItemGamedata();
|
Program.Log.Info("Loading gamedata...");
|
||||||
Program.Log.Info("Loaded {0} items.", mGamedataItems.Count);
|
GamedataItems = Database.GetItemGamedata();
|
||||||
mGamedataGuildleves = Database.GetGuildleveGamedata();
|
Program.Log.Info("Loaded {0} items.", GamedataItems.Count);
|
||||||
Program.Log.Info("Loaded {0} guildleves.", mGamedataGuildleves.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);
|
WorldManager = new WorldManager(this);
|
||||||
mWorldManager.LoadZoneList();
|
WorldManager.LoadZoneList();
|
||||||
mWorldManager.LoadSeamlessBoundryList();
|
WorldManager.LoadSeamlessBoundryList();
|
||||||
mWorldManager.LoadActorClasses();
|
WorldManager.LoadActorClasses();
|
||||||
mWorldManager.LoadENPCs();
|
WorldManager.LoadENPCs();
|
||||||
mWorldManager.LoadBattleNpcs();
|
WorldManager.LoadBattleNpcs();
|
||||||
mWorldManager.LoadStatusEffects();
|
WorldManager.LoadStatusEffects();
|
||||||
mWorldManager.LoadBattleCommands();
|
WorldManager.LoadBattleCommands();
|
||||||
mWorldManager.LoadBattleTraits();
|
WorldManager.LoadBattleTraits();
|
||||||
mWorldManager.SpawnAllActors();
|
WorldManager.SpawnAllActors();
|
||||||
mWorldManager.StartZoneThread();
|
WorldManager.StartZoneThread();
|
||||||
|
|
||||||
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT));
|
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
ServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -91,8 +96,8 @@ namespace Meteor.Map
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mServerSocket.Bind(serverEndPoint);
|
ServerSocket.Bind(serverEndPoint);
|
||||||
mServerSocket.Listen(BACKLOG);
|
ServerSocket.Listen(BACKLOG);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -100,7 +105,7 @@ namespace Meteor.Map
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +113,7 @@ namespace Meteor.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
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;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
|
|
||||||
mProcessor = new PacketProcessor(this);
|
mProcessor = new PacketProcessor(this);
|
||||||
|
@ -122,36 +127,36 @@ namespace Meteor.Map
|
||||||
|
|
||||||
public Session AddSession(uint id)
|
public Session AddSession(uint id)
|
||||||
{
|
{
|
||||||
if (mSessionList.ContainsKey(id))
|
if (SessionList.ContainsKey(id))
|
||||||
{
|
{
|
||||||
mSessionList[id].ClearInstance();
|
SessionList[id].ClearInstance();
|
||||||
return mSessionList[id];
|
return SessionList[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
Session session = new Session(id);
|
Session session = new Session(id);
|
||||||
mSessionList.Add(id, session);
|
SessionList.Add(id, session);
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveSession(uint id)
|
public void RemoveSession(uint id)
|
||||||
{
|
{
|
||||||
if (mSessionList.ContainsKey(id))
|
if (SessionList.ContainsKey(id))
|
||||||
{
|
{
|
||||||
mSessionList.Remove(id);
|
SessionList.Remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Session GetSession(uint id)
|
public Session GetSession(uint id)
|
||||||
{
|
{
|
||||||
if (mSessionList.ContainsKey(id))
|
if (SessionList.ContainsKey(id))
|
||||||
return mSessionList[id];
|
return SessionList[id];
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Session GetSession(string name)
|
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()))
|
if (s.GetActor().DisplayName.ToLower().Equals(name.ToLower()))
|
||||||
return s;
|
return s;
|
||||||
|
@ -161,7 +166,7 @@ namespace Meteor.Map
|
||||||
|
|
||||||
public Dictionary<uint, Session> GetSessionList()
|
public Dictionary<uint, Session> GetSessionList()
|
||||||
{
|
{
|
||||||
return mSessionList;
|
return SessionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -179,29 +184,29 @@ namespace Meteor.Map
|
||||||
conn.socket = socket.EndAccept(result);
|
conn.socket = socket.EndAccept(result);
|
||||||
conn.buffer = new byte[BUFFER_SIZE];
|
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);
|
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
|
//Queue recieving of data from the connection
|
||||||
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
|
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
|
||||||
//Queue the accept of the next incomming connection
|
//Queue the accept of the next incomming connection
|
||||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||||
}
|
}
|
||||||
catch (SocketException)
|
catch (SocketException)
|
||||||
{
|
{
|
||||||
if (conn != null)
|
if (conn != null)
|
||||||
{
|
{
|
||||||
mWorldConnection = null;
|
WorldConnection = null;
|
||||||
}
|
}
|
||||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
if (conn != null)
|
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
|
//Check if disconnected
|
||||||
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
|
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
|
||||||
{
|
{
|
||||||
mWorldConnection = null;
|
WorldConnection = null;
|
||||||
Program.Log.Info("Disconnected from world server!");
|
Program.Log.Info("Disconnected from world server!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +265,7 @@ namespace Meteor.Map
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mWorldConnection = null;
|
WorldConnection = null;
|
||||||
Program.Log.Info("Disconnected from world server!");
|
Program.Log.Info("Disconnected from world server!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +273,7 @@ namespace Meteor.Map
|
||||||
{
|
{
|
||||||
if (conn.socket != null)
|
if (conn.socket != null)
|
||||||
{
|
{
|
||||||
mWorldConnection = null;
|
WorldConnection = null;
|
||||||
Program.Log.Info("Disconnected from world server!");
|
Program.Log.Info("Disconnected from world server!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,54 +283,90 @@ namespace Meteor.Map
|
||||||
|
|
||||||
public static ZoneConnection GetWorldConnection()
|
public static ZoneConnection GetWorldConnection()
|
||||||
{
|
{
|
||||||
return mWorldConnection;
|
return WorldConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Server GetServer()
|
public static Server GetServer()
|
||||||
{
|
{
|
||||||
return mSelf;
|
return _Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandProcessor GetCommandProcessor()
|
public static CommandProcessor GetCommandProcessor()
|
||||||
{
|
{
|
||||||
return mCommandProcessor;
|
return CommandProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorldManager GetWorldManager()
|
public static WorldManager GetWorldManager()
|
||||||
{
|
{
|
||||||
return mWorldManager;
|
return WorldManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<uint, ItemData> GetGamedataItems()
|
public static Dictionary<uint, ItemData> GetGamedataItems()
|
||||||
{
|
{
|
||||||
return mGamedataItems;
|
return GamedataItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Actor GetStaticActors(uint id)
|
public static Actor GetStaticActors(uint id)
|
||||||
{
|
{
|
||||||
return mStaticActors.GetActor(id);
|
return StaticActors.GetActor(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Actor GetStaticActors(string name)
|
public static Actor GetStaticActors(string name)
|
||||||
{
|
{
|
||||||
return mStaticActors.FindStaticActor(name);
|
return StaticActors.FindStaticActor(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemData GetItemGamedata(uint id)
|
public static ItemData GetItemGamedata(uint id)
|
||||||
{
|
{
|
||||||
if (mGamedataItems.ContainsKey(id))
|
if (GamedataItems.ContainsKey(id))
|
||||||
return mGamedataItems[id];
|
return GamedataItems[id];
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GuildleveData GetGuildleveGamedata(uint id)
|
public static GuildleveData GetGuildleveGamedata(uint id)
|
||||||
{
|
{
|
||||||
if (mGamedataGuildleves.ContainsKey(id))
|
if (GamedataGuildleves.ContainsKey(id))
|
||||||
return mGamedataGuildleves[id];
|
return GamedataGuildleves[id];
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static QuestData GetQuestGamedata(uint id)
|
||||||
|
{
|
||||||
|
if (GamedataQuests.ContainsKey(id))
|
||||||
|
return GamedataQuests[id];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static QuestData[] 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 QuestData[] GetQuestGamedataByPrerequisite(uint questId)
|
||||||
|
{
|
||||||
|
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest == questId).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QuestData[] GetQuestGamedataAllPrerequisite()
|
||||||
|
{
|
||||||
|
return GamedataQuests.Values.Where(quest => quest.PrerequisiteQuest != 0).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QuestData[] 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.area;
|
||||||
using Meteor.Map.actors.chara.npc;
|
using Meteor.Map.actors.chara.npc;
|
||||||
using Meteor.Map.Actors;
|
using Meteor.Map.Actors;
|
||||||
using Meteor.Map.dataobjects;
|
using Meteor.Map.DataObjects;
|
||||||
using Meteor.Map.lua;
|
using Meteor.Map.lua;
|
||||||
using Meteor.Map.packets.send;
|
using Meteor.Map.packets.send;
|
||||||
using Meteor.Map.packets.send.actor;
|
using Meteor.Map.packets.send.actor;
|
||||||
|
|
Loading…
Add table
Reference in a new issue