Is there anyway i could improve this grabbing system?
Some feedback will be very much appreciated!
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
repeat wait() until Player.Character
local Char = Player.Character
local Humanoid = Char:WaitForChild("Humanoid")
local HRP = Char:WaitForChild("HumanoidRootPart")
local PlayerGui = Player:WaitForChild("PlayerGui")
local GrabGui = PlayerGui:WaitForChild("GrabGui")
local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Mouse = Player:GetMouse()
local Camera = workspace.CurrentCamera
local SetNetworkOwnerEvent = ReplicatedStorage:WaitForChild("SetNetworkOwnerEvent")
local GrabEvent = ReplicatedStorage:WaitForChild("GrabEvent")
local Holding = false
local MaxGrabDistance = 10
local Object
local GrabbingForce
local GrabbingGyro
local RotatingR = false
local RotatingT = false
local RotateIncrement = math.rad(2)
local RotateCFrame = CFrame.Angles(0, 0, 0)
local ObjectDistance
local Animation = script:WaitForChild("HoldAnimation")
local AnimTrack = nil
function PlayAnimation(PlayAnim)
if PlayAnim and not AnimTrack then
AnimTrack = Humanoid:LoadAnimation(Animation)
AnimTrack:Play()
elseif AnimTrack and not PlayAnim then
AnimTrack:Stop()
AnimTrack = nil
end
end
-- Functions
function Grab()
print("Grabbing")
local BodyPos = Instance.new("BodyPosition")
local BodyGyro = Instance.new("BodyGyro")
BodyPos.D = 650
BodyGyro.D = 150
BodyGyro.MaxTorque = Vector3.new(2000, 2000, 2000)
Object = Mouse.Target
local CanGrab = Object.CanGrab
GrabEvent:FireServer(CanGrab, false)
CanGrab.Value = false
SetNetworkOwnerEvent:FireServer(Object, true)
RotateCFrame = Object.CFrame
GrabbingForce = BodyPos
GrabbingGyro = BodyGyro
GrabbingForce.Name = "GrabbingForce"
GrabbingForce.Parent = Object
GrabbingGyro.Name = "GrabbingGyro"
GrabbingGyro.Parent = Object
ObjectDistance = (Mouse.Target.Position - HRP.Position).Magnitude
PlayAnimation(true)
Holding = true
end
function Release()
if Holding == true then
print("Releasing")
GrabbingForce:Destroy()
GrabbingGyro:Destroy()
SetNetworkOwnerEvent:FireServer(Object, false)
GrabEvent:FireServer(Object:FindFirstChild("CanGrab"), true)
local CanGrab = Object.CanGrab
CanGrab.Value = true
PlayAnimation(false)
Holding = false
Object = nil
end
end
-- Start Grab
UIS.InputBegan:Connect(function(inputObject)
if (inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.KeyCode == Enum.KeyCode.ButtonR2) and Mouse.Target and not Mouse.Target.Locked and Humanoid.Health > 0 then
local magnitude = (Mouse.Target.Position - HRP.Position).Magnitude
local CanGrabValue = Mouse.Target:FindFirstChild("CanGrab")
if Mouse.Target and not Mouse.Target.Locked and magnitude < MaxGrabDistance and not Holding and CanGrabValue and CanGrabValue.Value == true then
Grab()
else
Release()
end
end
end)
-- End Grab
UIS.InputEnded:Connect(function(inputObject)
if inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.KeyCode == Enum.KeyCode.ButtonR2 then
Release()
end
end)
RS.RenderStepped:Connect(function()
-- Grab GUI
if Mouse.Target and not Mouse.Target.Locked then
local magnitude = (Mouse.Target.Position - HRP.Position).Magnitude
if magnitude < MaxGrabDistance and not Holding then
local CanGrabValue = Mouse.Target:FindFirstChild("CanGrab")
if CanGrabValue and CanGrabValue.Value == true then
GrabGui.GrabText.Visible = true
else
GrabGui.GrabText.Visible = false
end
else
GrabGui.GrabText.Visible = false
end
else
GrabGui.GrabText.Visible = false
end
-- Grabbing
if Holding and Object and Object:IsA("BasePart") then
local magnitude = (Object.Position - HRP.Position).Magnitude
if Holding and Object and GrabbingForce and GrabbingGyro and magnitude < (MaxGrabDistance + 5) then
GrabbingForce.Position = Camera.CFrame.Position + (Mouse.UnitRay.Direction * (ObjectDistance + (workspace.CurrentCamera.CoordinateFrame.p - HRP.Position + Vector3.new(0, 1, 0)).magnitude - 2))
if RotatingR then
local rotateCFrame2 = CFrame.Angles(RotateIncrement, 0, 0)
RotateCFrame = GrabbingGyro.CFrame:ToWorldSpace(rotateCFrame2)
GrabbingGyro.CFrame = RotateCFrame
print("R")
end
if RotatingT then
local rotateCFrame2 = CFrame.Angles(0, RotateIncrement, 0)
RotateCFrame = GrabbingGyro.CFrame:ToWorldSpace(rotateCFrame2)
GrabbingGyro.CFrame = RotateCFrame
print("T")
end
else
Release()
end
-- Anti fly
if Object then
Object.Touched:Connect(function(hit)
if hit.Parent and hit.Parent == Char then
Release()
end
end)
end
end
-- Item price tag
if Mouse.Target then
local PurchasableItem = Mouse.Target:FindFirstChild("PurchasableItem")
local magnitude = (Mouse.Target.Position - HRP.Position).Magnitude
if not Holding and PurchasableItem and magnitude <= MaxGrabDistance then
local Gui = Mouse.Target:FindFirstChild("ItemInfoGui")
if Gui then
Gui.Enabled = true
repeat
wait()
until not Mouse.Target or (Mouse.Target and not Mouse.Target:FindFirstChild("PurchasableItem")) or Holding
Gui.Enabled = false
end
end
end
end)
--== Rotate/Tilt Object ==--
-- Start Rotate/Tilt
UIS.InputBegan:Connect(function(inpObj, gp)
if inpObj.KeyCode == Enum.KeyCode.R then -- Rotate
RotatingR = true
end
if inpObj.KeyCode == Enum.KeyCode.T then -- Tilt
RotatingT = true
end
end)
-- Stop Rotate/Tilt
UIS.InputEnded:Connect(function(inpObj, gp)
if inpObj.KeyCode == Enum.KeyCode.R then -- Rotate
RotatingR = false
end
if inpObj.KeyCode == Enum.KeyCode.T then -- Tilt
RotatingT = false
end
end)
--== Make sure that theres no floating object when the player leaves or dies ==--
Players.PlayerRemoving:Connect(function(player)
if Object and Object.Parent and player == Player then
Release()
end
end)
Humanoid.Died:Connect(function()
if Object and Object.Parent then
Release()
end
end)