The “distance to point” method you used is really nice because it’s so simple. Thankfully we can also do a “distance to line segment” method that would work great for rivers. Distance to point makes a sphere- shaped region, distance to line segment makes a capsule-shaped region.
We can find that kind of distance with maths, but it’s already been done before so let’s just google how to do it. Here’s a stackoverflow result showing how it can be done with code, and here’s a port to Lua from an earlier reply I posted.
In your case this might also work for the ocean. If players can’t actually travel on the ocean and can only be near the coast, then the coast can be made up of a bunch of line segments just like a river. Let me know if your use case makes this not work and I’ll come up with another way if I can.
EDIT: Part of what made your fountain solution nice is that you can use an invisible part to represent the center of the sphere-shaped region, so you can edit the sphere in a visual and interactive way. The same can be done with line segments! A line segment can be represented by the points at the Front and Back faces of a Part, and you can get the endpoints like so:
function partEndPoints( part )
return
(part.CFrame * CFrame.new(0, 0, -part.Size.Z/2)).p,
(part.CFrame * CFrame.new(0, 0, part.Size.Z/2)).p
end
You could even make the width or height of the part affect the max distance from the line segment where it detects players.