How to make a part become invisible and visible when touched but only if level is high enough (basically, a door)

Hi, I’m trying to make a system in where a player can open a door locally if they have enough levels.
The level value is held in game.ServerStorage.Statfile.[plrname].statnumbers.rpglevel
Here is the SCRIPT placed inside the door. (game.Workspace.Doors.door1)

local levelreq = 20
local Request = game.ReplicatedStorage:FindFirstChild("openrequest")
local palt = script.Parent
local Players = game:GetService("Players")

local function j(plr, red, palt)
	local red = levelreq
	local palt = script.Parent
	Request:FireClient(red, palt)
	warn("sent to door opener")
end

palt.Touched:Connect(j)

Here is the LOCALSCRIPT contained in ServerScriptService

local Request = game.ReplicatedStorage:FindFirstChild("openrequest")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local function onrequestFired(plr, red, palt)
	warn(plr.Name .. red .. palt)
	local plrlevel = game.ServerStorage.Statfile:FindFirstChild(plr.Name).statnumbers.rpglevel.Value

	if plrlevel >= red then
		palt.Transparency = 0.5
		palt.CanCollide = false
		warn(plr.Name.. " opened a door with a levelreq of ".. red)
		wait(0.1)
		palt.Transparency = 0
		palt.CanCollide = true
	else
		warn(plr.Name.. " tried to open a door with a levelreq of " .. red)
	end
end
Request.OnServerEvent:Connect(onrequestFired)

Both scripts do not send errors, and they do not warn either.

1 Like

Local scripts do not go in ServerScriptService; they go in either StarterGui if you’re scripting UIs or they go into StarterPlayerScripts.

Additionally, the code in ServerScriptService will only work efficiently on the server, so the first thing you need to do is cut and paste all of your code from the local script in ServerScriptService to a regular script.

Secondly, instead of a remote event, let’s make a bindable event instead since we are communicating with two server scripts. Instead of :FireClient on the workspace script, replace that with Fire() and make sure you put in the player parameter too since previously, the server had no idea which player was firing it. On the server, replace .OnClientEvent with .Event.

Now your code should work! Reply if it’s still not working or if you have any additional questions.

--server script
local plrs = game:GetService("Players")
local rs = game:GetService("ReplicatedStorage")
local open = rs:WaitForChild("openrequest")
local part = script.Parent

local function onTouched(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		local char = hit.Parent
		local plr = plrs:GetPlayerFromCharacter(char)
		if plr then
			open:FireClient(plr, part)
		end
	end
end

part.Touched:Connect(onTouched)
--local script
local rs = game:GetService("ReplicatedStorage")
local statsFolder = rs:WaitForChild("Statfile")
local open = rs:WaitForChild("openrequest")
local player = game.Players.LocalPlayer
local plrStats = statsFolder:WaitForChild(player.Name)
local statNumbers = plrStats:WaitForChild("statnumbers")
local rpgStat = statNumbers:WaitForChild("rpglevel")

local function onOpenRequest(part)
	if rpgStat.Value < 20 then
		return
	elseif rpgStat.Value >= 20 then
		part.Transparency = 0.5
		part.CanCollide = false
		part.Transparency = 0
		part.CanCollide = true
	end
end

open.OnServerEvent:Connect(onOpenRequest)

Local scripts can’t access the ServerStorage folder so move the statsFolder to the ReplicatedStorage folder as both local scripts and server scripts can access it.

The script contained in the workspace works fine!
but i cannot say the same for the ServerScriptService script.

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local function onrequestFired(plr, red, palt)
	warn(plr.Name .. red.Value .. palt.Name)
	local plrlevel = game.ServerStorage.Statfile:FindFirstChild(plr.Name).statnumbers.rpglevel.Value

	if plrlevel >= red then
		palt.Transparency = 0.5
		palt.CanCollide = false
		warn(plr.Name.. " opened a door with a levelreq of ".. red)
		wait(0.1)
		palt.Transparency = 0
		palt.CanCollide = true
	else
		warn(plr.Name.. " tried to open a door with a levelreq of " .. red)
	end
end
Request.Event:Connect(onrequestFired)

When it is run, my warning of “sent to door opener” appears, but the door opener returns with
ServerScriptService.DoorOpener:5: attempt to index number with 'Value'
Do you have any idea why this is happening?

It’s a number value, so you need to reference the value property.

if plrlevel >= red.Value then

Oh, thank you! That would’ve slipped through the cracks in the end.
I still have the problem though, and it’s referencing this line
warn(plr.Name .. red.Value .. palt.Name)
When i seperated these values into individual warns, it errored at the “red” part (required level, which should return as 20)

Another error, which appeared when i had seperated the warns, and is probably a mistake on my part, is the fact that the script detects whatever body part touches the part, and not the player itself. It would be helpful if you shared an answer to this, even though i’ll be able to do it myself (sort of fact-checking)

The script is able to detect the door part just fine.

1 Like

Your first problem is a string concatenation error that occurs whenever you try to join a string value with a number value. You need to use tostring(red.Value) to avoid this error.

To get the player from the body part, all you need to do is get the body part’s parent, which always ends up as the player model in the workspace.