diff --git a/stardew-access/HarmonyPatches.cs b/stardew-access/HarmonyPatches.cs index e22dbc4..c5c26cf 100644 --- a/stardew-access/HarmonyPatches.cs +++ b/stardew-access/HarmonyPatches.cs @@ -38,12 +38,12 @@ namespace stardew_access #region Title Menu Patches harmony.Patch( original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(TitleMenuPatches), nameof(TitleMenuPatches.TitleMenuPatch)) + postfix: new HarmonyMethod(typeof(TitleMenuPatch), nameof(TitleMenuPatch.DrawPatch)) ); harmony.Patch( original: AccessTools.Method(typeof(LoadGameMenu.SaveFileSlot), nameof(LoadGameMenu.SaveFileSlot.Draw), new Type[] { typeof(SpriteBatch), typeof(int) }), - postfix: new HarmonyMethod(typeof(TitleMenuPatches), nameof(TitleMenuPatches.LoadGameMenuPatch)) + postfix: new HarmonyMethod(typeof(LoadGameMenuPatch), nameof(LoadGameMenuPatch.DrawPatch)) ); harmony.Patch( @@ -53,12 +53,12 @@ namespace stardew_access harmony.Patch( original: AccessTools.Method(typeof(CoopMenu), nameof(CoopMenu.update), new Type[] { typeof(GameTime) }), - postfix: new HarmonyMethod(typeof(TitleMenuPatches), nameof(TitleMenuPatches.CoopMenuPatch)) + postfix: new HarmonyMethod(typeof(CoopMenuPatch), nameof(CoopMenuPatch.DrawPatch)) ); harmony.Patch( original: AccessTools.Method(typeof(AdvancedGameOptions), nameof(AdvancedGameOptions.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(TitleMenuPatches), nameof(TitleMenuPatches.AdvancedGameOptionsPatch)) + postfix: new HarmonyMethod(typeof(AdvancedGameOptionsPatch), nameof(AdvancedGameOptionsPatch.DrawPatch)) ); #endregion diff --git a/stardew-access/Patches/IClickableMenuPatch.cs b/stardew-access/Patches/IClickableMenuPatch.cs index 5478bb5..b0a6c8c 100644 --- a/stardew-access/Patches/IClickableMenuPatch.cs +++ b/stardew-access/Patches/IClickableMenuPatch.cs @@ -19,7 +19,23 @@ namespace stardew_access.Patches internal static void Cleanup(IClickableMenu menu) { - if (menu is LetterViewerMenu) + if (menu is TitleMenu) + { + TitleMenuPatch.Cleanup(); + } + else if (menu is CoopMenu) + { + CoopMenuPatch.Cleanup(); + } + else if (menu is LoadGameMenu) + { + LoadGameMenuPatch.Cleanup(); + } + else if (menu is AdvancedGameOptions) + { + AdvancedGameOptionsPatch.Cleanup(); + } + else if (menu is LetterViewerMenu) { DialoguePatches.currentLetterText = " "; } diff --git a/stardew-access/Patches/TitleMenuPatches.cs b/stardew-access/Patches/TitleMenuPatches.cs deleted file mode 100644 index af8cba3..0000000 --- a/stardew-access/Patches/TitleMenuPatches.cs +++ /dev/null @@ -1,238 +0,0 @@ -using StardewValley; -using StardewValley.Menus; -using static StardewValley.Menus.LoadGameMenu; - -namespace stardew_access.Patches -{ - internal class TitleMenuPatches - { - public static string advancedGameOptionsQueryKey = " "; - - internal static void AdvancedGameOptionsPatch(AdvancedGameOptions __instance) - { - try - { - int currentItemIndex = Math.Max(0, Math.Min(__instance.options.Count - 7, __instance.currentItemIndex)); - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); - - if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) - { - string toSpeak = "OK Button"; - if (advancedGameOptionsQueryKey != toSpeak) - { - advancedGameOptionsQueryKey = toSpeak; - MainClass.ScreenReader.Say(toSpeak, true); - } - return; - } - - for (int i = 0; i < __instance.optionSlots.Count; i++) - { - if (__instance.optionSlots[i].bounds.Contains(x, y) && currentItemIndex + i < __instance.options.Count && __instance.options[currentItemIndex + i].bounds.Contains(x - __instance.optionSlots[i].bounds.X, y - __instance.optionSlots[i].bounds.Y)) - { - OptionsElement optionsElement = __instance.options[currentItemIndex + i]; - string toSpeak = optionsElement.label; - - if (optionsElement is OptionsButton) - toSpeak = $" {toSpeak} Button"; - else if (optionsElement is OptionsCheckbox) - toSpeak = (((OptionsCheckbox)optionsElement).isChecked ? "Enabled" : "Disabled") + $" {toSpeak} Checkbox"; - else if (optionsElement is OptionsDropDown) - toSpeak = $"{toSpeak} Dropdown, option {((OptionsDropDown)optionsElement).dropDownDisplayOptions[((OptionsDropDown)optionsElement).selectedOption]} selected"; - else if (optionsElement is OptionsSlider) - toSpeak = $"{((OptionsSlider)optionsElement).value}% {toSpeak} Slider"; - else if (optionsElement is OptionsPlusMinus) - toSpeak = $"{((OptionsPlusMinus)optionsElement).displayOptions[((OptionsPlusMinus)optionsElement).selected]} selected of {toSpeak}"; - else if (optionsElement is OptionsInputListener) - { - string buttons = ""; - ((OptionsInputListener)optionsElement).buttonNames.ForEach(name => { buttons += $", {name}"; }); - toSpeak = $"{toSpeak} is bound to {buttons}. Left click to change."; - } - else if (optionsElement is OptionsTextEntry) - { - toSpeak = $"Seed text box"; - } - else - { - if (toSpeak.Contains(":")) - toSpeak = toSpeak.Replace(":", ""); - - toSpeak = $"{toSpeak} Options:"; - } - - if (advancedGameOptionsQueryKey != toSpeak) - { - advancedGameOptionsQueryKey = 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 CoopMenuPatch(CoopMenu __instance, CoopMenu.Tab ___currentTab) - { - try - { - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); - string toSpeak = " "; - - #region Join/Host Button (Important! This should be checked before checking other buttons) - if (__instance.slotButtons[0].containsPoint(x, y)) - { - if (___currentTab == CoopMenu.Tab.JOIN_TAB) - toSpeak = "Join lan game"; - if (___currentTab == CoopMenu.Tab.HOST_TAB) - toSpeak = "Host new farm"; - } - #endregion - - #region Other Buttons - if (__instance.joinTab.containsPoint(x, y)) - { - toSpeak = "Join Tab Button"; - } - else if (__instance.hostTab.containsPoint(x, y)) - { - toSpeak = "Host Tab Button"; - } - else if (__instance.refreshButton.containsPoint(x, y)) - { - toSpeak = "Refresh Button"; - } - #endregion - - if (toSpeak != " ") - MainClass.ScreenReader.SayWithChecker(toSpeak, true); - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - - internal static void TitleMenuPatch(TitleMenu __instance, bool ___isTransitioningButtons) - { - try - { - if (___isTransitioningButtons) - return; - - string toSpeak = ""; - - __instance.buttons.ForEach(component => - { - if (component.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - string name = component.name; - string label = component.label; - toSpeak = $"{name} {label} Button"; - } - }); - - if (__instance.muteMusicButton.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - toSpeak = "Mute Music Button"; - } - - if (__instance.aboutButton.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - toSpeak = "About Button"; - } - - if (__instance.languageButton.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - toSpeak = "Language Button"; - } - - if (__instance.windowedButton.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - toSpeak = "Fullscreen: " + ((Game1.isFullscreen) ? "enabled" : "disabled"); - } - - if (TitleMenu.subMenu != null && __instance.backButton.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - string text = "Back Button"; - MainClass.ScreenReader.SayWithChecker(text, true); - } - - // Fix for back button not working using keyboard - if (TitleMenu.subMenu is CharacterCustomization && ((CharacterCustomization)TitleMenu.subMenu).backButton.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) - { - // Perform Left Click - if (MainClass.Config.LeftClickMainKey.JustPressed()) - { - __instance.backButtonPressed(); - } - } - - if (TitleMenu.subMenu == null && toSpeak != "") - MainClass.ScreenReader.SayWithChecker(toSpeak, true); - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - - internal static void LoadGameMenuPatch(SaveFileSlot __instance, LoadGameMenu ___menu, int i) - { - try - { - int x = Game1.getMouseX(true), y = Game1.getMouseY(true); - if (___menu.slotButtons[i].containsPoint(x, y)) - { - if (__instance.Farmer != null) - { - #region Farms - if (___menu.deleteButtons.Count > 0 && ___menu.deleteButtons[i].containsPoint(x, y)) - { - MainClass.ScreenReader.SayWithChecker($"Delete {__instance.Farmer.farmName.Value} Farm", true); - return; - } - - if (___menu.deleteConfirmationScreen) - { - // Used diff. functions to narrate to prevent it from speaking the message again on selecting another button. - string message = "Really delete farm?"; - - MainClass.ScreenReader.SayWithChecker(message, true); - if (___menu.okDeleteButton.containsPoint(x, y)) - { - MainClass.ScreenReader.SayWithMenuChecker("Ok Button", false); - } - else if (___menu.cancelDeleteButton.containsPoint(x, y)) - { - MainClass.ScreenReader.SayWithMenuChecker("Cancel Button", false); - } - return; - } - - String farmerName = __instance.Farmer.displayName; - String farmName = __instance.Farmer.farmName.Value; - String money = __instance.Farmer.Money.ToString(); - String hoursPlayed = Utility.getHoursMinutesStringFromMilliseconds(__instance.Farmer.millisecondsPlayed); - string dateStringForSaveGame = ((!__instance.Farmer.dayOfMonthForSaveGame.HasValue || - !__instance.Farmer.seasonForSaveGame.HasValue || - !__instance.Farmer.yearForSaveGame.HasValue) ? __instance.Farmer.dateStringForSaveGame : Utility.getDateStringFor(__instance.Farmer.dayOfMonthForSaveGame.Value, __instance.Farmer.seasonForSaveGame.Value, __instance.Farmer.yearForSaveGame.Value)); - - string toSpeak = $"{farmName} Farm Selected, \t\n Farmer: {farmerName}, \t\nMoney: {money}, \t\nHours Played: {hoursPlayed}, \t\nDate: {dateStringForSaveGame}"; - - MainClass.ScreenReader.SayWithChecker(toSpeak, true); - #endregion - } - } - } - catch (Exception e) - { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); - } - } - } -} diff --git a/stardew-access/Patches/TitleMenuPatches/AdvancedGameOptionsPatch.cs b/stardew-access/Patches/TitleMenuPatches/AdvancedGameOptionsPatch.cs new file mode 100644 index 0000000..606ab1c --- /dev/null +++ b/stardew-access/Patches/TitleMenuPatches/AdvancedGameOptionsPatch.cs @@ -0,0 +1,85 @@ +using StardewValley; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class AdvancedGameOptionsPatch + { + public static string advancedGameOptionsQueryKey = " "; + + internal static void DrawPatch(AdvancedGameOptions __instance) + { + try + { + int currentItemIndex = Math.Max(0, Math.Min(__instance.options.Count - 7, __instance.currentItemIndex)); + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); + + if (__instance.okButton != null && __instance.okButton.containsPoint(x, y)) + { + string toSpeak = "OK Button"; + if (advancedGameOptionsQueryKey != toSpeak) + { + advancedGameOptionsQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + for (int i = 0; i < __instance.optionSlots.Count; i++) + { + if (!__instance.optionSlots[i].bounds.Contains(x, y) + || currentItemIndex + i >= __instance.options.Count + || !__instance.options[currentItemIndex + i].bounds.Contains(x - __instance.optionSlots[i].bounds.X, y - __instance.optionSlots[i].bounds.Y)) + continue; + + OptionsElement optionsElement = __instance.options[currentItemIndex + i]; + string toSpeak = optionsElement.label; + + if (optionsElement is OptionsButton) + toSpeak = $" {toSpeak} Button"; + else if (optionsElement is OptionsCheckbox) + toSpeak = (((OptionsCheckbox)optionsElement).isChecked ? "Enabled" : "Disabled") + $" {toSpeak} Checkbox"; + else if (optionsElement is OptionsDropDown) + toSpeak = $"{toSpeak} Dropdown, option {((OptionsDropDown)optionsElement).dropDownDisplayOptions[((OptionsDropDown)optionsElement).selectedOption]} selected"; + else if (optionsElement is OptionsSlider) + toSpeak = $"{((OptionsSlider)optionsElement).value}% {toSpeak} Slider"; + else if (optionsElement is OptionsPlusMinus) + toSpeak = $"{((OptionsPlusMinus)optionsElement).displayOptions[((OptionsPlusMinus)optionsElement).selected]} selected of {toSpeak}"; + else if (optionsElement is OptionsInputListener) + { + string buttons = ""; + ((OptionsInputListener)optionsElement).buttonNames.ForEach(name => { buttons += $", {name}"; }); + toSpeak = $"{toSpeak} is bound to {buttons}. Left click to change."; + } + else if (optionsElement is OptionsTextEntry) + { + toSpeak = $"Seed text box"; + } + else + { + if (toSpeak.Contains(":")) + toSpeak = toSpeak.Replace(":", ""); + + toSpeak = $"{toSpeak} Options:"; + } + + if (advancedGameOptionsQueryKey != toSpeak) + { + advancedGameOptionsQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + } + catch (Exception e) + { + MainClass.ErrorLog($"An error occured in advanced game menu patch:\n{e.Message}\n{e.StackTrace}"); + } + } + + internal static void Cleanup() + { + advancedGameOptionsQueryKey = ""; + } + } +} diff --git a/stardew-access/Patches/CharacterCustomizationMenuPatches.cs b/stardew-access/Patches/TitleMenuPatches/CharacterCustomizationMenuPatches.cs similarity index 99% rename from stardew-access/Patches/CharacterCustomizationMenuPatches.cs rename to stardew-access/Patches/TitleMenuPatches/CharacterCustomizationMenuPatches.cs index fa3e13f..005456d 100644 --- a/stardew-access/Patches/CharacterCustomizationMenuPatches.cs +++ b/stardew-access/Patches/TitleMenuPatches/CharacterCustomizationMenuPatches.cs @@ -119,7 +119,7 @@ namespace stardew_access.Patches } catch (Exception e) { - MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}"); + MainClass.ErrorLog($"An error occured in character customization menu patch:\n{e.Message}\n{e.StackTrace}"); } } diff --git a/stardew-access/Patches/TitleMenuPatches/CoopMenuPatch.cs b/stardew-access/Patches/TitleMenuPatches/CoopMenuPatch.cs new file mode 100644 index 0000000..3f4eb6a --- /dev/null +++ b/stardew-access/Patches/TitleMenuPatches/CoopMenuPatch.cs @@ -0,0 +1,59 @@ +using StardewValley; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class CoopMenuPatch + { + private static string coopMenuQueryKey = ""; + + internal static void DrawPatch(CoopMenu __instance, CoopMenu.Tab ___currentTab) + { + try + { + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); + string toSpeak = ""; + + #region Join/Host Button (Important! This should be checked before checking other buttons) + if (__instance.slotButtons[0].containsPoint(x, y)) + { + if (___currentTab == CoopMenu.Tab.JOIN_TAB) + toSpeak = "Join lan game"; + if (___currentTab == CoopMenu.Tab.HOST_TAB) + toSpeak = "Host new farm"; + } + #endregion + + #region Other Buttons + if (__instance.joinTab.containsPoint(x, y)) + { + toSpeak = "Join Tab Button"; + } + else if (__instance.hostTab.containsPoint(x, y)) + { + toSpeak = "Host Tab Button"; + } + else if (__instance.refreshButton.containsPoint(x, y)) + { + toSpeak = "Refresh Button"; + } + #endregion + + if (coopMenuQueryKey != toSpeak) + { + coopMenuQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + } + catch (Exception e) + { + MainClass.ErrorLog($"An error occured in co-op menu patch:\n{e.Message}\n{e.StackTrace}"); + } + } + + internal static void Cleanup() + { + coopMenuQueryKey = ""; + } + } +} diff --git a/stardew-access/Patches/TitleMenuPatches/LoadGameMenuPatch.cs b/stardew-access/Patches/TitleMenuPatches/LoadGameMenuPatch.cs new file mode 100644 index 0000000..df16a22 --- /dev/null +++ b/stardew-access/Patches/TitleMenuPatches/LoadGameMenuPatch.cs @@ -0,0 +1,86 @@ +using StardewValley; +using StardewValley.Menus; +using static StardewValley.Menus.LoadGameMenu; + +namespace stardew_access.Patches +{ + internal class LoadGameMenuPatch + { + private static string loadGameMenuQueryKey = ""; + private static bool firstTimeInMenu = true; + + internal static void DrawPatch(SaveFileSlot __instance, LoadGameMenu ___menu, int i) + { + try + { + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); + string toSpeak = ""; + + if (!___menu.slotButtons[i].containsPoint(x, y)) return; + if (__instance.Farmer == null) return; + + if (___menu.deleteButtons.Count > 0 && ___menu.deleteButtons[i].containsPoint(x, y)) + { + toSpeak = $"Delete {__instance.Farmer.farmName.Value} Farm"; + if (loadGameMenuQueryKey != toSpeak) + { + loadGameMenuQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + if (___menu.deleteConfirmationScreen) + { + if (firstTimeInMenu) + { + firstTimeInMenu = false; + toSpeak = "Really delete farm?"; + } + + if (___menu.okDeleteButton.containsPoint(x, y)) + { + toSpeak = $"{toSpeak} Ok button"; + } + else if (___menu.cancelDeleteButton.containsPoint(x, y)) + { + toSpeak = $"{toSpeak} Cancel button"; + } + + if (loadGameMenuQueryKey != toSpeak) + { + loadGameMenuQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + return; + } + + String farmerName = __instance.Farmer.displayName; + String farmName = __instance.Farmer.farmName.Value; + String money = __instance.Farmer.Money.ToString(); + String hoursPlayed = Utility.getHoursMinutesStringFromMilliseconds(__instance.Farmer.millisecondsPlayed); + string dateStringForSaveGame = ((!__instance.Farmer.dayOfMonthForSaveGame.HasValue || + !__instance.Farmer.seasonForSaveGame.HasValue || + !__instance.Farmer.yearForSaveGame.HasValue) ? __instance.Farmer.dateStringForSaveGame : Utility.getDateStringFor(__instance.Farmer.dayOfMonthForSaveGame.Value, __instance.Farmer.seasonForSaveGame.Value, __instance.Farmer.yearForSaveGame.Value)); + + toSpeak = $"{farmName} Farm Selected, \t\n Farmer: {farmerName}, \t\nMoney: {money}, \t\nHours Played: {hoursPlayed}, \t\nDate: {dateStringForSaveGame}"; + + if (loadGameMenuQueryKey != toSpeak) + { + loadGameMenuQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + } + catch (Exception e) + { + MainClass.ErrorLog($"An error occured in load game menu patch:\n{e.Message}\n{e.StackTrace}"); + } + } + + internal static void Cleanup() + { + loadGameMenuQueryKey = ""; + firstTimeInMenu = true; + } + } +} diff --git a/stardew-access/Patches/TitleMenuPatches/TitleMenuPatches.cs b/stardew-access/Patches/TitleMenuPatches/TitleMenuPatches.cs new file mode 100644 index 0000000..7dbf06f --- /dev/null +++ b/stardew-access/Patches/TitleMenuPatches/TitleMenuPatches.cs @@ -0,0 +1,81 @@ +using StardewValley; +using StardewValley.Menus; + +namespace stardew_access.Patches +{ + internal class TitleMenuPatch + { + private static string titleMenuQueryKey = ""; + + internal static void DrawPatch(TitleMenu __instance, bool ___isTransitioningButtons) + { + try + { + if (___isTransitioningButtons) + return; + + int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position + string toSpeak = ""; + + if (__instance.muteMusicButton.containsPoint(x, y)) + { + toSpeak = "Mute Music Button"; + } + else if (__instance.aboutButton.containsPoint(x, y)) + { + toSpeak = "About Button"; + } + else if (__instance.languageButton.containsPoint(x, y)) + { + toSpeak = "Language Button"; + } + else if (__instance.windowedButton.containsPoint(x, y)) + { + toSpeak = "Fullscreen: " + ((Game1.isFullscreen) ? "enabled" : "disabled"); + } + else if (TitleMenu.subMenu != null && __instance.backButton.containsPoint(x, y)) + { + string text = "Back Button"; + MainClass.ScreenReader.SayWithChecker(text, true); + } + else + { + __instance.buttons.ForEach(component => + { + if (!component.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true))) + return; + + string name = component.name; + string label = component.label; + toSpeak = $"{name} {label} Button"; + }); + } + + // Fix for back button not working using keyboard + if (TitleMenu.subMenu is CharacterCustomization && ((CharacterCustomization)TitleMenu.subMenu).backButton.containsPoint(x, y)) + { + // Perform Left Click + if (MainClass.Config.LeftClickMainKey.JustPressed()) + { + __instance.backButtonPressed(); + } + } + + if (TitleMenu.subMenu == null && titleMenuQueryKey!=toSpeak) + { + titleMenuQueryKey = toSpeak; + MainClass.ScreenReader.Say(toSpeak, true); + } + } + catch (Exception e) + { + MainClass.ErrorLog($"An error occured in title menu patch:\n{e.Message}\n{e.StackTrace}"); + } + } + + internal static void Cleanup() + { + titleMenuQueryKey = ""; + } + } +}