Added toggle between stereo and mono sound for radar
This commit is contained in:
121
stardew-access/Features/CurrentPlayer.cs
Normal file
121
stardew-access/Features/CurrentPlayer.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using StardewValley;
|
||||
using StardewModdingAPI;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace stardew_access.Game
|
||||
{
|
||||
internal class CurrentPlayer
|
||||
{
|
||||
|
||||
public static int getHealth()
|
||||
{
|
||||
if(Game1.player == null)
|
||||
return 0;
|
||||
|
||||
int maxHealth = Game1.player.maxHealth;
|
||||
int currentHealth = Game1.player.health;
|
||||
|
||||
int healthPercentage = (int) (currentHealth * 100)/maxHealth;
|
||||
return healthPercentage;
|
||||
}
|
||||
|
||||
public static int getStamina()
|
||||
{
|
||||
if (Game1.player == null)
|
||||
return 0;
|
||||
|
||||
int maxStamina = Game1.player.maxStamina;
|
||||
int currentStamine = (int)Game1.player.stamina;
|
||||
|
||||
int staminaPercentage = (int)(currentStamine * 100) / maxStamina;
|
||||
|
||||
return staminaPercentage;
|
||||
}
|
||||
|
||||
public static int getPositionX()
|
||||
{
|
||||
if (Game1.player == null)
|
||||
return 0;
|
||||
|
||||
int x = (int)Game1.player.getTileLocation().X;
|
||||
return x;
|
||||
}
|
||||
|
||||
public static int getPositionY()
|
||||
{
|
||||
if (Game1.player == null)
|
||||
return 0;
|
||||
|
||||
int y = (int)Game1.player.getTileLocation().Y;
|
||||
return y;
|
||||
}
|
||||
|
||||
public static string getTimeOfDay()
|
||||
{
|
||||
int timeOfDay = Game1.timeOfDay;
|
||||
|
||||
int minutes = timeOfDay % 100;
|
||||
int hours = timeOfDay / 100;
|
||||
string amOrpm = "A M";
|
||||
if(hours>=12)
|
||||
{
|
||||
amOrpm = "P M";
|
||||
if (hours > 12)
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
return $"{hours}:{minutes} {amOrpm}";
|
||||
}
|
||||
|
||||
public static string getSeason()
|
||||
{
|
||||
return Game1.CurrentSeasonDisplayName;
|
||||
}
|
||||
|
||||
public static int getDate()
|
||||
{
|
||||
return Game1.dayOfMonth;
|
||||
}
|
||||
|
||||
public static string getDay()
|
||||
{
|
||||
return Game1.Date.DayOfWeek.ToString();
|
||||
}
|
||||
|
||||
public static int getMoney()
|
||||
{
|
||||
if(Game1.player == null)
|
||||
return -1;
|
||||
|
||||
return Game1.player.Money;
|
||||
}
|
||||
|
||||
public static Vector2 getNextTile()
|
||||
{
|
||||
int x = Game1.player.GetBoundingBox().Center.X;
|
||||
int y = Game1.player.GetBoundingBox().Center.Y;
|
||||
|
||||
int offset = 64;
|
||||
|
||||
switch (Game1.player.FacingDirection)
|
||||
{
|
||||
case 0:
|
||||
y -= offset;
|
||||
break;
|
||||
case 1:
|
||||
x += offset;
|
||||
break;
|
||||
case 2:
|
||||
y += offset;
|
||||
break;
|
||||
case 3:
|
||||
x -= offset;
|
||||
break;
|
||||
}
|
||||
|
||||
x /= Game1.tileSize;
|
||||
y /= Game1.tileSize;
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
106
stardew-access/Features/Other.cs
Normal file
106
stardew-access/Features/Other.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using StardewValley;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace stardew_access.Game
|
||||
{
|
||||
internal class Other
|
||||
{
|
||||
private static Item? currentSlotItem;
|
||||
private static Item? previousSlotItem;
|
||||
|
||||
private static GameLocation? currentLocation;
|
||||
private static GameLocation? previousLocation;
|
||||
|
||||
// Narrates current slected slot name
|
||||
public static void narrateCurrentSlot()
|
||||
{
|
||||
currentSlotItem = Game1.player.CurrentItem;
|
||||
|
||||
if (currentSlotItem == null)
|
||||
return;
|
||||
|
||||
if (previousSlotItem == currentSlotItem)
|
||||
return;
|
||||
|
||||
previousSlotItem = currentSlotItem;
|
||||
ScreenReader.say($"{currentSlotItem.DisplayName} Selected", true);
|
||||
}
|
||||
|
||||
// Narrates current location's name
|
||||
public static void narrateCurrentLocation()
|
||||
{
|
||||
currentLocation = Game1.currentLocation;
|
||||
|
||||
if (currentLocation == null)
|
||||
return;
|
||||
|
||||
if (previousLocation == currentLocation)
|
||||
return;
|
||||
|
||||
previousLocation = currentLocation;
|
||||
ScreenReader.say($"{currentLocation.Name} Entered",true);
|
||||
}
|
||||
|
||||
public static void SnapMouseToPlayer()
|
||||
{
|
||||
int x = Game1.player.GetBoundingBox().Center.X - Game1.viewport.X;
|
||||
int y = Game1.player.GetBoundingBox().Center.Y - Game1.viewport.Y;
|
||||
|
||||
int offset = 64;
|
||||
|
||||
switch (Game1.player.FacingDirection)
|
||||
{
|
||||
case 0:
|
||||
y -= offset;
|
||||
break;
|
||||
case 1:
|
||||
x += offset;
|
||||
break;
|
||||
case 2:
|
||||
y += offset;
|
||||
break;
|
||||
case 3:
|
||||
x -= offset;
|
||||
break;
|
||||
}
|
||||
|
||||
Game1.setMousePosition(x, y);
|
||||
}
|
||||
|
||||
public static async void narrateHudMessages()
|
||||
{
|
||||
MainClass.isNarratingHudMessage = true;
|
||||
try
|
||||
{
|
||||
if (Game1.hudMessages.Count > 0)
|
||||
{
|
||||
int lastIndex = Game1.hudMessages.Count - 1;
|
||||
HUDMessage lastMessage = Game1.hudMessages[lastIndex];
|
||||
if (!lastMessage.noIcon)
|
||||
{
|
||||
string toSpeak = lastMessage.Message;
|
||||
string searchQuery = toSpeak;
|
||||
|
||||
searchQuery = Regex.Replace(toSpeak, @"[\d+]", string.Empty);
|
||||
searchQuery.Trim();
|
||||
|
||||
|
||||
if (MainClass.hudMessageQueryKey != searchQuery)
|
||||
{
|
||||
MainClass.hudMessageQueryKey = searchQuery;
|
||||
|
||||
ScreenReader.say(toSpeak, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"Unable to narrate hud messages:\n{e.Message}\n{e.StackTrace}", StardewModdingAPI.LogLevel.Error);
|
||||
}
|
||||
|
||||
await Task.Delay(300);
|
||||
MainClass.isNarratingHudMessage = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
307
stardew-access/Features/Radar.cs
Normal file
307
stardew-access/Features/Radar.cs
Normal file
@@ -0,0 +1,307 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using StardewValley;
|
||||
using StardewValley.Objects;
|
||||
using StardewValley.TerrainFeatures;
|
||||
|
||||
namespace stardew_access.Game
|
||||
{
|
||||
internal class door {}
|
||||
internal class building{}
|
||||
internal class otherObjects{}
|
||||
internal class junimoBundle{}
|
||||
|
||||
public class Radar
|
||||
{
|
||||
private List<Vector2> closed;
|
||||
private List<Furniture> furnitures;
|
||||
private List<NPC> npcs;
|
||||
public List<string> exclusions;
|
||||
public bool isRunning;
|
||||
|
||||
public Radar()
|
||||
{
|
||||
isRunning = false;
|
||||
closed = new List<Vector2>();
|
||||
furnitures = new List<Furniture>();
|
||||
npcs = new List<NPC>();
|
||||
exclusions = new List<string>();
|
||||
|
||||
exclusions.Add("stone");
|
||||
exclusions.Add("weed");
|
||||
exclusions.Add("twig");
|
||||
exclusions.Add("coloured stone");
|
||||
exclusions.Add("mine stone");
|
||||
exclusions.Add("clay stone");
|
||||
exclusions.Add("fossil stone");
|
||||
exclusions.Add("crop");
|
||||
exclusions.Add("giant crop");
|
||||
exclusions.Add("grass");
|
||||
exclusions.Add("tree");
|
||||
exclusions.Add("flooring");
|
||||
exclusions.Add("water");
|
||||
exclusions.Add("door");
|
||||
}
|
||||
|
||||
public async void run()
|
||||
{
|
||||
MainClass.monitor.Log($"\n\nRead Tile started", StardewModdingAPI.LogLevel.Debug);
|
||||
isRunning = true;
|
||||
Vector2 currPosition = Game1.player.getTileLocation();
|
||||
int limit = 5;
|
||||
|
||||
closed.Clear();
|
||||
furnitures.Clear();
|
||||
npcs.Clear();
|
||||
findTile(currPosition, currPosition, limit);
|
||||
|
||||
MainClass.monitor.Log($"\nRead Tile stopped\n\n", StardewModdingAPI.LogLevel.Debug);
|
||||
await Task.Delay(3000);
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
public void findTile(Vector2 position, Vector2 center, int limit)
|
||||
{
|
||||
if (Math.Abs(position.X - center.X) > limit)
|
||||
return;
|
||||
if (Math.Abs(position.Y - center.Y) > limit)
|
||||
return;
|
||||
if (closed.Contains(position))
|
||||
return;
|
||||
|
||||
closed.Add(position);
|
||||
checkTile(position);
|
||||
|
||||
Vector2 northPosition = new(position.X, position.Y-1);
|
||||
Vector2 eastPosition = new(position.X+1, position.Y);
|
||||
Vector2 westPosition = new(position.X-1, position.Y);
|
||||
Vector2 southPosition = new(position.X, position.Y+1);
|
||||
|
||||
findTile(northPosition, center, limit);
|
||||
findTile(eastPosition, center, limit);
|
||||
findTile(westPosition, center, limit);
|
||||
findTile(southPosition, center, limit);
|
||||
}
|
||||
|
||||
public void checkTile(Vector2 position)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dictionary<Vector2, Netcode.NetRef<TerrainFeature>> terrainFeature = Game1.currentLocation.terrainFeatures.FieldDict;
|
||||
|
||||
// Check for npcs
|
||||
if (Game1.currentLocation.isCharacterAtTile(position) != null && !exclusions.Contains("npc"))
|
||||
{
|
||||
NPC npc = Game1.currentLocation.isCharacterAtTile(position);
|
||||
if (!npcs.Contains(npc))
|
||||
{
|
||||
if (npc.isVillager() || npc.CanSocialize)
|
||||
playSoundAt(position, npc.displayName, typeof(Farmer)); // Villager
|
||||
else
|
||||
playSoundAt(position, npc.displayName, typeof(NPC));
|
||||
}
|
||||
}
|
||||
// Check for animals
|
||||
else if (ReadTile.getFarmAnimalAt(Game1.currentLocation, (int)position.X, (int)position.Y) != null && !exclusions.Contains("animals"))
|
||||
{
|
||||
string name = ReadTile.getFarmAnimalAt(Game1.currentLocation, (int)position.X, (int)position.Y, onlyName: true);
|
||||
playSoundAt(position, name, typeof(FarmAnimal));
|
||||
}
|
||||
// Check for water
|
||||
else if (Game1.currentLocation.isWaterTile((int)position.X, (int)position.Y) && !exclusions.Contains("water"))
|
||||
{
|
||||
playSoundAt(position, null, typeof(WaterTiles));
|
||||
}
|
||||
// Check for objects
|
||||
else if (Game1.currentLocation.isObjectAtTile((int)position.X, (int)position.Y))
|
||||
{
|
||||
string? objectName = ReadTile.getObjectNameAtTile((int)position.X, (int)position.Y);
|
||||
StardewValley.Object obj = Game1.currentLocation.getObjectAtTile((int)position.X, (int)position.Y);
|
||||
|
||||
if (objectName != null)
|
||||
{
|
||||
if (obj is Furniture && !exclusions.Contains("furniture"))
|
||||
{
|
||||
if (!furnitures.Contains(obj as Furniture))
|
||||
{
|
||||
furnitures.Add(obj as Furniture);
|
||||
playSoundAt(position, objectName, typeof(Furniture));
|
||||
}
|
||||
}
|
||||
else if (obj is not Furniture)
|
||||
{
|
||||
playSoundAt(position, objectName, typeof(otherObjects));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for terrain features
|
||||
else if (terrainFeature.ContainsKey(position))
|
||||
{
|
||||
Netcode.NetRef<TerrainFeature> tr = terrainFeature[position];
|
||||
string? terrain = ReadTile.getTerrainFeatureAtTile(tr).ToLower();
|
||||
if (terrain != null)
|
||||
{
|
||||
if (tr.Get() is HoeDirt && !exclusions.Contains("crop"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Crop));
|
||||
}
|
||||
else if (tr.Get() is GiantCrop && !exclusions.Contains("giant crop"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(GiantCrop));
|
||||
}
|
||||
else if (tr.Get() is Bush && !exclusions.Contains("bush"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Bush));
|
||||
}
|
||||
else if (tr.Get() is CosmeticPlant && !exclusions.Contains("cosmetic plant"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(CosmeticPlant));
|
||||
}
|
||||
else if (tr.Get() is Flooring && !exclusions.Contains("flooring"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Flooring));
|
||||
}
|
||||
else if (tr.Get() is FruitTree && !exclusions.Contains("fruit tree"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(FruitTree));
|
||||
}
|
||||
else if (tr.Get() is Grass && !exclusions.Contains("grass"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Grass));
|
||||
}
|
||||
else if (tr.Get() is Tree && !exclusions.Contains("tree"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Tree));
|
||||
}
|
||||
else if (tr.Get() is Quartz && !exclusions.Contains("quartz"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Quartz));
|
||||
}
|
||||
else if (tr.Get() is Leaf && !exclusions.Contains("leaf"))
|
||||
{
|
||||
playSoundAt(position, terrain, typeof(Leaf));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for Mine ladders
|
||||
else if (ReadTile.isMineLadderAtTile((int)position.X, (int)position.Y) && !exclusions.Contains("ladder"))
|
||||
{
|
||||
playSoundAt(position, "ladder", typeof(door));
|
||||
}
|
||||
// Check for doors
|
||||
else if (ReadTile.isDoorAtTile((int)position.X, (int)position.Y) && !exclusions.Contains("door"))
|
||||
{
|
||||
playSoundAt(position, "door", typeof(door));
|
||||
}
|
||||
// Check for buildings on maps
|
||||
else if (ReadTile.getBuildingAtTile((int)position.X, (int)position.Y) != null && !exclusions.Contains("building"))
|
||||
{
|
||||
playSoundAt(position, ReadTile.getBuildingAtTile((int)position.X, (int)position.Y), typeof(building));
|
||||
}
|
||||
// Check for resource clumps
|
||||
else if (ReadTile.getResourceClumpAtTile((int)position.X, (int)position.Y) != null && !exclusions.Contains("resource clump"))
|
||||
{
|
||||
playSoundAt(position, "resource clump", typeof(ResourceClump));
|
||||
}
|
||||
// Check for junimo bundle
|
||||
else if (ReadTile.getJunimoBundleAt((int)position.X, (int)position.Y) != null && !exclusions.Contains("junimo bundle"))
|
||||
{
|
||||
playSoundAt(position, "junimo bundle", typeof(junimoBundle));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"{e.Message}\n{e.StackTrace}\n{e.Source}", StardewModdingAPI.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public void playSoundAt(Vector2 position, String? searchQuery, Type soundType)
|
||||
{
|
||||
// Skip if player is directly looking at the tile
|
||||
if (CurrentPlayer.getNextTile().Equals(position))
|
||||
return;
|
||||
|
||||
if (searchQuery == null || !exclusions.Contains(searchQuery.ToLower().Trim()))
|
||||
{
|
||||
if(MainClass.radarDebug)
|
||||
MainClass.monitor.Log($"Object:{searchQuery.ToLower().Trim()}\tPosition: X={position.X} Y={position.Y}", StardewModdingAPI.LogLevel.Debug);
|
||||
|
||||
int px = (int)Game1.player.getTileX(); // Player's X postion
|
||||
int py = (int)Game1.player.getTileY(); // Player's Y postion
|
||||
|
||||
int ox = (int)position.X; // Object's X postion
|
||||
int oy = (int)position.Y; // Object's Y postion
|
||||
|
||||
int dx = ox - px; // Distance of object's X position
|
||||
int dy = oy - py; // Distance of object's Y position
|
||||
|
||||
if(dy < 0 && (Math.Abs(dy) >= Math.Abs(dx))) // Object is at top
|
||||
{
|
||||
Game1.currentLocation.localSoundAt(getSoundName(soundType, "top"), position);
|
||||
}
|
||||
else if (dx > 0 && (Math.Abs(dx) >= Math.Abs(dy))) // Object is at right
|
||||
{
|
||||
Game1.currentLocation.localSoundAt(getSoundName(soundType, "right"), position);
|
||||
}
|
||||
else if (dx < 0 && (Math.Abs(dx) > Math.Abs(dy))) // Object is at left
|
||||
{
|
||||
Game1.currentLocation.localSoundAt(getSoundName(soundType, "left"), position);
|
||||
}
|
||||
else if (dy > 0 && (Math.Abs(dy) > Math.Abs(dx))) // Object is at bottom
|
||||
{
|
||||
Game1.currentLocation.localSoundAt(getSoundName(soundType, "bottom"), position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string getSoundName(Type soundType, string post)
|
||||
{
|
||||
string soundName = $"_{post}";
|
||||
|
||||
if(MainClass.radarStereoSound)
|
||||
soundName = $"_mono{soundName}";
|
||||
|
||||
if(soundType == typeof(Farmer)) // Villagers and farmers
|
||||
soundName = $"npc{soundName}";
|
||||
if (soundType == typeof(FarmAnimal)) // Farm Animals
|
||||
soundName = $"npc{soundName}";
|
||||
else if(soundType == typeof(NPC)) // Other npcs, also includes enemies
|
||||
soundName = $"obj{soundName}";
|
||||
else if(soundType == typeof(WaterTiles)) // Water tiles
|
||||
soundName = $"obj{soundName}";
|
||||
else if(soundType == typeof(Furniture)) // Furnitures
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(otherObjects)) // Other Objects
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Crop)) // Crops
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(GiantCrop)) // Giant Crops
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Bush)) // Bush
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(CosmeticPlant)) // CosmeticPlant
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Flooring)) // Flooring
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(FruitTree)) // Fruit Tree
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Grass)) // Grass
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Tree)) // Trees
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Quartz)) // Quartz
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(Leaf)) // Leaf
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(door)) // Doors and Ladders
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(building)) // Buildings
|
||||
soundName = $"obj{soundName}";
|
||||
else if (soundType == typeof(ResourceClump)) // Resource CLumps
|
||||
soundName = $"obj{soundName}";
|
||||
else // Default
|
||||
soundName = $"obj{soundName}";
|
||||
|
||||
return soundName;
|
||||
}
|
||||
}
|
||||
}
|
||||
641
stardew-access/Features/ReadTile.cs
Normal file
641
stardew-access/Features/ReadTile.cs
Normal file
@@ -0,0 +1,641 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewValley;
|
||||
using StardewValley.Locations;
|
||||
using StardewValley.Objects;
|
||||
using StardewValley.TerrainFeatures;
|
||||
|
||||
namespace stardew_access.Game
|
||||
{
|
||||
public class ReadTile
|
||||
{
|
||||
public static bool isReadingTile = false;
|
||||
public static Vector2 prevTile;
|
||||
|
||||
public ReadTile()
|
||||
{
|
||||
isReadingTile = false;
|
||||
}
|
||||
|
||||
public static async void run(bool manuallyTriggered = false)
|
||||
{
|
||||
isReadingTile = true;
|
||||
|
||||
try
|
||||
{
|
||||
#region Get Next Grab Tile
|
||||
Vector2 gt = CurrentPlayer.getNextTile();
|
||||
int x = (int)gt.X;
|
||||
int y = (int)gt.Y;
|
||||
#endregion
|
||||
|
||||
if (Context.IsPlayerFree)
|
||||
{
|
||||
if (!manuallyTriggered && prevTile != gt)
|
||||
{
|
||||
ScreenReader.prevTextTile = " ";
|
||||
}
|
||||
|
||||
Dictionary<Vector2, Netcode.NetRef<TerrainFeature>> terrainFeature = Game1.currentLocation.terrainFeatures.FieldDict;
|
||||
string toSpeak = " ";
|
||||
|
||||
#region Get objects, crops, resource clumps, etc.
|
||||
if (Game1.currentLocation.isCharacterAtTile(gt) != null)
|
||||
{
|
||||
NPC npc = Game1.currentLocation.isCharacterAtTile(gt);
|
||||
toSpeak = npc.displayName;
|
||||
}
|
||||
else if(getFarmAnimalAt(Game1.currentLocation, x, y) != null)
|
||||
{
|
||||
toSpeak = getFarmAnimalAt(Game1.currentLocation, x, y);
|
||||
}
|
||||
else if (Game1.currentLocation.isWaterTile(x, y))
|
||||
{
|
||||
toSpeak = "Water";
|
||||
}
|
||||
else if (Game1.currentLocation.isObjectAtTile(x, y))
|
||||
{
|
||||
string? objectName = getObjectNameAtTile(x, y);
|
||||
if (objectName != null)
|
||||
toSpeak = objectName;
|
||||
}
|
||||
else if (terrainFeature.ContainsKey(gt))
|
||||
{
|
||||
string? terrain = getTerrainFeatureAtTile(terrainFeature[gt]);
|
||||
if (terrain != null)
|
||||
toSpeak = terrain;
|
||||
}
|
||||
else if (getResourceClumpAtTile(x, y) != null)
|
||||
{
|
||||
toSpeak = getResourceClumpAtTile(x, y);
|
||||
}
|
||||
else if (isDoorAtTile(x, y))
|
||||
{
|
||||
toSpeak = "Door";
|
||||
}
|
||||
else if (isMineLadderAtTile(x, y))
|
||||
{
|
||||
toSpeak = "Ladder";
|
||||
}
|
||||
else if(getBuildingAtTile(x, y) != null)
|
||||
{
|
||||
toSpeak = getBuildingAtTile(x, y);
|
||||
}
|
||||
else if(getJunimoBundleAt(x, y) != null)
|
||||
{
|
||||
toSpeak = getJunimoBundleAt(x, y);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Narrate toSpeak
|
||||
if (toSpeak != " ")
|
||||
if (manuallyTriggered)
|
||||
ScreenReader.say(toSpeak, true);
|
||||
else
|
||||
ScreenReader.sayWithTileQuery(toSpeak, x, y, true);
|
||||
#endregion
|
||||
|
||||
#region Play colliding sound effect
|
||||
if (isCollidingAtTile(x, y) && prevTile != gt)
|
||||
{
|
||||
Game1.playSound("colliding");
|
||||
}
|
||||
#endregion
|
||||
|
||||
prevTile = gt;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"Error in Read Tile:\n{e.Message}\n{e.StackTrace}", LogLevel.Debug);
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
isReadingTile = false;
|
||||
}
|
||||
|
||||
public static string? getJunimoBundleAt(int x, int y)
|
||||
{
|
||||
if (Game1.currentLocation is not CommunityCenter)
|
||||
return null;
|
||||
|
||||
CommunityCenter communityCenter = (Game1.currentLocation as CommunityCenter);
|
||||
|
||||
string? 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 (communityCenter.shouldNoteAppearInArea(CommunityCenter.getAreaNumberFromName(name)))
|
||||
return $"{name} bundle";
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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 = (location as Farm).getAllFarmAnimals();
|
||||
else if(location is AnimalHouse)
|
||||
farmAnimals = (location as AnimalHouse).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;
|
||||
}
|
||||
|
||||
public static string? getBuildingAtTile(int x, int y)
|
||||
{
|
||||
string? toReturn = null;
|
||||
|
||||
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 (index != null)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 1955:
|
||||
case 41:
|
||||
toReturn = "Mail Box";
|
||||
break;
|
||||
case 1003:
|
||||
toReturn = "Street lamp";
|
||||
break;
|
||||
case 78:
|
||||
toReturn = "Trash bin";
|
||||
break;
|
||||
case 617:
|
||||
toReturn = "Daily quest";
|
||||
break;
|
||||
case 616:
|
||||
toReturn = "Calender";
|
||||
break;
|
||||
}
|
||||
|
||||
if (Game1.currentLocation is FarmHouse || Game1.currentLocation is IslandFarmHouse)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 173:
|
||||
toReturn = "Fridge";
|
||||
break;
|
||||
case 169:
|
||||
case 170:
|
||||
case 171:
|
||||
case 172:
|
||||
toReturn = "Kitchen";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static string getTerrainFeatureAtTile(Netcode.NetRef<TerrainFeature> terrain)
|
||||
{
|
||||
string? toReturn = null;
|
||||
if (terrain.Get() is HoeDirt)
|
||||
{
|
||||
HoeDirt dirt = (HoeDirt)terrain.Get();
|
||||
if (dirt.crop != null)
|
||||
{
|
||||
string cropName = Game1.objectInformation[dirt.crop.indexOfHarvest].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)
|
||||
{
|
||||
int whichCrop = (terrain.Get() as GiantCrop).which.Value;
|
||||
switch (whichCrop)
|
||||
{
|
||||
case 0:
|
||||
toReturn = "Cauliflower";
|
||||
break;
|
||||
case 1:
|
||||
toReturn = "Melon";
|
||||
break;
|
||||
case 2:
|
||||
toReturn = "Pumpkin";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (terrain.Get() is Bush)
|
||||
{
|
||||
toReturn = "Bush";
|
||||
}
|
||||
else if (terrain.Get() is CosmeticPlant)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
toReturn = getFruitTree((FruitTree)terrain.Get());
|
||||
}
|
||||
else if (terrain.Get() is Grass)
|
||||
{
|
||||
toReturn = "Grass";
|
||||
}
|
||||
else if (terrain.Get() is Tree)
|
||||
{
|
||||
toReturn = getTree((Tree)terrain.Get());
|
||||
}
|
||||
else if (terrain.Get() is Quartz)
|
||||
{
|
||||
toReturn = "Quartz";
|
||||
}
|
||||
else if (terrain.Get() is Leaf)
|
||||
{
|
||||
toReturn = "Leaf";
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static string? getObjectNameAtTile(int x, int y)
|
||||
{
|
||||
string? toReturn = null;
|
||||
|
||||
StardewValley.Object obj = Game1.currentLocation.getObjectAtTile(x, y);
|
||||
int index = obj.ParentSheetIndex;
|
||||
toReturn = obj.DisplayName;
|
||||
|
||||
// Get object names based on 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";
|
||||
case 792:
|
||||
case 793:
|
||||
case 794:
|
||||
return "Fertile weed";
|
||||
case 319:
|
||||
case 320:
|
||||
case 321:
|
||||
return "Ice crystal";
|
||||
case 75:
|
||||
return "Geode";
|
||||
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";
|
||||
case 668:
|
||||
case 670:
|
||||
case 845:
|
||||
case 846:
|
||||
case 847:
|
||||
return "Mine stone";
|
||||
case 818:
|
||||
return "Clay stone";
|
||||
case 816:
|
||||
case 817:
|
||||
return "Fossil stone";
|
||||
case 25:
|
||||
return "Stone";
|
||||
case 118:
|
||||
case 120:
|
||||
case 122:
|
||||
case 124:
|
||||
return "Barrel";
|
||||
case 119:
|
||||
case 121:
|
||||
case 123:
|
||||
case 125:
|
||||
return "Item box";
|
||||
}
|
||||
|
||||
if (Game1.inMine || Game1.currentLocation is Mine)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 76:
|
||||
return "Frozen geode";
|
||||
case 77:
|
||||
return "Magma geode";
|
||||
case 8:
|
||||
case 66:
|
||||
return "Amethyst node";
|
||||
case 14:
|
||||
case 62:
|
||||
return "Aquamarine node";
|
||||
case 843:
|
||||
case 844:
|
||||
return "Cinder shard node";
|
||||
case 2:
|
||||
case 72:
|
||||
return "Diamond node";
|
||||
case 12:
|
||||
case 60:
|
||||
return "Emerald node";
|
||||
case 44:
|
||||
return "Gem node";
|
||||
case 6:
|
||||
case 70:
|
||||
return "Jade node";
|
||||
case 46:
|
||||
return "Mystic stone";
|
||||
case 74:
|
||||
return "Prismatic node";
|
||||
case 4:
|
||||
case 64:
|
||||
return "Ruby node";
|
||||
case 10:
|
||||
case 68:
|
||||
return "Topaz node";
|
||||
case 819:
|
||||
return "Omni geode node";
|
||||
case 751:
|
||||
case 849:
|
||||
return "Copper node";
|
||||
case 764:
|
||||
return "Gold node";
|
||||
case 765:
|
||||
return "Iridium node";
|
||||
case 290:
|
||||
case 850:
|
||||
return "Iron node";
|
||||
}
|
||||
}
|
||||
|
||||
if(obj is Chest)
|
||||
{
|
||||
Chest chest = (Chest)obj;
|
||||
toReturn = chest.Type;
|
||||
toReturn = chest.DisplayName;
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static bool isMineLadderAtTile(int x, int y)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Game1.inMine || Game1.currentLocation is Mine)
|
||||
{
|
||||
int index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
|
||||
|
||||
if (index == 173 || index == 174)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool isDoorAtTile(int x, int y)
|
||||
{
|
||||
Point tilePoint = new Point(x, y);
|
||||
List<SerializableDictionary<Point, string>> doorList = Game1.currentLocation.doors.ToList();
|
||||
|
||||
for (int i=0; i < doorList.Count; i++)
|
||||
{
|
||||
for(int j = 0; j< doorList[i].Keys.Count; j++)
|
||||
{
|
||||
if (doorList[i].Keys.Contains(tilePoint))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string? getResourceClumpAtTile(int x, int 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user