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..91810b0d7 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, would you please 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, would you please 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, would you please 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, would you please 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..9e353ddca 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, would you please 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, would you please 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, would you please 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, would you please 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, would you please 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..18b8b082e 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(GrammarBuilder.ForceCommandIdentifiers)
.OneOf("track", "I beat", "I defeated", "I beat off", "I killed")
.Append(BossKey, bossNames);
var markBoss = new GrammarBuilder()
.Append("Hey tracker,")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers)
.Append("mark")
.Append(BossKey, bossNames)
.Append("as")
@@ -58,17 +60,24 @@ private GrammarBuilder GetMarkBossAsNotDefeatedRule()
var markBoss = new GrammarBuilder()
.Append("Hey tracker,")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers)
.Append("mark")
.Append(BossKey, bossNames)
.Append("as")
.OneOf("alive", "not defeated", "undefeated");
+ var untrack = new GrammarBuilder()
+ .Append("Hey tracker,")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers)
+ .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 +109,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(GrammarBuilder.ForceCommandIdentifiers);
+
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(GrammarBuilder.ForceCommandIdentifiers);
+
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/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 2c34d6789..8be81890f 100644
--- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/ItemTrackingModule.cs
@@ -1,8 +1,10 @@
-using System.Runtime.Versioning;
+using System.Linq;
+using System.Runtime.Versioning;
using System.Speech.Recognition;
using Microsoft.Extensions.Logging;
using TrackerCouncil.Smz3.Abstractions;
+using TrackerCouncil.Smz3.Shared;
using TrackerCouncil.Smz3.Tracking.Services;
namespace TrackerCouncil.Smz3.Tracking.VoiceCommands;
@@ -46,7 +48,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld)
var trackItemNormal = new GrammarBuilder()
.Append("Hey tracker,")
- .Optional("please", "would you kindly")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray())
.OneOf("track", "add")
.Append(ItemNameKey, itemNames);
@@ -54,7 +56,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld)
{
var trackItemDungeon = new GrammarBuilder()
.Append("Hey tracker,")
- .Optional("please", "would you kindly")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray())
.OneOf("track", "add")
.Append(ItemNameKey, itemNames)
.OneOf("in", "from")
@@ -62,7 +64,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld)
var trackItemLocation = new GrammarBuilder()
.Append("Hey tracker,")
- .Optional("please", "would you kindly")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray())
.OneOf("track", "add")
.Append(ItemNameKey, itemNames)
.OneOf("in", "from", "in the", "from the")
@@ -70,7 +72,7 @@ private GrammarBuilder GetTrackItemRule(bool isMultiworld)
var trackItemRoom = new GrammarBuilder()
.Append("Hey tracker,")
- .Optional("please", "would you kindly")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray())
.OneOf("track", "add")
.Append(ItemNameKey, itemNames)
.OneOf("in", "from", "in the", "from the")
@@ -155,14 +157,14 @@ private GrammarBuilder GetUntrackItemRule()
var untrackItem = new GrammarBuilder()
.Append("Hey tracker,")
- .Optional("please", "would you kindly")
+ .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")
+ .Optional(GrammarBuilder.ForceCommandIdentifiers.Concat(["please", "would you kindly"]).ToArray())
.Append("toggle")
.Append(ItemNameKey, itemNames)
.Append("off");
@@ -180,7 +182,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(GrammarBuilder.ForceCommandIdentifiers)
+ .OneOf("I have", "I've got", "I possess", "I am in the possession of", "track")
.Append(ItemCountKey, numbers)
.Append(ItemNameKey, itemNames);
}
@@ -194,19 +197,23 @@ public override void AddCommands()
{
var item = GetItemFromResult(TrackerBase, result, out var itemName);
+ var force = result.Text.ContainsAny(GrammarBuilder.ForceCommandIdentifiers);
+
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 +223,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 +294,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(GrammarBuilder.ForceCommandIdentifiers);
+ 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(GrammarBuilder.ForceCommandIdentifiers);
+ TrackerBase.ItemTracker.TrackItemAmount(item, count, result.Confidence, force: force);
});
}
}