algorembrant's picture
Upload 88 files
0712d5f verified
-- src/StarterPlayer/StarterCharacterScripts/DragController.client.lua
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
-- Create highlight effect
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
-- Hover detection for draggable parts
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
-- Scroll wheel for hold distance adjustment
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
-- Respawn handling
player.CharacterAdded:Connect(function(char)
character = char
camera = workspace.CurrentCamera
stopDragging()
end)
-- Hover detection loop
hoverConnection = RunService.RenderStepped:Connect(updateHover)
UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)
UserInputService.InputChanged:Connect(onInputChanged)