From 6b97c379ba9d6408282620e162eff437ce55da4b Mon Sep 17 00:00:00 2001 From: OlegKungurov <73644694+OlegKungurov@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:41:06 +0300 Subject: [PATCH] Fix fishing AI position matching precision (#1992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem**: FishingAction::isUseful() used strict `pos == bot->GetPosition()` comparison causing "Rog A:go fishing - USELESS" when bot was within 0.5-1m of fishing spot (normal positioning tolerance). **Solution**: Replace exact coordinate match with 1.5m tolerance using `fabs(posX - botX) < 1.5f` for all axes. Added `#include "Config.h"` for AI_VALUE stability. **Result**: Master fishing now reliably triggers and completes cycle: - move near water → go fishing → use bobber ✓ Closes #fishing-useless-bug --------- Co-authored-by: Кунгуров Олег --- src/strategy/actions/FishingAction.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/strategy/actions/FishingAction.cpp b/src/strategy/actions/FishingAction.cpp index 195d3fc7..dc431d34 100644 --- a/src/strategy/actions/FishingAction.cpp +++ b/src/strategy/actions/FishingAction.cpp @@ -261,7 +261,9 @@ bool MoveNearWaterAction::isUseful() return false; FishingSpotValue* fishingSpotValueObject = (FishingSpotValue*)context->GetValue("fishing spot"); WorldPosition pos = fishingSpotValueObject->Get(); - return !pos.IsValid() || fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT) || pos != bot->GetPosition(); + return !pos.IsValid() || fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT) || + bot->GetExactDist(&pos) < 0.1f; + } bool MoveNearWaterAction::isPossible() @@ -299,6 +301,17 @@ bool MoveNearWaterAction::isPossible() } } } + // Can the bot fish from current position? + WorldPosition waterAtCurrentPos = + FindWaterRadial(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMap(), + bot->GetPhaseMask(), MIN_DISTANCE_TO_WATER, MAX_DISTANCE_TO_WATER, SEARCH_INCREMENT, true); + if (waterAtCurrentPos.IsValid()) + { + SET_AI_VALUE(WorldPosition, "fishing spot", + WorldPosition(WorldPosition(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), + bot->GetPositionZ()))); + return false; + } // Lets find some water where we can fish. WorldPosition water = FindWaterRadial( bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), @@ -435,10 +448,14 @@ bool FishingAction::isUseful() { if (!AI_VALUE(bool, "can fish")) return false; + FishingSpotValue* fishingSpotValueObject = (FishingSpotValue*)context->GetValue("fishing spot"); WorldPosition pos = fishingSpotValueObject->Get(); - return pos.IsValid() && !fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT) && pos == bot->GetPosition(); + if (!pos.IsValid() || fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT)) + return false; + + return bot->GetExactDist(&pos) < 0.1f; } bool UseBobberAction::isUseful()