From 435118298444083b0ddbbc6d9a789ec3622421a5 Mon Sep 17 00:00:00 2001 From: Mohammad Shoaib Date: Fri, 15 Apr 2022 14:27:52 +0530 Subject: [PATCH] Organized code and added parrot perch to read tile --- .gitignore | 1 + stardew-access/API.cs | 4 +- stardew-access/Features/Radar.cs | 7 +- stardew-access/Features/ReadTile.cs | 838 +---------------- stardew-access/Features/TileInfo.cs | 876 ++++++++++++++++++ stardew-access/HarmonyPatches.cs | 24 +- stardew-access/Patches/DialoguePatches.cs | 3 +- ...mMenuPatches.cs => DonationMenuPatches.cs} | 137 ++- stardew-access/Patches/MenuPatches.cs | 132 +-- 9 files changed, 1039 insertions(+), 983 deletions(-) create mode 100644 stardew-access/Features/TileInfo.cs rename stardew-access/Patches/{MuseumMenuPatches.cs => DonationMenuPatches.cs} (71%) diff --git a/.gitignore b/.gitignore index 7bc055e..82c0f04 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore .vscode/* +.git-old/ # User-specific files *.rsuser diff --git a/stardew-access/API.cs b/stardew-access/API.cs index 902eed7..0362154 100644 --- a/stardew-access/API.cs +++ b/stardew-access/API.cs @@ -37,7 +37,7 @@ namespace stardew_access.ScreenReader /// Name of the object as the first item (Item1) and category as the second item (Item2). Returns null if no object found. public (string?, string?) GetNameWithCategoryNameAtTile(Vector2 tile) { - return ReadTile.getNameWithCategoryNameAtTile(tile); + return TileInfo.getNameWithCategoryNameAtTile(tile); } /// @@ -47,7 +47,7 @@ namespace stardew_access.ScreenReader /// Name of the object. Returns null if no object found. public string? GetNameAtTile(Vector2 tile) { - return ReadTile.getNameAtTile(tile); + return TileInfo.getNameAtTile(tile); } /// Speaks the text via the loaded screen reader (if any). diff --git a/stardew-access/Features/Radar.cs b/stardew-access/Features/Radar.cs index 62b4c27..c0b0eaa 100644 --- a/stardew-access/Features/Radar.cs +++ b/stardew-access/Features/Radar.cs @@ -1,7 +1,6 @@ using Microsoft.Xna.Framework; using StardewValley; using StardewValley.Objects; -using StardewValley.TerrainFeatures; namespace stardew_access.Features { @@ -187,7 +186,7 @@ namespace stardew_access.Features public (bool, string?, string) CheckTile(Vector2 position) { - (string? name, CATEGORY? category) tileDetail = ReadTile.getNameWithCategoryAtTile(position); + (string? name, CATEGORY? category) tileDetail = TileInfo.getNameWithCategoryAtTile(position); if (tileDetail.name == null) return (false, null, CATEGORY.Others.ToString()); @@ -204,7 +203,7 @@ namespace stardew_access.Features { if (Game1.currentLocation.isObjectAtTile((int)position.X, (int)position.Y)) { - (string? name, CATEGORY category) objDetails = ReadTile.getObjectAtTile((int)position.X, (int)position.Y); + (string? name, CATEGORY category) objDetails = TileInfo.getObjectAtTile((int)position.X, (int)position.Y); string? objectName = objDetails.name; CATEGORY category = objDetails.category; StardewValley.Object obj = Game1.currentLocation.getObjectAtTile((int)position.X, (int)position.Y); @@ -228,7 +227,7 @@ namespace stardew_access.Features } else { - (string? name, CATEGORY? category) tileDetail = ReadTile.getNameWithCategoryAtTile(position); + (string? name, CATEGORY? category) tileDetail = TileInfo.getNameWithCategoryAtTile(position); if (tileDetail.name != null) { if (tileDetail.category == null) diff --git a/stardew-access/Features/ReadTile.cs b/stardew-access/Features/ReadTile.cs index 33c5931..54dcb92 100644 --- a/stardew-access/Features/ReadTile.cs +++ b/stardew-access/Features/ReadTile.cs @@ -1,17 +1,9 @@ using Microsoft.Xna.Framework; using StardewModdingAPI; using StardewValley; -using StardewValley.Buildings; -using StardewValley.Locations; -using StardewValley.Objects; -using StardewValley.TerrainFeatures; namespace stardew_access.Features { - public enum MachineState - { - Ready, Busy, Waiting - } public class ReadTile { public static bool isReadingTile = false; @@ -51,9 +43,9 @@ namespace stardew_access.Features MainClass.ScreenReader.PrevTextTile = " "; } - bool isColliding = isCollidingAtTile(x, y); + bool isColliding = TileInfo.isCollidingAtTile(x, y); - string? toSpeak = getNameAtTile(tile); + string? toSpeak = TileInfo.getNameAtTile(tile); #region Narrate toSpeak if (toSpeak != null) @@ -81,831 +73,5 @@ namespace stardew_access.Features MainClass.ErrorLog($"Error in Read Tile:\n{e.Message}\n{e.StackTrace}"); } } - - ///Returns the name of the object at tile alongwith it's category's name - public static (string? name, string? categoryName) getNameWithCategoryNameAtTile(Vector2 tile) - { - (string? name, CATEGORY? category) tileDetail = getNameWithCategoryAtTile(tile); - - if (tileDetail.category == null) - tileDetail.category = CATEGORY.Others; - - return (tileDetail.name, tileDetail.category.ToString()); - } - - ///Returns the name of the object at tile - public static string? getNameAtTile(Vector2 tile) - { - return getNameWithCategoryAtTile(tile).name; - } - - ///Returns the name of the object at tile alongwith it's category - public static (string? name, CATEGORY? category) getNameWithCategoryAtTile(Vector2 tile) - { - int x = (int)tile.X; - int y = (int)tile.Y; - string? toReturn = ""; - CATEGORY? category = CATEGORY.Others; - - bool isColliding = isCollidingAtTile(x, y); - Dictionary> terrainFeature = Game1.currentLocation.terrainFeatures.FieldDict; - string? door = getDoorAtTile(x, y); - (CATEGORY? category, string? name) tileInfo = getTileInfo(x, y); - string? junimoBundle = getJunimoBundleAt(x, y); - string? resourceClump = getResourceClumpAtTile(x, y); - string? farmAnimal = getFarmAnimalAt(Game1.currentLocation, x, y); - - if (Game1.currentLocation.isCharacterAtTile(tile) != null) - { - NPC npc = Game1.currentLocation.isCharacterAtTile(tile); - toReturn = npc.displayName; - if (npc.isVillager() || npc.CanSocialize) - category = CATEGORY.Farmers; - else - category = CATEGORY.NPCs; - } - else if (farmAnimal != null) - { - toReturn = farmAnimal; - category = CATEGORY.FarmAnimals; - } - else if (Game1.currentLocation.isWaterTile(x, y) && isColliding) - { - toReturn = "Water"; - category = CATEGORY.WaterTiles; - } - else if (Game1.currentLocation.isObjectAtTile(x, y)) - { - (string? name, CATEGORY? category) obj = getObjectAtTile(x, y); - toReturn = obj.name; - category = obj.category; - } - else if (terrainFeature.ContainsKey(tile)) - { - (string? name, CATEGORY category) tf = getTerrainFeatureAtTile(terrainFeature[tile]); - string? terrain = tf.name; - if (terrain != null) - { - toReturn = terrain; - category = tf.category; - } - - } - else if (Game1.currentLocation.getLargeTerrainFeatureAt(x, y) != null) - { - toReturn = getBushAtTile(x, y); - category = CATEGORY.Bush; - } - else if (resourceClump != null) - { - toReturn = resourceClump; - category = CATEGORY.ResourceClumps; - } - else if (door != null) - { - toReturn = door; - category = CATEGORY.Doors; - } - else if (isMineDownLadderAtTile(x, y)) - { - toReturn = "Ladder"; - category = CATEGORY.Doors; - } - else if (isMineUpLadderAtTile(x, y)) - { - toReturn = "Up Ladder"; - category = CATEGORY.Doors; - } - else if (isElevatorAtTile(x, y)) - { - toReturn = "Elevator"; - category = CATEGORY.Doors; - } - else if (tileInfo.name != null) - { - toReturn = tileInfo.name; - category = tileInfo.category; - } - else if (junimoBundle != null) - { - toReturn = junimoBundle; - category = CATEGORY.JunimoBundle; - } - - if (toReturn == "") - return (null, category); - - return (toReturn, category); - } - - public static string? getBushAtTile(int x, int y) - { - string? toReturn = null; - Bush bush = (Bush)Game1.currentLocation.getLargeTerrainFeatureAt(x, y); - int size = bush.size.Value; - - #region Check if bush is harvestable or not - if (!bush.townBush.Value && (int)bush.tileSheetOffset.Value == 1 && bush.inBloom(Game1.GetSeasonForLocation(Game1.currentLocation), Game1.dayOfMonth)) - { - // Taken from the game's code - string season = ((int)bush.overrideSeason.Value == -1) ? Game1.GetSeasonForLocation(Game1.currentLocation) : Utility.getSeasonNameFromNumber(bush.overrideSeason.Value); - int shakeOff = -1; - if (!(season == "spring")) - { - if (season == "fall") - { - shakeOff = 410; - } - } - else - { - shakeOff = 296; - } - if ((int)size == 3) - { - shakeOff = 815; - } - if ((int)size == 4) - { - shakeOff = 73; - } - if (shakeOff == -1) - { - return null; - } - - toReturn = "Harvestable"; - } - #endregion - - if (bush.townBush.Value) - toReturn = $"{toReturn} Town Bush"; - else if (bush.greenhouseBush.Value) - toReturn = $"{toReturn} Greenhouse Bush"; - else - toReturn = $"{toReturn} Bush"; - - return toReturn; - } - - public static string? getJunimoBundleAt(int x, int y) - { - string? name = null; - if (Game1.currentLocation is CommunityCenter communityCenter) - { - name = (x, y) switch - { - (14, 5) => "Pantry", - (14, 23) => "Crafts Room", - (40, 10) => "Fish Tank", - (63, 14) => "Boiler Room", - (55, 6) => "Vault", - (46, 11) => "Bulletin Board", - _ => null, - }; - if (name != null && communityCenter.shouldNoteAppearInArea(CommunityCenter.getAreaNumberFromName(name))) - return $"{name} bundle"; - } - else if (Game1.currentLocation is AbandonedJojaMart) - { - name = (x, y) switch - { - (8, 8) => "Missing", - _ => null, - }; - - if (name != null) - return $"{name} bundle"; - } - - return null; - } - - public static bool isCollidingAtTile(int x, int y) - { - Rectangle rect = new Rectangle(x * 64 + 1, y * 64 + 1, 62, 62); - - if (Game1.currentLocation.isCollidingPosition(rect, Game1.viewport, true, 0, glider: false, Game1.player, pathfinding: true)) - { - return true; - } - - if (Game1.currentLocation is Woods && getStumpsInWoods(x, y) != null) - return true; - - return false; - } - - public static string? getFarmAnimalAt(GameLocation? location, int x, int y, bool onlyName = false) - { - if (location == null) - return null; - - if (location is not Farm && location is not AnimalHouse) - return null; - - List? farmAnimals = null; - - if (location is Farm) - farmAnimals = ((Farm)location).getAllFarmAnimals(); - else if (location is AnimalHouse) - farmAnimals = ((AnimalHouse)location).animals.Values.ToList(); - - if (farmAnimals == null || farmAnimals.Count <= 0) - return null; - - for (int i = 0; i < farmAnimals.Count; i++) - { - int fx = farmAnimals[i].getTileX(); - int fy = farmAnimals[i].getTileY(); - - if (fx.Equals(x) && fy.Equals(y)) - { - string name = farmAnimals[i].displayName; - int age = farmAnimals[i].age.Value; - string type = farmAnimals[i].displayType; - - if (onlyName) - return name; - - return $"{name}, {type}, age {age}"; - } - } - - return null; - } - - /// - /// - /// - /// - /// - /// category: This is the category of the tile. Default to Furnitures. - ///
name: This is the name of the tile. Default to null if the tile tile has nothing on it.
- public static (CATEGORY? category, string? name) getTileInfo(int x, int y) - { - - int? index = null; - - if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) - index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; - /* Add More - MainClass.monitor.Log(index.ToString(), LogLevel.Debug); - */ - - if (Game1.currentLocation is Farm) - { - Building building = ((Farm)Game1.currentLocation).getBuildingAt(new Vector2(x, y)); - if (building != null) - { - return (CATEGORY.Buildings, building.buildingType.Value); - } - } - - if (index != null) - { - switch (index) - { - case 1955: - case 41: - return (CATEGORY.Furnitures, "Mail Box"); - case 1003: - return (CATEGORY.Furnitures, "Street lamp"); - case 78: - return (CATEGORY.Furnitures, "Trash bin"); - case 617: - return (CATEGORY.Furnitures, "Daily quest"); - case 616: - return (CATEGORY.Furnitures, "Calender"); - } - - if (Game1.currentLocation is FarmHouse || Game1.currentLocation is IslandFarmHouse) - { - switch (index) - { - case 173: - return (CATEGORY.Furnitures, "Fridge"); - case 169: - case 170: - case 171: - case 172: - return (CATEGORY.Furnitures, "Kitchen"); - } - } - - } - - return (null, null); - } - - public static (string? name, CATEGORY category) getTerrainFeatureAtTile(Netcode.NetRef terrain) - { - string? toReturn = null; - CATEGORY category = CATEGORY.Others; - - if (terrain.Get() is HoeDirt) - { - category = CATEGORY.Crops; - HoeDirt dirt = (HoeDirt)terrain.Get(); - if (dirt.crop != null) - { - string cropName = Game1.objectInformation[dirt.crop.indexOfHarvest.Value].Split('/')[0]; - toReturn = $"{cropName}"; - - bool isWatered = dirt.state.Value == HoeDirt.watered; - bool isHarvestable = dirt.readyForHarvest(); - bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer; - - if (isWatered) - toReturn = "Watered " + toReturn; - - if (isFertilized) - toReturn = "Fertilized " + toReturn; - - if (isHarvestable) - toReturn = "Harvestable " + toReturn; - } - else - { - toReturn = "Soil"; - bool isWatered = dirt.state.Value == HoeDirt.watered; - bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer; - - if (isWatered) - toReturn = "Watered " + toReturn; - - if (isFertilized) - toReturn = "Fertilized " + toReturn; - } - } - else if (terrain.Get() is GiantCrop) - { - category = CATEGORY.Crops; - int whichCrop = ((GiantCrop)terrain.Get()).which.Value; - switch (whichCrop) - { - case 0: - toReturn = "Cauliflower"; - break; - case 1: - toReturn = "Melon"; - break; - case 2: - toReturn = "Pumpkin"; - break; - } - } - else if (terrain.Get() is CosmeticPlant) - { - category = CATEGORY.Furnitures; - CosmeticPlant cosmeticPlant = (CosmeticPlant)terrain.Get(); - toReturn = cosmeticPlant.textureName().ToLower(); - - if (toReturn.Contains("terrain")) - toReturn.Replace("terrain", ""); - - if (toReturn.Contains("feature")) - toReturn.Replace("feature", ""); - } - else if (terrain.Get() is Flooring && MainClass.Config.ReadFlooring) - { - category = CATEGORY.Flooring; - Flooring flooring = (Flooring)terrain.Get(); - bool isPathway = flooring.isPathway.Get(); - bool isSteppingStone = flooring.isSteppingStone.Get(); - - toReturn = "Flooring"; - - if (isPathway) - toReturn = "Pathway"; - - if (isSteppingStone) - toReturn = "Stepping Stone"; - } - else if (terrain.Get() is FruitTree) - { - category = CATEGORY.Trees; - toReturn = getFruitTree((FruitTree)terrain.Get()); - } - else if (terrain.Get() is Grass) - { - category = CATEGORY.Debris; - toReturn = "Grass"; - } - else if (terrain.Get() is Tree) - { - category = CATEGORY.Trees; - toReturn = getTree((Tree)terrain.Get()); - } - else if (terrain.Get() is Quartz) - { - category = CATEGORY.MineItems; - toReturn = "Quartz"; - } - - return (toReturn, category); - } - - public static string getFruitTree(FruitTree fruitTree) - { - int stage = fruitTree.growthStage.Value; - int fruitIndex = fruitTree.indexOfFruit.Get(); - - string toReturn = Game1.objectInformation[fruitIndex].Split('/')[0]; - - if (stage == 0) - toReturn = $"{toReturn} seed"; - else if (stage == 1) - toReturn = $"{toReturn} sprout"; - else if (stage == 2) - toReturn = $"{toReturn} sapling"; - else if (stage == 3) - toReturn = $"{toReturn} bush"; - else if (stage >= 4) - toReturn = $"{toReturn} tree"; - - if (fruitTree.fruitsOnTree.Value > 0) - toReturn = $"Harvestable {toReturn}"; - - return toReturn; - } - - public static string getTree(Tree tree) - { - int treeType = tree.treeType.Value; - int treeStage = tree.growthStage.Value; - string treeName = "tree"; - string seedName = ""; - - // Return with the name if it's one of the 3 special trees - switch (treeType) - { - case 4: - case 5: - return "Winter Tree"; - case 6: - return "Palm Tree"; - case 7: - return "Mushroom Tree"; - } - - - if (treeType <= 3) - seedName = Game1.objectInformation[308 + treeType].Split('/')[0]; - else if (treeType == 8) - seedName = Game1.objectInformation[292].Split('/')[0]; - - if (treeStage >= 1) - { - switch (seedName.ToLower()) - { - case "mahogany seed": - treeName = "Mahogany"; - break; - case "acorn": - treeName = "Oak"; - break; - case "maple seed": - treeName = "Maple"; - break; - case "pine cone": - treeName = "Pine"; - break; - default: - treeName = "Coconut"; - break; - } - - if (treeStage == 1) - treeName = $"{treeName} sprout"; - else if (treeStage == 2) - treeName = $"{treeName} sapling"; - else if (treeStage == 3 || treeStage == 4) - treeName = $"{treeName} bush"; - else if (treeStage >= 5) - treeName = $"{treeName} tree"; - - return treeName; - } - - return seedName; - } - - #region Objects - public static (string? name, CATEGORY category) getObjectAtTile(int x, int y) - { - (string? name, CATEGORY category) toReturn = (null, CATEGORY.Others); - - StardewValley.Object obj = Game1.currentLocation.getObjectAtTile(x, y); - int index = obj.ParentSheetIndex; - toReturn.name = obj.DisplayName; - - // Get object names based on index - (string? name, CATEGORY category) correctNameAndCategory = getCorrectNameAndCategoryFromIndex(index); - if (correctNameAndCategory.name != null) - toReturn = correctNameAndCategory; - - if (toReturn.name.ToLower().Equals("stone")) // Fix for `Busy stone` - toReturn.category = CATEGORY.Debris; - - if (obj is Chest) - { - Chest chest = (Chest)obj; - toReturn = (chest.DisplayName, CATEGORY.Chests); - } - - if (obj is Furniture) - toReturn.category = CATEGORY.Furnitures; - - if (toReturn.category == CATEGORY.Others) // Fix for `Harvestable table` and `Busy nodes` - { - MachineState machineState = GetMachineState(obj); - if (machineState == MachineState.Ready) - toReturn.name = $"Harvestable {toReturn.name}"; - else if (machineState == MachineState.Busy) - toReturn.name = $"Busy {toReturn.name}"; - } - return toReturn; - } - - private static MachineState GetMachineState(StardewValley.Object machine) - { - if (machine is CrabPot crabPot) - if (crabPot.bait.Value is not null && crabPot.heldObject.Value is null) - return MachineState.Busy; - return GetMachineState(machine.readyForHarvest.Value, machine.MinutesUntilReady, machine.heldObject.Value); - } - - private static MachineState GetMachineState(bool readyForHarvest, int minutesUntilReady, StardewValley.Object? heldObject) - { - if (readyForHarvest || (heldObject is not null && minutesUntilReady <= 0)) - return MachineState.Ready; - else if (minutesUntilReady > 0) - return MachineState.Busy; - else - return MachineState.Waiting; - } - - private static (string? name, CATEGORY category) getCorrectNameAndCategoryFromIndex(int index) - { - switch (index) - { - case 313: - case 314: - case 315: - case 316: - case 317: - case 318: - case 452: - case 674: - case 675: - case 676: - case 677: - case 678: - case 679: - case 750: - case 784: - case 785: - case 786: - return ("Weed", CATEGORY.Debris); - case 792: - case 793: - case 794: - return ("Fertile weed", CATEGORY.Debris); - case 319: - case 320: - case 321: - return ("Ice crystal", CATEGORY.Debris); - case 75: - return ("Geode", CATEGORY.MineItems); - case 32: - case 34: - case 36: - case 38: - case 40: - case 42: - case 48: - case 50: - case 52: - case 54: - case 56: - case 58: - return ("Coloured stone", CATEGORY.Debris); - case 668: - case 670: - case 845: - case 846: - case 847: - return ("Mine stone", CATEGORY.MineItems); - case 818: - return ("Clay stone", CATEGORY.Debris); - case 816: - case 817: - return ("Fossil stone", CATEGORY.Debris); - case 118: - case 120: - case 122: - case 124: - return ("Barrel", CATEGORY.MineItems); - case 119: - case 121: - case 123: - case 125: - return ("Item box", CATEGORY.MineItems); - } - - if (Game1.currentLocation is Mine or MineShaft) - { - switch (index) - { - case 76: - return ("Frozen geode", CATEGORY.MineItems); - case 77: - return ("Magma geode", CATEGORY.MineItems); - case 8: - case 66: - return ("Amethyst node", CATEGORY.MineItems); - case 14: - case 62: - return ("Aquamarine node", CATEGORY.MineItems); - case 843: - case 844: - return ("Cinder shard node", CATEGORY.MineItems); - case 2: - case 72: - return ("Diamond node", CATEGORY.MineItems); - case 12: - case 60: - return ("Emerald node", CATEGORY.MineItems); - case 44: - return ("Gem node", CATEGORY.MineItems); - case 6: - case 70: - return ("Jade node", CATEGORY.MineItems); - case 46: - return ("Mystic stone", CATEGORY.MineItems); - case 74: - return ("Prismatic node", CATEGORY.MineItems); - case 4: - case 64: - return ("Ruby node", CATEGORY.MineItems); - case 10: - case 68: - return ("Topaz node", CATEGORY.MineItems); - case 819: - return ("Omni geode node", CATEGORY.MineItems); - case 751: - case 849: - return ("Copper node", CATEGORY.MineItems); - case 764: - return ("Gold node", CATEGORY.MineItems); - case 765: - return ("Iridium node", CATEGORY.MineItems); - case 290: - case 850: - return ("Iron node", CATEGORY.MineItems); - } - } - - return (null, CATEGORY.Others); - } - #endregion - - public static bool isMineDownLadderAtTile(int x, int y) - { - try - { - if (Game1.currentLocation is Mine or MineShaft) - { - int? index = null; - - if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) - index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; - - if (index == 173 || index == 174) - return true; - } - } - catch (Exception) { } - - return false; - } - - public static bool isMineUpLadderAtTile(int x, int y) - { - try - { - if (Game1.currentLocation is Mine or MineShaft) - { - int? index = null; - - if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) - index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; - - if (index == 115) - return true; - } - } - catch (Exception) { } - - return false; - } - - public static bool isElevatorAtTile(int x, int y) - { - try - { - if (Game1.currentLocation is Mine or MineShaft) - { - int? index = null; - - if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) - index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; - - if (index == 112) - return true; - } - } - catch (Exception) { } - - return false; - } - - public static string? getDoorAtTile(int x, int y) - { - Point tilePoint = new Point(x, y); - StardewValley.Network.NetPointDictionary doorList = Game1.currentLocation.doors; - - for (int i = 0; i < doorList.Count(); i++) - { - if (doorList.ContainsKey(tilePoint)) - { - string? doorName; - doorList.TryGetValue(tilePoint, out doorName); - - if (doorName != null) - return $"{doorName} door"; - else - return "door"; - } - } - - return null; - } - - public static string? getResourceClumpAtTile(int x, int y) - { - if (Game1.currentLocation is Woods) - return getStumpsInWoods(x, y); - - for (int i = 0; i < Game1.currentLocation.resourceClumps.Count; i++) - { - if (Game1.currentLocation.resourceClumps[i].occupiesTile(x, y)) - { - int index = Game1.currentLocation.resourceClumps[i].parentSheetIndex.Value; - - switch (index) - { - case 600: - return "Large Stump"; - case 602: - return "Hollow Log"; - case 622: - return "Meteorite"; - case 752: - case 754: - case 756: - case 758: - return "Mine Rock"; - case 672: - return "Boulder"; - default: - return "Unknown"; - } - } - } - - return null; - } - - public static string? getStumpsInWoods(int x, int y) - { - if (Game1.currentLocation is not Woods) - return null; - - if ((x == 8 || x == 9) && y == 7) - { - return "Old Master Cannoli"; - } - Netcode.NetObjectList stumps = ((Woods)Game1.currentLocation).stumps; - for (int i = 0; i < stumps.Count; i++) - { - if (stumps[i].occupiesTile(x, y)) - { - return "Large Stump"; - } - } - return null; - } } } diff --git a/stardew-access/Features/TileInfo.cs b/stardew-access/Features/TileInfo.cs new file mode 100644 index 0000000..1fb346f --- /dev/null +++ b/stardew-access/Features/TileInfo.cs @@ -0,0 +1,876 @@ +using Microsoft.Xna.Framework; +using StardewValley; +using StardewValley.Buildings; +using StardewValley.Locations; +using StardewValley.Objects; +using StardewValley.TerrainFeatures; + +namespace stardew_access.Features +{ + public enum MachineState + { + Ready, Busy, Waiting + } + + public class TileInfo + { + ///Returns the name of the object at tile alongwith it's category's name + public static (string? name, string? categoryName) getNameWithCategoryNameAtTile(Vector2 tile) + { + (string? name, CATEGORY? category) tileDetail = getNameWithCategoryAtTile(tile); + + if (tileDetail.category == null) + tileDetail.category = CATEGORY.Others; + + return (tileDetail.name, tileDetail.category.ToString()); + } + + ///Returns the name of the object at tile + public static string? getNameAtTile(Vector2 tile) + { + return getNameWithCategoryAtTile(tile).name; + } + + ///Returns the name of the object at tile alongwith it's category + public static (string? name, CATEGORY? category) getNameWithCategoryAtTile(Vector2 tile) + { + int x = (int)tile.X; + int y = (int)tile.Y; + string? toReturn = ""; + CATEGORY? category = CATEGORY.Others; + + bool isColliding = isCollidingAtTile(x, y); + Dictionary> terrainFeature = Game1.currentLocation.terrainFeatures.FieldDict; + string? door = getDoorAtTile(x, y); + (CATEGORY? category, string? name) tileInfo = getTileInfo(x, y); + string? junimoBundle = getJunimoBundleAt(x, y); + string? resourceClump = getResourceClumpAtTile(x, y); + string? farmAnimal = getFarmAnimalAt(Game1.currentLocation, x, y); + string? parrot = getParrotPerchAtTile(x, y); + + if (Game1.currentLocation.isCharacterAtTile(tile) != null) + { + NPC npc = Game1.currentLocation.isCharacterAtTile(tile); + toReturn = npc.displayName; + if (npc.isVillager() || npc.CanSocialize) + category = CATEGORY.Farmers; + else + category = CATEGORY.NPCs; + } + else if (farmAnimal != null) + { + toReturn = farmAnimal; + category = CATEGORY.FarmAnimals; + } + else if (Game1.currentLocation.isWaterTile(x, y) && isColliding) + { + toReturn = "Water"; + category = CATEGORY.WaterTiles; + } + else if (Game1.currentLocation.isObjectAtTile(x, y)) + { + (string? name, CATEGORY? category) obj = getObjectAtTile(x, y); + toReturn = obj.name; + category = obj.category; + } + else if (terrainFeature.ContainsKey(tile)) + { + (string? name, CATEGORY category) tf = getTerrainFeatureAtTile(terrainFeature[tile]); + string? terrain = tf.name; + if (terrain != null) + { + toReturn = terrain; + category = tf.category; + } + + } + else if (Game1.currentLocation.getLargeTerrainFeatureAt(x, y) != null) + { + toReturn = getBushAtTile(x, y); + category = CATEGORY.Bush; + } + else if (resourceClump != null) + { + toReturn = resourceClump; + category = CATEGORY.ResourceClumps; + } + else if (door != null) + { + toReturn = door; + category = CATEGORY.Doors; + } + else if (isMineDownLadderAtTile(x, y)) + { + toReturn = "Ladder"; + category = CATEGORY.Doors; + } + else if (isMineUpLadderAtTile(x, y)) + { + toReturn = "Up Ladder"; + category = CATEGORY.Doors; + } + else if (isElevatorAtTile(x, y)) + { + toReturn = "Elevator"; + category = CATEGORY.Doors; + } + else if (parrot != null) + { + toReturn = parrot; + category = CATEGORY.Buildings; + } + else if (tileInfo.name != null) + { + toReturn = tileInfo.name; + category = tileInfo.category; + } + else if (junimoBundle != null) + { + toReturn = junimoBundle; + category = CATEGORY.JunimoBundle; + } + + if (toReturn == "") + return (null, category); + + return (toReturn, category); + } + + public static string? getBushAtTile(int x, int y) + { + string? toReturn = null; + Bush bush = (Bush)Game1.currentLocation.getLargeTerrainFeatureAt(x, y); + int size = bush.size.Value; + + #region Check if bush is harvestable or not + if (!bush.townBush.Value && (int)bush.tileSheetOffset.Value == 1 && bush.inBloom(Game1.GetSeasonForLocation(Game1.currentLocation), Game1.dayOfMonth)) + { + // Taken from the game's code + string season = ((int)bush.overrideSeason.Value == -1) ? Game1.GetSeasonForLocation(Game1.currentLocation) : Utility.getSeasonNameFromNumber(bush.overrideSeason.Value); + int shakeOff = -1; + if (!(season == "spring")) + { + if (season == "fall") + { + shakeOff = 410; + } + } + else + { + shakeOff = 296; + } + if ((int)size == 3) + { + shakeOff = 815; + } + if ((int)size == 4) + { + shakeOff = 73; + } + if (shakeOff == -1) + { + return null; + } + + toReturn = "Harvestable"; + } + #endregion + + if (bush.townBush.Value) + toReturn = $"{toReturn} Town Bush"; + else if (bush.greenhouseBush.Value) + toReturn = $"{toReturn} Greenhouse Bush"; + else + toReturn = $"{toReturn} Bush"; + + return toReturn; + } + + public static string? getJunimoBundleAt(int x, int y) + { + string? name = null; + if (Game1.currentLocation is CommunityCenter communityCenter) + { + name = (x, y) switch + { + (14, 5) => "Pantry", + (14, 23) => "Crafts Room", + (40, 10) => "Fish Tank", + (63, 14) => "Boiler Room", + (55, 6) => "Vault", + (46, 11) => "Bulletin Board", + _ => null, + }; + if (name != null && communityCenter.shouldNoteAppearInArea(CommunityCenter.getAreaNumberFromName(name))) + return $"{name} bundle"; + } + else if (Game1.currentLocation is AbandonedJojaMart) + { + name = (x, y) switch + { + (8, 8) => "Missing", + _ => null, + }; + + if (name != null) + return $"{name} bundle"; + } + + return null; + } + + public static bool isCollidingAtTile(int x, int y) + { + Rectangle rect = new Rectangle(x * 64 + 1, y * 64 + 1, 62, 62); + + if (Game1.currentLocation.isCollidingPosition(rect, Game1.viewport, true, 0, glider: false, Game1.player, pathfinding: true)) + { + return true; + } + + if (Game1.currentLocation is Woods && getStumpsInWoods(x, y) != null) + return true; + + return false; + } + + public static string? getFarmAnimalAt(GameLocation? location, int x, int y, bool onlyName = false) + { + if (location == null) + return null; + + if (location is not Farm && location is not AnimalHouse) + return null; + + List? farmAnimals = null; + + if (location is Farm) + farmAnimals = ((Farm)location).getAllFarmAnimals(); + else if (location is AnimalHouse) + farmAnimals = ((AnimalHouse)location).animals.Values.ToList(); + + if (farmAnimals == null || farmAnimals.Count <= 0) + return null; + + for (int i = 0; i < farmAnimals.Count; i++) + { + int fx = farmAnimals[i].getTileX(); + int fy = farmAnimals[i].getTileY(); + + if (fx.Equals(x) && fy.Equals(y)) + { + string name = farmAnimals[i].displayName; + int age = farmAnimals[i].age.Value; + string type = farmAnimals[i].displayType; + + if (onlyName) + return name; + + return $"{name}, {type}, age {age}"; + } + } + + return null; + } + + /// + /// + /// + /// + /// + /// category: This is the category of the tile. Default to Furnitures. + ///
name: This is the name of the tile. Default to null if the tile tile has nothing on it.
+ public static (CATEGORY? category, string? name) getTileInfo(int x, int y) + { + + int? index = null; + + if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) + index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; + /* Add More + MainClass.monitor.Log(index.ToString(), LogLevel.Debug); + */ + + if (Game1.currentLocation is Farm) + { + Building building = ((Farm)Game1.currentLocation).getBuildingAt(new Vector2(x, y)); + if (building != null) + { + return (CATEGORY.Buildings, building.buildingType.Value); + } + } + + if (index != null) + { + switch (index) + { + case 1955: + case 41: + return (CATEGORY.Furnitures, "Mail Box"); + case 1003: + return (CATEGORY.Furnitures, "Street lamp"); + case 78: + return (CATEGORY.Furnitures, "Trash bin"); + case 617: + return (CATEGORY.Furnitures, "Daily quest"); + case 616: + return (CATEGORY.Furnitures, "Calender"); + } + + if (Game1.currentLocation is FarmHouse || Game1.currentLocation is IslandFarmHouse) + { + switch (index) + { + case 173: + return (CATEGORY.Furnitures, "Fridge"); + case 169: + case 170: + case 171: + case 172: + return (CATEGORY.Furnitures, "Kitchen"); + } + } + + } + + return (null, null); + } + + public static (string? name, CATEGORY category) getTerrainFeatureAtTile(Netcode.NetRef terrain) + { + string? toReturn = null; + CATEGORY category = CATEGORY.Others; + + if (terrain.Get() is HoeDirt) + { + category = CATEGORY.Crops; + HoeDirt dirt = (HoeDirt)terrain.Get(); + if (dirt.crop != null) + { + string cropName = Game1.objectInformation[dirt.crop.indexOfHarvest.Value].Split('/')[0]; + toReturn = $"{cropName}"; + + bool isWatered = dirt.state.Value == HoeDirt.watered; + bool isHarvestable = dirt.readyForHarvest(); + bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer; + + if (isWatered) + toReturn = "Watered " + toReturn; + + if (isFertilized) + toReturn = "Fertilized " + toReturn; + + if (isHarvestable) + toReturn = "Harvestable " + toReturn; + } + else + { + toReturn = "Soil"; + bool isWatered = dirt.state.Value == HoeDirt.watered; + bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer; + + if (isWatered) + toReturn = "Watered " + toReturn; + + if (isFertilized) + toReturn = "Fertilized " + toReturn; + } + } + else if (terrain.Get() is GiantCrop) + { + category = CATEGORY.Crops; + int whichCrop = ((GiantCrop)terrain.Get()).which.Value; + switch (whichCrop) + { + case 0: + toReturn = "Cauliflower"; + break; + case 1: + toReturn = "Melon"; + break; + case 2: + toReturn = "Pumpkin"; + break; + } + } + else if (terrain.Get() is CosmeticPlant) + { + category = CATEGORY.Furnitures; + CosmeticPlant cosmeticPlant = (CosmeticPlant)terrain.Get(); + toReturn = cosmeticPlant.textureName().ToLower(); + + if (toReturn.Contains("terrain")) + toReturn.Replace("terrain", ""); + + if (toReturn.Contains("feature")) + toReturn.Replace("feature", ""); + } + else if (terrain.Get() is Flooring && MainClass.Config.ReadFlooring) + { + category = CATEGORY.Flooring; + Flooring flooring = (Flooring)terrain.Get(); + bool isPathway = flooring.isPathway.Get(); + bool isSteppingStone = flooring.isSteppingStone.Get(); + + toReturn = "Flooring"; + + if (isPathway) + toReturn = "Pathway"; + + if (isSteppingStone) + toReturn = "Stepping Stone"; + } + else if (terrain.Get() is FruitTree) + { + category = CATEGORY.Trees; + toReturn = getFruitTree((FruitTree)terrain.Get()); + } + else if (terrain.Get() is Grass) + { + category = CATEGORY.Debris; + toReturn = "Grass"; + } + else if (terrain.Get() is Tree) + { + category = CATEGORY.Trees; + toReturn = getTree((Tree)terrain.Get()); + } + else if (terrain.Get() is Quartz) + { + category = CATEGORY.MineItems; + toReturn = "Quartz"; + } + + return (toReturn, category); + } + + public static string getFruitTree(FruitTree fruitTree) + { + int stage = fruitTree.growthStage.Value; + int fruitIndex = fruitTree.indexOfFruit.Get(); + + string toReturn = Game1.objectInformation[fruitIndex].Split('/')[0]; + + if (stage == 0) + toReturn = $"{toReturn} seed"; + else if (stage == 1) + toReturn = $"{toReturn} sprout"; + else if (stage == 2) + toReturn = $"{toReturn} sapling"; + else if (stage == 3) + toReturn = $"{toReturn} bush"; + else if (stage >= 4) + toReturn = $"{toReturn} tree"; + + if (fruitTree.fruitsOnTree.Value > 0) + toReturn = $"Harvestable {toReturn}"; + + return toReturn; + } + + public static string getTree(Tree tree) + { + int treeType = tree.treeType.Value; + int treeStage = tree.growthStage.Value; + string treeName = "tree"; + string seedName = ""; + + // Return with the name if it's one of the 3 special trees + switch (treeType) + { + case 4: + case 5: + return "Winter Tree"; + case 6: + return "Palm Tree"; + case 7: + return "Mushroom Tree"; + } + + + if (treeType <= 3) + seedName = Game1.objectInformation[308 + treeType].Split('/')[0]; + else if (treeType == 8) + seedName = Game1.objectInformation[292].Split('/')[0]; + + if (treeStage >= 1) + { + switch (seedName.ToLower()) + { + case "mahogany seed": + treeName = "Mahogany"; + break; + case "acorn": + treeName = "Oak"; + break; + case "maple seed": + treeName = "Maple"; + break; + case "pine cone": + treeName = "Pine"; + break; + default: + treeName = "Coconut"; + break; + } + + if (treeStage == 1) + treeName = $"{treeName} sprout"; + else if (treeStage == 2) + treeName = $"{treeName} sapling"; + else if (treeStage == 3 || treeStage == 4) + treeName = $"{treeName} bush"; + else if (treeStage >= 5) + treeName = $"{treeName} tree"; + + return treeName; + } + + return seedName; + } + + #region Objects + public static (string? name, CATEGORY category) getObjectAtTile(int x, int y) + { + (string? name, CATEGORY category) toReturn = (null, CATEGORY.Others); + + StardewValley.Object obj = Game1.currentLocation.getObjectAtTile(x, y); + int index = obj.ParentSheetIndex; + toReturn.name = obj.DisplayName; + + // Get object names based on index + (string? name, CATEGORY category) correctNameAndCategory = getCorrectNameAndCategoryFromIndex(index); + if (correctNameAndCategory.name != null) + toReturn = correctNameAndCategory; + + if (toReturn.name.ToLower().Equals("stone")) // Fix for `Busy stone` + toReturn.category = CATEGORY.Debris; + + if (obj is Chest) + { + Chest chest = (Chest)obj; + toReturn = (chest.DisplayName, CATEGORY.Chests); + } + + if (obj is Furniture) + toReturn.category = CATEGORY.Furnitures; + + if (toReturn.category == CATEGORY.Others) // Fix for `Harvestable table` and `Busy nodes` + { + MachineState machineState = GetMachineState(obj); + if (machineState == MachineState.Ready) + toReturn.name = $"Harvestable {toReturn.name}"; + else if (machineState == MachineState.Busy) + toReturn.name = $"Busy {toReturn.name}"; + } + return toReturn; + } + + private static MachineState GetMachineState(StardewValley.Object machine) + { + if (machine is CrabPot crabPot) + if (crabPot.bait.Value is not null && crabPot.heldObject.Value is null) + return MachineState.Busy; + return GetMachineState(machine.readyForHarvest.Value, machine.MinutesUntilReady, machine.heldObject.Value); + } + + private static MachineState GetMachineState(bool readyForHarvest, int minutesUntilReady, StardewValley.Object? heldObject) + { + if (readyForHarvest || (heldObject is not null && minutesUntilReady <= 0)) + return MachineState.Ready; + else if (minutesUntilReady > 0) + return MachineState.Busy; + else + return MachineState.Waiting; + } + + private static (string? name, CATEGORY category) getCorrectNameAndCategoryFromIndex(int index) + { + switch (index) + { + case 313: + case 314: + case 315: + case 316: + case 317: + case 318: + case 452: + case 674: + case 675: + case 676: + case 677: + case 678: + case 679: + case 750: + case 784: + case 785: + case 786: + return ("Weed", CATEGORY.Debris); + case 792: + case 793: + case 794: + return ("Fertile weed", CATEGORY.Debris); + case 319: + case 320: + case 321: + return ("Ice crystal", CATEGORY.Debris); + case 75: + return ("Geode", CATEGORY.MineItems); + case 32: + case 34: + case 36: + case 38: + case 40: + case 42: + case 48: + case 50: + case 52: + case 54: + case 56: + case 58: + return ("Coloured stone", CATEGORY.Debris); + case 668: + case 670: + case 845: + case 846: + case 847: + return ("Mine stone", CATEGORY.MineItems); + case 818: + return ("Clay stone", CATEGORY.Debris); + case 816: + case 817: + return ("Fossil stone", CATEGORY.Debris); + case 118: + case 120: + case 122: + case 124: + return ("Barrel", CATEGORY.MineItems); + case 119: + case 121: + case 123: + case 125: + return ("Item box", CATEGORY.MineItems); + } + + if (Game1.currentLocation is Mine or MineShaft) + { + switch (index) + { + case 76: + return ("Frozen geode", CATEGORY.MineItems); + case 77: + return ("Magma geode", CATEGORY.MineItems); + case 8: + case 66: + return ("Amethyst node", CATEGORY.MineItems); + case 14: + case 62: + return ("Aquamarine node", CATEGORY.MineItems); + case 843: + case 844: + return ("Cinder shard node", CATEGORY.MineItems); + case 2: + case 72: + return ("Diamond node", CATEGORY.MineItems); + case 12: + case 60: + return ("Emerald node", CATEGORY.MineItems); + case 44: + return ("Gem node", CATEGORY.MineItems); + case 6: + case 70: + return ("Jade node", CATEGORY.MineItems); + case 46: + return ("Mystic stone", CATEGORY.MineItems); + case 74: + return ("Prismatic node", CATEGORY.MineItems); + case 4: + case 64: + return ("Ruby node", CATEGORY.MineItems); + case 10: + case 68: + return ("Topaz node", CATEGORY.MineItems); + case 819: + return ("Omni geode node", CATEGORY.MineItems); + case 751: + case 849: + return ("Copper node", CATEGORY.MineItems); + case 764: + return ("Gold node", CATEGORY.MineItems); + case 765: + return ("Iridium node", CATEGORY.MineItems); + case 290: + case 850: + return ("Iron node", CATEGORY.MineItems); + } + } + + return (null, CATEGORY.Others); + } + #endregion + + public static bool isMineDownLadderAtTile(int x, int y) + { + try + { + if (Game1.currentLocation is Mine or MineShaft) + { + int? index = null; + + if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) + index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; + + if (index == 173 || index == 174) + return true; + } + } + catch (Exception) { } + + return false; + } + + public static bool isMineUpLadderAtTile(int x, int y) + { + try + { + if (Game1.currentLocation is Mine or MineShaft) + { + int? index = null; + + if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) + index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; + + if (index == 115) + return true; + } + } + catch (Exception) { } + + return false; + } + + public static bool isElevatorAtTile(int x, int y) + { + try + { + if (Game1.currentLocation is Mine or MineShaft) + { + int? index = null; + + if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null) + index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex; + + if (index == 112) + return true; + } + } + catch (Exception) { } + + return false; + } + + public static string? getDoorAtTile(int x, int y) + { + Point tilePoint = new Point(x, y); + StardewValley.Network.NetPointDictionary doorList = Game1.currentLocation.doors; + + for (int i = 0; i < doorList.Count(); i++) + { + if (doorList.ContainsKey(tilePoint)) + { + string? doorName; + doorList.TryGetValue(tilePoint, out doorName); + + if (doorName != null) + return $"{doorName} door"; + else + return "door"; + } + } + + return null; + } + + public static string? getResourceClumpAtTile(int x, int y) + { + if (Game1.currentLocation is Woods) + return getStumpsInWoods(x, y); + + for (int i = 0; i < Game1.currentLocation.resourceClumps.Count; i++) + { + if (Game1.currentLocation.resourceClumps[i].occupiesTile(x, y)) + { + int index = Game1.currentLocation.resourceClumps[i].parentSheetIndex.Value; + + switch (index) + { + case 600: + return "Large Stump"; + case 602: + return "Hollow Log"; + case 622: + return "Meteorite"; + case 752: + case 754: + case 756: + case 758: + return "Mine Rock"; + case 672: + return "Boulder"; + default: + return "Unknown"; + } + } + } + + return null; + } + + public static string? getStumpsInWoods(int x, int y) + { + if (Game1.currentLocation is not Woods) + return null; + + if ((x == 8 || x == 9) && y == 7) + { + return "Old Master Cannoli"; + } + Netcode.NetObjectList stumps = ((Woods)Game1.currentLocation).stumps; + for (int i = 0; i < stumps.Count; i++) + { + if (stumps[i].occupiesTile(x, y)) + { + return "Large Stump"; + } + } + return null; + } + + public static string? getParrotPerchAtTile(int x, int y) + { + if (Game1.currentLocation is not IslandLocation islandLocation) + return null; + + foreach (var perch in islandLocation.parrotUpgradePerches) + { + if (!perch.tilePosition.Value.Equals(new Point(x, y))) + continue; + + string toSpeak = $"Parrot required nuts {perch.requiredNuts.Value}"; + + if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Complete) + return $"Request Completed"; + else if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Idle) + return toSpeak; + else if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.StartBuilding) + return "Parrots started building request"; + else if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Building) + return "Parrots building request"; + else + return toSpeak; + } + + return null; + } + } +} \ No newline at end of file diff --git a/stardew-access/HarmonyPatches.cs b/stardew-access/HarmonyPatches.cs index 96e0da4..ae60975 100644 --- a/stardew-access/HarmonyPatches.cs +++ b/stardew-access/HarmonyPatches.cs @@ -158,12 +158,7 @@ namespace stardew_access harmony.Patch( original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }), - prefix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuKeyPressPatch)) - ); - - harmony.Patch( - original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuPatch)) + prefix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuKeyPressPatch)) ); harmony.Patch( @@ -195,11 +190,6 @@ namespace stardew_access original: AccessTools.Method(typeof(ItemListMenu), nameof(ItemListMenu.draw), new Type[] { typeof(SpriteBatch) }), postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.ItemListMenuPatch)) ); - - harmony.Patch( - original: AccessTools.Method(typeof(FieldOfficeMenu), nameof(FieldOfficeMenu.draw), new Type[] { typeof(SpriteBatch) }), - postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.FieldOfficeMenuPatch)) - ); #endregion #region Quest Patches @@ -251,6 +241,18 @@ namespace stardew_access #endregion + #region Donation Menus + harmony.Patch( + original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }), + postfix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuPatch)) + ); + + harmony.Patch( + original: AccessTools.Method(typeof(FieldOfficeMenu), nameof(FieldOfficeMenu.draw), new Type[] { typeof(SpriteBatch) }), + postfix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.FieldOfficeMenuPatch)) + ); + #endregion + harmony.Patch( original: AccessTools.Method(typeof(Game1), nameof(Game1.playSound)), prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.PlaySoundPatch)) diff --git a/stardew-access/Patches/DialoguePatches.cs b/stardew-access/Patches/DialoguePatches.cs index 1228cb8..b59bbef 100644 --- a/stardew-access/Patches/DialoguePatches.cs +++ b/stardew-access/Patches/DialoguePatches.cs @@ -2,7 +2,6 @@ using StardewModdingAPI; using StardewValley; using StardewValley.Menus; -using System.Text; namespace stardew_access.Patches { @@ -197,6 +196,8 @@ namespace stardew_access.Patches return; else if (Game1.activeClickableMenu is FieldOfficeMenu) return; + else if (Game1.activeClickableMenu is MuseumMenu) + return; #endregion string toSpeak = " "; diff --git a/stardew-access/Patches/MuseumMenuPatches.cs b/stardew-access/Patches/DonationMenuPatches.cs similarity index 71% rename from stardew-access/Patches/MuseumMenuPatches.cs rename to stardew-access/Patches/DonationMenuPatches.cs index 6a06c65..ce244ac 100644 --- a/stardew-access/Patches/MuseumMenuPatches.cs +++ b/stardew-access/Patches/DonationMenuPatches.cs @@ -1,15 +1,15 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; -using StardewModdingAPI; using StardewValley; using StardewValley.Locations; using StardewValley.Menus; namespace stardew_access.Patches { - internal class MuseumMenuPatches + internal class DonationMenuPatches { - private static string museumQueryKey = " "; + internal static string museumQueryKey = " "; + internal static string fieldOfficeMenuQuery = " "; private static bool isMoving = false; private static (int x, int y)[] donationTiles = { @@ -29,6 +29,8 @@ namespace stardew_access.Patches (42,16),(43,16),(44,16),(45,16),(46,16),(47,16), }; + #region Museum + internal static bool MuseumMenuKeyPressPatch() { try @@ -275,5 +277,134 @@ namespace stardew_access.Patches } } #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 + { + for (int i = 0; i < __instance.inventory.inventory.Count; i++) + { + if (!__instance.inventory.inventory[i].containsPoint(x, y)) + continue; + + if (__instance.inventory.actualInventory[i] == null) + toSpeak = "Empty slot"; + else + toSpeak = $"{__instance.inventory.actualInventory[i].Stack} {__instance.inventory.actualInventory[i].DisplayName}"; + + if (fieldOfficeMenuQuery != $"{toSpeak}:{i}") + { + fieldOfficeMenuQuery = $"{toSpeak}:{i}"; + MainClass.ScreenReader.Say(toSpeak, true); + } + + 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 (__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 } } \ No newline at end of file diff --git a/stardew-access/Patches/MenuPatches.cs b/stardew-access/Patches/MenuPatches.cs index 33d0581..362c78b 100644 --- a/stardew-access/Patches/MenuPatches.cs +++ b/stardew-access/Patches/MenuPatches.cs @@ -20,130 +20,6 @@ namespace stardew_access.Patches internal static string forgeMenuQuery = " "; internal static string itemListMenuQuery = " "; public static Vector2? prevTile = null; - private static string fieldOfficeMenuQuery = " "; - - 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 - { - for (int i = 0; i < __instance.inventory.inventory.Count; i++) - { - if (!__instance.inventory.inventory[i].containsPoint(x, y)) - continue; - - if (__instance.inventory.actualInventory[i] == null) - toSpeak = "Empty slot"; - else - toSpeak = $"{__instance.inventory.actualInventory[i].Stack} {__instance.inventory.actualInventory[i].DisplayName}"; - - if (fieldOfficeMenuQuery != $"{toSpeak}:{i}") - { - fieldOfficeMenuQuery = $"{toSpeak}:{i}"; - MainClass.ScreenReader.Say(toSpeak, true); - } - - 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 (__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 ItemListMenuPatch(ItemListMenu __instance, string ___title, int ___currentTab, int ___totalValueOfItems, List ___itemsToList) { @@ -553,7 +429,7 @@ namespace stardew_access.Patches if (cueName == "grassyStep" || cueName == "sandyStep" || cueName == "snowyStep" || cueName == "stoneStep" || cueName == "thudStep" || cueName == "woodyStep") { Vector2 nextTile = CurrentPlayer.getNextTile(); - if (ReadTile.isCollidingAtTile((int)nextTile.X, (int)nextTile.Y)) + if (TileInfo.isCollidingAtTile((int)nextTile.X, (int)nextTile.Y)) { if (prevTile != nextTile) { @@ -955,7 +831,11 @@ namespace stardew_access.Patches } else if (menu is FieldOfficeMenu) { - fieldOfficeMenuQuery = " "; + DonationMenuPatches.fieldOfficeMenuQuery = " "; + } + else if (menu is MuseumMenu) + { + DonationMenuPatches.museumQueryKey = " "; } else if (menu is PondQueryMenu) {