Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Queue System Script by lenovo768
- Discord: the_king_here
- Description: Manages player queueing using Zone module, UI elements, player limits,
- friend-only mode, camera control, and player teleportation after countdown.
- --]]
- --// Services
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local TweenService = game:GetService("TweenService")
- local Lighting = game:GetService("Lighting")
- local Players = game:GetService("Players")
- --// Modules
- local Zone = require(ReplicatedStorage:WaitForChild("Module"):WaitForChild("Zone"))
- --// References
- local QueuesFolder = workspace:WaitForChild("Queqe"):WaitForChild("QueueStand")
- local CameraEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("CameraEvent")
- local Blur = Lighting:WaitForChild("BlurForGui")
- --// Tween Info Constants
- local showTweenInfo = TweenInfo.new(0.3, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
- local hideTweenInfo = TweenInfo.new(0.3, Enum.EasingStyle.Back, Enum.EasingDirection.In)
- --// Settings
- local DefaultDuration = 45
- --// Utility Functions
- -- Teleports player to a specific position while keeping rotation
- local function teleportPlayerOut(player: Player, position: Vector3)
- if not player.Character or not player.Character:FindFirstChild("HumanoidRootPart") then return end
- local root:BasePart = player.Character.HumanoidRootPart
- local rotation = root.CFrame.Rotation -- get's the current rotation
- player.Character:PivotTo(CFrame.new(position) * rotation) -- Teleports the player while keeping their rotation
- end
- -- Clears the player queue UI tiles
- local function clearQueueUI(frame: Frame)
- for _, tile in pairs(frame.QueueTiles:GetChildren()) do
- if tile:IsA("ImageButton") then
- tile.ImageLabel.Image = ""
- tile.PlayerName.Value = ""
- end
- end
- end
- -- Main Logic Per Queue Stand
- for _, stand in pairs(QueuesFolder:GetChildren()) do
- if not stand:IsA("Model") then continue end
- local zonePart = stand:WaitForChild("Circle"):WaitForChild("Zone")
- if not zonePart then continue end
- local zone = Zone.new(zonePart)
- -- State Variables
- local owner = nil --refrence to the player who first enter in the zone
- local playerCount = 0 --counts the player that are currently in zone
- local duration = DefaultDuration -- Countdown duration
- local queuePlayers = {} --Keeps a live list of players who are currently standing inside the queue zone
- local kickedPlayers = {} --It temporarily mark players who were forcefully removed from the queue zone so the system knows not to handle them like normal leavers
- local connections = {} --keeps track of all active connections so that we can disconnect them later
- -- Updates the count label on Billboard GUI
- local function updateCountDisplay(frame, allowed)
- stand.PlayerCount.BillboardGui.TextLabel.Text = `${playerCount}/${allowed}` --shows player count and max limit in the UI so player can see it
- end
- -- Start countdown timer
- local function startCountdown(frame)
- task.spawn(function()
- while duration > 0 and owner do --if duration/time is greater then 0 and owner is still in the zone then keep countdowning
- task.wait(1)
- duration -= 1
- frame.AutoStartingText.TimeAmountText.Text = duration
- end
- if not owner then return end --it stopes the execution of this function immediately if the owner has left
- -- Timer ends, teleport all players
- for _, plr in ipairs(queuePlayers) do
- task.spawn(function()
- CameraEvent:FireClient(plr, "Cutscene", workspace.Cutscene.Rigs.CameraRig.CameraRoot, nil, plr == owner) --it handles the camera movement of the cutscene
- task.wait(1.5)
- teleportPlayerOut(plr, zonePart.CFrame.Position + Vector3.new(25, 0, 0)) --Ejects player from queue to allow others access
- end)
- end
- CameraEvent:FireClient(owner, "PlayAnimation", nil, frame) --it plays curscene animation
- CameraEvent:FireClient(owner, "DecreaseFieldOfView", nil, frame) --it decreases the camera FOV and hides the UI with animation
- end)
- end
- -- Handles friend filter toggle
- local function setupFriendToggle(frame)
- local connection = frame.IsOnlyFriendsAllowed.Changed:Connect(function()
- if not owner or not frame.IsOnlyFriendsAllowed.Value then return end --if owner has left or the isonlyfriendallowed button is turned off then it stops the execution of the function
- -- kicks the player out if he is not friend of owner (the person who entered first) on roblox
- for i = #queuePlayers, 1, -1 do
- local queuedPlayer = queuePlayers[i]
- if queuedPlayer == owner then continue end
- if not owner:IsFriendsWith(queuedPlayer.UserId) then
- teleportPlayerOut(queuedPlayer, zonePart.CFrame.Position + Vector3.new(25, 0, 0)) --Ejects player from queue to allow others access
- table.insert(kickedPlayers, queuedPlayer)
- table.remove(queuePlayers, i)
- playerCount -= 1
- end
- end
- updateCountDisplay(frame, frame.AllowedPlayers.Value) --updates the count UI to show the current player count and max limit
- clearQueueUI(frame) --removes the kicked player's presence from the queue display frame
- --it updates queue frame that shows current players in the queue
- for index, plr in ipairs(queuePlayers) do
- local tile = frame.QueueTiles:FindFirstChild("QueueTile" .. index)
- if tile then
- tile.ImageLabel.Image = Players:GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420) --it returns the close picture of player's face
- tile.PlayerName.Value = plr.Name
- end
- end
- end)
- table.insert(connections, connection) --adding the connection to connection table to keep record of it and to disconnect it when needed
- end
- -- Kick a player via kick button/player can kick any player he wants by clicking kick button on the queue frame
- local function setupKickButton(frame, targetPlayer)
- for _, tile in pairs(frame.QueueTiles:GetChildren()) do --loop through all childs of queueTitles which actually include all players that are in queue
- if tile:IsA("ImageButton") and tile.PlayerName.Value == targetPlayer.Name then
- local button = tile:FindFirstChild("KickButton") --button to kick player out of the zone
- if button then
- local connection = button.MouseButton1Click:Connect(function()
- if targetPlayer == owner then return end --if owner tries to kick himself then it will stop execution and do nothing
- teleportPlayerOut(targetPlayer, zonePart.CFrame.Position + Vector3.new(25, 0, 0))--Ejects player from queue to allow others access
- table.insert(kickedPlayers, targetPlayer) --temporarily add player to kick table to keep record of it
- local index = table.find(queuePlayers, targetPlayer)
- if index then
- table.remove(queuePlayers, index)
- playerCount -= 1
- end
- updateCountDisplay(frame, frame.AllowedPlayers.Value) --updates the count UI to show the current player count and max limit
- clearQueueUI(frame) --removes the kicked player's presence from the queue display frame
- --it updates queue frame that shows current players in the queue
- for idx, plr in ipairs(queuePlayers) do
- local t = frame.QueueTiles:FindFirstChild("QueueTile" .. idx)
- if t then
- t.ImageLabel.Image = Players:GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420) --it returns the close shot of player's face
- t.PlayerName.Value = plr.Name
- end
- end
- end)
- table.insert(connections, connection)
- end
- end
- end
- end
- -- Setup Start and Cancel buttons for owner
- local function setupOwnerButtons(frame)
- local cancelConnection = frame.SelectionUI.CancelButton.MouseButton1Click:Connect(function()
- CameraEvent:FireClient(owner, "DecreaseFieldOfView", nil, frame) --it decreases the camera FOV and hides the UI with animation
- end)
- table.insert(connections, cancelConnection)
- local startConnection = frame.StartButton.MouseButton1Click:Connect(function() --if owner clicks start button then it will stop the countdown loop and start the game instantly
- duration = 0
- end)
- table.insert(connections, startConnection)
- end
- -- Assign a new owner and begin queue logic
- local function initializeOwner(player)
- owner = player --player who joined first get assigned as a owner
- playerCount = 1 --increases playercount to 1
- duration = DefaultDuration --set the start time duration to default 45 seconds
- queuePlayers = {player} --it adds the owner to the queue player, since this table holds all player that are in zone
- kickedPlayers = {}
- local frame = player:WaitForChild("PlayerGui"):WaitForChild("SSimUI"):WaitForChild("Frame") --refrence to the frame that gives different options to the owner
- frame.Position = UDim2.new(0.5, 0, 1.5, 0) --setting the position of the frame to the bottom down of the screen
- frame.Visible = true --make frame visible
- frame.AutoStartingText.TimeAmountText.Text = duration --updating frame text to show current duration
- CameraEvent:FireClient(owner, "IncreaseFieldOfView", nil, frame) --function to animate frame position, camera FOV and blur size
- local tile = frame.QueueTiles:FindFirstChild("QueueTile1")
- if tile then
- tile.ImageLabel.Image = Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420) --it returns the close shot of player's face
- tile.PlayerName.Value = player.Name
- end
- --calling upper functions to make the UI buttons works
- setupFriendToggle(frame)
- setupOwnerButtons(frame)
- startCountdown(frame)
- end
- -- Player enters the zone
- zone.playerEntered:Connect(function(player) --it runs whenever any player enters in the region of the zone
- if table.find(queuePlayers, player) then return end
- table.insert(queuePlayers, player) --insert players in queuePlayers, since it holds record of all players that are in zone
- local playerGui = player:WaitForChild("PlayerGui")
- local frame = playerGui:WaitForChild("SSimUI"):WaitForChild("Frame")
- if not owner then
- initializeOwner(player) --defines owner if not defined yet
- return
- end
- local allowed = frame.AllowedPlayers.Value
- if playerCount >= allowed then --checks if the max player count is reached, if it is then it kicks the player out
- teleportPlayerOut(player, zonePart.CFrame.Position + Vector3.new(25, 0, 0))
- table.insert(kickedPlayers, player)
- return
- end
- if frame.IsOnlyFriendsAllowed.Value and not owner:IsFriendsWith(player.UserId) then -- it kicks the player out if IsOnlyFriendAllowed setting is turned ON but the player is not a friend of owner
- teleportPlayerOut(player, zonePart.CFrame.Position + Vector3.new(25, 0, 0))
- table.insert(kickedPlayers, player)
- return
- end
- playerCount += 1 --updates the playercount
- updateCountDisplay(frame, allowed) --updates the UI that shows the current player count
- local tile = frame.QueueTiles:FindFirstChild("QueueTile" .. playerCount)
- if tile then
- tile.ImageLabel.Image = Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
- tile.PlayerName.Value = player.Name
- end
- setupKickButton(frame, player)
- end)
- -- Player leaves the zone
- zone.playerExited:Connect(function(player) --it runs whenever any player leaves the region of the zone
- local index = table.find(queuePlayers, player)
- if index then
- table.remove(queuePlayers, index) --it removes the player from the queuePlayers table since player is not in zone anymore
- playerCount -= 1
- end
- local kickIndex = table.find(kickedPlayers, player)
- if kickIndex then
- table.remove(kickedPlayers, kickIndex) --if player was kicked from the zone that it removes the player from the zone without decreasing playerCount
- end
- if player == owner then --if player who exited the zone is the owner then it disconnect all connections and closes the frame
- local frame = player:WaitForChild("PlayerGui"):WaitForChild("SSimUI"):WaitForChild("Frame")
- CameraEvent:FireClient(owner, "DecreaseFieldOfView", nil, frame)
- frame.Visible = false
- for _, conn in ipairs(connections) do --Disconnecting all connections
- if conn and typeof(conn) == "RBXScriptConnection" then
- conn:Disconnect()
- end
- end
- table.clear(connections) --clears the connections table, since all connections are disconnected so we don't need to track them anymore
- clearQueueUI(frame) --it cleared the frame that shows the presence of players in the queue
- for _, plr in ipairs(queuePlayers) do
- teleportPlayerOut(plr, zonePart.CFrame.Position + Vector3.new(25, 0, 0)) --Ejects player from queue to allow others access
- end
- table.clear(queuePlayers) --it clears the queuePlayers table, since the queue is over
- owner = nil --removes the player refrence from the variable owner, since the player has left the queue
- playerCount = 0 --resets the player count
- duration = DefaultDuration --resets the queue duration
- else
- if owner and owner:FindFirstChild("PlayerGui") then -- if the player who left is not a owner and the owner still exist in queue then it clears only that player existance from the queueTitles frame
- local frame = owner.PlayerGui:FindFirstChild("SSimUI") and owner.PlayerGui.SSimUI:FindFirstChild("Frame")
- if frame then
- for _, tile in pairs(frame.QueueTiles:GetChildren()) do
- if tile:IsA("ImageButton") and tile.PlayerName.Value == player.Name then
- tile.ImageLabel.Image = ""
- tile.PlayerName.Value = ""
- end
- end
- updateCountDisplay(frame, frame.AllowedPlayers.Value) --updates the count UI to show the current player count and max limit
- end
- end
- end
- end)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement