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

Why do I get this error? Please read before reviewing code.

The error shows up at line 11 (The clicked function) It works in studio but not ingame. I tried waiting for the mouse but it just waits infinitely. The error that shows up (without the waiting) is "attempt to index local 'mouse' (a nil value)". I've checked and everything seems to be fine. when I changed mouse = player:GetMouse() to mouse = player (thinking maybe player was already the mouse), it said: Hit is not a part of Player.

part = script.Parent.PrimaryPart
mouseClicked = false
partMoving = false
collision = false
isincollision = false
originalcolor = {}
outOfBounds = false

function clicked(player)
	mouse = player:GetMouse()
	playerSlot = PlayerSlot(player)
	for i,v in pairs(script.Parent:GetChildren()) do
		local increment = 0
		if v.ClassName == "Part" then
			increment = increment+1
			table.insert(originalcolor, v.BrickColor)
		end
	end
	if mouseClicked == false then
		mouseClicked = true
		if partMoving == false then
			partMoving = true
			wait()
			mouseClicked = false
			MovePart(player)
		else
			wait()
			mouseClicked = false
			PlacePart(player)
		end
	end
end

function RoundUp(number)
	local roundNumber = number-(number%0.5)
	return roundNumber
end

function MovePart(player)
	local mouse = player:GetMouse()
	while partMoving == true do
		script.Parent:SetPrimaryPartCFrame(CFrame.new((RoundUp(mouse.Hit.p.x)), script.Parent.PrimaryPart.CFrame.Y, (RoundUp(mouse.Hit.p.Z))))
		wait()
	end
end

function PlacePart(player)
	local mouse = player:GetMouse()
	if isincollision == false then
		if outOfBounds == false then
			partMoving = false
		end
	end
end

script.Parent.PrimaryPart.Changed:connect(function()
	for i,modelpart in pairs(script.Parent:GetChildren()) do
		if modelpart.ClassName == "Part" then
			for i,part in pairs(modelpart:GetTouchingParts()) do
				if part.Parent ~= script.Parent then
					if collision == false then
						collision = true
					end
				end
			end
		end
	end
	if collision ~= false then
		isincollision = true
		for i,v in pairs(script.Parent:GetChildren()) do
			if v.ClassName == "Part" then
				if v.BrickColor ~= BrickColor.new("Really red") then
					v.BrickColor = BrickColor.new("Really red")
					v.Transparency = 0.5
				end
			end
		end
	else
		isincollision = false
		local increment = 0
		if outOfBounds == false then
			for i,v in pairs(script.Parent:GetChildren()) do
				if v.ClassName == "Part" then
					increment = increment+1
					local color = tostring(originalcolor[increment])
					if v.BrickColor == BrickColor.new("Really red") then
						v.BrickColor = BrickColor.new(color)
						v.Transparency = 0
					end
				end
			end
		end
	end
	collision = false
end)

function PlayerSlot(player)
	for i,v in pairs(game.Workspace.Slots:GetChildren()) do
		if v.Slot_Owner.Value == player.Name then
			print(v)
			return v
		end
	end
end

script.Parent.PrimaryPart.Changed:connect(function()
	local partSize = script.Parent.PrimaryPart.Size
	local partPos = script.Parent.PrimaryPart.CFrame
	local slotPosX = playerSlot.slot.Position.X
	local slotPosZ = playerSlot.slot.Position.Z
	local slotSizeX = playerSlot.slot.Size.X
	local slotSizeZ = playerSlot.slot.Size.Z
	local oneOutOfBounds = false
	
	if oneOutOfBounds == false then
		if partPos.X + partSize.X/2 > slotPosX+slotSizeX/2 then
			oneOutOfBounds = true
		elseif partPos.X - partSize.X/2 < slotPosX-slotSizeX/2 then
			oneOutOfBounds = true
		end
	end
	
	if oneOutOfBounds == false then
		if partPos.Z + partSize.Z/2 > slotPosZ+slotSizeZ/2 then
			oneOutOfBounds = true
		elseif partPos.Z - partSize.Z/2 < slotPosZ-slotSizeZ/2 then
			oneOutOfBounds = true
		end
	end
		
	if oneOutOfBounds == true then
		outOfBounds = true
		for i,v in pairs(script.Parent:GetChildren()) do
			if v.ClassName == "Part" then
				if v.BrickColor ~= BrickColor.new("Really red") then
					v.BrickColor = BrickColor.new("Really red")
					v.Transparency = 0.5
				end
			end
		end
	else
		outOfBounds = false
	end
end)

script.Parent.ClickDetector.MouseClick:connect(clicked)

3 answers

✓ Accepted answer

ASSUMING your game is Filtering Enabled, your problem would be in that you are trying to get the Mouse from a player in a Script which is Server side, but you can only get the mouse from a Local Script on the Client side. It works in Studio because Studio ignores Filtering Enabled and allows you to cross this boundary, while in a real server it would be respected and you would not be able to access that sort of data from the server side.

To fix this you would need to do all your mouse stuff on a Local Script on the client side, and then fire Remote Events/Functions to the Server side to move all the parts and objects around.

1 comment

0

Got it, let me try that right now. I thought it was that but wanted to make sure because I didn't want to do un needed programming. I've restarted this script 3 times because some things weren't the way I wanted them to be lol.

Capitalization matters

maybe the problem is instead of

 playerSlot = PlayerSlot(player)

try

 playerSlot = playerSlot(player)

I have no idea what this script even does, but since you mentioned that line, I am assuming this is the problem

3 comments

0

Like I said, read everything. What that variable does is it calls the PlayerSlot function sending the player variable. Then, playerSlot sets it self as the return value of the PlayerSlot function.

0

"Read everything" how about you explain the code to us instead? Reading the code won't mean we'll understand what you're trying to accomplish well enough that we will be able to help you.

0

On the very last line :Connect instead of connect??? I don't think there is much of a difference though

The reason that this isn't working as you expect, is because you are using a ClickDetector which is Server side, but you are trying to access the player's Mouse which is Client side.

What this comes down to, is you aren't able to use both in the same script, as one needs to be used in a Script, and the other a LocalScript.

I won't be writing your whole script over for you, but hopefully I can point you in the right direction.

To make things easier, you should start off by moving things completely either on the Client or on the Server.

If you choose to stay on the server, you've lost the mouse and all of it's positioning. All you get to know is when someone clicks your click detector and who it was.

If you go on the Client, you ditch the click detector, however you can use useful things like mouse.Target and determine if what you clicked is the door/clickable part by checking it's name or objects inside of it. This will allow you to also get it's mouse.Hit.p and so on to do more math stuff.

--

With those 2 options, I would go with the client especially if you need the specific position the mouse clicked, and not just which part. This isn't a quick fix, I know, however I hope you can get going in the right direction from it.

Once you've layed down client code, you can use RemoteEvents or RemoteFunctions to handle things you don't trust the client with.

3 comments

0

Here, go down to "Server to Client", it sais that the client does NOT have information the server doesn't have. That means, even if I were to do player:GetMouse() or game.Players[player.Name]:GetMouse(), they would both do the same thing. Get the mouse of the player specified.

0

Please read the very top of THIS article: http://wiki.roblox.com/index.php?title=API:Class/PlayerMouse "Each Player has a PlayerMouse which acts exactly the same as the Mouse object. The only way to access this object is with the GetMouse method of the Player object from a LocalScript." Hence, you cannot access it in a server script because that kind of user input is client side.

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