diff --git a/FFXIVClassic Lobby Server/Database.cs b/FFXIVClassic Lobby Server/Database.cs
index b37b8efc..1f7ec710 100644
--- a/FFXIVClassic Lobby Server/Database.cs
+++ b/FFXIVClassic Lobby Server/Database.cs
@@ -228,6 +228,8 @@ namespace FFXIVClassic_Lobby_Server
{
conn.Dispose();
}
+
+
}
Log.database(String.Format("CID={0} state updated to active(2).", cid));
diff --git a/FFXIVClassic Lobby Server/PacketProcessor.cs b/FFXIVClassic Lobby Server/PacketProcessor.cs
index 6f3e8979..db2dcaaf 100644
--- a/FFXIVClassic Lobby Server/PacketProcessor.cs
+++ b/FFXIVClassic Lobby Server/PacketProcessor.cs
@@ -253,21 +253,21 @@ namespace FFXIVClassic_Lobby_Server
info.x = 0.016f;
info.y = 10.35f;
info.z = -36.91f;
- info.rot = 0.025f;
+ info.rot = 0.025f;
break;
case 2: //fst0Battle03 (Gridania)
info.zoneId = 166;
- info.x = 356.09f;
- info.y = 3.74f;
- info.z = -701.62f;
- info.rot = -1.4f;
+ info.x = 369.5434f;
+ info.y = 4.21f;
+ info.z = -706.1074f;
+ info.rot = -1.26721f;
break;
case 3: //wil0Battle01 (Ul'dah)
info.zoneId = 184;
- info.x = 12.63f;
- info.y = 196.05f;
- info.z = 131.01f;
- info.rot = -1.34f;
+ info.x = 5.364327f;
+ info.y = 196.0f;
+ info.z = 133.6561f;
+ info.rot = -2.849384f;
break;
}
diff --git a/FFXIVClassic Map Server/ClientConnection.cs b/FFXIVClassic Map Server/ClientConnection.cs
index a5751a56..ae14c995 100644
--- a/FFXIVClassic Map Server/ClientConnection.cs
+++ b/FFXIVClassic Map Server/ClientConnection.cs
@@ -47,8 +47,7 @@ namespace FFXIVClassic_Lobby_Server
BasePacket packet = sendPacketQueue.Take();
byte[] packetBytes = packet.getPacketBytes();
- byte[] buffer = new byte[0xFFFF];
- Array.Copy(packetBytes, buffer, packetBytes.Length);
+
try
{
socket.Send(packetBytes);
diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs
index 3f114e1c..e9ecd342 100644
--- a/FFXIVClassic Map Server/Database.cs
+++ b/FFXIVClassic Map Server/Database.cs
@@ -310,6 +310,56 @@ namespace FFXIVClassic_Lobby_Server
}
}
+ public static void saveQuest(Player player, Quest quest)
+ {
+ int slot = player.getQuestSlot(quest.actorId);
+ if (slot == -1)
+ {
+ Log.error(String.Format("Tried saving quest player didn't have: Player: {0:x}, QuestId: {0:x}", player.actorId, quest.actorId));
+ return;
+ }
+ else
+ saveQuest(player, quest, slot);
+ }
+
+ public static void saveQuest(Player player, Quest quest, int slot)
+ {
+ string query;
+ MySqlCommand cmd;
+
+ using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
+ {
+ try
+ {
+ conn.Open();
+
+ query = @"
+ INSERT INTO characters_quest_scenario
+ (characterId, slot, questId, questData, questFlags)
+ VALUES
+ (@charaId, @slot, @questId, @questData, @questFlags)
+ ON DUPLICATE KEY UPDATE
+ questData = @questData, questFlags = @questFlags
+ ";
+
+ cmd = new MySqlCommand(query, conn);
+ cmd.Parameters.AddWithValue("@charaId", player.actorId);
+ cmd.Parameters.AddWithValue("@slot", slot);
+ cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.actorId);
+ cmd.Parameters.AddWithValue("@questData", quest.GetSerializedQuestData());
+ cmd.Parameters.AddWithValue("@questFlags", quest.GetQuestFlags());
+
+ cmd.ExecuteNonQuery();
+ }
+ catch (MySqlException e)
+ { Console.WriteLine(e); }
+ finally
+ {
+ conn.Dispose();
+ }
+ }
+ }
+
public static void loadPlayerCharacter(Player player)
{
string query;
@@ -627,7 +677,9 @@ namespace FFXIVClassic_Lobby_Server
query = @"
SELECT
slot,
- questId
+ questId,
+ questData,
+ questFlags
FROM characters_quest_scenario WHERE characterId = @charId";
cmd = new MySqlCommand(query, conn);
@@ -638,9 +690,21 @@ namespace FFXIVClassic_Lobby_Server
{
int index = reader.GetUInt16(0);
player.playerWork.questScenario[index] = 0xA0F00000 | reader.GetUInt32(1);
+ string questData = null;
+ uint questFlags = 0;
+
+ if (!reader.IsDBNull(2))
+ questData = reader.GetString(2);
+ else
+ questData = "{}";
+
+ if (!reader.IsDBNull(3))
+ questFlags = reader.GetUInt32(3);
+ else
+ questFlags = 0;
string questName = Server.getStaticActors(player.playerWork.questScenario[index]).actorName;
- player.questScenario[index] = new Quest(player.playerWork.questScenario[index], questName);
+ player.questScenario[index] = new Quest(player, player.playerWork.questScenario[index], questName, questData, questFlags);
}
}
diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index d11205d9..39d2345e 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -72,6 +72,9 @@
+
+
+
@@ -135,6 +138,7 @@
+
@@ -244,6 +248,7 @@
+
@@ -277,11 +282,11 @@
xcopy "$(SolutionDir)data" "$(SolutionDir)$(ProjectName)\$(OutDir)" /E /C /D
-
\ No newline at end of file
diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs
index 5d04595e..2e210934 100644
--- a/FFXIVClassic Map Server/PacketProcessor.cs
+++ b/FFXIVClassic Map Server/PacketProcessor.cs
@@ -259,19 +259,27 @@ namespace FFXIVClassic_Lobby_Server
break;
}
*/
- player.getActor().eventCurrentOwner = eventStart.scriptOwnerActorID;
- player.getActor().eventCurrentStarter = eventStart.triggerName;
- //Is it a static actor? If not look in the player's instance
- Actor ownerActor = Server.getStaticActors(player.getActor().eventCurrentOwner);
+ Actor ownerActor = Server.getStaticActors(eventStart.scriptOwnerActorID);
+ if (ownerActor != null && ownerActor is Command)
+ {
+ player.getActor().currentCommand = eventStart.scriptOwnerActorID;
+ player.getActor().currentCommandName = eventStart.triggerName;
+ }
+ else
+ {
+ player.getActor().currentEventOwner = eventStart.scriptOwnerActorID;
+ player.getActor().currentEventName = eventStart.triggerName;
+ }
+
if (ownerActor == null)
{
//Is it a instance actor?
- ownerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner);
+ ownerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().currentEventOwner);
if (ownerActor == null)
{
//Is it a Director?
- if (player.getActor().currentDirector != null && player.getActor().eventCurrentOwner == player.getActor().currentDirector.actorId)
+ if (player.getActor().currentDirector != null && player.getActor().currentEventOwner == player.getActor().currentDirector.actorId)
ownerActor = player.getActor().currentDirector;
else
{
@@ -295,12 +303,12 @@ namespace FFXIVClassic_Lobby_Server
Log.debug(String.Format("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.dumpParams(eventUpdate.luaParams)));
//Is it a static actor? If not look in the player's instance
- Actor updateOwnerActor = Server.getStaticActors(player.getActor().eventCurrentOwner);
+ Actor updateOwnerActor = Server.getStaticActors(player.getActor().currentEventOwner);
if (updateOwnerActor == null)
{
- updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner);
+ updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().currentEventOwner);
- if (player.getActor().currentDirector != null && player.getActor().eventCurrentOwner == player.getActor().currentDirector.actorId)
+ if (player.getActor().currentDirector != null && player.getActor().currentEventOwner == player.getActor().currentDirector.actorId)
updateOwnerActor = player.getActor().currentDirector;
if (updateOwnerActor == null)
diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs
index 52e6480b..f0057765 100644
--- a/FFXIVClassic Map Server/Server.cs
+++ b/FFXIVClassic Map Server/Server.cs
@@ -330,6 +330,7 @@ namespace FFXIVClassic_Lobby_Server
#endregion
+
public static WorldManager GetWorldManager()
{
return mWorldManager;
@@ -344,5 +345,6 @@ namespace FFXIVClassic_Lobby_Server
{
return gamedataItems;
}
+
}
}
\ No newline at end of file
diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs
index 3d5d33c5..7484ac22 100644
--- a/FFXIVClassic Map Server/WorldManager.cs
+++ b/FFXIVClassic Map Server/WorldManager.cs
@@ -347,7 +347,7 @@ namespace FFXIVClassic_Map_Server
}
//Moves actor to new zone, and sends packets to spawn at the given zone entrance
- public void DoZoneChange(Player player, uint destinationZoneId, uint zoneEntrance)
+ public void DoZoneChange(Player player, uint zoneEntrance)
{
if (!zoneEntranceList.ContainsKey(zoneEntrance))
{
@@ -356,7 +356,7 @@ namespace FFXIVClassic_Map_Server
}
ZoneEntrance ze = zoneEntranceList[zoneEntrance];
- DoZoneChange(player, destinationZoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation);
+ DoZoneChange(player, ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation);
}
//Moves actor to new zone, and sends packets to spawn at the given coords.
@@ -416,11 +416,11 @@ namespace FFXIVClassic_Map_Server
if (ze.zoneId != player.zoneId)
return;
- DoPlayerMoveInZone(player, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation);
+ DoPlayerMoveInZone(player, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation, ze.spawnType);
}
//Moves actor within the zone
- public void DoPlayerMoveInZone(Player player, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
+ public void DoPlayerMoveInZone(Player player, float spawnX, float spawnY, float spawnZ, float spawnRotation, byte spawnType = 0xF)
{
//Remove player from currentZone if transfer else it's login
if (player.zone != null)
@@ -436,7 +436,7 @@ namespace FFXIVClassic_Map_Server
//Send packets
player.playerSession.queuePacket(_0xE2Packet.buildPacket(player.actorId, 0x0), true, false);
- player.playerSession.queuePacket(player.createSpawnTeleportPacket(player.actorId, 0x0f), true, false);
+ player.playerSession.queuePacket(player.createSpawnTeleportPacket(player.actorId, spawnType), true, false);
player.sendInstanceUpdate();
}
@@ -454,6 +454,9 @@ namespace FFXIVClassic_Map_Server
//Set the current zone and add player
player.zone = zone;
+
+ LuaEngine.onBeginLogin(player);
+
zone.addActorToZone(player);
//Send packets
diff --git a/FFXIVClassic Map Server/actors/area/PrivateArea.cs b/FFXIVClassic Map Server/actors/area/PrivateArea.cs
index ab788357..3c6f6726 100644
--- a/FFXIVClassic Map Server/actors/area/PrivateArea.cs
+++ b/FFXIVClassic Map Server/actors/area/PrivateArea.cs
@@ -35,7 +35,14 @@ namespace FFXIVClassic_Map_Server.actors.area
public override SubPacket createScriptBindPacket(uint playerActorId)
{
List lParams;
- lParams = LuaUtils.createLuaParamList("/Area/PrivateArea/" + className, false, true, zoneName, privateAreaName, 0x9E, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, false, false, false);
+
+ string path = className;
+
+ if (className.ToLower().Contains("content"))
+ path = "Content/" + className;
+
+ lParams = LuaUtils.createLuaParamList("/Area/PrivateArea/" + path, false, true, zoneName, privateAreaName, 0x9E, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, false, false, false);
+ ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams).debugPrintSubPacket();
return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams);
}
diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs
index 8ada9422..c453e82f 100644
--- a/FFXIVClassic Map Server/actors/chara/Character.cs
+++ b/FFXIVClassic Map Server/actors/chara/Character.cs
@@ -81,6 +81,11 @@ namespace FFXIVClassic_Map_Server.Actors
return SetActorIdleAnimationPacket.buildPacket(actorId, playerActorId, animationId);
}
+ public void setQuestGraphic(Player player, int graphicNum)
+ {
+ player.queuePacket(SetActorQuestGraphicPacket.buildPacket(player.actorId, actorId, graphicNum));
+ }
+
}
}
diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs
index 9e43c677..4ea2ed8a 100644
--- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs
+++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs
@@ -2,6 +2,7 @@
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.actors;
+using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
@@ -20,6 +21,8 @@ namespace FFXIVClassic_Map_Server.Actors
{
private uint actorClassId;
+ public NpcWork npcWork = new NpcWork();
+
public Npc(uint id, string actorName, uint zoneId, float posX, float posY, float posZ, float rot, ushort actorState, uint animationId, uint displayNameId, string customDisplayName, string className)
: base(id)
{
@@ -38,6 +41,26 @@ namespace FFXIVClassic_Map_Server.Actors
this.zoneId = zoneId;
loadNpcTemplate(id);
+
+ charaWork.battleSave.potencial = 1.0f;
+
+ charaWork.parameterSave.state_mainSkill[0] = 3;
+ charaWork.parameterSave.state_mainSkill[2] = 3;
+ charaWork.parameterSave.state_mainSkillLevel = 2;
+
+ charaWork.parameterSave.hp[0] = 500;
+ charaWork.parameterSave.hpMax[0] = 500;
+ charaWork.property[0] = 1;
+ charaWork.property[1] = 1;
+
+ if (className.Equals("JellyfishScenarioLimsaLv00"))
+ {
+ charaWork.property[2] = 1;
+ npcWork.hateType = 1;
+ }
+
+ charaWork.property[3] = 1;
+ charaWork.property[4] = 1;
}
public SubPacket createAddActorPacket(uint playerActorId)
@@ -50,7 +73,7 @@ namespace FFXIVClassic_Map_Server.Actors
List lParams;
Player player = Server.GetWorldManager().GetPCInWorld(playerActorId);
- lParams = LuaEngine.doActorOnInstantiate(player, this);
+ lParams = LuaEngine.doActorInstantiate(player, this);
if (lParams == null)
{
@@ -80,6 +103,54 @@ namespace FFXIVClassic_Map_Server.Actors
return BasePacket.createPacket(subpackets, true, false);
}
+ public override BasePacket getInitPackets(uint playerActorId)
+ {
+ ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId);
+
+ //Properties
+ for (int i = 0; i < charaWork.property.Length; i++)
+ {
+ if (charaWork.property[i] != 0)
+ propPacketUtil.addProperty(String.Format("charaWork.property[{0}]", i));
+ }
+
+ //Parameters
+ propPacketUtil.addProperty("charaWork.parameterSave.hp[0]");
+ propPacketUtil.addProperty("charaWork.parameterSave.hpMax[0]");
+ propPacketUtil.addProperty("charaWork.parameterSave.mp");
+ propPacketUtil.addProperty("charaWork.parameterSave.mpMax");
+ propPacketUtil.addProperty("charaWork.parameterTemp.tp");
+
+ if (charaWork.parameterSave.state_mainSkill[0] != 0)
+ propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkill[0]");
+ if (charaWork.parameterSave.state_mainSkill[1] != 0)
+ propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkill[1]");
+ if (charaWork.parameterSave.state_mainSkill[2] != 0)
+ propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkill[2]");
+ if (charaWork.parameterSave.state_mainSkill[3] != 0)
+ propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkill[3]");
+
+ propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkillLevel");
+
+ //Status Times
+ for (int i = 0; i < charaWork.statusShownTime.Length; i++)
+ {
+ if (charaWork.statusShownTime[i] != 0xFFFFFFFF)
+ propPacketUtil.addProperty(String.Format("charaWork.statusShownTime[{0}]", i));
+ }
+
+ //General Parameters
+ for (int i = 3; i < charaWork.battleTemp.generalParameter.Length; i++)
+ {
+ if (charaWork.battleTemp.generalParameter[i] != 0)
+ propPacketUtil.addProperty(String.Format("charaWork.battleTemp.generalParameter[{0}]", i));
+ }
+
+ propPacketUtil.addProperty("npcWork.hateType");
+
+ return BasePacket.createPacket(propPacketUtil.done(), true, false);
+ }
+
public uint getActorClassId()
{
return actorClassId;
diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs
index 76d1de0a..80f02af9 100644
--- a/FFXIVClassic Map Server/actors/chara/player/Player.cs
+++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs
@@ -84,6 +84,15 @@ namespace FFXIVClassic_Map_Server.Actors
45000, 47000, 50000, 53000, 56000, 59000, 62000, 65000, 68000, 71000, //Level <= 40
74000, 78000, 81000, 85000, 89000, 92000, 96000, 100000, 100000, 110000}; //Level <= 50
+ //Event Related
+ public uint currentEventOwner = 0;
+ public string currentEventName = "";
+
+ public uint currentCommand = 0;
+ public string currentCommandName = "";
+
+ public uint eventMenuId = 0;
+
//Player Info
public uint[] timers = new uint[20];
public ushort currentJob;
@@ -108,12 +117,7 @@ namespace FFXIVClassic_Map_Server.Actors
public bool hasGoobbue;
public byte chocoboAppearance;
public string chocoboName;
- public byte mountState = 0;
-
- //Event Related
- public uint eventCurrentOwner = 0;
- public string eventCurrentStarter = "";
- public uint eventMenuId = 0;
+ public byte mountState = 0;
public uint achievementPoints;
@@ -125,7 +129,7 @@ namespace FFXIVClassic_Map_Server.Actors
public Quest[] questScenario = new Quest[16];
public Quest[] questGuildleve = new Quest[8];
- public Director currentDirector;// = new OpeningDirector(0x46080012);
+ public Director currentDirector;
public PlayerWork playerWork = new PlayerWork();
@@ -256,7 +260,7 @@ namespace FFXIVClassic_Map_Server.Actors
if (isMyPlayer(playerActorId))
{
if (currentDirector != null)
- lParams = LuaUtils.createLuaParamList("/Chara/Player/Player_work", false, false, true, currentDirector, 0, false, timers, true);
+ lParams = LuaUtils.createLuaParamList("/Chara/Player/Player_work", false, false, true, currentDirector, true, 0, false, timers, true);
else
lParams = LuaUtils.createLuaParamList("/Chara/Player/Player_work", false, false, false, true, 0, false, timers, true);
}
@@ -472,12 +476,15 @@ namespace FFXIVClassic_Map_Server.Actors
public void sendZoneInPackets(WorldManager world, ushort spawnType)
{
- queuePacket(SetMapPacket.buildPacket(actorId, zone.regionId, zone.actorId));
+ queuePacket(SetActorIsZoningPacket.buildPacket(actorId, actorId, false));
+ queuePacket(_0x10Packet.buildPacket(actorId, 0xFF));
queuePacket(SetMusicPacket.buildPacket(actorId, zone.bgmDay, 0x01));
queuePacket(SetWeatherPacket.buildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR));
+
+ queuePacket(SetMapPacket.buildPacket(actorId, zone.regionId, zone.actorId));
queuePacket(getSpawnPackets(actorId, spawnType));
- //getSpawnPackets(actorId, spawnType).debugPrintPacket();
+ getSpawnPackets(actorId, spawnType).debugPrintPacket();
#region grouptest
//Retainers
@@ -511,6 +518,7 @@ namespace FFXIVClassic_Map_Server.Actors
playerSession.queuePacket(getInitPackets(actorId));
+
BasePacket areaMasterSpawn = zone.getSpawnPackets(actorId);
BasePacket debugSpawn = world.GetDebugActor().getSpawnPackets(actorId);
BasePacket worldMasterSpawn = world.GetActor().getSpawnPackets(actorId);
@@ -523,8 +531,8 @@ namespace FFXIVClassic_Map_Server.Actors
playerSession.queuePacket(debugSpawn);
if (directorSpawn != null)
{
- directorSpawn.debugPrintPacket();
- currentDirector.getInitPackets(actorId).debugPrintPacket();
+ //directorSpawn.debugPrintPacket();
+ // currentDirector.getInitPackets(actorId).debugPrintPacket();
queuePacket(directorSpawn);
queuePacket(currentDirector.getInitPackets(actorId));
//queuePacket(currentDirector.getSetEventStatusPackets(actorId));
@@ -591,6 +599,12 @@ namespace FFXIVClassic_Map_Server.Actors
playerSession.queuePacket(packet, true, false);
}
+ public void queuePackets(List packets)
+ {
+ foreach (SubPacket subpacket in packets)
+ playerSession.queuePacket(subpacket, true, false);
+ }
+
public void broadcastPacket(SubPacket packet, bool sendToSelf)
{
if (sendToSelf)
@@ -953,6 +967,47 @@ namespace FFXIVClassic_Map_Server.Actors
public Equipment getEquipment()
{
return equipment;
+ }
+
+ public byte getInitialTown()
+ {
+ return playerWork.initialTown;
+ }
+
+ public int getFreeQuestSlot()
+ {
+ for (int i = 0; i < questScenario.Length; i++)
+ {
+ if (questScenario[i] == null)
+ return i;
+ }
+
+ return -1;
+ }
+
+ public void addQuest(uint id)
+ {
+ Actor actor = Server.getStaticActors((0xA0F00000 | id));
+ addQuest(actor.actorName);
+ }
+
+ public void addQuest(string name)
+ {
+ Actor actor = Server.getStaticActors(name);
+
+ if (actor == null)
+ return;
+
+ uint id = actor.actorId;
+
+ int freeSlot = getFreeQuestSlot();
+
+ if (freeSlot == -1)
+ return;
+
+ playerWork.questScenario[freeSlot] = id;
+ questScenario[freeSlot] = new Quest(this, playerWork.questScenario[freeSlot], name, null, 0);
+ Database.saveQuest(this, questScenario[freeSlot]);
}
public Quest getQuest(uint id)
@@ -966,6 +1021,28 @@ namespace FFXIVClassic_Map_Server.Actors
return null;
}
+ public Quest getQuest(string name)
+ {
+ for (int i = 0; i < questScenario.Length; i++)
+ {
+ if (questScenario[i] != null && questScenario[i].actorName.ToLower().Equals(name.ToLower()))
+ return questScenario[i];
+ }
+
+ return null;
+ }
+
+ public bool hasQuest(string name)
+ {
+ for (int i = 0; i < questScenario.Length; i++)
+ {
+ if (questScenario[i] != null && questScenario[i].actorName.ToLower().Equals(name.ToLower()))
+ return true;
+ }
+
+ return false;
+ }
+
public bool hasQuest(uint id)
{
for (int i = 0; i < questScenario.Length; i++)
@@ -977,19 +1054,46 @@ namespace FFXIVClassic_Map_Server.Actors
return false;
}
- public void setDirector(string directorType)
+ public int getQuestSlot(uint id)
+ {
+ for (int i = 0; i < questScenario.Length; i++)
+ {
+ if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id))
+ return i;
+ }
+
+ return -1;
+ }
+
+ public void setDirector(string directorType, bool sendPackets)
{
if (directorType.Equals("openingDirector"))
{
- currentDirector = new OpeningDirector(0x46080012);
+ currentDirector = new OpeningDirector(this, 0x46080012);
+ }
+ else if (directorType.Equals("QuestDirectorMan0l001"))
+ {
+ currentDirector = new QuestDirectorMan0l001(this, 0x46080012);
+ }
+ else if (directorType.Equals("QuestDirectorMan0g001"))
+ {
+ currentDirector = new QuestDirectorMan0g001(this, 0x46080012);
+ }
+ else if (directorType.Equals("QuestDirectorMan0u001"))
+ {
+ currentDirector = new QuestDirectorMan0u001(this, 0x46080012);
+ }
+
+ if (sendPackets)
+ {
+ queuePacket(RemoveActorPacket.buildPacket(actorId, 0x46080012));
+ queuePacket(currentDirector.getSpawnPackets(actorId));
+ queuePacket(currentDirector.getInitPackets(actorId));
+ //queuePacket(currentDirector.getSetEventStatusPackets(actorId));
+ //currentDirector.getSpawnPackets(actorId).debugPrintPacket();
+ //currentDirector.getInitPackets(actorId).debugPrintPacket();
}
- queuePacket(RemoveActorPacket.buildPacket(actorId, 0x46080012));
- queuePacket(currentDirector.getSpawnPackets(actorId));
- queuePacket(currentDirector.getInitPackets(actorId));
- // queuePacket(currentDirector.getSetEventStatusPackets(actorId));
- // currentDirector.getSpawnPackets(actorId).debugPrintPacket();
- // currentDirector.getInitPackets(actorId).debugPrintPacket();
}
public Director getDirector()
@@ -1037,22 +1141,32 @@ namespace FFXIVClassic_Map_Server.Actors
public void runEventFunction(string functionName, params object[] parameters)
{
List lParams = LuaUtils.createLuaParamList(parameters);
- SubPacket spacket = RunEventFunctionPacket.buildPacket(actorId, eventCurrentOwner, eventCurrentStarter, functionName, lParams);
+ SubPacket spacket = RunEventFunctionPacket.buildPacket(actorId, currentEventOwner, currentEventName, functionName, lParams);
spacket.debugPrintSubPacket();
queuePacket(spacket);
}
public void endEvent()
{
- SubPacket p = EndEventPacket.buildPacket(actorId, eventCurrentOwner, eventCurrentStarter);
+ SubPacket p = EndEventPacket.buildPacket(actorId, currentEventOwner, currentEventName);
p.debugPrintSubPacket();
queuePacket(p);
- eventCurrentOwner = 0;
- eventCurrentStarter = "";
+ currentEventOwner = 0;
+ currentEventName = "";
eventMenuId = 0;
}
+ public void endCommand()
+ {
+ SubPacket p = EndEventPacket.buildPacket(actorId, currentCommand, currentCommandName);
+ p.debugPrintSubPacket();
+ queuePacket(p);
+
+ currentCommand = 0;
+ currentCommandName = "";
+ }
+
public void setCurrentMenuId(uint id)
{
eventMenuId = id;
@@ -1067,12 +1181,7 @@ namespace FFXIVClassic_Map_Server.Actors
{
//Update Instance
- List instanceUpdatePackets = playerSession.updateInstance(zone.getActorsAroundActor(this, 50));
- foreach (BasePacket bp in instanceUpdatePackets)
- {
- // bp.debugPrintPacket();
- queuePacket(bp);
- }
+ playerSession.updateInstance(zone.getActorsAroundActor(this, 50));
}
diff --git a/FFXIVClassic Map Server/actors/director/Director.cs b/FFXIVClassic Map Server/actors/director/Director.cs
index bc63ec27..4ae68542 100644
--- a/FFXIVClassic Map Server/actors/director/Director.cs
+++ b/FFXIVClassic Map Server/actors/director/Director.cs
@@ -1,5 +1,6 @@
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
using System;
using System.Collections.Generic;
@@ -10,10 +11,12 @@ using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.director
{
class Director : Actor
- {
- public Director(uint id) : base(id)
- {
+ {
+ Player owner;
+ public Director(Player owner, uint id) : base(id)
+ {
+ this.owner = owner;
}
public virtual BasePacket getSpawnPackets(uint playerActorId, uint spawnType)
@@ -37,5 +40,15 @@ namespace FFXIVClassic_Map_Server.actors.director
return BasePacket.createPacket(initProperties.buildPacket(playerActorId, actorId), true, false);
}
+ public void onTalked(Npc npc)
+ {
+ LuaEngine.doDirectorOnTalked(this, owner, npc);
+ }
+
+ public void onCommand(Command command)
+ {
+ LuaEngine.doDirectorOnCommand(this, owner, command);
+ }
+
}
}
diff --git a/FFXIVClassic Map Server/actors/director/OpeningDirector.cs b/FFXIVClassic Map Server/actors/director/OpeningDirector.cs
index 6c45066b..67d35c6c 100644
--- a/FFXIVClassic Map Server/actors/director/OpeningDirector.cs
+++ b/FFXIVClassic Map Server/actors/director/OpeningDirector.cs
@@ -1,4 +1,5 @@
using FFXIVClassic_Lobby_Server.packets;
+using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
using System;
@@ -11,12 +12,15 @@ namespace FFXIVClassic_Map_Server.actors.director
{
class OpeningDirector : Director
{
- public OpeningDirector(uint id) : base(id)
+ public OpeningDirector(Player player, uint id) : base(player, id)
{
this.displayNameId = 0;
- this.customDisplayName = "openingDire";
+ this.customDisplayName = String.Format("openingDire_{0}_{1}", player.zone.zoneName, "04");
+
+ this.actorName = String.Format("openingDire_{0}_{1}@{2:x3}{3:x2}", player.zone.zoneName, "04", player.zoneId, 0);
+
+ this.actorName = this.actorName.Replace("Battle", "Btl");
- this.actorName = "openingDire";
this.className = "OpeningDirector";
this.eventConditions = new EventList();
diff --git a/FFXIVClassic Map Server/actors/director/WeatherDirector.cs b/FFXIVClassic Map Server/actors/director/WeatherDirector.cs
index 658776de..f560a902 100644
--- a/FFXIVClassic Map Server/actors/director/WeatherDirector.cs
+++ b/FFXIVClassic Map Server/actors/director/WeatherDirector.cs
@@ -15,8 +15,8 @@ namespace FFXIVClassic_Map_Server.Actors
{
private uint weatherId;
- public WeatherDirector(uint weatherId)
- : base(0x5FF80003)
+ public WeatherDirector(Player player, uint weatherId)
+ : base(player, 0x5FF80003)
{
this.weatherId = weatherId;
diff --git a/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0g001.cs b/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0g001.cs
new file mode 100644
index 00000000..51908902
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0g001.cs
@@ -0,0 +1,41 @@
+using FFXIVClassic_Lobby_Server.packets;
+using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.lua;
+using FFXIVClassic_Map_Server.packets.send.actor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FFXIVClassic_Map_Server.actors.director
+{
+ class QuestDirectorMan0g001 : Director
+ {
+ public QuestDirectorMan0g001(Player player, uint id)
+ : base(player, id)
+ {
+ this.displayNameId = 0;
+ this.customDisplayName = "questDirect_fst0Btl03_01";
+
+ this.actorName = "questDirect_fst0Btl03_01@0A615";
+ this.className = "QuestDirectorMan0g001";
+
+ this.eventConditions = new EventList();
+
+ List noticeEventList = new List();
+
+ noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
+ noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
+
+ this.eventConditions.noticeEventConditions = noticeEventList;
+ }
+
+ public override SubPacket createScriptBindPacket(uint playerActorId)
+ {
+ List lParams;
+ lParams = LuaUtils.createLuaParamList("/Director/Quest/QuestDirectorMan0g001", false, false, false, false, false, 0x753A);
+ return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams);
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0l001.cs b/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0l001.cs
new file mode 100644
index 00000000..2d5d1aec
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0l001.cs
@@ -0,0 +1,41 @@
+using FFXIVClassic_Lobby_Server.packets;
+using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.lua;
+using FFXIVClassic_Map_Server.packets.send.actor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FFXIVClassic_Map_Server.actors.director
+{
+ class QuestDirectorMan0l001 : Director
+ {
+ public QuestDirectorMan0l001(Player player, uint id)
+ : base(player, id)
+ {
+ this.displayNameId = 0;
+ this.customDisplayName = "questDirect_ocn0Btl02_01";
+
+ this.actorName = "questDirect_ocn0Btl02_01@0C196";
+ this.className = "QuestDirectorMan0l001";
+
+ this.eventConditions = new EventList();
+
+ List noticeEventList = new List();
+
+ noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
+ noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
+
+ this.eventConditions.noticeEventConditions = noticeEventList;
+ }
+
+ public override SubPacket createScriptBindPacket(uint playerActorId)
+ {
+ List lParams;
+ lParams = LuaUtils.createLuaParamList("/Director/Quest/QuestDirectorMan0l001", false, false, false, false, false, 0x7532);
+ return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams);
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0u001.cs b/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0u001.cs
new file mode 100644
index 00000000..2a860b05
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/director/quest/QuestDirectorMan0u001.cs
@@ -0,0 +1,41 @@
+using FFXIVClassic_Lobby_Server.packets;
+using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.lua;
+using FFXIVClassic_Map_Server.packets.send.actor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FFXIVClassic_Map_Server.actors.director
+{
+ class QuestDirectorMan0u001 : Director
+ {
+ public QuestDirectorMan0u001(Player player, uint id)
+ : base(player, id)
+ {
+ this.displayNameId = 0;
+ this.customDisplayName = "questDirect_wil0Btl01_01";
+
+ this.actorName = "questDirect_wil0Btl01_01@0A615";
+ this.className = "QuestDirectorMan0u001";
+
+ this.eventConditions = new EventList();
+
+ List noticeEventList = new List();
+
+ noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
+ noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
+
+ this.eventConditions.noticeEventConditions = noticeEventList;
+ }
+
+ public override SubPacket createScriptBindPacket(uint playerActorId)
+ {
+ List lParams;
+ lParams = LuaUtils.createLuaParamList("/Director/Quest/QuestDirectorMan0u001", false, false, false, false, false, 0x757F);
+ return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams);
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/quest/Quest.cs b/FFXIVClassic Map Server/actors/quest/Quest.cs
index c125548e..8a6469e5 100644
--- a/FFXIVClassic Map Server/actors/quest/Quest.cs
+++ b/FFXIVClassic Map Server/actors/quest/Quest.cs
@@ -1,4 +1,6 @@
-using FFXIVClassic_Lobby_Server.common;
+using FFXIVClassic_Lobby_Server;
+using FFXIVClassic_Lobby_Server.common;
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -6,6 +8,7 @@ namespace FFXIVClassic_Map_Server.Actors
{
class Quest : Actor
{
+ private Player owner;
private int currentPhase = 0;
private uint questFlags = 0;
private Dictionary questData = new Dictionary();
@@ -13,17 +16,27 @@ namespace FFXIVClassic_Map_Server.Actors
public Quest(uint actorID, string name)
: base(actorID)
{
- actorName = name;
+ actorName = name;
}
- public void InitQuestData(string dataName, object initialValue)
+ public Quest(Player owner, uint actorID, string name, string questDataJson, uint questFlags)
+ : base(actorID)
{
- questData[dataName] = initialValue;
- }
+ this.owner = owner;
+ actorName = name;
+ this.questFlags = questFlags;
- public void UpdateQuestData(string dataName, object data)
- {
- if (questData.ContainsKey(dataName))
+ if (questDataJson != null)
+ this.questData = JsonConvert.DeserializeObject>(questDataJson);
+ else
+ questData = null;
+
+ if (questData == null)
+ questData = new Dictionary();
+ }
+
+ public void SetQuestData(string dataName, object data)
+ {
questData[dataName] = data;
//Inform update
@@ -37,11 +50,21 @@ namespace FFXIVClassic_Map_Server.Actors
return null;
}
+ public void ClearQuestData()
+ {
+ questData.Clear();
+ }
+
public uint GetQuestId()
{
return actorId;
}
+ public void ClearQuestFlags()
+ {
+ questFlags = 0;
+ }
+
public void SetQuestFlag(int bitIndex, bool value)
{
if (bitIndex >= 32)
@@ -68,7 +91,7 @@ namespace FFXIVClassic_Map_Server.Actors
return false;
}
else
- return (questFlags & (1 << bitIndex)) == 1;
+ return (questFlags & (1 << bitIndex)) == (1 << bitIndex);
}
public int GetPhase()
@@ -81,5 +104,20 @@ namespace FFXIVClassic_Map_Server.Actors
currentPhase++;
}
+ public uint GetQuestFlags()
+ {
+ return questFlags;
+ }
+
+ public string GetSerializedQuestData()
+ {
+ return JsonConvert.SerializeObject(questData, Formatting.Indented);
+ }
+
+ public void SaveData()
+ {
+ Database.saveQuest(owner, this);
+ }
+
}
}
diff --git a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
index 455448dc..2a966f81 100644
--- a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
+++ b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
@@ -2,6 +2,7 @@
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
using System;
using System.Collections.Generic;
@@ -112,7 +113,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
}
- public List updateInstance(List list)
+ public void updateInstance(List list)
{
List basePackets = new List();
List removeActorSubpackets = new List();
@@ -123,14 +124,11 @@ namespace FFXIVClassic_Map_Server.dataobjects
{
if (!list.Contains(actorInstanceList[i]))
{
- removeActorSubpackets.Add(RemoveActorPacket.buildPacket(playerActor.actorId, actorInstanceList[i].actorId));
+ getActor().queuePacket(RemoveActorPacket.buildPacket(playerActor.actorId, actorInstanceList[i].actorId));
actorInstanceList.RemoveAt(i);
}
}
- if (removeActorSubpackets.Count != 0)
- basePackets.Add(BasePacket.createPacket(removeActorSubpackets, true, false));
-
//Add new actors or move
for (int i = 0; i < list.Count; i++)
{
@@ -141,21 +139,22 @@ namespace FFXIVClassic_Map_Server.dataobjects
if (actorInstanceList.Contains(actor))
{
- posUpdateSubpackets.Add(actor.createPositionUpdatePacket(playerActor.actorId));
+ getActor().queuePacket(actor.createPositionUpdatePacket(playerActor.actorId));
}
else
{
- basePackets.Add(actor.getSpawnPackets(playerActor.actorId, 1));
- basePackets.Add(actor.getInitPackets(playerActor.actorId));
- basePackets.Add(actor.getSetEventStatusPackets(playerActor.actorId));
+ getActor().queuePacket(actor.getSpawnPackets(playerActor.actorId, 1));
+ getActor().queuePacket(actor.getInitPackets(playerActor.actorId));
+ getActor().queuePacket(actor.getSetEventStatusPackets(playerActor.actorId));
actorInstanceList.Add(actor);
+
+ if (actor is Npc)
+ {
+ LuaEngine.doActorOnSpawn(getActor(), (Npc)actor);
+ }
}
}
- if (posUpdateSubpackets.Count > 0)
- basePackets.Add(BasePacket.createPacket(posUpdateSubpackets, true, false));
-
- return basePackets;
}
diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs
index a9d18ee5..89d2c272 100644
--- a/FFXIVClassic Map Server/lua/LuaEngine.cs
+++ b/FFXIVClassic Map Server/lua/LuaEngine.cs
@@ -1,4 +1,5 @@
using FFXIVClassic_Lobby_Server;
+using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.Actors;
@@ -31,7 +32,7 @@ namespace FFXIVClassic_Map_Server.lua
UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic;
}
- public static List doActorOnInstantiate(Player player, Actor target)
+ public static List doActorInstantiate(Player player, Actor target)
{
string luaPath;
@@ -39,23 +40,19 @@ namespace FFXIVClassic_Map_Server.lua
{
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.getName());
if (File.Exists(luaPath))
- {
- Script script = new Script();
- ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
- script.Globals["getStaticActor"] = (Func)Server.getStaticActors;
- script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor;
- script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata;
- script.DoFile(luaPath);
- DynValue result = script.Call(script.Globals["onInstantiate"], target);
+ {
+ Script script = loadScript(luaPath);
+
+ if (script == null)
+ return null;
+
+ DynValue result = script.Call(script.Globals["init"], target);
List lparams = LuaUtils.createLuaParamList(result);
return lparams;
}
else
{
- List sendError = new List();
- sendError.Add(EndEventPacket.buildPacket(player.actorId, player.eventCurrentOwner, player.eventCurrentStarter));
- player.sendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", String.Format("ERROR: Could not find script for actor {0}.", target.getName()));
- player.playerSession.queuePacket(BasePacket.createPacket(sendError, true, false));
+ SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.getName()));
return null;
}
}
@@ -80,13 +77,10 @@ namespace FFXIVClassic_Map_Server.lua
if (File.Exists(luaPath))
{
- Script script = new Script();
- ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
- script.Globals["getWorldManager"] = (Func)Server.GetWorldManager;
- script.Globals["getStaticActor"] = (Func)Server.getStaticActors;
- script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor;
- script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata;
- script.DoFile(luaPath);
+ Script script = loadScript(luaPath);
+
+ if (script == null)
+ return;
//Have to do this to combine LuaParams
List