From d7166cadc00581fd91f71bdf4813d3a9ab998b71 Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Thu, 18 Aug 2016 22:58:09 -0500 Subject: [PATCH 1/7] Added GM Ticket support on the DB --- FFXIVClassic Map Server/Database.cs | 161 ++++++++++++++++++ .../FFXIVClassic Map Server.csproj | 1 + FFXIVClassic Map Server/PacketProcessor.cs | 17 +- 3 files changed, 171 insertions(+), 8 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 823e8b13..49fc2082 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -10,6 +10,7 @@ using FFXIVClassic_Map_Server.packets.send.player; using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.actors.chara.player; +using FFXIVClassic_Map_Server.packets.receive.supportdesk; namespace FFXIVClassic_Map_Server { @@ -1246,6 +1247,166 @@ namespace FFXIVClassic_Map_Server return cheevosPacket.BuildPacket(player.actorId); } + public static void SaveSupportTicket(GMSupportTicketPacket gmTicket) + { + 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 supportdesk_tickets + (id, title, body, langCode) + VALUES + (@id, @title, @body, @langCode) + ON DUPLICATE KEY UPDATE + questData = @questData, questFlags = @questFlags + "; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", gmTicket.ticketIssueIndex); + cmd.Parameters.AddWithValue("@title", gmTicket.ticketTitle); + cmd.Parameters.AddWithValue("@body", gmTicket.ticketBody); + cmd.Parameters.AddWithValue("@langCode", gmTicket.langCode); + + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + } + + public static string[] getFAQNames(uint lanCode=1) + { + string[] faqs = null; + List raw = new List(); + 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(); + + string query = @" + SELECT + id, + label, + sort, + FROM supportdesk_faqs + ORDER BY sort"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + uint id = reader.GetUInt32(0); + string label = reader.GetString(1); + raw.Add(label); + } + } + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + faqs = raw.ToArray(); + } + } + return faqs; + } + + public static string getFAQBody(uint id, uint lanCode=1) + { + string body = string.Empty; + 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(); + + string query = @" + SELECT + body + FROM supportdesk_faqs + WHERE id=" + id; + + MySqlCommand cmd = new MySqlCommand(query, conn); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + body = reader.GetString(2); + } + } + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + return body; + } + + public static string[] getIssues(uint lanCode = 1) + { + string[] issues = null; + List raw = new List(); + 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(); + + string query = @" + SELECT + id, + title, + sort, + FROM supportdesk_issues + ORDER BY sort"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + uint id = reader.GetUInt32(0); + string label = reader.GetString(1); + raw.Add(label); + } + } + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + issues = raw.ToArray(); + } + } + return issues; + } } } diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 2bd335eb..740eefb9 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -123,6 +123,7 @@ + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 590315c8..b999b639 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -17,8 +17,8 @@ using FFXIVClassic_Map_Server.packets.receive.recruitment; using FFXIVClassic_Map_Server.packets.send.recruitment; using FFXIVClassic_Map_Server.packets.receive.events; using FFXIVClassic_Map_Server.lua; -using FFXIVClassic_Map_Server.Actors; - +using FFXIVClassic_Map_Server.Actors; + namespace FFXIVClassic_Map_Server { class PacketProcessor @@ -374,17 +374,17 @@ namespace FFXIVClassic_Map_Server //Request for FAQ/Info List case 0x01D0: FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data); - client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, new string[] { "Testing FAQ1", "Coded style!" }), true, false)); + client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, Database.getFAQNames(faqRequest.langCode)), true, false)); break; //Request for body of a faq/info selection case 0x01D1: FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data); - client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, "HERE IS A GIANT BODY. Nothing else to say!"), true, false)); + client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, Database.getFAQBody(faqBodyRequest.faqIndex, faqBodyRequest.langCode)), true, false)); break; //Request issue list case 0x01D2: GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data); - client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false)); + client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, Database.getIssues(issuesRequest.langCode)), true, false)); break; //Request if GM ticket exists case 0x01D3: @@ -392,12 +392,13 @@ namespace FFXIVClassic_Map_Server break; //Request for GM response message case 0x01D4: - client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false)); + client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "Ticket Title", "Enter your Help request here."), true, false)); break; //GM Ticket Sent case 0x01D5: - GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data); - Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody); + GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data); + Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody); + Database.SaveSupportTicket(gmTicket); client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, true), true, false)); break; //Request to end ticket From 7c9077beec9dc206afda0c7dc8d148d5d57ec7ac Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Thu, 18 Aug 2016 22:59:23 -0500 Subject: [PATCH 2/7] Added support for Linux/OSX Paths --- FFXIVClassic Map Server/actors/chara/npc/Npc.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index e711dbd0..e869b067 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -48,8 +48,8 @@ namespace FFXIVClassic_Map_Server.Actors LoadNpcAppearance(actorClass.actorClassId); - this.classPath = actorClass.classPath; - className = classPath.Substring(classPath.LastIndexOf("/")+1); + className = actorClass.classPath.Substring(actorClass.classPath.LastIndexOf("/") + 1); + this.classPath = String.Format("{0}/{1}", actorClass.classPath.Substring(0, actorClass.classPath.LastIndexOf('/')).ToLower(), className); charaWork.battleSave.potencial = 1.0f; From 270d4ce43670742d442462118e11f1880fe49aeb Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Thu, 18 Aug 2016 23:36:04 -0500 Subject: [PATCH 3/7] Fixed MySQL Syntax issues --- FFXIVClassic Map Server/Database.cs | 86 ++++++++++++++--------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 49fc2082..6c210395 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -30,10 +30,10 @@ namespace FFXIVClassic_Map_Server cmd.Parameters.AddWithValue("@sessionId", sessionId); using (MySqlDataReader Reader = cmd.ExecuteReader()) { - while (Reader.Read()) - { - id = Reader.GetUInt32("userId"); - } + while (Reader.Read()) + { + id = Reader.GetUInt32("userId"); + } } } catch (MySqlException e) @@ -43,11 +43,11 @@ namespace FFXIVClassic_Map_Server finally { conn.Dispose(); - } + } } return id; } - + public static DBWorld GetServer(uint serverId) { 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))) @@ -56,7 +56,7 @@ namespace FFXIVClassic_Map_Server try { conn.Open(); - world = conn.Query("SELECT * FROM servers WHERE id=@ServerId", new {ServerId = serverId}).SingleOrDefault(); + world = conn.Query("SELECT * FROM servers WHERE id=@ServerId", new { ServerId = serverId }).SingleOrDefault(); } catch (MySqlException e) { @@ -69,7 +69,7 @@ namespace FFXIVClassic_Map_Server return world; } - } + } public static List GetNpcList() { @@ -99,7 +99,7 @@ namespace FFXIVClassic_Map_Server 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 gamedataItems = new Dictionary(); - + try { conn.Open(); @@ -145,7 +145,7 @@ namespace FFXIVClassic_Map_Server { conn.Dispose(); } - + return gamedataItems; } } @@ -244,7 +244,7 @@ namespace FFXIVClassic_Map_Server public static void SavePlayerPosition(Player player) { - string query; + 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))) @@ -262,7 +262,7 @@ namespace FFXIVClassic_Map_Server currentZoneId = @zoneId WHERE id = @charaId "; - + cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@charaId", player.actorId); cmd.Parameters.AddWithValue("@x", player.positionX); @@ -371,9 +371,9 @@ namespace FFXIVClassic_Map_Server } public static void LoadPlayerCharacter(Player player) - { + { string query; - MySqlCommand cmd; + 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))) { @@ -404,7 +404,7 @@ namespace FFXIVClassic_Map_Server restBonus, achievementPoints, playTime - FROM characters WHERE id = @charId"; + FROM characters WHERE id = @charId"; cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@charId", player.actorId); @@ -437,7 +437,7 @@ namespace FFXIVClassic_Map_Server player.playTime = reader.GetUInt32(19); } } - + //Get class levels query = @" SELECT @@ -470,7 +470,7 @@ namespace FFXIVClassic_Map_Server { if (reader.Read()) { - player.charaWork.battleSave.skillLevel[Player.CLASSID_PUG-1] = reader.GetInt16("pug"); + player.charaWork.battleSave.skillLevel[Player.CLASSID_PUG - 1] = reader.GetInt16("pug"); player.charaWork.battleSave.skillLevel[Player.CLASSID_GLA - 1] = reader.GetInt16("gla"); player.charaWork.battleSave.skillLevel[Player.CLASSID_MRD - 1] = reader.GetInt16("mrd"); player.charaWork.battleSave.skillLevel[Player.CLASSID_ARC - 1] = reader.GetInt16("arc"); @@ -519,7 +519,7 @@ namespace FFXIVClassic_Map_Server player.charaWork.parameterSave.state_mainSkillLevel = player.charaWork.battleSave.skillLevel[reader.GetByte(4) - 1]; } } - + //Load appearance query = @" SELECT @@ -662,7 +662,7 @@ namespace FFXIVClassic_Map_Server player.timers[i] = reader.GetUInt32(i); } } - + //Load Hotbar query = @" SELECT @@ -675,11 +675,11 @@ namespace FFXIVClassic_Map_Server cmd.Parameters.AddWithValue("@charId", player.actorId); cmd.Parameters.AddWithValue("@classId", player.charaWork.parameterSave.state_mainSkill[0]); using (MySqlDataReader reader = cmd.ExecuteReader()) - { + { while (reader.Read()) { int index = reader.GetUInt16(0); - player.charaWork.command[index+32] = reader.GetUInt32(1); + player.charaWork.command[index + 32] = reader.GetUInt32(1); player.charaWork.parameterSave.commandSlot_recastTime[index] = reader.GetUInt32(2); } } @@ -692,7 +692,7 @@ namespace FFXIVClassic_Map_Server questData, questFlags FROM characters_quest_scenario WHERE characterId = @charId"; - + cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@charId", player.actorId); using (MySqlDataReader reader = cmd.ExecuteReader()) @@ -777,7 +777,7 @@ namespace FFXIVClassic_Map_Server { int npcLSId = reader.GetUInt16(0); player.playerWork.npcLinkshellChatCalling[npcLSId] = reader.GetBoolean(1); - player.playerWork.npcLinkshellChatExtra[npcLSId] = reader.GetBoolean(2); + player.playerWork.npcLinkshellChatExtra[npcLSId] = reader.GetBoolean(2); } } @@ -952,7 +952,7 @@ namespace FFXIVClassic_Map_Server cmd.Parameters.AddWithValue("@type", type); using (MySqlDataReader reader = cmd.ExecuteReader()) - { + { while (reader.Read()) { uint uniqueId = reader.GetUInt32(0); @@ -999,7 +999,7 @@ namespace FFXIVClassic_Map_Server { conn.Open(); - + string query = @" INSERT INTO server_items @@ -1017,7 +1017,7 @@ namespace FFXIVClassic_Map_Server "; MySqlCommand cmd2 = new MySqlCommand(query2, conn); - + cmd.Parameters.AddWithValue("@itemId", itemId); cmd.Parameters.AddWithValue("@quality", quality); cmd.Parameters.AddWithValue("@itemType", itemType); @@ -1053,12 +1053,12 @@ namespace FFXIVClassic_Map_Server { conn.Open(); - string query = @" + string query = @" UPDATE characters_inventory SET quantity = @quantity WHERE characterId = @charId AND slot = @slot AND inventoryType = @type; "; - + MySqlCommand cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@charId", player.actorId); cmd.Parameters.AddWithValue("@quantity", quantity); @@ -1098,7 +1098,7 @@ namespace FFXIVClassic_Map_Server DELETE FROM server_items WHERE id = @serverItemId; - "; + "; MySqlCommand cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@charId", player.actorId); @@ -1168,7 +1168,7 @@ namespace FFXIVClassic_Map_Server try { conn.Open(); - + //Load Last 5 Completed string query = @" SELECT @@ -1183,7 +1183,7 @@ namespace FFXIVClassic_Map_Server int count = 0; while (reader.Read()) { - uint id = reader.GetUInt32(0); + uint id = reader.GetUInt32(0); latestAchievements[count++] = id; } } @@ -1210,7 +1210,7 @@ namespace FFXIVClassic_Map_Server try { conn.Open(); - + string query = @" SELECT packetOffsetId FROM characters_achievements @@ -1222,7 +1222,7 @@ namespace FFXIVClassic_Map_Server using (MySqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) - { + { uint offset = reader.GetUInt32(0); if (offset < 0 || offset >= cheevosPacket.achievementFlags.Length) @@ -1230,7 +1230,7 @@ namespace FFXIVClassic_Map_Server Program.Log.Error("SQL Error; achievement flag offset id out of range: " + offset); continue; } - cheevosPacket.achievementFlags[offset] = true; + cheevosPacket.achievementFlags[offset] = true; } } } @@ -1262,10 +1262,7 @@ namespace FFXIVClassic_Map_Server INSERT INTO supportdesk_tickets (id, title, body, langCode) VALUES - (@id, @title, @body, @langCode) - ON DUPLICATE KEY UPDATE - questData = @questData, questFlags = @questFlags - "; + (@id, @title, @body, @langCode)"; cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@id", gmTicket.ticketIssueIndex); @@ -1286,7 +1283,7 @@ namespace FFXIVClassic_Map_Server } } - public static string[] getFAQNames(uint lanCode=1) + public static string[] getFAQNames(uint lanCode = 1) { string[] faqs = null; List raw = new List(); @@ -1300,7 +1297,7 @@ namespace FFXIVClassic_Map_Server SELECT id, label, - sort, + sort FROM supportdesk_faqs ORDER BY sort"; @@ -1329,7 +1326,7 @@ namespace FFXIVClassic_Map_Server return faqs; } - public static string getFAQBody(uint id, uint lanCode=1) + public static string getFAQBody(uint id, uint lanCode = 1) { string body = string.Empty; 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))) @@ -1342,15 +1339,16 @@ namespace FFXIVClassic_Map_Server SELECT body FROM supportdesk_faqs - WHERE id=" + id; + WHERE id=@id"; MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", id); using (MySqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { - body = reader.GetString(2); + body = reader.GetString(0); } } } @@ -1380,7 +1378,7 @@ namespace FFXIVClassic_Map_Server SELECT id, title, - sort, + sort FROM supportdesk_issues ORDER BY sort"; From 4f3828e5942413bd526c5ace836c1ec3d0fe5da0 Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Fri, 19 Aug 2016 00:10:07 -0500 Subject: [PATCH 4/7] Added MySQL tables for Support Desk --- sql/supportdesk_faqs.sql | 53 ++++++++++++++++++++++++++++++++++++ sql/supportdesk_issues.sql | 54 +++++++++++++++++++++++++++++++++++++ sql/supportdesk_tickets.sql | 52 +++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 sql/supportdesk_faqs.sql create mode 100644 sql/supportdesk_issues.sql create mode 100644 sql/supportdesk_tickets.sql diff --git a/sql/supportdesk_faqs.sql b/sql/supportdesk_faqs.sql new file mode 100644 index 00000000..e623ea27 --- /dev/null +++ b/sql/supportdesk_faqs.sql @@ -0,0 +1,53 @@ +-- MySQL dump 10.13 Distrib 5.7.13, for Linux (x86_64) +-- +-- Host: localhost Database: ffxiv +-- ------------------------------------------------------ +-- Server version 5.7.13-0ubuntu0.16.04.2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `supportdesk_faqs` +-- + +DROP TABLE IF EXISTS `supportdesk_faqs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `supportdesk_faqs` ( + `id` int(10) NOT NULL, + `label` varchar(50) NOT NULL, + `body` varchar(50) NOT NULL, + `sort` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `supportdesk_faqs` +-- + +LOCK TABLES `supportdesk_faqs` WRITE; +/*!40000 ALTER TABLE `supportdesk_faqs` DISABLE KEYS */; +INSERT INTO `supportdesk_faqs` VALUES (1,'Testing','Testy Test FAQ!',1); +/*!40000 ALTER TABLE `supportdesk_faqs` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-08-19 5:05:33 diff --git a/sql/supportdesk_issues.sql b/sql/supportdesk_issues.sql new file mode 100644 index 00000000..09acaba5 --- /dev/null +++ b/sql/supportdesk_issues.sql @@ -0,0 +1,54 @@ +-- MySQL dump 10.13 Distrib 5.7.13, for Linux (x86_64) +-- +-- Host: localhost Database: ffxiv +-- ------------------------------------------------------ +-- Server version 5.7.13-0ubuntu0.16.04.2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `supportdesk_issues` +-- + +DROP TABLE IF EXISTS `supportdesk_issues`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `supportdesk_issues` ( + `id` int(11) NOT NULL, + `title` varchar(50) NOT NULL, + `sort` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `supportdesk_issues` +-- + +LOCK TABLES `supportdesk_issues` WRITE; +/*!40000 ALTER TABLE `supportdesk_issues` DISABLE KEYS */; +INSERT INTO `supportdesk_issues` VALUES (1,'Report Harassment',1); +INSERT INTO `supportdesk_issues` VALUES (2,'Report Cheating',2); +INSERT INTO `supportdesk_issues` VALUES (3,'Leave Suggestion',3); +/*!40000 ALTER TABLE `supportdesk_issues` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-08-19 5:05:51 diff --git a/sql/supportdesk_tickets.sql b/sql/supportdesk_tickets.sql new file mode 100644 index 00000000..3f3d9c9e --- /dev/null +++ b/sql/supportdesk_tickets.sql @@ -0,0 +1,52 @@ +-- MySQL dump 10.13 Distrib 5.7.13, for Linux (x86_64) +-- +-- Host: localhost Database: ffxiv +-- ------------------------------------------------------ +-- Server version 5.7.13-0ubuntu0.16.04.2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `supportdesk_tickets` +-- + +DROP TABLE IF EXISTS `supportdesk_tickets`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `supportdesk_tickets` ( + `id` int(20) NOT NULL, + `title` varchar(100) NOT NULL, + `body` varchar(100) NOT NULL, + `langCode` varchar(10) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `supportdesk_tickets` +-- + +LOCK TABLES `supportdesk_tickets` WRITE; +/*!40000 ALTER TABLE `supportdesk_tickets` DISABLE KEYS */; +/*!40000 ALTER TABLE `supportdesk_tickets` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-08-19 5:06:23 From fb18c1fbe47a7d05063dbb3d64f4872361da9d89 Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Fri, 19 Aug 2016 14:40:43 -0500 Subject: [PATCH 5/7] Added DB Support for Chocobo Lenders --- FFXIVClassic Map Server/Database.cs | 38 ++++++++++++++ .../actors/chara/player/Player.cs | 17 +++++++ .../npc/populace/PopulaceChocoboLender.lua | 51 ++++++++++++++++--- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 6c210395..1860ba61 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -1406,5 +1406,43 @@ namespace FFXIVClassic_Map_Server } return issues; } + + public static void IssuePlayerChocobo(Player player, byte appearanceId, string name) + { + 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_chocobo + (characterId, hasChocobo, chocoboAppearance, chocoboName) + VALUES + (@characterId, @hasChocobo, @chocoboAppearance, @chocoboName) + ON DUPLICATE KEY UPDATE + hasChocobo=@hasChocobo, chocoboAppearance=@chocoboAppearance, chocoboName=@chocoboName"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@characterId", player.actorId); + cmd.Parameters.AddWithValue("@hasChocobo", 1); + cmd.Parameters.AddWithValue("@chocoboAppearance", appearanceId); + cmd.Parameters.AddWithValue("@chocoboName", name); + + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + } } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 6a0f5a22..98cc0cc0 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -704,6 +704,11 @@ namespace FFXIVClassic_Map_Server.Actors QueuePacket(SetMusicPacket.BuildPacket(actorId, musicId, 1)); } + public void ChangeMusicWithEffect(ushort musicId, ushort effect) + { + QueuePacket(SetMusicPacket.BuildPacket(actorId, musicId, effect)); + } + public void SendChocoboAppearance() { BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance), true); @@ -1263,5 +1268,17 @@ namespace FFXIVClassic_Map_Server.Actors } + public void issueChocobo(byte appearanceId, string name) + { + Database.IssuePlayerChocobo(this, appearanceId, name); + hasChocobo = true; + chocoboAppearance = appearanceId; + chocoboName = name; + } + + public void changeChocoboAppearance(int appearanceId) + { + + } } } diff --git a/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua b/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua index 0440d6da..62ba4f81 100644 --- a/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua +++ b/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua @@ -21,11 +21,50 @@ end function onEventStarted(player, npc, triggerName) - --callClientFunction(player, "eventTalkWelcome", player); - callClientFunction(player, "eventAskMainMenu", player, 20, true, true, true, true, 4); - callClientFunction(player, "eventTalkMyChocobo", player); - callClientFunction(player, "eventSetChocoboName", false); - callClientFunction(player, "eventAfterChocoboName", player); - + local curLevel = 20; + local hasIssuance = true; + local hasChocobo = player.hasChocobo; + + if (player.isGM and hasChocobo == false) then + hasIssuance = true; + end + + local rentPrice = 800; + local playerFunds = 0; --TODO: pull character's money + local hasFunds = (playerFunds >= rentPrice); + + callClientFunction(player, "eventTalkWelcome", player); + menuChoice = callClientFunction(player, "eventAskMainMenu", player, curLevel, hasFunds, hasIssuance, hasChocobo, hasChocobo, 4); + + if (menuChoice == 1) then -- Issuance option + callClientFunction(player, "eventTalkMyChocobo", player); + nameResponse = callClientFunction(player, "eventSetChocoboName", false); + + if (nameResponse == "") then -- Cancel Chocobo naming + callClientFunction(player, "eventCancelChocoboName", player); + end + + appearance = 1; -- TODO: pull correct appearance based on GC + --player:issueChocobo(appearance, nameResponse); + if (nameResponse ~= "") then -- Successfully named Chocobo + callClientFunction(player, "eventAfterChocoboName", player); + end + elseif(menuChoice == 2 and hasChocobo) then -- Summon Bird + player:ChangeMusic(83); + player:SendChocoboAppearance(); + player:SendGameMessage(player, worldMaster, 26001, 0x20); + player:SetMountState(1); + elseif(menuChoice == 3) then -- Change Barding + callClientFunction(player, "eventTalkStepBreak", player); + elseif(menuChoice == 5) then -- Rent Bird + if (hasFunds == false) then -- Not enough money + -- Do not enough money action?? + else + --Issue rental chocobo + end + else + callClientFunction(player, "eventTalkStepBreak", player); + end + player:EndEvent(); end \ No newline at end of file From 46350a0724f216f2a44a151aa6cc6ce88071a4c7 Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Fri, 19 Aug 2016 16:32:14 -0500 Subject: [PATCH 6/7] Fixed Bugs --- FFXIVClassic Map Server/actors/area/Area.cs | 708 ++--- .../actors/chara/player/Player.cs | 2500 ++++++++--------- FFXIVClassic Map Server/lua/LuaPlayer.cs | 5 + 3 files changed, 1604 insertions(+), 1609 deletions(-) diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index f82ff5a2..04e6be4f 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -1,358 +1,358 @@ -using FFXIVClassic_Map_Server; -using FFXIVClassic.Common; -using FFXIVClassic_Map_Server.packets; -using FFXIVClassic_Map_Server.actors.area; -using FFXIVClassic_Map_Server.actors.chara.npc; -using FFXIVClassic_Map_Server.dataobjects; -using FFXIVClassic_Map_Server.dataobjects.chara; -using FFXIVClassic_Map_Server.lua; -using FFXIVClassic_Map_Server.packets.send.actor; -using MoonSharp.Interpreter; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using FFXIVClassic_Map_Server; +using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.packets; +using FFXIVClassic_Map_Server.actors.area; +using FFXIVClassic_Map_Server.actors.chara.npc; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.dataobjects.chara; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.packets.send.actor; +using MoonSharp.Interpreter; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using FFXIVClassic_Map_Server.packets.send; -namespace FFXIVClassic_Map_Server.Actors -{ - class Area : Actor - { - public string zoneName; - public ushort regionId; - public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid; - public ushort weatherNormal, weatherCommon, weatherRare; - public ushort bgmDay, bgmNight, bgmBattle; - - protected string classPath; - - public int boundingGridSize = 50; - public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000; - protected int numXBlocks, numYBlocks; - protected int halfWidth, halfHeight; - - protected List mSpawnLocations = new List(); - protected Dictionary mActorList = new Dictionary(); - protected List[,] mActorBlock; - - LuaScript areaScript; - - public Area(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid) - : base(id) - { - - this.zoneName = zoneName; - this.regionId = regionId; - this.canStealth = canStealth; - this.isIsolated = isIsolated; - this.isInn = isInn; - this.canRideChocobo = canRideChocobo; - this.isInstanceRaid = isInstanceRaid; - - this.bgmDay = bgmDay; - this.bgmNight = bgmNight; - this.bgmBattle = bgmBattle; - - this.displayNameId = 0; - this.customDisplayName = "_areaMaster"; - this.actorName = String.Format("_areaMaster@{0:X5}",id<<8); - - this.className = className; - - numXBlocks = (maxX - minX) / boundingGridSize; - numYBlocks = (maxY - minY) / boundingGridSize; - mActorBlock = new List[numXBlocks, numYBlocks]; - halfWidth = numXBlocks / 2; - halfHeight = numYBlocks / 2; - - for (int y = 0; y < numYBlocks; y++) - { - for (int x = 0; x < numXBlocks; x++ ) - { - mActorBlock[x, y] = new List(); - } - } - - } - - public override SubPacket CreateScriptBindPacket(uint playerActorId) - { - List lParams; - lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false); - return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, "ZoneDefault", lParams); - } - - public override BasePacket GetSpawnPackets(uint playerActorId) - { - List subpackets = new List(); - subpackets.Add(CreateAddActorPacket(playerActorId, 0)); - subpackets.Add(CreateSpeedPacket(playerActorId)); - subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1)); - subpackets.Add(CreateNamePacket(playerActorId)); - subpackets.Add(CreateStatePacket(playerActorId)); - subpackets.Add(CreateIsZoneingPacket(playerActorId)); - subpackets.Add(CreateScriptBindPacket(playerActorId)); - return BasePacket.CreatePacket(subpackets, true, false); - } - - #region Actor Management - - public void AddActorToZone(Actor actor) - { - if (!mActorList.ContainsKey(actor.actorId)) - mActorList.Add(actor.actorId, actor); - - int gridX = (int)actor.positionX / boundingGridSize; - int gridY = (int)actor.positionZ / boundingGridSize; - - gridX += halfWidth; - gridY += halfHeight; - - //Boundries - if (gridX < 0) - gridX = 0; - if (gridX >= numXBlocks) - gridX = numXBlocks - 1; - if (gridY < 0) - gridY = 0; - if (gridY >= numYBlocks) - gridY = numYBlocks - 1; - - lock (mActorBlock) - mActorBlock[gridX, gridY].Add(actor); - } - - public void RemoveActorFromZone(Actor actor) - { - mActorList.Remove(actor.actorId); - - int gridX = (int)actor.positionX / boundingGridSize; - int gridY = (int)actor.positionZ / boundingGridSize; - - gridX += halfWidth; - gridY += halfHeight; - - //Boundries - if (gridX < 0) - gridX = 0; - if (gridX >= numXBlocks) - gridX = numXBlocks - 1; - if (gridY < 0) - gridY = 0; - if (gridY >= numYBlocks) - gridY = numYBlocks - 1; - - lock (mActorBlock) - mActorBlock[gridX, gridY].Remove(actor); - } - - public void UpdateActorPosition(Actor actor) - { - int gridX = (int)actor.positionX / boundingGridSize; - int gridY = (int)actor.positionZ / boundingGridSize; - - gridX += halfWidth; - gridY += halfHeight; - - //Boundries - if (gridX < 0) - gridX = 0; - if (gridX >= numXBlocks) - gridX = numXBlocks - 1; - if (gridY < 0) - gridY = 0; - if (gridY >= numYBlocks) - gridY = numYBlocks - 1; - - int gridOldX = (int)actor.oldPositionX / boundingGridSize; - int gridOldY = (int)actor.oldPositionZ / boundingGridSize; - - gridOldX += halfWidth; - gridOldY += halfHeight; - - //Boundries - if (gridOldX < 0) - gridOldX = 0; - if (gridOldX >= numXBlocks) - gridOldX = numXBlocks - 1; - if (gridOldY < 0) - gridOldY = 0; - if (gridOldY >= numYBlocks) - gridOldY = numYBlocks - 1; - - //Still in same block - if (gridX == gridOldX && gridY == gridOldY) - return; - - lock (mActorBlock) - { - mActorBlock[gridOldX, gridOldY].Remove(actor); - mActorBlock[gridX, gridY].Add(actor); - } - } - - public List GetActorsAroundPoint(float x, float y, int checkDistance) - { - checkDistance /= boundingGridSize; - - int gridX = (int)x/boundingGridSize; - int gridY = (int)y/boundingGridSize; - - gridX += halfWidth; - gridY += halfHeight; - - //Boundries - if (gridX < 0) - gridX = 0; - if (gridX >= numXBlocks) - gridX = numXBlocks - 1; - if (gridY < 0) - gridY = 0; - if (gridY >= numYBlocks) - gridY = numYBlocks - 1; - - List result = new List(); - - for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++) - { - for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) - { - result.AddRange(mActorBlock[gx, gy]); - } - } - - //Remove players if isolation zone - if (isIsolated) - { - for (int i = 0; i < result.Count; i++) - { - if (result[i] is Player) - result.RemoveAt(i); - } - } - - return result; - } - - public List GetActorsAroundActor(Actor actor, int checkDistance) - { - checkDistance /= boundingGridSize; - - int gridX = (int)actor.positionX / boundingGridSize; - int gridY = (int)actor.positionZ / boundingGridSize; - - gridX += halfWidth; - gridY += halfHeight; - - //Boundries - if (gridX < 0) - gridX = 0; - if (gridX >= numXBlocks) - gridX = numXBlocks - 1; - if (gridY < 0) - gridY = 0; - if (gridY >= numYBlocks) - gridY = numYBlocks - 1; - - List result = new List(); - - for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++) - { - for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++) - { - result.AddRange(mActorBlock[gx, gy]); - } - } - - //Remove players if isolation zone - if (isIsolated) - { - for (int i = 0; i < result.Count; i++) - { - if (result[i] is Player) - result.RemoveAt(i); - } - } - - return result; - } - - #endregion - - public Actor FindActorInZone(uint id) - { - if (!mActorList.ContainsKey(id)) - return null; - return mActorList[id]; - } - - public Player FindPCInZone(string name) - { - foreach (Actor a in mActorList.Values) - { - if (a is Player) - { - if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower())) - return (Player)a; - } - } - return null; - } - - public Player FindPCInZone(uint id) - { - if (!mActorList.ContainsKey(id)) - return null; - return (Player)mActorList[id]; - } - - public void Clear() - { - //Clear All - mActorList.Clear(); - for (int y = 0; y < numYBlocks; y++) - { - for (int x = 0; x < numXBlocks; x++) - { - mActorBlock[x, y].Clear(); - } - } - } - - public void BroadcastPacketAroundActor(Actor actor, SubPacket packet) - { - if (isIsolated) - return; - - List aroundActor = GetActorsAroundActor(actor, 50); - foreach (Actor a in aroundActor) - { - if (a is Player) - { - if (isIsolated && packet.header.sourceId != a.actorId) - continue; - - SubPacket clonedPacket = new SubPacket(packet, actor.actorId); - Player p = (Player)a; - p.QueuePacket(clonedPacket); - } - } - } - - public void SpawnActor(SpawnLocation location) - { - ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId); - - if (actorClass == null) +namespace FFXIVClassic_Map_Server.Actors +{ + class Area : Actor + { + public string zoneName; + public ushort regionId; + public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid; + public ushort weatherNormal, weatherCommon, weatherRare; + public ushort bgmDay, bgmNight, bgmBattle; + + protected string classPath; + + public int boundingGridSize = 50; + public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000; + protected int numXBlocks, numYBlocks; + protected int halfWidth, halfHeight; + + protected List mSpawnLocations = new List(); + protected Dictionary mActorList = new Dictionary(); + protected List[,] mActorBlock; + + LuaScript areaScript; + + public Area(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid) + : base(id) + { + + this.zoneName = zoneName; + this.regionId = regionId; + this.canStealth = canStealth; + this.isIsolated = isIsolated; + this.isInn = isInn; + this.canRideChocobo = canRideChocobo; + this.isInstanceRaid = isInstanceRaid; + + this.bgmDay = bgmDay; + this.bgmNight = bgmNight; + this.bgmBattle = bgmBattle; + + this.displayNameId = 0; + this.customDisplayName = "_areaMaster"; + this.actorName = String.Format("_areaMaster@{0:X5}",id<<8); + + this.className = className; + + numXBlocks = (maxX - minX) / boundingGridSize; + numYBlocks = (maxY - minY) / boundingGridSize; + mActorBlock = new List[numXBlocks, numYBlocks]; + halfWidth = numXBlocks / 2; + halfHeight = numYBlocks / 2; + + for (int y = 0; y < numYBlocks; y++) + { + for (int x = 0; x < numXBlocks; x++ ) + { + mActorBlock[x, y] = new List(); + } + } + + } + + public override SubPacket CreateScriptBindPacket(uint playerActorId) + { + List lParams; + lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false); + return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, "ZoneDefault", lParams); + } + + public override BasePacket GetSpawnPackets(uint playerActorId) + { + List subpackets = new List(); + subpackets.Add(CreateAddActorPacket(playerActorId, 0)); + subpackets.Add(CreateSpeedPacket(playerActorId)); + subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1)); + subpackets.Add(CreateNamePacket(playerActorId)); + subpackets.Add(CreateStatePacket(playerActorId)); + subpackets.Add(CreateIsZoneingPacket(playerActorId)); + subpackets.Add(CreateScriptBindPacket(playerActorId)); + return BasePacket.CreatePacket(subpackets, true, false); + } + + #region Actor Management + + public void AddActorToZone(Actor actor) + { + if (!mActorList.ContainsKey(actor.actorId)) + mActorList.Add(actor.actorId, actor); + + int gridX = (int)actor.positionX / boundingGridSize; + int gridY = (int)actor.positionZ / boundingGridSize; + + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + + lock (mActorBlock) + mActorBlock[gridX, gridY].Add(actor); + } + + public void RemoveActorFromZone(Actor actor) + { + mActorList.Remove(actor.actorId); + + int gridX = (int)actor.positionX / boundingGridSize; + int gridY = (int)actor.positionZ / boundingGridSize; + + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + + lock (mActorBlock) + mActorBlock[gridX, gridY].Remove(actor); + } + + public void UpdateActorPosition(Actor actor) + { + int gridX = (int)actor.positionX / boundingGridSize; + int gridY = (int)actor.positionZ / boundingGridSize; + + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + + int gridOldX = (int)actor.oldPositionX / boundingGridSize; + int gridOldY = (int)actor.oldPositionZ / boundingGridSize; + + gridOldX += halfWidth; + gridOldY += halfHeight; + + //Boundries + if (gridOldX < 0) + gridOldX = 0; + if (gridOldX >= numXBlocks) + gridOldX = numXBlocks - 1; + if (gridOldY < 0) + gridOldY = 0; + if (gridOldY >= numYBlocks) + gridOldY = numYBlocks - 1; + + //Still in same block + if (gridX == gridOldX && gridY == gridOldY) return; - Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, actorId, location.x, location.y, location.z, location.rot, location.state, location.animId, null); - npc.LoadEventConditions(actorClass.eventConditions); - - AddActorToZone(npc); - } - + lock (mActorBlock) + { + mActorBlock[gridOldX, gridOldY].Remove(actor); + mActorBlock[gridX, gridY].Add(actor); + } + } + + public List GetActorsAroundPoint(float x, float y, int checkDistance) + { + checkDistance /= boundingGridSize; + + int gridX = (int)x/boundingGridSize; + int gridY = (int)y/boundingGridSize; + + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + + List result = new List(); + + for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++) + { + for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) + { + result.AddRange(mActorBlock[gx, gy]); + } + } + + //Remove players if isolation zone + if (isIsolated) + { + for (int i = 0; i < result.Count; i++) + { + if (result[i] is Player) + result.RemoveAt(i); + } + } + + return result; + } + + public List GetActorsAroundActor(Actor actor, int checkDistance) + { + checkDistance /= boundingGridSize; + + int gridX = (int)actor.positionX / boundingGridSize; + int gridY = (int)actor.positionZ / boundingGridSize; + + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + + List result = new List(); + + for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++) + { + for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++) + { + result.AddRange(mActorBlock[gx, gy]); + } + } + + //Remove players if isolation zone + if (isIsolated) + { + for (int i = 0; i < result.Count; i++) + { + if (result[i] is Player) + result.RemoveAt(i); + } + } + + return result; + } + + #endregion + + public Actor FindActorInZone(uint id) + { + if (!mActorList.ContainsKey(id)) + return null; + return mActorList[id]; + } + + public Player FindPCInZone(string name) + { + foreach (Actor a in mActorList.Values) + { + if (a is Player) + { + if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower())) + return (Player)a; + } + } + return null; + } + + public Player FindPCInZone(uint id) + { + if (!mActorList.ContainsKey(id)) + return null; + return (Player)mActorList[id]; + } + + public void Clear() + { + //Clear All + mActorList.Clear(); + for (int y = 0; y < numYBlocks; y++) + { + for (int x = 0; x < numXBlocks; x++) + { + mActorBlock[x, y].Clear(); + } + } + } + + public void BroadcastPacketAroundActor(Actor actor, SubPacket packet) + { + if (isIsolated) + return; + + List aroundActor = GetActorsAroundActor(actor, 50); + foreach (Actor a in aroundActor) + { + if (a is Player) + { + if (isIsolated && packet.header.sourceId != a.actorId) + continue; + + SubPacket clonedPacket = new SubPacket(packet, actor.actorId); + Player p = (Player)a; + p.QueuePacket(clonedPacket); + } + } + } + + public void SpawnActor(SpawnLocation location) + { + ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId); + + if (actorClass == null) + return; + + Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, actorId, location.x, location.y, location.z, location.rot, location.state, location.animId, null); + npc.LoadEventConditions(actorClass.eventConditions); + + AddActorToZone(npc); + } + public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false) { weatherNormal = weather; @@ -372,6 +372,6 @@ namespace FFXIVClassic_Map_Server.Actors } } } - } - } -} + } + } +} diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 98cc0cc0..4d7f333b 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -1,611 +1,611 @@ -using FFXIVClassic.Common; -using FFXIVClassic_Map_Server.packets; -using FFXIVClassic_Map_Server.actors.chara.player; -using FFXIVClassic_Map_Server.actors.director; -using FFXIVClassic_Map_Server.dataobjects; -using FFXIVClassic_Map_Server.dataobjects.chara; -using FFXIVClassic_Map_Server.lua; -using FFXIVClassic_Map_Server.packets.send; -using FFXIVClassic_Map_Server.packets.send.actor; -using FFXIVClassic_Map_Server.packets.send.actor.events; -using FFXIVClassic_Map_Server.packets.send.Actor.inventory; -using FFXIVClassic_Map_Server.packets.send.events; -using FFXIVClassic_Map_Server.packets.send.list; -using FFXIVClassic_Map_Server.packets.send.player; -using FFXIVClassic_Map_Server.utils; -using System; -using System.Collections.Generic; -using MoonSharp.Interpreter; -using FFXIVClassic_Map_Server.packets.receive.events; - -namespace FFXIVClassic_Map_Server.Actors -{ - class Player : Character - { - public const int CLASSID_PUG = 2; - public const int CLASSID_GLA = 3; - public const int CLASSID_MRD = 4; - public const int CLASSID_ARC = 7; - public const int CLASSID_LNC = 8; - public const int CLASSID_THM = 22; - public const int CLASSID_CNJ = 23; - - public const int CLASSID_CRP = 29; - public const int CLASSID_BSM = 30; - public const int CLASSID_ARM = 31; - public const int CLASSID_GSM = 32; - public const int CLASSID_LTW = 33; - public const int CLASSID_WVR = 34; - public const int CLASSID_ALC = 35; - public const int CLASSID_CUL = 36; - - public const int CLASSID_MIN = 39; - public const int CLASSID_BTN = 40; - public const int CLASSID_FSH = 41; - - public const int MAXSIZE_INVENTORY_NORMAL = 200; - public const int MAXSIZE_INVENTORY_CURRANCY = 320; - public const int MAXSIZE_INVENTORY_KEYITEMS = 500; - public const int MAXSIZE_INVENTORY_LOOT = 10; - public const int MAXSIZE_INVENTORY_MELDREQUEST = 4; - public const int MAXSIZE_INVENTORY_BAZAAR = 10; - public const int MAXSIZE_INVENTORY_EQUIPMENT = 35; - - public const int TIMER_TOTORAK = 0; - public const int TIMER_DZEMAEL = 1; - public const int TIMER_BOWL_OF_EMBERS_HARD = 2; - public const int TIMER_BOWL_OF_EMBERS = 3; - public const int TIMER_THORNMARCH = 4; - public const int TIMER_AURUMVALE = 5; - public const int TIMER_CUTTERSCRY = 6; - public const int TIMER_BATTLE_ALEPORT = 7; - public const int TIMER_BATTLE_HYRSTMILL = 8; - public const int TIMER_BATTLE_GOLDENBAZAAR = 9; - public const int TIMER_HOWLING_EYE_HARD = 10; - public const int TIMER_HOWLING_EYE = 11; - public const int TIMER_CASTRUM_TOWER = 12; - public const int TIMER_BOWL_OF_EMBERS_EXTREME = 13; - public const int TIMER_RIVENROAD = 14; - public const int TIMER_RIVENROAD_HARD = 15; - public const int TIMER_BEHEST = 16; - public const int TIMER_COMPANYBEHEST = 17; - public const int TIMER_RETURN = 18; - public const int TIMER_SKIRMISH = 19; - - public static int[] MAXEXP = {570, 700, 880, 1100, 1500, 1800, 2300, 3200, 4300, 5000, //Level <= 10 - 5900, 6800, 7700, 8700, 9700, 11000, 12000, 13000, 15000, 16000, //Level <= 20 - 20000, 22000, 23000, 25000, 27000, 29000, 31000, 33000, 35000, 38000, //Level <= 30 - 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 Coroutine currentEventRunning; - - //Player Info - public uint[] timers = new uint[20]; - public ushort currentJob; - public uint currentTitle; - public uint playTime; - public uint lastPlayTimeUpdate; - public bool isGM = false; - public bool isZoneChanging = true; - - //Inventory - private Dictionary inventories = new Dictionary(); - private Equipment equipment; - - //GC Related - public byte gcCurrent; - public byte gcRankLimsa; - public byte gcRankGridania; - public byte gcRankUldah; - - //Mount Related - public bool hasChocobo; - public bool hasGoobbue; - public byte chocoboAppearance; - public string chocoboName; - public byte mountState = 0; - - public uint achievementPoints; - - //Property Array Request Stuff - private int lastPosition = 0; - private int lastStep = 0; - - //Quest Actors (MUST MATCH playerWork.questScenario/questGuildleve) - public Quest[] questScenario = new Quest[16]; - public Quest[] questGuildleve = new Quest[8]; - - public Director currentDirector; - - public PlayerWork playerWork = new PlayerWork(); - - public ConnectedPlayer playerSession; - - public Player(ConnectedPlayer cp, uint actorID) : base(actorID) - { - playerSession = cp; - actorName = String.Format("_pc{0:00000000}", actorID); - className = "Player"; - currentSubState = SetActorStatePacket.SUB_STATE_PLAYER; - - inventories[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL); - inventories[Inventory.KEYITEMS] = new Inventory(this, MAXSIZE_INVENTORY_KEYITEMS, Inventory.KEYITEMS); - inventories[Inventory.CURRENCY] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRENCY); - inventories[Inventory.MELDREQUEST] = new Inventory(this, MAXSIZE_INVENTORY_MELDREQUEST, Inventory.MELDREQUEST); - inventories[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR); - inventories[Inventory.LOOT] = new Inventory(this, MAXSIZE_INVENTORY_LOOT, Inventory.LOOT); - - equipment = new Equipment(this, inventories[Inventory.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, Inventory.EQUIPMENT); - - //Set the Skill level caps of all FFXIV (classes)skills to 50 - for (int i = 0; i < charaWork.battleSave.skillLevelCap.Length; i++) - { - if (i != CLASSID_PUG && - i != CLASSID_MRD && - i != CLASSID_GLA && - i != CLASSID_MRD && - i != CLASSID_ARC && - i != CLASSID_LNC && - i != CLASSID_THM && - i != CLASSID_CNJ && - i != CLASSID_CRP && - i != CLASSID_BSM && - i != CLASSID_ARM && - i != CLASSID_GSM && - i != CLASSID_LTW && - i != CLASSID_WVR && - i != CLASSID_ALC && - i != CLASSID_CUL && - i != CLASSID_MIN && - i != CLASSID_BTN && - i != CLASSID_FSH) - charaWork.battleSave.skillLevelCap[i] = 0xFF; - else - charaWork.battleSave.skillLevelCap[i] = 50; - - } - - charaWork.property[0] = 1; - charaWork.property[1] = 1; - charaWork.property[2] = 1; - charaWork.property[4] = 1; - - charaWork.command[0] = 0xA0F00000 | 21001; - charaWork.command[1] = 0xA0F00000 | 21001; - - charaWork.command[2] = 0xA0F00000 | 21002; - charaWork.command[3] = 0xA0F00000 | 12004; - charaWork.command[4] = 0xA0F00000 | 21005; - charaWork.command[5] = 0xA0F00000 | 21006; - charaWork.command[6] = 0xA0F00000 | 21007; - charaWork.command[7] = 0xA0F00000 | 12009; - charaWork.command[8] = 0xA0F00000 | 12010; - charaWork.command[9] = 0xA0F00000 | 12005; - charaWork.command[10] = 0xA0F00000 | 12007; - charaWork.command[11] = 0xA0F00000 | 12011; - charaWork.command[12] = 0xA0F00000 | 22012; - charaWork.command[13] = 0xA0F00000 | 22013; - charaWork.command[14] = 0xA0F00000 | 29497; - charaWork.command[15] = 0xA0F00000 | 22015; - - charaWork.command[32] = 0xA0F00000 | 27191; - charaWork.command[33] = 0xA0F00000 | 22302; - charaWork.command[34] = 0xA0F00000 | 28466; - - charaWork.commandAcquired[27150 - 26000] = true; - - playerWork.questScenarioComplete[110001 - 110001] = true; - playerWork.questGuildleveComplete[120050 - 120001] = true; - - for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++ ) - charaWork.additionalCommandAcquired[i] = true; - - for (int i = 0; i < charaWork.commandCategory.Length; i++) - charaWork.commandCategory[i] = 1; - - charaWork.battleTemp.generalParameter[3] = 1; - - charaWork.eventSave.bazaarTax = 5; - charaWork.battleSave.potencial = 6.6f; - - charaWork.commandCategory[0] = 1; - charaWork.commandCategory[1] = 1; - charaWork.commandCategory[32] = 1; - charaWork.commandCategory[33] = 1; - charaWork.commandCategory[34] = 1; - - charaWork.parameterSave.commandSlot_compatibility[0] = true; - charaWork.parameterSave.commandSlot_compatibility[1] = true; - charaWork.parameterSave.commandSlot_compatibility[32] = true; - - charaWork.commandBorder = 0x20; - - charaWork.parameterTemp.tp = 3000; - - Database.LoadPlayerCharacter(this); - lastPlayTimeUpdate = Utils.UnixTimeStampUTC(); - } - - public List Create0x132Packets(uint playerActorId) - { - List packets = new List(); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0xB, "commandForced")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0xA, "commandDefault")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x6, "commandWeak")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x4, "commandContent")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x6, "commandJudgeMode")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x100, "commandRequest")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x100, "widgetCreate")); - packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x100, "macroRequest")); - return packets; - } - - public override SubPacket CreateScriptBindPacket(uint playerActorId) - { - List lParams; - if (IsMyPlayer(playerActorId)) - { - if (currentDirector != null) - 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); - } - else - lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true); - return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); - } - - public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) - { - List subpackets = new List(); - subpackets.Add(CreateAddActorPacket(playerActorId, 8)); - if (IsMyPlayer(playerActorId)) - subpackets.AddRange(Create0x132Packets(playerActorId)); - subpackets.Add(CreateSpeedPacket(playerActorId)); - subpackets.Add(CreateSpawnPositonPacket(playerActorId, spawnType)); - subpackets.Add(CreateAppearancePacket(playerActorId)); - subpackets.Add(CreateNamePacket(playerActorId)); - subpackets.Add(_0xFPacket.BuildPacket(playerActorId, playerActorId)); - subpackets.Add(CreateStatePacket(playerActorId)); - subpackets.Add(CreateIdleAnimationPacket(playerActorId)); - subpackets.Add(CreateInitStatusPacket(playerActorId)); - subpackets.Add(CreateSetActorIconPacket(playerActorId)); - subpackets.Add(CreateIsZoneingPacket(playerActorId)); - subpackets.AddRange(CreatePlayerRelatedPackets(playerActorId)); - subpackets.Add(CreateScriptBindPacket(playerActorId)); - return BasePacket.CreatePacket(subpackets, true, false); - } - - public List CreatePlayerRelatedPackets(uint playerActorId) - { - List subpackets = new List(); - - if (gcCurrent != 0) - subpackets.Add(SetGrandCompanyPacket.BuildPacket(actorId, playerActorId, gcCurrent, gcRankLimsa, gcRankGridania, gcRankUldah)); - - if (currentTitle != 0) - subpackets.Add(SetPlayerTitlePacket.BuildPacket(actorId, playerActorId, currentTitle)); - - if (currentJob != 0) - subpackets.Add(SetCurrentJobPacket.BuildPacket(actorId, playerActorId, currentJob)); - - if (IsMyPlayer(playerActorId)) - { - subpackets.Add(_0x196Packet.BuildPacket(playerActorId, playerActorId)); - - if (hasChocobo && chocoboName != null && !chocoboName.Equals("")) - { - subpackets.Add(SetChocoboNamePacket.BuildPacket(actorId, playerActorId, chocoboName)); - subpackets.Add(SetHasChocoboPacket.BuildPacket(playerActorId, hasChocobo)); - } - - if (hasGoobbue) - subpackets.Add(SetHasGoobbuePacket.BuildPacket(playerActorId, hasGoobbue)); - - subpackets.Add(SetAchievementPointsPacket.BuildPacket(playerActorId, achievementPoints)); - subpackets.Add(Database.GetLatestAchievements(this)); - subpackets.Add(Database.GetAchievementsPacket(this)); - } - - return subpackets; - } - - public override BasePacket GetInitPackets(uint playerActorId) - { - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId); - - propPacketUtil.AddProperty("charaWork.eventSave.bazaarTax"); - propPacketUtil.AddProperty("charaWork.battleSave.potencial"); - - //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"); - propPacketUtil.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); - 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("charaWork.battleTemp.castGauge_speed[0]"); - propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[1]"); - - //Battle Save Skillpoint - - //Commands - propPacketUtil.AddProperty("charaWork.commandBorder"); - - - for (int i = 0; i < charaWork.command.Length; i++) - { - if (charaWork.command[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.command[{0}]", i)); - } - - - for (int i = 0; i < charaWork.commandCategory.Length; i++) - { - charaWork.commandCategory[i] = 1; - if (charaWork.commandCategory[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.commandCategory[{0}]", i)); - } - - for (int i = 0; i < charaWork.commandAcquired.Length; i++) - { - if (charaWork.commandAcquired[i] != false) - propPacketUtil.AddProperty(String.Format("charaWork.commandAcquired[{0}]", i)); - } - - - for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++) - { - if (charaWork.additionalCommandAcquired[i] != false) - propPacketUtil.AddProperty(String.Format("charaWork.additionalCommandAcquired[{0}]", i)); - } - - for (int i = 0; i < charaWork.parameterSave.commandSlot_compatibility.Length; i++) - { - charaWork.parameterSave.commandSlot_compatibility[i] = true; - if (charaWork.parameterSave.commandSlot_compatibility[i]) - propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", i)); - } - - /* - for (int i = 0; i < charaWork.parameterSave.commandSlot_recastTime.Length; i++) - { - if (charaWork.parameterSave.commandSlot_recastTime[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_recastTime[{0}]", i)); - } - */ - - //System - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[0]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[1]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[0]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[1]"); - - charaWork.parameterTemp.otherClassAbilityCount[0] = 4; - charaWork.parameterTemp.otherClassAbilityCount[1] = 5; - charaWork.parameterTemp.giftCount[1] = 5; - - propPacketUtil.AddProperty("charaWork.parameterTemp.otherClassAbilityCount[0]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.otherClassAbilityCount[1]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.giftCount[1]"); - - propPacketUtil.AddProperty("charaWork.depictionJudge"); - - //Scenario - for (int i = 0; i < playerWork.questScenario.Length; i++) - { - if (playerWork.questScenario[i] != 0) - propPacketUtil.AddProperty(String.Format("playerWork.questScenario[{0}]", i)); - } - - //Guildleve - Local - for (int i = 0; i < playerWork.questGuildleve.Length; i++) - { - if (playerWork.questGuildleve[i] != 0) - propPacketUtil.AddProperty(String.Format("playerWork.questGuildleve[{0}]", i)); - } - - //Guildleve - Regional - for (int i = 0; i < work.guildleveId.Length; i++) - { - if (work.guildleveId[i] != 0) - propPacketUtil.AddProperty(String.Format("work.guildleveId[{0}]", i)); - if (work.guildleveDone[i] != false) - propPacketUtil.AddProperty(String.Format("work.guildleveDone[{0}]", i)); - if (work.guildleveChecked[i] != false) - propPacketUtil.AddProperty(String.Format("work.guildleveChecked[{0}]", i)); - } - - //NPC Linkshell - for (int i = 0; i < playerWork.npcLinkshellChatCalling.Length; i++) - { - if (playerWork.npcLinkshellChatCalling[i] != false) - propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", i)); - if (playerWork.npcLinkshellChatExtra[i] != false) - propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", i)); - } - - propPacketUtil.AddProperty("playerWork.restBonusExpRate"); - - //Profile - propPacketUtil.AddProperty("playerWork.tribe"); - propPacketUtil.AddProperty("playerWork.guardian"); - propPacketUtil.AddProperty("playerWork.birthdayMonth"); - propPacketUtil.AddProperty("playerWork.birthdayDay"); - propPacketUtil.AddProperty("playerWork.initialTown"); - - return BasePacket.CreatePacket(propPacketUtil.Done(), true, false); - } - +using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.packets; +using FFXIVClassic_Map_Server.actors.chara.player; +using FFXIVClassic_Map_Server.actors.director; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.dataobjects.chara; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.packets.send; +using FFXIVClassic_Map_Server.packets.send.actor; +using FFXIVClassic_Map_Server.packets.send.actor.events; +using FFXIVClassic_Map_Server.packets.send.Actor.inventory; +using FFXIVClassic_Map_Server.packets.send.events; +using FFXIVClassic_Map_Server.packets.send.list; +using FFXIVClassic_Map_Server.packets.send.player; +using FFXIVClassic_Map_Server.utils; +using System; +using System.Collections.Generic; +using MoonSharp.Interpreter; +using FFXIVClassic_Map_Server.packets.receive.events; + +namespace FFXIVClassic_Map_Server.Actors +{ + class Player : Character + { + public const int CLASSID_PUG = 2; + public const int CLASSID_GLA = 3; + public const int CLASSID_MRD = 4; + public const int CLASSID_ARC = 7; + public const int CLASSID_LNC = 8; + public const int CLASSID_THM = 22; + public const int CLASSID_CNJ = 23; + + public const int CLASSID_CRP = 29; + public const int CLASSID_BSM = 30; + public const int CLASSID_ARM = 31; + public const int CLASSID_GSM = 32; + public const int CLASSID_LTW = 33; + public const int CLASSID_WVR = 34; + public const int CLASSID_ALC = 35; + public const int CLASSID_CUL = 36; + + public const int CLASSID_MIN = 39; + public const int CLASSID_BTN = 40; + public const int CLASSID_FSH = 41; + + public const int MAXSIZE_INVENTORY_NORMAL = 200; + public const int MAXSIZE_INVENTORY_CURRANCY = 320; + public const int MAXSIZE_INVENTORY_KEYITEMS = 500; + public const int MAXSIZE_INVENTORY_LOOT = 10; + public const int MAXSIZE_INVENTORY_MELDREQUEST = 4; + public const int MAXSIZE_INVENTORY_BAZAAR = 10; + public const int MAXSIZE_INVENTORY_EQUIPMENT = 35; + + public const int TIMER_TOTORAK = 0; + public const int TIMER_DZEMAEL = 1; + public const int TIMER_BOWL_OF_EMBERS_HARD = 2; + public const int TIMER_BOWL_OF_EMBERS = 3; + public const int TIMER_THORNMARCH = 4; + public const int TIMER_AURUMVALE = 5; + public const int TIMER_CUTTERSCRY = 6; + public const int TIMER_BATTLE_ALEPORT = 7; + public const int TIMER_BATTLE_HYRSTMILL = 8; + public const int TIMER_BATTLE_GOLDENBAZAAR = 9; + public const int TIMER_HOWLING_EYE_HARD = 10; + public const int TIMER_HOWLING_EYE = 11; + public const int TIMER_CASTRUM_TOWER = 12; + public const int TIMER_BOWL_OF_EMBERS_EXTREME = 13; + public const int TIMER_RIVENROAD = 14; + public const int TIMER_RIVENROAD_HARD = 15; + public const int TIMER_BEHEST = 16; + public const int TIMER_COMPANYBEHEST = 17; + public const int TIMER_RETURN = 18; + public const int TIMER_SKIRMISH = 19; + + public static int[] MAXEXP = {570, 700, 880, 1100, 1500, 1800, 2300, 3200, 4300, 5000, //Level <= 10 + 5900, 6800, 7700, 8700, 9700, 11000, 12000, 13000, 15000, 16000, //Level <= 20 + 20000, 22000, 23000, 25000, 27000, 29000, 31000, 33000, 35000, 38000, //Level <= 30 + 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 Coroutine currentEventRunning; + + //Player Info + public uint[] timers = new uint[20]; + public ushort currentJob; + public uint currentTitle; + public uint playTime; + public uint lastPlayTimeUpdate; + public bool isGM = false; + public bool isZoneChanging = true; + + //Inventory + private Dictionary inventories = new Dictionary(); + private Equipment equipment; + + //GC Related + public byte gcCurrent; + public byte gcRankLimsa; + public byte gcRankGridania; + public byte gcRankUldah; + + //Mount Related + public bool hasChocobo; + public bool hasGoobbue; + public byte chocoboAppearance; + public string chocoboName; + public byte mountState = 0; + + public uint achievementPoints; + + //Property Array Request Stuff + private int lastPosition = 0; + private int lastStep = 0; + + //Quest Actors (MUST MATCH playerWork.questScenario/questGuildleve) + public Quest[] questScenario = new Quest[16]; + public Quest[] questGuildleve = new Quest[8]; + + public Director currentDirector; + + public PlayerWork playerWork = new PlayerWork(); + + public ConnectedPlayer playerSession; + + public Player(ConnectedPlayer cp, uint actorID) : base(actorID) + { + playerSession = cp; + actorName = String.Format("_pc{0:00000000}", actorID); + className = "Player"; + currentSubState = SetActorStatePacket.SUB_STATE_PLAYER; + + inventories[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL); + inventories[Inventory.KEYITEMS] = new Inventory(this, MAXSIZE_INVENTORY_KEYITEMS, Inventory.KEYITEMS); + inventories[Inventory.CURRENCY] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRENCY); + inventories[Inventory.MELDREQUEST] = new Inventory(this, MAXSIZE_INVENTORY_MELDREQUEST, Inventory.MELDREQUEST); + inventories[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR); + inventories[Inventory.LOOT] = new Inventory(this, MAXSIZE_INVENTORY_LOOT, Inventory.LOOT); + + equipment = new Equipment(this, inventories[Inventory.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, Inventory.EQUIPMENT); + + //Set the Skill level caps of all FFXIV (classes)skills to 50 + for (int i = 0; i < charaWork.battleSave.skillLevelCap.Length; i++) + { + if (i != CLASSID_PUG && + i != CLASSID_MRD && + i != CLASSID_GLA && + i != CLASSID_MRD && + i != CLASSID_ARC && + i != CLASSID_LNC && + i != CLASSID_THM && + i != CLASSID_CNJ && + i != CLASSID_CRP && + i != CLASSID_BSM && + i != CLASSID_ARM && + i != CLASSID_GSM && + i != CLASSID_LTW && + i != CLASSID_WVR && + i != CLASSID_ALC && + i != CLASSID_CUL && + i != CLASSID_MIN && + i != CLASSID_BTN && + i != CLASSID_FSH) + charaWork.battleSave.skillLevelCap[i] = 0xFF; + else + charaWork.battleSave.skillLevelCap[i] = 50; + + } + + charaWork.property[0] = 1; + charaWork.property[1] = 1; + charaWork.property[2] = 1; + charaWork.property[4] = 1; + + charaWork.command[0] = 0xA0F00000 | 21001; + charaWork.command[1] = 0xA0F00000 | 21001; + + charaWork.command[2] = 0xA0F00000 | 21002; + charaWork.command[3] = 0xA0F00000 | 12004; + charaWork.command[4] = 0xA0F00000 | 21005; + charaWork.command[5] = 0xA0F00000 | 21006; + charaWork.command[6] = 0xA0F00000 | 21007; + charaWork.command[7] = 0xA0F00000 | 12009; + charaWork.command[8] = 0xA0F00000 | 12010; + charaWork.command[9] = 0xA0F00000 | 12005; + charaWork.command[10] = 0xA0F00000 | 12007; + charaWork.command[11] = 0xA0F00000 | 12011; + charaWork.command[12] = 0xA0F00000 | 22012; + charaWork.command[13] = 0xA0F00000 | 22013; + charaWork.command[14] = 0xA0F00000 | 29497; + charaWork.command[15] = 0xA0F00000 | 22015; + + charaWork.command[32] = 0xA0F00000 | 27191; + charaWork.command[33] = 0xA0F00000 | 22302; + charaWork.command[34] = 0xA0F00000 | 28466; + + charaWork.commandAcquired[27150 - 26000] = true; + + playerWork.questScenarioComplete[110001 - 110001] = true; + playerWork.questGuildleveComplete[120050 - 120001] = true; + + for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++ ) + charaWork.additionalCommandAcquired[i] = true; + + for (int i = 0; i < charaWork.commandCategory.Length; i++) + charaWork.commandCategory[i] = 1; + + charaWork.battleTemp.generalParameter[3] = 1; + + charaWork.eventSave.bazaarTax = 5; + charaWork.battleSave.potencial = 6.6f; + + charaWork.commandCategory[0] = 1; + charaWork.commandCategory[1] = 1; + charaWork.commandCategory[32] = 1; + charaWork.commandCategory[33] = 1; + charaWork.commandCategory[34] = 1; + + charaWork.parameterSave.commandSlot_compatibility[0] = true; + charaWork.parameterSave.commandSlot_compatibility[1] = true; + charaWork.parameterSave.commandSlot_compatibility[32] = true; + + charaWork.commandBorder = 0x20; + + charaWork.parameterTemp.tp = 3000; + + Database.LoadPlayerCharacter(this); + lastPlayTimeUpdate = Utils.UnixTimeStampUTC(); + } + + public List Create0x132Packets(uint playerActorId) + { + List packets = new List(); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0xB, "commandForced")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0xA, "commandDefault")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x6, "commandWeak")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x4, "commandContent")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x6, "commandJudgeMode")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x100, "commandRequest")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x100, "widgetCreate")); + packets.Add(_0x132Packet.BuildPacket(playerActorId, 0x100, "macroRequest")); + return packets; + } + + public override SubPacket CreateScriptBindPacket(uint playerActorId) + { + List lParams; + if (IsMyPlayer(playerActorId)) + { + if (currentDirector != null) + 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); + } + else + lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true); + return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); + } + + public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) + { + List subpackets = new List(); + subpackets.Add(CreateAddActorPacket(playerActorId, 8)); + if (IsMyPlayer(playerActorId)) + subpackets.AddRange(Create0x132Packets(playerActorId)); + subpackets.Add(CreateSpeedPacket(playerActorId)); + subpackets.Add(CreateSpawnPositonPacket(playerActorId, spawnType)); + subpackets.Add(CreateAppearancePacket(playerActorId)); + subpackets.Add(CreateNamePacket(playerActorId)); + subpackets.Add(_0xFPacket.BuildPacket(playerActorId, playerActorId)); + subpackets.Add(CreateStatePacket(playerActorId)); + subpackets.Add(CreateIdleAnimationPacket(playerActorId)); + subpackets.Add(CreateInitStatusPacket(playerActorId)); + subpackets.Add(CreateSetActorIconPacket(playerActorId)); + subpackets.Add(CreateIsZoneingPacket(playerActorId)); + subpackets.AddRange(CreatePlayerRelatedPackets(playerActorId)); + subpackets.Add(CreateScriptBindPacket(playerActorId)); + return BasePacket.CreatePacket(subpackets, true, false); + } + + public List CreatePlayerRelatedPackets(uint playerActorId) + { + List subpackets = new List(); + + if (gcCurrent != 0) + subpackets.Add(SetGrandCompanyPacket.BuildPacket(actorId, playerActorId, gcCurrent, gcRankLimsa, gcRankGridania, gcRankUldah)); + + if (currentTitle != 0) + subpackets.Add(SetPlayerTitlePacket.BuildPacket(actorId, playerActorId, currentTitle)); + + if (currentJob != 0) + subpackets.Add(SetCurrentJobPacket.BuildPacket(actorId, playerActorId, currentJob)); + + if (IsMyPlayer(playerActorId)) + { + subpackets.Add(_0x196Packet.BuildPacket(playerActorId, playerActorId)); + + if (hasChocobo && chocoboName != null && !chocoboName.Equals("")) + { + subpackets.Add(SetChocoboNamePacket.BuildPacket(actorId, playerActorId, chocoboName)); + subpackets.Add(SetHasChocoboPacket.BuildPacket(playerActorId, hasChocobo)); + } + + if (hasGoobbue) + subpackets.Add(SetHasGoobbuePacket.BuildPacket(playerActorId, hasGoobbue)); + + subpackets.Add(SetAchievementPointsPacket.BuildPacket(playerActorId, achievementPoints)); + subpackets.Add(Database.GetLatestAchievements(this)); + subpackets.Add(Database.GetAchievementsPacket(this)); + } + + return subpackets; + } + + public override BasePacket GetInitPackets(uint playerActorId) + { + ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId); + + propPacketUtil.AddProperty("charaWork.eventSave.bazaarTax"); + propPacketUtil.AddProperty("charaWork.battleSave.potencial"); + + //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"); + propPacketUtil.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); + 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("charaWork.battleTemp.castGauge_speed[0]"); + propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[1]"); + + //Battle Save Skillpoint + + //Commands + propPacketUtil.AddProperty("charaWork.commandBorder"); + + + for (int i = 0; i < charaWork.command.Length; i++) + { + if (charaWork.command[i] != 0) + propPacketUtil.AddProperty(String.Format("charaWork.command[{0}]", i)); + } + + + for (int i = 0; i < charaWork.commandCategory.Length; i++) + { + charaWork.commandCategory[i] = 1; + if (charaWork.commandCategory[i] != 0) + propPacketUtil.AddProperty(String.Format("charaWork.commandCategory[{0}]", i)); + } + + for (int i = 0; i < charaWork.commandAcquired.Length; i++) + { + if (charaWork.commandAcquired[i] != false) + propPacketUtil.AddProperty(String.Format("charaWork.commandAcquired[{0}]", i)); + } + + + for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++) + { + if (charaWork.additionalCommandAcquired[i] != false) + propPacketUtil.AddProperty(String.Format("charaWork.additionalCommandAcquired[{0}]", i)); + } + + for (int i = 0; i < charaWork.parameterSave.commandSlot_compatibility.Length; i++) + { + charaWork.parameterSave.commandSlot_compatibility[i] = true; + if (charaWork.parameterSave.commandSlot_compatibility[i]) + propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", i)); + } + + /* + for (int i = 0; i < charaWork.parameterSave.commandSlot_recastTime.Length; i++) + { + if (charaWork.parameterSave.commandSlot_recastTime[i] != 0) + propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_recastTime[{0}]", i)); + } + */ + + //System + propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[0]"); + propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[1]"); + propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[0]"); + propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[1]"); + + charaWork.parameterTemp.otherClassAbilityCount[0] = 4; + charaWork.parameterTemp.otherClassAbilityCount[1] = 5; + charaWork.parameterTemp.giftCount[1] = 5; + + propPacketUtil.AddProperty("charaWork.parameterTemp.otherClassAbilityCount[0]"); + propPacketUtil.AddProperty("charaWork.parameterTemp.otherClassAbilityCount[1]"); + propPacketUtil.AddProperty("charaWork.parameterTemp.giftCount[1]"); + + propPacketUtil.AddProperty("charaWork.depictionJudge"); + + //Scenario + for (int i = 0; i < playerWork.questScenario.Length; i++) + { + if (playerWork.questScenario[i] != 0) + propPacketUtil.AddProperty(String.Format("playerWork.questScenario[{0}]", i)); + } + + //Guildleve - Local + for (int i = 0; i < playerWork.questGuildleve.Length; i++) + { + if (playerWork.questGuildleve[i] != 0) + propPacketUtil.AddProperty(String.Format("playerWork.questGuildleve[{0}]", i)); + } + + //Guildleve - Regional + for (int i = 0; i < work.guildleveId.Length; i++) + { + if (work.guildleveId[i] != 0) + propPacketUtil.AddProperty(String.Format("work.guildleveId[{0}]", i)); + if (work.guildleveDone[i] != false) + propPacketUtil.AddProperty(String.Format("work.guildleveDone[{0}]", i)); + if (work.guildleveChecked[i] != false) + propPacketUtil.AddProperty(String.Format("work.guildleveChecked[{0}]", i)); + } + + //NPC Linkshell + for (int i = 0; i < playerWork.npcLinkshellChatCalling.Length; i++) + { + if (playerWork.npcLinkshellChatCalling[i] != false) + propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", i)); + if (playerWork.npcLinkshellChatExtra[i] != false) + propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", i)); + } + + propPacketUtil.AddProperty("playerWork.restBonusExpRate"); + + //Profile + propPacketUtil.AddProperty("playerWork.tribe"); + propPacketUtil.AddProperty("playerWork.guardian"); + propPacketUtil.AddProperty("playerWork.birthdayMonth"); + propPacketUtil.AddProperty("playerWork.birthdayDay"); + propPacketUtil.AddProperty("playerWork.initialTown"); + + return BasePacket.CreatePacket(propPacketUtil.Done(), true, false); + } + public void SendSeamlessZoneInPackets() { QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, SetMusicPacket.EFFECT_FADEIN)); QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1)); - } - - public void SendZoneInPackets(WorldManager world, ushort spawnType) - { - 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, 1)); - - QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); - - QueuePacket(GetSpawnPackets(actorId, spawnType)); - GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); - - #region grouptest - //Retainers - List retainerListEntries = new List(); - retainerListEntries.Add(new ListEntry(actorId, 0xFFFFFFFF, 0x139E, false, true, customDisplayName)); - retainerListEntries.Add(new ListEntry(0x23, 0x0, 0xFFFFFFFF, false, false, "TEST1")); - retainerListEntries.Add(new ListEntry(0x24, 0x0, 0xFFFFFFFF, false, false, "TEST2")); - retainerListEntries.Add(new ListEntry(0x25, 0x0, 0xFFFFFFFF, false, false, "TEST3")); - BasePacket retainerListPacket = BasePacket.CreatePacket(ListUtils.CreateRetainerList(actorId, 0xF4, 1, 0x800000000004e639, retainerListEntries), true, false); - playerSession.QueuePacket(retainerListPacket); - - //Party - List partyListEntries = new List(); - partyListEntries.Add(new ListEntry(actorId, 0xFFFFFFFF, 0xFFFFFFFF, false, true, customDisplayName)); - partyListEntries.Add(new ListEntry(0x029B27D3, 0xFFFFFFFF, 0x195, false, true, "Valentine Bluefeather")); - BasePacket partyListPacket = BasePacket.CreatePacket(ListUtils.CreatePartyList(actorId, 0xF4, 1, 0x8000000000696df2, partyListEntries), true, false); - playerSession.QueuePacket(partyListPacket); - #endregion - - #region Inventory & Equipment - QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId)); - inventories[Inventory.NORMAL].SendFullInventory(); - inventories[Inventory.CURRENCY].SendFullInventory(); - inventories[Inventory.KEYITEMS].SendFullInventory(); - inventories[Inventory.BAZAAR].SendFullInventory(); - inventories[Inventory.MELDREQUEST].SendFullInventory(); - inventories[Inventory.LOOT].SendFullInventory(); - equipment.SendFullEquipment(false); - playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId), true, false); - #endregion - - playerSession.QueuePacket(GetInitPackets(actorId)); - - - BasePacket areaMasterSpawn = zone.GetSpawnPackets(actorId); - BasePacket debugSpawn = world.GetDebugActor().GetSpawnPackets(actorId); - BasePacket worldMasterSpawn = world.GetActor().GetSpawnPackets(actorId); - BasePacket weatherDirectorSpawn = new WeatherDirector(this, 8003).GetSpawnPackets(actorId); - BasePacket directorSpawn = null; - - if (currentDirector != null) - directorSpawn = currentDirector.GetSpawnPackets(actorId); - - playerSession.QueuePacket(areaMasterSpawn); - playerSession.QueuePacket(debugSpawn); - if (directorSpawn != null) - { - //directorSpawn.DebugPrintPacket(); - // currentDirector.GetInitPackets(actorId).DebugPrintPacket(); - QueuePacket(directorSpawn); - QueuePacket(currentDirector.GetInitPackets(actorId)); - //QueuePacket(currentDirector.GetSetEventStatusPackets(actorId)); - } - playerSession.QueuePacket(worldMasterSpawn); - - if (zone.isInn) - { - SetCutsceneBookPacket cutsceneBookPacket = new SetCutsceneBookPacket(); - for (int i = 0; i < 2048; i++) - cutsceneBookPacket.cutsceneFlags[i] = true; - - SubPacket packet = cutsceneBookPacket.BuildPacket(actorId, "", 11, 1, 1); - - packet.DebugPrintSubPacket(); - QueuePacket(packet); - } - - playerSession.QueuePacket(weatherDirectorSpawn); - -/* - #region hardcode - BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); //Item Storage, Inn Door Created - BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); //NPC Create ??? Final init - reply10.ReplaceActorID(actorId); - reply11.ReplaceActorID(actorId); - //playerSession.QueuePacket(reply10); - // playerSession.QueuePacket(reply11); - #endregion -*/ - } - - private void SendRemoveInventoryPackets(List slots) - { - int currentIndex = 0; - - while (true) - { - if (slots.Count - currentIndex >= 64) - QueuePacket(InventoryRemoveX64Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex >= 32) - QueuePacket(InventoryRemoveX32Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex >= 16) - QueuePacket(InventoryRemoveX16Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex >= 8) - QueuePacket(InventoryRemoveX08Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex == 1) - QueuePacket(InventoryRemoveX01Packet.BuildPacket(actorId, slots[currentIndex])); - else - break; - } - - } - - public bool IsMyPlayer(uint otherActorId) - { - return actorId == otherActorId; - } - - public void QueuePacket(BasePacket packet) - { - playerSession.QueuePacket(packet); - } - - public void QueuePacket(SubPacket packet) - { - playerSession.QueuePacket(packet, true, false); - } - - public void QueuePackets(List packets) - { - foreach (SubPacket subpacket in packets) - playerSession.QueuePacket(subpacket, true, false); - } - + } + + public void SendZoneInPackets(WorldManager world, ushort spawnType) + { + 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, 1)); + + QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); + + QueuePacket(GetSpawnPackets(actorId, spawnType)); + GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); + + #region grouptest + //Retainers + List retainerListEntries = new List(); + retainerListEntries.Add(new ListEntry(actorId, 0xFFFFFFFF, 0x139E, false, true, customDisplayName)); + retainerListEntries.Add(new ListEntry(0x23, 0x0, 0xFFFFFFFF, false, false, "TEST1")); + retainerListEntries.Add(new ListEntry(0x24, 0x0, 0xFFFFFFFF, false, false, "TEST2")); + retainerListEntries.Add(new ListEntry(0x25, 0x0, 0xFFFFFFFF, false, false, "TEST3")); + BasePacket retainerListPacket = BasePacket.CreatePacket(ListUtils.CreateRetainerList(actorId, 0xF4, 1, 0x800000000004e639, retainerListEntries), true, false); + playerSession.QueuePacket(retainerListPacket); + + //Party + List partyListEntries = new List(); + partyListEntries.Add(new ListEntry(actorId, 0xFFFFFFFF, 0xFFFFFFFF, false, true, customDisplayName)); + partyListEntries.Add(new ListEntry(0x029B27D3, 0xFFFFFFFF, 0x195, false, true, "Valentine Bluefeather")); + BasePacket partyListPacket = BasePacket.CreatePacket(ListUtils.CreatePartyList(actorId, 0xF4, 1, 0x8000000000696df2, partyListEntries), true, false); + playerSession.QueuePacket(partyListPacket); + #endregion + + #region Inventory & Equipment + QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId)); + inventories[Inventory.NORMAL].SendFullInventory(); + inventories[Inventory.CURRENCY].SendFullInventory(); + inventories[Inventory.KEYITEMS].SendFullInventory(); + inventories[Inventory.BAZAAR].SendFullInventory(); + inventories[Inventory.MELDREQUEST].SendFullInventory(); + inventories[Inventory.LOOT].SendFullInventory(); + equipment.SendFullEquipment(false); + playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId), true, false); + #endregion + + playerSession.QueuePacket(GetInitPackets(actorId)); + + + BasePacket areaMasterSpawn = zone.GetSpawnPackets(actorId); + BasePacket debugSpawn = world.GetDebugActor().GetSpawnPackets(actorId); + BasePacket worldMasterSpawn = world.GetActor().GetSpawnPackets(actorId); + BasePacket weatherDirectorSpawn = new WeatherDirector(this, 8003).GetSpawnPackets(actorId); + BasePacket directorSpawn = null; + + if (currentDirector != null) + directorSpawn = currentDirector.GetSpawnPackets(actorId); + + playerSession.QueuePacket(areaMasterSpawn); + playerSession.QueuePacket(debugSpawn); + if (directorSpawn != null) + { + //directorSpawn.DebugPrintPacket(); + // currentDirector.GetInitPackets(actorId).DebugPrintPacket(); + QueuePacket(directorSpawn); + QueuePacket(currentDirector.GetInitPackets(actorId)); + //QueuePacket(currentDirector.GetSetEventStatusPackets(actorId)); + } + playerSession.QueuePacket(worldMasterSpawn); + + if (zone.isInn) + { + SetCutsceneBookPacket cutsceneBookPacket = new SetCutsceneBookPacket(); + for (int i = 0; i < 2048; i++) + cutsceneBookPacket.cutsceneFlags[i] = true; + + SubPacket packet = cutsceneBookPacket.BuildPacket(actorId, "", 11, 1, 1); + + packet.DebugPrintSubPacket(); + QueuePacket(packet); + } + + playerSession.QueuePacket(weatherDirectorSpawn); + +/* + #region hardcode + BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); //Item Storage, Inn Door Created + BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); //NPC Create ??? Final init + reply10.ReplaceActorID(actorId); + reply11.ReplaceActorID(actorId); + //playerSession.QueuePacket(reply10); + // playerSession.QueuePacket(reply11); + #endregion +*/ + } + + private void SendRemoveInventoryPackets(List slots) + { + int currentIndex = 0; + + while (true) + { + if (slots.Count - currentIndex >= 64) + QueuePacket(InventoryRemoveX64Packet.BuildPacket(actorId, slots, ref currentIndex)); + else if (slots.Count - currentIndex >= 32) + QueuePacket(InventoryRemoveX32Packet.BuildPacket(actorId, slots, ref currentIndex)); + else if (slots.Count - currentIndex >= 16) + QueuePacket(InventoryRemoveX16Packet.BuildPacket(actorId, slots, ref currentIndex)); + else if (slots.Count - currentIndex >= 8) + QueuePacket(InventoryRemoveX08Packet.BuildPacket(actorId, slots, ref currentIndex)); + else if (slots.Count - currentIndex == 1) + QueuePacket(InventoryRemoveX01Packet.BuildPacket(actorId, slots[currentIndex])); + else + break; + } + + } + + public bool IsMyPlayer(uint otherActorId) + { + return actorId == otherActorId; + } + + public void QueuePacket(BasePacket packet) + { + playerSession.QueuePacket(packet); + } + + public void QueuePacket(SubPacket packet) + { + playerSession.QueuePacket(packet, true, false); + } + + public void QueuePackets(List packets) + { + foreach (SubPacket subpacket in packets) + playerSession.QueuePacket(subpacket, true, false); + } + public void SendPacket(string path) { try @@ -619,666 +619,656 @@ namespace FFXIVClassic_Map_Server.Actors { this.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "[SendPacket]", "Unable to send packet."); } - } - - public void BroadcastPacket(SubPacket packet, bool sendToSelf) - { - if (sendToSelf) - QueuePacket(packet); - - foreach (Actor a in playerSession.actorInstanceList) - { - if (a is Player) - { - Player p = (Player)a; - SubPacket clonedPacket = new SubPacket(packet, a.actorId); - p.QueuePacket(clonedPacket); - } - } - } - - public void SetDCFlag(bool flag) - { - if (flag) - { - BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, actorId, SetActorIconPacket.DISCONNECTING), true); - } - else - { - if (isGM) - BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, actorId, SetActorIconPacket.ISGM), true); - else - BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, actorId, 0), true); - } - } - - public void CleanupAndSave() - { - //Remove actor from zone and main server list - zone.RemoveActorFromZone(this); - Server.GetServer().RemovePlayer(this); - - //Save Player - Database.SavePlayerPlayTime(this); - Database.SavePlayerPosition(this); - - Program.Log.Info("{0} has been logged out and saved.", this.customDisplayName); - } - - public Area GetZone() - { - return zone; - } - - public void SendMessage(uint logType, string sender, string message) - { - QueuePacket(SendMessagePacket.BuildPacket(actorId, actorId, logType, sender, message)); - } - - public void Logout() - { - QueuePacket(LogoutPacket.BuildPacket(actorId)); - CleanupAndSave(); - } - - public void QuitGame() - { - QueuePacket(QuitPacket.BuildPacket(actorId)); - CleanupAndSave(); - } - - public uint GetPlayTime(bool doUpdate) - { - if (doUpdate) - { - uint curTime = Utils.UnixTimeStampUTC(); - playTime += curTime - lastPlayTimeUpdate; - lastPlayTimeUpdate = curTime; - } - - return playTime; - } - - public void ChangeMusic(ushort musicId) - { - QueuePacket(SetMusicPacket.BuildPacket(actorId, musicId, 1)); - } - - public void ChangeMusicWithEffect(ushort musicId, ushort effect) + } + + public void BroadcastPacket(SubPacket packet, bool sendToSelf) { - QueuePacket(SetMusicPacket.BuildPacket(actorId, musicId, effect)); - } - - public void SendChocoboAppearance() - { - BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance), true); - } - - public void SendGoobbueAppearance() - { - BroadcastPacket(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1), true); - } - - public void SetMountState(byte mountState) - { - this.mountState = mountState; - } - - public byte GetMountState() - { - return mountState; - } - - public void DoEmote(uint emoteId) - { - BroadcastPacket(ActorDoEmotePacket.BuildPacket(actorId, actorId, currentTarget, emoteId), true); - } - - public void SendGameMessage(Actor sourceActor, Actor textIdOwner, ushort textId, byte log, params object[] msgParams) - { - if (msgParams.Length == 0) - { - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log)); - } - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, params object[] msgParams) - { - if (msgParams.Length == 0) - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log)); - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams) - { - if (msgParams.Length == 0) - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log)); - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams) - { - if (msgParams.Length == 0) - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log)); - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void BroadcastWorldMessage(ushort worldMasterId, params object[] msgParams) - { - //SubPacket worldMasterMessage = - //zone.BroadcastPacketAroundActor(this, worldMasterMessage); - } - - public void GraphicChange(uint slot, uint graphicId) - { - appearanceIds[slot] = graphicId; - } - - public void GraphicChange(uint slot, uint weapId, uint equipId, uint variantId, uint colorId) - { - - uint mixedVariantId; - - if (weapId == 0) - mixedVariantId = ((variantId & 0x1F) << 5) | colorId; - else - mixedVariantId = variantId; - - uint graphicId = - (weapId & 0x3FF) << 20 | - (equipId & 0x3FF) << 10 | - (mixedVariantId & 0x3FF); - - appearanceIds[slot] = graphicId; - - } - - public void SendAppearance() - { - BroadcastPacket(CreateAppearancePacket(actorId), true); - } - - public void SendCharaExpInfo() - { - if (lastStep == 0) - { - int maxLength; - if ((sizeof(short) * charaWork.battleSave.skillLevel.Length)-lastPosition < 0x5E) - maxLength = (sizeof(short) * charaWork.battleSave.skillLevel.Length) - lastPosition; - else - maxLength = 0x5E; - - byte[] skillLevelBuffer = new byte[maxLength]; - Buffer.BlockCopy(charaWork.battleSave.skillLevel, 0, skillLevelBuffer, 0, skillLevelBuffer.Length); - SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); - - charaInfo1.SetIsArrayMode(true); - if (maxLength == 0x5E) - { - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x0); - lastPosition += maxLength; - } - else - { - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x3); - lastPosition = 0; - lastStep++; - } - - charaInfo1.AddTarget(); - - QueuePacket(charaInfo1.BuildPacket(actorId, actorId)); - } - else if (lastStep == 1) - { - int maxLength; - if ((sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition < 0x5E) - maxLength = (sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition; - else - maxLength = 0x5E; - - byte[] skillCapBuffer = new byte[maxLength]; - Buffer.BlockCopy(charaWork.battleSave.skillLevelCap, lastPosition, skillCapBuffer, 0, skillCapBuffer.Length); - SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); - - - if (maxLength == 0x5E) - { - charaInfo1.SetIsArrayMode(true); - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x1); - lastPosition += maxLength; - } - else - { - charaInfo1.SetIsArrayMode(false); - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x3); - lastStep = 0; - lastPosition = 0; - } - - charaInfo1.AddTarget(); - - QueuePacket(charaInfo1.BuildPacket(actorId, actorId)); - } - - } - - public InventoryItem[] GetGearset(ushort classId) - { - return Database.GetEquipment(this, classId); - } - - public void PrepareClassChange(byte classId) - { - //If new class, init abilties and level - - SendCharaExpInfo(); - } - - public void DoClassChange(byte classId) - { - //load hotbars - //Calculate stats - //Calculate hp/mp - - //Get Potenciel ?????? - - //Set HP/MP/TP PARAMS - - //Set mainskill and level - - //Set Parameters - - //Set current EXP - - //Set Hotbar Commands 1 - //Set Hotbar Commands 2 - //Set Hotbar Commands 3 - - //Check if bonus point available... set - - //Set rested EXP - - charaWork.parameterSave.state_mainSkill[0] = classId; - charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1]; - - playerWork.restBonusExpRate = 0.0f; - - ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/stateForAll", this, actorId); - - propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); - propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); - propertyBuilder.NewTarget("playerWork/expBonus"); - propertyBuilder.AddProperty("playerWork.restBonusExpRate"); - - List packets = propertyBuilder.Done(); - - foreach (SubPacket packet in packets) - BroadcastPacket(packet, true); - - Database.SavePlayerCurrentClass(this); - } - - public void GraphicChange(int slot, InventoryItem invItem) - { - if (invItem == null) - appearanceIds[slot] = 0; - else - { - Item item = Server.GetItemGamedata(invItem.itemId); - if (item is EquipmentItem) - { - EquipmentItem eqItem = (EquipmentItem)item; - - uint mixedVariantId; - - if (eqItem.graphicsWeaponId == 0) - mixedVariantId = ((eqItem.graphicsVariantId & 0x1F) << 5) | eqItem.graphicsColorId; - else - mixedVariantId = eqItem.graphicsVariantId; - - uint graphicId = - (eqItem.graphicsWeaponId & 0x3FF) << 20 | - (eqItem.graphicsEquipmentId & 0x3FF) << 10 | - (mixedVariantId & 0x3FF); - - appearanceIds[slot] = graphicId; - } - } - - Database.SavePlayerAppearance(this); - - BroadcastPacket(CreateAppearancePacket(actorId), true); - } - - public Inventory GetInventory(ushort type) - { - if (inventories.ContainsKey(type)) - return inventories[type]; - else - return null; - } - - public Actor GetActorInInstance(uint actorId) - { - foreach (Actor a in playerSession.actorInstanceList) - { - if (a.actorId == actorId) - return a; - } - - return null; - } - - public void SetZoneChanging(bool flag) - { - isZoneChanging = flag; - } - - public bool IsInZoneChange() - { - return isZoneChanging; - } - - 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) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) - return questScenario[i]; - } - - return null; - } - - public Quest GetQuest(string name) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].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++) - { - if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) - return true; - } - - return false; - } - - 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(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(); - } - - } - - public Director GetDirector() - { - return currentDirector; - } - - public void ExaminePlayer(Actor examinee) - { - Player toBeExamined; - if (examinee is Player) - toBeExamined = (Player)examinee; - else - return; - - QueuePacket(InventoryBeginChangePacket.BuildPacket(toBeExamined.actorId, actorId)); - toBeExamined.GetEquipment().SendCheckEquipmentToPlayer(this); - QueuePacket(InventoryEndChangePacket.BuildPacket(toBeExamined.actorId, actorId)); - } - - public void SendRequestedInfo(params object[] parameters) - { - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = InfoRequestResponsePacket.BuildPacket(actorId, actorId, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void StartEvent(Actor owner, EventStartPacket start) - { - //Have to do this to combine LuaParams - List objects = new List(); - objects.Add(this); - objects.Add(owner); - objects.Add(start.triggerName); - - if (start.luaParams != null) - objects.AddRange(LuaUtils.CreateLuaParamObjectList(start.luaParams)); - - if (owner is Npc) - { - currentEventRunning = ((Npc)owner).GetEventStartCoroutine(this); - - if (currentEventRunning != null) - { - try - { - currentEventRunning.Resume(objects.ToArray()); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } - else - { - EndEvent(); - } - } - else - { - currentEventRunning = LuaEngine.DoActorOnEventStarted(this, owner, start); - - if (currentEventRunning != null) - { - try - { - currentEventRunning.Resume(objects.ToArray()); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } - else - { - EndEvent(); - } - } - - } - - public void UpdateEvent(EventUpdatePacket update) - { - if (currentEventRunning == null) - return; - - if (currentEventRunning.State == CoroutineState.Suspended) - { - try - { - currentEventRunning.Resume(LuaUtils.CreateLuaParamObjectList(update.luaParams)); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } - } - - public void KickEvent(Actor actor, string conditionName, params object[] parameters) - { - if (actor == null) - return; - - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, conditionName, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void SetEventStatus(Actor actor, string conditionName, bool enabled, byte unknown) - { - QueuePacket(packets.send.actor.events.SetEventStatus.BuildPacket(actorId, actor.actorId, enabled, unknown, conditionName)); - } - - public void RunEventFunction(string functionName, params object[] parameters) - { - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = RunEventFunctionPacket.BuildPacket(actorId, currentEventOwner, currentEventName, functionName, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void EndEvent() - { - SubPacket p = EndEventPacket.BuildPacket(actorId, currentEventOwner, currentEventName); - p.DebugPrintSubPacket(); - QueuePacket(p); - - currentEventOwner = 0; - currentEventName = ""; - currentEventRunning = null; - } - - public void SendInstanceUpdate() + if (sendToSelf) + QueuePacket(packet); + + foreach (Actor a in playerSession.actorInstanceList) + { + if (a is Player) + { + Player p = (Player)a; + SubPacket clonedPacket = new SubPacket(packet, a.actorId); + p.QueuePacket(clonedPacket); + } + } + } + + public void SetDCFlag(bool flag) + { + if (flag) + { + BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, actorId, SetActorIconPacket.DISCONNECTING), true); + } + else + { + if (isGM) + BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, actorId, SetActorIconPacket.ISGM), true); + else + BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, actorId, 0), true); + } + } + + public void CleanupAndSave() + { + //Remove actor from zone and main server list + zone.RemoveActorFromZone(this); + Server.GetServer().RemovePlayer(this); + + //Save Player + Database.SavePlayerPlayTime(this); + Database.SavePlayerPosition(this); + + Program.Log.Info("{0} has been logged out and saved.", this.customDisplayName); + } + + public Area GetZone() + { + return zone; + } + + public void SendMessage(uint logType, string sender, string message) + { + QueuePacket(SendMessagePacket.BuildPacket(actorId, actorId, logType, sender, message)); + } + + public void Logout() + { + QueuePacket(LogoutPacket.BuildPacket(actorId)); + CleanupAndSave(); + } + + public void QuitGame() + { + QueuePacket(QuitPacket.BuildPacket(actorId)); + CleanupAndSave(); + } + + public uint GetPlayTime(bool doUpdate) + { + if (doUpdate) + { + uint curTime = Utils.UnixTimeStampUTC(); + playTime += curTime - lastPlayTimeUpdate; + lastPlayTimeUpdate = curTime; + } + + return playTime; + } + + public void ChangeMusic(ushort musicId) + { + QueuePacket(SetMusicPacket.BuildPacket(actorId, musicId, 1)); + } + + public void SendChocoboAppearance() + { + BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance), true); + } + + public void SendGoobbueAppearance() + { + BroadcastPacket(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1), true); + } + + public void SetMountState(byte mountState) + { + this.mountState = mountState; + } + + public byte GetMountState() + { + return mountState; + } + + public void DoEmote(uint emoteId) + { + BroadcastPacket(ActorDoEmotePacket.BuildPacket(actorId, actorId, currentTarget, emoteId), true); + } + + public void SendGameMessage(Actor sourceActor, Actor textIdOwner, ushort textId, byte log, params object[] msgParams) + { + if (msgParams.Length == 0) + { + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log)); + } + else + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); + } + + public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, params object[] msgParams) + { + if (msgParams.Length == 0) + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log)); + else + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); + } + + public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams) + { + if (msgParams.Length == 0) + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log)); + else + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams))); + } + + public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams) + { + if (msgParams.Length == 0) + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log)); + else + QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams))); + } + + public void BroadcastWorldMessage(ushort worldMasterId, params object[] msgParams) + { + //SubPacket worldMasterMessage = + //zone.BroadcastPacketAroundActor(this, worldMasterMessage); + } + + public void GraphicChange(uint slot, uint graphicId) + { + appearanceIds[slot] = graphicId; + } + + public void GraphicChange(uint slot, uint weapId, uint equipId, uint variantId, uint colorId) { - Server.GetWorldManager().SeamlessCheck(this); - + uint mixedVariantId; + + if (weapId == 0) + mixedVariantId = ((variantId & 0x1F) << 5) | colorId; + else + mixedVariantId = variantId; + + uint graphicId = + (weapId & 0x3FF) << 20 | + (equipId & 0x3FF) << 10 | + (mixedVariantId & 0x3FF); + + appearanceIds[slot] = graphicId; + + } + + public void SendAppearance() + { + BroadcastPacket(CreateAppearancePacket(actorId), true); + } + + public void SendCharaExpInfo() + { + if (lastStep == 0) + { + int maxLength; + if ((sizeof(short) * charaWork.battleSave.skillLevel.Length)-lastPosition < 0x5E) + maxLength = (sizeof(short) * charaWork.battleSave.skillLevel.Length) - lastPosition; + else + maxLength = 0x5E; + + byte[] skillLevelBuffer = new byte[maxLength]; + Buffer.BlockCopy(charaWork.battleSave.skillLevel, 0, skillLevelBuffer, 0, skillLevelBuffer.Length); + SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); + + charaInfo1.SetIsArrayMode(true); + if (maxLength == 0x5E) + { + charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x0); + lastPosition += maxLength; + } + else + { + charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x3); + lastPosition = 0; + lastStep++; + } + + charaInfo1.AddTarget(); + + QueuePacket(charaInfo1.BuildPacket(actorId, actorId)); + } + else if (lastStep == 1) + { + int maxLength; + if ((sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition < 0x5E) + maxLength = (sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition; + else + maxLength = 0x5E; + + byte[] skillCapBuffer = new byte[maxLength]; + Buffer.BlockCopy(charaWork.battleSave.skillLevelCap, lastPosition, skillCapBuffer, 0, skillCapBuffer.Length); + SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); + + + if (maxLength == 0x5E) + { + charaInfo1.SetIsArrayMode(true); + charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x1); + lastPosition += maxLength; + } + else + { + charaInfo1.SetIsArrayMode(false); + charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x3); + lastStep = 0; + lastPosition = 0; + } + + charaInfo1.AddTarget(); + + QueuePacket(charaInfo1.BuildPacket(actorId, actorId)); + } + + } + + public InventoryItem[] GetGearset(ushort classId) + { + return Database.GetEquipment(this, classId); + } + + public void PrepareClassChange(byte classId) + { + //If new class, init abilties and level + + SendCharaExpInfo(); + } + + public void DoClassChange(byte classId) + { + //load hotbars + //Calculate stats + //Calculate hp/mp + + //Get Potenciel ?????? + + //Set HP/MP/TP PARAMS + + //Set mainskill and level + + //Set Parameters + + //Set current EXP + + //Set Hotbar Commands 1 + //Set Hotbar Commands 2 + //Set Hotbar Commands 3 + + //Check if bonus point available... set + + //Set rested EXP + + charaWork.parameterSave.state_mainSkill[0] = classId; + charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1]; + + playerWork.restBonusExpRate = 0.0f; + + ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/stateForAll", this, actorId); + + propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); + propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); + propertyBuilder.NewTarget("playerWork/expBonus"); + propertyBuilder.AddProperty("playerWork.restBonusExpRate"); + + List packets = propertyBuilder.Done(); + + foreach (SubPacket packet in packets) + BroadcastPacket(packet, true); + + Database.SavePlayerCurrentClass(this); + } + + public void GraphicChange(int slot, InventoryItem invItem) + { + if (invItem == null) + appearanceIds[slot] = 0; + else + { + Item item = Server.GetItemGamedata(invItem.itemId); + if (item is EquipmentItem) + { + EquipmentItem eqItem = (EquipmentItem)item; + + uint mixedVariantId; + + if (eqItem.graphicsWeaponId == 0) + mixedVariantId = ((eqItem.graphicsVariantId & 0x1F) << 5) | eqItem.graphicsColorId; + else + mixedVariantId = eqItem.graphicsVariantId; + + uint graphicId = + (eqItem.graphicsWeaponId & 0x3FF) << 20 | + (eqItem.graphicsEquipmentId & 0x3FF) << 10 | + (mixedVariantId & 0x3FF); + + appearanceIds[slot] = graphicId; + } + } + + Database.SavePlayerAppearance(this); + + BroadcastPacket(CreateAppearancePacket(actorId), true); + } + + public Inventory GetInventory(ushort type) + { + if (inventories.ContainsKey(type)) + return inventories[type]; + else + return null; + } + + public Actor GetActorInInstance(uint actorId) + { + foreach (Actor a in playerSession.actorInstanceList) + { + if (a.actorId == actorId) + return a; + } + + return null; + } + + public void SetZoneChanging(bool flag) + { + isZoneChanging = flag; + } + + public bool IsInZoneChange() + { + return isZoneChanging; + } + + 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) + { + for (int i = 0; i < questScenario.Length; i++) + { + if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) + return questScenario[i]; + } + + return null; + } + + public Quest GetQuest(string name) + { + for (int i = 0; i < questScenario.Length; i++) + { + if (questScenario[i] != null && questScenario[i].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++) + { + if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) + return true; + } + + return false; + } + + 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(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(); + } + + } + + public Director GetDirector() + { + return currentDirector; + } + + public void ExaminePlayer(Actor examinee) + { + Player toBeExamined; + if (examinee is Player) + toBeExamined = (Player)examinee; + else + return; + + QueuePacket(InventoryBeginChangePacket.BuildPacket(toBeExamined.actorId, actorId)); + toBeExamined.GetEquipment().SendCheckEquipmentToPlayer(this); + QueuePacket(InventoryEndChangePacket.BuildPacket(toBeExamined.actorId, actorId)); + } + + public void SendRequestedInfo(params object[] parameters) + { + List lParams = LuaUtils.CreateLuaParamList(parameters); + SubPacket spacket = InfoRequestResponsePacket.BuildPacket(actorId, actorId, lParams); + spacket.DebugPrintSubPacket(); + QueuePacket(spacket); + } + + public void StartEvent(Actor owner, EventStartPacket start) + { + //Have to do this to combine LuaParams + List objects = new List(); + objects.Add(this); + objects.Add(owner); + objects.Add(start.triggerName); + + if (start.luaParams != null) + objects.AddRange(LuaUtils.CreateLuaParamObjectList(start.luaParams)); + + if (owner is Npc) + { + currentEventRunning = ((Npc)owner).GetEventStartCoroutine(this); + + if (currentEventRunning != null) + { + try + { + currentEventRunning.Resume(objects.ToArray()); + } + catch (ScriptRuntimeException e) + { + Program.Log.Error("[LUA] {0}", e.DecoratedMessage); + EndEvent(); + } + } + else + { + EndEvent(); + } + } + else + { + currentEventRunning = LuaEngine.DoActorOnEventStarted(this, owner, start); + + if (currentEventRunning != null) + { + try + { + currentEventRunning.Resume(objects.ToArray()); + } + catch (ScriptRuntimeException e) + { + Program.Log.Error("[LUA] {0}", e.DecoratedMessage); + EndEvent(); + } + } + else + { + EndEvent(); + } + } + + } + + public void UpdateEvent(EventUpdatePacket update) + { + if (currentEventRunning == null) + return; + + if (currentEventRunning.State == CoroutineState.Suspended) + { + try + { + currentEventRunning.Resume(LuaUtils.CreateLuaParamObjectList(update.luaParams)); + } + catch (ScriptRuntimeException e) + { + Program.Log.Error("[LUA] {0}", e.DecoratedMessage); + EndEvent(); + } + } + } + + public void KickEvent(Actor actor, string conditionName, params object[] parameters) + { + if (actor == null) + return; + + List lParams = LuaUtils.CreateLuaParamList(parameters); + SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, conditionName, lParams); + spacket.DebugPrintSubPacket(); + QueuePacket(spacket); + } + + public void SetEventStatus(Actor actor, string conditionName, bool enabled, byte unknown) + { + QueuePacket(packets.send.actor.events.SetEventStatus.BuildPacket(actorId, actor.actorId, enabled, unknown, conditionName)); + } + + public void RunEventFunction(string functionName, params object[] parameters) + { + List lParams = LuaUtils.CreateLuaParamList(parameters); + SubPacket spacket = RunEventFunctionPacket.BuildPacket(actorId, currentEventOwner, currentEventName, functionName, lParams); + spacket.DebugPrintSubPacket(); + QueuePacket(spacket); + } + + public void EndEvent() + { + SubPacket p = EndEventPacket.BuildPacket(actorId, currentEventOwner, currentEventName); + p.DebugPrintSubPacket(); + QueuePacket(p); + + currentEventOwner = 0; + currentEventName = ""; + currentEventRunning = null; + } + + public void SendInstanceUpdate() + { + + Server.GetWorldManager().SeamlessCheck(this); + //Update Instance List aroundMe = new List(); aroundMe.AddRange(zone.GetActorsAroundActor(this, 50)); if (zone2 != null) aroundMe.AddRange(zone2.GetActorsAroundActor(this, 50)); - playerSession.UpdateInstance(aroundMe); - - } - - public void issueChocobo(byte appearanceId, string name) + playerSession.UpdateInstance(aroundMe); + + } + + public void IssueChocobo(byte appearanceId, string nameResponse) { - Database.IssuePlayerChocobo(this, appearanceId, name); + Database.IssuePlayerChocobo(this, appearanceId, nameResponse); hasChocobo = true; chocoboAppearance = appearanceId; - chocoboName = name; - } - - public void changeChocoboAppearance(int appearanceId) - { - - } - } -} + chocoboName = nameResponse; + } + } +} diff --git a/FFXIVClassic Map Server/lua/LuaPlayer.cs b/FFXIVClassic Map Server/lua/LuaPlayer.cs index 5ad16978..aa2aa5b7 100644 --- a/FFXIVClassic Map Server/lua/LuaPlayer.cs +++ b/FFXIVClassic Map Server/lua/LuaPlayer.cs @@ -25,6 +25,11 @@ namespace FFXIVClassic_Map_Server.lua player.playerSession.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weatherID, 1), true, false); } + public void IssueChocobo(int appearanceId, string name) + { + player.IssueChocobo((byte) appearanceId, name); + } + public void GetParameter(string paramName) { From 00e5e4f642bcf3f7dddae6766c61ca259e74462d Mon Sep 17 00:00:00 2001 From: Jordan Maxwell Date: Fri, 19 Aug 2016 17:43:04 -0500 Subject: [PATCH 7/7] Updated Chocobo Lender script --- FFXIVClassic Map Server/WorldManager.cs | 2 - .../npc/populace/PopulaceChocoboLender.lua | 55 ++++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index aa5bdfe5..34e0f189 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -735,7 +735,5 @@ namespace FFXIVClassic_Map_Server else return null; } - } - } diff --git a/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua b/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua index 62ba4f81..9f73179f 100644 --- a/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua +++ b/data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua @@ -21,39 +21,45 @@ end function onEventStarted(player, npc, triggerName) - local curLevel = 20; - local hasIssuance = true; + local curLevel = 20; -- TODO: pull from character + local hasIssuance = true; -- TODO: pull from character local hasChocobo = player.hasChocobo; - if (player.isGM and hasChocobo == false) then + if (player.isGM and hasChocobo == false) then -- Let GMs auto have the issuance for debugging hasIssuance = true; end + if (hasChocobo) then + hasIssuance = false; + end + local rentPrice = 800; local playerFunds = 0; --TODO: pull character's money local hasFunds = (playerFunds >= rentPrice); callClientFunction(player, "eventTalkWelcome", player); - menuChoice = callClientFunction(player, "eventAskMainMenu", player, curLevel, hasFunds, hasIssuance, hasChocobo, hasChocobo, 4); + local menuChoice = callClientFunction(player, "eventAskMainMenu", player, curLevel, hasFunds, hasIssuance, hasChocobo, hasChocobo, 4); if (menuChoice == 1) then -- Issuance option callClientFunction(player, "eventTalkMyChocobo", player); - nameResponse = callClientFunction(player, "eventSetChocoboName", false); + local nameResponse = callClientFunction(player, "eventSetChocoboName", false); if (nameResponse == "") then -- Cancel Chocobo naming - callClientFunction(player, "eventCancelChocoboName", player); + local cancelState = callClientFunction(player, "eventCancelChocoboName", player); + --Do anything with cancel state? end - appearance = 1; -- TODO: pull correct appearance based on GC - --player:issueChocobo(appearance, nameResponse); + local appearance = 1; -- TODO: pull correct appearance based on GC + player:IssueChocobo(appearance, nameResponse); if (nameResponse ~= "") then -- Successfully named Chocobo callClientFunction(player, "eventAfterChocoboName", player); end - elseif(menuChoice == 2 and hasChocobo) then -- Summon Bird - player:ChangeMusic(83); - player:SendChocoboAppearance(); - player:SendGameMessage(player, worldMaster, 26001, 0x20); - player:SetMountState(1); + + mountChocobo(player); + teleportOutOfCity(player); + elseif(menuChoice == 2) then -- Summon Bird + mountChocobo(player); + teleportOutOfCity(player); elseif(menuChoice == 3) then -- Change Barding callClientFunction(player, "eventTalkStepBreak", player); elseif(menuChoice == 5) then -- Rent Bird @@ -67,4 +73,27 @@ function onEventStarted(player, npc, triggerName) end player:EndEvent(); +end + +function mountChocobo(player) + --TODO fix this + --[[ + player:ChangeMusic(83); + player:SendChocoboAppearance(); + player:SendGameMessage(player, worldMaster, 26001, 0x20); + player:SetMountState(1); + ]] +end + +function teleportOutOfCity(player) + --TODO: Teleport out of city + local zoneId = player:GetPos()[4]; + local worldManager = GetWorldManager(); + if(zoneId == 155) then --Gridania + worldManager:DoZoneChange(player, 150, nil, 0x02, 319, 4, -996, 0.00); + elseif(zoneId == 133) then -- Limsa + worldManager:DoZoneChange(player, 133, nil, 0x02, -73, 30, 169, 2); + elseif(zoneId == 175) then -- Ul'dah + + end end \ No newline at end of file