Organized code and added parrot perch to read tile
parent
f0a85e0be9
commit
4351182984
|
@ -4,6 +4,7 @@
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
.git-old/
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace stardew_access.ScreenReader
|
||||||
/// <returns>Name of the object as the first item (Item1) and category as the second item (Item2). Returns null if no object found.</returns>
|
/// <returns>Name of the object as the first item (Item1) and category as the second item (Item2). Returns null if no object found.</returns>
|
||||||
public (string?, string?) GetNameWithCategoryNameAtTile(Vector2 tile)
|
public (string?, string?) GetNameWithCategoryNameAtTile(Vector2 tile)
|
||||||
{
|
{
|
||||||
return ReadTile.getNameWithCategoryNameAtTile(tile);
|
return TileInfo.getNameWithCategoryNameAtTile(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -47,7 +47,7 @@ namespace stardew_access.ScreenReader
|
||||||
/// <returns>Name of the object. Returns null if no object found.</returns>
|
/// <returns>Name of the object. Returns null if no object found.</returns>
|
||||||
public string? GetNameAtTile(Vector2 tile)
|
public string? GetNameAtTile(Vector2 tile)
|
||||||
{
|
{
|
||||||
return ReadTile.getNameAtTile(tile);
|
return TileInfo.getNameAtTile(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Speaks the text via the loaded screen reader (if any).</summary>
|
/// <summary>Speaks the text via the loaded screen reader (if any).</summary>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Objects;
|
using StardewValley.Objects;
|
||||||
using StardewValley.TerrainFeatures;
|
|
||||||
|
|
||||||
namespace stardew_access.Features
|
namespace stardew_access.Features
|
||||||
{
|
{
|
||||||
|
@ -187,7 +186,7 @@ namespace stardew_access.Features
|
||||||
|
|
||||||
public (bool, string?, string) CheckTile(Vector2 position)
|
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)
|
if (tileDetail.name == null)
|
||||||
return (false, null, CATEGORY.Others.ToString());
|
return (false, null, CATEGORY.Others.ToString());
|
||||||
|
|
||||||
|
@ -204,7 +203,7 @@ namespace stardew_access.Features
|
||||||
{
|
{
|
||||||
if (Game1.currentLocation.isObjectAtTile((int)position.X, (int)position.Y))
|
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;
|
string? objectName = objDetails.name;
|
||||||
CATEGORY category = objDetails.category;
|
CATEGORY category = objDetails.category;
|
||||||
StardewValley.Object obj = Game1.currentLocation.getObjectAtTile((int)position.X, (int)position.Y);
|
StardewValley.Object obj = Game1.currentLocation.getObjectAtTile((int)position.X, (int)position.Y);
|
||||||
|
@ -228,7 +227,7 @@ namespace stardew_access.Features
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(string? name, CATEGORY? category) tileDetail = ReadTile.getNameWithCategoryAtTile(position);
|
(string? name, CATEGORY? category) tileDetail = TileInfo.getNameWithCategoryAtTile(position);
|
||||||
if (tileDetail.name != null)
|
if (tileDetail.name != null)
|
||||||
{
|
{
|
||||||
if (tileDetail.category == null)
|
if (tileDetail.category == null)
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using StardewModdingAPI;
|
using StardewModdingAPI;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Buildings;
|
|
||||||
using StardewValley.Locations;
|
|
||||||
using StardewValley.Objects;
|
|
||||||
using StardewValley.TerrainFeatures;
|
|
||||||
|
|
||||||
namespace stardew_access.Features
|
namespace stardew_access.Features
|
||||||
{
|
{
|
||||||
public enum MachineState
|
|
||||||
{
|
|
||||||
Ready, Busy, Waiting
|
|
||||||
}
|
|
||||||
public class ReadTile
|
public class ReadTile
|
||||||
{
|
{
|
||||||
public static bool isReadingTile = false;
|
public static bool isReadingTile = false;
|
||||||
|
@ -51,9 +43,9 @@ namespace stardew_access.Features
|
||||||
MainClass.ScreenReader.PrevTextTile = " ";
|
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
|
#region Narrate toSpeak
|
||||||
if (toSpeak != null)
|
if (toSpeak != null)
|
||||||
|
@ -81,831 +73,5 @@ namespace stardew_access.Features
|
||||||
MainClass.ErrorLog($"Error in Read Tile:\n{e.Message}\n{e.StackTrace}");
|
MainClass.ErrorLog($"Error in Read Tile:\n{e.Message}\n{e.StackTrace}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>Returns the name of the object at tile alongwith it's category's name</summary>
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
///<summary>Returns the name of the object at tile</summary>
|
|
||||||
public static string? getNameAtTile(Vector2 tile)
|
|
||||||
{
|
|
||||||
return getNameWithCategoryAtTile(tile).name;
|
|
||||||
}
|
|
||||||
|
|
||||||
///<summary>Returns the name of the object at tile alongwith it's category</summary>
|
|
||||||
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<Vector2, Netcode.NetRef<TerrainFeature>> 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<FarmAnimal>? 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x"></param>
|
|
||||||
/// <param name="y"></param>
|
|
||||||
/// <returns>category: This is the category of the tile. Default to Furnitures.
|
|
||||||
/// <br/>name: This is the name of the tile. Default to null if the tile tile has nothing on it.</returns>
|
|
||||||
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<TerrainFeature> 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<string, Netcode.NetString> 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<ResourceClump> stumps = ((Woods)Game1.currentLocation).stumps;
|
|
||||||
for (int i = 0; i < stumps.Count; i++)
|
|
||||||
{
|
|
||||||
if (stumps[i].occupiesTile(x, y))
|
|
||||||
{
|
|
||||||
return "Large Stump";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
{
|
||||||
|
///<summary>Returns the name of the object at tile alongwith it's category's name</summary>
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>Returns the name of the object at tile</summary>
|
||||||
|
public static string? getNameAtTile(Vector2 tile)
|
||||||
|
{
|
||||||
|
return getNameWithCategoryAtTile(tile).name;
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>Returns the name of the object at tile alongwith it's category</summary>
|
||||||
|
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<Vector2, Netcode.NetRef<TerrainFeature>> 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<FarmAnimal>? 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <param name="y"></param>
|
||||||
|
/// <returns>category: This is the category of the tile. Default to Furnitures.
|
||||||
|
/// <br/>name: This is the name of the tile. Default to null if the tile tile has nothing on it.</returns>
|
||||||
|
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<TerrainFeature> 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<string, Netcode.NetString> 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<ResourceClump> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -158,12 +158,7 @@ namespace stardew_access
|
||||||
|
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }),
|
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }),
|
||||||
prefix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuKeyPressPatch))
|
prefix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuKeyPressPatch))
|
||||||
);
|
|
||||||
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
|
||||||
postfix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuPatch))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
|
@ -195,11 +190,6 @@ namespace stardew_access
|
||||||
original: AccessTools.Method(typeof(ItemListMenu), nameof(ItemListMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
original: AccessTools.Method(typeof(ItemListMenu), nameof(ItemListMenu.draw), new Type[] { typeof(SpriteBatch) }),
|
||||||
postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.ItemListMenuPatch))
|
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
|
#endregion
|
||||||
|
|
||||||
#region Quest Patches
|
#region Quest Patches
|
||||||
|
@ -251,6 +241,18 @@ namespace stardew_access
|
||||||
|
|
||||||
#endregion
|
#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(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(Game1), nameof(Game1.playSound)),
|
original: AccessTools.Method(typeof(Game1), nameof(Game1.playSound)),
|
||||||
prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.PlaySoundPatch))
|
prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.PlaySoundPatch))
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using StardewModdingAPI;
|
using StardewModdingAPI;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Menus;
|
using StardewValley.Menus;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace stardew_access.Patches
|
namespace stardew_access.Patches
|
||||||
{
|
{
|
||||||
|
@ -197,6 +196,8 @@ namespace stardew_access.Patches
|
||||||
return;
|
return;
|
||||||
else if (Game1.activeClickableMenu is FieldOfficeMenu)
|
else if (Game1.activeClickableMenu is FieldOfficeMenu)
|
||||||
return;
|
return;
|
||||||
|
else if (Game1.activeClickableMenu is MuseumMenu)
|
||||||
|
return;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
string toSpeak = " ";
|
string toSpeak = " ";
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Content;
|
using Microsoft.Xna.Framework.Content;
|
||||||
using StardewModdingAPI;
|
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Locations;
|
using StardewValley.Locations;
|
||||||
using StardewValley.Menus;
|
using StardewValley.Menus;
|
||||||
|
|
||||||
namespace stardew_access.Patches
|
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 bool isMoving = false;
|
||||||
private static (int x, int y)[] donationTiles =
|
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),
|
(42,16),(43,16),(44,16),(45,16),(46,16),(47,16),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#region Museum
|
||||||
|
|
||||||
internal static bool MuseumMenuKeyPressPatch()
|
internal static bool MuseumMenuKeyPressPatch()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -275,5 +277,134 @@ namespace stardew_access.Patches
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#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
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,130 +20,6 @@ namespace stardew_access.Patches
|
||||||
internal static string forgeMenuQuery = " ";
|
internal static string forgeMenuQuery = " ";
|
||||||
internal static string itemListMenuQuery = " ";
|
internal static string itemListMenuQuery = " ";
|
||||||
public static Vector2? prevTile = null;
|
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<Item> ___itemsToList)
|
internal static void ItemListMenuPatch(ItemListMenu __instance, string ___title, int ___currentTab, int ___totalValueOfItems, List<Item> ___itemsToList)
|
||||||
{
|
{
|
||||||
|
@ -553,7 +429,7 @@ namespace stardew_access.Patches
|
||||||
if (cueName == "grassyStep" || cueName == "sandyStep" || cueName == "snowyStep" || cueName == "stoneStep" || cueName == "thudStep" || cueName == "woodyStep")
|
if (cueName == "grassyStep" || cueName == "sandyStep" || cueName == "snowyStep" || cueName == "stoneStep" || cueName == "thudStep" || cueName == "woodyStep")
|
||||||
{
|
{
|
||||||
Vector2 nextTile = CurrentPlayer.getNextTile();
|
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)
|
if (prevTile != nextTile)
|
||||||
{
|
{
|
||||||
|
@ -955,7 +831,11 @@ namespace stardew_access.Patches
|
||||||
}
|
}
|
||||||
else if (menu is FieldOfficeMenu)
|
else if (menu is FieldOfficeMenu)
|
||||||
{
|
{
|
||||||
fieldOfficeMenuQuery = " ";
|
DonationMenuPatches.fieldOfficeMenuQuery = " ";
|
||||||
|
}
|
||||||
|
else if (menu is MuseumMenu)
|
||||||
|
{
|
||||||
|
DonationMenuPatches.museumQueryKey = " ";
|
||||||
}
|
}
|
||||||
else if (menu is PondQueryMenu)
|
else if (menu is PondQueryMenu)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue