File size: 5,270 Bytes
0712d5f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | -- 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)
|