An issue I can't figure out

Everytime I duplicate this Booth, I want 5 of them in total but I can’t figure out how to make it work in every single model rather than just one. Should I make a Table that accesses every single Booth model so this way I can make it function when it’s duplicated or are there any other solutions?

In-game
https://gyazo.com/e16f5763f4d3a58d88db8521640b9812

Server

local Players = game:GetService("Players")
local ProximityPromptService = game:GetService("ProximityPromptService")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ChatService = game:GetService("Chat")

local ProximityPrompt = Instance.new("ProximityPrompt")
ProximityPrompt.Parent = game.Workspace.Booth.ProxPart -- Here 
ProximityPrompt.Enabled = true
ProximityPrompt.HoldDuration = 0.3
ProximityPrompt.ActionText = "Claim Booth"

local SurfaceGui = Instance.new("SurfaceGui")
SurfaceGui.Parent = game.Workspace.Booth.Header -- Here
SurfaceGui.Face = "Back"
SurfaceGui.Enabled = true

local FrameGui = Instance.new("Frame")
FrameGui.Parent = SurfaceGui
FrameGui.Size = UDim2.new(1, 0, 1, 0)
FrameGui.BackgroundTransparency = 1

local TextGui = Instance.new("TextLabel")
TextGui.Parent = FrameGui
TextGui.Size = UDim2.new(1, 0, 1, 0)
TextGui.Font = Enum.Font.FredokaOne
TextGui.BackgroundTransparency = 1
TextGui.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
TextGui.TextColor3 = Color3.fromRGB(255, 255, 255)
TextGui.Text = "Empty"
TextGui.TextScaled = true

local BillboardGui = Instance.new("BillboardGui")
BillboardGui.Parent = game.Workspace.Booth.Header
BillboardGui.Size = UDim2.new(1, 0, 1.2, 0)
BillboardGui.StudsOffset = Vector3.new(-1.5, 5, 0)

local BillboardText = Instance.new("TextLabel")
BillboardText.Parent = BillboardGui
BillboardText.Size = UDim2.new(4, 0, 1, 0)
BillboardText.Font = Enum.Font.FredokaOne
BillboardText.TextStrokeTransparency = 0.9
BillboardText.TextColor3 = Color3.fromRGB(255, 255, 255)
BillboardText.Text = "CLAIM BOOTH!"
BillboardText.TextScaled = true
BillboardText.BackgroundTransparency = 1

local tweenInfo = TweenInfo.new(
	2.5, 
	Enum.EasingStyle.Bounce, 
	Enum.EasingDirection.Out, 
	-1,  
	true, 
	1
)

local Tween = TweenService:Create(BillboardText, tweenInfo, { Size = UDim2.new(3.5, 0, 4, 0) })

Tween:Play()

local RemoteEvent = Instance.new("RemoteEvent")
RemoteEvent.Parent = ReplicatedStorage
RemoteEvent.Name = "BoothEvent"
local Claimed = Instance.new("ObjectValue")
Claimed.Value = nil

local function onPlayerRemoving(player)
	
	if 	Claimed.Value == player then 
		Claimed.Value = nil
		BillboardText.Text = "Claim Booth!"
		BillboardText.TextColor3 = Color3.fromRGB(255, 255, 255)
		Tween:Play()
		ProximityPrompt.Enabled = true
		print("A player has left:  " .. player.Name)	
		
	end
end

Players.PlayerRemoving:Connect(onPlayerRemoving)

ProximityPrompt.Triggered:Connect(function(player)
	
	if Claimed.Value == nil then
		Claimed.Value = player
		BillboardText.Text = "Owned by:  " .. player.Name
		BillboardText.TextColor3 = Color3.fromRGB(203, 203, 203)
		Tween:Cancel()
		ProximityPrompt.Enabled = false
		
		RemoteEvent:FireClient(player)
			
	end	
end)

local RemoteFunction = ReplicatedStorage.RemoteFunction

RemoteFunction.OnServerInvoke = function(player, text)
	
	if Claimed.Value == player then
		local FilteredText = ChatService:FilterStringForBroadcast(text, player)
		TextGui.Text = FilteredText
		return FilteredText
		
	end
end

Client

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local ChatService = game:GetService("Chat")
local RemoteEvent = game.ReplicatedStorage:WaitForChild("BoothEvent")
local BoothGui = game.StarterGui.BoothGui
local LocalPlayer = Players.LocalPlayer
local PlayerBoothGui = LocalPlayer.PlayerGui:WaitForChild("BoothGui")

RemoteEvent.OnClientEvent:Connect(function()
	PlayerBoothGui.Enabled = true
	PlayerBoothGui.Frame.BackgroundTransparency = 0
end)

local CloseButton = PlayerBoothGui.Frame.CloseButton

CloseButton.MouseButton1Click:Connect(function()
	if PlayerBoothGui.Enabled == true then
		PlayerBoothGui.Enabled = false
	end 
end)

local SubmitButton = PlayerBoothGui.Frame.SubmitButton
local RemoteFunction = ReplicatedStorage.RemoteFunction
local Textbox = PlayerBoothGui.Frame.Frame.TextBox

SubmitButton.MouseButton1Click:Connect(function()

	local filteredName = RemoteFunction:InvokeServer(Textbox.Text)
	Textbox.Text = filteredName 
	PlayerBoothGui.Enabled = false
	
end)

What can I do here to make it apply to every single Booth I duplicate?

Any help is appreciated!

2 Likes

Question: What exactly happens when you try to use another booth?

3 Likes

You’re only parenting a proximityprompt clone to one booth. So instead of just using

local ProximityPrompt = Instance.new("ProximityPrompt")
ProximityPrompt.Parent = game.Workspace.Booth.ProxPart

use this

for _, v in pairs(workspace:GetChildren()) do
  if v.Name == "Booth" then
     local ProximityPrompt = Instance.new("ProximityPrompt")
     ProximityPrompt.Enabled = true
     ProximityPrompt.HoldDuration = 0.3
     ProximityPrompt.ActionText = "Claim Booth"
     ProximityPrompt.Parent = v.ProxPart
  end
end

(sorry for the errors lol, i fixed it)

P.S. you might want to use an in pairs loop for the entire script instead of just that part

1 Like

Okay on second thought, you definitely are gonna want to use an i, v in pairs() loop for almost the whole script. So do this:

 for _, booth in pairs(workspace:GetChildren()) do
     if booth.Name == "Booth" then
        --Paste all of your code from line 7 and below here, and just revise it and stuff to make it work
     end
 end
2 Likes

Module Scripts and CollectionService are 100% your friend in this scenario.

You can create a module script, we’ll call this module script BoothHandler, where instead of copying a script to every booth, you can instead check if an object is a booth, and then just tell it to run the modules functions. Something similar to what I wrote below:

Module Script:


--[[ SERVICES ]]--

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local ChatService = game:GetService("Chat")

--[[ PRIVATE FUNCTIONS ]]--

local function Tween(inst, goal)
	local info = TweenInfo.new(
		2.5, 
		Enum.EasingStyle.Bounce, 
		Enum.EasingDirection.Out, 
		-1,  
		true, 
		1
	)
	local tween = TweenService:Create(inst, info, goal)
	return tween
end

--[[ MODULE ]]--

local module = {}

function module.NewBooth(booth)
	--// Instances
	local RemoteFunction = booth.RemoteFunction
	local RemoteEvent = ReplicatedStorage.BoothEvent
	local Claimed = booth.Value
	local ProximityPrompt = booth.ProxPart.ProximityPrompt
	local SurfaceGui = booth.Header.SurfaceGui
	local BillboardGui = booth.Header.BillboardGui
	local BillboardText = BillboardGui.TextLabel
	
	--// Functions
	local function SetOwnerNil(plr)
		Claimed.Value = nil
		BillboardText.Text = "CLAIM BOOTH!"
		BillboardText.TextColor3 = Color3.fromRGB(255, 255, 255)
		SurfaceGui.Frame.TextLabel.Text = "Empty"
		Tween(BillboardGui.TextLabel, { Size = UDim2.new(3.5, 0, 4, 0) }):Play()
		ProximityPrompt.Enabled = true
		CollectionService:RemoveTag(plr, "HasBooth")
		print("A player has left:  " .. plr.Name)
	end

	local function SetOwner(plr)
		Claimed.Value = plr
		BillboardText.Text = "Owned by:  " .. plr.Name
		BillboardText.TextColor3 = Color3.fromRGB(203, 203, 203)
		Tween(BillboardText, { Size = UDim2.new(3.5, 0, 4, 0) }):Cancel()
		ProximityPrompt.Enabled = false
		RemoteEvent:FireClient(plr, booth)
		CollectionService:AddTag(plr, "HasBooth")
	end
		
	--// Events
	-- When triggered, that player will claim the booth
	ProximityPrompt.Triggered:Connect(function(player)
		--print(booth.Name.." triggered.")
		if Claimed.Value == nil and not CollectionService:HasTag(player, "HasBooth") then
			SetOwner(player)
		else
			print("Uh oh! "..player.Name.." already has a booth!")
		end
	end)
	
	-- When triggered will filter, set, and pass back the string to the client
	RemoteFunction.OnServerInvoke = function(player, text)
		local FilteredText = ChatService:FilterStringForBroadcast(text, player)
		--print(booth.Name)
		if Claimed.Value == player then
			SurfaceGui.Frame.TextLabel.Text = FilteredText
			return FilteredText
		end
	end
	
	-- When a player leaves, will free this booth for the next player
	Players.PlayerRemoving:Connect(function(plr)
		if Claimed.Value == plr then
			SetOwnerNil(plr)
		end
		return
	end)
	
	--// Code
	Tween(BillboardGui.TextLabel, { Size = UDim2.new(3.5, 0, 4, 0) }):Play()
end

return module

We can then utilize the power of Collection Service. Before I explain how it works, I HIGHLY HIGHLY suggest you download Tag Editor, it makes using collection service 100x easier.

With collection service, we can create a tag called Booth, then we can add this tag to every booth we have in the game. Once we’ve added a tag to each booth, we just have initialize each booth so they can make use of our module script. We can do that by using something like this:

SERVER:


--[[ SERVICES ]]--

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")
local BoothHandler = require(ReplicatedStorage.BoothHandler)

--[[ EVENTS ]]--

-- Initializes all present existing booths
local function Init()
	for _, booth in pairs(CollectionService:GetTagged("Booth")) do
		BoothHandler.NewBooth(booth)
	end
end

Init()

The function Init will grab every instance that has the tag Booth using a for loop, if it has that tag it will run the NewBooth function in our module script BoothHandler. Then just like that, every booth works with just one line of code:

BoothHandler.NewBooth(booth)

With the power of Module Scripts and Collection Service you can also create a kinda live time booth updater… thingy, if we add this to our server script:

-- If a new booth/instance is created with the tag booth, it will run BoothHandler.NewBooth() | (THIS IS ASSUMING THE INSTANCE HAS THE PROPERTIES OF A BOOTH!!!)
CollectionService:GetInstanceAddedSignal("Booth"):Connect(function(inst)
	BoothHandler.NewBooth(inst)
end)

Then we can add booths to the game in real time just like this: (idk why you would do this, but just thought I’d show you how cool this combo is).

Overall, this is how I’d do it, but I highly suggest you look into module scripts and collection service if you haven’t already. My code could still be optimized better but it’s sufficient. Oh also here’s the workplace, I hope you can analyze and learn something from it. Other than that, if you have any questions feel free to ask. :smiley:

Booth_Example.rbxl (62.6 KB)

2 Likes

Thank you for your help means a lot, been learning Lua for a bout 2 weeks now and this helps expand my knowledge by miles :exploding_head:

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