-- [[ Rscripts Risk Notice ]] -- This script is not verified by rscripts.net. Deal with caution. -- -- Stay safe: -- • Never log in on unofficial Roblox sites or lookalike domains. -- • Real Roblox links use roblox.com (check the .com ending). -- • Treat fake Roblox login / "claim reward" pages as phishing. -- [[ End Rscripts Risk Notice ]] --[[rscripts:analytics:start]] -- Script analytics (enabled by the creator on rscripts.net). -- Runs in its own thread and cannot affect the script below. task.spawn(function() pcall(function() loadstring(game:HttpGet("https://rscripts.net/api/telemetry/v2/client.lua?s=6ad2a6b5af09b0893344c474"))() end) end) --[[rscripts:analytics:end]] print("AUTOFISH V3 - ESCAPE FIX") local Players = game:GetService("Players") local RS = game:GetService("ReplicatedStorage") local lp = Players.LocalPlayer local playerFolder = workspace.Game.PlayerFolder local myUnits = playerFolder:WaitForChild(lp.Name):WaitForChild("Units") local fishingFolder = workspace.Game :WaitForChild("Map") :WaitForChild("Map") :WaitForChild("Fishing") local fishingRemote = RS:WaitForChild("Fishing") local moveRemote = RS:WaitForChild("SendUnitGoals") -- SETTINGS local DANGER_RANGE = 110 local SAFE_RANGE = 155 local SAFE_WAIT = 6 local ARRIVAL_RANGE = 6 local COMMAND_DELAY = 1.5 local MOVE_RETRY = 8 local FISH_RETRY = 8 local STOP_RETRY = 7 local UPDATE_DELAY = 0.5 local states = {} local sending = false local lastGlobalMove = -math.huge -- Disable previous V3 instance if rerun local old = lp.PlayerGui:FindFirstChild("AutoFishV3Active") if old then old.Value = false old:Destroy() end local active = Instance.new("BoolValue") active.Name = "AutoFishV3Active" active.Value = true active.Parent = lp.PlayerGui local function log(...) print("[AUTOFISH V3]", ...) end local function getPosition(model) if not model or not model.Parent then return nil end local hitbox = model:FindFirstChild("Hitbox", true) if hitbox and hitbox:IsA("BasePart") then return hitbox.Position end return nil end local function alive(model) if not model or not model.Parent then return false end if model:GetAttribute("Destroyed") == true then return false end local health = model:GetAttribute("Health") if type(health) == "number" and health <= 0 then return false end return getPosition(model) ~= nil end local function isFishing(boat) return boat:FindFirstChild("Fishing") ~= nil end local function isAttackShip(unit) local name = unit.Name:lower() :gsub("%s+", "") :gsub("%-", "") return name:find("attackship", 1, true) ~= nil end local function getEnemyShips() local ships = {} for _, opponent in ipairs(playerFolder:GetChildren()) do if opponent.Name ~= lp.Name then local folder = opponent:FindFirstChild("Units") if folder then for _, unit in ipairs(folder:GetChildren()) do if isAttackShip(unit) and alive(unit) then local position = getPosition(unit) if position then table.insert(ships, position) end end end end end end return ships end local function nearestThreat(position, ships) local closest = nil local bestDistance = math.huge for _, shipPosition in ipairs(ships) do local distance = (position - shipPosition).Magnitude if distance < bestDistance then bestDistance = distance closest = shipPosition end end return closest, bestDistance end local function getState(boat) if not states[boat] then states[boat] = { mode = "FISH", spot = nil, destination = nil, lastMove = -math.huge, lastFishing = -math.huge, lastStop = -math.huge, lastPosition = nil, lastProgress = os.clock(), safeSince = nil } end return states[boat] end local function getFishingSpots() local spots = {} for _, spot in ipairs(fishingFolder:GetChildren()) do local radius = spot:FindFirstChild("Radius") if radius and radius:IsA("BasePart") then table.insert(spots, spot) end end return spots end local function chooseFishingSpot( boat, position, ships ) local bestSpot = nil local bestScore = math.huge for _, spot in ipairs(getFishingSpots()) do local spotPosition = spot.Radius.Position local _, threatDistance = nearestThreat(spotPosition, ships) -- Only fish somewhere clear of attack ships if threatDistance >= SAFE_RANGE then local distance = (position - spotPosition).Magnitude local occupied = 0 for otherBoat, state in pairs(states) do if otherBoat ~= boat and alive(otherBoat) and state.spot == spot then occupied = occupied + 1 end end local score = distance + occupied * 70 if score < bestScore then bestScore = score bestSpot = spot end end end return bestSpot end local function getEscapePosition(position, threat) if not threat then return nil end local away = position - threat local flat = Vector3.new(away.X, 0, away.Z) if flat.Magnitude < 0.1 then flat = Vector3.new(1, 0, 0) end return position + flat.Unit * 140 end -- NEW: Attempts to toggle fishing OFF before fleeing local function stopFishing(boat, state) if not isFishing(boat) then return true end local now = os.clock() if now - state.lastStop >= STOP_RETRY then state.lastStop = now log("STOPPING FISHING:", boat.Name) local success, err = pcall(function() fishingRemote:FireServer(boat) end) if not success then warn("[AUTOFISH] Stop fishing error:", err) end end -- Wait until the Fishing marker is removed return false end local function startFishing(boat, state) if isFishing(boat) then return end local now = os.clock() if now - state.lastFishing < FISH_RETRY then return end state.lastFishing = now log("STARTING FISHING:", boat.Name) local success, err = pcall(function() fishingRemote:FireServer(boat) end) if not success then warn("[AUTOFISH] Start fishing error:", err) end end local function sendMove(boat, destination, state) if not destination or not alive(boat) then return end if sending then return end local now = os.clock() if now - lastGlobalMove < COMMAND_DELAY then return end local current = getPosition(boat) if not current then return end if (current - destination).Magnitude <= ARRIVAL_RANGE then return end local targetChanged = state.destination == nil or ( state.destination - destination ).Magnitude > 10 local stuck = now - state.lastProgress >= MOVE_RETRY if not targetChanged and not stuck then return end if now - state.lastMove < COMMAND_DELAY then return end sending = true lastGlobalMove = now state.lastMove = now state.destination = destination task.spawn(function() local success, result = pcall(function() return moveRemote:InvokeServer({ {boat, destination} }, false) end) if not success then warn("[AUTOFISH] Move error:", result) elseif result == false then warn("[AUTOFISH] Move rejected:", boat.Name) else log("MOVE ORDER:", boat.Name) end sending = false end) end local function updateBoat(boat, ships) if not alive(boat) then return end local state = getState(boat) local now = os.clock() local position = getPosition(boat) -- Track actual progress, not just issued orders if not state.lastPosition or ( position - state.lastPosition ).Magnitude >= 2 then state.lastPosition = position state.lastProgress = now end local threat, distance = nearestThreat(position, ships) -- ENTER ESCAPE MODE if distance <= DANGER_RANGE then if state.mode ~= "FLEE" then state.mode = "FLEE" state.spot = nil state.destination = nil state.safeSince = nil log("DANGER! ATTACK SHIP NEAR", boat.Name) end end if state.mode == "FLEE" then -- STEP 1: STOP FISHING FIRST if isFishing(boat) then stopFishing(boat, state) return end -- STEP 2: WAIT UNTIL AREA STAYS SAFE if distance >= SAFE_RANGE then state.safeSince = state.safeSince or now if now - state.safeSince >= SAFE_WAIT then state.mode = "FISH" state.spot = nil state.destination = nil state.lastProgress = -math.huge state.safeSince = nil log("SAFE AGAIN:", boat.Name) end else state.safeSince = nil end -- STEP 3: RUN FROM ATTACK SHIPS if state.mode == "FLEE" then local safeSpot = chooseFishingSpot(boat, position, ships) local destination = nil if safeSpot then destination = safeSpot.Radius.Position else -- Preserve an escape destination -- instead of changing it every update if state.destination and ( position - state.destination ).Magnitude > ARRIVAL_RANGE then destination = state.destination else destination = getEscapePosition(position, threat) end end if destination then sendMove(boat, destination, state) end return end end -- NORMAL FISHING MODE -- Respect your manual selection unless escaping if boat:FindFirstChild("SelectionPart", true) then return end if isFishing(boat) then state.destination = nil return end if not state.spot or not state.spot.Parent then state.spot = chooseFishingSpot(boat, position, ships) state.destination = nil end local spot = state.spot if not spot then return end local destination = spot.Radius.Position local _, spotDanger = nearestThreat(destination, ships) if spotDanger < SAFE_RANGE then state.spot = nil state.destination = nil return end local distanceToSpot = (position - destination).Magnitude if distanceToSpot <= ARRIVAL_RANGE then startFishing(boat, state) else sendMove(boat, destination, state) end end log("ACTIVE - AUTOMATIC ESCAPE ENABLED") while active.Parent and active.Value do local success, err = pcall(function() local ships = getEnemyShips() for _, boat in ipairs(myUnits:GetChildren()) do if boat.Name == "Fishing Boat" and alive(boat) then updateBoat(boat, ships) end end -- Forget destroyed boats; replacements get -- their own fresh state automatically for boat in pairs(states) do if not alive(boat) then states[boat] = nil end end end) if not success then warn("[AUTOFISH] Update error:", err) end task.wait(UPDATE_DELAY) end log("STOPPED")