From 7aa92749c219ebc6d204bc602599d4ebe399fa5f Mon Sep 17 00:00:00 2001 From: stdNullPtr Date: Sun, 1 Jun 2025 20:20:57 +0300 Subject: [PATCH 1/3] feat: add interact key fishing mode support Implement configurable interact key mode as alternative to mouse-based fishing: - Add UseInteractKey and KeyboardKeyInteract config properties - Update ConfigValidator to validate interact key requirements - Modify FishingStateMachine to skip FindBobber state when using interact mode - Replace mouse right-click with configured interact key in CatchFish state - Update audio detection to work without bobber detection in interact mode - Add comprehensive logging for both traditional and interact modes - Update CLAUDE.md with interact key feature documentation Addresses issue #2 - provides bot-detection-safer alternative by eliminating mouse movement patterns while maintaining audio-based fish detection. --- CLAUDE.md | 16 ++++++++++++++++ Phishy/Configs/ConfigValidator.cs | 8 ++++++++ Phishy/Configs/Properties.cs | 8 ++++++++ Phishy/FishingStateMachine.cs | 31 ++++++++++++++++++++++++++----- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 64a47e3..7e8ccbf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -69,6 +69,22 @@ The audio detection system is critical for fish detection: - Resource disposal for COM objects - Exit key is END (not DEL) +### Interact Key Feature + +The bot supports two fishing modes: + +1. **Traditional Mode (default)**: Uses cursor detection + mouse clicks + - Detects bobber via cursor icon changes (EVENT_OBJECT_NAMECHANGE) + - Moves mouse in spiral pattern to find bobber + - Right-clicks on bobber to catch fish + +2. **Interact Key Mode**: Uses WoW's "Interact with Target" feature + - Set `use-interact-key: true` in configuration.yaml + - Configure `keyboard-key-interact` (default: f) + - Skips bobber detection entirely + - Uses keyboard interaction instead of mouse clicks + - Requires WoW expansion that supports interact feature (not available in vanilla) + ### Testing Audio Issues If audio detection isn't working: diff --git a/Phishy/Configs/ConfigValidator.cs b/Phishy/Configs/ConfigValidator.cs index c116acc..6087c4e 100644 --- a/Phishy/Configs/ConfigValidator.cs +++ b/Phishy/Configs/ConfigValidator.cs @@ -48,6 +48,14 @@ public static ValidationResult Validate(Properties properties) } } + if (properties.UseInteractKey) + { + if (string.IsNullOrWhiteSpace(properties.KeyboardKeyInteract)) + { + errors.Add("KeyboardKeyInteract is required when UseInteractKey is enabled"); + } + } + return new ValidationResult(errors); } } diff --git a/Phishy/Configs/Properties.cs b/Phishy/Configs/Properties.cs index 884a4ff..6701c5f 100644 --- a/Phishy/Configs/Properties.cs +++ b/Phishy/Configs/Properties.cs @@ -35,6 +35,12 @@ public sealed class Properties [YamlMember(Description = "Window name of the game, when you hover over it in the taskbar")] public string GameWindowName { get; set; } + [YamlMember(Description = "Use interact key instead of mouse clicking for fishing (requires WoW expansion with interact feature, Default: false)")] + public bool UseInteractKey { get; set; } + + [YamlMember(Description = "Keyboard key binding for interact with target (required if UseInteractKey is true, Default: f)")] + public string? KeyboardKeyInteract { get; set; } + public Properties() { KeyboardPressLogout = KeyboardUtils.ConvertToString(Keys.D3); @@ -46,5 +52,7 @@ public Properties() SecondLureBuffDurationMinutes = null; FishingChannelDurationSeconds = TimeSpan.FromSeconds(20).Seconds; GameWindowName = "Game Window Name"; + UseInteractKey = false; + KeyboardKeyInteract = KeyboardUtils.ConvertToString(Keys.F); } } \ No newline at end of file diff --git a/Phishy/FishingStateMachine.cs b/Phishy/FishingStateMachine.cs index bab74dc..84ce31c 100644 --- a/Phishy/FishingStateMachine.cs +++ b/Phishy/FishingStateMachine.cs @@ -123,7 +123,15 @@ public void Update(CancellationToken cancellationToken) case FishingState.CatchFish: Console.WriteLine("[FishingStateMachine]: You caught a fish!"); - MouseUtils.SendMouseInput(MouseButtons.Right); + if (AppConfig.Props.UseInteractKey) + { + Console.WriteLine($"[FishingStateMachine]: Using interact key: {AppConfig.Props.KeyboardKeyInteract}"); + KeyboardUtils.SendKeyInput(AppConfig.Props.KeyboardKeyInteract!); + } + else + { + MouseUtils.SendMouseInput(MouseButtons.Right); + } _isLineCast = false; Thread.Sleep(TimeSpan.FromSeconds(1)); @@ -178,7 +186,14 @@ private void TryTransition() case FishingState.CastLine: if (_isLineCast) { - TransitionTo(FishingState.FindBobber); + if (AppConfig.Props.UseInteractKey) + { + TransitionTo(FishingState.WaitAndCatch); + } + else + { + TransitionTo(FishingState.FindBobber); + } } break; case FishingState.FindBobber: @@ -269,7 +284,8 @@ private void ListenForFish(CancellationToken cancellationToken, TimeSpan timeout float maxSoundLevel = 0f; const float FISH_DETECTION_THRESHOLD = 0.1f; - Console.WriteLine($"[FishingStateMachine]: Starting to listen for fish splash (threshold: {FISH_DETECTION_THRESHOLD})..."); + string mode = AppConfig.Props.UseInteractKey ? "interact key" : "mouse click"; + Console.WriteLine($"[FishingStateMachine]: Starting to listen for fish splash (threshold: {FISH_DETECTION_THRESHOLD}, mode: {mode})..."); while (!cancellationToken.IsCancellationRequested) { @@ -290,11 +306,16 @@ private void ListenForFish(CancellationToken cancellationToken, TimeSpan timeout // Log every 2 seconds or when significant sound detected if (DateTime.Now - lastLogTime > TimeSpan.FromSeconds(2) || currentSoundLevel > 0.01f) { - Console.WriteLine($"[FishingStateMachine]: Listening... Bobber found: {bobberFound}, Current sound: {currentSoundLevel:F4}, Max sound: {maxSoundLevel:F4}, Checks: {checkCount}"); + string statusMsg = AppConfig.Props.UseInteractKey + ? $"Interact mode: Ready, Current sound: {currentSoundLevel:F4}, Max sound: {maxSoundLevel:F4}, Checks: {checkCount}" + : $"Bobber found: {bobberFound}, Current sound: {currentSoundLevel:F4}, Max sound: {maxSoundLevel:F4}, Checks: {checkCount}"; + Console.WriteLine($"[FishingStateMachine]: Listening... {statusMsg}"); lastLogTime = DateTime.Now; } - if (bobberFound && currentSoundLevel > FISH_DETECTION_THRESHOLD) + bool canDetectFish = AppConfig.Props.UseInteractKey || bobberFound; + + if (canDetectFish && currentSoundLevel > FISH_DETECTION_THRESHOLD) { Console.WriteLine($"[FishingStateMachine]: FISH DETECTED! Sound level: {currentSoundLevel:F4} (threshold: {FISH_DETECTION_THRESHOLD})"); _isBobberDipped = true; From c662ca485b62305be95e4268f11554864ec47dff Mon Sep 17 00:00:00 2001 From: stdNullPtr Date: Sun, 1 Jun 2025 21:46:23 +0300 Subject: [PATCH 2/3] fix: make interact key follow established config pattern - Change KeyboardKeyInteract to non-nullable with default 'f' - Remove validation requirement since default is always provided - Remove null-forgiving operator in state machine - Follows same pattern as other keyboard bindings in codebase --- Phishy/Configs/ConfigValidator.cs | 7 ------- Phishy/Configs/Properties.cs | 4 ++-- Phishy/FishingStateMachine.cs | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Phishy/Configs/ConfigValidator.cs b/Phishy/Configs/ConfigValidator.cs index 6087c4e..36d0c47 100644 --- a/Phishy/Configs/ConfigValidator.cs +++ b/Phishy/Configs/ConfigValidator.cs @@ -48,13 +48,6 @@ public static ValidationResult Validate(Properties properties) } } - if (properties.UseInteractKey) - { - if (string.IsNullOrWhiteSpace(properties.KeyboardKeyInteract)) - { - errors.Add("KeyboardKeyInteract is required when UseInteractKey is enabled"); - } - } return new ValidationResult(errors); } diff --git a/Phishy/Configs/Properties.cs b/Phishy/Configs/Properties.cs index 6701c5f..9232efd 100644 --- a/Phishy/Configs/Properties.cs +++ b/Phishy/Configs/Properties.cs @@ -38,8 +38,8 @@ public sealed class Properties [YamlMember(Description = "Use interact key instead of mouse clicking for fishing (requires WoW expansion with interact feature, Default: false)")] public bool UseInteractKey { get; set; } - [YamlMember(Description = "Keyboard key binding for interact with target (required if UseInteractKey is true, Default: f)")] - public string? KeyboardKeyInteract { get; set; } + [YamlMember(Description = "Keyboard key binding for interact with target (Default: f)")] + public string KeyboardKeyInteract { get; set; } public Properties() { diff --git a/Phishy/FishingStateMachine.cs b/Phishy/FishingStateMachine.cs index 84ce31c..cf3ceb9 100644 --- a/Phishy/FishingStateMachine.cs +++ b/Phishy/FishingStateMachine.cs @@ -126,7 +126,7 @@ public void Update(CancellationToken cancellationToken) if (AppConfig.Props.UseInteractKey) { Console.WriteLine($"[FishingStateMachine]: Using interact key: {AppConfig.Props.KeyboardKeyInteract}"); - KeyboardUtils.SendKeyInput(AppConfig.Props.KeyboardKeyInteract!); + KeyboardUtils.SendKeyInput(AppConfig.Props.KeyboardKeyInteract); } else { From dc9920802a9604ae40a5fbf8d8b39267f897c822 Mon Sep 17 00:00:00 2001 From: stdNullPtr Date: Sun, 1 Jun 2025 22:04:05 +0300 Subject: [PATCH 3/3] fix: send lowercase letters and reduce log spam - Modify KeyboardUtils to send lowercase letters without braces - Keep braces for special keys (numbers, etc.) but use direct send for letters - Reduce log spam by increasing threshold from 0.01f to 0.05f - Increase log interval from 2 seconds to 5 seconds - Should fix capital F issue in WoW chat window --- Phishy/Configs/Properties.cs | 2 +- Phishy/FishingStateMachine.cs | 15 +++++++++++---- Phishy/Utils/KeyboardUtils.cs | 11 ++++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Phishy/Configs/Properties.cs b/Phishy/Configs/Properties.cs index 9232efd..070bd43 100644 --- a/Phishy/Configs/Properties.cs +++ b/Phishy/Configs/Properties.cs @@ -53,6 +53,6 @@ public Properties() FishingChannelDurationSeconds = TimeSpan.FromSeconds(20).Seconds; GameWindowName = "Game Window Name"; UseInteractKey = false; - KeyboardKeyInteract = KeyboardUtils.ConvertToString(Keys.F); + KeyboardKeyInteract = "f"; } } \ No newline at end of file diff --git a/Phishy/FishingStateMachine.cs b/Phishy/FishingStateMachine.cs index cf3ceb9..01e945d 100644 --- a/Phishy/FishingStateMachine.cs +++ b/Phishy/FishingStateMachine.cs @@ -55,8 +55,15 @@ public void Update(CancellationToken cancellationToken) _isBobberFound = false; } - Console.WriteLine("[FishingStateMachine]: Moving to center of screen..."); - MouseUtils.MoveToCenterOfWindow(AppConfig.Props.GameWindowName, true, 100); + if (!AppConfig.Props.UseInteractKey) + { + Console.WriteLine("[FishingStateMachine]: Moving to center of screen..."); + MouseUtils.MoveToCenterOfWindow(AppConfig.Props.GameWindowName, true, 100); + } + else + { + Console.WriteLine("[FishingStateMachine]: Interact mode enabled - skipping mouse positioning..."); + } TryTransition(); break; @@ -303,8 +310,8 @@ private void ListenForFish(CancellationToken cancellationToken, TimeSpan timeout maxSoundLevel = currentSoundLevel; } - // Log every 2 seconds or when significant sound detected - if (DateTime.Now - lastLogTime > TimeSpan.FromSeconds(2) || currentSoundLevel > 0.01f) + // Log every 5 seconds or when significant sound detected (higher threshold) + if (DateTime.Now - lastLogTime > TimeSpan.FromSeconds(5) || currentSoundLevel > 0.05f) { string statusMsg = AppConfig.Props.UseInteractKey ? $"Interact mode: Ready, Current sound: {currentSoundLevel:F4}, Max sound: {maxSoundLevel:F4}, Checks: {checkCount}" diff --git a/Phishy/Utils/KeyboardUtils.cs b/Phishy/Utils/KeyboardUtils.cs index a96848b..6145d33 100644 --- a/Phishy/Utils/KeyboardUtils.cs +++ b/Phishy/Utils/KeyboardUtils.cs @@ -10,7 +10,16 @@ public static void SendKeyInput(Keys key) public static void SendKeyInput(string key) { - SendKeys.SendWait("{" + key + "}"); + // For single letter keys, send without braces to get lowercase + // For special keys (like numbers converted from Keys.D1), use braces + if (key.Length == 1 && char.IsLetter(key[0])) + { + SendKeys.SendWait(key.ToLower()); + } + else + { + SendKeys.SendWait("{" + key + "}"); + } } public static string ConvertToString(Keys key)