From 062a24a4edd4f8c1789c5d5e1388bb5f915fb92b Mon Sep 17 00:00:00 2001 From: SilicaAndPina Date: Tue, 5 Jan 2021 20:09:12 +1300 Subject: [PATCH] add horse catching minigame, --- DataCollection/gamedata.json | 7 +- .../Horse Isle Server/Game/Horse/WildHorse.cs | 89 ++++++++++++++++++- .../Game/Inventory/HorseInventory.cs | 12 +++ .../Horse Isle Server/Game/Messages.cs | 10 +++ .../Horse Isle Server/Game/Meta.cs | 31 ++++++- .../Horse Isle Server/Player/User.cs | 2 + .../Horse Isle Server/Server/Database.cs | 67 ++++++++++++++ .../Horse Isle Server/Server/GameClient.cs | 3 + .../Horse Isle Server/Server/GameDataJson.cs | 6 +- .../Horse Isle Server/Server/GameServer.cs | 82 ++++++++++++++++- .../Horse Isle Server/Server/PacketBuilder.cs | 5 ++ 11 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 Horse Isle Server/Horse Isle Server/Game/Inventory/HorseInventory.cs diff --git a/DataCollection/gamedata.json b/DataCollection/gamedata.json index c6e7a40..3482141 100644 --- a/DataCollection/gamedata.json +++ b/DataCollection/gamedata.json @@ -131,7 +131,12 @@ "password_input":"
^PLReply:|^PS14|ANSWER^R1", "last_poet":"^R1^LLast Player Poet:%USERNAME% ^R1", "horse":{ - "stat_format":"%BASE%;%COMPAINON%;%TACK%;%MAX%;" + "stat_format":"%BASE%;%COMPAINON%;%TACK%;%MAX%;", + "horses_here":"HORSES HERE:
", + "wild_horse":"^I252^T6%NAME%, It's a %BREED%^B3U%RANDOMID%^R1", + "horse_timer":"You have 60 seconds to capture the horse. Good luck!", + "horse_escaped":"The Horse Evaded Capture.", + "hore_caught":"You Captured the Horse!" }, "libary":{ "main_menu":"Welcome to the Library! You can research different subjects.
^T2Search Residents: ^D30|SEARCH NPC^R1^T2Search Ranches: ^D31|SEARCH RANCH^R1^T2Research Horses: ^D4|VIEW BREEDS^R1^T2Research Tack: ^D9|VIEW TACK^R1^T2Research Companions: ^D10|VIEW COMPANIONS^R1^T2Research Mini-Games: ^D12|VIEW MINIGAMES^R1^T2Research Locations: ^D22|VIEW LOCATIONS^R1^T2Research Awards: ^D23|VIEW AWARDS^R1^T2Read Books: ^D38|READ BOOKS^R1", diff --git a/Horse Isle Server/Horse Isle Server/Game/Horse/WildHorse.cs b/Horse Isle Server/Horse Isle Server/Game/Horse/WildHorse.cs index 58025a9..d63ee37 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Horse/WildHorse.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Horse/WildHorse.cs @@ -1,4 +1,5 @@ -using HISP.Server; +using HISP.Player; +using HISP.Server; using System; using System.Collections.Generic; using System.Linq; @@ -79,11 +80,44 @@ namespace HISP.Game.Horse } } } + else + { + x = MapX; + y = MapY; + } wildHorses.Add(this); if(addToDatabase) Database.AddWildHorse(this); } + public void Escape() + { + while(true) + { + int tryX = X + GameServer.RandomNumberGenerator.Next(-15, 15); + int tryY = Y + GameServer.RandomNumberGenerator.Next(-15, 15); + + // Horses cannot be in towns. + if (World.InTown(tryX, tryY)) + continue; + if (World.InSpecialTile(tryX, tryY)) + continue; + + if (Map.CheckPassable(tryX, tryY)) + { + X = tryX; + Y = tryY; + break; + } + } + + } + + public void Capture(User forUser) + { + Despawn(this); + } + private static List wildHorses = new List(); public static WildHorse[] WildHorses { @@ -115,6 +149,56 @@ namespace HISP.Game.Horse Database.LoadWildHorses(); GenerateHorses(); } + + public static WildHorse[] GetHorsesAt(int x, int y) + { + List horses = new List(); + foreach (WildHorse wildHorse in WildHorses) + { + if (wildHorse.X == x && wildHorse.Y == y) + horses.Add(wildHorse); + } + return horses.ToArray(); + } + + public static bool DoesHorseExist(int randomId) + { + foreach (WildHorse wildHorse in WildHorses) + { + if (wildHorse.Instance.RandomId == randomId) + return true; + } + return false; + } + public static WildHorse GetHorseById(int randomId) + { + foreach(WildHorse wildHorse in WildHorses) + { + if (wildHorse.Instance.RandomId == randomId) + return wildHorse; + } + throw new KeyNotFoundException("No horse with id: " + randomId + " was found."); + } + + public static void Despawn(WildHorse horse) + { + Database.RemoveWildHorse(horse.Instance.RandomId); + wildHorses.Remove(horse); + } + + public static void Update() + { + foreach(WildHorse wildHorse in WildHorses) + { + wildHorse.Timeout -= 1; + if (wildHorse.Timeout <= 0) + Despawn(wildHorse); + } + if(WildHorses.Length < 40) + { + GenerateHorses(); + } + } public HorseInstance Instance; public int X { @@ -124,6 +208,7 @@ namespace HISP.Game.Horse } set { + Database.SetWildHorseX(this.Instance.RandomId, value); x = value; } } @@ -135,6 +220,7 @@ namespace HISP.Game.Horse } set { + Database.SetWildHorseY(this.Instance.RandomId, value); y = value; } } @@ -146,6 +232,7 @@ namespace HISP.Game.Horse } set { + Database.SetWildHorseTimeout(this.Instance.RandomId, value); timeout = value; } } diff --git a/Horse Isle Server/Horse Isle Server/Game/Inventory/HorseInventory.cs b/Horse Isle Server/Horse Isle Server/Game/Inventory/HorseInventory.cs new file mode 100644 index 0000000..e866e2a --- /dev/null +++ b/Horse Isle Server/Horse Isle Server/Game/Inventory/HorseInventory.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HISP.Game.Inventory +{ + class HorseInventory + { + } +} diff --git a/Horse Isle Server/Horse Isle Server/Game/Messages.cs b/Horse Isle Server/Horse Isle Server/Game/Messages.cs index f05a041..2fbfb79 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Messages.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Messages.cs @@ -164,6 +164,11 @@ namespace HISP.Game // Horse public static string BreedViewerMaximumStats; public static string StatFormat; + public static string HorsesHere; + public static string WildHorseFormat; + public static string HorseCaptureTimer; + public static string YouCapturedTheHorse; + public static string HorseEvadedCapture; // Consume @@ -355,6 +360,11 @@ namespace HISP.Game // Click public static string NothingInterestingHere; + + public static string FormatWildHorse(string name, string breed, int randomId) + { + return WildHorseFormat.Replace("%NAME%", name).Replace("%BREED%", breed).Replace("%RANDOMID%", randomId.ToString()); + } public static string FormatHorseBreedPreview(string name, string description) { return BreedViewerFormat.Replace("%NAME%", name).Replace("%DESCRIPTION%", description); diff --git a/Horse Isle Server/Horse Isle Server/Game/Meta.cs b/Horse Isle Server/Horse Isle Server/Game/Meta.cs index 94b19d1..6f9f153 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Meta.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Meta.cs @@ -434,7 +434,20 @@ namespace HISP.Game return message; } - + public static string BuildHorseList(User user) + { + string message = ""; + WildHorse[] horses = WildHorse.GetHorsesAt(user.X, user.Y); + if(horses.Length > 0) + { + message = Messages.HorsesHere; + foreach(WildHorse horse in horses) + { + message += Messages.FormatWildHorse(horse.Instance.Name, horse.Instance.Breed.Name, horse.Instance.RandomId); + } + } + return message; + } public static string BuildAwardList(User user) { string message = Messages.AwardHeader; @@ -835,9 +848,23 @@ namespace HISP.Game + return message; + } + public static string BuildHorseEscapedMessage() + { + string message = Messages.HorseEvadedCapture; + message += Messages.BackToMap; + message += Messages.MetaTerminator; return message; } + public static string BuildHorseCaughtMessage() + { + string message = Messages.YouCapturedTheHorse; + message += Messages.BackToMap; + message += Messages.MetaTerminator; + return message; + } public static string BuildAbuseReportPage() { @@ -960,7 +987,7 @@ namespace HISP.Game { string message = ""; message += buildLocationString(x, y); - + message += BuildHorseList(user); message += buildNpc(user, x, y); diff --git a/Horse Isle Server/Horse Isle Server/Player/User.cs b/Horse Isle Server/Horse Isle Server/Player/User.cs index 10608f4..0de948c 100644 --- a/Horse Isle Server/Horse Isle Server/Player/User.cs +++ b/Horse Isle Server/Horse Isle Server/Player/User.cs @@ -5,6 +5,7 @@ using HISP.Server; using HISP.Player.Equips; using HISP.Game.Services; using HISP.Game.Inventory; +using HISP.Game.Horse; namespace HISP.Player { @@ -45,6 +46,7 @@ namespace HISP.Player public PlayerQuests Quests; public Highscore Highscores; public Award Awards; + public int CapturingHorseId; public DateTime LoginTime; public DateTime SubscribedUntil diff --git a/Horse Isle Server/Horse Isle Server/Server/Database.cs b/Horse Isle Server/Horse Isle Server/Server/Database.cs index e4b90c8..769d3db 100644 --- a/Horse Isle Server/Horse Isle Server/Server/Database.cs +++ b/Horse Isle Server/Horse Isle Server/Server/Database.cs @@ -34,11 +34,26 @@ namespace HISP.Server string Leaderboards = "CREATE TABLE Leaderboards(playerId INT, minigame TEXT(128), wins INT, looses INT, timesplayed INT, score INT, type TEXT(128))"; string NpcStartPoint = "CREATE TABLE NpcStartPoint(playerId INT, npcId INT, chatpointId INT)"; string PoetryRooms = "CREATE TABLE PoetryRooms(poetId INT, X INT, Y INT, roomId INT)"; + string Horses = "CREATE TABLE Horses(randomId INT, originalOwner INT, breed INT, name TEXT(128), description TEXT(1028), sex TEXT(128), color TEXT(128), health INT, shoes INT, hunger INT, thirst INT, mood INT, groom INT, tiredness INT, experience INT, speed INT, strength INT, conformation INT, agility INT, endurance INT, inteligence INT, personality INT, height INT, saddle INT, saddlepad INT, bridle INT, companion INT, autoSell INT, category TEXT(128), spoiled INT, magicUsed INT)" string WildHorse = "CREATE TABLE WildHorse(randomId INT, originalOwner INT, breed INT, x INT, y INT, name TEXT(128), description TEXT(1028), sex TEXT(128), color TEXT(128), health INT, shoes INT, hunger INT, thirst INT, mood INT, groom INT, tiredness INT, experience INT, speed INT, strength INT, conformation INT, agility INT, endurance INT, inteligence INT, personality INT, height INT, saddle INT, saddlepad INT, bridle INT, companion INT, timeout INT, autoSell INT, category TEXT(128), spoiled INT, magicUsed INT)"; string LastPlayer = "CREATE TABLE LastPlayer(roomId TEXT(1028), playerId INT)"; string DeleteOnlineUsers = "DELETE FROM OnlineUsers"; + try + { + + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = Horses; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + catch (Exception e) + { + Logger.WarnPrint(e.Message); + }; + + try { @@ -325,6 +340,58 @@ namespace HISP.Server } } + public static void SetWildHorseX(int randomId, int x) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "UPDATE WildHorse SET x=@x WHERE randomId=@randomId"; + sqlCommand.Parameters.AddWithValue("@randomId", randomId); + sqlCommand.Parameters.AddWithValue("@x", x); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + public static void SetWildHorseTimeout(int randomId, int timeout) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "UPDATE WildHorse SET timeout=@timeout WHERE randomId=@randomId"; + sqlCommand.Parameters.AddWithValue("@randomId", randomId); + sqlCommand.Parameters.AddWithValue("@timeout", timeout); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + public static void RemoveWildHorse(int randomId) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "DELETE FROM WildHorse WHERE randomId=@randomId"; + sqlCommand.Parameters.AddWithValue("@randomId", randomId); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + + public static void SetWildHorseY(int randomId, int x) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "UPDATE WildHorse SET y=@y WHERE randomId=@randomId"; + sqlCommand.Parameters.AddWithValue("@randomId", randomId); + sqlCommand.Parameters.AddWithValue("@y", x); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } public static void AddWildHorse(WildHorse horse) { diff --git a/Horse Isle Server/Horse Isle Server/Server/GameClient.cs b/Horse Isle Server/Horse Isle Server/Server/GameClient.cs index 58a74bc..4f09980 100644 --- a/Horse Isle Server/Horse Isle Server/Server/GameClient.cs +++ b/Horse Isle Server/Horse Isle Server/Server/GameClient.cs @@ -245,6 +245,9 @@ namespace HISP.Server case PacketBuilder.PACKET_SWFMODULE: GameServer.OnSwfModuleCommunication(this, Packet); break; + case PacketBuilder.PACKET_HORSE: + GameServer.OnHorseInteraction(this, Packet); + break; case PacketBuilder.PACKET_WISH: GameServer.OnWish(this, Packet); break; diff --git a/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs b/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs index e61af5e..27e8921 100644 --- a/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs +++ b/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs @@ -589,7 +589,11 @@ namespace HISP.Server // Horses Messages.StatFormat = gameData.messages.meta.horse.stat_format; - + Messages.HorsesHere = gameData.messages.meta.horse.horses_here; + Messages.WildHorseFormat = gameData.messages.meta.horse.wild_horse; + Messages.HorseCaptureTimer = gameData.messages.meta.horse.horse_timer; + Messages.YouCapturedTheHorse = gameData.messages.meta.horse.hore_caught; + Messages.HorseEvadedCapture = gameData.messages.meta.horse.horse_escaped; // Libary Messages.LibaryMainMenu = gameData.messages.meta.libary.main_menu; diff --git a/Horse Isle Server/Horse Isle Server/Server/GameServer.cs b/Horse Isle Server/Horse Isle Server/Server/GameServer.cs index 94e289c..6c5fcb1 100644 --- a/Horse Isle Server/Horse Isle Server/Server/GameServer.cs +++ b/Horse Isle Server/Horse Isle Server/Server/GameServer.cs @@ -64,7 +64,7 @@ namespace HISP.Server Database.IncPlayerTirednessForOfflineUsers(); DroppedItems.Update(); - WildHorse.GenerateHorses(); + WildHorse.Update(); minuteTimer.Change(oneMinute, oneMinute); } @@ -81,6 +81,86 @@ namespace HISP.Server sender.SendPacket(crossDomainPolicyResponse); } + + public static void OnHorseInteraction(GameClient sender, byte[] packet) + { + if (!sender.LoggedIn) + { + Logger.ErrorPrint(sender.RemoteIp + " Sent horse interaction when not logged in."); + return; + } + + if(packet.Length < 4) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid sized horse interaction packet."); + return; + } + + byte method = packet[1]; + switch(method) + { + case PacketBuilder.HORSE_ESCAPE: + if(WildHorse.DoesHorseExist(sender.LoggedinUser.CapturingHorseId)) + { + WildHorse capturing = WildHorse.GetHorseById(sender.LoggedinUser.CapturingHorseId); + capturing.Escape(); + Logger.InfoPrint(sender.LoggedinUser.Username + " Failed to capture: " + capturing.Instance.Breed.Name + " new location: " + capturing.X + ", " + capturing.Y); + + sender.LoggedinUser.MetaPriority = true; + byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildHorseEscapedMessage()); + sender.SendPacket(metaPacket); + + UpdateAreaForAll(sender.LoggedinUser.X, sender.LoggedinUser.Y); + } + + break; + case PacketBuilder.HORSE_CAUGHT: + if (WildHorse.DoesHorseExist(sender.LoggedinUser.CapturingHorseId)) + { + WildHorse capturing = WildHorse.GetHorseById(sender.LoggedinUser.CapturingHorseId); + capturing.Capture(sender.LoggedinUser); + Logger.InfoPrint(sender.LoggedinUser.Username + " Captured a: " + capturing.Instance.Breed.Name + " new location: " + capturing.X + ", " + capturing.Y); + + sender.LoggedinUser.MetaPriority = true; + byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildHorseCaughtMessage()); + sender.SendPacket(metaPacket); + + UpdateAreaForAll(sender.LoggedinUser.X, sender.LoggedinUser.Y); + } + + break; + case PacketBuilder.HORSE_TRY_CAPTURE: + int randomId = 0; + string packetStr = Encoding.UTF8.GetString(packet); + string randomIdStr = packetStr.Substring(2, packetStr.Length - 4); + try + { + randomId = int.Parse(randomIdStr); + + } + catch (Exception) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid randomid to horse interaction packet "); + return; + } + if (!WildHorse.DoesHorseExist(randomId)) + { + Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to catch a horse that doesnt exist."); + return; + } + sender.LoggedinUser.CapturingHorseId = randomId; + byte[] chatPacket = PacketBuilder.CreateChat(Messages.HorseCaptureTimer, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(chatPacket); + byte[] swfModulePacket = PacketBuilder.CreateSwfModulePacket("catchhorse", PacketBuilder.PACKET_SWF_MODULE_FORCE); + sender.SendPacket(swfModulePacket); + + break; + default: + Logger.DebugPrint("Unknown horse packet: " + BitConverter.ToString(packet).Replace("-", " ")); + break; + } + } + public static void OnDynamicInputReceived(GameClient sender, byte[] packet) { if (!sender.LoggedIn) diff --git a/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs b/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs index 6d3e4f7..3eb4665 100644 --- a/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs +++ b/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs @@ -24,6 +24,7 @@ namespace HISP.Server public const byte PACKET_SWF_MODULE_FORCE = 0x28; public const byte PACKET_SWF_MODULE_GENTLE = 0x2A; public const byte PACKET_PLACE_INFO = 0x1E; + public const byte PACKET_HORSE = 0x19; public const byte PACKET_AREA_DEFS = 0x79; public const byte PACKET_ITEM_INTERACTION = 0x1E; public const byte PACKET_ANNOUNCEMENT = 0x7E; @@ -44,6 +45,10 @@ namespace HISP.Server public const byte PACKET_WISH = 0x2C; public const byte PACKET_SWFMODULE = 0x50; + public const byte HORSE_TRY_CAPTURE = 0x1C; + public const byte HORSE_ESCAPE = 0x1E; + public const byte HORSE_CAUGHT = 0x1D; + public const byte SWFMODULE_BRICKPOET = 0x5A; public const byte BRICKPOET_LIST_ALL = 0x14;