| |
|
| | local Players = game:GetService("Players")
|
| | local UserInputService = game:GetService("UserInputService")
|
| | local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
| | local RunService = game:GetService("RunService")
|
| | local CollectionService = game:GetService("CollectionService")
|
| |
|
| | local player = Players.LocalPlayer
|
| | local mouse = player:GetMouse()
|
| | local camera = workspace.CurrentCamera
|
| | local character = player.Character or player.CharacterAdded:Wait()
|
| |
|
| | local DraggingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("DraggingConfig"))
|
| | local DragEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("DragEvent")
|
| | local DropEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("DropEvent")
|
| |
|
| | local isDragging = false
|
| | local draggedPart = nil
|
| | local targetAttachment = nil
|
| | local currentHoldDistance = DraggingConfig.HoldDistance
|
| | local highlightedPart = nil
|
| | local highlight = nil
|
| |
|
| | local renderConnection = nil
|
| | local hoverConnection = nil
|
| |
|
| |
|
| | local function createHighlight(part)
|
| | removeHighlight()
|
| | if not part then return end
|
| |
|
| | highlight = Instance.new("SelectionBox")
|
| | highlight.Adornee = part
|
| | highlight.Color3 = Color3.fromRGB(100, 200, 255)
|
| | highlight.LineThickness = 0.03
|
| | highlight.SurfaceTransparency = 0.8
|
| | highlight.SurfaceColor3 = Color3.fromRGB(100, 200, 255)
|
| | highlight.Parent = part
|
| |
|
| | highlightedPart = part
|
| | end
|
| |
|
| | function removeHighlight()
|
| | if highlight then
|
| | highlight:Destroy()
|
| | highlight = nil
|
| | end
|
| | highlightedPart = nil
|
| | end
|
| |
|
| |
|
| | local function updateHover()
|
| | if isDragging then return end
|
| |
|
| | local target = mouse.Target
|
| | if target and (CollectionService:HasTag(target, "Draggable") or CollectionService:HasTag(target, "TreeSegment")) then
|
| | if target ~= highlightedPart then
|
| | createHighlight(target)
|
| | end
|
| | else
|
| | removeHighlight()
|
| | end
|
| | end
|
| |
|
| | local function updateDraggingPosition()
|
| | if not isDragging or not draggedPart or not targetAttachment then return end
|
| |
|
| | local char = player.Character
|
| | if not char then return end
|
| |
|
| | local head = char:FindFirstChild("Head")
|
| | if not head then return end
|
| |
|
| | local rayOrigin = head.Position
|
| | local rayDirection = camera.CFrame.LookVector * currentHoldDistance
|
| |
|
| | local raycastParams = RaycastParams.new()
|
| | raycastParams.FilterDescendantsInstances = {char, draggedPart}
|
| | raycastParams.FilterType = Enum.RaycastFilterType.Exclude
|
| |
|
| | local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
|
| |
|
| | local targetPos = rayOrigin + rayDirection
|
| | if raycastResult then
|
| | targetPos = raycastResult.Position
|
| | end
|
| |
|
| | targetAttachment.WorldCFrame = CFrame.new(targetPos) * CFrame.Angles(0, camera.CFrame.Rotation.Y, 0)
|
| | end
|
| |
|
| | local function stopDragging()
|
| | if not isDragging then return end
|
| | isDragging = false
|
| | draggedPart = nil
|
| | targetAttachment = nil
|
| | currentHoldDistance = DraggingConfig.HoldDistance
|
| |
|
| | if renderConnection then
|
| | renderConnection:Disconnect()
|
| | renderConnection = nil
|
| | end
|
| |
|
| | DropEvent:FireServer()
|
| | end
|
| |
|
| | local function onInputBegan(input, gameProcessed)
|
| | if gameProcessed then return end
|
| |
|
| | if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
| | if isDragging then return end
|
| |
|
| | local targetPart = mouse.Target
|
| | if not targetPart then return end
|
| |
|
| | if not CollectionService:HasTag(targetPart, "Draggable") and not CollectionService:HasTag(targetPart, "TreeSegment") then return end
|
| |
|
| | local char = player.Character
|
| | if not char or not char:FindFirstChild("HumanoidRootPart") then return end
|
| |
|
| | local distance = (char.HumanoidRootPart.Position - targetPart.Position).Magnitude
|
| | if distance > DraggingConfig.MaxGrabDistance then return end
|
| |
|
| | removeHighlight()
|
| |
|
| | DragEvent:FireServer(targetPart, mouse.Hit.Position)
|
| |
|
| | local attachmentName = "TargetAttachment_Player" .. player.UserId
|
| |
|
| | local t = 0
|
| | while not workspace.Terrain:FindFirstChild(attachmentName) and t < 1 do
|
| | t = t + task.wait()
|
| | end
|
| |
|
| | targetAttachment = workspace.Terrain:FindFirstChild(attachmentName)
|
| |
|
| | if targetAttachment then
|
| | isDragging = true
|
| | draggedPart = targetPart
|
| | currentHoldDistance = DraggingConfig.HoldDistance
|
| |
|
| | renderConnection = RunService.RenderStepped:Connect(updateDraggingPosition)
|
| | end
|
| | end
|
| | end
|
| |
|
| | local function onInputEnded(input, gameProcessed)
|
| | if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
| | stopDragging()
|
| | end
|
| | end
|
| |
|
| |
|
| | local function onInputChanged(input)
|
| | if not isDragging then return end
|
| |
|
| | if input.UserInputType == Enum.UserInputType.MouseWheel then
|
| | currentHoldDistance = math.clamp(
|
| | currentHoldDistance + input.Position.Z * 2,
|
| | 3,
|
| | DraggingConfig.MaxGrabDistance
|
| | )
|
| | end
|
| | end
|
| |
|
| |
|
| | player.CharacterAdded:Connect(function(char)
|
| | character = char
|
| | camera = workspace.CurrentCamera
|
| | stopDragging()
|
| | end)
|
| |
|
| |
|
| | hoverConnection = RunService.RenderStepped:Connect(updateHover)
|
| |
|
| | UserInputService.InputBegan:Connect(onInputBegan)
|
| | UserInputService.InputEnded:Connect(onInputEnded)
|
| | UserInputService.InputChanged:Connect(onInputChanged)
|
| |
|