local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local VirtualInputManager = game:GetService("VirtualInputManager")

local Player = Players.LocalPlayer
local Cooldown = 0
local Parried = false
local Connection = nil

-- Get the current active ball targeting players
local function GetBall()
	for _, Ball in ipairs(workspace.Balls:GetChildren()) do
		if Ball:GetAttribute("realBall") then
			return Ball
		end
	end
end

-- Disconnect previous attribute listener if needed
local function ResetConnection()
	if Connection then
		Connection:Disconnect()
		Connection = nil
	end
end

-- Watch for new balls and listen to their "target" attribute
workspace.Balls.ChildAdded:Connect(function()
	local Ball = GetBall()
	if not Ball then return end
	ResetConnection()
	if Ball:GetAttribute("target") == nil then return end
	Connection = Ball:GetAttributeChangedSignal("target"):Connect(function()
		Parried = false
	end)
end)

-- Main loop for detection and parrying
RunService.PreSimulation:Connect(function()
	local Ball = GetBall()
	if not Ball then return end

	local Target = Ball:GetAttribute("target")
	if not Target or Target ~= Player.Name then return end

	local Character = Player.Character
	if not Character then return end

	local HRP = Character:FindFirstChild("HumanoidRootPart")
	if not HRP then return end

	local Zoomies = Ball:FindFirstChild("zoomies")
	if not Zoomies or not Zoomies:FindFirstChild("VectorVelocity") then return end

	local BallVelocity = Zoomies.VectorVelocity
	local Speed = BallVelocity.Magnitude
	if Speed < 1 then return end

	local BallToPlayer = HRP.Position - Ball.Position
	local Distance = BallToPlayer.Magnitude
	local TimeToImpact = Distance / Speed

	-- Calculate the ball's angular velocity (spin)
	local AngularVelocity = Zoomies:FindFirstChild("AngularVelocity")
	if not AngularVelocity then return end

	local AngularSpeed = AngularVelocity.Magnitude  -- Assuming it has a Vector3 AngularVelocity (spin axis)
	local CurvatureFactor = AngularSpeed / Speed  -- A simple ratio to control the curve's strength

	-- Calculate how much the ball might curve towards the player
	local CurveAmount = BallVelocity.Unit:Cross(AngularVelocity.Unit).Magnitude * CurvatureFactor
	local CurvedPrediction = Ball.Position + BallVelocity * 0.2 + Vector3.new(CurveAmount, 0, 0) -- Adjust this for your axis

	-- Directional check to ensure it's aimed toward player
	local Direction = BallVelocity.Unit
	local Alignment = Direction:Dot(BallToPlayer.Unit)
	local AngularThreshold = 0.98
	local CloseEnough = Distance <= 60

	-- Adjust time-to-impact detection based on the ball's curvature
	local bufferTime = 0.05  -- Add buffer time for earlier parry reactions
	local adjustedParryWindow = 0.4  -- Base window for parry timing (adjustable)

	-- Speed-based parry window adjustment
	local speedThreshold = 50  -- Speed threshold that will change timing window
	if Speed > speedThreshold then
		adjustedParryWindow = adjustedParryWindow - 0.1  -- Shorten window for faster balls
	elseif Speed < speedThreshold then
		adjustedParryWindow = adjustedParryWindow + 0.1  -- Extend window for slower balls
	end

	-- Trigger parry if conditions are met, factoring in curvature and timing
	if Alignment >= AngularThreshold and CloseEnough and not Parried and TimeToImpact <= (adjustedParryWindow - bufferTime) then
		local PredictedHit = (CurvedPrediction - HRP.Position).Magnitude <= 2  -- Close enough to the predicted position
		if PredictedHit then
			VirtualInputManager:SendMouseButtonEvent(0, 0, 0, true, game, 0)
			Parried = true
			Cool
down = tick()
		end
	elseif Parried and (tick() - Cooldown) >= 1 then
		Parried = false
	end
end)

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: