Getting a new vector at max distance

First of all, I apologize if I confuse anyone with my messy drawing or terrible explanation. Currently I am scripting a bow that shoots an arrow to the Player’s mouse position. Using Bézier Curves I made it so the arrow drops to the mouse position. Everything works perfectly, but now I would like to add a max distance the arrow can fire. I figured I would use magnitude to check the distance between the tool’s position and the mouse position and then check if this distance is greater than the max distance I have set. This also works, but now I need to get the new P2 vector.

If we have our max magnitude to 30 studs and we fire an arrow that is 70 studs away. Instead of doing the top vector and firing the arrow 70 studs away, it should calculate a new P2 and follow the bottom vector that has a magnitude of 30 studs. I can easily get P0 and we can get P1 when we get the new P2. But how would we get the new P2 from the current vectors we have?

function quadBezier(t, p0, p1, p2)
return (1 - t)^2 * p0 + 2 * (1 - t) * t * p1 + t^2 * p2
end

function getp1(p1, p2)
    local a,b,c = p1.X+p2.X,p1.y+p2.y,p1.z+p2.z
    return Vector3.new(a/2, (b/2) + 3, c/2)
end

fire.OnServerEvent:connect(function(plr, mousePos, toolPos)
local points = {}

local distance = (mousePos - toolPos).Magnitude
print(mousePos - toolPos)
local p0, p2, p1 = toolPos,nil,nil

if distance < maxDistance then
	p2 = mousePos
	p1 = getp1(p0,p2)

	local a = Instance.new("Model", game.Workspace)
	a.Name = "Path"

	for t=0,1,0.01 do
		local p = quadBezier(t, p0, p1, p2)
		points[t] = p
	end
	
	for i,v in pairs(points) do
		
		local b = Instance.new("Part")
		b.Anchored = true
		b.Size = Vector3.new(1,1,1)
		b.Position = v
		b.Transparency = 0
		b.CanCollide = false
		b.Parent = a
	end
end
end)

This is the current script just in case you need a reference to it.

P.S Didn’t know how to title this post because it is very specific

4 Likes

So if I’m getting this right do you want it so if the arrow is going further then it should you want it fall short into the ground.
If so you could instead get the unit Direction of the start and goal point and multiply that by your max distance and use that in a ray, use workspace:FindPartOnRay(p0, (p0 - p2).Unit*MaxDistance) -- .Unit gets the direction of the position your aiming for from the start position and can only work on vectors but can be used on CFrames if you do (cf1.p - cf2.p).Unit, then it times it so the ray stops looking when it gets to the max range the bow can do to find the position it is when its in mid air, then send a ray down to the ground to get where the arrow should land and finally set that as p2.

There could possibly be a better way of doing it but right now this is the one that I thought of right now, either way if it doesn’t solve your problem then I’m sorry about wasting your time mate but if it is what your looking for then be careful with things like cliffs and tall hills as some weird behavior with beziers might arise.

4 Likes

Your problem seems to be solved by @kian90cainereal, but I just thought this would help.

2 Likes

Yea that will definitely help as if you use this method you’ll get the arrows to have a similar bullet drop to whats used in phantom forces or any other gun game and it will help avoid a lot of the weird behaviors I was taking about when referring to bezier functions, the only thing you would need to add is rays that cast to the current position of the arrow to the next position of the arrow using the .Unit method combined with the .Magnitude I explained in my post to check for any players in the way of the arrow and do things like weld the arrow to the target hit or deal damage.

2 Likes

I’m a little confused? Your current method is to calculate p1 by doing (p0 + p3)/2 + Vector3.new(0, 3, 0). What’s wrong with this method for your use case?

2 Likes