Appear or disappear a text if we have a tool

Hello, I am a beginner in scripting.

I took the help of a tutorial for the door and I would like to learn how to add a text when a player already has something, this could be used to make,

for example:
a text that appears when a player touches a part (joins the group) and when he joins the group, and he touches the part, the text does not appear

currently I made a door with a pass card, I displayed a text when the player touches the hitbox but the problem is that, I would like to display the text only when the player does not have a card, and check if the player has the card then don’t show the text, how to do it please?

local touchpart = game.Workspace:WaitForChild("Game"):WaitForChild("System"):WaitForChild("KeycardDoor"):WaitForChild("hitbox")
local player = game.Players.LocalPlayer
local text = player.PlayerGui.Notif.Text
local canhit = true

touchpart.Touched:Connect(function(hit)
	if canhit == true then
		local name = hit.Parent.Name
		if hit and hit.Parent:FindFirstChild("Humanoid") then
			text.Visible = true
			for i,p in pairs(game.Players:GetChildren()) do
				if p.Name == name then
					canhit = false
					text.Visible = true
					wait(3)
					text.Visible = false
					canhit = true
					break
				elseif p.Name ~= name then
					text.Visible = false
				end
			end
		end
		local Tool = player.Backpack:FindFirstChild("KEYCARD")  or player.Character:FindFirstChild("KEYCARD")
		if Tool then
			text.Visible = false
		end
	end
end)

You will need a script that runs on server-side to check is the player a member in your group. You can follow these simple steps.

  1. Make a Boolean Variable inside StarterPlayer.StarterPlayerScripts

  2. Make a script inside ServerScriptStorage, and write these code in it:

local groupID = 0 -- Your Group Id here

game:GetService("Players").PlayerAdded:Connect(function(plr)
	if plr:IsInGroup(groupID) then
		plr.PlayerScripts:WaitForChild("IsInGroup").Value = true -- Change "IsInGroup" with your variable's name
	end
end)
  1. Add these codes to your door’s script:
local touchpart = game.Workspace:WaitForChild("Game"):WaitForChild("System"):WaitForChild("KeycardDoor"):WaitForChild("hitbox")
local player = game.Players.LocalPlayer
local text = player.PlayerGui.Notif.Text
local canhit = true

local isInGroup = player.PlayerScripts:WaitForChild("IsInGroup") -- Change "IsInGroup" with your variable's name

touchpart.Touched:Connect(function(hit)
	if canhit == true then
		local name = hit.Parent.Name
		if hit and hit.Parent:FindFirstChild("Humanoid") then
			text.Visible = true
			for i,p in pairs(game.Players:GetChildren()) do
				if p.Name == name and isInGroup == true then
					canhit = false
					text.Visible = true
					wait(3)
					text.Visible = false
					canhit = true
					break
				elseif p.Name == name and isInGroup == false then
					text.Visible = true
				elseif p.Name ~= name then
					text.Visible = false
				end
			end
		end
		local Tool = player.Backpack:FindFirstChild("KEYCARD")  or player.Character:FindFirstChild("KEYCARD")
		if Tool then
			text.Visible = false
		end
	end
end)

You may want to make sure the text disappears when he’s not touching the door anymore (If they don’t join the group)

  1. Add these (Optional):
touchpart.TouchEnded:Connect(function(hit)
	text.Visible = false
end)

If you found a problem using this solution, please don’t hestitate to ask me again.

Thas’s all, thank you.

Okay I see tysm,
but how can I make everything on the client side? the text, the door…?

Are you trying to make it so it appears when the player doesn’t have a tool or when they aren’t in the group?

I talked about the group as an example to give a better explanation but in reality it did the opposite :confused:

yes, I would like it to appear only when the player does not have the cardpass

You can read this article instead, may it helps you either.

It was stated that

The IsInGroup Player function sends a request to the Roblox website asking whether a player is a member of a group, given the ID of that group.
Using this in a Script, as opposed to a LocalScript, will not get you the most up-to-date information. If a player leaves a group while they are in the game, IsInGroup will still think they’re in that group until they leave. However, this does not happen when used with a LocalScript.
This is because the method caches results, so multiple calls of IsInGroup on the same player with the same group ID will yield the same result as when the method was first called with the given group ID. The caching behavior is on a per-peer basis: a server does not share the same cache as a client.

i will help you for the “Tool” Check script soon.

local touchpart = game.Workspace:WaitForChild("Game"):WaitForChild("System"):WaitForChild("KeycardDoor"):WaitForChild("hitbox")
local player = game.Players.LocalPlayer
local text = player.PlayerGui.Notif.Text
local canhit = true

touchpart.Touched:Connect(function(hit)
	if canhit == true then
		local name = hit.Parent.Name
		if hit and hit.Parent:FindFirstChild("Humanoid") then
			local hasKeyCard = false
			-- Check if the player has the key card
			local Tool = player.Backpack:FindFirstChild("KEYCARD") or player.Character:FindFirstChild("KEYCARD")
			if Tool then
				hasKeyCard = true
			end
			
			if not hasKeyCard then
				text.Visible = true
				wait(3)
				text.Visible = false
			end
		end
	end
end)
local touchpart = game.Workspace:WaitForChild("Game"):WaitForChild("System"):WaitForChild("KeycardDoor"):WaitForChild("hitbox")
local player = game.Players.LocalPlayer
local text = player.PlayerGui.Notif.Text
local canhit = true

touchpart.Touched:Connect(function(hit)
	if canhit == true then
		local name = hit.Parent.Name
		if hit and hit.Parent:FindFirstChild("Humanoid") then
			local hasKeyCard = false
			-- Check if the player has the key card
			local Tool = player.Backpack:FindFirstChild("KEYCARD") or player.Character:FindFirstChild("KEYCARD")
			if Tool then
				hasKeyCard = true
			end
			
			if not hasKeyCard then
				text.Visible = true
				wait(3)
				text.Visible = false
			end
		end
	end
end)

Take note that you don’t necessarily need to use for i,v in pairs

1 Like

Yes please I am not planning to add the isInGroup function at the moment, I prefer do 1 task per 1 task,

and I tried to modify your script to remove the isInGroup function but I think I broke everything I don’t have the skills yet to be able to modify such a thing.

here some screenshots :
capt 2
capt 1

Are you trying to make the door passable when the Tool named “KEYCARD” is available in the player’s backpack ?

Well, this is what i expect it gonna be

local touchpart = game.Workspace:WaitForChild("Game"):WaitForChild("System"):WaitForChild("KeycardDoor"):WaitForChild("hitbox")
local player = game.Players.LocalPlayer
local text = player.PlayerGui.Notif.Text
local canhit = true

touchpart.Touched:Connect(function(hit)
	local Tool = player.Backpack:FindFirstChild("KEYCARD")  or player.Character:FindFirstChild("KEYCARD") -- If none found = nil
	if canhit == true then
		local name = hit.Parent.Name
		if hit and hit.Parent:FindFirstChild("Humanoid") then
			text.Visible = true
			for i,p in pairs(game.Players:GetChildren()) do
				if p.Name == name then
					if Tool then -- If the thing that touches the door is player and they was found to have the KEYCARD then proceed
						canhit = false
						text.Visible = true
						wait(3)
						text.Visible = false
						canhit = true
					else -- If they are player who touches the door but was found have no tool named "KEYCARD" in their backpack nor character
						text.Visible = true
					end
					break
				elseif p.Name ~= name then -- if its not a player's character
					text.Visible = false
				end
			end
		end
		

	end
end)

touchpart.TouchEnded:Connect(function(hit) -- making sure the text go unvisible when the player stop touching it (whose who dont have the keycard)
	text.Visible = false
end)

Got any error? Please let me know!

Thank you so much !

But I still need to learn, I don’t quite understand, why we need to add:
local canhit = true
before you start writing the rest?

or also why can’t we write directly :
if not hasKeyCard then
text.Visible = false

1 Like

That local canhit = true is optional variable to write, developers wrote it so they can disable some statements incase there are any bugs in future development

the if not hasKeyCard then > text.Visible = false will’nt make the Door to tell the player that they need the Keycard to pass

But, if your question is why don’t we just write if not hasKeyCard then > text.Visible = true, the last code is making sure that the text won’t gone visible forever when the player leave the door untouched.

Sorry for bad sentences, i hope you understand.

1 Like

Oh i see tysm for that !!

I have one last question and then I can finish my first task ^^

I used a tutorial to do the door, the problem is that the person does it in a script and I would like to put it in a local script so that it is on the client and not on the server, I didn’t find an explanation about this,

do I have to change the script or smth, because when I try to copy and paste that into the localscript and I check if everything is good, nothing works,

I’m sure I’m missing something to know to understand why a script and a local script do not work the same way

here is the code :

local door = script.Parent:WaitForChild("Door")
if not door.PrimaryPart then
	door.PrimaryPart = door:WaitForChild("HINGE")
end


--CONFIGURATION--
local keycardName = "KEYCARD"

local timeOpen = 8

local goalRot = 105

local openLength = 2
local closeLength = 1.2
-----------------

local pos = door:GetPivot().Position
local initialRot = door.PrimaryPart.Orientation.Y

local opened = false
local animationHappening = false

local prompt = Instance.new("ProximityPrompt")
prompt.ObjectText = "Keycard Door"
prompt.ActionText = "Open door"
prompt.KeyboardKeyCode = Enum.KeyCode.E
prompt.HoldDuration = 0
prompt.RequiresLineOfSight = false
prompt.MaxActivationDistance = 8
prompt.Parent = door

local cfv = Instance.new("CFrameValue")
cfv.Value = door:GetPivot()
cfv.Parent = door

cfv:GetPropertyChangedSignal("Value"):Connect(function()
	door:PivotTo(cfv.Value)
end)


function ease(x)
	local n1 = 7.5625
	local d1 = 2.75

	if (x < 1 / d1) then
		return n1 * x * x
	elseif (x < 2 / d1) then
		x -= 1.5/d1
		return n1 * (x) * x + 0.75
	elseif (x < 2.5 / d1) then
		x -= 2.25/d1
		return n1 * (x) * x + 0.9375
	else
		x -= 2.625/d1
		return n1 * (x) * x + 0.984375
	end
end


function closeDoor()

	if opened and not animationHappening then
		opened = false
		animationHappening = true

		local currentRot = door.PrimaryPart.Orientation.Y

		local closeStarted = tick()
		while true do
			local x = (tick() - closeStarted) / closeLength
			local rotOffset = ease(x) * -goalRot

			cfv.Value = CFrame.new(pos) * CFrame.Angles(0, math.rad((initialRot + goalRot) + rotOffset), 0)

			if x >= 1 then
				break
			end

			game:GetService("RunService").Heartbeat:Wait()
		end
		
		animationHappening = false
		prompt.Enabled = true
	end
end

function openDoor()
	
	if not opened and not animationHappening then
		opened = true
		animationHappening = true
		
		prompt.Enabled = false

		local openStarted = tick()
		
		while true do
			local x = (tick() - openStarted) / openLength
			local rotOffset = ease(x) * goalRot

			cfv.Value = CFrame.new(pos) * CFrame.Angles(0, math.rad(initialRot + rotOffset), 0)
			
			if x >= 1 then
				break
			end
			
			game:GetService("RunService").Heartbeat:Wait()
		end
		
		animationHappening = false
	end
end



prompt.Triggered:Connect(function(plr)
	
	local char = plr.Character
	if char and char:FindFirstChild("Humanoid") and char.Humanoid.Health > 0 then
		
		if char:FindFirstChild(keycardName) and char[keycardName]:IsA("Tool") then
		
			task.spawn(openDoor)
			task.wait(timeOpen)
			task.spawn(closeDoor)
		end
	end
end)

I think I found the solution which is quite simple, would it be necessary to use the RunContext and switch to local?

When moving code from a regular Script to a LocalScript, it’s important to understand the differences between the two:

  1. Scope: A Script runs on the server and has access to all game data and services, while a LocalScript runs on the client and only has access to client-side objects and services.
  2. Replication: LocalScripts run on each player’s device independently, so they can’t access information about other players directly or perform actions that affect the game state for everyone. They can only manipulate objects and data that are specific to the player running the LocalScript.
  3. Performance: LocalScripts should primarily handle UI, input, and client-side effects. Heavy computation or server-related tasks should still be done on the server.

However, you’re checking for the existence of a tool in the player’s inventory (char:FindFirstChild(keycardName)), which involves checking the player’s data, and then triggering actions based on that. This requires server-side checks.

You can seperate the script to client-server communicating script if you need it to be put on client side.

That’s actually an awesome way to learn about how roblox is managing your data in the game.

If you need to finish it instead of learning, you can follow the whole tutorial without changing anything important unless you know what you’re doing.

From what i research from the script, you only need to put the “Checking the tool” statements to server-side. And create new statements to make the communicate and check if the player really have it.

If they have it you can start the animation of the door

I inquired about the “Script between Client and Server”

although it is a little too difficult for my 3 days of experiences ^^ but I think that in the future, it will be useful to me. for the exploiters

What do you mean by :
“you only need to put the “Checking the tool” statements to server-side”

local Tool = player.Backpack:FindFirstChild("KEYCARD") or player.Character:FindFirstChild("KEYCARD")
			if Tool then
				hasKeyCard = true
			end

actually, my script is in a local script*

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.