Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Script has suddenly broken after barely changing it (building tools script)? [SOLVED]

I was just making a game called "Mayor Sphereoid's Community Place" and I was trying to create build tools. To add some context to why I'm not using the Tool instance, the characters are not humanoids but they are balls with custom controls and a custom camera, meaning that most things compatible with a normal Roblox avatar won't work with my characters.

In my game, there is: A remote function, PartFunction, used to run part functions as a client A remote event, PartMod, used to change values of parts as a client A custom configuration folder put inside a player instance containing the currently held tool

These scripts worked a minute ago and I barely changed anything!

ServerScriptService PartMod (Script)

game.ReplicatedStorage:WaitForChild("PartMod").OnServerEvent:Connect(function(player, part, attr, value, operation)
	if operation == "add" then
		part[attr] = part[attr] + value
	elseif operation == "multiply" then
		part[attr] = part[attr] * value
	else
		part[attr] = value
	end
end)

game.ReplicatedStorage:WaitForChild("PartFunction").OnServerInvoke = function(player, part, func, ...)
	if func == "Clone" then
		local result = part:Clone()
		result.Parent = game.ReplicatedStorage.StoredParts
		result.Name = string.format("%x", math.random(0, 15)) .. "x" .. string.format("%x", player.UserId)
		return {name=part.Name, key=result.Name}
	elseif func == "Destroy" then
		part:Destroy()
	elseif func == "Resize" then
		local testPart = part:Clone()
		testPart:Resize(...)
		if testPart.Size.X <= 0.05
			or testPart.Size.Y <= 0.05
			or testPart.Size.Z <= 0.05 then
			testPart:Destroy()
			return false
		end
		testPart:Destroy()
		return part:Resize(...)
	end
end

StarterPlayerScripts ToolControl (LocalScript)

local player = game.Players.LocalPlayer
local config = player:WaitForChild("Configuration")
local mouse = player:GetMouse()
local rs = game.ReplicatedStorage

local partMod = function(...) rs.PartMod:FireServer(...) end
local partFunc = function(...) return rs.PartFunction:InvokeServer(...) end

-- partMod(part, attr, val, [operation])
-- partFunc(part, func, ...)

local part = nil
local handles = Instance.new("Handles", player.PlayerGui)
local ogMoveDistance = 0
local ogResizeDistance = 0

local function round(x, y)
	return math.floor(x / y + 0.5) * y
end

local function handleHandlerInit()
	ogMoveDistance = 0
	ogResizeDistance = 0
end

local function handleHandler(face, distance)
	local inc = 0.25
	if face == Enum.NormalId.Top or face == Enum.NormalId.Bottom then
		inc = inc * 1.2
	end
	
	-- Resize
	
	if config.Tool.Value == "resize" then
		distance = distance / 4
		local delta = distance - ogResizeDistance
		if math.abs(delta) >= inc then
			local sizeDelta = math.floor(delta / inc + 0.5) * inc
			print(sizeDelta)
			if partFunc(part, "Resize", face, sizeDelta) then
				ogResizeDistance = distance
			end
		end
		
	-- Move
		
	elseif config.Tool.Value == "move" then
		local delta = distance - ogMoveDistance
		if math.abs(delta) >= inc then
			local sizeDelta = math.floor(delta / inc + 0.5) * inc
			partMod(part, "CFrame", CFrame.new(Vector3.FromNormalId(face) * sizeDelta), "multiply")
			ogMoveDistance = distance
		end
	end
end

handles.Name = "BToolHandles"
handles.MouseButton1Down:Connect(handleHandlerInit)
handles.MouseDrag:Connect(handleHandler)

game:GetService("UserInputService").InputBegan:Connect(function(key)
	if key.UserInputType == Enum.UserInputType.MouseButton1
		and key.UserInputState == Enum.UserInputState.Begin then
		if mouse.Target 
			and mouse.X < mouse.ViewSizeX - 90 then

			if mouse.Target.Parent == workspace.BuildingParts then
				
				-- Clone tool

				if config.Tool.Value == "clone" then
					local info = partFunc(mouse.Target, "Clone")
					part = rs.StoredParts:FindFirstChild(info.key)
					partMod(part, "CFrame", CFrame.new(0, part.Size.Y, 0), "multiply")
					partMod(part, "Name", info.name)

					if not part:FindFirstChild("Ownership") then
						local ownership = Instance.new("IntValue", part)
						ownership.Name = "Ownership"
						ownership.Value = player.UserId
					end

					partMod(part, "Parent", workspace.BuildingParts)
				end

				-- Select tool

				if config.Tool.Value == "select"
					and not mouse.Target.Locked
					and part.Ownership then
					if part.Ownership.Value == player.UserId then
						handles.Adornee = part
					end

				-- Destroy tool

				if config.Tool.Value == "destroy"
					and not mouse.Target.Locked
					and part:FindFirstChild("Ownership") then
					if part.Ownership.Value == player.UserId then
						partFunc(mouse.Target, "Destroy")
					end
				end
			end
			
		-- Remove unused handles
		elseif config.Tool.Value == "select"
			and mouse.X < mouse.ViewSizeX - 90 then
			handles.Adornee = nil
		end
	end
end)

This is just so weird! Please help immediately!

NOTES:

I wanted to make it so that parts can't go to 0.05x0.05x0.05 size

I have a control panel on the right which I don't want anyone to click through (hence mouse.X < mouse.ViewSizeX - 90)

There are no errors that appear!

Edit: There is an error that appears, actually. Look at my answer for more info.

1 answer

Tada! I was dumb! Turns out that hidden among so many useless errors from broken plugins was this thing:

Players.Owengren.PlayerScripts.ToolControl:112: Expected identifier when parsing expression, got ')'

Sorry!

This discussion is preserved as it was. New answers, comments, and votes are closed.