From fdc8af92eb78db8d397de2312e8898181f6df6d1 Mon Sep 17 00:00:00 2001
From: shoaib11120 <shoaib.khan20@outlook.com>
Date: Thu, 9 Dec 2021 15:00:40 +0530
Subject: [PATCH] Fixed dialogue narration

---
 stardew-access/ModEntry.cs | 80 +++++++++++++++++++++++++++-----------
 1 file changed, 57 insertions(+), 23 deletions(-)

diff --git a/stardew-access/ModEntry.cs b/stardew-access/ModEntry.cs
index 9485462..d5c168f 100644
--- a/stardew-access/ModEntry.cs
+++ b/stardew-access/ModEntry.cs
@@ -7,6 +7,8 @@ using HarmonyLib;
 using StardewValley.Menus;
 using Microsoft.Xna.Framework.Graphics;
 using System.Text;
+using StardewValley.BellsAndWhistles;
+using Microsoft.Xna.Framework;
 
 namespace stardew_access
 {
@@ -17,6 +19,8 @@ namespace stardew_access
         Harmony harmony;
         public static IMonitor monitor;
         private static string prevText = "";
+        private static DialogueBox? dialogueBox = null;
+        private int index = 0;
         /*********
         ** Public methods
         *********/
@@ -35,13 +39,9 @@ namespace stardew_access
 
             // Add patches
             harmony.Patch(
-                original: AccessTools.Constructor(typeof(DialogueBox), new Type[] { typeof(Dialogue) }),
-                postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.dialogBoxPostfix))
+               original: AccessTools.Method(typeof(DialogueBox), nameof(DialogueBox.draw), new Type[] {typeof(SpriteBatch)}),
+               postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.dialogBoxPostfix))
             );
-            /*harmony.Patch(
-               original: AccessTools.Method(typeof(DialogueBox), nameof(DialogueBox.receiveLeftClick)),
-               postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.dialogBoxRecieveLeftClickPostfix))
-            );*/
 
             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 >) }),
@@ -49,6 +49,46 @@ namespace stardew_access
             );
 
             helper.Events.Input.ButtonPressed += this.OnButtonPressed;
+            helper.Events.GameLoop.OneSecondUpdateTicked += this.OnOneSecondUpdateTicked;
+        }
+
+        private static void dialogBoxPostfix(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 iClickableMenuDrawHoverTextPostFix(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)
@@ -138,21 +178,6 @@ namespace stardew_access
             }
         }
 
-        private static void dialogBoxPostfix(Dialogue dialogue)
-        {
-            try
-            {
-                string speakerName = dialogue.speaker.Name;
-                List<string> dialogues = dialogue.dialogues;
-                int dialogueIndex = dialogue.currentDialogueIndex;
-
-                screenReader.Speak($"{speakerName} said, {dialogues[dialogueIndex]}", false);
-            } catch (Exception e)
-            {
-                monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error);
-            }
-        }
-
         private void initializeScreenReader()
         {
             NvdaOutput nvdaOutput = null;
@@ -192,15 +217,24 @@ namespace stardew_access
                 screenReader = sapiOutput;
         }
 
-
         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
             if (!Context.IsWorldReady)
               return;
 
             // Narrate Health And Energy
-            if (Equals(e.Button, SButton.R))
+            if (Equals(e.Button, SButton.I))
             {
                 screenReader.Speak($"Health is {CurrentPlayer.getHealth()} and Stamina is {CurrentPlayer.getStamina()}");
             }