Files
stardew-access/stardew-access/Patches/DialogueBoxPatch.cs
Mohammad Shoaib Khan 8523026ed0 Improved and organised code for dialogue box patch
Moved letter viewer menu patch to its own class
moved npc patch to its own clas
moved draw hover text patch to IClickableMenuPatch.cs
2023-03-08 12:06:46 +05:30

132 lines
4.5 KiB
C#

using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI;
using StardewValley;
using StardewValley.Menus;
namespace stardew_access.Patches
{
internal class DialoguePatches
{
private static string currentDialogue = "";
private static string previousSpeakerName = "";
private static bool isDialogueAppearingFirstTime = true;
internal static void DialoguePatch(DialogueBox __instance, SpriteBatch b)
{
try
{
if (__instance.transitioning) return;
if (narrateCharacterDialogue(__instance)) return;
if (narrateQuestionDialogue(__instance)) return;
narrateBasicDialogue(__instance.getCurrentString());
}
catch (Exception e)
{
MainClass.ErrorLog($"Unable to narrate dialog:\n{e.StackTrace}\n{e.Message}");
}
}
internal static void RecieveLeftClickPatch()
{
// CLears the currentDialogue string on closing dialog
Cleanup();
}
private static bool narrateCharacterDialogue(DialogueBox __instance)
{
if (__instance.characterDialogue == null) return false;
// For Normal Character dialogues
Dialogue dialogue = __instance.characterDialogue;
string speakerName = dialogue.speaker.displayName;
string dialogueText = "";
string responseText = "";
bool hasResponses = dialogue.isCurrentDialogueAQuestion();
dialogueText = $"{speakerName} said {__instance.getCurrentString()}";
if (hasResponses)
{
responseText = getCurrentResponseText(__instance);
CheckAndSpeak(isDialogueAppearingFirstTime ? $"{dialogueText} \n\t {responseText}" : responseText, responseText);
if (isDialogueAppearingFirstTime) isDialogueAppearingFirstTime = false;
}
else
{
CheckAndSpeak(dialogueText);
}
return true;
}
private static bool narrateQuestionDialogue(DialogueBox __instance)
{
if (!__instance.isQuestion) return false;
// For Dialogues with responses/answers like the dialogue when we click on tv
string questionText = "";
string responseText = "";
bool hasResponses = false;
if (__instance.responses.Count > 0) hasResponses = true;
if (!hasResponses) return false;
questionText = __instance.getCurrentString();
responseText = getCurrentResponseText(__instance);
CheckAndSpeak(isDialogueAppearingFirstTime ? $"{questionText} \n\t {responseText}" : responseText, responseText);
if (isDialogueAppearingFirstTime) isDialogueAppearingFirstTime = false;
return true;
}
private static void narrateBasicDialogue(string dialogue)
{
// Basic dialogues like `No mails in the mail box`
if (Game1.activeClickableMenu is not DialogueBox) return;
CheckAndSpeak(dialogue);
}
private static string getCurrentResponseText(DialogueBox __instance)
{
List<Response> responses = __instance.responses;
if (__instance.selectedResponse >= 0 && __instance.selectedResponse < responses.Count)
{
return $"{__instance.selectedResponse + 1}: {responses[__instance.selectedResponse].responseText}";
}
else
{
// When the dialogue is not finished writing then the selectedResponse is <0 and this results
// in the first response not being detcted, so this sets the first response option to be the default
// if the current dialogue is a question or has responses
return $"1: {responses[0].responseText}";
}
}
private static void CheckAndSpeak(string toSpeak)
{
if (currentDialogue == toSpeak) return;
currentDialogue = toSpeak;
MainClass.ScreenReader.Say(toSpeak, true);
}
private static void CheckAndSpeak(string toSpeak, string checkQuery)
{
if (currentDialogue == checkQuery) return;
currentDialogue = checkQuery;
MainClass.ScreenReader.Say(toSpeak, true);
}
internal static void Cleanup()
{
currentDialogue = "";
isDialogueAppearingFirstTime = true;
}
}
}