Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Squid Game User Interface Controller
- Handles shop UI, reward UI, tool activation, gamepasses, animations, and GUI interaction logic using Knit framework.
- ]]
- --by the_king_here
- --//SERVICES
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local Knit = require(ReplicatedStorage.Packages.Knit)
- local TweenService = game:GetService("TweenService")
- local runService = game:GetService("RunService")
- local MPS = game:GetService("MarketplaceService")
- local LightningService = game:GetService("Lighting")
- local SoundService = game:GetService("SoundService")
- --TweenInfo config for UI transitions (0.3s, Back Out easing)
- local tweenInfoUI = TweenInfo.new(0.3, Enum.EasingStyle.Back, Enum.EasingDirection.Out, 0)
- -- Creating a Knit Controller
- local UserInterfaceController = Knit.CreateController{
- Name = "UserInterface",
- }
- -- Will store reference to the server side service later
- local MapHandlerService
- -- Reference to the local player
- local player = game.Players.LocalPlayer
- -- Control module to disable movement during certain actions
- local Controls = require(player.PlayerScripts.PlayerModule):GetControls()
- -- UI References in PlayerGui
- local TrollUI = player.PlayerGui:WaitForChild("Troll")
- local PushUI = player.PlayerGui:WaitForChild("PushUI")
- local SettingsUI = player.PlayerGui:WaitForChild("Settings")
- local ShopUI = player.PlayerGui:WaitForChild("Shop")
- local InventoryUI = player.PlayerGui:WaitForChild("Inventory")
- local RewardUI = player.PlayerGui:WaitForChild("Reward")
- -- Music References
- local BackgroundMusic = SoundService:WaitForChild("LobbyMusic")
- local SquidMusic = SoundService:WaitForChild("Music")
- -- Developer product IDs
- local Products = {
- EliminatePlayers = 3312415657,
- SpeedTroll = 3312416017,
- KillRandomPersonTroll = 3312444642,
- TakeCoinsTroll = 3312417586,
- }
- -- Push upgrades (more force or quantity)
- local PushProducts = {
- Push1 = 3313283431,
- Push2 = 3313283430,
- Push5 = 3313283433,
- Push7 = 3313283424,
- Push10 = 3313286623,
- }
- -- Tweening for background music transitions
- local tweenInfoForMusic = TweenInfo.new(1.5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0)
- -- Reference to the camera for FOV changes
- local camera = workspace.CurrentCamera
- -- Blur effect (GUI background blur)
- local Blur = LightningService:FindFirstChild("BlurForGui")
- local UIStroke
- -- For rope animation disconnecting later
- local RopeAnimationConnection
- -- Countdown before round starts (e.g., "3, 2, 1... Run!")
- function UserInterfaceController:BackTimer(StartTime, EndTime, UIToShowTime)
- for i = StartTime, EndTime, -1 do
- task.wait(1)
- player.PlayerGui:WaitForChild("Timer").TextLabel.Visible = true
- player.PlayerGui.Timer.TextLabel.Text = i --Displays time on textlabel
- player.PlayerGui.Timer.TextLabel.TimerSound:Play() --plays timer sound every second
- if i ~= 0 then continue end
- task.wait(1)
- player.PlayerGui.Timer.TextLabel.Text = "Run!" -- Final message
- task.wait(1)
- player.PlayerGui.Timer.TextLabel.Visible = false
- end
- end
- function UserInterfaceController:HandleUIStroke(argunent, Parent)
- if argunent == "Add" then
- if not UIStroke then --UIStroke logic, it creates new UI stroke and add it to the button if there is no before and if there already exist then it just change the parent of existing stroke to the new button
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = Parent
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = Parent
- end
- elseif argunent == "Remove" then
- UIStroke.Parent = nil
- end
- end
- -- Displays a short message on screen (centered label) for 3 seconds
- function UserInterfaceController:ShowMessage(Message)
- player.PlayerGui:WaitForChild("Timer").TextLabel.Visible = true
- player.PlayerGui.Timer.TextLabel.Text = Message
- task.delay(3, function()
- player.PlayerGui.Timer.TextLabel.Visible = false
- end)
- end
- local Rope -- rope part reference (used in Easy or Hard maps)
- local maxSpeed -- max angular speed in radians/sec
- local accelTime = 3 -- how long to accelerate (ease in) in seconds
- local animationStarted = false -- variable to check if animation has started
- local animationStartTime = nil -- server-synced time when animation begins
- local initialCFrame -- store original rope CFrame
- function UserInterfaceController:HandleAnimation(IsEnabledControls)
- local now = workspace:GetServerTimeNow() --get current time
- -- Wait until server-synced animation time
- if not animationStarted and now >= animationStartTime then
- animationStarted = true
- end
- if not animationStarted then return end
- -- Enable player controls 1 second after rope starts
- if not IsEnabledControls then IsEnabledControls = true; Controls:Enable() end
- local elapsed = now - animationStartTime -- how long since animation began
- local rotation --Stores rotation value
- -- Accelerate with cubic easing for first 3 seconds
- if elapsed < accelTime then
- local progress = elapsed / accelTime
- rotation = 0.33 * maxSpeed * (progress ^ 3) * accelTime
- else
- -- Maintain constant speed after acceleration phase
- local constantTime = elapsed - accelTime
- rotation = 0.33 * maxSpeed * accelTime + maxSpeed * constantTime
- end
- -- Rotate rope by X-axis only
- local newCFrame = initialCFrame * CFrame.Angles(rotation, 0, 0)
- Rope:PivotTo(newCFrame)
- end
- -- Begins rope rotation animation based on server time
- function UserInterfaceController:startAnimationWhenReady(serverStartTime, Mode)
- -- Decide map + speed based on mode
- if Mode == "Easy" then
- maxSpeed = math.rad(210) -- degrees to radians
- Rope = workspace.Maps.EasyRopemap:WaitForChild("rope")
- else
- maxSpeed = math.rad(250)
- Rope = workspace.Maps.HadRopeMap:WaitForChild("rope")
- end
- local primary = Rope.PrimaryPart --Stores refrence to rope primaryPart
- initialCFrame = primary.CFrame -- store starting position
- animationStartTime = serverStartTime
- animationStarted = false
- Controls:Disable() -- Disable player movement during pre rope animation
- -- If player has LessGravity effect, set gravity to 70
- local LessGravity = player:FindFirstChild("LessGravity")
- if LessGravity.Value > 0 then
- MapHandlerService:LessGravity("DecreaseGravityValue")
- workspace.Gravity = 70
- end
- local IsEnabledControls = false --keep track whether controls of player has been restored or not
- -- Connect to RenderStepped to animate rope every frame
- RopeAnimationConnection = runService.RenderStepped:Connect(function()
- self:HandleAnimation(IsEnabledControls)
- end)
- end
- --returns name after removing text "button" from name if name contains text "Button"
- function UserInterfaceController:getNameAfterRemovingButton(name)
- local suffix = "Button"
- if name:sub(-#suffix) == suffix then
- return name:sub(1, -#suffix - 1)
- else
- return name
- end
- end
- local originalRotation = 0 --Stoers default rotation, which is usually 0
- -- function to scale UDim2 (used to make buttons shrink or grow)
- function UserInterfaceController:scaleSize(size: UDim2, scale: number): UDim2
- return UDim2.new(
- size.X.Scale * scale, size.X.Offset * scale,
- size.Y.Scale * scale, size.Y.Offset * scale
- )
- end
- -- When mouse enters button (hover), enlarge slightly + rotate
- function UserInterfaceController:onHover(button, originalSize)
- local hoverTween = TweenService:Create(button, TweenInfo.new(0.1), {
- Size = self:scaleSize(originalSize, 1.1),
- Rotation = 5,
- })
- hoverTween:Play()
- end
- -- When mouse leaves button, restore size and rotation
- function UserInterfaceController:onUnhover(button, originalSize)
- local unhoverTween = TweenService:Create(button, TweenInfo.new(0.1), {
- Size = originalSize,
- Rotation = originalRotation,
- })
- unhoverTween:Play()
- end
- -- When button is clicked, shrink quickly then bounce back
- function UserInterfaceController:onClick(button, originalSize)
- local shrinkTween = TweenService:Create(button, TweenInfo.new(0.05), {
- Size = self:scaleSize(originalSize, 0.8),
- })
- local restoreTween = TweenService:Create(button, TweenInfo.new(0.1), {
- Size = originalSize,
- })
- shrinkTween:Play()
- shrinkTween.Completed:Connect(function()
- restoreTween:Play()
- end)
- end
- local OpenedUI -- Tracks which UI is currently open
- function UserInterfaceController:tweenOpen(Canavs) --Function to open UI with tween/animation
- Canavs.Visible = true
- Canavs.Position = UDim2.new(0.5, 0, 1.5, 0)
- Canavs:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3) --Animating the position of the UI
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 100}):Play() --Increasing FOV with animation to give overall animation better look
- TweenService:Create(Blur, tweenInfoUI, {Size = 20}):Play() --Applying blur with animation
- end
- function UserInterfaceController:tweenClose(Canavs) --function to close UI with tween/animation
- Canavs:TweenPosition(UDim2.new(0.5, 0, 1.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3)
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 70}):Play()
- TweenService:Create(Blur, tweenInfoUI, {Size = 0}):Play()
- end
- function UserInterfaceController:handleUIState(Canavs)
- if not OpenedUI then -- No UI open yet
- OpenedUI = Canavs --Defines the current open UI
- self:tweenOpen(Canavs)
- elseif OpenedUI and OpenedUI ~= Canavs then-- Switching from one UI to another
- self:tweenClose(OpenedUI)
- OpenedUI = Canavs
- self:tweenOpen(Canavs)
- elseif OpenedUI == Canavs then -- UI is already open, so close it
- OpenedUI = nil --closed opened UI so now no UI opened so make OpenedUI variable nil
- self:tweenClose(Canavs)
- end
- end
- -- Applies hover/click effcts and manages showing/hiding UIs like Shop, Inventory, etc.
- function UserInterfaceController:AnimateUIs()
- local UIButtons = player:WaitForChild("PlayerGui"):WaitForChild("Buttons")
- local Debounce = false -- Prevents spam clicking
- for i, button in pairs(UIButtons:GetChildren()) do
- if not button:IsA("Frame") then continue end
- local Button = button:FindFirstChildOfClass("TextButton") -- Find the clickable button
- if not Button then continue end
- local originalSize = button.Size
- local FrameName = self:getNameAfterRemovingButton(button.Name) -- Remove "Button" suffix
- local Frame = player.PlayerGui:FindFirstChild(FrameName) --get the frame with the given value after removing "Button" suffix
- if not Frame then continue end
- local isModes = Frame.Name == "Modes"
- local Canavs = Frame:FindFirstChild(isModes and "Frame" or "Canvas")
- local CloseButton = isModes and Frame.Frame:FindFirstChild("Close") or (Canavs and Canavs:FindFirstChild("Container") and Canavs.Container:FindFirstChild("Main") and Canavs.Container.Main:FindFirstChild("Close"))
- if not Canavs or not CloseButton then continue end
- -- Hover event
- button.MouseEnter:Connect(function()
- self:onHover(button, originalSize)
- end)
- -- Unhover event
- button.MouseLeave:Connect(function()
- self:onUnhover(button, originalSize)
- end)
- -- Button click (open/close logic)
- Button.MouseButton1Click:Connect(function()
- if Debounce then return end
- Debounce = true
- self:onClick(button, originalSize)
- self:handleUIState(Canavs)
- task.delay(0.3, function()
- Debounce = false
- end)
- end)
- -- Close button logic/closes the opened UI
- CloseButton.MouseButton1Click:Connect(function()
- if Debounce then return end
- Debounce = true
- OpenedUI = nil
- --Closes UI with tween
- self:tweenClose(Canavs)
- -- Reset camera FOV and continblur
- task.delay(0.3, function()
- Debounce = false
- end)
- end)
- end
- end
- function UserInterfaceController:PromptPurchase(ClickedButtonName)
- if ClickedButtonName == "EliminatePlayers" then
- MPS:PromptProductPurchase(player, Products.EliminatePlayers)
- elseif ClickedButtonName == "SpeedTroll" then
- MPS:PromptProductPurchase(player, Products.SpeedTroll)
- elseif ClickedButtonName == "KillRandomPersonTroll" then
- MPS:PromptProductPurchase(player, Products.KillRandomPersonTroll)
- elseif ClickedButtonName == "TakeCoinsTroll" then
- MPS:PromptProductPurchase(player, Products.TakeCoinsTroll)
- elseif ClickedButtonName == "Push1" then
- MPS:PromptProductPurchase(player, PushProducts.Push1)
- elseif ClickedButtonName == "Push2" then
- MPS:PromptProductPurchase(player, PushProducts.Push2)
- elseif ClickedButtonName == "Push5" then
- MPS:PromptProductPurchase(player, PushProducts.Push5)
- elseif ClickedButtonName == "Push7" then
- MPS:PromptProductPurchase(player, PushProducts.Push7)
- elseif ClickedButtonName == "Push10" then
- MPS:PromptProductPurchase(player, PushProducts.Push10)
- end
- end
- --Handles working of troll UI
- function UserInterfaceController:TrollUI()
- -- Loop through each troll button (ImageButton inside Main Container)
- for i, trolls in pairs(TrollUI.Canvas.Container.Main.Container:GetChildren()) do
- if not trolls:IsA("ImageButton") then return end
- trolls.MouseEnter:Connect(function() -- When hovered, add purple UIStroke around "Default" image
- self:HandleUIStroke("Add", trolls:FindFirstChild("Default"))
- end)
- -- Remove stroke on mouse leave
- trolls.MouseLeave:Connect(function()
- self:HandleUIStroke("Remove")
- end)
- -- Refrence to the buy button inside Equipped or Default
- local BuyButton:ImageButton = trolls.Equipped:FindFirstChild("Buy") or trolls.Default:FindFirstChild("Buy")
- -- When clicked, trigger Marketplace purchase for selected troll type
- BuyButton.MouseButton1Click:Connect(function()
- local ClickedTrollName = BuyButton.Parent.Parent.Name
- self:PromptPurchase(ClickedTrollName)
- end)
- end
- end
- function UserInterfaceController:PushIUI()
- -- Loop through each push product (Push1, Push2, etc.)
- for i, button in pairs(PushUI.Canvas.Container.Main.Container:GetChildren()) do
- if not button:IsA("ImageButton") then return end
- button.MouseEnter:Connect(function()-- Same hover stroke logic as TrollUI
- self:HandleUIStroke("Add", button:FindFirstChild("Default"))
- end)
- button.MouseLeave:Connect(function()
- self:HandleUIStroke("Remove")
- end)
- -- Find Buy button
- local BuyButton:ImageButton = button.Equipped:FindFirstChild("Buy") or button.Default:FindFirstChild("Buy")
- -- Trigger MarketplaceService purchase when clickedcont
- BuyButton.MouseButton1Click:Connect(function()
- local ClickedButtonName = BuyButton.Parent.Parent.Name
- self:PromptPurchase(ClickedButtonName)
- end)
- end
- end
- function UserInterfaceController:applyTabStyle(activeBtn, inactive1, inactive2) --Function to switch between tabs
- activeBtn.BackgroundColor3 = Color3.fromRGB(255, 255, 255) --Changing the current selected tab button color to white
- activeBtn:FindFirstChild("UIGradient").Enabled = true --Appling UIGradient to the selected tab button
- activeBtn.Text.TextColor3 = Color3.new(255, 255, 255) --Changing the current selected tab text color to white
- inactive1.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Changing the inactive/non-selected tab button color to black
- inactive1:FindFirstChild("UIGradient").Enabled = false --Removing UIGradient effect from the non-selected tab button
- inactive1.Text.TextColor3 = Color3.new(113, 113, 113) --Changing the non-selected tab text color to white
- inactive2.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Changing the inactive/non-selected tab button color to black
- inactive2:FindFirstChild("UIGradient").Enabled = false --Removing UIGradient effect from the non-selected tab button
- inactive2.Text.TextColor3 = Color3.new(113, 113, 113) --Changing the non-selected tab text color to white
- end
- function UserInterfaceController:applyHoverEffect(button) --it appies effect to the template whenever mouse hover over and remove effect whenever mouse leave the button
- button.MouseEnter:Connect(function()
- self:HandleUIStroke("Add", button:FindFirstChild("Default"))
- end)
- button.MouseLeave:Connect(function()
- self:HandleUIStroke("Remove")
- end)
- end
- function UserInterfaceController:handleGamepassBuy(button) --Function to guess which gamepass prompt should popup
- local name = button.Parent.Parent.Name
- if name == "Coins2x" then
- MPS:PromptGamePassPurchase(player, 1272744022)
- elseif name == "Sprint" then
- MPS:PromptGamePassPurchase(player, 1273130340)
- elseif name == "RainbowNameTag" then
- MPS:PromptGamePassPurchase(player, 1274510513)
- end
- end
- function UserInterfaceController:handleProductBuy(button) --Function to prompt product purchase
- local name = button.Parent.Parent.Name
- local ids = {
- Coins50 = 3314212399,
- Coins100 = 3314212620,
- Coins300 = 3314213085,
- Coins500 = 3314213295,
- Coins1000 = 3314214142,
- }
- if ids[name] then
- MPS:PromptProductPurchase(player, ids[name])
- end
- end
- --Defines a reusable function to process items inside a container e.g gamepass or product UI elements
- function UserInterfaceController:processContainer(container, handlerFunc)
- for _, item in pairs(container:GetChildren()) do
- if not item:IsA("ImageButton") then return end
- self:applyHoverEffect(item) ---- Apply the hover effect logic
- local BuyButton:ImageButton = item.Equipped:FindFirstChild("Buy") or item.Default:FindFirstChild("Buy") --Trying to find the 'Buy' button either inside Equipped or Default frame
- if BuyButton then --Condition to check If a valid BuyButton is found
- handlerFunc(BuyButton) -- Execute the handler function/purchase logic depending on tab
- end
- end
- end
- function UserInterfaceController:handleRobuxBuy(itemName) --if player don't have enough ingame money to buy specific gamepass/product then he can pay robux to buy it
- local ids = {
- ExtraLifes = 3314996213,
- LessGravity = 3314996574,
- NameTags = 3314996930,
- }
- if ids[itemName] then
- MPS:PromptProductPurchase(player, ids[itemName])
- end
- end
- local ClonedPopupUI
- function UserInterfaceController:handleNotEnoughCoins(textLabel)
- textLabel.Text = "Not Enough Coins!"
- task.delay(2, function()
- textLabel.Text = "Buy"
- end)
- end
- -- Function to handle NameTag purchase
- function UserInterfaceController:handleNameTagPurchase()
- local NameTag = ReplicatedStorage.Assets:FindFirstChild("nametagui"):Clone()
- MapHandlerService:GiveNameTags(player.PlayerGui.ColourWheelGui.ColourDisplay.BackgroundColor3)
- player.PlayerGui.ColourWheelGui.Enabled = false
- end
- -- Function to handle general item purchase
- function UserInterfaceController:handleItemPurchase(button)
- local CloneTemplate = button.Parent.Parent:Clone()
- CloneTemplate.Parent = InventoryUI.Canvas.Container.Main.Container
- CloneTemplate.Default.Buy:Destroy()
- end
- function UserInterfaceController:onYesButtonClick(button) --if player click yes and have enough money as well then it procceed with the purchase
- local PlayerCoins = player:FindFirstChild("leaderstats"):WaitForChild("Coins")
- if PlayerCoins and PlayerCoins.Value >= button.Cost.Value then
- PlayerCoins.Value -= button.Cost.Value --deduct the cost of the purchase from player's coins
- if button.Parent.Parent.Name == "NameTags" then
- self:handleNameTagPurchase()
- else
- self:handleItemPurchase(button)
- end
- ClonedPopupUI:Destroy()
- else
- self:handleNotEnoughCoins()
- end
- end
- function UserInterfaceController:handlePopupBuy(button) --function to show popup UI whenever player clicks buy button so he can buy stuff cancel the purchase or buy it with robux
- local PopupUI = player.PlayerGui.Popup -- Refrence to popup UI
- ClonedPopupUI = PopupUI:Clone()
- ClonedPopupUI.Parent = player.PlayerGui
- ClonedPopupUI.Canvas.Visible = true
- if button.Parent.Parent.Name == "NameTags" then
- player.PlayerGui.ColourWheelGui.Enabled = true
- end
- ClonedPopupUI.Canvas.Main.YesButton.MouseButton1Click:Connect(function()
- self:onYesButtonClick(button)
- end)
- ClonedPopupUI.Canvas.Main.Closebutton.MouseButton1Click:Connect(function()
- ClonedPopupUI:Destroy() --remove cloned popupUI uplon clicking the close button
- end)
- ClonedPopupUI.Canvas.Main.Close.MouseButton1Click:Connect(function()
- ClonedPopupUI:Destroy() --remove cloned popupUI uplon clicking the cancel button
- end)
- ClonedPopupUI.Canvas.Main.BuyWithRobux.MouseButton1Click:Connect(function()
- self:handleRobuxBuy(button.Parent.Parent.Name) --if player don't have enough in game coins then by clicking BuyWithRobux button player can purchase items with robux instead
- ClonedPopupUI:Destroy()
- end)
- end
- function UserInterfaceController:ShopeUI()
- local NavigationList = ShopUI.Canvas.Container.Navigation.List
- local GamepassButton = NavigationList.Gamepass
- local DeveloperProductsButton = NavigationList.DeveloperProducts
- local StoreButton = NavigationList.Store
- local Container1 = ShopUI.Canvas.Container.Main.Container1 -- Gamepasses Tab
- local Container2 = ShopUI.Canvas.Container.Main.Container2 -- Dev Products Tab
- local Container3 = ShopUI.Canvas.Container.Main.Container3 -- Store Items Tab
- -- Gamepass tab button logic
- GamepassButton.MouseButton1Click:Connect(function()
- if Container2.Visible or Container3.Visible then
- Container2.Visible = false -- Hide other tabs
- Container3.Visible = false
- Container1.Visible = true -- Show gamepasses Tab
- self:applyTabStyle(GamepassButton, DeveloperProductsButton, StoreButton)
- end
- end)
- --Developer Products tab Button logic
- DeveloperProductsButton.MouseButton1Click:Connect(function()
- if Container1.Visible or Container3.Visible then
- Container1.Visible = false
- Container3.Visible = false
- Container2.Visible = true
- self:applyTabStyle(DeveloperProductsButton, GamepassButton, StoreButton)
- end
- end)
- -- Store tab button logic
- StoreButton.MouseButton1Click:Connect(function()
- if Container1.Visible or Container2.Visible then
- Container1.Visible = false
- Container2.Visible = false
- Container3.Visible = true
- self:applyTabStyle(StoreButton, GamepassButton, DeveloperProductsButton)
- end
- end)
- self:processContainer(Container1, function(BuyButton) --Process all gamepass UI items in Container1 and attach gamepass buying logic to Buy button
- BuyButton.MouseButton1Click:Connect(function() --Connecting the MouseButton1Click event to call the handleGamepassBuy function for gamepass purchase
- self:handleGamepassBuy(BuyButton) --Calls the function that prompts the player to buy the associated gamepass
- end)
- end)
- self:processContainer(Container2, function(BuyButton) --Process all developer product UI items in Container2 and attach product purchase logic to Buy button
- BuyButton.MouseButton1Click:Connect(function() --Connecting the MouseButton1Click event to call the handleGamepassBuy function for product purchase
- self:handleProductBuy(BuyButton) -- Calls the function that prompts the player to buy the associated developer product
- end)
- end)
- self:processContainer(Container3, function(BuyButton) --Process all store item UI elements in Container3 and attach custom popup handling to Buy button
- BuyButton.MouseButton1Click:Connect(function() --Connecting the MouseButton1Click event to call the handleGamepassBuy function for store purchases
- self:handlePopupBuy(BuyButton)--Calls the function that prompts the player to buy the associated item
- end)
- end)
- end
- function UserInterfaceController:OnUseButtonClicked(SidePanel, SelectedChild)
- if SidePanel.ItemName.Text == "ExtraLifes" then
- MapHandlerService:ExtraLifes() --Calls "ExtraLifes" function from MapHandlerService (server) to give player extra lifes
- SelectedChild:Destroy() -- Consume/Remove item
- SidePanel.ImageLabel.Image = ""
- SidePanel.ItemName.Text = "ItemName"
- SidePanel.ItemDescription.Text = "ItemDescription"
- elseif SidePanel.ItemName.Text == "LessGravity" then
- MapHandlerService:LessGravity("IncreaseGravityValue") --Calls "LessGravity" function
- end
- end
- function UserInterfaceController:UpdateSidePanel(SelectedChild, child, SidePanel)
- if SelectedChild or SelectedChild == child then return end
- SelectedChild = child
- UIStroke.Parent = child:FindFirstChild("Default")
- -- Update side panel
- SidePanel.ItemName.Text = child.Name
- SidePanel.ImageLabel.Image = child.Default.ImageLabel.Image
- SidePanel.ItemDescription.Text = child.Default.TextLabel.Text
- end
- function UserInterfaceController:InventoryHandler()
- local Container = InventoryUI.Canvas.Container.Main.Container -- refrence to hte frame that holds item buttons
- local SidePanel = InventoryUI.Canvas.Container.Main.SidePanel -- refrence to the frame that shows selected item details
- local SelectedChild = nil -- Currently selected item
- -- Setup UIStroke for selection outline
- local UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = nil
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- -- Use button logic
- SidePanel.Use.MouseButton1Click:Connect(function()
- self:OnUseButtonClicked(SidePanel, SelectedChild, SidePanel)
- end)
- -- When new item added to inventory
- Container.ChildAdded:Connect(function(child:ImageButton)
- child.MouseButton1Click:Connect(function()
- self:UpdateSidePanel(SelectedChild, child)
- end)
- end)
- end
- -- Format seconds into MM:SS format
- function UserInterfaceController:FormatTime(seconds)
- seconds = math.max(0, math.floor(seconds))
- local minutes = math.floor(seconds / 60)
- local secs = seconds % 60
- return string.format("%02d:%02d", minutes, secs)
- end
- -- Unlock times for rewards (in seconds)
- local TimeToUnlock = {
- Reward1 = 5 * 60,
- Reward2 = 10 * 60,
- Reward3 = 15 * 60,
- Reward4 = 20 * 60,
- Reward5 = 25 * 60,
- Reward6 = 30 * 60,
- Reward7 = 35 * 60,
- }
- function UserInterfaceController:UpdateRewardTimer(StartTime)
- for _, rewards in pairs(RewardUI.Canvas.Container.Main.Container:GetChildren()) do
- if not rewards:IsA("ImageButton") then continue end
- if rewards.Equipped.TextLabel.Text == "Unlock in: 00:00" then continue end -- if timer is already 0 then it prevents running the below code without disturbing the loop
- rewards.Equipped.TextLabel.Text = "Unlock in: " .. self:FormatTime(TimeToUnlock[rewards.Name] - (tick() - StartTime)) --Update the rewards time after formating seconds into MM:SS format
- if rewards.Equipped.TextLabel.Text ~= "Unlock in: 00:00" then continue end --if timer is reached 0 sec it changes rewards button text to equip
- rewards.Equipped.Buy.Backing.Text.Text = "Equip"
- end
- end
- function UserInterfaceController:OnEquipButtonClicK(EquipButton, Rewards)
- if EquipButton.Backing.Text.Text == "Locked yet!" then return end --if item is currently lock then stop execution of event immediately
- --if player has already equipped item then unEquip it
- if EquipButton.Backing.Text.Text == "Unequip" then
- local Success, errorMessage = MapHandlerService:WearBrainRot(Rewards:FindFirstChild("AssetId").Value, Rewards) --Fires server to make put brainrot on player sure after putting brainrot on player it is visible to everyone
- if not Success then return end --if everything goes well then it changes button text to Equip
- EquipButton.Backing.Text.Text = "Equip"
- return
- end
- --if player has not equipped item then equip it
- local Success, errorMessage = MapHandlerService:WearBrainRot(Rewards:FindFirstChild("AssetId").Value, "Wear", Rewards)
- if not Success then return end
- EquipButton.Backing.Text.Text = "Unequip"
- end
- function UserInterfaceController:RewardUI()
- local StartTime = tick() --returns the number of seconds since January 1st, 1970 UTC, useful for time elapsed calculations
- -- Update timer every second
- while task.wait(1) do
- task.spawn(self:UpdateRewardTimer(StartTime))
- end
- --loop through all the rewards available in reward UI container/scrolling Frame
- for _, Rewards in pairs(RewardUI.Canvas.Container.Main.Container:GetChildren()) do
- if not Rewards:IsA("ImageButton") then continue end
- Rewards.MouseEnter:Connect(function() --apply Hover effect whenever mouse hovers over the button
- self:HandleUIStroke("Add", Rewards:FindFirstChild("Default"))
- end)
- --remove UIStroke after player mouse leaves the button
- Rewards.MouseLeave:Connect(function()
- self:HandleUIStroke("Remove")
- end)
- local EquipButton:ImageButton = Rewards.Equipped:FindFirstChild("Buy") or Rewards.Default:FindFirstChild("Buy") --refrence to buy button
- local EquippedHat --last equipped Hat accessory
- local EquippedNeck --Last equipped neck accessory
- local EquippedFace --last equipped fconace accessory
- --handles equip button logic
- EquipButton.MouseButton1Click:Connect(function()
- self:OnEquipButtonClicK(EquipButton, Rewards)
- end)
- end
- end
- function UserInterfaceController:HideGivenCharacter(char, turningOff)
- for _, child in pairs(char:GetDescendants()) do
- --This condition will only execute if the child is a type of "BasePart" Or "MeshPart" or "Decal"
- if not (child:IsA("MeshPart") or child:IsA("BasePart") or child:IsA("Decal")) then continue end
- if child.Name == "HumanoidRootPart" then continue end
- child.Transparency = turningOff and 0 or 1 -- Hide or show the bodyparts of player character
- end
- end
- function UserInterfaceController:ManagePlayersInvisiblity(turningOff)
- -- Loop through all other players
- for _, Player in pairs(game.Players:GetPlayers()) do
- if Player == player then continue end
- local char = Player.Character
- if not char then continue end
- self:HideGivenCharacter(char, turningOff)
- end
- end
- --handles logics of setting UI
- function UserInterfaceController:SettignsUI()
- for _, Settings in pairs(SettingsUI.Canvas.Container.Main.Container:GetChildren()) do
- if not Settings:IsA("ImageLabel") then continue end
- local ToggleButton = Settings:FindFirstChild("ToggleButton")
- if not ToggleButton then continue end
- ToggleButton.MouseButton1Click:Connect(function() --Event which runs upon toggle button is clicked using left mouse button
- -- Determine toggle state
- local turningOff = Settings.Background.Toggle.ActiveFrame.Visible == true
- Settings.Background.Toggle.ActiveFrame.Visible = not turningOff
- Settings.Background.Toggle.InactiveFrame.Visible = turningOff
- self:ManagePlayersInvisiblity(turningOff)
- end)
- end
- end
- function UserInterfaceController:KnitInit()
- MapHandlerService = Knit.GetService("MapHandlerService") -- Fetch server-side service
- -- Init all UI features
- self:TrollUI()
- self:PushIUI()
- self:AnimateUIs()
- self:SettignsUI()
- self:ShopeUI()
- self:RewardUI()
- self:InventoryHandler()
- -- Show round countdown
- MapHandlerService.Timer:Connect(function()
- self:BackTimer()
- end)
- -- Display a center-screen message from the server
- MapHandlerService.Message:Connect(function(Message)
- self:ShowMessage(Message)
- end)
- -- Rope animation controller from server
- MapHandlerService.AnimateRopes:Connect(function(serverStartTime, Mode)
- self:startAnimationWhenReady(serverStartTime, Mode)
- end)
- end
- return UserInterfaceController
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement