From 0c42479b6f7b4fc093de07e09bb1d69a5bd74406 Mon Sep 17 00:00:00 2001 From: MattEqualsCoder Date: Wed, 18 Dec 2024 22:50:53 -0500 Subject: [PATCH 1/2] Add sass when tracking things that are likely misheard --- .../ITrackerBossService.cs | 12 +- .../ITrackerItemService.cs | 15 +- .../ConfigFiles/ResponseConfig.cs | 174 ++++++++++-------- .../WorldData/Item.cs | 5 + .../WorldData/Location.cs | 4 +- .../WorldData/Regions/IHasBoss.cs | 2 +- .../WorldData/Regions/IHasLocations.cs | 2 + .../WorldData/Regions/IHasTreasure.cs | 5 + .../WorldData/Regions/Region.cs | 2 +- .../WorldData/Room.cs | 2 +- .../TrackingServices/TrackerBossService.cs | 32 +++- .../TrackingServices/TrackerItemService.cs | 42 ++++- .../TrackerLocationService.cs | 6 + .../VoiceCommands/BossTrackingModule.cs | 26 ++- .../VoiceCommands/ItemTrackingModule.cs | 36 ++-- 15 files changed, 243 insertions(+), 122 deletions(-) diff --git a/src/TrackerCouncil.Smz3.Abstractions/ITrackerBossService.cs b/src/TrackerCouncil.Smz3.Abstractions/ITrackerBossService.cs index 0e4ed9ee7..38233116c 100644 --- a/src/TrackerCouncil.Smz3.Abstractions/ITrackerBossService.cs +++ b/src/TrackerCouncil.Smz3.Abstractions/ITrackerBossService.cs @@ -17,8 +17,9 @@ public interface ITrackerBossService /// /// if the command implies the boss was killed; /// if the boss was simply "tracked". + /// If the boss should be forced to be tracked while auto tracking /// - public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool autoTracked = false, bool admittedGuilt = false); + public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool autoTracked = false, bool admittedGuilt = false, bool force = false); /// /// Marks a boss as defeated. @@ -30,15 +31,17 @@ public interface ITrackerBossService /// /// The speech recognition confidence. /// If this was tracked by the auto tracker + /// If the boss should be forced to be tracked while auto tracking public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? confidence = null, - bool autoTracked = false); + bool autoTracked = false, bool force = false); /// /// Un-marks a boss as defeated. /// /// The boss that should be 'revived'. /// The speech recognition confidence. - public void MarkBossAsNotDefeated(Boss boss, float? confidence = null); + /// If the boss should be forced to be untracked while auto tracking + public void MarkBossAsNotDefeated(Boss boss, float? confidence = null, bool force = false); /// /// Un-marks a dungeon as cleared and, if possible, untracks the boss @@ -46,7 +49,8 @@ public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? conf /// /// The dungeon that should be un-cleared. /// The speech recognition confidence. - public void MarkBossAsNotDefeated(IHasBoss region, float? confidence = null); + /// If the boss should be forced to be untracked while auto tracking + public void MarkBossAsNotDefeated(IHasBoss region, float? confidence = null, bool force = false); public void UpdateAccessibility(Progression? actualProgression = null, Progression? withKeysProgression = null); diff --git a/src/TrackerCouncil.Smz3.Abstractions/ITrackerItemService.cs b/src/TrackerCouncil.Smz3.Abstractions/ITrackerItemService.cs index 35d1c754f..0ef776856 100644 --- a/src/TrackerCouncil.Smz3.Abstractions/ITrackerItemService.cs +++ b/src/TrackerCouncil.Smz3.Abstractions/ITrackerItemService.cs @@ -24,13 +24,14 @@ public interface ITrackerItemService /// The location an item was tracked from /// If the item was gifted to the player by tracker or another player /// If tracker should not say anything + /// If the item should be forced to be tracked while auto tracking /// /// if the item was actually tracked; if the item could not be tracked, e.g. when /// tracking Bow twice. /// bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bool tryClear = true, - bool autoTracked = false, Location? location = null, bool giftedItem = false, bool silent = false); + bool autoTracked = false, Location? location = null, bool giftedItem = false, bool silent = false, bool force = false); /// /// Tracks the specifies item and clears it from the specified dungeon. @@ -41,7 +42,8 @@ bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bo /// /// The dungeon the item was tracked in. /// The speech recognition confidence. - void TrackItemFrom(Item item, IHasTreasure hasTreasure, string? trackedAs = null, float? confidence = null); + /// If the item should be forced to be tracked while auto tracking + void TrackItemFrom(Item item, IHasTreasure hasTreasure, string? trackedAs = null, float? confidence = null, bool force = false); /// /// Tracks the specified item and clears it from the specified room. @@ -52,7 +54,8 @@ bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bo /// /// The area the item was found in. /// The speech recognition confidence. - void TrackItemFrom(Item item, IHasLocations area, string? trackedAs = null, float? confidence = null); + /// If the item should be forced to be tracked while auto tracking + void TrackItemFrom(Item item, IHasLocations area, string? trackedAs = null, float? confidence = null, bool force = false); /// /// Sets the item count for the specified item. @@ -62,7 +65,8 @@ bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bo /// The amount of the item that is in the player's inventory now. /// /// The speech recognition confidence. - void TrackItemAmount(Item item, int count, float confidence); + /// If the item should be forced to be tracked while auto tracking + void TrackItemAmount(Item item, int count, float confidence, bool force = false); /// /// Tracks multiple items at the same time @@ -77,5 +81,6 @@ bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bo /// /// The item to untrack. /// The speech recognition confidence. - void UntrackItem(Item item, float? confidence = null); + /// If the item should be forced to be untracked while auto tracking + void UntrackItem(Item item, float? confidence = null, bool force = false); } diff --git a/src/TrackerCouncil.Smz3.Data/Configuration/ConfigFiles/ResponseConfig.cs b/src/TrackerCouncil.Smz3.Data/Configuration/ConfigFiles/ResponseConfig.cs index 3d53e0549..30c04b703 100644 --- a/src/TrackerCouncil.Smz3.Data/Configuration/ConfigFiles/ResponseConfig.cs +++ b/src/TrackerCouncil.Smz3.Data/Configuration/ConfigFiles/ResponseConfig.cs @@ -12,45 +12,45 @@ public class ResponseConfig : IMergeable, IConfigFile /// Gets the phrases to respond with when tracker starts. - /// = new() + /// public SchrodingersString? StartedTracking { get; init; } /// /// Gets the phrases to respond with when tracker starts in "alternate" /// mode. - /// = new() + /// public SchrodingersString? StartingTrackingAlternate { get; init; } /// /// Gets the phrases to respond with when tracker stops. - /// = new() + /// public SchrodingersString? StoppedTracking { get; init; } /// /// Gets the phrases to respond with when tracker stops after go mode /// has been turned on. - /// = new() + /// public SchrodingersString? StoppedTrackingPostGoMode { get; init; } /// /// Gets the phrases to respond with when speech recognition confidence /// does not meet the configured threshold for execution, but is high /// enough to be recognized. - /// = new() + /// public SchrodingersString? Misheard { get; init; } /// /// Gets the phrases to respond with when tracking a simple single-stage /// item. /// {0} is a placeholder for the name of the item. - /// = new() + /// public SchrodingersString? TrackedItem { get; init; } /// /// Gets the phrases to respond with when tracking two items at once. /// {0} is a placeholder for the name of the first item. /// {1} is a placeholder for the name of the second item. - /// = new() + /// public SchrodingersString? TrackedTwoItems { get; init; } /// @@ -58,7 +58,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the first item. /// {1} is a placeholder for the name of the second item. /// {2} is a placeholder for the name of the third item. - /// = new() + /// public SchrodingersString? TrackedThreeItems { get; init; } /// @@ -66,7 +66,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the first item. /// {1} is a placeholder for the name of the second item. /// {2} is the number of remaining items tracked. - /// = new() + /// public SchrodingersString? TrackedManyItems { get; init; } /// @@ -75,7 +75,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the base item name (e.g. Sword), /// {1} is a placeholder for the current stage of the progressive /// item (e.g. Master Sword). - /// = new() + /// public SchrodingersString? TrackedItemByStage { get; init; } /// @@ -83,7 +83,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the plural item name. {1} is /// a placeholder for the number of copies. - /// = new() + /// public SchrodingersString? TrackedItemMultiple { get; init; } /// @@ -91,7 +91,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the base item name (e.g. Sword), /// {1} is a placeholder for the current stage of the progressive /// item (e.g. Master Sword). - /// = new() + /// public SchrodingersString? TrackedProgressiveItem { get; init; } /// @@ -101,26 +101,26 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the base item name (e.g. Sword), /// {1} is a placeholder for the current stage of the progressive /// item (e.g. Master Sword). - /// = new() + /// public SchrodingersString? TrackedOlderProgressiveItem { get; init; } /// /// Gets the phrases to respond with when tracking an item that is /// already at the max tier. - /// = new() + /// public SchrodingersString? TrackedTooManyOfAnItem { get; init; } /// /// Gets the phrases to respond with when tracking a single-stage item /// that is already tracked. /// {0} is a placeholder for the name of the item. - /// = new() + /// public SchrodingersString? TrackedAlreadyTrackedItem { get; init; } /// /// Gets the phrases to respond with when tracking an item that is at /// its correct location according to the original game. - /// = new() + /// public SchrodingersString? TrackedVanillaItem { get; init; } /// @@ -128,19 +128,19 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is the plural name of the item. {1} is the number /// of items. - /// = new() + /// public SchrodingersString? TrackedExactAmountDuplicate { get; init; } /// /// Gets the phrases to respond with when tracking multiple items in an /// area at once. - /// = new() + /// public SchrodingersString? TrackedMultipleItems { get; init; } /// /// Gets the phrases to respond with when clearing multiple items in an /// area at once. - /// = new() + /// public SchrodingersString? ClearedMultipleItems { get; init; } /// @@ -170,7 +170,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the area. - /// = new() + /// public SchrodingersString? TrackedNothing { get; init; } /// @@ -186,7 +186,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the item with "a"/"the". - /// = new() + /// public SchrodingersString? UntrackedItem { get; init; } /// @@ -196,7 +196,7 @@ public class ResponseConfig : IMergeable, IConfigFile{1} is a placeholder for the name of the location that /// contains the item that is out of logic. {2} is a placeholder /// for one or more names of required items that are missing. - /// = new() + /// public SchrodingersString? TrackedOutOfLogicItem { get; init; } /// @@ -205,7 +205,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item was tracked. /// {1} is a placeholder for the name of the location that /// contains the item that is out of logic. - /// = new() + /// public SchrodingersString? TrackedOutOfLogicItemTooManyMissing { get; init; } /// @@ -213,7 +213,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the item with "a"/"the". - /// = new() + /// public SchrodingersString? UntrackedNothing { get; init; } /// @@ -221,7 +221,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the item with "a"/"the". - /// = new() + /// public SchrodingersString? UntrackedProgressiveItem { get; init; } /// @@ -229,7 +229,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the item with "a"/"the". - /// = new() + /// public SchrodingersString? UntrackedItemMultiple { get; init; } /// @@ -237,38 +237,38 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the item with "a"/"the". - /// = new() + /// public SchrodingersString? UntrackedItemMultipleLast { get; init; } /// /// Gets the phrases to respond with when Shaktool becomes available. - /// = new() + /// public SchrodingersString? ShaktoolAvailable { get; init; } /// /// Gets the phrases to respond with when Peg World becomes available. - /// = new() + /// public SchrodingersString? PegWorldAvailable { get; init; } /// /// Gets the phrases to respond with when Peg World mode is toggled on. - /// = new() + /// public SchrodingersString? PegWorldModeOn { get; init; } /// /// Gets the phrases to respond with when pegging a single Peg World peg. - /// = new() + /// public SchrodingersString? PegWorldModePegged { get; init; } /// /// Gets the phrases to respond with when pegging multiple Peg World pegs. - /// = new() + /// public Dictionary? PegWorldModePeggedMultiple { get; init; } /// /// Gets the phrases to respond with when all Peg World pegs have been /// pegged or Peg World mode is toggled off manually. - /// = new() + /// public SchrodingersString? PegWorldModeDone { get; init; } /// @@ -276,7 +276,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon. {1} /// is a placeholder for the name of the reward that was marked. - /// = new() + /// public SchrodingersString? DungeonRewardMarked { get; init; } /// @@ -284,27 +284,27 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the reward that was /// marked. - /// = new() + /// public SchrodingersString? RemainingDungeonsMarked { get; init; } /// /// Gets the phrases to respond with when there are no unmarked /// dungeons. - /// = new() + /// public SchrodingersString? NoRemainingDungeons { get; init; } /// /// Gets the phrases to respond with when clearing all locations in a /// dungeon. /// {0} is a placeholder for the name of the dungeon. - /// = new() + /// public SchrodingersString? DungeonCleared { get; init; } /// /// Gets the phrases to respond with when clearing all location in a /// dungeon, but all locations are already cleared. /// {0} is a placeholder for the name of the dungeon. - /// = new() + /// public SchrodingersString? DungeonAlreadyCleared { get; init; } /// @@ -314,7 +314,7 @@ public class ResponseConfig : IMergeable, IConfigFile{2} is a placeholder for the items that are required for a /// missed location. - /// = new() + /// public SchrodingersString? DungeonClearedWithInaccessibleItems { get; init; } /// @@ -322,14 +322,14 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon. {1} /// is a placeholder for the name of a location that was missed. - /// = new() + /// public SchrodingersString? DungeonClearedWithTooManyInaccessibleItems { get; init; } /// /// Gets the phrases to respond with when clearing a dungeon. /// {0} is a placeholder for the name of the dungeon that was /// cleared. {1} is a placeholder for the boss of the dungeon. - /// = new() + /// public SchrodingersString? DungeonBossCleared { get; init; } /// @@ -337,7 +337,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon that was /// cleared. {1} is a placeholder for the boss of the dungeon. - /// = new() + /// public SchrodingersString? DungeonBossAlreadyCleared { get; init; } /// @@ -345,7 +345,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon. {1} /// is a placeholder for the boss of the dungeon. - /// = new() + /// public SchrodingersString? DungeonBossUncleared { get; init; } /// @@ -353,13 +353,13 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon. {1} /// is a placeholder for the boss of the dungeon. - /// = new() + /// public SchrodingersString? DungeonBossNotYetCleared { get; init; } /// /// Gets the phrases to respond with when the player defeated a boss /// with remarkable skill and add content! - /// = new() + /// public SchrodingersString? DungeonBossClearedAddContent { get; init; } /// @@ -367,14 +367,14 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the medallion. /// {1} is a placeholder for the name of the dungeon. - /// = new() + /// public SchrodingersString? DungeonRequirementMarked { get; init; } /// /// Gets the phrases to respond with when marking the wrong dungeon with /// a required medallion. /// {0} is a placeholder for the name of the dungeon. - /// = new() + /// public SchrodingersString? DungeonRequirementInvalid { get; init; } /// @@ -384,7 +384,7 @@ public class ResponseConfig : IMergeable, IConfigFile{1} is a placeholder for the name of the dungeon. /// {2} is a placeholder for the name of the medallion that was /// tracked. - /// = new() + /// public SchrodingersString? DungeonRequirementMismatch { get; init; } /// @@ -402,7 +402,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon. {1} /// is the actual amount of items left. {2} is the amount of /// items requested to clear. - /// = new() + /// public SchrodingersString? DungeonTooManyTreasuresTracked { get; init; } /// @@ -411,14 +411,14 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the dungeon. {1} /// is a placeholder for the name of the item, including "a" or "the", /// as appropriate. - /// = new() + /// public SchrodingersString? ItemTrackedInIncorrectDungeon { get; init; } /// /// Gets the phrases to respond with when marking an item at a location. /// {0} is a placeholder for the name of the location. {1} /// is a placeholder for the name of the item. - /// = new() + /// public SchrodingersString? LocationMarked { get; init; } /// @@ -428,26 +428,34 @@ public class ResponseConfig : IMergeable, IConfigFile{2} is a /// placeholder for the name of the item that was previously marked /// here. - /// = new() + /// public SchrodingersString? LocationMarkedAgain { get; init; } /// /// Gets the phrases to respond with when marking an item as /// nothing/bullshit. /// {0} is a placeholder for the name of the location. - /// = new() + /// public SchrodingersString? LocationMarkedAsBullshit { get; init; } + /// + /// Gets the phrases to respond with when attempting to make an item at a location, but that location has already + /// been cleared. + /// {0} is a placeholder for the name of the location. {1} + /// is a placeholder for the name of the item. + /// + public SchrodingersString? LocationMarkedButAlreadyCleared { get; set; } + /// /// Gets the phrases to respond with when marking an item at a location that was preconfigured. /// {0} is a placeholder for the name of the location. - /// = new() + /// public SchrodingersString? LocationMarkedPreConfigured { get; init; } /// /// Gets the phrases to respond with when tracking an item at a location that was preconfigured. /// {0} is a placeholder for the name of the location. - /// = new() + /// public SchrodingersString? TrackedPreConfigured { get; init; } /// @@ -457,24 +465,24 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the item that was tracked or marked. /// {1} is a placeholder for the item that was in the same /// location in the seed. - /// = new() + /// public SchrodingersString? LocationHasDifferentItem { get; init; } /// /// Gets the phrases to respond with when clearing a location. /// {0} is a placeholder for the name of the location. - /// = new() + /// public SchrodingersString? LocationCleared { get; init; } /// /// Gets the phrases to respond with when clearing multiple locations. /// {0} is a placeholder for the number of locations. - /// = new() + /// public SchrodingersString? LocationsCleared { get; init; } /// /// Gets the phrases to respond with when trying to clear the last marked locations when there aren't any - /// = new() + /// public SchrodingersString? NoMarkedLocations { get; init; } /// @@ -482,7 +490,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the number of locations. /// {1} is a placeholder for the name of the region - /// = new() + /// public SchrodingersString? LocationsClearedSameRegion { get; init; } /// @@ -492,7 +500,7 @@ public class ResponseConfig : IMergeable, IConfigFile /// Gets the phrases to respond with when undoing Go Mode. - /// = new() + /// public SchrodingersString? GoModeToggledOff { get; init; } /// @@ -501,7 +509,7 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the location. {2} is a /// placeholder for the name of the item, including "a"/"the". - /// = new() + /// public SchrodingersString? AreaDoesNotHaveItem { get; init; } /// @@ -510,102 +518,108 @@ public class ResponseConfig : IMergeable, IConfigFile{0} is a placeholder for the name of the item. {1} is /// a placeholder for the name of the location. {2} is a /// placeholder for the name of the item, including "a"/"the". - /// = new() + /// public SchrodingersString? AreaHasMoreThanOneItem { get; init; } /// /// Gets the phrases to respond with after tracking an item that doesn't /// open up new areas. - /// = new() + /// public SchrodingersString? TrackedUselessItem { get; init; } /// /// Gets the phrases to respond with when counting Hyper Beam shots. - /// = new() + /// public Dictionary? CountHyperBeamShots { get; init; } /// /// Gets the phrases to respond with when an internal error occurs. - /// = new() + /// public SchrodingersString? Error { get; init; } + /// + /// Response to say when attempting to manually track something when autotracking is enabled + /// {0} is a placeholder for the command that the user can say to force tracker to do the action. + /// + public SchrodingersString? AutoTrackingEnabledSass { get; init; } + /// /// Gets the phrases to respond with before undoing the last action. - /// = new() + /// public SchrodingersString? ActionUndone { get; init; } /// /// Gets the phrases to respond with when there is nothing to undo. - /// = new() + /// public SchrodingersString? NothingToUndo { get; init; } /// /// Gets the phrases to respond with when the latest undo action /// has expired - /// = new() + /// public SchrodingersString? UndoExpired { get; init; } /// /// Gets the phrases to respond with when changing a Tracker setting. /// {0} is a placeholder for the name of the setting that was /// changed. {1} is a placeholder for the new value. - /// = new() + /// public SchrodingersString? TrackerSettingChanged { get; init; } /// /// Gets the phrases to respond with when marking a boss as defeated. /// {0} is a placeholder for the name of the boss. - /// = new() + /// public SchrodingersString? BossDefeated { get; init; } /// /// Gets the phrases to respond with when marking a boss as defeated who /// was already marked. /// {0} is a placeholder for the name of the boss. - /// = new() + /// public SchrodingersString? BossAlreadyDefeated { get; init; } /// /// Gets the phrases to respond with when un-marking a boss as defeated. /// {0} is a placeholder for the name of the boss. - /// = new() + /// public SchrodingersString? BossUndefeated { get; init; } /// /// Gets the phrases to respond with when un-marking a boss as defeated /// who hasn't been defeated yet. /// {0} is a placeholder for the name of the boss. - /// = new() + /// public SchrodingersString? BossNotYetDefeated { get; init; } /// /// Gets the phrases to respond with when the timer is resumed - /// = new() + /// public SchrodingersString? TimerResumed { get; init; } /// /// Gets the phrases to respond with when the timer is reset - /// = new() + /// public SchrodingersString? TimerReset { get; init; } /// /// Gets the phrases to respond with when the timer is paused - /// = new() + /// public SchrodingersString? TimerPaused { get; init; } /// /// Gets the phrases to respond with when tracker is muted - /// = new() + /// public SchrodingersString? Muted { get; init; } /// /// Gets the phrases to respond with when tracker is unmuted - /// = new() + /// public SchrodingersString? Unmuted { get; init; } /// /// Gets the phrases to respond with when the game is beaten - /// = new() + /// public SchrodingersString? BeatGame { get; init; } /// diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Item.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Item.cs index 6b3f6d62c..5a957e6ab 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Item.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Item.cs @@ -327,6 +327,11 @@ public void UpdateItemType(ItemType type) /// A string representing this item. public override string ToString() => $"{Name}"; + /// + /// Returns a random name from the items's metadata + /// + public string RandomName => Metadata.Name?.ToString() ?? Name; + private static List Copies(int nr, Func template) { return Enumerable.Range(1, nr).Select(i => template()).ToList(); diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs index 5fb354d83..57f022bf6 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs @@ -401,8 +401,8 @@ public string RandomName { var randomLocationName = Metadata.Name?.ToString() ?? Name; return Room != null - ? $"{Room.RandomName} - {randomLocationName}" - : $"{Region.RandomName} - {randomLocationName}"; + ? $"{Room.RandomAreaName} - {randomLocationName}" + : $"{Region.RandomAreaName} - {randomLocationName}"; } } diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasBoss.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasBoss.cs index fcd869c6f..400cd7510 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasBoss.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasBoss.cs @@ -90,7 +90,7 @@ public void ApplyState(TrackerState? state) /// /// Returns a randomized name from the metadata for the region /// - public string RandomRegionName => Region.RandomName; + public string RandomRegionName => Region.RandomAreaName; /// /// Returns a randomized name from the metadata for the boss diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasLocations.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasLocations.cs index 9fa9366fa..99242fcb7 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasLocations.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasLocations.cs @@ -42,4 +42,6 @@ public bool IsKeysanityForArea return Region is SMRegion && Region.Config.MetroidKeysanity; } } + + public string RandomAreaName => this is Room room ? room.RandomAreaName : Region?.Name ?? Name; } diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasTreasure.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasTreasure.cs index 88818b12f..109d60f80 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasTreasure.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/IHasTreasure.cs @@ -76,6 +76,11 @@ public void ApplyState(TrackerState? state) } } + /// + /// Returns a random name from the region's metadata + /// + public string RandomRegionName => Metadata.Name?.ToString() ?? Name; + event EventHandler? UpdatedTreasure; void OnUpdatedTreasure(); diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/Region.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/Region.cs index d14cf1180..660098b95 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/Region.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/Region.cs @@ -156,7 +156,7 @@ private bool MatchesItemPlacementRule(Item item) /// /// Returns a random string from the region's metadata /// - public string RandomName => Metadata.Name?.ToString() ?? Name; + public string RandomAreaName => Metadata.Name?.ToString() ?? Name; /// /// Determines whether the region can be entered with the specified diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Room.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Room.cs index aa79803f8..74d471477 100644 --- a/src/TrackerCouncil.Smz3.Data/WorldData/Room.cs +++ b/src/TrackerCouncil.Smz3.Data/WorldData/Room.cs @@ -76,5 +76,5 @@ public Room(Region region, string name, IMetadataService? metadata, params strin /// A new string that represents this room. public override string ToString() => $"{Region} - {Name}"; - public string RandomName => $"{Region.RandomName} - {Metadata.Name?.ToString() ?? Name}"; + public string RandomAreaName => $"{Region.RandomAreaName} - {Metadata.Name?.ToString() ?? Name}"; } diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs index 0cc8c9141..a87769b59 100644 --- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs +++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs @@ -13,7 +13,7 @@ internal class TrackerBossService(IPlayerProgressionService playerProgressionSer { public event EventHandler? BossUpdated; - public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool autoTracked = false, bool admittedGuilt = false) + public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool autoTracked = false, bool admittedGuilt = false, bool force = false) { if (region.BossDefeated && !autoTracked) { @@ -21,6 +21,12 @@ public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool a return; } + if (!autoTracked && Tracker.AutoTracker?.IsConnected == true && !force && region.BossType != BossType.None) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {region.RandomBossName}"]); + return; + } + List undoActions = []; var addedEvent = History.AddEvent( @@ -83,7 +89,7 @@ public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool a }); } - public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? confidence = null, bool autoTracked = false) + public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? confidence = null, bool autoTracked = false, bool force = false) { if (boss.Defeated) { @@ -92,6 +98,12 @@ public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? conf return; } + if (!autoTracked && Tracker.AutoTracker?.IsConnected == true && !force && boss.Type != BossType.None) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {boss.RandomName}"]); + return; + } + if (boss.Region != null) { MarkBossAsDefeated(boss.Region, confidence, autoTracked, admittedGuilt); @@ -127,7 +139,7 @@ public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? conf }); } - public void MarkBossAsNotDefeated(Boss boss, float? confidence = null) + public void MarkBossAsNotDefeated(Boss boss, float? confidence = null, bool force = false) { if (boss.Defeated != true) { @@ -135,6 +147,12 @@ public void MarkBossAsNotDefeated(Boss boss, float? confidence = null) return; } + if (Tracker.AutoTracker?.IsConnected == true && !force && boss.Type != BossType.None) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force untrack {boss.RandomName}"]); + return; + } + if (boss.Region != null) { MarkBossAsNotDefeated(boss.Region, confidence); @@ -162,7 +180,7 @@ public void MarkBossAsNotDefeated(Boss boss, float? confidence = null) /// /// The dungeon that should be un-cleared. /// The speech recognition confidence. - public void MarkBossAsNotDefeated(IHasBoss region, float? confidence = null) + public void MarkBossAsNotDefeated(IHasBoss region, float? confidence = null, bool force = false) { if (!region.BossDefeated) { @@ -170,6 +188,12 @@ public void MarkBossAsNotDefeated(IHasBoss region, float? confidence = null) return; } + if (Tracker.AutoTracker?.IsConnected == true && !force && region.BossType != BossType.None) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force untrack {region.RandomBossName}"]); + return; + } + region.BossDefeated = false; BossUpdated?.Invoke(this, new BossTrackedEventArgs(region.Boss, confidence, false)); Tracker.Say(response: Responses.DungeonBossUncleared, args: [region.RandomRegionName, region.RandomBossName]); diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs index 42fb58865..d30eb2cfd 100644 --- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs +++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs @@ -26,8 +26,14 @@ public override void Initialize() public event EventHandler? ItemTracked; - public bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bool tryClear = true, bool autoTracked = false, Location? location = null, bool giftedItem = false, bool silent = false) + public bool TrackItem(Item item, string? trackedAs = null, float? confidence = null, bool tryClear = true, bool autoTracked = false, Location? location = null, bool giftedItem = false, bool silent = false, bool force = false) { + if (!autoTracked && Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {item.RandomName}"]); + return false; + } + var didTrack = false; var accessibleBefore = worldQueryService.AccessibleLocations(false); var itemName = item.Name; @@ -239,9 +245,15 @@ public bool TrackItem(Item item, string? trackedAs = null, float? confidence = n return true; } - public void TrackItemFrom(Item item, IHasTreasure hasTreasure, string? trackedAs = null, float? confidence = null) + public void TrackItemFrom(Item item, IHasTreasure hasTreasure, string? trackedAs = null, float? confidence = null, bool force = false) { - if (!TrackItem(item, trackedAs, confidence, tryClear: false)) + if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {item.RandomName} from {hasTreasure.RandomRegionName}"]); + return; + } + + if (!TrackItem(item, trackedAs, confidence, tryClear: false, force: force)) { return; } @@ -273,8 +285,14 @@ public void TrackItemFrom(Item item, IHasTreasure hasTreasure, string? trackedAs }); } - public void TrackItemFrom(Item item, IHasLocations area, string? trackedAs = null, float? confidence = null) + public void TrackItemFrom(Item item, IHasLocations area, string? trackedAs = null, float? confidence = null, bool force = false) { + if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {item.RandomName} from {area.RandomAreaName}"]); + return; + } + var locations = area.Locations .Where(x => x.Item.Type == item.Type) .ToImmutableList(); @@ -320,8 +338,14 @@ public void TrackItemFrom(Item item, IHasLocations area, string? trackedAs = nul }); } - public void TrackItemAmount(Item item, int count, float confidence) + public void TrackItemAmount(Item item, int count, float confidence, bool force = false) { + if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {count} {item.Metadata.Plural}"]); + return; + } + var newItemCount = count; if (item.Metadata.CounterMultiplier > 1 && count % item.Metadata.CounterMultiplier == 0) @@ -384,8 +408,14 @@ public void TrackItems(List items, bool autoTracked, bool giftedItem) RestartIdleTimers(); } - public void UntrackItem(Item item, float? confidence = null) + public void UntrackItem(Item item, float? confidence = null, bool force = false) { + if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) + { + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force untrack {item.RandomName}"]); + return; + } + var originalTrackingState = item.TrackingState; playerProgressionService.ResetProgression(); diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs index b67dbb5e5..2d63d4679 100644 --- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs +++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs @@ -247,6 +247,12 @@ public void MarkLocation(Location location, ItemType item, float? confidence = n metadata ??= metadataService.Item(item); + if (location.Cleared) + { + Tracker.Say(response: Responses.LocationMarkedButAlreadyCleared, args: [locationName, metadata?.Name ?? item.GetDescription() ]); + return; + } + GiveLocationComment(location.Item.Type, location, isTracking: false, confidence, metadata); if (item == ItemType.Nothing) diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs index a048216da..411b05998 100644 --- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs +++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs @@ -33,11 +33,13 @@ private GrammarBuilder GetMarkBossAsDefeatedRule() var bossNames = GetBossNames(); var beatBoss = new GrammarBuilder() .Append("Hey tracker,") + .Optional("force", "sudo") .OneOf("track", "I beat", "I defeated", "I beat off", "I killed") .Append(BossKey, bossNames); var markBoss = new GrammarBuilder() .Append("Hey tracker,") + .Optional("force", "sudo") .Append("mark") .Append(BossKey, bossNames) .Append("as") @@ -48,6 +50,8 @@ private GrammarBuilder GetMarkBossAsDefeatedRule() .Append(BossKey, bossNames) .OneOf("is dead", "is fucking dead"); + + return GrammarBuilder.Combine(beatBoss, markBoss, bossIsDead); } @@ -58,17 +62,24 @@ private GrammarBuilder GetMarkBossAsNotDefeatedRule() var markBoss = new GrammarBuilder() .Append("Hey tracker,") + .Optional("force", "sudo") .Append("mark") .Append(BossKey, bossNames) .Append("as") .OneOf("alive", "not defeated", "undefeated"); + var untrack = new GrammarBuilder() + .Append("Hey tracker,") + .Optional("force", "sudo") + .Append("untrack") + .Append(BossKey, bossNames); + var bossIsAlive = new GrammarBuilder() .Append("Hey tracker,") .Append(BossKey, bossNames) .OneOf("is alive", "is still alive"); - return GrammarBuilder.Combine(markBoss, bossIsAlive); + return GrammarBuilder.Combine(markBoss, untrack, bossIsAlive); } [SupportedOSPlatform("windows")] @@ -100,29 +111,34 @@ public override void AddCommands() var admittedGuilt = result.Text.ContainsAny("killed", "beat", "defeated", "dead") && !result.Text.ContainsAny("beat off", "beaten off"); + var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + if (boss.Region != null) { // Track boss with associated dungeon or region - TrackerBase.BossTracker.MarkBossAsDefeated(boss.Region, result.Confidence, false, admittedGuilt); + TrackerBase.BossTracker.MarkBossAsDefeated(boss.Region, result.Confidence, false, admittedGuilt, force); return; } // Track standalone boss - TrackerBase.BossTracker.MarkBossAsDefeated(boss, admittedGuilt, result.Confidence); + TrackerBase.BossTracker.MarkBossAsDefeated(boss, admittedGuilt, result.Confidence, force); }); AddCommand("Mark boss as alive", GetMarkBossAsNotDefeatedRule(), (result) => { var boss = GetBossFromResult(TrackerBase, result) ?? throw new Exception($"Could not find boss or dungeon in command: '{result.Text}'"); + + var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + if (boss.Region != null) { // Untrack boss with associated dungeon or region - TrackerBase.BossTracker.MarkBossAsNotDefeated(boss.Region, result.Confidence); + TrackerBase.BossTracker.MarkBossAsNotDefeated(boss.Region, result.Confidence, force); return; } // Untrack standalone boss - TrackerBase.BossTracker.MarkBossAsNotDefeated(boss, result.Confidence); + TrackerBase.BossTracker.MarkBossAsNotDefeated(boss, result.Confidence, force); }); AddCommand("Mark boss as defeated with content", GetBossDefeatedWithContentRule(), (result) => diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs index 2c34d6789..0f7af767b 100644 --- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs +++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using TrackerCouncil.Smz3.Abstractions; +using TrackerCouncil.Smz3.Shared; using TrackerCouncil.Smz3.Tracking.Services; namespace TrackerCouncil.Smz3.Tracking.VoiceCommands; @@ -46,7 +47,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) var trackItemNormal = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly") + .Optional("please", "would you kindly", "force", "sudo") .OneOf("track", "add") .Append(ItemNameKey, itemNames); @@ -54,7 +55,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) { var trackItemDungeon = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly") + .Optional("please", "would you kindly", "force", "sudo") .OneOf("track", "add") .Append(ItemNameKey, itemNames) .OneOf("in", "from") @@ -62,7 +63,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) var trackItemLocation = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly") + .Optional("please", "would you kindly", "force", "sudo") .OneOf("track", "add") .Append(ItemNameKey, itemNames) .OneOf("in", "from", "in the", "from the") @@ -70,7 +71,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) var trackItemRoom = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly") + .Optional("please", "would you kindly", "force", "sudo") .OneOf("track", "add") .Append(ItemNameKey, itemNames) .OneOf("in", "from", "in the", "from the") @@ -155,14 +156,14 @@ private GrammarBuilder GetUntrackItemRule() var untrackItem = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly") + .Optional("please", "would you kindly", "force", "sudo") .OneOf("untrack", "remove") .Optional("a", "an", "the") .Append(ItemNameKey, itemNames); var toggleItemOff = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly") + .Optional("please", "would you kindly", "force", "sudo") .Append("toggle") .Append(ItemNameKey, itemNames) .Append("off"); @@ -180,7 +181,8 @@ private GrammarBuilder GetSetItemCountRule() return new GrammarBuilder() .Append("Hey tracker,") - .OneOf("I have", "I've got", "I possess", "I am in the possession of") + .Optional("force", "sudo") + .OneOf("I have", "I've got", "I possess", "I am in the possession of", "track") .Append(ItemCountKey, numbers) .Append(ItemNameKey, itemNames); } @@ -194,19 +196,23 @@ public override void AddCommands() { var item = GetItemFromResult(TrackerBase, result, out var itemName); + var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + if (result.Semantics.ContainsKey(DungeonKey)) { var dungeon = GetDungeonFromResult(TrackerBase, result); TrackerBase.ItemTracker.TrackItemFrom(item, dungeon, trackedAs: itemName, - confidence: result.Confidence); + confidence: result.Confidence, + force: force); } else if (result.Semantics.ContainsKey(RoomKey)) { var room = GetRoomFromResult(TrackerBase, result); TrackerBase.ItemTracker.TrackItemFrom(item, room, trackedAs: itemName, - confidence: result.Confidence); + confidence: result.Confidence, + force: force); } else if (result.Semantics.ContainsKey(LocationKey)) { @@ -216,13 +222,15 @@ public override void AddCommands() confidence: result.Confidence, tryClear: true, autoTracked: false, - location: location); + location: location, + force: force); } else { TrackerBase.ItemTracker.TrackItem(item, trackedAs: itemName, - confidence: result.Confidence); + confidence: result.Confidence, + force: force); } }); @@ -285,14 +293,16 @@ public override void AddCommands() AddCommand("Untrack an item", GetUntrackItemRule(), (result) => { var item = GetItemFromResult(TrackerBase, result, out _); - TrackerBase.ItemTracker.UntrackItem(item, result.Confidence); + var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + TrackerBase.ItemTracker.UntrackItem(item, result.Confidence, force: force); }); AddCommand("Set item count", GetSetItemCountRule(), (result) => { var item = GetItemFromResult(TrackerBase, result, out _); var count = (int)result.Semantics[ItemCountKey].Value; - TrackerBase.ItemTracker.TrackItemAmount(item, count, result.Confidence); + var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + TrackerBase.ItemTracker.TrackItemAmount(item, count, result.Confidence, force: force); }); } } From 0d7d82c36044baa8fceab230db88bfd0ce499e7a Mon Sep 17 00:00:00 2001 From: MattEqualsCoder Date: Thu, 19 Dec 2024 22:21:53 -0500 Subject: [PATCH 2/2] Update prompts to further prevent tracker from doing things incorrectly --- .../TrackingServices/TrackerBossService.cs | 8 +++---- .../TrackingServices/TrackerItemService.cs | 10 ++++---- .../VoiceCommands/BossTrackingModule.cs | 14 +++++------ .../VoiceCommands/GrammarBuilder.cs | 2 ++ .../VoiceCommands/ItemTrackingModule.cs | 23 ++++++++++--------- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs index a87769b59..91810b0d7 100644 --- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs +++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerBossService.cs @@ -23,7 +23,7 @@ public void MarkBossAsDefeated(IHasBoss region, float? confidence = null, bool a if (!autoTracked && Tracker.AutoTracker?.IsConnected == true && !force && region.BossType != BossType.None) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {region.RandomBossName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please track {region.RandomBossName}"]); return; } @@ -100,7 +100,7 @@ public void MarkBossAsDefeated(Boss boss, bool admittedGuilt = true, float? conf if (!autoTracked && Tracker.AutoTracker?.IsConnected == true && !force && boss.Type != BossType.None) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {boss.RandomName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please track {boss.RandomName}"]); return; } @@ -149,7 +149,7 @@ public void MarkBossAsNotDefeated(Boss boss, float? confidence = null, bool forc if (Tracker.AutoTracker?.IsConnected == true && !force && boss.Type != BossType.None) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force untrack {boss.RandomName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please untrack {boss.RandomName}"]); return; } @@ -190,7 +190,7 @@ public void MarkBossAsNotDefeated(IHasBoss region, float? confidence = null, boo if (Tracker.AutoTracker?.IsConnected == true && !force && region.BossType != BossType.None) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force untrack {region.RandomBossName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please untrack {region.RandomBossName}"]); return; } diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs index d30eb2cfd..9e353ddca 100644 --- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs +++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs @@ -30,7 +30,7 @@ public bool TrackItem(Item item, string? trackedAs = null, float? confidence = n { if (!autoTracked && Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {item.RandomName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please track {item.RandomName}"]); return false; } @@ -249,7 +249,7 @@ public void TrackItemFrom(Item item, IHasTreasure hasTreasure, string? trackedAs { if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {item.RandomName} from {hasTreasure.RandomRegionName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please track {item.RandomName} from {hasTreasure.RandomRegionName}"]); return; } @@ -289,7 +289,7 @@ public void TrackItemFrom(Item item, IHasLocations area, string? trackedAs = nul { if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {item.RandomName} from {area.RandomAreaName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please track {item.RandomName} from {area.RandomAreaName}"]); return; } @@ -342,7 +342,7 @@ public void TrackItemAmount(Item item, int count, float confidence, bool force = { if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force track {count} {item.Metadata.Plural}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please track {count} {item.Metadata.Plural}"]); return; } @@ -412,7 +412,7 @@ public void UntrackItem(Item item, float? confidence = null, bool force = false) { if (Tracker.AutoTracker?.IsConnected == true && !force && item.Type != ItemType.Nothing) { - Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, force untrack {item.RandomName}"]); + Tracker.Say(response: Responses.AutoTrackingEnabledSass, args: [$"Hey tracker, would you please untrack {item.RandomName}"]); return; } diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs index 411b05998..18b8b082e 100644 --- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs +++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/BossTrackingModule.cs @@ -33,13 +33,13 @@ private GrammarBuilder GetMarkBossAsDefeatedRule() var bossNames = GetBossNames(); var beatBoss = new GrammarBuilder() .Append("Hey tracker,") - .Optional("force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers) .OneOf("track", "I beat", "I defeated", "I beat off", "I killed") .Append(BossKey, bossNames); var markBoss = new GrammarBuilder() .Append("Hey tracker,") - .Optional("force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers) .Append("mark") .Append(BossKey, bossNames) .Append("as") @@ -50,8 +50,6 @@ private GrammarBuilder GetMarkBossAsDefeatedRule() .Append(BossKey, bossNames) .OneOf("is dead", "is fucking dead"); - - return GrammarBuilder.Combine(beatBoss, markBoss, bossIsDead); } @@ -62,7 +60,7 @@ private GrammarBuilder GetMarkBossAsNotDefeatedRule() var markBoss = new GrammarBuilder() .Append("Hey tracker,") - .Optional("force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers) .Append("mark") .Append(BossKey, bossNames) .Append("as") @@ -70,7 +68,7 @@ private GrammarBuilder GetMarkBossAsNotDefeatedRule() var untrack = new GrammarBuilder() .Append("Hey tracker,") - .Optional("force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers) .Append("untrack") .Append(BossKey, bossNames); @@ -111,7 +109,7 @@ public override void AddCommands() var admittedGuilt = result.Text.ContainsAny("killed", "beat", "defeated", "dead") && !result.Text.ContainsAny("beat off", "beaten off"); - var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + var force = result.Text.ContainsAny(GrammarBuilder.ForceCommandIdentifiers); if (boss.Region != null) { @@ -128,7 +126,7 @@ public override void AddCommands() { var boss = GetBossFromResult(TrackerBase, result) ?? throw new Exception($"Could not find boss or dungeon in command: '{result.Text}'"); - var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + var force = result.Text.ContainsAny(GrammarBuilder.ForceCommandIdentifiers); if (boss.Region != null) { diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/GrammarBuilder.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/GrammarBuilder.cs index c12790646..8c1a3238d 100644 --- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/GrammarBuilder.cs +++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/GrammarBuilder.cs @@ -11,6 +11,8 @@ namespace TrackerCouncil.Smz3.Tracking.VoiceCommands; /// public class GrammarBuilder { + public static string[] ForceCommandIdentifiers = ["would you please", "please, I'm begging you"]; + private readonly System.Speech.Recognition.GrammarBuilder _grammar = null!; private readonly List _elements; diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs index 0f7af767b..8be81890f 100644 --- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs +++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs @@ -1,4 +1,5 @@ -using System.Runtime.Versioning; +using System.Linq; +using System.Runtime.Versioning; using System.Speech.Recognition; using Microsoft.Extensions.Logging; @@ -47,7 +48,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) var trackItemNormal = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly", "force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray()) .OneOf("track", "add") .Append(ItemNameKey, itemNames); @@ -55,7 +56,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) { var trackItemDungeon = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly", "force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray()) .OneOf("track", "add") .Append(ItemNameKey, itemNames) .OneOf("in", "from") @@ -63,7 +64,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) var trackItemLocation = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly", "force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray()) .OneOf("track", "add") .Append(ItemNameKey, itemNames) .OneOf("in", "from", "in the", "from the") @@ -71,7 +72,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld) var trackItemRoom = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly", "force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray()) .OneOf("track", "add") .Append(ItemNameKey, itemNames) .OneOf("in", "from", "in the", "from the") @@ -156,14 +157,14 @@ private GrammarBuilder GetUntrackItemRule() var untrackItem = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly", "force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray()) .OneOf("untrack", "remove") .Optional("a", "an", "the") .Append(ItemNameKey, itemNames); var toggleItemOff = new GrammarBuilder() .Append("Hey tracker,") - .Optional("please", "would you kindly", "force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray()) .Append("toggle") .Append(ItemNameKey, itemNames) .Append("off"); @@ -181,7 +182,7 @@ private GrammarBuilder GetSetItemCountRule() return new GrammarBuilder() .Append("Hey tracker,") - .Optional("force", "sudo") + .Optional(GrammarBuilder.ForceCommandIdentifiers) .OneOf("I have", "I've got", "I possess", "I am in the possession of", "track") .Append(ItemCountKey, numbers) .Append(ItemNameKey, itemNames); @@ -196,7 +197,7 @@ public override void AddCommands() { var item = GetItemFromResult(TrackerBase, result, out var itemName); - var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + var force = result.Text.ContainsAny(GrammarBuilder.ForceCommandIdentifiers); if (result.Semantics.ContainsKey(DungeonKey)) { @@ -293,7 +294,7 @@ public override void AddCommands() AddCommand("Untrack an item", GetUntrackItemRule(), (result) => { var item = GetItemFromResult(TrackerBase, result, out _); - var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + var force = result.Text.ContainsAny(GrammarBuilder.ForceCommandIdentifiers); TrackerBase.ItemTracker.UntrackItem(item, result.Confidence, force: force); }); @@ -301,7 +302,7 @@ public override void AddCommands() { var item = GetItemFromResult(TrackerBase, result, out _); var count = (int)result.Semantics[ItemCountKey].Value; - var force = result.Text.ContainsAny("Hey tracker, force", "Hey tracker, sudo"); + var force = result.Text.ContainsAny(GrammarBuilder.ForceCommandIdentifiers); TrackerBase.ItemTracker.TrackItemAmount(item, count, result.Confidence, force: force); }); }