Made Load Game Menu accessible, organised code
This commit is contained in:
		| @@ -5,7 +5,7 @@ namespace stardew_access.Game | |||||||
| { | { | ||||||
|     internal class CurrentPlayer |     internal class CurrentPlayer | ||||||
|     { |     { | ||||||
|         private static Farmer player = null; |         private static Farmer? player = null; | ||||||
|  |  | ||||||
|         CurrentPlayer() |         CurrentPlayer() | ||||||
|         { |         { | ||||||
| @@ -40,5 +40,23 @@ namespace stardew_access.Game | |||||||
|  |  | ||||||
|             return staminaPercentage; |             return staminaPercentage; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public static int getPositionX() | ||||||
|  |         { | ||||||
|  |             if (player == null) | ||||||
|  |                 initPlayer(); | ||||||
|  |  | ||||||
|  |             int x = (int)player.getTileLocation().X; | ||||||
|  |             return x; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static int getPositionY() | ||||||
|  |         { | ||||||
|  |             if (player == null) | ||||||
|  |                 initPlayer(); | ||||||
|  |  | ||||||
|  |             int y = (int)player.getTileLocation().Y; | ||||||
|  |             return y; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,26 +1,20 @@ | |||||||
| using AccessibleOutput; | using stardew_access.Game; | ||||||
| using stardew_access.Game; |  | ||||||
| using StardewModdingAPI; | using StardewModdingAPI; | ||||||
| using StardewModdingAPI.Events; | using StardewModdingAPI.Events; | ||||||
| using StardewValley; | using StardewValley; | ||||||
| using HarmonyLib; | using HarmonyLib; | ||||||
| using StardewValley.Menus; | using StardewValley.Menus; | ||||||
| using Microsoft.Xna.Framework.Graphics; | using Microsoft.Xna.Framework.Graphics; | ||||||
| using System.Text; | using stardew_access.Patches; | ||||||
| using StardewValley.BellsAndWhistles; |  | ||||||
| using Microsoft.Xna.Framework; |  | ||||||
|  |  | ||||||
| namespace stardew_access | namespace stardew_access | ||||||
| { | { | ||||||
|     /// <summary>The mod entry point.</summary> |  | ||||||
|     public class MainClass : Mod |     public class MainClass : Mod | ||||||
|     { |     { | ||||||
|         public static IAccessibleOutput screenReader; |         private Harmony? harmony; | ||||||
|         Harmony harmony; |         public static IMonitor? monitor; | ||||||
|         public static IMonitor monitor; |  | ||||||
|         private static string prevText = ""; |  | ||||||
|         private static DialogueBox? dialogueBox = null; |  | ||||||
|         private int index = 0; |  | ||||||
|         /********* |         /********* | ||||||
|         ** Public methods |         ** Public methods | ||||||
|         *********/ |         *********/ | ||||||
| @@ -32,7 +26,7 @@ namespace stardew_access | |||||||
|             monitor = Monitor; |             monitor = Monitor; | ||||||
|  |  | ||||||
|             // Initialize the screen reader |             // Initialize the screen reader | ||||||
|             initializeScreenReader(); |             ScreenReader.initializeScreenReader(); | ||||||
|  |  | ||||||
|             // Init harmony |             // Init harmony | ||||||
|             harmony = new Harmony(ModManifest.UniqueID); |             harmony = new Harmony(ModManifest.UniqueID); | ||||||
| @@ -40,225 +34,29 @@ namespace stardew_access | |||||||
|             // Add patches |             // Add patches | ||||||
|             harmony.Patch( |             harmony.Patch( | ||||||
|                original: AccessTools.Method(typeof(DialogueBox), nameof(DialogueBox.draw), new Type[] {typeof(SpriteBatch)}), |                original: AccessTools.Method(typeof(DialogueBox), nameof(DialogueBox.draw), new Type[] {typeof(SpriteBatch)}), | ||||||
|                postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.DialoguePatch)) |                postfix: new HarmonyMethod(typeof(DialoguePatch), nameof(DialoguePatch.CharachterDialoguePatch)) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|             harmony.Patch( |             harmony.Patch( | ||||||
|                 original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawHoverText), new Type[] { typeof(SpriteBatch), typeof(string), typeof(SpriteFont), typeof(int), typeof(int), typeof(int) , typeof(string) , typeof(int) , typeof(string[]) , typeof(Item) , typeof(int) , typeof(int), typeof(int), typeof(int), typeof(int), typeof(float), typeof(CraftingRecipe) , typeof(IList < Item >) }), |                 original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawHoverText), new Type[] { typeof(SpriteBatch), typeof(string), typeof(SpriteFont), typeof(int), typeof(int), typeof(int) , typeof(string) , typeof(int) , typeof(string[]) , typeof(Item) , typeof(int) , typeof(int), typeof(int), typeof(int), typeof(int), typeof(float), typeof(CraftingRecipe) , typeof(IList < Item >) }), | ||||||
|                 postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.HoverTextPatch)) |                 postfix: new HarmonyMethod(typeof(DialoguePatch), nameof(DialoguePatch.HoverTextPatch)) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|             harmony.Patch( |             harmony.Patch( | ||||||
|                 original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.draw) , new Type[] {typeof(SpriteBatch)}), |                 original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.draw) , new Type[] {typeof(SpriteBatch)}), | ||||||
|                 postfix: new HarmonyMethod(typeof(MainClass), nameof(TitleMenuPatch)) |                 postfix: new HarmonyMethod(typeof(MenuPatch), nameof(MenuPatch.TitleMenuPatch)) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |             harmony.Patch( | ||||||
|  |                 original: AccessTools.Method(typeof(LoadGameMenu.SaveFileSlot), nameof(LoadGameMenu.SaveFileSlot.Draw), new Type[] { typeof(SpriteBatch), typeof(int) }), | ||||||
|  |                 postfix: new HarmonyMethod(typeof(MenuPatch), nameof(MenuPatch.LoadGameMenuPatch)) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|             helper.Events.Input.ButtonPressed += this.OnButtonPressed; |             helper.Events.Input.ButtonPressed += this.OnButtonPressed; | ||||||
|             //helper.Events.GameLoop.OneSecondUpdateTicked += this.OnOneSecondUpdateTicked; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private static void TitleMenuPatch(TitleMenu __instance, SpriteBatch b) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 __instance.allClickableComponents.ForEach(component => |  | ||||||
|                 { |  | ||||||
|                     if(component.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) |  | ||||||
|                     { |  | ||||||
|                         string name = component.name; |  | ||||||
|                         string label = component.label; |  | ||||||
|                         string toSpeak = $"{name} {label}"; |  | ||||||
|  |  | ||||||
|                         if(prevText != toSpeak) |  | ||||||
|                         { |  | ||||||
|                             prevText = toSpeak; |  | ||||||
|                             screenReader.Speak(toSpeak, true); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|             catch (Exception) |  | ||||||
|             { |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private static void DialoguePatch(DialogueBox __instance, SpriteBatch b) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 Dialogue dialogue = __instance.characterDialogue; |  | ||||||
|                 string speakerName = dialogue.speaker.Name; |  | ||||||
|                 List<string> dialogues = dialogue.dialogues; |  | ||||||
|                 int dialogueIndex = dialogue.currentDialogueIndex; |  | ||||||
|                 monitor.Log("" + dialogue.isCurrentStringContinuedOnNextScreen, LogLevel.Debug); |  | ||||||
|  |  | ||||||
|                 if (prevText != $"{speakerName} said, {dialogues[dialogueIndex]}") |  | ||||||
|                 { |  | ||||||
|                     prevText = $"{speakerName} said, {dialogues[dialogueIndex]}"; |  | ||||||
|                     screenReader.Speak($"{speakerName} said, {dialogues[dialogueIndex]}", false); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private void OnOneSecondUpdateTicked(object sender, OneSecondUpdateTickedEventArgs e) |  | ||||||
|         { |  | ||||||
|             if (Game1.activeClickableMenu != null) |  | ||||||
|             { |  | ||||||
|                 string name = Game1.activeClickableMenu.getCurrentlySnappedComponent().name; |  | ||||||
|                 string label = Game1.activeClickableMenu.getCurrentlySnappedComponent().label; |  | ||||||
|                 string toSpeeak = $"{name} {label}"; |  | ||||||
|  |  | ||||||
|                 if (prevText != toSpeeak) |  | ||||||
|                 { |  | ||||||
|                     prevText = toSpeeak; |  | ||||||
|                     screenReader.Speak(toSpeeak, true); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private static void HoverTextPatch(SpriteBatch b, string text, SpriteFont font, int xOffset = 0, int yOffset = 0, int moneyAmountToDisplayAtBottom = -1, string boldTitleText = null, int healAmountToDisplay = -1, string[] buffIconsToDisplay = null, Item hoveredItem = null, int currencySymbol = 0, int extraItemToShowIndex = -1, int extraItemToShowAmount = -1, int overrideX = -1, int overrideY = -1, float alpha = 1f, CraftingRecipe craftingIngredients = null, IList<Item> additional_craft_materials = null) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 StringBuilder toSpeak = new StringBuilder(); |  | ||||||
|  |  | ||||||
|                 #region Add title if any |  | ||||||
|                 if (boldTitleText != null) |  | ||||||
|                     toSpeak.Append($"{boldTitleText}.\n"); |  | ||||||
|                 #endregion |  | ||||||
|  |  | ||||||
|                 #region Add the base text |  | ||||||
|                 toSpeak.Append(text);  |  | ||||||
|                 #endregion |  | ||||||
|  |  | ||||||
|                 #region Add crafting ingredients |  | ||||||
|                 if (craftingIngredients != null) |  | ||||||
|                 { |  | ||||||
|  |  | ||||||
|                     toSpeak.Append($"\n{craftingIngredients.description}"); |  | ||||||
|                     toSpeak.Append("\nIngredients\n"); |  | ||||||
|  |  | ||||||
|                     craftingIngredients.recipeList.ToList().ForEach(recipe => |  | ||||||
|                     { |  | ||||||
|                         int count = recipe.Value; |  | ||||||
|                         int item = recipe.Key; |  | ||||||
|                         string name = craftingIngredients.getNameFromIndex(item); |  | ||||||
|  |  | ||||||
|                         toSpeak.Append($" ,{count} {name}"); |  | ||||||
|                     }); |  | ||||||
|                 }  |  | ||||||
|                 #endregion |  | ||||||
|  |  | ||||||
|                 #region Add health & stamina |  | ||||||
|                 if (hoveredItem is StardewValley.Object && (hoveredItem as StardewValley.Object).Edibility != -300) |  | ||||||
|                 { |  | ||||||
|                     int stamina_recovery = (hoveredItem as StardewValley.Object).staminaRecoveredOnConsumption(); |  | ||||||
|                     toSpeak.Append($"{stamina_recovery} Energy\n"); |  | ||||||
|                     if (stamina_recovery >= 0) |  | ||||||
|                     { |  | ||||||
|                         int health_recovery = (hoveredItem as StardewValley.Object).healthRecoveredOnConsumption(); |  | ||||||
|                         toSpeak.Append($"{health_recovery} Health"); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 #endregion |  | ||||||
|  |  | ||||||
|                 #region Add buff items (effects like +1 walking speed) |  | ||||||
|                 if (buffIconsToDisplay != null) |  | ||||||
|                 { |  | ||||||
|                     for (int i = 0; i < buffIconsToDisplay.Length; i++) |  | ||||||
|                     { |  | ||||||
|                         string buffName = ((Convert.ToInt32(buffIconsToDisplay[i]) > 0) ? "+" : "") + buffIconsToDisplay[i] + " "; |  | ||||||
|                         if (i <= 11) |  | ||||||
|                         { |  | ||||||
|                             buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + i, buffName); |  | ||||||
|                         } |  | ||||||
|                         try |  | ||||||
|                         { |  | ||||||
|                             int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' '))); |  | ||||||
|                             monitor.Log("" + count); |  | ||||||
|                             if (count != 0) |  | ||||||
|                                 toSpeak.Append($"{buffName}\n"); |  | ||||||
|                         } |  | ||||||
|                         catch (Exception) { } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 #endregion |  | ||||||
|  |  | ||||||
|                 #region Add money |  | ||||||
|                 if (moneyAmountToDisplayAtBottom != -1) |  | ||||||
|                     toSpeak.Append($"\nValue: {moneyAmountToDisplayAtBottom} coins\n"); |  | ||||||
|                 #endregion |  | ||||||
|  |  | ||||||
|                 #region Narrate toSpeak |  | ||||||
|                 if (prevText != toSpeak.ToString()) |  | ||||||
|                 { |  | ||||||
|                     prevText = toSpeak.ToString(); |  | ||||||
|                     screenReader.Speak(toSpeak.ToString(), true); |  | ||||||
|                 }  |  | ||||||
|                 #endregion |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private void initializeScreenReader() |  | ||||||
|         { |  | ||||||
|             NvdaOutput nvdaOutput = null; |  | ||||||
|             JawsOutput jawsOutput = null; |  | ||||||
|             SapiOutput sapiOutput = null; |  | ||||||
|  |  | ||||||
|             // Initialize NVDA |  | ||||||
|             try{ |  | ||||||
|                 nvdaOutput = new NvdaOutput(); |  | ||||||
|             }catch(Exception ex){ |  | ||||||
|                 Monitor.Log($"Error initializing NVDA:\n{ex.StackTrace}", LogLevel.Error); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // Initialize JAWS |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 jawsOutput = new JawsOutput(); |  | ||||||
|             }catch (Exception ex){ |  | ||||||
|                 Monitor.Log($"Error initializing JAWS:\n{ex.StackTrace}", LogLevel.Error); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // Initialize SAPI |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 sapiOutput = new SapiOutput(); |  | ||||||
|             }catch (Exception ex){ |  | ||||||
|                 Monitor.Log($"Error initializing SAPI:\n{ex.StackTrace}", LogLevel.Error); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (nvdaOutput != null && nvdaOutput.IsAvailable()) |  | ||||||
|                 screenReader = nvdaOutput; |  | ||||||
|  |  | ||||||
|             if(jawsOutput != null && jawsOutput.IsAvailable()) |  | ||||||
|                 screenReader = jawsOutput; |  | ||||||
|  |  | ||||||
|             if (sapiOutput != null && sapiOutput.IsAvailable()) |  | ||||||
|                 screenReader = sapiOutput; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnButtonPressed(object sender, ButtonPressedEventArgs e) |         private void OnButtonPressed(object sender, ButtonPressedEventArgs e) | ||||||
|         { |         { | ||||||
|             if (Equals(e.Button, SButton.K)) |  | ||||||
|             { |  | ||||||
|                 if (Game1.activeClickableMenu != null) |  | ||||||
|                 { |  | ||||||
|                     string name = Game1.activeClickableMenu.getCurrentlySnappedComponent().label; |  | ||||||
|                     screenReader.Speak(name, true); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             // ignore if player hasn't loaded a save yet |             // ignore if player hasn't loaded a save yet | ||||||
|             if (!Context.IsWorldReady) |             if (!Context.IsWorldReady) | ||||||
|               return; |               return; | ||||||
| @@ -266,7 +64,15 @@ namespace stardew_access | |||||||
|             // Narrate Health And Energy |             // Narrate Health And Energy | ||||||
|             if (Equals(e.Button, SButton.I)) |             if (Equals(e.Button, SButton.I)) | ||||||
|             { |             { | ||||||
|                 screenReader.Speak($"Health is {CurrentPlayer.getHealth()} and Stamina is {CurrentPlayer.getStamina()}"); |                 string toSpeak = $"Health is {CurrentPlayer.getHealth()} and Stamina is {CurrentPlayer.getStamina()}"; | ||||||
|  |                 ScreenReader.say(toSpeak, true); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Narrate Position | ||||||
|  |             if (Equals(e.Button, SButton.K)) | ||||||
|  |             { | ||||||
|  |                 string toSpeak = $"X: {CurrentPlayer.getPositionX()} , Y: {CurrentPlayer.getPositionX()}"; | ||||||
|  |                 ScreenReader.say(toSpeak, true); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										115
									
								
								stardew-access/Patches/DialoguePatch.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								stardew-access/Patches/DialoguePatch.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | using StardewModdingAPI; | ||||||
|  | using StardewValley; | ||||||
|  | using StardewValley.Menus; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
|  | namespace stardew_access.Patches | ||||||
|  | { | ||||||
|  |     internal class DialoguePatch | ||||||
|  |     { | ||||||
|  |         public static void CharachterDialoguePatch(DialogueBox __instance, SpriteBatch b) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 Dialogue dialogue = __instance.characterDialogue; | ||||||
|  |                 string speakerName = dialogue.speaker.Name; | ||||||
|  |                 List<string> dialogues = dialogue.dialogues; | ||||||
|  |                 int dialogueIndex = dialogue.currentDialogueIndex; | ||||||
|  |                 MainClass.monitor.Log("" + dialogue.isCurrentStringContinuedOnNextScreen, LogLevel.Debug); | ||||||
|  |                 string toSpeak = $"{speakerName} said, {dialogues[dialogueIndex]}"; | ||||||
|  |  | ||||||
|  |                 ScreenReader.sayWithChecker(toSpeak, false); | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         public static void HoverTextPatch(string? text, int moneyAmountToDisplayAtBottom = -1, string? boldTitleText = null, string[]? buffIconsToDisplay = null, Item? hoveredItem = null, CraftingRecipe? craftingIngredients = null) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 StringBuilder toSpeak = new StringBuilder(); | ||||||
|  |  | ||||||
|  |                 #region Add title if any | ||||||
|  |                 if (boldTitleText != null) | ||||||
|  |                     toSpeak.Append($"{boldTitleText}.\n"); | ||||||
|  |                 #endregion | ||||||
|  |  | ||||||
|  |                 #region Add the base text | ||||||
|  |                 toSpeak.Append(text); | ||||||
|  |                 #endregion | ||||||
|  |  | ||||||
|  |                 #region Add crafting ingredients | ||||||
|  |                 if (craftingIngredients != null) | ||||||
|  |                 { | ||||||
|  |  | ||||||
|  |                     toSpeak.Append($"\n{craftingIngredients.description}"); | ||||||
|  |                     toSpeak.Append("\nIngredients\n"); | ||||||
|  |  | ||||||
|  |                     craftingIngredients.recipeList.ToList().ForEach(recipe => | ||||||
|  |                     { | ||||||
|  |                         int count = recipe.Value; | ||||||
|  |                         int item = recipe.Key; | ||||||
|  |                         string name = craftingIngredients.getNameFromIndex(item); | ||||||
|  |  | ||||||
|  |                         toSpeak.Append($" ,{count} {name}"); | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |                 #endregion | ||||||
|  |  | ||||||
|  |                 #region Add health & stamina | ||||||
|  |                 if (hoveredItem is StardewValley.Object && (hoveredItem as StardewValley.Object).Edibility != -300) | ||||||
|  |                 { | ||||||
|  |                     int stamina_recovery = (hoveredItem as StardewValley.Object).staminaRecoveredOnConsumption(); | ||||||
|  |                     toSpeak.Append($"{stamina_recovery} Energy\n"); | ||||||
|  |                     if (stamina_recovery >= 0) | ||||||
|  |                     { | ||||||
|  |                         int health_recovery = (hoveredItem as StardewValley.Object).healthRecoveredOnConsumption(); | ||||||
|  |                         toSpeak.Append($"{health_recovery} Health"); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 #endregion | ||||||
|  |  | ||||||
|  |                 #region Add buff items (effects like +1 walking speed) | ||||||
|  |                 if (buffIconsToDisplay != null) | ||||||
|  |                 { | ||||||
|  |                     for (int i = 0; i < buffIconsToDisplay.Length; i++) | ||||||
|  |                     { | ||||||
|  |                         string buffName = ((Convert.ToInt32(buffIconsToDisplay[i]) > 0) ? "+" : "") + buffIconsToDisplay[i] + " "; | ||||||
|  |                         if (i <= 11) | ||||||
|  |                         { | ||||||
|  |                             buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + i, buffName); | ||||||
|  |                         } | ||||||
|  |                         try | ||||||
|  |                         { | ||||||
|  |                             int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' '))); | ||||||
|  |                             MainClass.monitor.Log("" + count); | ||||||
|  |                             if (count != 0) | ||||||
|  |                                 toSpeak.Append($"{buffName}\n"); | ||||||
|  |                         } | ||||||
|  |                         catch (Exception) { } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 #endregion | ||||||
|  |  | ||||||
|  |                 #region Add money | ||||||
|  |                 if (moneyAmountToDisplayAtBottom != -1) | ||||||
|  |                     toSpeak.Append($"\nValue: {moneyAmountToDisplayAtBottom} coins\n"); | ||||||
|  |                 #endregion | ||||||
|  |  | ||||||
|  |                 #region Narrate toSpeak | ||||||
|  |                 ScreenReader.sayWithChecker(toSpeak.ToString(), true); | ||||||
|  |                 #endregion | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								stardew-access/Patches/MenuPatch.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								stardew-access/Patches/MenuPatch.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | using StardewModdingAPI; | ||||||
|  | using StardewValley; | ||||||
|  | using StardewValley.Menus; | ||||||
|  |  | ||||||
|  | namespace stardew_access.Patches | ||||||
|  | { | ||||||
|  |     internal class MenuPatch | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |         public static void TitleMenuPatch(TitleMenu __instance) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 string toSpeak = ""; | ||||||
|  |  | ||||||
|  |                 __instance.buttons.ForEach(component => | ||||||
|  |                 { | ||||||
|  |                     if (component.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) | ||||||
|  |                     { | ||||||
|  |                         string name = component.name; | ||||||
|  |                         string label = component.label; | ||||||
|  |                         toSpeak = $"{name} {label} Button"; | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 if(__instance.muteMusicButton.containsPoint(Game1.getMousePosition(true).X,Game1.getMousePosition(true).Y)) | ||||||
|  |                 { | ||||||
|  |                     toSpeak = "Mute Music Button"; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (__instance.aboutButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) | ||||||
|  |                 { | ||||||
|  |                     toSpeak = "About Button"; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (__instance.languageButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) | ||||||
|  |                 { | ||||||
|  |                     toSpeak = "Language Button"; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (__instance.windowedButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) | ||||||
|  |                 { | ||||||
|  |                     toSpeak = "Fullscreen toggle Button"; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (TitleMenu.subMenu != null && __instance.backButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) | ||||||
|  |                 { | ||||||
|  |                     string text = "Back Button"; | ||||||
|  |                     ScreenReader.sayWithChecker(text, true); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (TitleMenu.subMenu == null && toSpeak != "") | ||||||
|  |                     ScreenReader.sayWithChecker(toSpeak, true); | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void LoadGameMenuPatch(LoadGameMenu.SaveFileSlot __instance, LoadGameMenu ___menu, int i) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 if (___menu.slotButtons[i].containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y)) | ||||||
|  |                 { | ||||||
|  |                     if (__instance.Farmer == null) | ||||||
|  |                         return; | ||||||
|  |  | ||||||
|  |                     String farmerName = __instance.Farmer.Name; | ||||||
|  |                     String farmName = __instance.Farmer.farmName; | ||||||
|  |                     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, \t\n Farmer:{farmerName}, \t\nMoney:{money}, \t\nHours Played:{hoursPlayed}, \t\nDate:{dateStringForSaveGame}"; | ||||||
|  |  | ||||||
|  |                     ScreenReader.sayWithChecker(toSpeak, true); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								stardew-access/ScreenReader.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								stardew-access/ScreenReader.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | using AccessibleOutput; | ||||||
|  | using StardewModdingAPI; | ||||||
|  |  | ||||||
|  | namespace stardew_access | ||||||
|  | { | ||||||
|  |     internal class ScreenReader | ||||||
|  |     { | ||||||
|  |         public static IAccessibleOutput? screenReader = null; | ||||||
|  |         private static string prevText = ""; | ||||||
|  |  | ||||||
|  |         public static void initializeScreenReader() | ||||||
|  |         { | ||||||
|  |             NvdaOutput? nvdaOutput = null; | ||||||
|  |             JawsOutput? jawsOutput = null; | ||||||
|  |             SapiOutput? sapiOutput = null; | ||||||
|  |  | ||||||
|  |             // Initialize NVDA | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 nvdaOutput = new NvdaOutput(); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Error initializing NVDA:\n{ex.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Initialize JAWS | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 jawsOutput = new JawsOutput(); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Error initializing JAWS:\n{ex.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Initialize SAPI | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 sapiOutput = new SapiOutput(); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 MainClass.monitor.Log($"Error initializing SAPI:\n{ex.StackTrace}", LogLevel.Error); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (nvdaOutput != null && nvdaOutput.IsAvailable()) | ||||||
|  |                 screenReader = nvdaOutput; | ||||||
|  |  | ||||||
|  |             if (jawsOutput != null && jawsOutput.IsAvailable()) | ||||||
|  |                 screenReader = jawsOutput; | ||||||
|  |  | ||||||
|  |             if (sapiOutput != null && sapiOutput.IsAvailable()) | ||||||
|  |                 screenReader = sapiOutput; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void say(string text, bool interrupt) | ||||||
|  |         { | ||||||
|  |             if (screenReader == null) | ||||||
|  |                 return; | ||||||
|  |  | ||||||
|  |             screenReader.Speak(text, interrupt); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void sayWithChecker(string text, bool interrupt) | ||||||
|  |         { | ||||||
|  |             if (screenReader == null) | ||||||
|  |                 return; | ||||||
|  |  | ||||||
|  |             if (prevText != text) | ||||||
|  |             { | ||||||
|  |                 prevText = text; | ||||||
|  |                 screenReader.Speak(text, interrupt); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user