mirror of
				https://bitbucket.org/Ioncannon/project-meteor-server.git
				synced 2025-05-20 08:26:59 -04:00 
			
		
		
		
	Finished quest state system idea
This commit is contained in:
		
							
								
								
									
										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; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user