Run it
Copy the script and paste it into your executor.
RunService = :()
Players = :()
Workspace = :()
LINE_WIDTH =
LINE_COLOR = .(, , )
LINE_TRANSPARENCY =
MAX_BOUNCES =
BEAM_SEGMENTS =
UPDATE_RATE =
BALL_RADIUS =
LINE_HEIGHT_OFFSET =
FRICTION_COEFFICIENT =
ELASTICITY =
COLLISION_ELASTICITY =
VELOCITY_PREDICTION_MULTIPLIER =
WALL_MARGIN_MULTIPLIER =
SPIN_EFFECT_MULTIPLIER =
COLLISION_THRESHOLD =
MIN_COLLISION_DISTANCE = BALL_RADIUS *
WALL_BOUNCE_OFFSET =
MICRO_STEP_SIZE =
TRAJECTORY_RESOLUTION =
MAX_TRAJECTORY_LENGTH =
ROLLING_FRICTION =
SPIN_DECAY =
CUE_IMPACT_FACTOR =
MIN_VELOCITY_THRESHOLD =
AIR_RESISTANCE =
TABLE_FRICTION =
ENERGY_CONSERVATION =
(parent, name)
success, result = (()
parent:(name, )
)
success result
(path, timeout)
timeout = timeout
start = ()
current = Workspace
_, name (path)
() - start < timeout
child = (current, name)
child
current = child
.()
current ~= Workspace current
Table1 = ({, }) ({})
Table1
_, obj (Workspace:())
obj:() (obj.Name:() obj.Name:())
Table1 = obj
Table1
Table1 = Workspace
HitTrajectory
searchPaths = {
{, },
{},
{, },
{, },
{, }
}
_, path (searchPaths)
HitTrajectory = (path, )
HitTrajectory
HitTrajectory
_, obj (Workspace:())
obj:() obj.Name:():()
HitTrajectory = obj
()
balls = {}
potentialBallParents = {
Workspace,
Table1,
(Workspace, ),
(Workspace, ),
(Table1, )
}
_, parent (potentialBallParents)
parent
_, obj (parent:())
obj:() obj.Name:():()
(obj.Name:():() obj.Name:():())
.(balls, obj)
cueBall, targetBalls = , {}
_, ball (balls)
name = ball.Name:()
name:() name:() name:()
cueBall = ball
(name:() #balls > )
.(targetBalls, ball)
cueBall
_, ball (balls)
ball.BrickColor == BrickColor.() ball.Color == .(, , )
cueBall = ball
cueBall, targetBalls
cueBall, targetBalls = ()
selectedTargetBall = targetBalls[]
beamContainer = .()
beamContainer.Name =
beamContainer.Parent = Workspace
tableBounds =
()
tableSurface =
candidates = {}
_, part (Table1:())
part:()
size = part.Size
(size.X > size.Z > ) part.Name:() part.Name:() part.Name:()
.(candidates, {part = part, area = size.X * size.Z})
.(candidates, (a, b) a.area > b.area )
tableSurface = candidates[] candidates[].part
tableSurface
_, part (Table1:())
part:() part.Position.Y > part.Position.Y <
tableSurface = part
tableSurface
{
minX = -, maxX = ,
minZ = -, maxZ = ,
y =
}
cf = tableSurface.CFrame
size = tableSurface.Size
halfX = size.X /
halfZ = size.Z /
corners = {
cf * .(-halfX, , -halfZ),
cf * .(halfX, , -halfZ),
cf * .(-halfX, , halfZ),
cf * .(halfX, , halfZ)
}
minX, maxX = .huge, -.huge
minZ, maxZ = .huge, -.huge
_, corner (corners)
minX = .(minX, corner.X)
maxX = .(maxX, corner.X)
minZ = .(minZ, corner.Z)
maxZ = .(maxZ, corner.Z)
margin = BALL_RADIUS * WALL_MARGIN_MULTIPLIER
surfaceHeight = tableSurface.Position.Y + (size.Y / )
{
minX = minX + margin,
maxX = maxX - margin,
minZ = minZ + margin,
maxZ = maxZ - margin,
y = surfaceHeight + LINE_HEIGHT_OFFSET,
center = tableSurface.Position,
surface = tableSurface,
width = (maxX - minX) - ( * margin),
length = (maxZ - minZ) - ( * margin)
}
()
HitTrajectory HitTrajectory:()
lookVec = HitTrajectory.CFrame.LookVector
dir = .(lookVec.X, , lookVec.Z)
dir.Unit
cueBall
cueStick = (Workspace, )
(Workspace, )
(Table1, )
(Workspace, )
cueStick cueStick:()
lookVec = cueStick.CFrame.LookVector
dir = .(lookVec.X, , lookVec.Z)
dir.Unit
cueBall selectedTargetBall
direction = (selectedTargetBall.Position - cueBall.Position)
dir = .(direction.X, , direction.Z)
dir.Unit
.(, , -).Unit
(rayOrigin, rayDir, sphereCenter, sphereRadius)
oc = rayOrigin - sphereCenter
a = rayDir:(rayDir)
b = * oc:(rayDir)
c = oc:(oc) - sphereRadius * sphereRadius
discriminant = b * b - * a * c
discriminant <
,
sqrtDisc = .(discriminant)
t1 = (-b - sqrtDisc) / ( * a)
t2 = (-b + sqrtDisc) / ( * a)
t1 >
, rayOrigin + rayDir * t1
t2 >
, rayOrigin + rayDir * t2
,
(startPos, direction)
direction = .(direction.X, , direction.Z).Unit
tableBounds
tableBounds = ()
intersections = {}
epsilon =
.(direction.X) > epsilon
tRight = (tableBounds.maxX - startPos.X) / direction.X
tLeft = (tableBounds.minX - startPos.X) / direction.X
tRight > epsilon
pos = startPos + (direction * tRight)
pos.Z >= tableBounds.minZ - epsilon pos.Z <= tableBounds.maxZ + epsilon
.(intersections, {
t = tRight,
pos = pos,
normal = .(-, , ),
wall =
})
tLeft > epsilon
pos = startPos + (direction * tLeft)
pos.Z >= tableBounds.minZ - epsilon pos.Z <= tableBounds.maxZ + epsilon
.(intersections, {
t = tLeft,
pos = pos,
normal = .(, , ),
wall =
})
.(direction.Z) > epsilon
tBack = (tableBounds.maxZ - startPos.Z) / direction.Z
tFront = (tableBounds.minZ - startPos.Z) / direction.Z
tBack > epsilon
pos = startPos + (direction * tBack)
pos.X >= tableBounds.minX - epsilon pos.X <= tableBounds.maxX + epsilon
.(intersections, {
t = tBack,
pos = pos,
normal = .(, , -),
wall =
})
tFront > epsilon
pos = startPos + (direction * tFront)
pos.X >= tableBounds.minX - epsilon pos.X <= tableBounds.maxX + epsilon
.(intersections, {
t = tFront,
pos = pos,
normal = .(, , ),
wall =
})
.(intersections, (a, b) a.t < b.t )
#intersections >
hit = intersections[]
hitPos = .(hit.pos.X, tableBounds.y, hit.pos.Z)
hitPos, hit.normal, hit.t
, ,
(direction, normal, elasticity, spinFactor, incidentAngle)
dotProduct = direction:(normal)
reflection = direction - ( * dotProduct * normal)
spinFactor incidentAngle
tangent = normal:(.(, , ))
spinComponent = .(incidentAngle) * spinFactor *
reflection = reflection + (tangent * spinComponent)
angleInfluence = .(incidentAngle * ) *
reflection = reflection + (tangent * angleInfluence)
microAdjust = .(incidentAngle * ) * spinFactor *
reflection = reflection + (tangent * microAdjust)
energyLoss = ( - elasticity) *
(reflection * (elasticity - energyLoss) * ENERGY_CONSERVATION).Unit
(rayOrigin, rayDir, targetBall)
targetBall , ,
targetPos = .(
targetBall.Position.X,
tableBounds.y,
targetBall.Position.Z
)
collisionRadius = BALL_RADIUS * * COLLISION_THRESHOLD
hit, collisionPoint = (rayOrigin, rayDir, targetPos, collisionRadius)
hit collisionPoint
normal = (collisionPoint - targetPos).Unit
incidentAngle = .(.(rayDir:(-normal), -, ))
reflectedDir = (rayDir, normal, COLLISION_ELASTICITY, SPIN_EFFECT_MULTIPLIER, incidentAngle)
, collisionPoint, reflectedDir, targetPos
, , ,
(points)
#points <
beamContainer:()
maxBeams = .(BEAM_SEGMENTS, #points - )
i = , maxBeams
startPoint = points[i]
endPoint = points[i + ]
startPoint endPoint
distance = (endPoint - startPoint).Magnitude
distance >
attachment0 = .()
attachment1 = .()
attachment0.WorldPosition = startPoint
attachment1.WorldPosition = endPoint
beam = .()
beam.Attachment0 = attachment0
beam.Attachment1 = attachment1
beam.Width0 = LINE_WIDTH
beam.Width1 = LINE_WIDTH
beam.Color = ColorSequence.(LINE_COLOR)
beam.Transparency = NumberSequence.(LINE_TRANSPARENCY)
beam.FaceCamera =
beam.LightEmission =
beam.LightInfluence =
beam.Texture =
beam.TextureLength = distance /
beam.TextureMode = .TextureMode.Wrap
beam.TextureSpeed =
beam.Segments = .(, .(, distance * ))
beam.CurveSize0 =
beam.CurveSize1 =
attachment0.Parent = beamContainer
attachment1.Parent = beamContainer
beam.Parent = beamContainer
()
tableBounds
tableBounds = ()
trajectoryPoints = {}
startPos, direction
cueBall
startPos = .(cueBall.Position.X, tableBounds.y, cueBall.Position.Z)
direction = ()
.(trajectoryPoints, startPos)
hitBall, collisionPoint, reflectedDir, targetPos = (startPos, direction, selectedTargetBall)
hitBall collisionPoint targetPos
distToCollision = (collisionPoint - startPos).Magnitude
ultraSmoothSteps = .(, .(distToCollision / ))
step = , ultraSmoothSteps
t = step / ultraSmoothSteps
smoothT = t * t * ( - * t)
point = startPos:(collisionPoint, smoothT)
.(trajectoryPoints, point)
.(trajectoryPoints, collisionPoint)
.(trajectoryPoints, targetPos)
startPos = targetPos
direction = reflectedDir direction
startPos = HitTrajectory .(
HitTrajectory.Position.X,
tableBounds.y,
HitTrajectory.Position.Z
) .(, tableBounds.y, )
direction = ()
.(trajectoryPoints, startPos)
currentPos = startPos
currentDir = direction
totalDistance =
maxDistance = MAX_TRAJECTORY_LENGTH
velocity =
spinFactor = SPIN_EFFECT_MULTIPLIER
bounce = , MAX_BOUNCES
hitPos, hitNormal, hitDistance = (currentPos, currentDir)
hitPos hitNormal
segmentDistance = (hitPos - currentPos).Magnitude
totalDistance = totalDistance + segmentDistance
totalDistance > maxDistance
remainingDist = maxDistance - (totalDistance - segmentDistance)
finalPos = currentPos + (currentDir * remainingDist)
endSteps = .(, .(remainingDist / ))
step = , endSteps
t = step / endSteps
smoothT = t * t * ( - * t)
.(trajectoryPoints, currentPos:(finalPos, smoothT))
incidentAngle = .(.(currentDir:(-hitNormal), -, ))
bounceElasticity = ELASTICITY * ( - (bounce * ))
steps = .(, .(segmentDistance / ))
step = , steps
t = step / steps
smoothT = t * t * ( - * t)
point = currentPos:(hitPos, smoothT)
.(trajectoryPoints, point)
velocity = velocity * ROLLING_FRICTION * TABLE_FRICTION * AIR_RESISTANCE
spinFactor = spinFactor * SPIN_DECAY
currentDir = (currentDir, hitNormal, bounceElasticity, spinFactor, incidentAngle)
currentPos = hitPos + (currentDir * WALL_BOUNCE_OFFSET)
velocity < MIN_VELOCITY_THRESHOLD
.(trajectoryPoints, currentPos)
endPos = currentPos + (currentDir * )
steps = .(, .((endPos - currentPos).Magnitude / ))
step = , steps
t = step / steps
smoothT = t * t * ( - * t)
point = currentPos:(endPos, smoothT)
.(trajectoryPoints, point)
trajectoryPoints
()
selectedTargetBall selectedTargetBall:()
points = ()
#points >=
i = , #points -
targetPos = .(
selectedTargetBall.Position.X,
tableBounds.y,
selectedTargetBall.Position.Z
)
pointDist = (points[i] - targetPos).Magnitude
pointDist < BALL_RADIUS * i < #points
velocityDir = (points[i + ] - points[i]).Unit
bodyVel = selectedTargetBall:()
bodyVel
bodyVel = .()
bodyVel.Name =
bodyVel.MaxForce = .(, , )
bodyVel.P =
bodyVel.Parent = selectedTargetBall
speed = VELOCITY_PREDICTION_MULTIPLIER * CUE_IMPACT_FACTOR *
bodyVel.Velocity = velocityDir * speed
lastUpdate =
()
now = ()
now - lastUpdate < UPDATE_RATE
lastUpdate = now
now % < UPDATE_RATE
cueBall, targetBalls = ()
selectedTargetBall = targetBalls[] selectedTargetBall
points = ()
(points)
()
.()
tableBounds = ()
()
()
(, MAX_BOUNCES, )
(, ELASTICITY, )
(, COLLISION_ELASTICITY, )
(, UPDATE_RATE, )
(, MAX_TRAJECTORY_LENGTH, )
(, TRAJECTORY_RESOLUTION, )
()
()
()
()
()
connection = RunService.Heartbeat:(update)
()
connection:()
beamContainer
beamContainer:()
cleanup
success, err = (()
cleanup = ()
)
success
(, err)
Players.PlayerRemoving:((player)
player == Players.LocalPlayer cleanup
()
)
remote = .()
remote.Name =
remote.Parent = Workspace
remote.OnServerInvoke = (player)
player == Players.LocalPlayer
beamContainer.Parent
beamContainer.Parent =
beamContainer.Parent = Workspace
()
()Only a full target ball line trajectory for this game, and it鈥檚 fully open sourced and customizable. The full trajectory line it鈥檚 not 100% accurate. Made by AI.

Universal