diff --git a/stardew-access/HarmonyPatches.cs b/stardew-access/HarmonyPatches.cs index a145139..1194110 100644 --- a/stardew-access/HarmonyPatches.cs +++ b/stardew-access/HarmonyPatches.cs @@ -106,7 +106,7 @@ namespace stardew_access #region Menu Patches harmony.Patch( original: AccessTools.Method(typeof(LetterViewerMenu), nameof(LetterViewerMenu.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.LetterViewerMenuPatch)) + postfix: new HarmonyMethod(typeof(DialoguePatches), nameof(DialoguePatches.LetterViewerMenuPatch)) ); harmony.Patch( @@ -141,12 +141,12 @@ namespace stardew_access harmony.Patch( original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }), - prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.MuseumMenuKeyPressPatch)) + prefix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuKeyPressPatch)) ); harmony.Patch( original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.MuseumMenuPatch)) + postfix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuPatch)) ); #endregion diff --git a/stardew-access/ModEntry.cs b/stardew-access/ModEntry.cs index c982f3c..2e3c61a 100644 --- a/stardew-access/ModEntry.cs +++ b/stardew-access/ModEntry.cs @@ -15,14 +15,22 @@ namespace stardew_access #region Global Vars private static ModConfig config; private Harmony? harmony; - private static IMonitor monitor; - private static Radar radarFeature; + private static IMonitor? monitor; + private static Radar? radarFeature; private static IScreenReader? screenReader; private static IModHelper modHelper; internal static ModConfig Config { get => config; set => config = value; } public static IModHelper ModHelper { get => modHelper; } - public static Radar RadarFeature { get => radarFeature; set => radarFeature = value; } + public static Radar RadarFeature + { + get + { + if (radarFeature == null) { radarFeature = new Radar(); } + return radarFeature; + } + set => radarFeature = value; + } public static string hudMessageQueryKey = ""; public static bool isNarratingHudMessage = false; @@ -67,8 +75,6 @@ namespace stardew_access CustomCommands.Initialize(); - RadarFeature = new Radar(); - harmony = new Harmony(ModManifest.UniqueID); HarmonyPatches.Initialize(harmony); @@ -108,12 +114,10 @@ namespace stardew_access if (!Context.IsPlayerFree) return; - // Reset variables - MenuPatches.resetGlobalVars(); - QuestPatches.resetGlobalVars(); - + // Narrates currently selected inventory slot Other.narrateCurrentSlot(); + // Narrate current location's name Other.narrateCurrentLocation(); if (Config.SnapMouse) @@ -246,11 +250,17 @@ namespace stardew_access public static void ErrorLog(string message) { + if (monitor == null) + return; + monitor.Log(message, LogLevel.Error); } public static void DebugLog(string message) { + if (monitor == null) + return; + monitor.Log(message, LogLevel.Debug); } } diff --git a/stardew-access/Patches/DialoguePatches.cs b/stardew-access/Patches/DialoguePatches.cs index 437ddaa..99d8450 100644 --- a/stardew-access/Patches/DialoguePatches.cs +++ b/stardew-access/Patches/DialoguePatches.cs @@ -8,6 +8,7 @@ namespace stardew_access.Patches { internal class DialoguePatches { + internal static string currentLetterText = " "; internal static string currentDialogue = " "; internal static bool isDialogueAppearingFirstTime = true; @@ -192,20 +193,20 @@ namespace stardew_access.Patches return; #endregion - StringBuilder toSpeak = new StringBuilder(" "); + string toSpeak = " "; #region Add item count before title if (hoveredItem != null && hoveredItem.HasBeenInInventory) { int count = hoveredItem.Stack; if (count > 1) - toSpeak.Append($"{count} "); + toSpeak = $"{toSpeak} {count} "; } #endregion #region Add title if any if (boldTitleText != null) - toSpeak.Append($"{boldTitleText}\n"); + toSpeak = $"{toSpeak} {boldTitleText}\n"; #endregion #region Add quality of item @@ -214,15 +215,15 @@ namespace stardew_access.Patches int quality = ((StardewValley.Object)hoveredItem).quality; if (quality == 1) { - toSpeak.Append("Silver quality"); + toSpeak = $"{toSpeak} Silver quality"; } else if (quality == 2 || quality == 3) { - toSpeak.Append("Gold quality"); + toSpeak = $"{toSpeak} Gold quality"; } else if (quality >= 4) { - toSpeak.Append("Iridium quality"); + toSpeak = $"{toSpeak} Iridium quality"; } } #endregion @@ -233,26 +234,29 @@ namespace stardew_access.Patches string itemName = Game1.objectInformation[extraItemToShowIndex].Split('/')[0]; if (extraItemToShowAmount != -1) - toSpeak.Append($"Required: {extraItemToShowAmount} {itemName}"); + toSpeak = $"{toSpeak} Required: {extraItemToShowAmount} {itemName}"; else - toSpeak.Append($"Required: {itemName}"); + toSpeak = $"{toSpeak} Required: {itemName}"; } #endregion #region Add money if (moneyAmountToDisplayAtBottom != -1) - toSpeak.Append($"\nCost: {moneyAmountToDisplayAtBottom}g\n"); + toSpeak = $"{toSpeak} \nCost: {moneyAmountToDisplayAtBottom}g\n"; #endregion #region Add the base text - toSpeak.Append(text); + if (text == "???") + toSpeak = "unknown"; + else + toSpeak = $"{toSpeak} {text}"; #endregion #region Add crafting ingredients if (craftingIngredients != null) { - toSpeak.Append($"\n{craftingIngredients.description}"); - toSpeak.Append("\nIngredients\n"); + toSpeak = $"{toSpeak} \n{craftingIngredients.description}"; + toSpeak = $"{toSpeak} \nIngredients\n"; craftingIngredients.recipeList.ToList().ForEach(recipe => { @@ -260,7 +264,7 @@ namespace stardew_access.Patches int item = recipe.Key; string name = craftingIngredients.getNameFromIndex(item); - toSpeak.Append($" ,{count} {name}"); + toSpeak = $"{toSpeak} ,{count} {name}"; }); } #endregion @@ -269,11 +273,11 @@ namespace stardew_access.Patches if (hoveredItem is StardewValley.Object && ((StardewValley.Object)hoveredItem).Edibility != -300) { int stamina_recovery = ((StardewValley.Object)hoveredItem).staminaRecoveredOnConsumption(); - toSpeak.Append($"{stamina_recovery} Energy\n"); + toSpeak = $"{toSpeak} {stamina_recovery} Energy\n"; if (stamina_recovery >= 0) { int health_recovery = ((StardewValley.Object)hoveredItem).healthRecoveredOnConsumption(); - toSpeak.Append($"{health_recovery} Health"); + toSpeak = $"{toSpeak} {health_recovery} Health"; } } #endregion @@ -292,7 +296,7 @@ namespace stardew_access.Patches { int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' '))); if (count != 0) - toSpeak.Append($"{buffName}\n"); + toSpeak = $"{toSpeak} {buffName}\n"; } catch (Exception) { } } @@ -317,5 +321,80 @@ namespace stardew_access.Patches MainClass.ErrorLog($"Unable to narrate dialog:\n{e.StackTrace}\n{e.Message}"); } } + + + internal static void LetterViewerMenuPatch(LetterViewerMenu __instance) + { + try + { + if (!__instance.IsActive()) + return; + + int x = Game1.getMousePosition().X, y = Game1.getMousePosition().Y; + #region Texts in the letter + string message = __instance.mailMessage[__instance.page]; + + string toSpeak = $"{message}"; + + if (__instance.ShouldShowInteractable()) + { + if (__instance.moneyIncluded > 0) + { + string moneyText = Game1.content.LoadString("Strings\\UI:LetterViewer_MoneyIncluded", __instance.moneyIncluded); + toSpeak += $"\t\n\t ,Included money: {moneyText}"; + } + else if (__instance.learnedRecipe != null && __instance.learnedRecipe.Length > 0) + { + string recipeText = Game1.content.LoadString("Strings\\UI:LetterViewer_LearnedRecipe", __instance.cookingOrCrafting); + toSpeak += $"\t\n\t ,Learned Recipe: {recipeText}"; + } + } + + if (currentLetterText != toSpeak) + { + currentLetterText = toSpeak; + + // snap mouse to accept quest button + if (__instance.acceptQuestButton != null && __instance.questID != -1) + { + toSpeak += "\t\n Left click to accept quest."; + __instance.acceptQuestButton.snapMouseCursorToCenter(); + } + if (__instance.mailMessage.Count > 1) + toSpeak = $"Page {__instance.page + 1} of {__instance.mailMessage.Count}:\n\t{toSpeak}"; + + MainClass.GetScreenReader().Say(toSpeak, false); + } + #endregion + + #region Narrate items given in the mail + if (__instance.ShouldShowInteractable()) + { + foreach (ClickableComponent c in __instance.itemsToGrab) + { + string name = c.name; + string label = c.label; + + if (c.containsPoint(x, y)) + MainClass.GetScreenReader().SayWithChecker($"Grab: {name} \t\n {label}", false); + } + } + #endregion + + #region Narrate buttons + if (__instance.backButton != null && __instance.backButton.visible && __instance.backButton.containsPoint(x, y)) + MainClass.GetScreenReader().SayWithChecker($"Previous page button", false); + + if (__instance.forwardButton != null && __instance.forwardButton.visible && __instance.forwardButton.containsPoint(x, y)) + MainClass.GetScreenReader().SayWithChecker($"Next page button", false); + + #endregion + } + catch (Exception e) + { + + MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); + } + } } } diff --git a/stardew-access/Patches/MenuPatches.cs b/stardew-access/Patches/MenuPatches.cs index 40180dc..27c559c 100644 --- a/stardew-access/Patches/MenuPatches.cs +++ b/stardew-access/Patches/MenuPatches.cs @@ -10,147 +10,8 @@ namespace stardew_access.Patches { internal class MenuPatches { - private static string currentLetterText = " "; - private static string museumQueryKey = " "; private static string currentLevelUpTitle = " "; public static Vector2? prevTile = null; - private static bool isMoving = false; - - #region Museum Menu Patch - internal static bool MuseumMenuKeyPressPatch() - { - try - { - if (isMoving) - return false; - - if (!isMoving) - { - isMoving = true; - Task.Delay(200).ContinueWith(_ => { isMoving = false; }); - } - - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - - return true; - } - - internal static void MuseumMenuPatch(MuseumMenu __instance, bool ___holdingMuseumPiece) - { - try - { - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position - - if (__instance.heldItem != null) - { - // Museum Inventory - string toSpeak = ""; - int tileX = (int)(Utility.ModifyCoordinateFromUIScale(x) + (float)Game1.viewport.X) / 64; - int tileY = (int)(Utility.ModifyCoordinateFromUIScale(y) + (float)Game1.viewport.Y) / 64; - LibraryMuseum libraryMuseum = (LibraryMuseum)Game1.currentLocation; - - if (libraryMuseum.isTileSuitableForMuseumPiece(tileX, tileY)) - toSpeak = $"slot {tileX}x {tileY}y"; - - if (museumQueryKey != toSpeak) - { - museumQueryKey = toSpeak; - MainClass.GetScreenReader().Say(toSpeak, true); - } - } - else - { - // Player Inventory - if (!narrateHoveredItemInInventory(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y)) - { - if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) - { - if (museumQueryKey != $"ok button") - { - museumQueryKey = $"ok button"; - MainClass.GetScreenReader().Say("ok button", true); - } - } - } - } - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - #endregion - - internal static bool narrateHoveredItemInInventory(InventoryMenu inventoryMenu, List inventory, IList actualInventory, int x, int y) - { - #region Narrate hovered item - for (int i = 0; i < inventory.Count; i++) - { - if (inventory[i].containsPoint(x, y)) - { - string toSpeak = ""; - if ((i + 1) <= actualInventory.Count) - { - if (actualInventory[i] != null) - { - string name = actualInventory[i].DisplayName; - int stack = actualInventory[i].Stack; - string quality = ""; - - #region Add quality of item - if (actualInventory[i] is StardewValley.Object && ((StardewValley.Object)actualInventory[i]).quality > 0) - { - int qualityIndex = ((StardewValley.Object)actualInventory[i]).quality; - if (qualityIndex == 1) - { - quality = "Silver quality"; - } - else if (qualityIndex == 2 || qualityIndex == 3) - { - quality = "Gold quality"; - } - else if (qualityIndex >= 4) - { - quality = "Iridium quality"; - } - } - #endregion - - if (inventoryMenu.highlightMethod(inventoryMenu.actualInventory[i])) - name = $"Donatable {name}"; - - if (stack > 1) - toSpeak = $"{stack} {name} {quality}"; - else - toSpeak = $"{name} {quality}"; - } - else - { - // For empty slot - toSpeak = "Empty Slot"; - } - } - else - { - // For empty slot - toSpeak = "Empty Slot"; - } - - if (museumQueryKey != $"{toSpeak}:{i}") - { - museumQueryKey = $"{toSpeak}:{i}"; - MainClass.GetScreenReader().Say(toSpeak, true); - } - return true; - } - } - #endregion - return false; - } internal static bool PlaySoundPatch(string cueName) { @@ -407,80 +268,6 @@ namespace stardew_access.Patches } } - internal static void LetterViewerMenuPatch(LetterViewerMenu __instance) - { - try - { - if (!__instance.IsActive()) - return; - - int x = Game1.getMousePosition().X, y = Game1.getMousePosition().Y; - #region Texts in the letter - string message = __instance.mailMessage[__instance.page]; - - string toSpeak = $"{message}"; - - if (__instance.ShouldShowInteractable()) - { - if (__instance.moneyIncluded > 0) - { - string moneyText = Game1.content.LoadString("Strings\\UI:LetterViewer_MoneyIncluded", __instance.moneyIncluded); - toSpeak += $"\t\n\t ,Included money: {moneyText}"; - } - else if (__instance.learnedRecipe != null && __instance.learnedRecipe.Length > 0) - { - string recipeText = Game1.content.LoadString("Strings\\UI:LetterViewer_LearnedRecipe", __instance.cookingOrCrafting); - toSpeak += $"\t\n\t ,Learned Recipe: {recipeText}"; - } - } - - if (currentLetterText != toSpeak) - { - currentLetterText = toSpeak; - - // snap mouse to accept quest button - if (__instance.acceptQuestButton != null && __instance.questID != -1) - { - toSpeak += "\t\n Left click to accept quest."; - __instance.acceptQuestButton.snapMouseCursorToCenter(); - } - if (__instance.mailMessage.Count > 1) - toSpeak = $"Page {__instance.page + 1} of {__instance.mailMessage.Count}:\n\t{toSpeak}"; - - MainClass.GetScreenReader().Say(toSpeak, false); - } - #endregion - - #region Narrate items given in the mail - if (__instance.ShouldShowInteractable()) - { - foreach (ClickableComponent c in __instance.itemsToGrab) - { - string name = c.name; - string label = c.label; - - if (c.containsPoint(x, y)) - MainClass.GetScreenReader().SayWithChecker($"Grab: {name} \t\n {label}", false); - } - } - #endregion - - #region Narrate buttons - if (__instance.backButton != null && __instance.backButton.visible && __instance.backButton.containsPoint(x, y)) - MainClass.GetScreenReader().SayWithChecker($"Previous page button", false); - - if (__instance.forwardButton != null && __instance.forwardButton.visible && __instance.forwardButton.containsPoint(x, y)) - MainClass.GetScreenReader().SayWithChecker($"Next page button", false); - - #endregion - } - catch (Exception e) - { - - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - #region Cleanup on exitting a menu internal static void Game1ExitActiveMenuPatch() { @@ -508,6 +295,21 @@ namespace stardew_access.Patches private static void Cleanup(IClickableMenu menu) { + if (menu is LetterViewerMenu) + { + DialoguePatches.currentLetterText = " "; + } + + if (menu is LevelUpMenu) + { + currentLevelUpTitle = " "; + } + + if (menu is Billboard) + { + QuestPatches.currentDailyQuestText = " "; + } + if (menu is GameMenu) { GameMenuPatches.gameMenuQueryKey = ""; @@ -576,10 +378,5 @@ namespace stardew_access.Patches if (MainClass.GetScreenReader() != null) MainClass.GetScreenReader().CloseScreenReader(); } - internal static void resetGlobalVars() - { - currentLetterText = " "; - currentLevelUpTitle = " "; - } } } diff --git a/stardew-access/Patches/MuseumMenuPatches.cs b/stardew-access/Patches/MuseumMenuPatches.cs new file mode 100644 index 0000000..3949de2 --- /dev/null +++ b/stardew-access/Patches/MuseumMenuPatches.cs @@ -0,0 +1,146 @@ +using StardewValley; +using StardewValley.Locations; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class MuseumMenuPatches + { + private static string museumQueryKey = " "; + private static bool isMoving = false; + + internal static bool MuseumMenuKeyPressPatch() + { + try + { + if (isMoving) + return false; + + if (!isMoving) + { + isMoving = true; + Task.Delay(200).ContinueWith(_ => { isMoving = false; }); + } + + } + catch (Exception e) + { + MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); + } + + return true; + } + + internal static void MuseumMenuPatch(MuseumMenu __instance, bool ___holdingMuseumPiece) + { + try + { + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position + + if (__instance.heldItem != null) + { + // Museum Inventory + string toSpeak = " "; + int tileX = (int)(Utility.ModifyCoordinateFromUIScale(x) + (float)Game1.viewport.X) / 64; + int tileY = (int)(Utility.ModifyCoordinateFromUIScale(y) + (float)Game1.viewport.Y) / 64; + LibraryMuseum libraryMuseum = (LibraryMuseum)Game1.currentLocation; + + if (libraryMuseum.isTileSuitableForMuseumPiece(tileX, tileY)) + toSpeak = $"slot {tileX}x {tileY}y"; + + if (museumQueryKey != toSpeak) + { + museumQueryKey = toSpeak; + MainClass.GetScreenReader().Say(toSpeak, true); + } + } + else + { + // Player Inventory + if (!narrateHoveredItemInInventory(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y)) + { + if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) + { + if (museumQueryKey != $"ok button") + { + museumQueryKey = $"ok button"; + MainClass.GetScreenReader().Say("ok button", true); + } + } + } + } + } + catch (Exception e) + { + MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); + } + } + + internal static bool narrateHoveredItemInInventory(InventoryMenu inventoryMenu, List inventory, IList actualInventory, int x, int y) + { + #region Narrate hovered item + for (int i = 0; i < inventory.Count; i++) + { + if (inventory[i].containsPoint(x, y)) + { + string toSpeak = ""; + if ((i + 1) <= actualInventory.Count) + { + if (actualInventory[i] != null) + { + string name = actualInventory[i].DisplayName; + int stack = actualInventory[i].Stack; + string quality = ""; + + #region Add quality of item + if (actualInventory[i] is StardewValley.Object && ((StardewValley.Object)actualInventory[i]).quality > 0) + { + int qualityIndex = ((StardewValley.Object)actualInventory[i]).quality; + if (qualityIndex == 1) + { + quality = "Silver quality"; + } + else if (qualityIndex == 2 || qualityIndex == 3) + { + quality = "Gold quality"; + } + else if (qualityIndex >= 4) + { + quality = "Iridium quality"; + } + } + #endregion + + if (inventoryMenu.highlightMethod(inventoryMenu.actualInventory[i])) + name = $"Donatable {name}"; + + if (stack > 1) + toSpeak = $"{stack} {name} {quality}"; + else + toSpeak = $"{name} {quality}"; + } + else + { + // For empty slot + toSpeak = "Empty Slot"; + } + } + else + { + // For empty slot + toSpeak = "Empty Slot"; + } + + if (museumQueryKey != $"{toSpeak}:{i}") + { + museumQueryKey = $"{toSpeak}:{i}"; + MainClass.GetScreenReader().Say(toSpeak, true); + } + return true; + } + } + #endregion + return false; + } + } +} \ No newline at end of file diff --git a/stardew-access/Patches/QuestPatches.cs b/stardew-access/Patches/QuestPatches.cs index 4d1b48c..1bd8303 100644 --- a/stardew-access/Patches/QuestPatches.cs +++ b/stardew-access/Patches/QuestPatches.cs @@ -8,7 +8,7 @@ namespace stardew_access.Patches { internal class QuestPatches { - private static string currentDailyQuestText = " "; + internal static string currentDailyQuestText = " "; #region For Special Orders Board internal static void SpecialOrdersBoardPatch(SpecialOrdersBoard __instance) @@ -243,10 +243,5 @@ namespace stardew_access.Patches } #endregion - - internal static void resetGlobalVars() - { - currentDailyQuestText = " "; - } } }