First Tool Ever

Hello, this is the first tool that I’ve created. Essentially what it does is when equipped a blueprint of a build pops up where the mouse position is, and when you hold your mouse down, it places a built version; up to a total of 5 uses before deletion.
What do you guys think? How can I improve this to make it cleaner and run more efficiently? I am somewhat new to scripting.

LocalScript
local Tool = script.Parent
local player = game.Players.LocalPlayer
local UserInputService = game:GetService("UserInputService")
local mouse = game.Players.LocalPlayer:GetMouse()
local equipped = false
local mtarget = game.ReplicatedStorage.PlacementSandbags
local BuiltSandBags = game.ReplicatedStorage.BuildEvent
local BuiltBarbedWire = game.ReplicatedStorage.BuiltBarbed
local mouseDown = false
local i = 0
local uses = 0
local remoteEvent = game.ReplicatedStorage.BuildEvent
local isDown = false
-----------------
mouseDown = false
degree = 180
------------------
local sandbagDirect = game.ReplicatedStorage.PlacementSandbags
local barbedWireDirect = game.ReplicatedStorage.BarbedPlacement
local currentBuild = sandbagDirect
local barbedCopy
local degreeCFRAME
-----------------
local function KeyPress(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.Keyboard and equipped then
		if input.KeyCode == Enum.KeyCode.E then
			degree = degree - 15
			sandBagsPlaceCopy.Orientation = Vector3.new(0, degree, 0)
			if currentBuild == barbedWireDirect then
				local gpc = barbedCopy:GetPrimaryPartCFrame()
				degreeCFRAME = gpc * CFrame.Angles(0, math.rad(-15), 0)
				barbedCopy:SetPrimaryPartCFrame(degreeCFRAME)
			end
		elseif input.KeyCode == Enum.KeyCode.Q then
			degree = degree + 15
			sandBagsPlaceCopy.Orientation = Vector3.new(0, degree, 0)
			if currentBuild == barbedWireDirect then
				local gpc = barbedCopy:GetPrimaryPartCFrame()
				degreeCFRAME = gpc * CFrame.Angles(0, math.rad(15), 0)
				barbedCopy:SetPrimaryPartCFrame(degreeCFRAME)
			end
		elseif input.KeyCode == Enum.KeyCode.T then
			degree = degree + 180
			sandBagsPlaceCopy.Orientation = Vector3.new(0, degree, 0)
			if currentBuild == barbedWireDirect then
				local gpc = barbedCopy:GetPrimaryPartCFrame()
				degreeCFRAME = gpc * CFrame.Angles(0, math.rad(180), 0)
				barbedCopy:SetPrimaryPartCFrame(degreeCFRAME)
			end
		elseif input.KeyCode == Enum.KeyCode.F and currentBuild == sandbagDirect then
			barbedCopy = barbedWireDirect:Clone()
			currentBuild = barbedWireDirect
			game.Workspace:FindFirstChild('PlacementSandbags'):Destroy()
			barbedCopy.Parent = workspace
		elseif input.KeyCode == Enum.KeyCode.F and currentBuild == barbedWireDirect then
			currentBuild = sandbagDirect
			sandBagsPlaceCopy = mtarget:Clone()
			sandBagsPlaceCopy.Parent = workspace
			game.Workspace:FindFirstChild('BarbedPlacement'):Destroy()
		end
	end
end
 
local function countDown()
	print('countdown called')
	local sandBagsCopy = BuiltSandBags:Clone()
	local BarbedCopy = BuiltBarbedWire:Clone()
	while mouseDown do
		wait()
		if mouseDown and i <= 4 then
			wait(1)
 			i = i + 1
		end
		if i >= 4 then
			print(degree)
			remoteEvent:FireServer(degree, posX, posY, posZ, currentBuild, degreeCFRAME, modelOrien)
			print(degree)
			uses = uses + 1
			i = 0
			wait()
		end
		if uses >= 5 then
			sandBagsPlaceCopy:Destroy()
			barbedCopy:Destroy()
			script.Parent:Destroy()
		end
	end
end

mouse.Button1Down:Connect(function()
	if not isDown then
		isDown = true
		mouseDown = true
		game.Players.LocalPlayer.PlayerGui.ShovelTimerGUI.TimerFrame.Visible = true
		if currentBuild == barbedWireDirect then
			local gpc = barbedCopy:GetPrimaryPartCFrame()
			degreeCFRAME = gpc * CFrame.Angles(0, math.rad(0), 0)
			barbedCopy:SetPrimaryPartCFrame(degreeCFRAME)
			countDown()
		end
		countDown()
	end
end)
mouse.Button1Up:Connect(function()
	if isDown then
		isDown = false
		mouseDown = false
		game.Players.LocalPlayer.PlayerGui.ShovelTimerGUI.TimerFrame.Visible = false
		i = 0
	end
end)


local function toolEquipped()
	equipped = true
	sandBagsPlaceCopy = mtarget:Clone()
	sandBagsPlaceCopy.Parent = workspace
end

local function toolUnEquipped()
	equipped = false
	mouseDown = false
	i = 0
	sandBagsPlaceCopy:Destroy()
	if currentBuild == barbedWireDirect then
		barbedCopy:Destroy()
	end
	currentBuild = sandbagDirect
end

local function mouseMove()
	if equipped and mouse.Target.Name == "Terrain" and currentBuild == sandbagDirect then
		mouseDown = false
		posX, posY, posZ = mouse.Hit.X, mouse.Hit.Y, mouse.Hit.Z
		posY = posY + 1
		sandBagsPlaceCopy.Position = Vector3.new(posX, posY, posZ)
		i = 0
		if game.Players.LocalPlayer.PlayerGui.ShovelTimerGUI.TimerFrame.Visible == true then
			game.Players.LocalPlayer.PlayerGui.ShovelTimerGUI.TimerFrame.Visible = false
		end
		elseif equipped and mouse.Target.Name == "Terrain" and currentBuild == barbedWireDirect then
		mouseDown = false
		posX, posY, posZ = mouse.Hit.X, mouse.Hit.Y, mouse.Hit.Z
		posY = posY - 2
		barbedCopy:MoveTo(Vector3.new(posX, posY, posZ))
		i = 0
		if game.Players.LocalPlayer.PlayerGui.ShovelTimerGUI.TimerFrame.Visible == true then
			game.Players.LocalPlayer.PlayerGui.ShovelTimerGUI.TimerFrame.Visible = false
		end
	end
end

Tool.Equipped:Connect(toolEquipped)

Tool.Unequipped:Connect(toolUnEquipped)

mouse.Move:Connect(mouseMove)

UserInputService.InputBegan:Connect(KeyPress)
3 Likes

Looks good, but local scripts shouldn’t be relied on too heavily with tools because they are not exploit proof, I would suggest using both server scripts and local scripts instead. The local script would handle things like animations and UserInputService, other things like damage and userstat should be handled on the server.

I am aware of that, but this is a building tool. Not a weapon.