From 4020ebaa620d638aa00380b879a8855dbc568b76 Mon Sep 17 00:00:00 2001 From: SilicaAndPina Date: Thu, 14 Jan 2021 18:11:57 +1300 Subject: [PATCH] Implement companions --- DataCollection/gamedata.json | 13 ++++- .../Horse Isle Server/Game/Messages.cs | 43 ++++++++++++++-- .../Horse Isle Server/Game/Meta.cs | 25 +++++++++- .../Horse Isle Server/Server/Database.cs | 27 ++++++++++ .../Horse Isle Server/Server/GameDataJson.cs | 17 +++++-- .../Horse Isle Server/Server/GameServer.cs | 50 ++++++++++++++++++- 6 files changed, 164 insertions(+), 11 deletions(-) diff --git a/DataCollection/gamedata.json b/DataCollection/gamedata.json index 0ec0cdf..c4290ad 100644 --- a/DataCollection/gamedata.json +++ b/DataCollection/gamedata.json @@ -157,6 +157,15 @@ "pet_horse":"Your horse whinnies lightly. (+%MOOD% mood / -%TIREDNESS% tiredness)", "pet_horse_too_happy":"Your horse is as happy as it can be now. Your horse whinnies lightly. (+%MOOD% mood / -%TIREDNESS% tiredness)", "description_edit":"^PLHorse's Name:|%HORSENAME%^D11|GENERATE RANDOM HORSE NAME^R1^LDescription: (reset if you generate name)^R1^PB120|%DESCRIPTION%^PS5|SAVE CHANGES", + "tack_fail_autosell":"You cannot put tack on a horse with Auto-Sell set.", + "companion_menu":{ + "menu_header":"%HORSENAME%'s current companion:
", + "companions_avalible":"^LYou have the following companions available:^R1", + "companion_entry":"^I%ICONID%^T5[ %COUNT% ] %NAME%^B3K%ID%^R1", + "selected_companion":"^I%ICONID%^T5%NAME%^B3M4^R1", + "companion_equip_message":"You gave %HORSENAME% a %ITEM% for a companion.", + "companion_remove_message":"You removed the companion from %HORSENAME%." + }, "auto_sell":{ "auto_sell_meta":"Auto-Selling a horse:
By setting this value, any other player can buy this horse from you at any time. If you have a Ranch, they can even buy the horse when you are offline! (Put the cost to 0 to stop it from being for auto-sale.)^PMAuto-Sell horse for:|%AUTOSELL%^PS10|SET COST", "auto_sell_confirmed":"Setting up Auto-Sell for horse at $%MONEY%", @@ -189,7 +198,9 @@ "no_auto_sell":"NO Auto-Sell", "auto_sell_format":"Auto-Selling: $%MONEY%", - "auto_sell":"^R1^T2[%AUTOSELL%]^D25|SET AUTO-SELL PRICE", + "change_auto_sell":"^D25|CHANGE AUTO-SELL", + "set_auto_sell":"^D25|SET AUTO-SELL PRICE", + "auto_sell":"^R1^T2[%AUTOSELL%]", "cannot_auto_sell_tacked":"^R1^T8Cannot set Auto-Sell on a Horse with Tack", "marked_as":"^R1^LHorse currently marked [%CATEGORY%]. Mark:^R1^D52c1|KEEPER^D52c2|TRAINING^D52c3|TRADING^D52c4|RETIRED^R1", diff --git a/Horse Isle Server/Horse Isle Server/Game/Messages.cs b/Horse Isle Server/Horse Isle Server/Game/Messages.cs index 5435220..4d9ad4f 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Messages.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Messages.cs @@ -227,6 +227,19 @@ namespace HISP.Game public static string HorseAutoSellConfirmedFormat; public static string HorseAutoSellRemoved; + public static string HorseChangeAutoSell; + public static string HorseSetAutoSell; + + public static string HorseTackFailAutoSell; + + // Horse compainion menu + public static string HorseCompanionMenuHeaderFormat; + public static string HorseCompnaionMenuCurrentCompanionFormat; + public static string HorseCompanionEntryFormat; + public static string HorseCompanionEquipMessageFormat; + public static string HorseCompanionRemoveMessageFormat; + public static string HorseCompanionMenuCurrentlyAvalibleCompanions; + // Horse Feed Menu public static string HorseCurrentStatusFormat; public static string HorseHoldingHorseFeed; @@ -434,6 +447,26 @@ namespace HISP.Game // Click public static string NothingInterestingHere; + public static string FormatHorseCompanionRemoveMessage(string horseName) + { + return HorseCompanionRemoveMessageFormat.Replace("%HORSENAME%", horseName); + } + public static string FormatHorseCompanionEquipMessage(string horseName, string itemName) + { + return HorseCompanionEquipMessageFormat.Replace("%HORSENAME%", horseName).Replace("%ITEM%", itemName); + } + public static string FormatHorseCompanionSelected(int icon, string name) + { + return HorseCompnaionMenuCurrentCompanionFormat.Replace("%ICONID%", icon.ToString()).Replace("%NAME%", name); + } + public static string FormatHorseCompanionMenuHeader(string horseName) + { + return HorseCompanionMenuHeaderFormat.Replace("%HORSENAME%", horseName); + } + public static string FormatHorseCompanionOption(int icon, int count, string name, int id) + { + return HorseCompanionEntryFormat.Replace("%ICONID%", icon.ToString()).Replace("%COUNT%", count.ToString("N0")).Replace("%NAME%", name).Replace("%ID%", id.ToString()); + } public static string FormatAutoSellConfirmedMessage(int money) { @@ -917,23 +950,23 @@ namespace HISP.Game } public static string FormatSellMessage(string itemName, int price) { - return Sold1Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString()); + return Sold1Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString("N0")); } public static string FormatSellAllMessage(string itemName, int price, int sellAmount) { - return SoldAllFormat.Replace("%AMOUNT%",sellAmount.ToString()).Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString()); + return SoldAllFormat.Replace("%AMOUNT%",sellAmount.ToString()).Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString("N0")); } public static string FormatBuy25Message(string itemName, int price) { - return Brought25Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString()); + return Brought25Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString("N0")); } public static string FormatBuy5Message(string itemName, int price) { - return Brought5Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString()); + return Brought5Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString("N0")); } public static string FormatBuyMessage(string itemName, int price) { - return Brought1Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString()); + return Brought1Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString("N0")); } public static string FormatShopEntry(int iconid, string count, string name, int price) { diff --git a/Horse Isle Server/Horse Isle Server/Game/Meta.cs b/Horse Isle Server/Horse Isle Server/Game/Meta.cs index 4d0e3f5..5170aa0 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Meta.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Meta.cs @@ -998,6 +998,25 @@ namespace HISP.Game message += Messages.MetaTerminator; return message; } + + public static string BuildHorseCompanionEquipMenu(HorseInstance horse, User user) + { + string message = ""; + message += Messages.FormatHorseCompanionMenuHeader(horse.Name); + if (horse.Equipment.Companion != null) + message += Messages.FormatHorseCompanionSelected(horse.Equipment.Companion.IconId, horse.Equipment.Companion.Name); + message += Messages.HorseCompanionMenuCurrentlyAvalibleCompanions; + foreach (InventoryItem item in user.Inventory.GetItemList()) + { + Item.ItemInformation itemInfo = item.ItemInstances[0].GetItemInfo(); + if(itemInfo.Type == "COMPANION") + { + message += Messages.FormatHorseCompanionOption(itemInfo.IconId, item.ItemInstances.Count, itemInfo.Name, item.ItemId); + } + } + message += Messages.BackToHorse; + return message; + } public static string BuildHorseDescriptionEditMeta(HorseInstance horse) { string message = Messages.FormatDescriptionEditMeta(horse.Name, horse.Description); @@ -1027,12 +1046,16 @@ namespace HISP.Game message += Messages.FormatPetButton(horse.RandomId); message += Messages.FormatProfileButton(horse.RandomId); - if (horse.Equipment.Saddle == null && horse.Equipment.SaddlePad == null && horse.Equipment.Bridle == null) + if (horse.Equipment.Saddle == null && horse.Equipment.SaddlePad == null && horse.Equipment.Bridle == null && horse.Equipment.Companion == null) { string autoSellMessage = Messages.HorseNoAutoSell; if (horse.AutoSell > 0) autoSellMessage = Messages.FormatAutoSellPrice(horse.AutoSell); message += Messages.FormatAutoSell(autoSellMessage); + if (horse.AutoSell > 0) + message += Messages.HorseChangeAutoSell; + else + message += Messages.HorseSetAutoSell; } else { diff --git a/Horse Isle Server/Horse Isle Server/Server/Database.cs b/Horse Isle Server/Horse Isle Server/Server/Database.cs index f0376da..fa2ce07 100644 --- a/Horse Isle Server/Horse Isle Server/Server/Database.cs +++ b/Horse Isle Server/Horse Isle Server/Server/Database.cs @@ -1247,6 +1247,20 @@ namespace HISP.Server sqlCommand.Dispose(); } } + public static void SetCompanion(int horseRandomId, int companionItemId) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "UPDATE Horses SET companion=@companion WHERE randomId=@randomId"; + sqlCommand.Parameters.AddWithValue("@companion", companionItemId); + sqlCommand.Parameters.AddWithValue("@randomId", horseRandomId); + sqlCommand.Prepare(); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } public static void ClearSaddle(int horseRandomId) { @@ -1290,6 +1304,19 @@ namespace HISP.Server } } + public static void ClearCompanion(int horseRandomId) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "UPDATE Horses SET companion=NULL WHERE randomId=@randomId"; + sqlCommand.Parameters.AddWithValue("@randomId", horseRandomId); + sqlCommand.Prepare(); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } public static void SetWorldWeather(string Weather) { diff --git a/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs b/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs index b7e9e29..eefaa76 100644 --- a/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs +++ b/Horse Isle Server/Horse Isle Server/Server/GameDataJson.cs @@ -661,10 +661,21 @@ namespace HISP.Server Messages.HorseSetNewCategoryMessageFormat = gameData.messages.meta.horse.horse_set_new_category; Messages.HorseAutoSellMenuFormat = gameData.messages.meta.horse.auto_sell.auto_sell_meta; - Messages.HorseIsAutoSell = gameData.messages.meta.auto_sell.horse.is_auto_sell; - Messages.HorseAutoSellConfirmedFormat = gameData.messages.meta.auto_sell.horse.auto_sell_confirmed; - Messages.HorseAutoSellRemoved = gameData.messages.meta.auto_sell.horse.auto_sell_remove; + Messages.HorseIsAutoSell = gameData.messages.meta.horse.auto_sell.is_auto_sell; + Messages.HorseAutoSellConfirmedFormat = gameData.messages.meta.horse.auto_sell.auto_sell_confirmed; + Messages.HorseAutoSellRemoved = gameData.messages.meta.horse.auto_sell.auto_sell_remove; + Messages.HorseSetAutoSell = gameData.messages.meta.horse.horse_inventory.set_auto_sell; + Messages.HorseChangeAutoSell = gameData.messages.meta.horse.horse_inventory.change_auto_sell; + Messages.HorseTackFailAutoSell = gameData.messages.meta.horse.tack_fail_autosell; + + // Horse companion menu + Messages.HorseCompanionMenuHeaderFormat = gameData.messages.meta.horse.companion_menu.menu_header; + Messages.HorseCompnaionMenuCurrentCompanionFormat = gameData.messages.meta.horse.companion_menu.selected_companion; + Messages.HorseCompanionEntryFormat = gameData.messages.meta.horse.companion_menu.companion_entry; + Messages.HorseCompanionEquipMessageFormat = gameData.messages.meta.horse.companion_menu.companion_equip_message; + Messages.HorseCompanionRemoveMessageFormat = gameData.messages.meta.horse.companion_menu.companion_remove_message; + Messages.HorseCompanionMenuCurrentlyAvalibleCompanions = gameData.messages.meta.horse.companion_menu.companions_avalible; // Horse Feed Menu Messages.HorseCurrentStatusFormat = gameData.messages.meta.horse.feed_horse.current_status; diff --git a/Horse Isle Server/Horse Isle Server/Server/GameServer.cs b/Horse Isle Server/Horse Isle Server/Server/GameServer.cs index 1d13e73..004b320 100644 --- a/Horse Isle Server/Horse Isle Server/Server/GameServer.cs +++ b/Horse Isle Server/Horse Isle Server/Server/GameServer.cs @@ -351,6 +351,13 @@ namespace HISP.Server { if(sender.LoggedinUser.LastViewedHorse != null) { + if(sender.LoggedinUser.LastViewedHorse.AutoSell > 0) + { + byte[] failMessagePacket = PacketBuilder.CreateChat(Messages.HorseTackFailAutoSell, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(failMessagePacket); + break; + } + if(sender.LoggedinUser.Inventory.HasItemId(itemId)) { Item.ItemInformation itemInfo = Item.GetItemById(itemId); @@ -389,6 +396,22 @@ namespace HISP.Server sender.SendPacket(equipMsgPacket); } + else if(itemInfo.Type == "COMPANION") + { + if (sender.LoggedinUser.LastViewedHorse.Equipment.Companion != null) + sender.LoggedinUser.Inventory.AddIgnoringFull(new ItemInstance(sender.LoggedinUser.LastViewedHorse.Equipment.Companion.Id)); + Database.SetCompanion(sender.LoggedinUser.LastViewedHorse.RandomId, itemInfo.Id); + sender.LoggedinUser.LastViewedHorse.Equipment.Companion = itemInfo; + + sender.LoggedinUser.Inventory.Remove(sender.LoggedinUser.Inventory.GetItemByItemId(itemId).ItemInstances[0]); // Remove item from inventory. + + sender.LoggedinUser.MetaPriority = true; + byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildHorseCompanionEquipMenu(sender.LoggedinUser.LastViewedHorse, sender.LoggedinUser)); + sender.SendPacket(metaPacket); + + byte[] equipMsgPacket = PacketBuilder.CreateChat(Messages.FormatHorseCompanionEquipMessage(sender.LoggedinUser.LastViewedHorse.Name, itemInfo.Name), PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(equipMsgPacket); + } else { Logger.ErrorPrint(sender.LoggedinUser.Username + " tried to equip a tack item to a hrose but that item was not of type \"TACK\"."); @@ -437,6 +460,12 @@ namespace HISP.Server Database.ClearBridle(sender.LoggedinUser.LastViewedHorse.RandomId); sender.LoggedinUser.LastViewedHorse.Equipment.Bridle = null; break; + case 0x34: // Companion + if (sender.LoggedinUser.LastViewedHorse.Equipment.Companion != null) + sender.LoggedinUser.Inventory.AddIgnoringFull(new ItemInstance(sender.LoggedinUser.LastViewedHorse.Equipment.Companion.Id)); + Database.ClearCompanion(sender.LoggedinUser.LastViewedHorse.RandomId); + sender.LoggedinUser.LastViewedHorse.Equipment.Companion = null; + goto companionRemove; default: Logger.ErrorPrint("Unknown equip slot: " + equipSlot.ToString("X")); break; @@ -447,6 +476,16 @@ namespace HISP.Server sender.LoggedinUser.MetaPriority = true; byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildTackMenu(sender.LoggedinUser.LastViewedHorse, sender.LoggedinUser)); sender.SendPacket(metaPacket); + break; + companionRemove:; + itemUnequipedMessage = PacketBuilder.CreateChat(Messages.FormatHorseCompanionRemoveMessage(sender.LoggedinUser.LastViewedHorse.Name), PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(itemUnequipedMessage); + + sender.LoggedinUser.MetaPriority = true; + metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildHorseCompanionEquipMenu(sender.LoggedinUser.LastViewedHorse, sender.LoggedinUser)); + sender.SendPacket(metaPacket); + break; + } else { @@ -988,10 +1027,19 @@ namespace HISP.Server metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildHorseList()); sender.SendPacket(metaPacket); break; - case "5": + case "5": // Back to horse if (sender.LoggedinUser.LastViewedHorse != null) UpdateHorseMenu(sender, sender.LoggedinUser.LastViewedHorse); break; + case "6": // Equip companion + if (sender.LoggedinUser.LastViewedHorse != null) + { + sender.LoggedinUser.MetaPriority = true; + HorseInstance horseInstance = sender.LoggedinUser.LastViewedHorse; + metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildHorseCompanionEquipMenu(horseInstance,sender.LoggedinUser)); + sender.SendPacket(metaPacket); + } + break; case "11": // Randomize horse name if (sender.LoggedinUser.LastViewedHorse != null) {