-- https://discord.gg/vqRNXrhYJG join n give me suggestions for new games pls
local ws = game:GetService("Workspace")
local rs = game:GetService("RunService")
local Players = game:GetService("Players")
local uis = game:GetService("UserInputService")
local hs = game:GetService("HttpService")
local CFG = {
mainExtend = 50,
deflectExtend = 50,
pulseSpeed = 3, pulseMin = 0.3, pulseMax = 0.7,
matchBallHeight = true,
bounceLogic = true,
halfWidth = 12.8 / 2,
halfLength = 24.8 / 2,
mainColor = Color3.fromRGB(0, 255, 255),
deflectColor = Color3.fromRGB(255, 80, 80),
warnColor = Color3.fromRGB(255, 100, 0)
}
local state = { pulsePhase = 0 }
local savedProfiles = {}
if makefolder and isfolder then
if not isfolder("TrajectoryConfigs") then
makefolder("TrajectoryConfigs")
end
end
local function loadProfilesFromDisk()
savedProfiles = {}
if listfiles and isfolder and isfolder("TrajectoryConfigs") then
local files = listfiles("TrajectoryConfigs")
for _, filePath in ipairs(files) do
local fileName = filePath:match("([^\\/]+)%.json$")
if fileName then
local success, content = pcall(readfile, filePath)
if success then
local dataSuccess, data = pcall(function() return hs:JSONDecode(content) end)
if dataSuccess and data then
savedProfiles[fileName] = data
end
end
end
end
end
end
local function saveProfileToDisk(name, data)
savedProfiles[name] = data
if writefile and isfolder and isfolder("TrajectoryConfigs") then
local success, content = pcall(function() return hs:JSONEncode(data) end)
if success then
pcall(writefile, "TrajectoryConfigs/" .. name .. ".json", content)
end
end
end
loadProfilesFromDisk()
local container = ws:FindFirstChild("TrajVisualContainer")
if container then container:Destroy() end
container = Instance.new("Folder")
container.Name = "TrajVisualContainer"
container.Parent = ws
local function create3DLine(color)
local part = Instance.new("Part")
part.Material = Enum.Material.Neon
part.Color = color
part.Shape = Enum.PartType.Cylinder
part.Anchored = true
part.CanCollide = false
part.CastShadow = false
part.Parent = container
return part
end
local draw3D = {
main = create3DLine(CFG.mainColor),
deflect = create3DLine(CFG.deflectColor)
}
local function createUI()
local oldGui = Players.LocalPlayer:WaitForChild("PlayerGui"):FindFirstChild("TrajMenuGui")
if oldGui then oldGui:Destroy() end
local sg = Instance.new("ScreenGui")
sg.Name = "TrajMenuGui"
sg.ResetOnSpawn = false
sg.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
sg.Parent = Players.LocalPlayer:WaitForChild("PlayerGui")
local frame = Instance.new("Frame")
frame.Name = "MainFrame"
frame.Size = UDim2.new(0, 320, 0, 300)
frame.Position = UDim2.new(0.5, -160, 0.4, -150)
frame.BackgroundColor3 = Color3.fromRGB(22, 22, 26)
frame.BorderSizePixel = 0
frame.Active = true
frame.Draggable = true
frame.Parent = sg
local stroke = Instance.new("UIStroke")
stroke.Thickness = 1.5
stroke.Color = Color3.fromRGB(45, 45, 55)
stroke.Parent = frame
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 8)
corner.Parent = frame
local tabBar = Instance.new("Frame")
tabBar.Size = UDim2.new(1, 0, 0, 35)
tabBar.BackgroundColor3 = Color3.fromRGB(30, 30, 36)
tabBar.BorderSizePixel = 0
tabBar.Parent = frame
local tbCorner = Instance.new("UICorner")
tbCorner.CornerRadius = UDim.new(0, 8)
tbCorner.Parent = tabBar
local cover = Instance.new("Frame")
cover.Size = UDim2.new(1, 0, 0, 10)
cover.Position = UDim2.new(0, 0, 1, -10)
cover.BackgroundColor3 = Color3.fromRGB(30, 30, 36)
cover.BorderSizePixel = 0
cover.Parent = tabBar
local mainPage = Instance.new("Frame")
mainPage.Size = UDim2.new(1, 0, 1, -35)
mainPage.Position = UDim2.new(0, 0, 0, 35)
mainPage.BackgroundTransparency = 1
mainPage.Visible = true
mainPage.Parent = frame
local configPage = Instance.new("Frame")
configPage.Size = UDim2.new(1, 0, 1, -35)
configPage.Position = UDim2.new(0, 0, 0, 35)
configPage.BackgroundTransparency = 1
configPage.Visible = false
configPage.Parent = frame
local mainTabBtn = Instance.new("TextButton")
mainTabBtn.Size = UDim2.new(0, 95, 1, 0)
mainTabBtn.BackgroundTransparency = 1
mainTabBtn.Text = "Main Settings"
mainTabBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
mainTabBtn.Font = Enum.Font.GothamBold
mainTabBtn.TextSize = 12
mainTabBtn.Parent = tabBar
local configTabBtn = Instance.new("TextButton")
configTabBtn.Size = UDim2.new(0, 95, 1, 0)
configTabBtn.Position = UDim2.new(0, 95, 0, 0)
configTabBtn.BackgroundTransparency = 1
configTabBtn.Text = "Saved Configs"
configTabBtn.TextColor3 = Color3.fromRGB(140, 140, 150)
configTabBtn.Font = Enum.Font.GothamBold
configTabBtn.TextSize = 12
configTabBtn.Parent = tabBar
mainTabBtn.MouseButton1Click:Connect(function()
mainPage.Visible = true
configPage.Visible = false
mainTabBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
configTabBtn.TextColor3 = Color3.fromRGB(140, 140, 150)
end)
configTabBtn.MouseButton1Click:Connect(function()
mainPage.Visible = false
configPage.Visible = true
mainTabBtn.TextColor3 = Color3.fromRGB(140, 140, 150)
configTabBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
end)
local info = Instance.new("TextLabel")
info.Size = UDim2.new(0, 110, 1, 0)
info.Position = UDim2.new(1, -120, 0, 0)
info.BackgroundTransparency = 1
info.Text = "[RShift to Hide]"
info.TextColor3 = Color3.fromRGB(130, 130, 140)
info.Font = Enum.Font.Gotham
info.TextSize = 11
info.TextXAlignment = Enum.TextXAlignment.Right
info.Parent = tabBar
uis.InputBegan:Connect(function(input, gpe)
if not gpe and input.KeyCode == Enum.KeyCode.RightShift then
frame.Visible = not frame.Visible
end
end)
local mainLenFill, mainLenKnob, mainLenLabel
local deflectLenFill, deflectLenKnob, deflectLenLabel
local function createSlider(text, defaultVal, maxVal, posY, callback)
local label = Instance.new("TextLabel")
label.Size = UDim2.new(1, -30, 0, 18)
label.Position = UDim2.new(0, 15, 0, posY)
label.BackgroundTransparency = 1
label.Text = text .. ": " .. tostring(math.round(defaultVal))
label.TextColor3 = Color3.fromRGB(200, 200, 200)
label.Font = Enum.Font.GothamSemibold
label.TextSize = 11
label.TextXAlignment = Enum.TextXAlignment.Left
label.Parent = mainPage
local track = Instance.new("Frame")
track.Size = UDim2.new(1, -30, 0, 5)
track.Position = UDim2.new(0, 15, 0, posY + 20)
track.BackgroundColor3 = Color3.fromRGB(45, 45, 55)
track.BorderSizePixel = 0
track.Parent = mainPage
local fill = Instance.new("Frame")
fill.Size = UDim2.new(defaultVal / maxVal, 0, 1, 0)
fill.BackgroundColor3 = Color3.fromRGB(0, 180, 255)
fill.BorderSizePixel = 0
fill.Parent = track
local knob = Instance.new("ImageButton")
knob.Size = UDim2.new(0, 12, 0, 12)
knob.Position = UDim2.new(defaultVal / maxVal, -6, 0.5, -6)
knob.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
knob.Parent = track
local snap = false
knob.MouseButton1Down:Connect(function() snap = true end)
uis.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then snap = false end end)
rs.RenderStepped:Connect(function()
if snap then
local mousePos = uis:GetMouseLocation().X
local trackStart = track.AbsolutePosition.X
local trackWidth = track.AbsoluteSize.X
local perc = math.clamp((mousePos - trackStart) / trackWidth, 0, 1)
fill.Size = UDim2.new(perc, 0, 1, 0)
knob.Position = UDim2.new(perc, -6, 0.5, -6)
local val = math.round(perc * maxVal)
label.Text = text .. ": " .. tostring(val)
callback(val)
end
end)
return fill, knob, label
end
local function createColorInput(text, defaultRGB, posY, callback)
local label = Instance.new("TextLabel")
label.Size = UDim2.new(0, 120, 0, 25)
label.Position = UDim2.new(0, 15, 0, posY)
label.BackgroundTransparency = 1
label.Text = text
label.TextColor3 = Color3.fromRGB(180, 180, 180)
label.Font = Enum.Font.GothamSemibold
label.TextSize = 11
label.TextXAlignment = Enum.TextXAlignment.Left
label.Parent = mainPage
local box = Instance.new("TextBox")
box.Size = UDim2.new(1, -155, 0, 25)
box.Position = UDim2.new(0, 140, 0, posY)
box.BackgroundColor3 = Color3.fromRGB(35, 35, 42)
box.BorderSizePixel = 0
box.Text = defaultRGB
box.TextColor3 = Color3.fromRGB(240, 240, 240)
box.Font = Enum.Font.Code
box.TextSize = 11
box.Parent = mainPage
local bCorner = Instance.new("UICorner")
bCorner.CornerRadius = UDim.new(0, 4)
bCorner.Parent = box
box.FocusLost:Connect(function()
local r, g, b = box.Text:match("(%d+),(%d+),(%d+)")
if r and g and b then
local col = Color3.fromRGB(tonumber(r), tonumber(g), tonumber(b))
callback(col)
end
end)
return box
end
mainLenFill, mainLenKnob, mainLenLabel = createSlider("Main Length", CFG.mainExtend, 2000, 15, function(v) CFG.mainExtend = v end)
local mainColorBox = createColorInput("Main Line Color (RGB):", string.format("%d,%d,%d", CFG.mainColor.R*255, CFG.mainColor.G*255, CFG.mainColor.B*255), 48, function(col)
CFG.mainColor = col
end)
deflectLenFill, deflectLenKnob, deflectLenLabel = createSlider("Deflect Length", CFG.deflectExtend, 2000, 90, function(v) CFG.deflectExtend = v end)
local deflectColorBox = createColorInput("Deflect Line Color (RGB):", string.format("%d,%d,%d", CFG.deflectColor.R*255, CFG.deflectColor.G*255, CFG.deflectColor.B*255), 123, function(col)
CFG.deflectColor = col
end)
local toggleBtn = Instance.new("TextButton")
toggleBtn.Size = UDim2.new(1, -30, 0, 30)
toggleBtn.Position = UDim2.new(0, 15, 0, 175)
toggleBtn.BackgroundColor3 = CFG.bounceLogic and Color3.fromRGB(0, 150, 100) or Color3.fromRGB(60, 60, 70)
toggleBtn.Font = Enum.Font.GothamBold
toggleBtn.Text = CFG.bounceLogic and "Cushion Bounce: ON" or "Cushion Bounce: OFF"
toggleBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
toggleBtn.TextSize = 11
toggleBtn.Parent = mainPage
local btnCorner = Instance.new("UICorner")
btnCorner.CornerRadius = UDim.new(0, 5)
btnCorner.Parent = toggleBtn
local function updateBounceUI()
toggleBtn.BackgroundColor3 = CFG.bounceLogic and Color3.fromRGB(0, 150, 100) or Color3.fromRGB(60, 60, 70)
toggleBtn.Text = CFG.bounceLogic and "Cushion Bounce: ON" or "Cushion Bounce: OFF"
end
toggleBtn.MouseButton1Click:Connect(function()
CFG.bounceLogic = not CFG.bounceLogic
updateBounceUI()
end)
local profileInput = Instance.new("TextBox")
profileInput.Size = UDim2.new(1, -110, 0, 30)
profileInput.Position = UDim2.new(0, 15, 0, 15)
profileInput.BackgroundColor3 = Color3.fromRGB(35, 35, 42)
profileInput.BorderSizePixel = 0
profileInput.Text = ""
profileInput.PlaceholderText = "Enter profile name..."
profileInput.TextColor3 = Color3.fromRGB(255, 255, 255)
profileInput.Font = Enum.Font.Gotham
profileInput.TextSize = 12
profileInput.Parent = configPage
local piCorner = Instance.new("UICorner")
piCorner.CornerRadius = UDim.new(0, 4)
piCorner.Parent = profileInput
local saveBtn = Instance.new("TextButton")
saveBtn.Size = UDim2.new(0, 70, 0, 30)
saveBtn.Position = UDim2.new(1, -85, 0, 15)
saveBtn.BackgroundColor3 = Color3.fromRGB(0, 120, 200)
saveBtn.Font = Enum.Font.GothamBold
saveBtn.Text = "Save"
saveBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
saveBtn.TextSize = 12
saveBtn.Parent = configPage
local sbCorner = Instance.new("UICorner")
sbCorner.CornerRadius = UDim.new(0, 4)
sbCorner.Parent = saveBtn
local listFrame = Instance.new("ScrollingFrame")
listFrame.Size = UDim2.new(1, -30, 1, -70)
listFrame.Position = UDim2.new(0, 15, 0, 55)
listFrame.BackgroundTransparency = 1
listFrame.BorderSizePixel = 0
listFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
listFrame.ScrollBarThickness = 4
listFrame.Parent = configPage
local listLayout = Instance.new("UIListLayout")
listLayout.Padding = UDim.new(0, 5)
listLayout.SortOrder = Enum.SortOrder.LayoutOrder
listLayout.Parent = listFrame
local function refreshProfileList()
for _, item in ipairs(listFrame:GetChildren()) do
if item:IsA("Frame") then item:Destroy() end
end
local count = 0
for name, data in pairs(savedProfiles) do
count = count + 1
local row = Instance.new("Frame")
row.Size = UDim2.new(1, -5, 0, 35)
row.BackgroundColor3 = Color3.fromRGB(30, 30, 35)
row.BorderSizePixel = 0
row.Parent = listFrame
local rCorner = Instance.new("UICorner")
rCorner.CornerRadius = UDim.new(0, 4)
rCorner.Parent = row
local rLabel = Instance.new("TextLabel")
rLabel.Size = UDim2.new(1, -85, 1, 0)
rLabel.Position = UDim2.new(0, 10, 0, 0)
rLabel.BackgroundTransparency = 1
rLabel.Text = name
rLabel.TextColor3 = Color3.fromRGB(230, 230, 230)
rLabel.Font = Enum.Font.GothamSemibold
rLabel.TextSize = 12
rLabel.TextXAlignment = Enum.TextXAlignment.Left
rLabel.Parent = row
local loadBtn = Instance.new("TextButton")
loadBtn.Size = UDim2.new(0, 60, 0, 25)
loadBtn.Position = UDim2.new(1, -70, 0.5, -12)
loadBtn.BackgroundColor3 = Color3.fromRGB(50, 150, 50)
loadBtn.Font = Enum.Font.GothamBold
loadBtn.Text = "Load"
loadBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
loadBtn.TextSize = 11
loadBtn.Parent = row
local lCorner = Instance.new("UICorner")
lCorner.CornerRadius = UDim.new(0, 4)
lCorner.Parent = loadBtn
loadBtn.MouseButton1Click:Connect(function()
CFG.mainExtend = data.mainExtend
CFG.deflectExtend = data.deflectExtend
CFG.bounceLogic = data.bounceLogic
CFG.mainColor = Color3.fromRGB(data.mainColor[1], data.mainColor[2], data.mainColor[3])
CFG.deflectColor = Color3.fromRGB(data.deflectColor[1], data.deflectColor[2], data.deflectColor[3])
mainLenFill.Size = UDim2.new(CFG.mainExtend / 2000, 0, 1, 0)
mainLenKnob.Position = UDim2.new(CFG.mainExtend / 2000, -6, 0.5, -6)
mainLenLabel.Text = "Main Length: " .. tostring(CFG.mainExtend)
deflectLenFill.Size = UDim2.new(CFG.deflectExtend / 2000, 0, 1, 0)
deflectLenKnob.Position = UDim2.new(CFG.deflectExtend / 2000, -6, 0.5, -6)
deflectLenLabel.Text = "Deflect Length: " .. tostring(CFG.deflectExtend)
mainColorBox.Text = string.format("%d,%d,%d", CFG.mainColor.R*255, CFG.mainColor.G*255, CFG.mainColor.B*255)
deflectColorBox.Text = string.format("%d,%d,%d", CFG.deflectColor.R*255, CFG.deflectColor.G*255, CFG.deflectColor.B*255)
updateBounceUI()
end)
end
listFrame.CanvasSize = UDim2.new(0, 0, 0, count * 40)
end
saveBtn.MouseButton1Click:Connect(function()
local name = profileInput.Text:gsub("[^%w_-]", "")
if name ~= "" then
local data = {
mainExtend = CFG.mainExtend,
deflectExtend = CFG.deflectExtend,
bounceLogic = CFG.bounceLogic,
mainColor = {math.round(CFG.mainColor.R*255), math.round(CFG.mainColor.G*255), math.round(CFG.mainColor.B*255)},
deflectColor = {math.round(CFG.deflectColor.R*255), math.round(CFG.deflectColor.G*255), math.round(CFG.deflectColor.B*255)}
}
saveProfileToDisk(name, data)
profileInput.Text = ""
refreshProfileList()
end
end)
refreshProfileList()
end
createUI()
local function isBallBlocking(startPos, endPos, tableFolder, ignoreLineMirror)
if not tableFolder then return false end
local ballsFolder = tableFolder:FindFirstChild("Balls")
if not ballsFolder then return false end
local dir = (endPos - startPos)
local dist = dir.Magnitude
if dist < 0.5 then return false end
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
local targets = {}
for _, obj in ipairs(ballsFolder:GetChildren()) do
if obj:IsA("BasePart") and obj ~= ignoreLineMirror then
if tonumber(obj.Name) then
table.insert(targets, obj)
end
end
end
if #targets == 0 then return false end
raycastParams.FilterDescendantsInstances = targets
local segments = 8
local radius = 0.35
for i = 1, segments do
local frac = (i - 1) / (segments - 1)
local checkPos = startPos + (dir.Unit * (frac * dist))
local result = ws:Raycast(checkPos, Vector3.new(0, -5, 0), raycastParams)
if result and result.Instance then
if (result.Instance.Position - checkPos).Magnitude 0 then tX = (maxX - currentPos.X) / currentDir.X
elseif currentDir.X 0 then tZ = (maxZ - currentPos.Z) / currentDir.Z
elseif currentDir.Z 0 and tMin < remainingDist then
currentPos = currentPos + currentDir * tMin
remainingDist = remainingDist - tMin
if not CFG.bounceLogic or isDeflectionLine then
remainingDist = 0
break
else
if tMin == tX then
currentDir = Vector3.new(-currentDir.X, currentDir.Y, currentDir.Z)
else
currentDir = Vector3.new(currentDir.X, currentDir.Y, -currentDir.Z)
end
end
else
break
end
end
local finalLocalPos = currentPos + (currentDir * remainingDist)
return tableCF:PointToWorldSpace(finalLocalPos)
end
local function getLinePoints(part)
local pos, cf = part.Position, part.CFrame
local right = cf.RightVector
local halfW = part.Size.X / 2
return pos - right * halfW, pos + right * halfW
end
local function update3DLinePart(cPart, lineMirrorPart, length, tablePart, tableFolder, alpha, isDeflectionLine, forceColorOverride)
if not lineMirrorPart then
cPart.Transparency = 1
return nil, nil
end
local start3D, end3D = getLinePoints(lineMirrorPart)
local dir3D = (end3D - start3D)
if dir3D.Magnitude < 0.001 then
cPart.Transparency = 1
return nil, nil
end
local final3DTarget = calculateBounces3D(start3D, dir3D.Unit, length, tablePart, isDeflectionLine)
if CFG.matchBallHeight and tablePart then
final3DTarget = Vector3.new(final3DTarget.X, start3D.Y, final3DTarget.Z)
end
local distance = (final3DTarget - start3D).Magnitude
if distance < 0.01 then
cPart.Transparency = 1
return nil, nil
end
local isBlocked = forceColorOverride or isBallBlocking(start3D, final3DTarget, tableFolder, lineMirrorPart)
if isBlocked then
local alternatePulse = (math.sin(state.pulsePhase * 2.5) + 1) / 2
cPart.Color = CFG.warnColor:Lerp(Color3.fromRGB(255, 0, 0), alternatePulse)
else
cPart.Color = isDeflectionLine and CFG.deflectColor or CFG.mainColor
end
cPart.Size = Vector3.new(distance, 0.06, 0.06)
cPart.CFrame = CFrame.lookAt(start3D, final3DTarget) * CFrame.new(0, 0, -distance / 2) * CFrame.Angles(0, math.rad(90), 0)
cPart.Transparency = 1 - alpha
return final3DTarget, isBlocked
end
local function cleanup()
if container then container:Destroy() end
end
if _G._trajCleanup then _G._trajCleanup() end
_G._trajCleanup = cleanup
local function lerp(a, b, t) return a + (b - a) * t end
rs.RenderStepped:Connect(function(dt)
state.pulsePhase = state.pulsePhase + dt * CFG.pulseSpeed
local pulse = (math.sin(state.pulsePhase) + 1) / 2
local liveAlpha = lerp(CFG.pulseMin, CFG.pulseMax, pulse)
local tv = ws:FindFirstChild("TrajectoryViz")
local poolsModel = ws:FindFirstChild("Pools")
local activeFelt = nil
local activeTableFolder = nil
if poolsModel then
local shortestDist = math.huge
local lp = Players.LocalPlayer
local char = lp and lp.Character
local root = char and char:FindFirstChild("HumanoidRootPart")
if root then
for _, folder in ipairs(poolsModel:GetChildren()) do
local felt = folder:FindFirstChild("PoolLevel1")
if felt and felt:IsA("BasePart") then
local dist = (root.Position - felt.Position).Magnitude
if dist < shortestDist and dist < 50 then
shortestDist = dist
activeFelt = felt
activeTableFolder = folder
end
end
end
end
end
if not tv then
draw3D.main.Transparency = 1
draw3D.deflect.Transparency = 1
return
end
local mainHitTarget, mainBlocked = update3DLinePart(draw3D.main, tv:FindFirstChild("TrajHitLine"), CFG.mainExtend, activeFelt, activeTableFolder, liveAlpha, false, false)
update3DLinePart(draw3D.deflect, tv:FindFirstChild("TrajDeflectLine"), CFG.deflectExtend, activeFelt, activeTableFolder, liveAlpha, true, mainBlocked)
end)