Trying to remake a Lumber Tycoon 2 Grab System

Hello, I’m currently doing game when I need some grab system, So I tried to remake the one that have Lumber Tycoon 2, But the basic systems works like detection of keys , But the moving part I can’t figure out how it can be done,

My version:

So if you play it and you will come near to the part and click on it it will works but not as original Lumber Tycoon 2 system

My code

-- Server Script
local remotes = game.ReplicatedStorage.GrabRemotes

game.Players.PlayerAdded:Connect(function(plr)
	local GrabbingItem = Instance.new("StringValue",plr)
	GrabbingItem.Name = "CurrentGrabbing"
	
	local IsGrabbing = Instance.new("BoolValue",plr)
	IsGrabbing.Name = "IsGrabing"
	IsGrabbing.Value = false
end)

local AllowedModels = {
	"TestPart"
}

remotes.initGrabbing.OnServerEvent:Connect(function(plr,Item)
	if table.find(AllowedModels,Item.Name) ~= nil then
		print("Succesfully start grabbing init!")
		plr.CurrentGrabbing.Value = Item.Name
		plr.IsGrabing.Value = true
		
	end
end) 
remotes.resetGrabbing.OnServerEvent:Connect(function(plr)
	print("Sucesfully reseted grabbing values")
	plr.CurrentGrabbing.Value = ""
	plr.IsGrabing.Value = false
end)
remotes.CheckIfTrue.OnServerInvoke = function(plr,Item)
	if table.find(AllowedModels,Item.Name) ~= nil then
		return true
	else
		return false
	end
end
remotes.IsGrabbing.OnServerInvoke = function(plr)
	if plr.IsGrabing.Value == true then
		return true
	else
		return false
	end
end
remotes.MoveItem.OnServerEvent:Connect(function(plr,pos)
	if plr.IsGrabing.Value == true then
		workspace[plr.CurrentGrabbing.Value].Position = pos + Vector3.new(0,2,0)
	end
end)

Thanks for any help!

4 Likes

You did not understand it, It is working but the position of part is not correct

I don’t know how you calculate the position on the client, but I believe it could be a good idea to use an AlignPosition constraint for moving instead of directly setting the position. You should also add a limit to how far away the dragged part can be from the player.

Server:

local remotes = game.ReplicatedStorage.GrabRemotes

local function createAlignPos(part)
	local alignPos = Instance.new("AlignPosition")
	alignPos.MaxForce = 10000
	alingPos.Responsiveness = 200
	
	local attach0, attach1 = Instance.new("Attachment"), Instance.new("Attachment")
	alignPos.Attachment0, alignPos.Attachment1 = attach0, attach1
	
	attach0.Parent, attach1.Parent = workspace.Terrain, part
	alignPos.Parent = part
	
	return alignPos
end

local function destroyAlignPos()
	alignPos.Attachment0:Destroy()
	alignPos.Attachment1:Destroy()
	alignPos:Destroy()
end

game.Players.PlayerAdded:Connect(function(plr)
	local GrabbingItem = Instance.new("StringValue",plr)
	GrabbingItem.Name = "CurrentGrabbing"
	
	local IsGrabbing = Instance.new("BoolValue",plr)
	IsGrabbing.Name = "IsGrabing"
	IsGrabbing.Value = false
end)

local AllowedModels = {
	"TestPart"
}

remotes.initGrabbing.OnServerEvent:Connect(function(plr,Item)
	if table.find(AllowedModels,Item.Name) ~= nil then
		print("Succesfully start grabbing init!")
		createAlignPos(item)
		plr.CurrentGrabbing.Value = Item.Name
		plr.IsGrabing.Value = true
	end
end) 

remotes.resetGrabbing.OnServerEvent:Connect(function(plr)
	print("Sucesfully reseted grabbing values")
	destroyAlignPos(plr.CurrentGrabbing.Value.AlignPosition)
	plr.CurrentGrabbing.Value = ""
	plr.IsGrabing.Value = false
end)

remotes.CheckIfTrue.OnServerInvoke = function(plr,Item)
	return table.find(AllowedModels,Item.Name) ~= nil
end

remotes.IsGrabbing.OnServerInvoke = function(plr)
	return plr.IsGrabbing.Value
end

remotes.MoveItem.OnServerEvent:Connect(function(plr, pos)
	if plr.IsGrabing.Value == true then
		plr.CurrentGrabbing.Value.AlignPosition.Attachment0.Position = pos
	end
end)

Client side position calculation

local Players = game:GetService("Players")

local ITEM_MAX_DISTANCE = 20

local plr = Players.LocalPlayer
local mouse = plr:GetMouse()

local raycastParams = RayCastParams.new()
raycastParams.FilterType = Enum.FilterType.BlackList

local function calculatePos() -- send the return value of this to the server
	raycastParams.FilterDescendantsInstances = {plr.Character, plr.CurrentGrabbing.Value}
	local unitRay = mouse.UnitRay
	local origin = unitRay.Origin
	local directionWithMagnitude = unitRay.Direction*ITEM_MAX_DISTANCE
	local rayCastResult = workspace:RayCast(origin, directionWithMagnitude, raycastParams)
	if rayCastResult then
		return rayCastResult.Position
	else return origin+directionWithMagnitude
	end
end
3 Likes

I made one of these systems a while back for one of my games and you should use BodyPositions to move the part. You can use math.clamp to prevent the part from moving too far away from the player. If the game is multiplayer, make sure to set the network ownership of the part to the server to avoid glitching.