Organised code for donation menu patches
parent
5195313a5b
commit
2ddebd3615
|
@ -167,11 +167,6 @@ namespace stardew_access
|
||||||
postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.LanguageSelectionMenuPatch))
|
postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.LanguageSelectionMenuPatch))
|
||||||
);
|
);
|
||||||
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }),
|
|
||||||
prefix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuKeyPressPatch))
|
|
||||||
);
|
|
||||||
|
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(ChooseFromListMenu), nameof(ChooseFromListMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
original: AccessTools.Method(typeof(ChooseFromListMenu), nameof(ChooseFromListMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
||||||
postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.ChooseFromListMenuPatch))
|
postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.ChooseFromListMenuPatch))
|
||||||
|
@ -255,12 +250,17 @@ namespace stardew_access
|
||||||
#region Donation Menus
|
#region Donation Menus
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
||||||
postfix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuPatch))
|
postfix: new HarmonyMethod(typeof(MuseumMenuPatch), nameof(MuseumMenuPatch.DrawPatch))
|
||||||
|
);
|
||||||
|
|
||||||
|
harmony.Patch(
|
||||||
|
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }),
|
||||||
|
prefix: new HarmonyMethod(typeof(MuseumMenuPatch), nameof(MuseumMenuPatch.RecieveKeyPressPatch))
|
||||||
);
|
);
|
||||||
|
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(FieldOfficeMenu), nameof(FieldOfficeMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
original: AccessTools.Method(typeof(FieldOfficeMenu), nameof(FieldOfficeMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
||||||
postfix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.FieldOfficeMenuPatch))
|
postfix: new HarmonyMethod(typeof(FieldOfficeMenuPatch), nameof(FieldOfficeMenuPatch.DrawPatch))
|
||||||
);
|
);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -159,5 +159,16 @@ namespace stardew_access.Patches
|
||||||
MainClass.ScreenReader.Say(toSpeak, true);
|
MainClass.ScreenReader.Say(toSpeak, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void Cleanup()
|
||||||
|
{
|
||||||
|
CarpenterMenuPatch.carpenterMenuQuery = "";
|
||||||
|
CarpenterMenuPatch.isUpgrading = false;
|
||||||
|
CarpenterMenuPatch.isDemolishing = false;
|
||||||
|
CarpenterMenuPatch.isPainting = false;
|
||||||
|
CarpenterMenuPatch.isMoving = false;
|
||||||
|
CarpenterMenuPatch.isConstructing = false;
|
||||||
|
CarpenterMenuPatch.carpenterMenu = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ namespace stardew_access.Patches
|
||||||
bool isPrevButtonPressed = MainClass.Config.ChatMenuNextKey.JustPressed();
|
bool isPrevButtonPressed = MainClass.Config.ChatMenuNextKey.JustPressed();
|
||||||
bool isNextButtonPressed = MainClass.Config.ChatMenuPreviousKey.JustPressed();
|
bool isNextButtonPressed = MainClass.Config.ChatMenuPreviousKey.JustPressed();
|
||||||
|
|
||||||
if (___messages.Count > 0)
|
if (___messages.Count <= 0) return;
|
||||||
{
|
|
||||||
#region To narrate previous and next chat messages
|
#region To narrate previous and next chat messages
|
||||||
if (isNextButtonPressed && !isChatRunning)
|
if (isNextButtonPressed && !isChatRunning)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,6 @@ namespace stardew_access.Patches
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (___messages.Count > 0)
|
else if (___messages.Count > 0)
|
||||||
{
|
{
|
||||||
#region To narrate latest chat message
|
#region To narrate latest chat message
|
||||||
|
|
|
@ -1,328 +0,0 @@
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Content;
|
|
||||||
using StardewValley;
|
|
||||||
using StardewValley.Locations;
|
|
||||||
using StardewValley.Menus;
|
|
||||||
|
|
||||||
namespace stardew_access.Patches
|
|
||||||
{
|
|
||||||
internal class DonationMenuPatches
|
|
||||||
{
|
|
||||||
internal static string museumQueryKey = " ";
|
|
||||||
internal static string fieldOfficeMenuQuery = " ";
|
|
||||||
private static bool isMoving = false;
|
|
||||||
private static (int x, int y)[] donationTiles =
|
|
||||||
{
|
|
||||||
(26,5),(26,6),(26,7),(26,8),(26,9),(26,10),(26,11),
|
|
||||||
(29,5),(30,5),(31,5),(32,5),(33,5),(34,5),(35,5),(36,5),
|
|
||||||
(28,6),(29,6),(30,6),(31,6),(32,6),(33,6),(34,6),(35,6),(36,6),(37,6),
|
|
||||||
(28,9),(29,9),(30,9),(31,9),(32,9),(33,9),(34,9),(35,9),(36,9),
|
|
||||||
(28,10),(29,10),(30,10),(31,10),(32,10),(33,10),(34,10),(35,10),(36,10),
|
|
||||||
(30,13),(31,13),(32,13),(33,13),(34,13),
|
|
||||||
(30,14),(31,14),(32,14),(33,14),(34,14),
|
|
||||||
(28,15),(29,15),(30,15),(31,15),(32,15),(33,15),(34,15),(35,15),(36,15),
|
|
||||||
(28,16),(29,16),(30,16),(31,16),(32,16),(33,16),(34,16),(35,16),(36,16),
|
|
||||||
(39,6),(40,6),(41,6),(42,6),(43,6),(44,6),(45,6),(46,6),
|
|
||||||
(39,7),(40,7),(41,7),(42,7),(43,7),(44,7),(45,7),(46,7),
|
|
||||||
(48,5),(48,6),(48,7),
|
|
||||||
(42,15),(43,15),(44,15),(45,15),(46,15),(47,15),
|
|
||||||
(42,16),(43,16),(44,16),(45,16),(46,16),(47,16),
|
|
||||||
};
|
|
||||||
|
|
||||||
#region Museum
|
|
||||||
|
|
||||||
internal static bool MuseumMenuKeyPressPatch()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (isMoving)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isMoving)
|
|
||||||
{
|
|
||||||
isMoving = true;
|
|
||||||
Task.Delay(200).ContinueWith(_ => { isMoving = false; });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void MuseumMenuPatch(MuseumMenu __instance, bool ___holdingMuseumPiece)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
||||||
|
|
||||||
if (__instance.heldItem != null)
|
|
||||||
{
|
|
||||||
// Museum Inventory
|
|
||||||
string toSpeak = " ";
|
|
||||||
int tileX = (int)(Utility.ModifyCoordinateFromUIScale(x) + (float)Game1.viewport.X) / 64;
|
|
||||||
int tileY = (int)(Utility.ModifyCoordinateFromUIScale(y) + (float)Game1.viewport.Y) / 64;
|
|
||||||
LibraryMuseum libraryMuseum = (LibraryMuseum)Game1.currentLocation;
|
|
||||||
|
|
||||||
if (libraryMuseum.isTileSuitableForMuseumPiece(tileX, tileY))
|
|
||||||
toSpeak = $"slot {tileX}x {tileY}y";
|
|
||||||
|
|
||||||
if (museumQueryKey != toSpeak)
|
|
||||||
{
|
|
||||||
museumQueryKey = toSpeak;
|
|
||||||
MainClass.ScreenReader.Say(toSpeak, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Player Inventory
|
|
||||||
int i = InventoryUtils.narrateHoveredSlotAndReturnIndex(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y,
|
|
||||||
handleHighlightedItem: true, highlightedItemPrefix: "Donatable ");
|
|
||||||
if (i != -9999)
|
|
||||||
{
|
|
||||||
bool isPrimaryInfoKeyPressed = MainClass.Config.PrimaryInfoKey.JustPressed(); // For donating hovered item
|
|
||||||
|
|
||||||
if (isPrimaryInfoKeyPressed && __instance.inventory.actualInventory[i] != null)
|
|
||||||
{
|
|
||||||
foreach (var tile in donationTiles)
|
|
||||||
{
|
|
||||||
#region Manually donates the hovered item (https://github.com/veywrn/StardewValley/blob/3ff171b6e9e6839555d7881a391b624ccd820a83/StardewValley/Menus/MuseumMenu.cs#L206-L247)
|
|
||||||
int tileX = tile.x;
|
|
||||||
int tileY = tile.y;
|
|
||||||
|
|
||||||
if (((LibraryMuseum)Game1.currentLocation).isTileSuitableForMuseumPiece(tileX, tileY) && ((LibraryMuseum)Game1.currentLocation).isItemSuitableForDonation(__instance.inventory.actualInventory[i]))
|
|
||||||
{
|
|
||||||
int objectID = __instance.inventory.actualInventory[i].ParentSheetIndex;
|
|
||||||
int rewardsCount = ((LibraryMuseum)Game1.currentLocation).getRewardsForPlayer(Game1.player).Count;
|
|
||||||
((LibraryMuseum)Game1.currentLocation).museumPieces.Add(new Vector2(tileX, tileY), ((StardewValley.Object)__instance.inventory.actualInventory[i]).ParentSheetIndex);
|
|
||||||
Game1.playSound("stoneStep");
|
|
||||||
if (((LibraryMuseum)Game1.currentLocation).getRewardsForPlayer(Game1.player).Count > rewardsCount)
|
|
||||||
{
|
|
||||||
Game1.playSound("reward");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Game1.playSound("newArtifact");
|
|
||||||
}
|
|
||||||
Game1.player.completeQuest(24);
|
|
||||||
__instance.inventory.actualInventory[i].Stack--;
|
|
||||||
if (__instance.inventory.actualInventory[i].Stack <= 0)
|
|
||||||
{
|
|
||||||
__instance.inventory.actualInventory[i] = null;
|
|
||||||
}
|
|
||||||
int pieces = ((LibraryMuseum)Game1.currentLocation).museumPieces.Count();
|
|
||||||
Game1.stats.checkForArchaeologyAchievements();
|
|
||||||
switch (pieces)
|
|
||||||
{
|
|
||||||
case 95:
|
|
||||||
globalChatInfoMessage("MuseumComplete", Game1.player.farmName.Value);
|
|
||||||
break;
|
|
||||||
case 40:
|
|
||||||
globalChatInfoMessage("Museum40", Game1.player.farmName.Value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
globalChatInfoMessage("donation", Game1.player.Name, "object:" + objectID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
|
|
||||||
{
|
|
||||||
if (museumQueryKey != $"ok button")
|
|
||||||
{
|
|
||||||
museumQueryKey = $"ok button";
|
|
||||||
MainClass.ScreenReader.Say("ok button", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region These methods are taken from the game's source code, https://github.com/veywrn/StardewValley/blob/3ff171b6e9e6839555d7881a391b624ccd820a83/StardewValley/Multiplayer.cs#L1331-L1395
|
|
||||||
internal static void globalChatInfoMessage(string messageKey, params string[] args)
|
|
||||||
{
|
|
||||||
if (Game1.IsMultiplayer || Game1.multiplayerMode != 0)
|
|
||||||
{
|
|
||||||
receiveChatInfoMessage(Game1.player, messageKey, args);
|
|
||||||
sendChatInfoMessage(messageKey, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void sendChatInfoMessage(string messageKey, params string[] args)
|
|
||||||
{
|
|
||||||
if (Game1.IsClient)
|
|
||||||
{
|
|
||||||
Game1.client.sendMessage(15, messageKey, args);
|
|
||||||
}
|
|
||||||
else if (Game1.IsServer)
|
|
||||||
{
|
|
||||||
foreach (long id in Game1.otherFarmers.Keys)
|
|
||||||
{
|
|
||||||
Game1.server.sendMessage(id, 15, Game1.player, messageKey, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void receiveChatInfoMessage(Farmer sourceFarmer, string messageKey, string[] args)
|
|
||||||
{
|
|
||||||
if (Game1.chatBox != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string[] processedArgs = args.Select(delegate (string arg)
|
|
||||||
{
|
|
||||||
if (arg.StartsWith("achievement:"))
|
|
||||||
{
|
|
||||||
int key = Convert.ToInt32(arg.Substring("achievement:".Length));
|
|
||||||
return Game1.content.Load<Dictionary<int, string>>("Data\\Achievements")[key].Split('^')[0];
|
|
||||||
}
|
|
||||||
return arg.StartsWith("object:") ? new StardewValley.Object(Convert.ToInt32(arg.Substring("object:".Length)), 1).DisplayName : arg;
|
|
||||||
}).ToArray();
|
|
||||||
ChatBox chatBox = Game1.chatBox;
|
|
||||||
LocalizedContentManager content = Game1.content;
|
|
||||||
string path = "Strings\\UI:Chat_" + messageKey;
|
|
||||||
object[] substitutions = processedArgs;
|
|
||||||
chatBox.addInfoMessage(content.LoadString(path, substitutions));
|
|
||||||
}
|
|
||||||
catch (ContentLoadException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch (FormatException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch (OverflowException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch (KeyNotFoundException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Field Office
|
|
||||||
|
|
||||||
internal static void FieldOfficeMenuPatch(FieldOfficeMenu __instance)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
|
||||||
string toSpeak = " ";
|
|
||||||
|
|
||||||
if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
|
|
||||||
{
|
|
||||||
toSpeak = "Trashcan";
|
|
||||||
}
|
|
||||||
else if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
|
|
||||||
{
|
|
||||||
toSpeak = "ok button";
|
|
||||||
}
|
|
||||||
else if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
|
||||||
{
|
|
||||||
toSpeak = "drop item";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (InventoryUtils.narrateHoveredSlot(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < __instance.pieceHolders.Count; i++)
|
|
||||||
{
|
|
||||||
if (!__instance.pieceHolders[i].containsPoint(x, y))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (__instance.pieceHolders[i].item == null)
|
|
||||||
toSpeak = i switch
|
|
||||||
{
|
|
||||||
0 => "Center skeleton slot",
|
|
||||||
1 => "Center skeleton slot",
|
|
||||||
2 => "Center skeleton slot",
|
|
||||||
3 => "Center skeleton slot",
|
|
||||||
4 => "Center skeleton slot",
|
|
||||||
5 => "Center skeleton slot",
|
|
||||||
6 => "Snake slot",
|
|
||||||
7 => "Snake slot",
|
|
||||||
8 => "Snake slot",
|
|
||||||
9 => "Bat slot",
|
|
||||||
10 => "Frog slot",
|
|
||||||
_ => "Donation slot"
|
|
||||||
};
|
|
||||||
else
|
|
||||||
toSpeak = $"Slot {i + 1} finished: {__instance.pieceHolders[i].item.DisplayName}";
|
|
||||||
|
|
||||||
if (!MainClass.Config.DisableInventoryVerbosity && __instance.heldItem != null && __instance.pieceHolders[i].item == null)
|
|
||||||
{
|
|
||||||
int highlight = getPieceIndexForDonationItem(__instance.heldItem.ParentSheetIndex);
|
|
||||||
if (highlight != -1 && highlight == i)
|
|
||||||
toSpeak += "Donatable ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldOfficeMenuQuery != $"{toSpeak}:{i}")
|
|
||||||
{
|
|
||||||
fieldOfficeMenuQuery = $"{toSpeak}:{i}";
|
|
||||||
MainClass.ScreenReader.Say(toSpeak, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldOfficeMenuQuery != toSpeak)
|
|
||||||
{
|
|
||||||
fieldOfficeMenuQuery = toSpeak;
|
|
||||||
MainClass.ScreenReader.Say(toSpeak, true);
|
|
||||||
|
|
||||||
if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
|
||||||
Game1.playSound("drop_item");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception e)
|
|
||||||
{
|
|
||||||
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int getPieceIndexForDonationItem(int itemIndex)
|
|
||||||
{
|
|
||||||
switch (itemIndex)
|
|
||||||
{
|
|
||||||
case 820:
|
|
||||||
return 5;
|
|
||||||
case 821:
|
|
||||||
return 4;
|
|
||||||
case 822:
|
|
||||||
return 3;
|
|
||||||
case 823:
|
|
||||||
return 0;
|
|
||||||
case 824:
|
|
||||||
return 1;
|
|
||||||
case 825:
|
|
||||||
return 8;
|
|
||||||
case 826:
|
|
||||||
return 7;
|
|
||||||
case 827:
|
|
||||||
return 9;
|
|
||||||
case 828:
|
|
||||||
return 10;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
using StardewValley;
|
||||||
|
using StardewValley.Menus;
|
||||||
|
|
||||||
|
namespace stardew_access.Patches
|
||||||
|
{
|
||||||
|
internal class FieldOfficeMenuPatch
|
||||||
|
{
|
||||||
|
private static string fieldOfficeMenuQuery = "";
|
||||||
|
|
||||||
|
internal static void DrawPatch(FieldOfficeMenu __instance)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
||||||
|
string toSpeak = " ";
|
||||||
|
|
||||||
|
if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
|
||||||
|
{
|
||||||
|
toSpeak = "Trashcan";
|
||||||
|
}
|
||||||
|
else if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
|
||||||
|
{
|
||||||
|
toSpeak = "ok button";
|
||||||
|
}
|
||||||
|
else if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
||||||
|
{
|
||||||
|
toSpeak = "drop item";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (InventoryUtils.narrateHoveredSlot(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < __instance.pieceHolders.Count; i++)
|
||||||
|
{
|
||||||
|
if (!__instance.pieceHolders[i].containsPoint(x, y))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (__instance.pieceHolders[i].item == null)
|
||||||
|
toSpeak = i switch
|
||||||
|
{
|
||||||
|
0 => "Center skeleton slot",
|
||||||
|
1 => "Center skeleton slot",
|
||||||
|
2 => "Center skeleton slot",
|
||||||
|
3 => "Center skeleton slot",
|
||||||
|
4 => "Center skeleton slot",
|
||||||
|
5 => "Center skeleton slot",
|
||||||
|
6 => "Snake slot",
|
||||||
|
7 => "Snake slot",
|
||||||
|
8 => "Snake slot",
|
||||||
|
9 => "Bat slot",
|
||||||
|
10 => "Frog slot",
|
||||||
|
_ => "Donation slot"
|
||||||
|
};
|
||||||
|
else
|
||||||
|
toSpeak = $"Slot {i + 1} finished: {__instance.pieceHolders[i].item.DisplayName}";
|
||||||
|
|
||||||
|
if (!MainClass.Config.DisableInventoryVerbosity && __instance.heldItem != null && __instance.pieceHolders[i].item == null)
|
||||||
|
{
|
||||||
|
int highlight = getPieceIndexForDonationItem(__instance.heldItem.ParentSheetIndex);
|
||||||
|
if (highlight != -1 && highlight == i)
|
||||||
|
toSpeak += "Donatable ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldOfficeMenuQuery != $"{toSpeak}:{i}")
|
||||||
|
{
|
||||||
|
fieldOfficeMenuQuery = $"{toSpeak}:{i}";
|
||||||
|
MainClass.ScreenReader.Say(toSpeak, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldOfficeMenuQuery != toSpeak)
|
||||||
|
{
|
||||||
|
fieldOfficeMenuQuery = toSpeak;
|
||||||
|
MainClass.ScreenReader.Say(toSpeak, true);
|
||||||
|
|
||||||
|
if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
||||||
|
Game1.playSound("drop_item");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int getPieceIndexForDonationItem(int itemIndex)
|
||||||
|
{
|
||||||
|
switch (itemIndex)
|
||||||
|
{
|
||||||
|
case 820:
|
||||||
|
return 5;
|
||||||
|
case 821:
|
||||||
|
return 4;
|
||||||
|
case 822:
|
||||||
|
return 3;
|
||||||
|
case 823:
|
||||||
|
return 0;
|
||||||
|
case 824:
|
||||||
|
return 1;
|
||||||
|
case 825:
|
||||||
|
return 8;
|
||||||
|
case 826:
|
||||||
|
return 7;
|
||||||
|
case 827:
|
||||||
|
return 9;
|
||||||
|
case 828:
|
||||||
|
return 10;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Cleanup()
|
||||||
|
{
|
||||||
|
fieldOfficeMenuQuery = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,245 @@
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using StardewValley;
|
||||||
|
using StardewValley.Locations;
|
||||||
|
using StardewValley.Menus;
|
||||||
|
|
||||||
|
namespace stardew_access.Patches
|
||||||
|
{
|
||||||
|
internal class MuseumMenuPatch
|
||||||
|
{
|
||||||
|
private static string museumQueryKey = "";
|
||||||
|
private static bool isMoving = false;
|
||||||
|
private static (int x, int y)[] donationTiles =
|
||||||
|
{
|
||||||
|
(26,5),(26,6),(26,7),(26,8),(26,9),(26,10),(26,11),
|
||||||
|
(29,5),(30,5),(31,5),(32,5),(33,5),(34,5),(35,5),(36,5),
|
||||||
|
(28,6),(29,6),(30,6),(31,6),(32,6),(33,6),(34,6),(35,6),(36,6),(37,6),
|
||||||
|
(28,9),(29,9),(30,9),(31,9),(32,9),(33,9),(34,9),(35,9),(36,9),
|
||||||
|
(28,10),(29,10),(30,10),(31,10),(32,10),(33,10),(34,10),(35,10),(36,10),
|
||||||
|
(30,13),(31,13),(32,13),(33,13),(34,13),
|
||||||
|
(30,14),(31,14),(32,14),(33,14),(34,14),
|
||||||
|
(28,15),(29,15),(30,15),(31,15),(32,15),(33,15),(34,15),(35,15),(36,15),
|
||||||
|
(28,16),(29,16),(30,16),(31,16),(32,16),(33,16),(34,16),(35,16),(36,16),
|
||||||
|
(39,6),(40,6),(41,6),(42,6),(43,6),(44,6),(45,6),(46,6),
|
||||||
|
(39,7),(40,7),(41,7),(42,7),(43,7),(44,7),(45,7),(46,7),
|
||||||
|
(48,5),(48,6),(48,7),
|
||||||
|
(42,15),(43,15),(44,15),(45,15),(46,15),(47,15),
|
||||||
|
(42,16),(43,16),(44,16),(45,16),(46,16),(47,16),
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static bool RecieveKeyPressPatch()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (isMoving)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isMoving)
|
||||||
|
{
|
||||||
|
isMoving = true;
|
||||||
|
Task.Delay(200).ContinueWith(_ => { isMoving = false; });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DrawPatch(MuseumMenu __instance, bool ___holdingMuseumPiece)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
|
||||||
|
|
||||||
|
narrateMuseumInventory(__instance, x, y);
|
||||||
|
|
||||||
|
narratePlayerInventory(__instance, x, y);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void narrateMuseumInventory(MuseumMenu __instance, int x, int y)
|
||||||
|
{
|
||||||
|
if (__instance.heldItem == null) return;
|
||||||
|
|
||||||
|
string toSpeak = "";
|
||||||
|
int tileX = (int)(Utility.ModifyCoordinateFromUIScale(x) + (float)Game1.viewport.X) / 64;
|
||||||
|
int tileY = (int)(Utility.ModifyCoordinateFromUIScale(y) + (float)Game1.viewport.Y) / 64;
|
||||||
|
LibraryMuseum libraryMuseum = (LibraryMuseum)Game1.currentLocation;
|
||||||
|
|
||||||
|
if (libraryMuseum.isTileSuitableForMuseumPiece(tileX, tileY))
|
||||||
|
toSpeak = $"slot {tileX}x {tileY}y";
|
||||||
|
|
||||||
|
if (museumQueryKey != toSpeak)
|
||||||
|
{
|
||||||
|
museumQueryKey = toSpeak;
|
||||||
|
MainClass.ScreenReader.Say(toSpeak, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void narratePlayerInventory(MuseumMenu __instance, int x, int y)
|
||||||
|
{
|
||||||
|
if (__instance.heldItem != null) return;
|
||||||
|
|
||||||
|
int hoveredItemIndex = InventoryUtils.narrateHoveredSlotAndReturnIndex(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y,
|
||||||
|
handleHighlightedItem: true, highlightedItemPrefix: "Donatable ");
|
||||||
|
if (hoveredItemIndex != -9999)
|
||||||
|
{
|
||||||
|
bool isPrimaryInfoKeyPressed = MainClass.Config.PrimaryInfoKey.JustPressed(); // For donating hovered item
|
||||||
|
|
||||||
|
if (isPrimaryInfoKeyPressed && hoveredItemIndex >= 0 && hoveredItemIndex < __instance.inventory.actualInventory.Count && __instance.inventory.actualInventory[hoveredItemIndex] != null)
|
||||||
|
{
|
||||||
|
manuallyDonateItem(__instance, hoveredItemIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string toSpeak = "";
|
||||||
|
bool isDropItemButton = false;
|
||||||
|
|
||||||
|
if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
|
||||||
|
{
|
||||||
|
toSpeak = "Ok button";
|
||||||
|
}
|
||||||
|
else if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
|
||||||
|
{
|
||||||
|
toSpeak = "Drop Item";
|
||||||
|
isDropItemButton = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (museumQueryKey != toSpeak)
|
||||||
|
{
|
||||||
|
museumQueryKey = toSpeak;
|
||||||
|
MainClass.ScreenReader.Say(toSpeak, true);
|
||||||
|
if (isDropItemButton) Game1.playSound("drop_item");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void manuallyDonateItem(MuseumMenu __instance, int i)
|
||||||
|
{
|
||||||
|
foreach (var tile in donationTiles)
|
||||||
|
{
|
||||||
|
#region Manually donates the hovered item (https://github.com/veywrn/StardewValley/blob/3ff171b6e9e6839555d7881a391b624ccd820a83/StardewValley/Menus/MuseumMenu.cs#L206-L247)
|
||||||
|
int tileX = tile.x;
|
||||||
|
int tileY = tile.y;
|
||||||
|
|
||||||
|
if (((LibraryMuseum)Game1.currentLocation).isTileSuitableForMuseumPiece(tileX, tileY) && ((LibraryMuseum)Game1.currentLocation).isItemSuitableForDonation(__instance.inventory.actualInventory[i]))
|
||||||
|
{
|
||||||
|
int objectID = __instance.inventory.actualInventory[i].ParentSheetIndex;
|
||||||
|
int rewardsCount = ((LibraryMuseum)Game1.currentLocation).getRewardsForPlayer(Game1.player).Count;
|
||||||
|
((LibraryMuseum)Game1.currentLocation).museumPieces.Add(new Vector2(tileX, tileY), ((StardewValley.Object)__instance.inventory.actualInventory[i]).ParentSheetIndex);
|
||||||
|
Game1.playSound("stoneStep");
|
||||||
|
if (((LibraryMuseum)Game1.currentLocation).getRewardsForPlayer(Game1.player).Count > rewardsCount)
|
||||||
|
{
|
||||||
|
Game1.playSound("reward");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Game1.playSound("newArtifact");
|
||||||
|
}
|
||||||
|
Game1.player.completeQuest(24);
|
||||||
|
__instance.inventory.actualInventory[i].Stack--;
|
||||||
|
if (__instance.inventory.actualInventory[i].Stack <= 0)
|
||||||
|
{
|
||||||
|
__instance.inventory.actualInventory[i] = null;
|
||||||
|
}
|
||||||
|
int pieces = ((LibraryMuseum)Game1.currentLocation).museumPieces.Count();
|
||||||
|
Game1.stats.checkForArchaeologyAchievements();
|
||||||
|
switch (pieces)
|
||||||
|
{
|
||||||
|
case 95:
|
||||||
|
globalChatInfoMessage("MuseumComplete", Game1.player.farmName.Value);
|
||||||
|
break;
|
||||||
|
case 40:
|
||||||
|
globalChatInfoMessage("Museum40", Game1.player.farmName.Value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
globalChatInfoMessage("donation", Game1.player.Name, "object:" + objectID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region These methods are taken from the game's source code, https://github.com/veywrn/StardewValley/blob/3ff171b6e9e6839555d7881a391b624ccd820a83/StardewValley/Multiplayer.cs#L1331-L1395
|
||||||
|
internal static void globalChatInfoMessage(string messageKey, params string[] args)
|
||||||
|
{
|
||||||
|
if (Game1.IsMultiplayer || Game1.multiplayerMode != 0)
|
||||||
|
{
|
||||||
|
receiveChatInfoMessage(Game1.player, messageKey, args);
|
||||||
|
sendChatInfoMessage(messageKey, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void sendChatInfoMessage(string messageKey, params string[] args)
|
||||||
|
{
|
||||||
|
if (Game1.IsClient)
|
||||||
|
{
|
||||||
|
Game1.client.sendMessage(15, messageKey, args);
|
||||||
|
}
|
||||||
|
else if (Game1.IsServer)
|
||||||
|
{
|
||||||
|
foreach (long id in Game1.otherFarmers.Keys)
|
||||||
|
{
|
||||||
|
Game1.server.sendMessage(id, 15, Game1.player, messageKey, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void receiveChatInfoMessage(Farmer sourceFarmer, string messageKey, string[] args)
|
||||||
|
{
|
||||||
|
if (Game1.chatBox != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] processedArgs = args.Select(delegate (string arg)
|
||||||
|
{
|
||||||
|
if (arg.StartsWith("achievement:"))
|
||||||
|
{
|
||||||
|
int key = Convert.ToInt32(arg.Substring("achievement:".Length));
|
||||||
|
return Game1.content.Load<Dictionary<int, string>>("Data\\Achievements")[key].Split('^')[0];
|
||||||
|
}
|
||||||
|
return arg.StartsWith("object:") ? new StardewValley.Object(Convert.ToInt32(arg.Substring("object:".Length)), 1).DisplayName : arg;
|
||||||
|
}).ToArray();
|
||||||
|
ChatBox chatBox = Game1.chatBox;
|
||||||
|
LocalizedContentManager content = Game1.content;
|
||||||
|
string path = "Strings\\UI:Chat_" + messageKey;
|
||||||
|
object[] substitutions = processedArgs;
|
||||||
|
chatBox.addInfoMessage(content.LoadString(path, substitutions));
|
||||||
|
}
|
||||||
|
catch (Microsoft.Xna.Framework.Content.ContentLoadException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
internal static void Cleanup()
|
||||||
|
{
|
||||||
|
museumQueryKey = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -263,13 +263,7 @@ namespace stardew_access.Patches
|
||||||
}
|
}
|
||||||
else if (menu is CarpenterMenu)
|
else if (menu is CarpenterMenu)
|
||||||
{
|
{
|
||||||
CarpenterMenuPatch.carpenterMenuQuery = "";
|
CarpenterMenuPatch.Cleanup();
|
||||||
CarpenterMenuPatch.isUpgrading = false;
|
|
||||||
CarpenterMenuPatch.isDemolishing = false;
|
|
||||||
CarpenterMenuPatch.isPainting = false;
|
|
||||||
CarpenterMenuPatch.isMoving = false;
|
|
||||||
CarpenterMenuPatch.isConstructing = false;
|
|
||||||
CarpenterMenuPatch.carpenterMenu = null;
|
|
||||||
}
|
}
|
||||||
else if (menu is PurchaseAnimalsMenu)
|
else if (menu is PurchaseAnimalsMenu)
|
||||||
{
|
{
|
||||||
|
@ -305,11 +299,11 @@ namespace stardew_access.Patches
|
||||||
}
|
}
|
||||||
else if (menu is FieldOfficeMenu)
|
else if (menu is FieldOfficeMenu)
|
||||||
{
|
{
|
||||||
DonationMenuPatches.fieldOfficeMenuQuery = " ";
|
FieldOfficeMenuPatch.Cleanup();
|
||||||
}
|
}
|
||||||
else if (menu is MuseumMenu)
|
else if (menu is MuseumMenu)
|
||||||
{
|
{
|
||||||
DonationMenuPatches.museumQueryKey = " ";
|
MuseumMenuPatch.Cleanup();
|
||||||
}
|
}
|
||||||
else if (menu is PondQueryMenu)
|
else if (menu is PondQueryMenu)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue