1321 lines
61 KiB
C#
1321 lines
61 KiB
C#
using StardewValley;
|
|
using StardewValley.Locations;
|
|
using StardewValley.Menus;
|
|
using StardewValley.Objects;
|
|
|
|
namespace stardew_access.Patches
|
|
{
|
|
// Menus in the game menu i.e., the menu which opens when we press `e`
|
|
internal class GameMenuPatches
|
|
{
|
|
internal static string hoveredItemQueryKey = "";
|
|
internal static string geodeMenuQueryKey = "";
|
|
internal static string gameMenuQueryKey = "";
|
|
internal static string itemGrabMenuQueryKey = "";
|
|
internal static string craftingPageQueryKey = "";
|
|
internal static string inventoryPageQueryKey = "";
|
|
internal static string exitPageQueryKey = "";
|
|
internal static string optionsPageQueryKey = "";
|
|
internal static string shopMenuQueryKey = "";
|
|
internal static string socialPageQuery = "";
|
|
internal static string profilePageQuery = "";
|
|
internal static int currentSelectedCraftingRecipe = -1;
|
|
internal static bool isSelectingRecipe = false;
|
|
|
|
internal static void CollectionsPagePatch(CollectionsPage __instance)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMousePosition().X, y = Game1.getMousePosition().Y;
|
|
if (__instance.letterviewerSubMenu != null)
|
|
{
|
|
DialoguePatches.NarrateLetterContent(__instance.letterviewerSubMenu);
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
internal static void SocialPagePatch(SocialPage __instance, List<ClickableTextureComponent> ___sprites, int ___slotPosition, List<string> ___kidsNames)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
for (int i = ___slotPosition; i < ___slotPosition + 5; i++)
|
|
{
|
|
if (i < ___sprites.Count)
|
|
{
|
|
if (__instance.names[i] is string)
|
|
{
|
|
#region For NPCs
|
|
if (__instance.characterSlots[i].bounds.Contains(Game1.getMouseX(true), Game1.getMouseY(true)))
|
|
{
|
|
string name = $"{__instance.names[i] as string}";
|
|
int heartLevel = Game1.player.getFriendshipHeartLevelForNPC(name);
|
|
bool datable = SocialPage.isDatable(name);
|
|
Friendship friendship = __instance.getFriendship(name);
|
|
int giftsThisWeek = friendship.GiftsThisWeek;
|
|
bool hasTalked = Game1.player.hasPlayerTalkedToNPC(name);
|
|
bool spouse = friendship.IsMarried();
|
|
bool housemate = spouse && SocialPage.isRoommateOfAnyone(name);
|
|
___kidsNames.Add("Robin");
|
|
___kidsNames.Add("Pierre");
|
|
___kidsNames.Add("Caroline");
|
|
___kidsNames.Add("Jodi");
|
|
___kidsNames.Add("Kent");
|
|
___kidsNames.Add("George");
|
|
___kidsNames.Add("Evelyn");
|
|
___kidsNames.Add("Demetrius");
|
|
|
|
|
|
|
|
string toSpeak = $"{name}";
|
|
|
|
if (!hasTalked)
|
|
{
|
|
toSpeak = $"{toSpeak}, not talked yet";
|
|
}
|
|
|
|
|
|
if (datable | housemate)
|
|
{
|
|
string text2 = (LocalizedContentManager.CurrentLanguageCode != LocalizedContentManager.LanguageCode.pt) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11635") : ((__instance.getGender(name) == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11635").Split('/').First() : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11635").Split('/').Last());
|
|
if (housemate)
|
|
{
|
|
text2 = Game1.content.LoadString("Strings\\StringsFromCSFiles:Housemate");
|
|
}
|
|
else if (spouse)
|
|
{
|
|
text2 = ((__instance.getGender(name) == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11636") : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11637"));
|
|
}
|
|
else if (__instance.isMarriedToAnyone(name))
|
|
{
|
|
text2 = ((__instance.getGender(name) == 0) ? Game1.content.LoadString("Strings\\UI:SocialPage_MarriedToOtherPlayer_MaleNPC") : Game1.content.LoadString("Strings\\UI:SocialPage_MarriedToOtherPlayer_FemaleNPC"));
|
|
}
|
|
else if (!Game1.player.isMarried() && friendship.IsDating())
|
|
{
|
|
text2 = ((__instance.getGender(name) == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11639") : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11640"));
|
|
}
|
|
else if (__instance.getFriendship(name).IsDivorced())
|
|
{
|
|
text2 = ((__instance.getGender(name) == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11642") : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11643"));
|
|
}
|
|
|
|
toSpeak = $"{toSpeak}, {text2}";
|
|
}
|
|
if (!__instance.getFriendship(name).IsMarried() && ___kidsNames.Contains(name))
|
|
{
|
|
toSpeak = $"{toSpeak}, married";
|
|
}
|
|
if (spouse)
|
|
{
|
|
toSpeak = $"{toSpeak}, spouse";
|
|
}
|
|
else if (friendship.IsDating())
|
|
{
|
|
toSpeak = $"{toSpeak}, dating";
|
|
}
|
|
|
|
toSpeak = $"{toSpeak}, {heartLevel} hearts, {giftsThisWeek} gifts given this week.";
|
|
|
|
|
|
if (socialPageQuery != toSpeak)
|
|
{
|
|
socialPageQuery = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
}
|
|
else if (__instance.names[i] is long)
|
|
{
|
|
#region For Farmers
|
|
|
|
long farmerID = (long)__instance.names[i];
|
|
Farmer farmer = Game1.getFarmerMaybeOffline(farmerID);
|
|
if (farmer != null)
|
|
{
|
|
int gender = (!farmer.IsMale) ? 1 : 0;
|
|
ClickableTextureComponent clickableTextureComponent = ___sprites[i];
|
|
if (clickableTextureComponent.containsPoint(x, y))
|
|
{
|
|
Friendship friendship = Game1.player.team.GetFriendship(Game1.player.UniqueMultiplayerID, farmerID);
|
|
bool spouse = friendship.IsMarried();
|
|
string toSpeak = "";
|
|
|
|
string text2 = (LocalizedContentManager.CurrentLanguageCode != LocalizedContentManager.LanguageCode.pt) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11635") : ((gender == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11635").Split('/').First() : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11635").Split('/').Last());
|
|
if (spouse)
|
|
{
|
|
text2 = ((gender == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11636") : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11637"));
|
|
}
|
|
else if (farmer.isMarried() && !farmer.hasRoommate())
|
|
{
|
|
text2 = ((gender == 0) ? Game1.content.LoadString("Strings\\UI:SocialPage_MarriedToOtherPlayer_MaleNPC") : Game1.content.LoadString("Strings\\UI:SocialPage_MarriedToOtherPlayer_FemaleNPC"));
|
|
}
|
|
else if (!Game1.player.isMarried() && friendship.IsDating())
|
|
{
|
|
text2 = ((gender == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11639") : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11640"));
|
|
}
|
|
else if (friendship.IsDivorced())
|
|
{
|
|
text2 = ((gender == 0) ? Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11642") : Game1.content.LoadString("Strings\\StringsFromCSFiles:SocialPage.cs.11643"));
|
|
}
|
|
|
|
toSpeak = $"{farmer.displayName}, {text2}";
|
|
|
|
if (socialPageQuery != toSpeak)
|
|
{
|
|
socialPageQuery = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
internal static void ShopMenuPatch(ShopMenu __instance)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
bool isIPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.I);
|
|
bool isLeftShiftPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.LeftShift);
|
|
|
|
if (isLeftShiftPressed && isIPressed && __instance.inventory.inventory.Count > 0)
|
|
{
|
|
__instance.inventory.inventory[0].snapMouseCursorToCenter();
|
|
__instance.setCurrentlySnappedComponentTo(__instance.inventory.inventory[0].myID);
|
|
}
|
|
else if (!isLeftShiftPressed && isIPressed && __instance.forSaleButtons.Count > 0)
|
|
{
|
|
__instance.forSaleButtons[0].snapMouseCursorToCenter();
|
|
__instance.setCurrentlySnappedComponentTo(__instance.forSaleButtons[0].myID);
|
|
}
|
|
|
|
#region Narrate buttons in the menu
|
|
if (__instance.inventory.dropItemInvisibleButton != null && __instance.inventory.dropItemInvisibleButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Drop Item";
|
|
if (shopMenuQueryKey != toSpeak)
|
|
{
|
|
shopMenuQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
Game1.playSound("drop_item");
|
|
}
|
|
return;
|
|
}
|
|
if (__instance.upArrow != null && __instance.upArrow.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Up Arrow Button";
|
|
if (shopMenuQueryKey != toSpeak)
|
|
{
|
|
shopMenuQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
if (__instance.downArrow != null && __instance.downArrow.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Down Arrow Button";
|
|
if (shopMenuQueryKey != toSpeak)
|
|
{
|
|
shopMenuQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered item
|
|
if (narrateHoveredItemInInventory(__instance.inventory.inventory, __instance.inventory.actualInventory, x, y, hoverPrice: __instance.hoverPrice))
|
|
{
|
|
shopMenuQueryKey = "";
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered selling item
|
|
if (__instance.hoveredItem != null)
|
|
{
|
|
string name = __instance.hoveredItem.DisplayName;
|
|
string price = $"Buy Price: {__instance.hoverPrice} g";
|
|
string description = __instance.hoveredItem.getDescription();
|
|
string requirements = "";
|
|
|
|
#region Narrate required items for item
|
|
int itemIndex = -1, itemAmount = 5;
|
|
|
|
if (__instance.itemPriceAndStock[__instance.hoveredItem].Length > 2)
|
|
itemIndex = __instance.itemPriceAndStock[__instance.hoveredItem][2];
|
|
|
|
if (__instance.itemPriceAndStock[__instance.hoveredItem].Length > 3)
|
|
itemAmount = __instance.itemPriceAndStock[__instance.hoveredItem][3];
|
|
|
|
if (itemIndex != -1)
|
|
{
|
|
string itemName = Game1.objectInformation[itemIndex].Split('/')[0];
|
|
|
|
if (itemAmount != -1)
|
|
requirements = $"Required: {itemAmount} {itemName}";
|
|
else
|
|
requirements = $"Required: {itemName}";
|
|
}
|
|
#endregion
|
|
|
|
string toSpeak = $"{name}, {requirements}, {price}, \n\t{description}";
|
|
if (shopMenuQueryKey != toSpeak)
|
|
{
|
|
shopMenuQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
internal static void GameMenuPatch(GameMenu __instance)
|
|
{
|
|
try
|
|
{
|
|
// Continue if only in the Inventory Page or Crafting Page
|
|
if (__instance.currentTab != 0 && __instance.currentTab != 4 && __instance.currentTab != 6 && __instance.currentTab != 7)
|
|
return;
|
|
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
|
|
for (int i = 0; i < __instance.tabs.Count; i++)
|
|
{
|
|
if (__instance.tabs[i].containsPoint(x, y))
|
|
{
|
|
string toSpeak = $"{GameMenu.getLabelOfTabFromIndex(i)} Tab";
|
|
if (gameMenuQueryKey != toSpeak)
|
|
{
|
|
gameMenuQueryKey = 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 GeodeMenuPatch(GeodeMenu __instance)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
|
|
#region Narrate the treasure recieved on breaking the geode
|
|
if (__instance.geodeTreasure != null)
|
|
{
|
|
string name = __instance.geodeTreasure.DisplayName;
|
|
int stack = __instance.geodeTreasure.Stack;
|
|
|
|
string toSpeak = $"Recieved {stack} {name}";
|
|
|
|
if (geodeMenuQueryKey != toSpeak)
|
|
{
|
|
geodeMenuQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered buttons in the menu
|
|
if (__instance.geodeSpot != null && __instance.geodeSpot.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Place geode here";
|
|
if (geodeMenuQueryKey != toSpeak)
|
|
{
|
|
geodeMenuQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Drop item here";
|
|
|
|
if (geodeMenuQueryKey != toSpeak)
|
|
{
|
|
geodeMenuQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
Game1.playSound("drop_item");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Trash can";
|
|
|
|
if (geodeMenuQueryKey != toSpeak)
|
|
{
|
|
geodeMenuQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Ok button";
|
|
|
|
if (geodeMenuQueryKey != toSpeak)
|
|
{
|
|
geodeMenuQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered item
|
|
if (narrateHoveredItemInInventory(__instance.inventory.inventory, __instance.inventory.actualInventory, x, y))
|
|
geodeMenuQueryKey = "";
|
|
#endregion
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
internal static void ItemGrabMenuPatch(ItemGrabMenu __instance)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
bool isIPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.I);
|
|
bool isLeftShiftPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.LeftShift);
|
|
|
|
if (isLeftShiftPressed && isIPressed && __instance.inventory.inventory.Count > 0)
|
|
{
|
|
__instance.setCurrentlySnappedComponentTo(__instance.inventory.inventory[0].myID);
|
|
__instance.inventory.inventory[0].snapMouseCursorToCenter();
|
|
}
|
|
else if (!isLeftShiftPressed && isIPressed && __instance.ItemsToGrabMenu.inventory.Count > 0 && !__instance.shippingBin)
|
|
{
|
|
__instance.setCurrentlySnappedComponentTo(__instance.ItemsToGrabMenu.inventory[0].myID);
|
|
__instance.ItemsToGrabMenu.inventory[0].snapMouseCursorToCenter();
|
|
}
|
|
|
|
#region Narrate buttons in the menu
|
|
if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Ok Button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
gameMenuQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Trash Can";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.organizeButton != null && __instance.organizeButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Organize Button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.fillStacksButton != null && __instance.fillStacksButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Add to existing stacks button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.specialButton != null && __instance.specialButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Special Button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.colorPickerToggleButton != null && __instance.colorPickerToggleButton.containsPoint(x, y))
|
|
{
|
|
|
|
string toSpeak = "Color Picker: " + (__instance.chestColorPicker.visible ? "Enabled" : "Disabled");
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.junimoNoteIcon != null && __instance.junimoNoteIcon.containsPoint(x, y))
|
|
{
|
|
|
|
string toSpeak = "Community Center Button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Drop Item";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
Game1.playSound("drop_item");
|
|
}
|
|
return;
|
|
}
|
|
|
|
// FIXME
|
|
/*if (__instance.discreteColorPickerCC.Count > 0) {
|
|
for (int i = 0; i < __instance.discreteColorPickerCC.Count; i++)
|
|
{
|
|
if (__instance.discreteColorPickerCC[i].containsPoint(x, y))
|
|
{
|
|
MainClass.monitor.Log(i.ToString(), LogLevel.Debug);
|
|
string toSpeak = getChestColorName(i);
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
ScreenReader.say(toSpeak, true);
|
|
Game1.playSound("sa_drop_item");
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}*/
|
|
#endregion
|
|
|
|
#region Narrate the last shipped item if in the shipping bin
|
|
if (__instance.shippingBin && Game1.getFarm().lastItemShipped != null && __instance.lastShippedHolder.containsPoint(x, y))
|
|
{
|
|
Item lastShippedItem = Game1.getFarm().lastItemShipped;
|
|
string name = lastShippedItem.DisplayName;
|
|
int count = lastShippedItem.Stack;
|
|
|
|
string toSpeak = $"Last Shipped: {count} {name}";
|
|
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered item
|
|
if (narrateHoveredItemInInventory(__instance.inventory.inventory, __instance.inventory.actualInventory, x, y, true))
|
|
{
|
|
gameMenuQueryKey = "";
|
|
itemGrabMenuQueryKey = "";
|
|
return;
|
|
}
|
|
|
|
if (narrateHoveredItemInInventory(__instance.ItemsToGrabMenu.inventory, __instance.ItemsToGrabMenu.actualInventory, x, y, true))
|
|
{
|
|
gameMenuQueryKey = "";
|
|
itemGrabMenuQueryKey = "";
|
|
return;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
// TODO Add color names
|
|
private static string getChestColorName(int i)
|
|
{
|
|
string toReturn = "";
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 1:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 2:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 3:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 4:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 5:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 6:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 7:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 8:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 9:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 10:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 11:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 12:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 13:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 14:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 15:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 16:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 17:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 18:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 19:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
case 20:
|
|
toReturn = "Default chest color";
|
|
break;
|
|
}
|
|
return toReturn;
|
|
}
|
|
|
|
internal static void CraftingPagePatch(CraftingPage __instance, CraftingRecipe ___hoverRecipe, int ___currentCraftingPage)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
bool isIPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.I);
|
|
bool isCPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.C);
|
|
bool isLeftShiftPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.LeftShift);
|
|
|
|
if (isLeftShiftPressed && isIPressed && __instance.inventory.inventory.Count > 0)
|
|
{
|
|
// snap to first inventory slot
|
|
__instance.setCurrentlySnappedComponentTo(__instance.inventory.inventory[0].myID);
|
|
__instance.inventory.inventory[0].snapMouseCursorToCenter();
|
|
currentSelectedCraftingRecipe = -1;
|
|
}
|
|
else if (!isLeftShiftPressed && isIPressed && __instance.pagesOfCraftingRecipes[___currentCraftingPage].Count > 0)
|
|
{
|
|
// snap to first crafting recipe
|
|
__instance.setCurrentlySnappedComponentTo(__instance.pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(0).Key.myID);
|
|
__instance.pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(0).Key.snapMouseCursorToCenter();
|
|
currentSelectedCraftingRecipe = 0;
|
|
}
|
|
else if (isCPressed && !isSelectingRecipe)
|
|
{
|
|
isSelectingRecipe = true;
|
|
CycleThroughRecipies(__instance.pagesOfCraftingRecipes, ___currentCraftingPage, __instance);
|
|
Task.Delay(200).ContinueWith(_ => { isSelectingRecipe = false; });
|
|
}
|
|
|
|
#region Narrate buttons in the menu
|
|
if (__instance.upButton != null && __instance.upButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Previous Recipe List";
|
|
if (craftingPageQueryKey != toSpeak)
|
|
{
|
|
craftingPageQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.downButton != null && __instance.downButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Next Recipe List";
|
|
if (craftingPageQueryKey != toSpeak)
|
|
{
|
|
craftingPageQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.trashCan.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Trash Can";
|
|
if (craftingPageQueryKey != toSpeak)
|
|
{
|
|
craftingPageQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.dropItemInvisibleButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Drop Item";
|
|
if (craftingPageQueryKey != toSpeak)
|
|
{
|
|
craftingPageQueryKey = toSpeak;
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
Game1.playSound("drop_item");
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered recipe
|
|
if (___hoverRecipe != null)
|
|
{
|
|
string name = ___hoverRecipe.DisplayName;
|
|
int numberOfProduce = ___hoverRecipe.numberProducedPerCraft;
|
|
string description = "";
|
|
string ingredients = "";
|
|
string buffs = "";
|
|
string craftable = "";
|
|
|
|
description = $"Description:\n{___hoverRecipe.description}";
|
|
craftable = ___hoverRecipe.doesFarmerHaveIngredientsInInventory(getContainerContents(__instance._materialContainers)) ? "Craftable" : "Not Craftable";
|
|
|
|
#region Crafting ingredients
|
|
ingredients = "Ingredients:\n";
|
|
for (int i = 0; i < ___hoverRecipe.recipeList.Count; i++)
|
|
{
|
|
int recipeCount = ___hoverRecipe.recipeList.ElementAt(i).Value;
|
|
int recipeItem = ___hoverRecipe.recipeList.ElementAt(i).Key;
|
|
string recipeName = ___hoverRecipe.getNameFromIndex(recipeItem);
|
|
|
|
ingredients += $" ,{recipeCount} {recipeName}";
|
|
}
|
|
#endregion
|
|
|
|
#region Health & stamina and buff items (effects like +1 walking speed)
|
|
Item producesItem = ___hoverRecipe.createItem();
|
|
StardewValley.Object? producesItemObject = ((StardewValley.Object)producesItem);
|
|
|
|
if (producesItem is StardewValley.Object && producesItemObject.Edibility != -300)
|
|
{
|
|
int stamina_recovery = producesItemObject.staminaRecoveredOnConsumption();
|
|
buffs += $"{stamina_recovery} Energy";
|
|
if (stamina_recovery >= 0)
|
|
{
|
|
int health_recovery = producesItemObject.healthRecoveredOnConsumption();
|
|
buffs += $"\n{health_recovery} Health";
|
|
}
|
|
}
|
|
// These variables are taken from the game's code itself (IClickableMenu.cs -> 1016 line)
|
|
bool edibleItem = producesItem != null && producesItem is StardewValley.Object && (int)producesItemObject.Edibility != -300;
|
|
string[]? buffIconsToDisplay = (producesItem != null && edibleItem && Game1.objectInformation[producesItemObject.ParentSheetIndex].Split('/').Length > 7)
|
|
? producesItem.ModifyItemBuffs(Game1.objectInformation[producesItemObject.ParentSheetIndex].Split('/')[7].Split(' '))
|
|
: null;
|
|
|
|
if (buffIconsToDisplay != null)
|
|
{
|
|
for (int j = 0; j < buffIconsToDisplay.Length; j++)
|
|
{
|
|
string buffName = ((Convert.ToInt32(buffIconsToDisplay[j]) > 0) ? "+" : "") + buffIconsToDisplay[j] + " ";
|
|
if (j <= 11)
|
|
{
|
|
buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + j, buffName);
|
|
}
|
|
try
|
|
{
|
|
int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' ')));
|
|
if (count != 0)
|
|
buffs += $"{buffName}\n";
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
|
|
buffs = $"Buffs and boosts:\n {buffs}";
|
|
}
|
|
#endregion
|
|
|
|
|
|
string toSpeak = $"{numberOfProduce} {name}, {craftable}, \n\t{ingredients}, \n\t{description} \n\t{buffs}";
|
|
|
|
if (craftingPageQueryKey != toSpeak)
|
|
{
|
|
craftingPageQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
var isRecipeInFocus = false;
|
|
foreach (var item in __instance.pagesOfCraftingRecipes[___currentCraftingPage])
|
|
{
|
|
if (item.Key.containsPoint(x, y))
|
|
{
|
|
isRecipeInFocus = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isRecipeInFocus)
|
|
{
|
|
string query = $"unknown recipe:{__instance.getCurrentlySnappedComponent().myID}";
|
|
|
|
if (craftingPageQueryKey != query)
|
|
{
|
|
craftingPageQueryKey = query;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say("unknown recipe", true);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered item
|
|
if (narrateHoveredItemInInventory(__instance.inventory.inventory, __instance.inventory.actualInventory, x, y))
|
|
{
|
|
gameMenuQueryKey = "";
|
|
craftingPageQueryKey = "";
|
|
return;
|
|
}
|
|
#endregion
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
private static void CycleThroughRecipies(List<Dictionary<ClickableTextureComponent, CraftingRecipe>> pagesOfCraftingRecipes, int ___currentCraftingPage, CraftingPage __instance)
|
|
{
|
|
currentSelectedCraftingRecipe++;
|
|
if (currentSelectedCraftingRecipe < 0 || currentSelectedCraftingRecipe >= pagesOfCraftingRecipes[0].Count)
|
|
currentSelectedCraftingRecipe = 0;
|
|
|
|
__instance.setCurrentlySnappedComponentTo(pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.myID);
|
|
pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.snapMouseCursorToCenter();
|
|
|
|
// Skip if recipe is not unlocked/unknown
|
|
if (pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.hoverText.Equals("ghosted"))
|
|
CycleThroughRecipies(pagesOfCraftingRecipes, ___currentCraftingPage, __instance);
|
|
}
|
|
|
|
// This method is used to get the inventory items to check if the player has enough ingredients for a recipe
|
|
// Taken from CraftingPage.cs -> 169 line
|
|
internal static IList<Item>? getContainerContents(List<Chest> materialContainers)
|
|
{
|
|
if (materialContainers == null)
|
|
{
|
|
return null;
|
|
}
|
|
List<Item> items = new List<Item>();
|
|
for (int i = 0; i < materialContainers.Count; i++)
|
|
{
|
|
items.AddRange(materialContainers[i].items);
|
|
}
|
|
return items;
|
|
}
|
|
|
|
internal static void InventoryPagePatch(InventoryPage __instance)
|
|
{
|
|
try
|
|
{
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
|
|
#region Narrate buttons in the menu
|
|
if (__instance.inventory.dropItemInvisibleButton != null && __instance.inventory.dropItemInvisibleButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Drop Item";
|
|
if (inventoryPageQueryKey != toSpeak)
|
|
{
|
|
inventoryPageQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
Game1.playSound("drop_item");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.organizeButton != null && __instance.organizeButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Organize Inventory Button";
|
|
if (inventoryPageQueryKey != toSpeak)
|
|
{
|
|
inventoryPageQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Trash Can";
|
|
if (inventoryPageQueryKey != toSpeak)
|
|
{
|
|
inventoryPageQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.organizeButton != null && __instance.organizeButton.containsPoint(x, y))
|
|
{
|
|
string toSpeak = "Organize Button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (__instance.junimoNoteIcon != null && __instance.junimoNoteIcon.containsPoint(x, y))
|
|
{
|
|
|
|
string toSpeak = "Community Center Button";
|
|
if (itemGrabMenuQueryKey != toSpeak)
|
|
{
|
|
itemGrabMenuQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate equipment slots
|
|
for (int i = 0; i < __instance.equipmentIcons.Count; i++)
|
|
{
|
|
if (__instance.equipmentIcons[i].containsPoint(x, y))
|
|
{
|
|
string toSpeak = "";
|
|
|
|
#region Get name and description of the item
|
|
switch (__instance.equipmentIcons[i].name)
|
|
{
|
|
case "Hat":
|
|
{
|
|
if (Game1.player.hat.Value != null)
|
|
{
|
|
toSpeak = $"{Game1.player.hat.Value.DisplayName}, {Game1.player.hat.Value.getDescription()}";
|
|
}
|
|
else
|
|
{
|
|
toSpeak = "Hat slot";
|
|
}
|
|
}
|
|
break;
|
|
case "Left Ring":
|
|
{
|
|
if (Game1.player.leftRing.Value != null)
|
|
{
|
|
toSpeak = $"{Game1.player.leftRing.Value.DisplayName}, {Game1.player.leftRing.Value.getDescription()}";
|
|
}
|
|
else
|
|
{
|
|
toSpeak = "Left Ring slot";
|
|
}
|
|
}
|
|
break;
|
|
case "Right Ring":
|
|
{
|
|
if (Game1.player.rightRing.Value != null)
|
|
{
|
|
toSpeak = $"{Game1.player.rightRing.Value.DisplayName}, {Game1.player.rightRing.Value.getDescription()}";
|
|
}
|
|
else
|
|
{
|
|
toSpeak = "Right ring slot";
|
|
}
|
|
}
|
|
break;
|
|
case "Boots":
|
|
{
|
|
if (Game1.player.boots.Value != null)
|
|
{
|
|
toSpeak = $"{Game1.player.boots.Value.DisplayName}, {Game1.player.boots.Value.getDescription()}";
|
|
}
|
|
else
|
|
{
|
|
toSpeak = "Boots slot";
|
|
}
|
|
}
|
|
break;
|
|
case "Shirt":
|
|
{
|
|
if (Game1.player.shirtItem.Value != null)
|
|
{
|
|
toSpeak = $"{Game1.player.shirtItem.Value.DisplayName}, {Game1.player.shirtItem.Value.getDescription()}";
|
|
}
|
|
else
|
|
{
|
|
toSpeak = "Shirt slot";
|
|
}
|
|
}
|
|
break;
|
|
case "Pants":
|
|
{
|
|
if (Game1.player.pantsItem.Value != null)
|
|
{
|
|
toSpeak = $"{Game1.player.pantsItem.Value.DisplayName}, {Game1.player.pantsItem.Value.getDescription()}";
|
|
}
|
|
else
|
|
{
|
|
toSpeak = "Pants slot";
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endregion
|
|
|
|
if (inventoryPageQueryKey != toSpeak)
|
|
{
|
|
inventoryPageQueryKey = toSpeak;
|
|
gameMenuQueryKey = "";
|
|
hoveredItemQueryKey = "";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Narrate hovered item
|
|
if (narrateHoveredItemInInventory(__instance.inventory.inventory, __instance.inventory.actualInventory, x, y, true))
|
|
{
|
|
gameMenuQueryKey = "";
|
|
inventoryPageQueryKey = "";
|
|
return;
|
|
}
|
|
#endregion
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
internal static void OptionsPagePatch(OptionsPage __instance)
|
|
{
|
|
try
|
|
{
|
|
int currentItemIndex = Math.Max(0, Math.Min(__instance.options.Count - 7, __instance.currentItemIndex));
|
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true);
|
|
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 (toSpeak.Contains(":"))
|
|
toSpeak = toSpeak.Replace(":", "");
|
|
|
|
toSpeak = $"{toSpeak} Options:";
|
|
}
|
|
|
|
if (optionsPageQueryKey != toSpeak)
|
|
{
|
|
gameMenuQueryKey = "";
|
|
optionsPageQueryKey = 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 ExitPagePatch(ExitPage __instance)
|
|
{
|
|
try
|
|
{
|
|
if (__instance.exitToTitle.visible &&
|
|
__instance.exitToTitle.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true)))
|
|
{
|
|
string toSpeak = "Exit to Title Button";
|
|
if (exitPageQueryKey != toSpeak)
|
|
{
|
|
gameMenuQueryKey = "";
|
|
exitPageQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
if (__instance.exitToDesktop.visible &&
|
|
__instance.exitToDesktop.containsPoint(Game1.getMouseX(true), Game1.getMouseY(true)))
|
|
{
|
|
string toSpeak = "Exit to Desktop Button";
|
|
if (exitPageQueryKey != toSpeak)
|
|
{
|
|
gameMenuQueryKey = "";
|
|
exitPageQueryKey = toSpeak;
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
internal static bool narrateHoveredItemInInventory(List<ClickableComponent> inventory, IList<Item> actualInventory, int x, int y, bool giveExtraDetails = false, int hoverPrice = -1, int extraItemToShowIndex = -1, int extraItemToShowAmount = -1)
|
|
{
|
|
#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 = "";
|
|
string healthNStamine = "";
|
|
string buffs = "";
|
|
string description = "";
|
|
string price = "";
|
|
string requirements = "";
|
|
|
|
#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 (giveExtraDetails)
|
|
{
|
|
description = actualInventory[i].getDescription();
|
|
#region Add health & stamina provided by the item
|
|
if (actualInventory[i] is StardewValley.Object && ((StardewValley.Object)actualInventory[i]).Edibility != -300)
|
|
{
|
|
int stamina_recovery = ((StardewValley.Object)actualInventory[i]).staminaRecoveredOnConsumption();
|
|
healthNStamine += $"{stamina_recovery} Energy";
|
|
if (stamina_recovery >= 0)
|
|
{
|
|
int health_recovery = ((StardewValley.Object)actualInventory[i]).healthRecoveredOnConsumption();
|
|
healthNStamine += $"\n\t{health_recovery} Health";
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Add buff items (effects like +1 walking speed)
|
|
// These variables are taken from the game's code itself (IClickableMenu.cs -> 1016 line)
|
|
bool edibleItem = actualInventory[i] != null && actualInventory[i] is StardewValley.Object && (int)((StardewValley.Object)actualInventory[i]).Edibility != -300;
|
|
string[]? buffIconsToDisplay = (edibleItem && Game1.objectInformation[((StardewValley.Object)actualInventory[i]).ParentSheetIndex].Split('/').Length > 7) ? actualInventory[i].ModifyItemBuffs(Game1.objectInformation[((StardewValley.Object)actualInventory[i]).ParentSheetIndex].Split('/')[7].Split(' ')) : null;
|
|
if (buffIconsToDisplay != null)
|
|
{
|
|
for (int j = 0; j < buffIconsToDisplay.Length; j++)
|
|
{
|
|
string buffName = ((Convert.ToInt32(buffIconsToDisplay[j]) > 0) ? "+" : "") + buffIconsToDisplay[j] + " ";
|
|
if (j <= 11)
|
|
{
|
|
buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + j, buffName);
|
|
}
|
|
try
|
|
{
|
|
int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' ')));
|
|
if (count != 0)
|
|
buffs += $"{buffName}\n";
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#region Narrate hovered required ingredients
|
|
if (extraItemToShowIndex != -1)
|
|
{
|
|
string itemName = Game1.objectInformation[extraItemToShowIndex].Split('/')[0];
|
|
|
|
if (extraItemToShowAmount != -1)
|
|
requirements = $"Required: {extraItemToShowAmount} {itemName}";
|
|
else
|
|
requirements = $"Required: {itemName}";
|
|
}
|
|
#endregion
|
|
|
|
if (hoverPrice != -1)
|
|
{
|
|
price = $"Sell Price: {hoverPrice} g";
|
|
}
|
|
|
|
if (giveExtraDetails)
|
|
{
|
|
if (stack > 1)
|
|
toSpeak = $"{stack} {name} {quality}, \n{requirements}, \n{price}, \n{description}, \n{healthNStamine}, \n{buffs}";
|
|
else
|
|
toSpeak = $"{name} {quality}, \n{requirements}, \n{price}, \n{description}, \n{healthNStamine}, \n{buffs}";
|
|
}
|
|
else
|
|
{
|
|
if (stack > 1)
|
|
toSpeak = $"{stack} {name} {quality}, \n{requirements}, \n{price}";
|
|
else
|
|
toSpeak = $"{name} {quality}, \n{requirements}, \n{price}";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For empty slot
|
|
toSpeak = "Empty Slot";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For empty slot
|
|
toSpeak = "Empty Slot";
|
|
}
|
|
|
|
if (hoveredItemQueryKey != $"{toSpeak}:{i}")
|
|
{
|
|
hoveredItemQueryKey = $"{toSpeak}:{i}";
|
|
MainClass.ScreenReader.Say(toSpeak, true);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
#endregion
|
|
return false;
|
|
}
|
|
}
|
|
}
|