Sure, the code I use to run the prediction calculation is a slightly modified version of the module found in this post
local TERRAIN = game.Workspace.Terrain
local BEAM = Instance.new("Beam")
BEAM.Color = ColorSequence.new(Color3.new(1, 0, 0))
BEAM.Transparency = NumberSequence.new(0)
BEAM.FaceCamera = true
BEAM.Segments = 20
BEAM.Width0 = 0.1
BEAM.Width1 = 0.1
local TimerClass = require(script:WaitForChild("Iteration"))
-- Class
local Trajectory = {}
Trajectory.__index = Trajectory
-- Private Functions
local function reflect(v, n)
return -2*v:Dot(n)*n + v
end
local function drawBeamProjectile(g, v0, x0, t)
local c = 0.5*0.5*0.5
local p3 = 0.5*g*t*t + v0*t + x0
local p2 = p3 - (g*t*t + v0*t)/3
local p1 = (c*g*t*t + 0.5*v0*t + x0 - c*(x0+p3))/(3*c) - p2
local curve0 = (p1 - x0).Magnitude
local curve1 = (p2 - p3).Magnitude
local b = (x0 - p3).unit
local r1 = (p1 - x0).unit
local u1 = r1:Cross(b).unit
local r2 = (p2 - p3).unit
local u2 = r2:Cross(b).unit
b = u1:Cross(r1).unit
local cfA = CFrame.fromMatrix(x0, r1, u1, b)
local cfB = CFrame.fromMatrix(p3, r2, u2, b)
local A0 = Instance.new("Attachment")
local A1 = Instance.new("Attachment")
local Beam = BEAM:Clone()
A0.CFrame = cfA
A0.Parent = TERRAIN
A1.CFrame = cfB
A1.Parent = TERRAIN
Beam.Attachment0 = A0
Beam.Attachment1 = A1
Beam.CurveSize0 = curve0
Beam.CurveSize1 = -curve1
Beam.Parent = TERRAIN
end
-- Public Constructors
function Trajectory.new(gravity, timeStep, maxTime)
local self = setmetatable({}, Trajectory)
self.Gravity = gravity
self.TimeStep = timeStep or 0.1
self.MaxTime = maxTime or 0.5
self.MinSpeed = 5
self.MaxBounce = 5
return self
end
-- Public Methods
function Trajectory:Velocity(v0, t)
-- g*t + v0
return self.Gravity*t + v0
end
function Trajectory:Position(x0, v0, t)
-- 0.5*g*t^2 + v0*t + x0
return 0.5*self.Gravity*t*t + v0*t + x0
end
function Trajectory:PlaneQuadraticIntersection(x0, v0, p, n)
local a = (0.5*self.Gravity):Dot(n)
local b = v0:Dot(n)
local c = (x0 - p):Dot(n)
if (a ~= 0) then
local d = math.sqrt(b*b - 4*a*c)
return (-b - d)/(2*a)
else
return -c / b
end
end
function Trajectory:CalculateSingle(x0, v0, filter)
local t = 0
local hit, pos, normal, material
repeat
local p0 = self:Position(x0, v0, t)
local p1 = self:Position(x0, v0, t + self.TimeStep)
t = t + self.TimeStep
local ray = Ray.new(p0, p1 - p0)
local params = RaycastParams.new()
params.FilterDescendantsInstances = filter
params.FilterType = Enum.RaycastFilterType.Include
local raycast = workspace:Raycast(p0, p1 - p0, params)
hit, pos, normal, material = raycast and raycast.Instance, raycast and raycast.Position, raycast and raycast.Normal, raycast and raycast.Material
until (hit or t >= self.MaxTime)
if (hit) then
local t = self:PlaneQuadraticIntersection(x0, v0, pos, normal)
local x1 = self:Position(x0, v0, t)
return {hit, pos, normal, PhysicalProperties.new(material)}
else
return {hit}
end
end
--
return Trajectory