Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --// SERVICES
- local Players = game:GetService("Players")
- local RunService = game:GetService("RunService")
- local LocalPlayer = Players.LocalPlayer
- --// SETTINGS
- local MAX_REACH = 14
- local MIN_REACH = 14
- local DETECTION_RANGE = 21
- local CLOSE_HIT = 9
- local PREDICTION = 0.18
- local FIRETOUCH_DELAY = 0
- local JUMP_STATES = {
- [Enum.HumanoidStateType.Jumping] = true,
- [Enum.HumanoidStateType.Freefall] = true
- }
- --// VARIABLES
- local equipped = false
- local tool, bubble = nil, nil
- local hue = 0
- local heartbeatConnection
- --// FUNCTIONS
- -- Create visual bubble
- local function createBubble()
- local part = Instance.new("Part")
- part.Name = "SafeReachBubble"
- part.Anchored = true
- part.CanCollide = false
- part.CastShadow = false
- part.Shape = Enum.PartType.Ball
- part.Material = Enum.Material.ForceField
- part.Transparency = 0.2
- part.Color = Color3.fromHSV(0, 1, 1)
- part.Size = Vector3.new(MAX_REACH * 2, MAX_REACH * 2, MAX_REACH * 2)
- part.Parent = LocalPlayer.Character
- return part
- end
- -- Check visibility with raycasting
- local function isClear(origin, targetPos, targetChar)
- local dir = targetPos - origin
- local params = RaycastParams.new()
- params.FilterType = Enum.RaycastFilterType.Whitelist
- params.FilterDescendantsInstances = { targetChar }
- params.IgnoreWater = true
- local result = workspace:Raycast(origin, dir, params)
- return result and result.Instance and result.Instance:IsDescendantOf(targetChar)
- end
- -- Fire simulated touch
- local function touchCharacter(char, fromPos)
- local hrp = char:FindFirstChild("HumanoidRootPart")
- local handle = tool and tool:FindFirstChild("Handle")
- if not handle or not hrp then return end
- local distance = (fromPos - hrp.Position).Magnitude
- if distance > 8.9 then return end
- for _, part in ipairs(char:GetChildren()) do
- if part:IsA("BasePart") then
- task.delay(FIRETOUCH_DELAY, function()
- firetouchinterest(handle, part, 0)
- firetouchinterest(handle, part, 1)
- end)
- end
- end
- end
- -- Adjust reach based on movement
- local function getAdjustedReach(player, hrp, humanoid)
- if JUMP_STATES[humanoid:GetState()] then
- return MIN_REACH
- end
- local moveDir = humanoid.MoveDirection
- local toPlayer = (LocalPlayer.Character.HumanoidRootPart.Position - hrp.Position).Unit
- if moveDir.Magnitude > 0.1 and moveDir:Dot(-toPlayer) > 0.5 then
- return MIN_REACH
- end
- return MAX_REACH
- end
- -- Stop main loop
- local function stopLoop()
- if heartbeatConnection then
- heartbeatConnection:Disconnect()
- heartbeatConnection = nil
- end
- end
- -- When tool is equipped
- local function onEquipped()
- equipped = true
- tool = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Tool")
- if not tool then return end
- if not bubble then
- bubble = createBubble()
- end
- stopLoop()
- heartbeatConnection = RunService.Heartbeat:Connect(function()
- local char = LocalPlayer.Character
- local hrp = char and char:FindFirstChild("HumanoidRootPart")
- if not equipped or not tool or not hrp then return end
- hue = (hue + 0.01) % 1
- if bubble then
- bubble.Position = hrp.Position
- bubble.Color = Color3.fromHSV(hue, 1, 1)
- end
- for _, target in ipairs(Players:GetPlayers()) do
- if target ~= LocalPlayer and target.Character then
- local tChar = target.Character
- local tHRP = tChar:FindFirstChild("HumanoidRootPart")
- local humanoid = tChar:FindFirstChildOfClass("Humanoid")
- if tHRP and humanoid and humanoid.Health > 0 then
- local rawDistance = (hrp.Position - tHRP.Position).Magnitude
- -- Skip players who are farther than 9.3 studs
- if rawDistance > 9.3 then continue end
- if rawDistance <= DETECTION_RANGE then
- local reach = getAdjustedReach(target, tHRP, humanoid)
- if bubble then
- bubble.Size = Vector3.new(reach * 2, reach * 2, reach * 2)
- end
- if rawDistance <= reach then
- if rawDistance <= CLOSE_HIT then
- touchCharacter(tChar, hrp.Position)
- else
- local predicted = tHRP.Position + tHRP.Velocity * PREDICTION
- if isClear(hrp.Position, predicted, tChar) then
- touchCharacter(tChar, hrp.Position)
- elseif isClear(hrp.Position, tHRP.Position, tChar) then
- touchCharacter(tChar, hrp.Position)
- end
- end
- end
- end
- end
- end
- end
- end)
- end
- -- When tool is unequipped
- local function onUnequipped()
- equipped = false
- stopLoop()
- if bubble then
- bubble:Destroy()
- bubble = nil
- end
- end
- -- Set up character on spawn
- local function setupCharacter(char)
- local humanoid = char:FindFirstChildOfClass("Humanoid")
- local backpack = LocalPlayer:FindFirstChild("Backpack")
- if humanoid and backpack then
- local toolInBackpack = backpack:FindFirstChildOfClass("Tool")
- if toolInBackpack then
- humanoid:EquipTool(toolInBackpack)
- end
- end
- char.ChildAdded:Connect(function(child)
- if child:IsA("Tool") then
- child.Equipped:Connect(onEquipped)
- child.Unequipped:Connect(onUnequipped)
- end
- end)
- for _, child in ipairs(char:GetChildren()) do
- if child:IsA("Tool") then
- child.Equipped:Connect(onEquipped)
- child.Unequipped:Connect(onUnequipped)
- end
- end
- end
- -- INIT
- if LocalPlayer.Character then
- setupCharacter(LocalPlayer.Character)
- end
- LocalPlayer.CharacterAdded:Connect(setupCharacter)
Advertisement
Add Comment
Please, Sign In to add comment