diff --git a/stardew-access/CustomCommands.cs b/stardew-access/CustomCommands.cs index 557d7bf..8d10fc2 100644 --- a/stardew-access/CustomCommands.cs +++ b/stardew-access/CustomCommands.cs @@ -1,4 +1,5 @@ using Microsoft.Xna.Framework; +using stardew_access.Features; using stardew_access.Patches; using StardewModdingAPI; using StardewValley; @@ -327,18 +328,18 @@ namespace stardew_access return; } - BuildingNAnimalMenuPatches.marked[index] = new Vector2((int)Game1.player.getTileX(), (int)Game1.player.getTileY()); + BuildingOperations.marked[index] = new Vector2((int)Game1.player.getTileX(), (int)Game1.player.getTileY()); MainClass.InfoLog($"Location {(int)Game1.player.getTileX()}x {(int)Game1.player.getTileY()}y added at {index} index."); }); helper.ConsoleCommands.Add("marklist", "List all marked positions.", (string commmand, string[] args) => { string toPrint = ""; - for (int i = 0; i < BuildingNAnimalMenuPatches.marked.Length; i++) + for (int i = 0; i < BuildingOperations.marked.Length; i++) { - if (BuildingNAnimalMenuPatches.marked[i] != Vector2.Zero) + if (BuildingOperations.marked[i] != Vector2.Zero) { - toPrint = $"{toPrint}\n Index {i}: {BuildingNAnimalMenuPatches.marked[i].X}x {BuildingNAnimalMenuPatches.marked[i].Y}y"; + toPrint = $"{toPrint}\n Index {i}: {BuildingOperations.marked[i].X}x {BuildingOperations.marked[i].Y}y"; } } @@ -355,7 +356,7 @@ namespace stardew_access helper.ConsoleCommands.Add("buildsel", "Select the building index which you want to upgrade/demolish/paint", (string commmand, string[] args) => { - if ((Game1.activeClickableMenu is not CarpenterMenu && Game1.activeClickableMenu is not PurchaseAnimalsMenu && Game1.activeClickableMenu is not AnimalQueryMenu) || !BuildingNAnimalMenuPatches.isOnFarm) + if ((Game1.activeClickableMenu is not CarpenterMenu && Game1.activeClickableMenu is not PurchaseAnimalsMenu && Game1.activeClickableMenu is not AnimalQueryMenu) || !CarpenterMenuPatch.isOnFarm) { MainClass.InfoLog($"Cannot select building."); return; @@ -380,12 +381,12 @@ namespace stardew_access string? positionIndexInString = args.ElementAtOrDefault(1); int positionIndex = 0; - if (BuildingNAnimalMenuPatches.isMoving) + if (CarpenterMenuPatch.isMoving) { - if (BuildingNAnimalMenuPatches.isConstructing || BuildingNAnimalMenuPatches.isMoving) + if (CarpenterMenuPatch.isConstructing || CarpenterMenuPatch.isMoving) { - if (BuildingNAnimalMenuPatches.availableBuildings[index] == null) + if (BuildingOperations.availableBuildings[index] == null) { MainClass.InfoLog($"No building found with index {index}. Use buildlist."); return; @@ -406,9 +407,9 @@ namespace stardew_access } } } - else if (BuildingNAnimalMenuPatches.isConstructing && !BuildingNAnimalMenuPatches.isUpgrading) + else if (CarpenterMenuPatch.isConstructing && !CarpenterMenuPatch.isUpgrading) { - if (BuildingNAnimalMenuPatches.marked[index] == Vector2.Zero) + if (BuildingOperations.marked[index] == Vector2.Zero) { MainClass.InfoLog($"No marked position found at {index} index."); return; @@ -416,7 +417,7 @@ namespace stardew_access } else { - if (BuildingNAnimalMenuPatches.availableBuildings[index] == null) + if (BuildingOperations.availableBuildings[index] == null) { MainClass.InfoLog($"No building found with index {index}. Use buildlist."); return; @@ -427,19 +428,19 @@ namespace stardew_access if (Game1.activeClickableMenu is PurchaseAnimalsMenu) { - BuildingNAnimalMenuPatches.PurchaseAnimal(BuildingNAnimalMenuPatches.availableBuildings[index]); + BuildingOperations.PurchaseAnimal(BuildingOperations.availableBuildings[index]); } else if (Game1.activeClickableMenu is AnimalQueryMenu) { - BuildingNAnimalMenuPatches.MoveAnimal(BuildingNAnimalMenuPatches.availableBuildings[index]); + BuildingOperations.MoveAnimal(BuildingOperations.availableBuildings[index]); } else { - if (BuildingNAnimalMenuPatches.isConstructing && !BuildingNAnimalMenuPatches.isUpgrading) { response = BuildingNAnimalMenuPatches.Contstruct(BuildingNAnimalMenuPatches.marked[index]); } - else if (BuildingNAnimalMenuPatches.isMoving) { response = BuildingNAnimalMenuPatches.Move(BuildingNAnimalMenuPatches.availableBuildings[index], BuildingNAnimalMenuPatches.marked[positionIndex]); } - else if (BuildingNAnimalMenuPatches.isDemolishing) { response = BuildingNAnimalMenuPatches.Demolish(BuildingNAnimalMenuPatches.availableBuildings[index]); } - else if (BuildingNAnimalMenuPatches.isUpgrading) { response = BuildingNAnimalMenuPatches.Upgrade(BuildingNAnimalMenuPatches.availableBuildings[index]); } - else if (BuildingNAnimalMenuPatches.isPainting) { response = BuildingNAnimalMenuPatches.Paint(BuildingNAnimalMenuPatches.availableBuildings[index]); } + if (CarpenterMenuPatch.isConstructing && !CarpenterMenuPatch.isUpgrading) { response = BuildingOperations.Contstruct(BuildingOperations.marked[index]); } + else if (CarpenterMenuPatch.isMoving) { response = BuildingOperations.Move(BuildingOperations.availableBuildings[index], BuildingOperations.marked[positionIndex]); } + else if (CarpenterMenuPatch.isDemolishing) { response = BuildingOperations.Demolish(BuildingOperations.availableBuildings[index]); } + else if (CarpenterMenuPatch.isUpgrading) { response = BuildingOperations.Upgrade(BuildingOperations.availableBuildings[index]); } + else if (CarpenterMenuPatch.isPainting) { response = BuildingOperations.Paint(BuildingOperations.availableBuildings[index]); } } if (response != null) @@ -517,7 +518,7 @@ namespace stardew_access string? name = buildings[i].nameOfIndoorsWithoutUnique; name = (name == "null") ? buildings[i].buildingType.Value : name; - BuildingNAnimalMenuPatches.availableBuildings[buildingIndex] = buildings[i]; + BuildingOperations.availableBuildings[buildingIndex] = buildings[i]; toPrint = $"{toPrint}\nIndex {buildingIndex}: {name}: At {buildings[i].tileX}x and {buildings[i].tileY}y"; ++buildingIndex; } diff --git a/stardew-access/Features/BuildingOperations.cs b/stardew-access/Features/BuildingOperations.cs new file mode 100644 index 0000000..f970ba3 --- /dev/null +++ b/stardew-access/Features/BuildingOperations.cs @@ -0,0 +1,366 @@ +using Microsoft.Xna.Framework; +using stardew_access.Patches; +using StardewValley; +using StardewValley.Buildings; +using StardewValley.Locations; +using StardewValley.Objects; + +namespace stardew_access.Features +{ + internal class BuildingOperations + { + internal static Building?[] availableBuildings = new Building[100]; + internal static Vector2[] marked = new Vector2[10]; + + public static string? Demolish(Building? toDemolish) + { + if (toDemolish == null) + return null; + + string? response = null; + // This code is taken from the game's code (CarpenterMenu.cs::654) + Farm farm = (Farm)Game1.getLocationFromName("Farm"); + Action buildingLockFailed = delegate + { + if (CarpenterMenuPatch.isDemolishing) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_LockFailed"); + } + }; + Action continueDemolish = delegate + { + if (CarpenterMenuPatch.isDemolishing && toDemolish != null && farm.buildings.Contains(toDemolish)) + { + if ((int)toDemolish.daysOfConstructionLeft.Value > 0 || (int)toDemolish.daysUntilUpgrade.Value > 0) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_DuringConstruction"); + } + else if (toDemolish.indoors.Value != null && toDemolish.indoors.Value is AnimalHouse && ((AnimalHouse)toDemolish.indoors.Value).animalsThatLiveHere.Count > 0) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_AnimalsHere"); + } + else if (toDemolish.indoors.Value != null && toDemolish.indoors.Value.farmers.Any()) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_PlayerHere"); + } + else + { + if (toDemolish.indoors.Value != null && toDemolish.indoors.Value is Cabin) + { + foreach (Farmer current in Game1.getAllFarmers()) + { + if (current.currentLocation != null && current.currentLocation.Name == ((Cabin)toDemolish.indoors.Value).GetCellarName()) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_PlayerHere"); + return; + } + } + } + if (toDemolish.indoors.Value is Cabin && ((Cabin)toDemolish.indoors.Value).farmhand.Value.isActive()) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_FarmhandOnline"); + } + else + { + toDemolish.BeforeDemolish(); + Chest? chest = null; + if (toDemolish.indoors.Value is Cabin) + { + List list = ((Cabin)toDemolish.indoors.Value).demolish(); + if (list.Count > 0) + { + chest = new Chest(playerChest: true); + chest.fixLidFrame(); + chest.items.Set(list); + } + } + if (farm.destroyStructure(toDemolish)) + { + _ = (int)toDemolish.tileY.Value; + _ = (int)toDemolish.tilesHigh.Value; + Game1.flashAlpha = 1f; + toDemolish.showDestroyedAnimation(Game1.getFarm()); + Game1.playSound("explosion"); + Utility.spreadAnimalsAround(toDemolish, farm); + if (CarpenterMenuPatch.carpenterMenu != null) + DelayedAction.functionAfterDelay(CarpenterMenuPatch.carpenterMenu.returnToCarpentryMenu, 1500); + // freeze = true; + if (chest != null) + { + farm.objects[new Vector2((int)toDemolish.tileX.Value + (int)toDemolish.tilesWide.Value / 2, (int)toDemolish.tileY.Value + (int)toDemolish.tilesHigh.Value / 2)] = chest; + } + } + } + } + } + }; + if (toDemolish != null) + { + if (toDemolish.indoors.Value != null && toDemolish.indoors.Value is Cabin && !Game1.IsMasterGame) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_LockFailed"); + toDemolish = null; + return response; + } + if (CarpenterMenuPatch.carpenterMenu != null && !CarpenterMenuPatch.carpenterMenu.CanDemolishThis(toDemolish)) + { + toDemolish = null; + return response; + } + if (CarpenterMenuPatch.carpenterMenu != null && !Game1.IsMasterGame && !CarpenterMenuPatch.carpenterMenu.hasPermissionsToDemolish(toDemolish)) + { + toDemolish = null; + return response; + } + } + if (toDemolish != null && toDemolish.indoors.Value is Cabin) + { + Cabin cabin = (Cabin)toDemolish.indoors.Value; + if (cabin.farmhand.Value != null && (bool)cabin.farmhand.Value.isCustomized.Value) + { + Game1.currentLocation.createQuestionDialogue(Game1.content.LoadString("Strings\\UI:Carpenter_DemolishCabinConfirm", cabin.farmhand.Value.Name), Game1.currentLocation.createYesNoResponses(), delegate (Farmer f, string answer) + { + if (answer == "Yes") + { + Game1.activeClickableMenu = CarpenterMenuPatch.carpenterMenu; + Game1.player.team.demolishLock.RequestLock(continueDemolish, buildingLockFailed); + } + else + { + if (CarpenterMenuPatch.carpenterMenu != null) + DelayedAction.functionAfterDelay(CarpenterMenuPatch.carpenterMenu.returnToCarpentryMenu, 1000); + } + }); + return response; + } + } + if (toDemolish != null) + { + Game1.player.team.demolishLock.RequestLock(continueDemolish, buildingLockFailed); + } + + return response; + } + + public static string? Contstruct(Vector2 position) + { + string? response = null; + // This code is taken from the game's code (CarpenterMenu.cs::874) + Game1.player.team.buildLock.RequestLock(delegate + { + if (CarpenterMenuPatch.isOnFarm && Game1.locationRequest == null) + { + if (tryToBuild(position)) + { + if (CarpenterMenuPatch.carpenterMenu != null) + { + CarpenterMenuPatch.carpenterMenu.CurrentBlueprint.consumeResources(); + DelayedAction.functionAfterDelay(CarpenterMenuPatch.carpenterMenu.returnToCarpentryMenuAfterSuccessfulBuild, 2000); + } + // freeze = true; + } + else + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantBuild"); + } + } + Game1.player.team.buildLock.ReleaseLock(); + }); + + return response; + } + + public static bool tryToBuild(Vector2 position) + { + if (CarpenterMenuPatch.carpenterMenu == null) + return false; + return ((Farm)Game1.getLocationFromName("Farm")).buildStructure(CarpenterMenuPatch.carpenterMenu.CurrentBlueprint, position, Game1.player, CarpenterMenuPatch.isMagicalConstruction); + } + + public static string? Upgrade(Building? toUpgrade) + { + string? response = null; + // This code is taken from the game's code (CarpenterMenu.cs::775) + if (CarpenterMenuPatch.carpenterMenu != null && toUpgrade != null && CarpenterMenuPatch.carpenterMenu.CurrentBlueprint.name != null && toUpgrade.buildingType.Equals(CarpenterMenuPatch.carpenterMenu.CurrentBlueprint.nameOfBuildingToUpgrade)) + { + CarpenterMenuPatch.carpenterMenu.CurrentBlueprint.consumeResources(); + toUpgrade.daysUntilUpgrade.Value = 2; + toUpgrade.showUpgradeAnimation(Game1.getFarm()); + Game1.playSound("axe"); + DelayedAction.functionAfterDelay(CarpenterMenuPatch.carpenterMenu.returnToCarpentryMenuAfterSuccessfulBuild, 1500); + // freeze = true; + // Game1.multiplayer.globalChatInfoMessage("BuildingBuild", Game1.player.Name, Utility.AOrAn(carpenterMenu.CurrentBlueprint.displayName), carpenterMenu.CurrentBlueprint.displayName, Game1.player.farmName.Value); + } + else if (toUpgrade != null) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CantUpgrade_BuildingType"); + } + return response; + } + + public static string? Paint(Building? toPaint) + { + string? response = null; + // This code is taken from the game's code (CarpenterMenu.cs::793) + Farm farm_location = Game1.getFarm(); + if (toPaint != null) + { + if (!toPaint.CanBePainted()) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint"); + return response; + } + if (CarpenterMenuPatch.carpenterMenu != null && !CarpenterMenuPatch.carpenterMenu.HasPermissionsToPaint(toPaint)) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint_Permission"); + return response; + } + toPaint.color.Value = Color.White; + + if (CarpenterMenuPatch.carpenterMenu != null) + CarpenterMenuPatch.carpenterMenu.SetChildMenu(new StardewValley.Menus.BuildingPaintMenu(toPaint)); + } + /* TODO Add painting of farm house + else if (farm_location.GetHouseRect().Contains(Utility.Vector2ToPoint(new Vector2(toPaint.tileX, toPaint.tileY)))) + { + if (!carpenterMenu.CanPaintHouse()) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint"); + } + else if (!carpenterMenu.HasPermissionsToPaint(null)) + { + response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint_Permission"); + } + else + { + carpenterMenu.SetChildMenu(new BuildingPaintMenu("House", () => (farm_location.paintedHouseTexture != null) ? farm_location.paintedHouseTexture : Farm.houseTextures, farm_location.houseSource.Value, farm_location.housePaintColor.Value)); + } + }*/ + return response; + } + + public static string? Move(Building? buildingToMove, Vector2 position) + { + string? response = null; + // This code is taken from the game's code (CarpenterMenu.cs::829) + if (buildingToMove != null) + { + string? name = buildingToMove.nameOfIndoorsWithoutUnique; + name = (name == "null") ? buildingToMove.buildingType.Value : name; + + if ((int)buildingToMove.daysOfConstructionLeft.Value > 0) + { + buildingToMove = null; + return "Building under construction, cannot move"; + } + if (CarpenterMenuPatch.carpenterMenu != null && !CarpenterMenuPatch.carpenterMenu.hasPermissionsToMove(buildingToMove)) + { + buildingToMove = null; + return "You don't have permission to move this building"; + } + Game1.playSound("axchop"); + + if (((Farm)Game1.getLocationFromName("Farm")).buildStructure(buildingToMove, position, Game1.player)) + { + if (buildingToMove is ShippingBin) + { + ((ShippingBin)buildingToMove).initLid(); + } + if (buildingToMove is GreenhouseBuilding) + { + Game1.getFarm().greenhouseMoved.Value = true; + } + buildingToMove.performActionOnBuildingPlacement(); + buildingToMove = null; + Game1.playSound("axchop"); + DelayedAction.playSoundAfterDelay("dirtyHit", 50); + DelayedAction.playSoundAfterDelay("dirtyHit", 150); + + response = $"{buildingToMove} moved to {position.X}x {position.Y}y"; + } + else + { + Game1.playSound("cancel"); + response = $"Cannot move building to {position.X}x {position.Y}y"; + } + + } + + return response; + } + + public static void PurchaseAnimal(Building? selection) + { + if (selection == null) + return; + + if (PurchaseAnimalsMenuPatch.purchaseAnimalsMenu == null) + return; + + int x = (selection.tileX.Value * Game1.tileSize) - Game1.viewport.X; + int y = (selection.tileY.Value * Game1.tileSize) - Game1.viewport.Y; + + if (PurchaseAnimalsMenuPatch.animalBeingPurchased != null && !selection.buildingType.Value.Contains(PurchaseAnimalsMenuPatch.animalBeingPurchased.buildingTypeILiveIn.Value)) + { + string warn = Game1.content.LoadString("Strings\\StringsFromCSFiles:PurchaseAnimalsMenu.cs.11326", PurchaseAnimalsMenuPatch.animalBeingPurchased.displayType); + MainClass.ScreenReader.Say(warn, true); + return; + } + + if (((AnimalHouse)selection.indoors.Value).isFull()) + { + string warn = Game1.content.LoadString("Strings\\StringsFromCSFiles:PurchaseAnimalsMenu.cs.11321"); + MainClass.ScreenReader.Say(warn, true); + return; + } + + PurchaseAnimalsMenuPatch.purchaseAnimalsMenu.receiveLeftClick(x, y); + } + + public static void MoveAnimal(Building? selection) + { + if (selection == null) + return; + + if (AnimalQueryMenuPatch.animalQueryMenu == null) + return; + + if (AnimalQueryMenuPatch.animalBeingMoved == null) + return; + + // The following code is taken from the game's source code [AnimalQueryMenu.cs::receiveLeftClick] + if (selection.buildingType.Value.Contains(AnimalQueryMenuPatch.animalBeingMoved.buildingTypeILiveIn.Value)) + { + if (((AnimalHouse)selection.indoors.Value).isFull()) + { + string warn = Game1.content.LoadString("Strings\\UI:AnimalQuery_Moving_BuildingFull"); + MainClass.ScreenReader.Say(warn, true); + return; + } + if (selection.Equals(AnimalQueryMenuPatch.animalBeingMoved.home)) + { + string warn = Game1.content.LoadString("Strings\\UI:AnimalQuery_Moving_AlreadyHome"); + MainClass.ScreenReader.Say(warn, true); + return; + } + ((AnimalHouse)AnimalQueryMenuPatch.animalBeingMoved.home.indoors.Value).animalsThatLiveHere.Remove(AnimalQueryMenuPatch.animalBeingMoved.myID.Value); + if (((AnimalHouse)AnimalQueryMenuPatch.animalBeingMoved.home.indoors.Value).animals.ContainsKey(AnimalQueryMenuPatch.animalBeingMoved.myID.Value)) + { + ((AnimalHouse)selection.indoors.Value).animals.Add(AnimalQueryMenuPatch.animalBeingMoved.myID.Value, AnimalQueryMenuPatch.animalBeingMoved); + ((AnimalHouse)AnimalQueryMenuPatch.animalBeingMoved.home.indoors.Value).animals.Remove(AnimalQueryMenuPatch.animalBeingMoved.myID.Value); + } + AnimalQueryMenuPatch.animalBeingMoved.home = selection; + AnimalQueryMenuPatch.animalBeingMoved.homeLocation.Value = new Vector2((int)selection.tileX.Value, (int)selection.tileY.Value); + ((AnimalHouse)selection.indoors.Value).animalsThatLiveHere.Add(AnimalQueryMenuPatch.animalBeingMoved.myID.Value); + AnimalQueryMenuPatch.animalBeingMoved.makeSound(); + Game1.globalFadeToBlack(AnimalQueryMenuPatch.animalQueryMenu.finishedPlacingAnimal); + } + else + { + string warn = Game1.content.LoadString("Strings\\UI:AnimalQuery_Moving_CantLiveThere"); + MainClass.ScreenReader.Say(warn, true); + } + return; + } + } +} diff --git a/stardew-access/HarmonyPatches.cs b/stardew-access/HarmonyPatches.cs index bf570f2..72475db 100644 --- a/stardew-access/HarmonyPatches.cs +++ b/stardew-access/HarmonyPatches.cs @@ -237,17 +237,17 @@ namespace stardew_access harmony.Patch( original: AccessTools.Method(typeof(CarpenterMenu), nameof(CarpenterMenu.draw), new Type[] { typeof(SpriteBatch) }), - prefix: new HarmonyMethod(typeof(BuildingNAnimalMenuPatches), nameof(BuildingNAnimalMenuPatches.CarpenterMenuPatch)) + prefix: new HarmonyMethod(typeof(CarpenterMenuPatch), nameof(CarpenterMenuPatch.DrawPatch)) ); harmony.Patch( original: AccessTools.Method(typeof(PurchaseAnimalsMenu), nameof(PurchaseAnimalsMenu.draw), new Type[] { typeof(SpriteBatch) }), - prefix: new HarmonyMethod(typeof(BuildingNAnimalMenuPatches), nameof(BuildingNAnimalMenuPatches.PurchaseAnimalsMenuPatch)) + prefix: new HarmonyMethod(typeof(PurchaseAnimalsMenuPatch), nameof(PurchaseAnimalsMenuPatch.DrawPatch)) ); harmony.Patch( original: AccessTools.Method(typeof(AnimalQueryMenu), nameof(AnimalQueryMenu.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(BuildingNAnimalMenuPatches), nameof(BuildingNAnimalMenuPatches.AnimalQueryMenuPatch)) + postfix: new HarmonyMethod(typeof(AnimalQueryMenuPatch), nameof(AnimalQueryMenuPatch.DrawPatch)) ); #endregion diff --git a/stardew-access/ModEntry.cs b/stardew-access/ModEntry.cs index def28d6..1830c50 100644 --- a/stardew-access/ModEntry.cs +++ b/stardew-access/ModEntry.cs @@ -128,14 +128,14 @@ namespace stardew_access HarmonyPatches.Initialize(harmony); //Initialize marked locations - for (int i = 0; i < BuildingNAnimalMenuPatches.marked.Length; i++) + for (int i = 0; i < BuildingOperations.marked.Length; i++) { - BuildingNAnimalMenuPatches.marked[i] = Vector2.Zero; + BuildingOperations.marked[i] = Vector2.Zero; } - for (int i = 0; i < BuildingNAnimalMenuPatches.availableBuildings.Length; i++) + for (int i = 0; i < BuildingOperations.availableBuildings.Length; i++) { - BuildingNAnimalMenuPatches.availableBuildings[i] = null; + BuildingOperations.availableBuildings[i] = null; } #endregion diff --git a/stardew-access/Patches/AnimalQueryMenuPatch.cs b/stardew-access/Patches/AnimalQueryMenuPatch.cs new file mode 100644 index 0000000..232d573 --- /dev/null +++ b/stardew-access/Patches/AnimalQueryMenuPatch.cs @@ -0,0 +1,78 @@ +using StardewValley; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class AnimalQueryMenuPatch + { + internal static bool isNarratingAnimalInfo = false; + internal static string animalQueryMenuQuery = ""; + internal static AnimalQueryMenu? animalQueryMenu; + internal static FarmAnimal? animalBeingMoved = null; + internal static bool isOnFarm = false; + + internal static void DrawPatch(AnimalQueryMenu __instance, bool ___confirmingSell, FarmAnimal ___animal, TextBox ___textBox, string ___parentName, bool ___movingAnimal) + { + try + { + if (TextBoxPatch.isAnyTextBoxActive) return; + + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position + bool isPrimaryInfoKeyPressed = MainClass.Config.PrimaryInfoKey.JustPressed(); // For narrating animal details + string toSpeak = " ", details = " "; + + isOnFarm = ___movingAnimal; + animalQueryMenu = __instance; + animalBeingMoved = ___animal; + + if (isPrimaryInfoKeyPressed & !isNarratingAnimalInfo) + { + string name = ___animal.displayName; + string type = ___animal.displayType; + int age = (___animal.GetDaysOwned() + 1) / 28 + 1; + string ageText = (age <= 1) ? Game1.content.LoadString("Strings\\UI:AnimalQuery_Age1") : Game1.content.LoadString("Strings\\UI:AnimalQuery_AgeN", age); + string parent = ""; + if ((int)___animal.age.Value < (byte)___animal.ageWhenMature.Value) + { + ageText += Game1.content.LoadString("Strings\\UI:AnimalQuery_AgeBaby"); + } + if (___parentName != null) + { + parent = Game1.content.LoadString("Strings\\UI:AnimalQuery_Parent", ___parentName); + } + + details = $"Name: {name} Type: {type} \n\t Age: {ageText} {parent}"; + animalQueryMenuQuery = ""; + + isNarratingAnimalInfo = true; + Task.Delay(200).ContinueWith(_ => { isNarratingAnimalInfo = false; }); + } + + if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) + toSpeak = "OK button"; + else if (__instance.sellButton != null && __instance.sellButton.containsPoint(x, y)) + toSpeak = $"Sell for {___animal.getSellPrice()}g button"; + else if (___confirmingSell && __instance.yesButton != null && __instance.yesButton.containsPoint(x, y)) + toSpeak = "Confirm selling animal"; + else if (___confirmingSell && __instance.noButton != null && __instance.noButton.containsPoint(x, y)) + toSpeak = "Cancel selling animal"; + else if (__instance.moveHomeButton != null && __instance.moveHomeButton.containsPoint(x, y)) + toSpeak = "Change home building button"; + else if (__instance.allowReproductionButton != null && __instance.allowReproductionButton.containsPoint(x, y)) + toSpeak = ((___animal.allowReproduction.Value) ? "Enabled" : "Disabled") + " allow reproduction button"; + else if (__instance.textBoxCC != null && __instance.textBoxCC.containsPoint(x, y)) + toSpeak = "Animal name text box"; + + if (animalQueryMenuQuery != toSpeak) + { + animalQueryMenuQuery = toSpeak; + MainClass.ScreenReader.Say($"{details} {toSpeak}", true); + } + } + catch (System.Exception e) + { + MainClass.ErrorLog($"An error occured in AnimalQueryMenuPatch()->DrawPatch():\n{e.Message}\n{e.StackTrace}"); + } + } + } +} diff --git a/stardew-access/Patches/BuildingNAnimalMenuPatches.cs b/stardew-access/Patches/BuildingNAnimalMenuPatches.cs deleted file mode 100644 index 352011f..0000000 --- a/stardew-access/Patches/BuildingNAnimalMenuPatches.cs +++ /dev/null @@ -1,705 +0,0 @@ -using Microsoft.Xna.Framework; -using StardewValley; -using StardewValley.Buildings; -using StardewValley.Locations; -using StardewValley.Menus; -using StardewValley.Objects; - -namespace stardew_access.Patches -{ - internal class BuildingNAnimalMenuPatches - { - internal static Vector2[] marked = new Vector2[10]; - internal static Building?[] availableBuildings = new Building[100]; - internal static CarpenterMenu? carpenterMenu = null; - internal static bool isNarratingAnimalInfo = false; - internal static string animalQueryMenuQuery = " "; - internal static string carpenterMenuQuery = "", purchaseAnimalMenuQuery = ""; - internal static bool isSayingBlueprintInfo = false; - internal static string prevBlueprintInfo = ""; - internal static bool isOnFarm = false, isUpgrading = false, isDemolishing = false, isPainting = false, isConstructing = false, isMoving = false, isMagicalConstruction = false; - internal static bool firstTimeInNamingMenu = true; - internal static PurchaseAnimalsMenu? purchaseAnimalsMenu; - internal static AnimalQueryMenu? animalQueryMenu; - private static FarmAnimal? animalBeingPurchasedOrMoved = null; - - internal static void AnimalQueryMenuPatch(AnimalQueryMenu __instance, bool ___confirmingSell, FarmAnimal ___animal, TextBox ___textBox, string ___parentName, bool ___movingAnimal) - { - try - { - if (TextBoxPatch.isAnyTextBoxActive) return; - - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position - bool isPrimaryInfoKeyPressed = MainClass.Config.PrimaryInfoKey.JustPressed(); // For narrating animal details - string toSpeak = " ", details = " "; - - isOnFarm = ___movingAnimal; - animalQueryMenu = __instance; - animalBeingPurchasedOrMoved = ___animal; - - if (isPrimaryInfoKeyPressed & !isNarratingAnimalInfo) - { - string name = ___animal.displayName; - string type = ___animal.displayType; - int age = (___animal.GetDaysOwned() + 1) / 28 + 1; - string ageText = (age <= 1) ? Game1.content.LoadString("Strings\\UI:AnimalQuery_Age1") : Game1.content.LoadString("Strings\\UI:AnimalQuery_AgeN", age); - string parent = ""; - if ((int)___animal.age.Value < (byte)___animal.ageWhenMature.Value) - { - ageText += Game1.content.LoadString("Strings\\UI:AnimalQuery_AgeBaby"); - } - if (___parentName != null) - { - parent = Game1.content.LoadString("Strings\\UI:AnimalQuery_Parent", ___parentName); - } - - details = $"Name: {name} Type: {type} \n\t Age: {ageText} {parent}"; - animalQueryMenuQuery = " "; - - isNarratingAnimalInfo = true; - Task.Delay(200).ContinueWith(_ => { isNarratingAnimalInfo = false; }); - } - - if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) - toSpeak = "OK button"; - else if (__instance.sellButton != null && __instance.sellButton.containsPoint(x, y)) - toSpeak = $"Sell for {___animal.getSellPrice()}g button"; - else if (___confirmingSell && __instance.yesButton != null && __instance.yesButton.containsPoint(x, y)) - toSpeak = "Confirm selling animal"; - else if (___confirmingSell && __instance.noButton != null && __instance.noButton.containsPoint(x, y)) - toSpeak = "Cancel selling animal"; - else if (__instance.moveHomeButton != null && __instance.moveHomeButton.containsPoint(x, y)) - toSpeak = "Change home building button"; - else if (__instance.allowReproductionButton != null && __instance.allowReproductionButton.containsPoint(x, y)) - toSpeak = ((___animal.allowReproduction.Value) ? "Enabled" : "Disabled") + " allow reproduction button"; - else if (__instance.textBoxCC != null && __instance.textBoxCC.containsPoint(x, y)) - toSpeak = "Animal name text box"; - - if (animalQueryMenuQuery != toSpeak) - { - animalQueryMenuQuery = toSpeak; - MainClass.ScreenReader.Say($"{details} {toSpeak}", true); - } - } - catch (System.Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - - internal static void PurchaseAnimalsMenuPatch(PurchaseAnimalsMenu __instance, bool ___onFarm, bool ___namingAnimal, TextBox ___textBox, FarmAnimal ___animalBeingPurchased) - { - try - { - if (TextBoxPatch.isAnyTextBoxActive) return; - - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position - purchaseAnimalsMenu = __instance; - isOnFarm = ___onFarm; - animalBeingPurchasedOrMoved = ___animalBeingPurchased; - - if (___onFarm && ___namingAnimal) - { - string toSpeak = ""; - if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) - { - toSpeak = "Cancel Button"; - } - else if (__instance.doneNamingButton != null && __instance.doneNamingButton.containsPoint(x, y)) - { - toSpeak = "OK Button"; - } - else if (__instance.randomButton != null && __instance.randomButton.containsPoint(x, y)) - { - toSpeak = "Random Name Button"; - } - else if (__instance.textBoxCC != null && __instance.textBoxCC.containsPoint(x, y)) - { - toSpeak = "Name Text Box"; - // string? value = ___textBox.Text; - // if (value != "" && value != null && value != "null") - // toSpeak = $"{toSpeak}, Value: {value}"; - } - - if (purchaseAnimalMenuQuery != toSpeak) - { - purchaseAnimalMenuQuery = toSpeak; - - if (firstTimeInNamingMenu) - { - toSpeak = $"Enter the name of animal in the name text box. {toSpeak}"; - firstTimeInNamingMenu = false; - } - - MainClass.ScreenReader.Say(toSpeak, true); - } - } - else if (___onFarm && !___namingAnimal) - { - firstTimeInNamingMenu = true; - } - else if (!___onFarm && !___namingAnimal) - { - firstTimeInNamingMenu = true; - if (__instance.hovered != null) - { - string toSpeak = ""; - if (((StardewValley.Object)__instance.hovered.item).Type != null) - { - toSpeak = ((StardewValley.Object)__instance.hovered.item).Type; - } - else - { - string displayName = PurchaseAnimalsMenu.getAnimalTitle(__instance.hovered.hoverText); - int price = __instance.hovered.item.salePrice(); - string description = PurchaseAnimalsMenu.getAnimalDescription(__instance.hovered.hoverText); - - toSpeak = $"{displayName}, Price: {price}g, Description: {description}"; - } - - if (purchaseAnimalMenuQuery != toSpeak) - { - purchaseAnimalMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - } - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - - internal static void CarpenterMenuPatch( - CarpenterMenu __instance, bool ___onFarm, List ___ingredients, int ___price, - List ___blueprints, int ___currentBlueprintIndex, bool ___upgrading, bool ___demolishing, bool ___moving, - bool ___painting, bool ___magicalConstruction) - { - try - { - isOnFarm = ___onFarm; - carpenterMenu = __instance; - isMagicalConstruction = ___magicalConstruction; - if (!___onFarm) - { - isUpgrading = false; - isDemolishing = false; - isPainting = false; - isMoving = false; - isConstructing = false; - - #region The blueprint menu - BluePrint currentBluprint = __instance.CurrentBlueprint; - if (currentBluprint == null) - return; - - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position - bool isPrimaryInfoKeyPressed = MainClass.Config.PrimaryInfoKey.JustPressed(); - string ingredients = ""; - string name = currentBluprint.displayName; - string upgradeName = currentBluprint.nameOfBuildingToUpgrade; - string description = currentBluprint.description; - string price = $"{___price}g"; - string blueprintInfo; - int width = currentBluprint.tilesWidth; - int height = currentBluprint.tilesHeight; - - #region Get ingredients - for (int i = 0; i < ___ingredients.Count; i++) - { - string itemName = ___ingredients[i].DisplayName; - int itemStack = ___ingredients[i].Stack; - string itemQuality = ""; - - int qualityValue = ((StardewValley.Object)___ingredients[i]).Quality; - if (qualityValue == 1) - { - itemQuality = "Silver quality"; - } - else if (qualityValue == 2 || qualityValue == 3) - { - itemQuality = "Gold quality"; - } - else if (qualityValue >= 4) - { - itemQuality = "Iridium quality"; - } - - ingredients = $"{ingredients}, {itemStack} {itemName} {itemQuality}"; - } - #endregion - - blueprintInfo = $"{name}, Price: {price}, Ingredients: {ingredients}, Dimensions: {width} width and {height} height, Description: {description}"; - - if (isPrimaryInfoKeyPressed && !isSayingBlueprintInfo) - { - SayBlueprintInfo(blueprintInfo); - } - else if (prevBlueprintInfo != blueprintInfo) - { - prevBlueprintInfo = blueprintInfo; - SayBlueprintInfo(blueprintInfo); - } - else - { - if (__instance.backButton != null && __instance.backButton.containsPoint(x, y)) - { - string toSpeak = "Previous Blueprint"; - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - if (__instance.forwardButton != null && __instance.forwardButton.containsPoint(x, y)) - { - string toSpeak = "Next Blueprint"; - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - if (__instance.demolishButton != null && __instance.demolishButton.containsPoint(x, y)) - { - string toSpeak = $"Demolish Building" + (__instance.CanDemolishThis(___blueprints[___currentBlueprintIndex]) ? "" : ", cannot demolish building"); - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) - { - string toSpeak = "Construct Building" + (___blueprints[___currentBlueprintIndex].doesFarmerHaveEnoughResourcesToBuild() ? "" : ", cannot cunstrut building, not enough resources to build."); - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - if (__instance.moveButton != null && __instance.moveButton.containsPoint(x, y)) - { - string toSpeak = "Move Building"; - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - if (__instance.paintButton != null && __instance.paintButton.containsPoint(x, y)) - { - string toSpeak = "Paint Building"; - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - if (__instance.cancelButton != null && __instance.cancelButton.containsPoint(x, y)) - { - string toSpeak = "Cancel Button"; - if (carpenterMenuQuery != toSpeak) - { - carpenterMenuQuery = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - } - #endregion - } - else - { - if (___demolishing) - isDemolishing = true; - else if (___upgrading) - isUpgrading = true; - else if (___painting) - isPainting = true; - else if (___moving) - isMoving = true; - else - isConstructing = true; - } - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - - private static async void SayBlueprintInfo(string info) - { - isSayingBlueprintInfo = true; - MainClass.ScreenReader.Say(info, true); - await Task.Delay(300); - isSayingBlueprintInfo = false; - } - - public static string? Demolish(Building? toDemolish) - { - if (toDemolish == null) - return null; - - string? response = null; - // This code is taken from the game's code (CarpenterMenu.cs::654) - Farm farm = (Farm)Game1.getLocationFromName("Farm"); - Action buildingLockFailed = delegate - { - if (isDemolishing) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_LockFailed"); - } - }; - Action continueDemolish = delegate - { - if (isDemolishing && toDemolish != null && farm.buildings.Contains(toDemolish)) - { - if ((int)toDemolish.daysOfConstructionLeft.Value > 0 || (int)toDemolish.daysUntilUpgrade.Value > 0) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_DuringConstruction"); - } - else if (toDemolish.indoors.Value != null && toDemolish.indoors.Value is AnimalHouse && ((AnimalHouse)toDemolish.indoors.Value).animalsThatLiveHere.Count > 0) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_AnimalsHere"); - } - else if (toDemolish.indoors.Value != null && toDemolish.indoors.Value.farmers.Any()) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_PlayerHere"); - } - else - { - if (toDemolish.indoors.Value != null && toDemolish.indoors.Value is Cabin) - { - foreach (Farmer current in Game1.getAllFarmers()) - { - if (current.currentLocation != null && current.currentLocation.Name == ((Cabin)toDemolish.indoors.Value).GetCellarName()) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_PlayerHere"); - return; - } - } - } - if (toDemolish.indoors.Value is Cabin && ((Cabin)toDemolish.indoors.Value).farmhand.Value.isActive()) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_FarmhandOnline"); - } - else - { - toDemolish.BeforeDemolish(); - Chest? chest = null; - if (toDemolish.indoors.Value is Cabin) - { - List list = ((Cabin)toDemolish.indoors.Value).demolish(); - if (list.Count > 0) - { - chest = new Chest(playerChest: true); - chest.fixLidFrame(); - chest.items.Set(list); - } - } - if (farm.destroyStructure(toDemolish)) - { - _ = (int)toDemolish.tileY.Value; - _ = (int)toDemolish.tilesHigh.Value; - Game1.flashAlpha = 1f; - toDemolish.showDestroyedAnimation(Game1.getFarm()); - Game1.playSound("explosion"); - Utility.spreadAnimalsAround(toDemolish, farm); - if (carpenterMenu != null) - DelayedAction.functionAfterDelay(carpenterMenu.returnToCarpentryMenu, 1500); - // freeze = true; - if (chest != null) - { - farm.objects[new Vector2((int)toDemolish.tileX.Value + (int)toDemolish.tilesWide.Value / 2, (int)toDemolish.tileY.Value + (int)toDemolish.tilesHigh.Value / 2)] = chest; - } - } - } - } - } - }; - if (toDemolish != null) - { - if (toDemolish.indoors.Value != null && toDemolish.indoors.Value is Cabin && !Game1.IsMasterGame) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_LockFailed"); - toDemolish = null; - return response; - } - if (carpenterMenu != null && !carpenterMenu.CanDemolishThis(toDemolish)) - { - toDemolish = null; - return response; - } - if (carpenterMenu != null && !Game1.IsMasterGame && !carpenterMenu.hasPermissionsToDemolish(toDemolish)) - { - toDemolish = null; - return response; - } - } - if (toDemolish != null && toDemolish.indoors.Value is Cabin) - { - Cabin cabin = (Cabin)toDemolish.indoors.Value; - if (cabin.farmhand.Value != null && (bool)cabin.farmhand.Value.isCustomized.Value) - { - Game1.currentLocation.createQuestionDialogue(Game1.content.LoadString("Strings\\UI:Carpenter_DemolishCabinConfirm", cabin.farmhand.Value.Name), Game1.currentLocation.createYesNoResponses(), delegate (Farmer f, string answer) - { - if (answer == "Yes") - { - Game1.activeClickableMenu = carpenterMenu; - Game1.player.team.demolishLock.RequestLock(continueDemolish, buildingLockFailed); - } - else - { - if (carpenterMenu != null) - DelayedAction.functionAfterDelay(carpenterMenu.returnToCarpentryMenu, 1000); - } - }); - return response; - } - } - if (toDemolish != null) - { - Game1.player.team.demolishLock.RequestLock(continueDemolish, buildingLockFailed); - } - - return response; - } - - public static string? Contstruct(Vector2 position) - { - string? response = null; - // This code is taken from the game's code (CarpenterMenu.cs::874) - Game1.player.team.buildLock.RequestLock(delegate - { - if (isOnFarm && Game1.locationRequest == null) - { - if (tryToBuild(position)) - { - if (carpenterMenu != null) - { - carpenterMenu.CurrentBlueprint.consumeResources(); - DelayedAction.functionAfterDelay(carpenterMenu.returnToCarpentryMenuAfterSuccessfulBuild, 2000); - } - // freeze = true; - } - else - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantBuild"); - } - } - Game1.player.team.buildLock.ReleaseLock(); - }); - - return response; - } - - public static bool tryToBuild(Vector2 position) - { - if (carpenterMenu == null) - return false; - return ((Farm)Game1.getLocationFromName("Farm")).buildStructure(carpenterMenu.CurrentBlueprint, position, Game1.player, isMagicalConstruction); - } - - public static string? Upgrade(Building? toUpgrade) - { - string? response = null; - // This code is taken from the game's code (CarpenterMenu.cs::775) - if (carpenterMenu != null && toUpgrade != null && carpenterMenu.CurrentBlueprint.name != null && toUpgrade.buildingType.Equals(carpenterMenu.CurrentBlueprint.nameOfBuildingToUpgrade)) - { - carpenterMenu.CurrentBlueprint.consumeResources(); - toUpgrade.daysUntilUpgrade.Value = 2; - toUpgrade.showUpgradeAnimation(Game1.getFarm()); - Game1.playSound("axe"); - DelayedAction.functionAfterDelay(carpenterMenu.returnToCarpentryMenuAfterSuccessfulBuild, 1500); - // freeze = true; - // Game1.multiplayer.globalChatInfoMessage("BuildingBuild", Game1.player.Name, Utility.AOrAn(carpenterMenu.CurrentBlueprint.displayName), carpenterMenu.CurrentBlueprint.displayName, Game1.player.farmName.Value); - } - else if (toUpgrade != null) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CantUpgrade_BuildingType"); - } - return response; - } - - public static string? Paint(Building? toPaint) - { - string? response = null; - // This code is taken from the game's code (CarpenterMenu.cs::793) - Farm farm_location = Game1.getFarm(); - if (toPaint != null) - { - if (!toPaint.CanBePainted()) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint"); - return response; - } - if (carpenterMenu != null && !carpenterMenu.HasPermissionsToPaint(toPaint)) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint_Permission"); - return response; - } - toPaint.color.Value = Color.White; - - if (carpenterMenu != null) - carpenterMenu.SetChildMenu(new BuildingPaintMenu(toPaint)); - } - /* TODO Add painting of farm house - else if (farm_location.GetHouseRect().Contains(Utility.Vector2ToPoint(new Vector2(toPaint.tileX, toPaint.tileY)))) - { - if (!carpenterMenu.CanPaintHouse()) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint"); - } - else if (!carpenterMenu.HasPermissionsToPaint(null)) - { - response = Game1.content.LoadString("Strings\\UI:Carpenter_CannotPaint_Permission"); - } - else - { - carpenterMenu.SetChildMenu(new BuildingPaintMenu("House", () => (farm_location.paintedHouseTexture != null) ? farm_location.paintedHouseTexture : Farm.houseTextures, farm_location.houseSource.Value, farm_location.housePaintColor.Value)); - } - }*/ - return response; - } - - public static string? Move(Building? buildingToMove, Vector2 position) - { - string? response = null; - // This code is taken from the game's code (CarpenterMenu.cs::829) - if (buildingToMove != null) - { - string? name = buildingToMove.nameOfIndoorsWithoutUnique; - name = (name == "null") ? buildingToMove.buildingType.Value : name; - - if ((int)buildingToMove.daysOfConstructionLeft.Value > 0) - { - buildingToMove = null; - return "Building under construction, cannot move"; - } - if (carpenterMenu != null && !carpenterMenu.hasPermissionsToMove(buildingToMove)) - { - buildingToMove = null; - return "You don't have permission to move this building"; - } - Game1.playSound("axchop"); - - if (((Farm)Game1.getLocationFromName("Farm")).buildStructure(buildingToMove, position, Game1.player)) - { - if (buildingToMove is ShippingBin) - { - ((ShippingBin)buildingToMove).initLid(); - } - if (buildingToMove is GreenhouseBuilding) - { - Game1.getFarm().greenhouseMoved.Value = true; - } - buildingToMove.performActionOnBuildingPlacement(); - buildingToMove = null; - Game1.playSound("axchop"); - DelayedAction.playSoundAfterDelay("dirtyHit", 50); - DelayedAction.playSoundAfterDelay("dirtyHit", 150); - - response = $"{buildingToMove} moved to {position.X}x {position.Y}y"; - } - else - { - Game1.playSound("cancel"); - response = $"Cannot move building to {position.X}x {position.Y}y"; - } - - } - - return response; - } - - public static void PurchaseAnimal(Building? selection) - { - if (selection == null) - return; - - if (purchaseAnimalsMenu == null) - return; - - int x = (selection.tileX.Value * Game1.tileSize) - Game1.viewport.X; - int y = (selection.tileY.Value * Game1.tileSize) - Game1.viewport.Y; - - if (animalBeingPurchasedOrMoved != null && !selection.buildingType.Value.Contains(animalBeingPurchasedOrMoved.buildingTypeILiveIn.Value)) - { - string warn = Game1.content.LoadString("Strings\\StringsFromCSFiles:PurchaseAnimalsMenu.cs.11326", animalBeingPurchasedOrMoved.displayType); - MainClass.ScreenReader.Say(warn, true); - return; - } - - if (((AnimalHouse)selection.indoors.Value).isFull()) - { - string warn = Game1.content.LoadString("Strings\\StringsFromCSFiles:PurchaseAnimalsMenu.cs.11321"); - MainClass.ScreenReader.Say(warn, true); - return; - } - - purchaseAnimalsMenu.receiveLeftClick(x, y); - } - - public static void MoveAnimal(Building? selection) - { - if (selection == null) - return; - - if (animalQueryMenu == null) - return; - - if (animalBeingPurchasedOrMoved == null) - return; - - // The following code is taken from the game's source code [AnimalQueryMenu.cs::receiveLeftClick] - if (selection.buildingType.Value.Contains(animalBeingPurchasedOrMoved.buildingTypeILiveIn.Value)) - { - if (((AnimalHouse)selection.indoors.Value).isFull()) - { - string warn = Game1.content.LoadString("Strings\\UI:AnimalQuery_Moving_BuildingFull"); - MainClass.ScreenReader.Say(warn, true); - return; - } - if (selection.Equals(animalBeingPurchasedOrMoved.home)) - { - string warn = Game1.content.LoadString("Strings\\UI:AnimalQuery_Moving_AlreadyHome"); - MainClass.ScreenReader.Say(warn, true); - return; - } - ((AnimalHouse)animalBeingPurchasedOrMoved.home.indoors.Value).animalsThatLiveHere.Remove(animalBeingPurchasedOrMoved.myID.Value); - if (((AnimalHouse)animalBeingPurchasedOrMoved.home.indoors.Value).animals.ContainsKey(animalBeingPurchasedOrMoved.myID.Value)) - { - ((AnimalHouse)selection.indoors.Value).animals.Add(animalBeingPurchasedOrMoved.myID.Value, animalBeingPurchasedOrMoved); - ((AnimalHouse)animalBeingPurchasedOrMoved.home.indoors.Value).animals.Remove(animalBeingPurchasedOrMoved.myID.Value); - } - animalBeingPurchasedOrMoved.home = selection; - animalBeingPurchasedOrMoved.homeLocation.Value = new Vector2((int)selection.tileX.Value, (int)selection.tileY.Value); - ((AnimalHouse)selection.indoors.Value).animalsThatLiveHere.Add(animalBeingPurchasedOrMoved.myID.Value); - animalBeingPurchasedOrMoved.makeSound(); - Game1.globalFadeToBlack(animalQueryMenu.finishedPlacingAnimal); - } - else - { - string warn = Game1.content.LoadString("Strings\\UI:AnimalQuery_Moving_CantLiveThere"); - MainClass.ScreenReader.Say(warn, true); - } - return; - } - } -} diff --git a/stardew-access/Patches/CarpenterMenuPach.cs b/stardew-access/Patches/CarpenterMenuPach.cs new file mode 100644 index 0000000..3745452 --- /dev/null +++ b/stardew-access/Patches/CarpenterMenuPach.cs @@ -0,0 +1,195 @@ +using StardewValley; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class CarpenterMenuPatch + { + internal static CarpenterMenu? carpenterMenu = null; + internal static string carpenterMenuQuery = ""; + internal static bool isSayingBlueprintInfo = false; + internal static string prevBlueprintInfo = ""; + internal static bool isOnFarm = false, isUpgrading = false, isDemolishing = false, isPainting = false, isConstructing = false, isMoving = false, isMagicalConstruction = false; + + internal static void DrawPatch( + CarpenterMenu __instance, bool ___onFarm, List ___ingredients, int ___price, + List ___blueprints, int ___currentBlueprintIndex, bool ___upgrading, bool ___demolishing, bool ___moving, + bool ___painting, bool ___magicalConstruction) + { + try + { + isOnFarm = ___onFarm; + carpenterMenu = __instance; + isMagicalConstruction = ___magicalConstruction; + if (!___onFarm) + { + isUpgrading = false; + isDemolishing = false; + isPainting = false; + isMoving = false; + isConstructing = false; + + #region The blueprint menu + BluePrint currentBluprint = __instance.CurrentBlueprint; + if (currentBluprint == null) + return; + + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position + bool isPrimaryInfoKeyPressed = MainClass.Config.PrimaryInfoKey.JustPressed(); + string ingredients = ""; + string name = currentBluprint.displayName; + string upgradeName = currentBluprint.nameOfBuildingToUpgrade; + string description = currentBluprint.description; + string price = $"{___price}g"; + string blueprintInfo; + int width = currentBluprint.tilesWidth; + int height = currentBluprint.tilesHeight; + + #region Get ingredients + for (int i = 0; i < ___ingredients.Count; i++) + { + string itemName = ___ingredients[i].DisplayName; + int itemStack = ___ingredients[i].Stack; + string itemQuality = ""; + + int qualityValue = ((StardewValley.Object)___ingredients[i]).Quality; + if (qualityValue == 1) + { + itemQuality = "Silver quality"; + } + else if (qualityValue == 2 || qualityValue == 3) + { + itemQuality = "Gold quality"; + } + else if (qualityValue >= 4) + { + itemQuality = "Iridium quality"; + } + + ingredients = $"{ingredients}, {itemStack} {itemName} {itemQuality}"; + } + #endregion + + blueprintInfo = $"{name}, Price: {price}, Ingredients: {ingredients}, Dimensions: {width} width and {height} height, Description: {description}"; + + if (isPrimaryInfoKeyPressed && !isSayingBlueprintInfo) + { + SayBlueprintInfo(blueprintInfo); + } + else if (prevBlueprintInfo != blueprintInfo) + { + prevBlueprintInfo = blueprintInfo; + SayBlueprintInfo(blueprintInfo); + } + else + { + if (__instance.backButton != null && __instance.backButton.containsPoint(x, y)) + { + string toSpeak = "Previous Blueprint"; + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (__instance.forwardButton != null && __instance.forwardButton.containsPoint(x, y)) + { + string toSpeak = "Next Blueprint"; + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (__instance.demolishButton != null && __instance.demolishButton.containsPoint(x, y)) + { + string toSpeak = $"Demolish Building" + (__instance.CanDemolishThis(___blueprints[___currentBlueprintIndex]) ? "" : ", cannot demolish building"); + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) + { + string toSpeak = "Construct Building" + (___blueprints[___currentBlueprintIndex].doesFarmerHaveEnoughResourcesToBuild() ? "" : ", cannot cunstrut building, not enough resources to build."); + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (__instance.moveButton != null && __instance.moveButton.containsPoint(x, y)) + { + string toSpeak = "Move Building"; + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (__instance.paintButton != null && __instance.paintButton.containsPoint(x, y)) + { + string toSpeak = "Paint Building"; + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (__instance.cancelButton != null && __instance.cancelButton.containsPoint(x, y)) + { + string toSpeak = "Cancel Button"; + if (carpenterMenuQuery != toSpeak) + { + carpenterMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + } + #endregion + } + else + { + if (___demolishing) + isDemolishing = true; + else if (___upgrading) + isUpgrading = true; + else if (___painting) + isPainting = true; + else if (___moving) + isMoving = true; + else + isConstructing = true; + } + } + catch (Exception e) + { + MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); + } + } + + private static async void SayBlueprintInfo(string info) + { + isSayingBlueprintInfo = true; + MainClass.ScreenReader.Say(info, true); + await Task.Delay(300); + isSayingBlueprintInfo = false; + } + + + } +} diff --git a/stardew-access/Patches/IClickableMenuPatch.cs b/stardew-access/Patches/IClickableMenuPatch.cs index 1a3992a..ae98f9d 100644 --- a/stardew-access/Patches/IClickableMenuPatch.cs +++ b/stardew-access/Patches/IClickableMenuPatch.cs @@ -63,19 +63,24 @@ namespace stardew_access.Patches } else if (menu is CarpenterMenu) { - BuildingNAnimalMenuPatches.carpenterMenuQuery = ""; - BuildingNAnimalMenuPatches.isUpgrading = false; - BuildingNAnimalMenuPatches.isDemolishing = false; - BuildingNAnimalMenuPatches.isPainting = false; - BuildingNAnimalMenuPatches.isMoving = false; - BuildingNAnimalMenuPatches.isConstructing = false; - BuildingNAnimalMenuPatches.carpenterMenu = null; + CarpenterMenuPatch.carpenterMenuQuery = ""; + CarpenterMenuPatch.isUpgrading = false; + CarpenterMenuPatch.isDemolishing = false; + CarpenterMenuPatch.isPainting = false; + CarpenterMenuPatch.isMoving = false; + CarpenterMenuPatch.isConstructing = false; + CarpenterMenuPatch.carpenterMenu = null; } else if (menu is PurchaseAnimalsMenu) { - BuildingNAnimalMenuPatches.purchaseAnimalMenuQuery = ""; - BuildingNAnimalMenuPatches.firstTimeInNamingMenu = true; - BuildingNAnimalMenuPatches.purchaseAnimalsMenu = null; + PurchaseAnimalsMenuPatch.purchaseAnimalMenuQuery = ""; + PurchaseAnimalsMenuPatch.firstTimeInNamingMenu = true; + PurchaseAnimalsMenuPatch.purchaseAnimalsMenu = null; + } + else if (menu is AnimalQueryMenu) + { + AnimalQueryMenuPatch.animalQueryMenuQuery = ""; + AnimalQueryMenuPatch.animalQueryMenu = null; } else if (menu is DialogueBox) { diff --git a/stardew-access/Patches/PurchaseAnimalsMenuPatch.cs b/stardew-access/Patches/PurchaseAnimalsMenuPatch.cs new file mode 100644 index 0000000..0828c06 --- /dev/null +++ b/stardew-access/Patches/PurchaseAnimalsMenuPatch.cs @@ -0,0 +1,101 @@ +using StardewValley; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class PurchaseAnimalsMenuPatch + { + internal static FarmAnimal? animalBeingPurchased = null; + internal static bool isOnFarm = false; + internal static string purchaseAnimalMenuQuery = ""; + internal static PurchaseAnimalsMenu? purchaseAnimalsMenu; + internal static bool firstTimeInNamingMenu = true; + + internal static void DrawPatch(PurchaseAnimalsMenu __instance, bool ___onFarm, bool ___namingAnimal, TextBox ___textBox, FarmAnimal ___animalBeingPurchased) + { + try + { + if (TextBoxPatch.isAnyTextBoxActive) return; + + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position + purchaseAnimalsMenu = __instance; + isOnFarm = ___onFarm; + animalBeingPurchased = ___animalBeingPurchased; + + if (___onFarm && ___namingAnimal) + { + string toSpeak = ""; + if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) + { + toSpeak = "Cancel Button"; + } + else if (__instance.doneNamingButton != null && __instance.doneNamingButton.containsPoint(x, y)) + { + toSpeak = "OK Button"; + } + else if (__instance.randomButton != null && __instance.randomButton.containsPoint(x, y)) + { + toSpeak = "Random Name Button"; + } + else if (__instance.textBoxCC != null && __instance.textBoxCC.containsPoint(x, y)) + { + toSpeak = "Name Text Box"; + // string? value = ___textBox.Text; + // if (value != "" && value != null && value != "null") + // toSpeak = $"{toSpeak}, Value: {value}"; + } + + if (purchaseAnimalMenuQuery != toSpeak) + { + purchaseAnimalMenuQuery = toSpeak; + + if (firstTimeInNamingMenu) + { + toSpeak = $"Enter the name of animal in the name text box. {toSpeak}"; + firstTimeInNamingMenu = false; + } + + MainClass.ScreenReader.Say(toSpeak, true); + } + } + else if (___onFarm && !___namingAnimal) + { + firstTimeInNamingMenu = true; + } + else if (!___onFarm && !___namingAnimal) + { + firstTimeInNamingMenu = true; + if (__instance.hovered != null) + { + string toSpeak = ""; + if (((StardewValley.Object)__instance.hovered.item).Type != null) + { + toSpeak = ((StardewValley.Object)__instance.hovered.item).Type; + } + else + { + string displayName = PurchaseAnimalsMenu.getAnimalTitle(__instance.hovered.hoverText); + int price = __instance.hovered.item.salePrice(); + string description = PurchaseAnimalsMenu.getAnimalDescription(__instance.hovered.hoverText); + + toSpeak = $"{displayName}, Price: {price}g, Description: {description}"; + } + + if (purchaseAnimalMenuQuery != toSpeak) + { + purchaseAnimalMenuQuery = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + } + } + catch (Exception e) + { + MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); + } + } + + + } +}