Advertisement
Scripting_King

Untitled

Jul 5th, 2025
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 29.41 KB | Source Code | 0 0
  1. --[[
  2. Squid Game User Interface Controller
  3. Handles shop UI, reward UI, tool activation, gamepasses, animations, and GUI interaction logic using Knit framework.
  4. ]]
  5. --by the_king_here
  6. --//SERVICES
  7. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  8. local Knit = require(ReplicatedStorage.Packages.Knit)
  9. local TweenService = game:GetService("TweenService")
  10. local runService = game:GetService("RunService")
  11. local MPS = game:GetService("MarketplaceService")
  12. local LightningService = game:GetService("Lighting")
  13. local SoundService = game:GetService("SoundService")
  14.  
  15.  
  16. --TweenInfo config for UI transitions (0.3s, Back Out easing)
  17. local tweenInfoUI = TweenInfo.new(0.3, Enum.EasingStyle.Back, Enum.EasingDirection.Out, 0)
  18.  
  19. -- Creating a Knit Controller
  20. local UserInterfaceController = Knit.CreateController{
  21.     Name = "UserInterface",
  22. }
  23.  
  24. -- Will store reference to the server side service later
  25. local MapHandlerService
  26.  
  27. -- Reference to the local player
  28. local player = game.Players.LocalPlayer
  29.  
  30. -- Control module to disable movement during certain actions
  31. local Controls = require(player.PlayerScripts.PlayerModule):GetControls()
  32.  
  33. -- UI References in PlayerGui
  34. local TrollUI = player.PlayerGui:WaitForChild("Troll")
  35. local PushUI = player.PlayerGui:WaitForChild("PushUI")
  36. local SettingsUI = player.PlayerGui:WaitForChild("Settings")
  37. local ShopUI = player.PlayerGui:WaitForChild("Shop")
  38. local InventoryUI = player.PlayerGui:WaitForChild("Inventory")
  39. local RewardUI = player.PlayerGui:WaitForChild("Reward")
  40.  
  41. -- Music References
  42. local BackgroundMusic = SoundService:WaitForChild("LobbyMusic")
  43. local SquidMusic = SoundService:WaitForChild("Music")
  44.  
  45. -- Developer product IDs
  46. local Products = {
  47.     EliminatePlayers = 3312415657,
  48.     SpeedTroll = 3312416017,
  49.     KillRandomPersonTroll = 3312444642,
  50.     TakeCoinsTroll = 3312417586,
  51. }
  52.  
  53. -- Push upgrades (more force or quantity)
  54. local PushProducts = {
  55.     Push1 = 3313283431,
  56.     Push2 = 3313283430,
  57.     Push5 = 3313283433,
  58.     Push7 = 3313283424,
  59.     Push10 = 3313286623,
  60. }
  61.  
  62. -- Tweening for background music transitions
  63. local tweenInfoForMusic = TweenInfo.new(1.5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0)
  64.  
  65. -- Reference to the camera for FOV changes
  66. local camera = workspace.CurrentCamera
  67.  
  68. -- Blur effect (GUI background blur)
  69. local Blur = LightningService:FindFirstChild("BlurForGui")
  70.  
  71. -- For rope animation disconnecting later
  72. local RopeAnimationConnection
  73.  
  74. -- Countdown before round starts (e.g., "3, 2, 1... Run!")
  75. function UserInterfaceController:BackTimer(StartTime, EndTime, UIToShowTime)
  76.     for i = StartTime, EndTime, -1 do
  77.         wait(1)
  78.         player.PlayerGui:WaitForChild("Timer").TextLabel.Visible = true
  79.         player.PlayerGui.Timer.TextLabel.Text = i --Displays time on textlabel
  80.         player.PlayerGui.Timer.TextLabel.TimerSound:Play() --plays timer sound every second
  81.         if i == 0 then
  82.             wait(1)
  83.             player.PlayerGui.Timer.TextLabel.Text = "Run!" -- Final message
  84.             task.delay(1.5, function()
  85.                 player.PlayerGui.Timer.TextLabel.Visible = false
  86.             end)
  87.         end
  88.     end
  89. end
  90.  
  91. -- Displays a short message on screen (centered label) for 3 seconds
  92. function UserInterfaceController:ShowMessage(Message)
  93.     player.PlayerGui:WaitForChild("Timer").TextLabel.Visible = true
  94.     player.PlayerGui.Timer.TextLabel.Text = Message
  95.     task.delay(3, function()
  96.         player.PlayerGui.Timer.TextLabel.Visible = false
  97.     end)
  98. end
  99.  
  100. local Rope -- rope part reference (used in Easy or Hard maps)
  101.  
  102. local maxSpeed -- max angular speed in radians/sec
  103. local accelTime = 3 -- how long to accelerate (ease in) in seconds
  104. local animationStarted = false -- variable to check if animation has started
  105. local animationStartTime = nil  -- server-synced time when animation begins
  106.  
  107. local initialCFrame -- store original rope CFrame
  108.  
  109. -- Begins rope rotation animation based on server time
  110. function UserInterfaceController:startAnimationWhenReady(serverStartTime, Mode)
  111.     -- Decide map + speed based on mode
  112.     if Mode == "Easy" then
  113.         maxSpeed = math.rad(210) -- degrees to radians
  114.         Rope = workspace.Maps.EasyRopemap:WaitForChild("rope")
  115.     else
  116.         maxSpeed = math.rad(250)
  117.         Rope = workspace.Maps.HadRopeMap:WaitForChild("rope")
  118.     end
  119.     local primary = Rope.PrimaryPart --Stores refrence to rope primaryPart
  120.     initialCFrame = primary.CFrame -- store starting position
  121.     animationStartTime = serverStartTime
  122.     animationStarted = false
  123.     Controls:Disable() -- Disable player movement during pre rope animation
  124.  
  125.     -- If player has LessGravity effect, set gravity to 70
  126.     local LessGravity = player:FindFirstChild("LessGravity")
  127.     if LessGravity.Value > 0 then
  128.         MapHandlerService:LessGravity("DecreaseGravityValue")
  129.         workspace.Gravity = 70
  130.     end
  131.  
  132.  
  133.     local IsEnabledControls = false --keep track whether controls of player has been restored or not
  134.     -- Connect to RenderStepped to animate rope every frame
  135.     RopeAnimationConnection = runService.RenderStepped:Connect(function()
  136.         local now = workspace:GetServerTimeNow() --get current time
  137.         -- Wait until server-synced animation time
  138.         if not animationStarted and now >= animationStartTime then
  139.             animationStarted = true
  140.         end
  141.         if not animationStarted then return end
  142.  
  143.         -- Enable player controls 1 second after rope starts
  144.         if not IsEnabledControls then
  145.             IsEnabledControls = true
  146.             task.delay(1, function()
  147.                 Controls:Enable()
  148.             end)
  149.         end
  150.  
  151.         local elapsed = now - animationStartTime -- how long since animation began
  152.         local rotation --Stores rotation value
  153.  
  154.         -- Accelerate with cubic easing for first 3 seconds
  155.         if elapsed < accelTime then
  156.             local progress = elapsed / accelTime
  157.             rotation = 0.33 * maxSpeed * (progress ^ 3) * accelTime
  158.         else
  159.             -- Maintain constant speed after acceleration phase
  160.             local constantTime = elapsed - accelTime
  161.             rotation = 0.33 * maxSpeed * accelTime + maxSpeed * constantTime
  162.         end
  163.  
  164.         -- Rotate rope by X-axis only
  165.         local newCFrame = initialCFrame * CFrame.Angles(rotation, 0, 0)
  166.         Rope:PivotTo(newCFrame)
  167.     end)
  168. end
  169.  
  170. --returns name after removing text "button" from name if name contains text "Button"
  171. function UserInterfaceController:getNameAfterRemovingButton(name)
  172.     local suffix = "Button"
  173.     if name:sub(-#suffix) == suffix then
  174.         return name:sub(1, -#suffix - 1)
  175.     else
  176.         return name
  177.     end
  178. end
  179.  
  180. local originalRotation = 0 --Stoers default rotation, which is usually 0
  181.  
  182. -- function to scale UDim2 (used to make buttons shrink or grow)
  183. function UserInterfaceController:scaleSize(size: UDim2, scale: number): UDim2
  184.     return UDim2.new(
  185.         size.X.Scale * scale, size.X.Offset * scale,
  186.         size.Y.Scale * scale, size.Y.Offset * scale
  187.     )
  188. end
  189.  
  190. -- When mouse enters button (hover), enlarge slightly + rotate
  191. function UserInterfaceController:onHover(button, originalSize)
  192.     local hoverTween = TweenService:Create(button, TweenInfo.new(0.1), {
  193.         Size = self:scaleSize(originalSize, 1.1),
  194.         Rotation = 5,
  195.     })
  196.     hoverTween:Play()
  197. end
  198.  
  199. -- When mouse leaves button, restore size and rotation
  200. function UserInterfaceController:onUnhover(button, originalSize)
  201.     local unhoverTween = TweenService:Create(button, TweenInfo.new(0.1), {
  202.         Size = originalSize,
  203.         Rotation = originalRotation,
  204.     })
  205.     unhoverTween:Play()
  206. end
  207.  
  208. -- When button is clicked, shrink quickly then bounce back
  209. function UserInterfaceController:onClick(button, originalSize)
  210.     local shrinkTween = TweenService:Create(button, TweenInfo.new(0.05), {
  211.         Size = self:scaleSize(originalSize, 0.8),
  212.     })
  213.     local restoreTween = TweenService:Create(button, TweenInfo.new(0.1), {
  214.         Size = originalSize,
  215.     })
  216.  
  217.     shrinkTween:Play()
  218.     shrinkTween.Completed:Connect(function()
  219.         restoreTween:Play()
  220.     end)
  221. end
  222. local OpenedUI -- Tracks which UI is currently open
  223.  
  224. -- Applies hover/click effcts and manages showing/hiding UIs like Shop, Inventory, etc.
  225. function UserInterfaceController:AnimateUIs()
  226.     local UIButtons = player:WaitForChild("PlayerGui"):WaitForChild("Buttons")
  227.  
  228.     local Debounce = false -- Prevents spam clicking
  229.  
  230.     local function tweenOpen(Canavs) --Function to open UI with tween/animation
  231.         Canavs.Visible = true
  232.         Canavs.Position = UDim2.new(0.5, 0, 1.5, 0)
  233.         Canavs:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3) --Animating the position of the UI
  234.         TweenService:Create(camera, tweenInfoUI, {FieldOfView = 100}):Play() --Increasing FOV with animation to give overall animation better look
  235.         TweenService:Create(Blur, tweenInfoUI, {Size = 20}):Play() --Applying blur with animation
  236.     end
  237.  
  238.     local function tweenClose(Canavs) --function to close UI with tween/animation
  239.         Canavs:TweenPosition(UDim2.new(0.5, 0, 1.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3)
  240.         TweenService:Create(camera, tweenInfoUI, {FieldOfView = 70}):Play()
  241.         TweenService:Create(Blur, tweenInfoUI, {Size = 0}):Play()
  242.     end
  243.  
  244.     local function handleUIState(Canavs)
  245.         if not OpenedUI then -- No UI open yet
  246.             OpenedUI = Canavs --Defines the current open UI
  247.             tweenOpen(Canavs)
  248.         elseif OpenedUI and OpenedUI ~= Canavs then-- Switching from one UI to another
  249.             tweenClose(OpenedUI)
  250.             OpenedUI = Canavs
  251.             tweenOpen(Canavs)
  252.         elseif OpenedUI == Canavs then -- UI is already open, so close it
  253.             OpenedUI = nil --closed opened UI so now no UI opened so make OpenedUI variable nil
  254.             tweenClose(Canavs)
  255.         end
  256.  
  257.         task.delay(0.3, function()
  258.             Debounce = false
  259.         end)
  260.     end
  261.  
  262.     for i, button in pairs(UIButtons:GetChildren()) do
  263.         if not button:IsA("Frame") then continue end
  264.  
  265.         local Button = button:FindFirstChildOfClass("TextButton") -- Find the clickable button
  266.         if not Button then continue end
  267.  
  268.         local originalSize = button.Size
  269.         local FrameName = self:getNameAfterRemovingButton(button.Name) -- Remove "Button" suffix
  270.         local Frame = player.PlayerGui:FindFirstChild(FrameName) --get the frame with the given value after removing "Button" suffix
  271.         if not Frame then continue end
  272.  
  273.         local isModes = Frame.Name == "Modes"
  274.         local Canavs = Frame:FindFirstChild(isModes and "Frame" or "Canvas")
  275.         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"))
  276.  
  277.         if not Canavs or not CloseButton then continue end
  278.  
  279.         -- Hover event
  280.         button.MouseEnter:Connect(function()
  281.             self:onHover(button, originalSize)
  282.         end)
  283.  
  284.         -- Unhover event
  285.         button.MouseLeave:Connect(function()
  286.             self:onUnhover(button, originalSize)
  287.         end)
  288.  
  289.         -- Button click (open/close logic)
  290.         Button.MouseButton1Click:Connect(function()
  291.             if Debounce then return end
  292.             Debounce = true
  293.             self:onClick(button, originalSize)
  294.             handleUIState(Canavs)
  295.         end)
  296.  
  297.         -- Close button logic/closes the opened UI
  298.         CloseButton.MouseButton1Click:Connect(function()
  299.             if Debounce then return end
  300.             Debounce = true
  301.             OpenedUI = nil
  302.             --Closes UI with tween
  303.             tweenClose(Canavs)
  304.             -- Reset camera FOV and continblur
  305.             task.delay(0.3, function()
  306.                 Debounce = false
  307.             end)
  308.         end)
  309.     end
  310. end
  311.  
  312.  
  313. --Handles working of troll UI
  314. function UserInterfaceController:TrollUI()
  315.     local UIStroke
  316.     -- Loop through each troll button (ImageButton inside Main Container)
  317.     for i, trolls in pairs(TrollUI.Canvas.Container.Main.Container:GetChildren()) do
  318.         if not trolls:IsA("ImageButton") then return end
  319.         trolls.MouseEnter:Connect(function() -- When hovered, add purple UIStroke around "Default" image
  320.             if not UIStroke then
  321.                 UIStroke = Instance.new("UIStroke")
  322.                 UIStroke.Parent = trolls:FindFirstChild("Default")
  323.                 UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
  324.                 UIStroke.Color = Color3.fromRGB(126, 36, 233)
  325.                 UIStroke.Thickness = 2
  326.             else
  327.                 UIStroke.Parent = trolls:FindFirstChild("Default")
  328.             end
  329.         end)
  330.  
  331.         -- Remove stroke on mouse leave
  332.         trolls.MouseLeave:Connect(function()
  333.             UIStroke.Parent = nil
  334.         end)
  335.  
  336.         -- Refrence to the buy button inside Equipped or Default
  337.         local BuyButton:ImageButton = trolls.Equipped:FindFirstChild("Buy") or trolls.Default:FindFirstChild("Buy")
  338.  
  339.         -- When clicked, trigger Marketplace purchase for selected troll type
  340.         BuyButton.MouseButton1Click:Connect(function()
  341.             local ClickedTrollName = BuyButton.Parent.Parent.Name
  342.             if ClickedTrollName == "EliminatePlayers" then
  343.                 MPS:PromptProductPurchase(player, Products.EliminatePlayers)
  344.             elseif ClickedTrollName == "SpeedTroll" then
  345.                 MPS:PromptProductPurchase(player, Products.SpeedTroll)
  346.             elseif ClickedTrollName == "KillRandomPersonTroll" then
  347.                 MPS:PromptProductPurchase(player, Products.KillRandomPersonTroll)
  348.             elseif ClickedTrollName == "TakeCoinsTroll" then
  349.                 MPS:PromptProductPurchase(player, Products.TakeCoinsTroll)
  350.             end
  351.         end)
  352.     end
  353. end
  354.  
  355.  
  356.  
  357. function UserInterfaceController:PushIUI()
  358.     local UIStroke
  359.  
  360.     -- Loop through each push product (Push1, Push2, etc.)
  361.     for i, trolls in pairs(PushUI.Canvas.Container.Main.Container:GetChildren()) do
  362.         if not trolls:IsA("ImageButton") then return end
  363.         trolls.MouseEnter:Connect(function()-- Same hover stroke logic as TrollUI
  364.             if not UIStroke then
  365.                 UIStroke = Instance.new("UIStroke")
  366.                 UIStroke.Parent = trolls:FindFirstChild("Default")
  367.                 UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
  368.                 UIStroke.Color = Color3.fromRGB(126, 36, 233)
  369.                 UIStroke.Thickness = 2
  370.             else
  371.                 UIStroke.Parent = trolls:FindFirstChild("Default")
  372.             end
  373.         end)
  374.  
  375.         trolls.MouseLeave:Connect(function()
  376.             UIStroke.Parent = nil
  377.         end)
  378.  
  379.         -- Find Buy button
  380.         local BuyButton:ImageButton = trolls.Equipped:FindFirstChild("Buy") or trolls.Default:FindFirstChild("Buy")
  381.  
  382.         -- Trigger MarketplaceService purchase when clickedcont
  383.         BuyButton.MouseButton1Click:Connect(function()
  384.             local ClickedButtonName = BuyButton.Parent.Parent.Name
  385.             if ClickedButtonName == "Push1" then
  386.                 MPS:PromptProductPurchase(player, PushProducts.Push1)
  387.             elseif ClickedButtonName == "Push2" then
  388.                 MPS:PromptProductPurchase(player, PushProducts.Push2)
  389.             elseif ClickedButtonName == "Push5" then
  390.                 MPS:PromptProductPurchase(player, PushProducts.Push5)
  391.             elseif ClickedButtonName == "Push7" then
  392.                 MPS:PromptProductPurchase(player, PushProducts.Push7)
  393.             elseif ClickedButtonName == "Push10" then
  394.                 MPS:PromptProductPurchase(player, PushProducts.Push10)
  395.             end
  396.         end)
  397.     end
  398. end
  399.  
  400. local ClonedPopupUI
  401.  
  402. function UserInterfaceController:ShopeUI()
  403.     local UIStroke
  404.  
  405.     local NavigationList = ShopUI.Canvas.Container.Navigation.List
  406.  
  407.     local PopupUI = player.PlayerGui.Popup -- Refrence to popup UI
  408.  
  409.     local GamepassButton = NavigationList.Gamepass
  410.     local DeveloperProductsButton = NavigationList.DeveloperProducts
  411.     local StoreButton = NavigationList.Store
  412.  
  413.     local Container1 = ShopUI.Canvas.Container.Main.Container1 -- Gamepasses Tab
  414.     local Container2 = ShopUI.Canvas.Container.Main.Container2 -- Dev Products Tab
  415.     local Container3 = ShopUI.Canvas.Container.Main.Container3 -- Store Items Tab
  416.  
  417.     local function applyTabStyle(activeBtn, inactive1, inactive2) --Function to switch between tabs
  418.         activeBtn.BackgroundColor3 = Color3.fromRGB(255, 255, 255) --Changing the current selected tab button color to white
  419.         activeBtn:FindFirstChild("UIGradient").Enabled = true  --Appling UIGradient to the selected tab button
  420.         activeBtn.Text.TextColor3 = Color3.new(255, 255, 255) --Changing the current selected tab text color to white
  421.  
  422.         inactive1.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Changing the inactive/non-selected tab button color to black
  423.         inactive1:FindFirstChild("UIGradient").Enabled = false --Removing UIGradient effect from the non-selected tab button
  424.         inactive1.Text.TextColor3 = Color3.new(113, 113, 113) --Changing the non-selected tab text color to white
  425.  
  426.         inactive2.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Changing the inactive/non-selected tab button color to black
  427.         inactive2:FindFirstChild("UIGradient").Enabled = false --Removing UIGradient effect from the non-selected tab button
  428.         inactive2.Text.TextColor3 = Color3.new(113, 113, 113) --Changing the non-selected tab text color to white
  429.     end
  430.  
  431.     local function applyHoverEffect(button) --it appies effect to the template whenever mouse hover over and remove effect whenever mouse leave the button
  432.         button.MouseEnter:Connect(function()
  433.             if not UIStroke then
  434.                 UIStroke = Instance.new("UIStroke")
  435.                 UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
  436.                 UIStroke.Color = Color3.fromRGB(126, 36, 233)
  437.                 UIStroke.Thickness = 2
  438.             end
  439.             UIStroke.Parent = button:FindFirstChild("Default")
  440.         end)
  441.  
  442.         button.MouseLeave:Connect(function()
  443.             UIStroke.Parent = nil
  444.         end)
  445.     end
  446.  
  447.     local function handleGamepassBuy(button) --Function to guess which gamepass prompt should popup
  448.         local name = button.Parent.Parent.Name
  449.         if name == "Coins2x" then
  450.             MPS:PromptGamePassPurchase(player, 1272744022)
  451.         elseif name == "Sprint" then
  452.             MPS:PromptGamePassPurchase(player, 1273130340)
  453.         elseif name == "RainbowNameTag" then
  454.             MPS:PromptGamePassPurchase(player, 1274510513)
  455.         end
  456.     end
  457.  
  458.     local function handleProductBuy(button) --Function to prompt product purchase
  459.         local name = button.Parent.Parent.Name
  460.         local ids = {
  461.             Coins50 = 3314212399,
  462.             Coins100 = 3314212620,
  463.             Coins300 = 3314213085,
  464.             Coins500 = 3314213295,
  465.             Coins1000 = 3314214142,
  466.         }
  467.         if ids[name] then
  468.             MPS:PromptProductPurchase(player, ids[name])
  469.         end
  470.     end
  471.  
  472.     local function handleRobuxBuy(itemName) --if player don't have enough ingame money to buy specific gamepass/product then he can pay robux to buy it
  473.         local ids = {
  474.             ExtraLifes = 3314996213,
  475.             LessGravity = 3314996574,
  476.             NameTags = 3314996930,
  477.         }
  478.         if ids[itemName] then
  479.             MPS:PromptProductPurchase(player, ids[itemName])
  480.         end
  481.     end
  482.  
  483.     local function 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
  484.         ClonedPopupUI = PopupUI:Clone()
  485.         ClonedPopupUI.Parent = player.PlayerGui
  486.         ClonedPopupUI.Canvas.Visible = true
  487.  
  488.         if button.Parent.Parent.Name == "NameTags" then
  489.             player.PlayerGui.ColourWheelGui.Enabled = true
  490.         end
  491.  
  492.         ClonedPopupUI.Canvas.Main.YesButton.MouseButton1Click:Connect(function()
  493.             local PlayerCoins = player:FindFirstChild("leaderstats"):WaitForChild("Coins")
  494.             if PlayerCoins and PlayerCoins.Value >= button.Cost.Value then
  495.                 PlayerCoins.Value -= button.Cost.Value
  496.  
  497.                 if button.Parent.Parent.Name == "NameTags" then
  498.                     local NameTag = ReplicatedStorage.Assets:FindFirstChild("nametagui"):Clone()
  499.                     MapHandlerService:GiveNameTags(player.PlayerGui.ColourWheelGui.ColourDisplay.BackgroundColor3)
  500.                     player.PlayerGui.ColourWheelGui.Enabled = false
  501.                 else
  502.                     local CloneTemplate = button.Parent.Parent:Clone()
  503.                     CloneTemplate.Parent = InventoryUI.Canvas.Container.Main.Container
  504.                     CloneTemplate.Default.Buy:Destroy()
  505.                 end
  506.  
  507.                 ClonedPopupUI:Destroy()
  508.             else
  509.                 ClonedPopupUI.Canvas.Main.YesButton.Main.TextLabel.Text = "Not Enough Coins!"
  510.                 task.delay(2, function()
  511.                     ClonedPopupUI.Canvas.Main.YesButton.Main.TextLabel.Text = "Buy"
  512.                 end)
  513.             end
  514.         end)
  515.  
  516.         ClonedPopupUI.Canvas.Main.Closebutton.MouseButton1Click:Connect(function()
  517.             ClonedPopupUI:Destroy()
  518.         end)
  519.  
  520.         ClonedPopupUI.Canvas.Main.Close.MouseButton1Click:Connect(function()
  521.             ClonedPopupUI:Destroy()
  522.         end)
  523.  
  524.         ClonedPopupUI.Canvas.Main.BuyWithRobux.MouseButton1Click:Connect(function()
  525.             handleRobuxBuy(button.Parent.Parent.Name)
  526.         end)
  527.     end
  528.  
  529.     -- Gamepass tab button logic
  530.     GamepassButton.MouseButton1Click:Connect(function()
  531.         if Container2.Visible or Container3.Visible then
  532.             Container2.Visible = false -- Hide other tabs
  533.             Container3.Visible = false
  534.             Container1.Visible = true  -- Show gamepasses Tab
  535.             applyTabStyle(GamepassButton, DeveloperProductsButton, StoreButton)
  536.         end
  537.     end)
  538.  
  539.     --Developer Products tab Button logic
  540.     DeveloperProductsButton.MouseButton1Click:Connect(function()
  541.         if Container1.Visible or Container3.Visible then
  542.             Container1.Visible = false
  543.             Container3.Visible = false
  544.             Container2.Visible = true
  545.             applyTabStyle(DeveloperProductsButton, GamepassButton, StoreButton)
  546.         end
  547.     end)
  548.  
  549.     -- Store tab button logic
  550.     StoreButton.MouseButton1Click:Connect(function()
  551.         if Container1.Visible or Container2.Visible then
  552.             Container1.Visible = false
  553.             Container2.Visible = false
  554.             Container3.Visible = true
  555.             applyTabStyle(StoreButton, GamepassButton, DeveloperProductsButton)
  556.         end
  557.     end)
  558.  
  559.     --Defines a reusable function to process items inside a container e.g gamepass or product UI elements
  560.     local function processContainer(container, handlerFunc)
  561.         for _, item in pairs(container:GetChildren()) do
  562.             if not item:IsA("ImageButton") then return end
  563.             applyHoverEffect(item) ---- Apply the hover effect logic
  564.             local BuyButton:ImageButton = item.Equipped:FindFirstChild("Buy") or item.Default:FindFirstChild("Buy") --Trying to find the 'Buy' button either inside Equipped or Default frame
  565.  
  566.             if BuyButton then --Condition to check If a valid BuyButton is found
  567.                 handlerFunc(BuyButton) -- Execute the handler function/purchase logic depending on tab
  568.             end
  569.         end
  570.     end
  571.  
  572.     processContainer(Container1, function(BuyButton) --Process all gamepass UI items in Container1 and attach gamepass buying logic to Buy button
  573.         BuyButton.MouseButton1Click:Connect(function() --Connecting the MouseButton1Click event to call the handleGamepassBuy function for gamepass purchase
  574.             handleGamepassBuy(BuyButton) --Calls the function that prompts the player to buy the associated gamepass
  575.         end)
  576.     end)
  577.  
  578.  
  579.     processContainer(Container2, function(BuyButton) --Process all developer product UI items in Container2 and attach product purchase logic to Buy button
  580.         BuyButton.MouseButton1Click:Connect(function() --Connecting the MouseButton1Click event to call the handleGamepassBuy function for product purchase
  581.             handleProductBuy(BuyButton) -- Calls the function that prompts the player to buy the associated developer product
  582.         end)
  583.     end)
  584.  
  585.     processContainer(Container3, function(BuyButton) --Process all store item UI elements in Container3 and attach custom popup handling to Buy button
  586.         BuyButton.MouseButton1Click:Connect(function() --Connecting the MouseButton1Click event to call the handleGamepassBuy function for store purchases
  587.             handlePopupBuy(BuyButton)--Calls the function that prompts the player to buy the associated item
  588.         end)
  589.     end)
  590. end
  591.  
  592.  
  593. function UserInterfaceController:InventoryHandler()
  594.     local Container = InventoryUI.Canvas.Container.Main.Container -- refrence to hte frame that holds item buttons
  595.     local SidePanel = InventoryUI.Canvas.Container.Main.SidePanel -- refrence to the frame that shows selected item details
  596.  
  597.     local SelectedChild -- Currently selected item
  598.  
  599.     -- Setup UIStroke for selection outline
  600.     local UIStroke = Instance.new("UIStroke")
  601.     UIStroke.Parent = nil
  602.     UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
  603.     UIStroke.Color = Color3.fromRGB(126, 36, 233)
  604.     UIStroke.Thickness = 2
  605.  
  606.     -- Use button logic
  607.     SidePanel.Use.MouseButton1Click:Connect(function()
  608.         if SidePanel.ItemName.Text == "ExtraLifes" then
  609.             MapHandlerService:ExtraLifes() --Calls "ExtraLifes" function from MapHandlerService (server) to give player extra lifes
  610.             SelectedChild:Destroy() -- Consume/Remove item
  611.             SidePanel.ImageLabel.Image = ""
  612.             SidePanel.ItemName.Text = "ItemName"
  613.             SidePanel.ItemDescription.Text = "ItemDescription"
  614.         elseif SidePanel.ItemName.Text == "LessGravity" then
  615.             MapHandlerService:LessGravity("IncreaseGravityValue") --Calls "LessGravity" function
  616.         end
  617.     end)
  618.  
  619.     -- When new item added to inventory
  620.     Container.ChildAdded:Connect(function(child:ImageButton)
  621.         child.MouseButton1Click:Connect(function()
  622.             if SelectedChild or SelectedChild == child then return end
  623.             SelectedChild = child
  624.             UIStroke.Parent = child:FindFirstChild("Default")
  625.             -- Update side panel
  626.             SidePanel.ItemName.Text = child.Name
  627.             SidePanel.ImageLabel.Image = child.Default.ImageLabel.Image
  628.             SidePanel.ItemDescription.Text = child.Default.TextLabel.Text
  629.         end)
  630.     end)
  631. end
  632.  
  633. -- Format seconds into MM:SS format
  634. function UserInterfaceController:FormatTime(seconds)
  635.     seconds = math.max(0, math.floor(seconds))
  636.  
  637.     local minutes = math.floor(seconds / 60)
  638.     local secs = seconds % 60
  639.  
  640.     return string.format("%02d:%02d", minutes, secs)
  641. end
  642.  
  643. -- Unlock times for rewards (in seconds)
  644. local TimeToUnlock = {
  645.     Reward1 = 5 * 60,
  646.     Reward2 = 10 * 60,
  647.     Reward3 = 15 * 60,
  648.     Reward4 = 20 * 60,
  649.     Reward5 = 25 * 60,
  650.     Reward6 = 30 * 60,
  651.     Reward7 = 35 * 60,
  652. }
  653.  
  654. function UserInterfaceController:RewardUI()
  655.     local UIStroke
  656.  
  657.     local StartTime = tick() --returns the number of seconds since January 1st, 1970 UTC, useful for time elapsed calculations
  658.  
  659.     -- Update timer every second
  660.     spawn(function()
  661.         while wait(1) do
  662.             for _, rewards in pairs(RewardUI.Canvas.Container.Main.Container:GetChildren()) do
  663.                 if not rewards:IsA("ImageButton") then continue end
  664.  
  665.                 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
  666.  
  667.                 rewards.Equipped.TextLabel.Text = "Unlock in: " .. self:FormatTime(TimeToUnlock[rewards.Name] - (tick() - StartTime)) --Update the rewards time after formating seconds into MM:SS format
  668.  
  669.                 if rewards.Equipped.TextLabel.Text == "Unlock in: 00:00" then --if timer is reached 0 sec it changes rewards button text to equip
  670.                     rewards.Equipped.Buy.Backing.Text.Text = "Equip"
  671.                 end
  672.             end
  673.         end
  674.     end)
  675.  
  676.     --loop through all the rewards available in reward UI container/scrolling Frame
  677.     for _, Rewards in pairs(RewardUI.Canvas.Container.Main.Container:GetChildren()) do
  678.         if not Rewards:IsA("ImageButton") then continue end
  679.  
  680.         Rewards.MouseEnter:Connect(function() --apply Hover effect whenever mouse hovers over the button
  681.             if not UIStroke then  --same UIStroke logic
  682.                 UIStroke = Instance.new("UIStroke")
  683.                 UIStroke.Parent = Rewards:FindFirstChild("Default")
  684.                 UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
  685.                 UIStroke.Color = Color3.fromRGB(126, 36, 233)
  686.                 UIStroke.Thickness = 2
  687.             else
  688.                 UIStroke.Parent = Rewards:FindFirstChild("Default")
  689.             end
  690.         end)
  691.  
  692.         --remove UIStroke after player mouse leaves the button
  693.         Rewards.MouseLeave:Connect(function()
  694.             UIStroke.Parent = nil
  695.         end)
  696.  
  697.         local EquipButton:ImageButton = Rewards.Equipped:FindFirstChild("Buy") or Rewards.Default:FindFirstChild("Buy") --refrence to buy button
  698.  
  699.         local EquippedHat --last equipped Hat accessory
  700.         local EquippedNeck --Last equipped neck accessory
  701.         local EquippedFace --last equipped fconace accessory
  702.  
  703.         --handles equip button logic
  704.         EquipButton.MouseButton1Click:Connect(function()
  705.             if EquipButton.Backing.Text.Text == "Locked yet!" then return end --if item is currently lock then stop execution of event immediately
  706.  
  707.             --if player has already equipped item then unEquip it
  708.             if EquipButton.Backing.Text.Text == "Unequip" then
  709.                 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
  710.                 if Success then --if everything goes well then it changes button text to Equip
  711.                     EquipButton.Backing.Text.Text = "Equip"
  712.                 end
  713.                 return
  714.             end
  715.  
  716.             --if player has not equipped item then equip it
  717.             local Success, errorMessage = MapHandlerService:WearBrainRot(Rewards:FindFirstChild("AssetId").Value, "Wear", Rewards)
  718.             if Success then
  719.                 EquipButton.Backing.Text.Text = "Unequip"
  720.             end
  721.         end)
  722.     end
  723. end
  724.  
  725. --handles logics of setting UI
  726. function UserInterfaceController:SettignsUI()
  727.     for _, Settings in pairs(SettingsUI.Canvas.Container.Main.Container:GetChildren()) do
  728.         if not Settings:IsA("ImageLabel") then continue end
  729.  
  730.         local ToggleButton = Settings:FindFirstChild("ToggleButton")
  731.         if not ToggleButton then continue end
  732.  
  733.  
  734.         ToggleButton.MouseButton1Click:Connect(function() --Event which runs upon toggle button is clicked using left mouse button
  735.  
  736.             -- Determine toggle state
  737.             local turningOff = Settings.Background.Toggle.ActiveFrame.Visible == true
  738.  
  739.             Settings.Background.Toggle.ActiveFrame.Visible = not turningOff
  740.             Settings.Background.Toggle.InactiveFrame.Visible = turningOff
  741.  
  742.             -- Loop through all other players
  743.             for _, Player in pairs(game.Players:GetPlayers()) do
  744.                 if Player == player then continue end
  745.  
  746.                 local char = Player.Character
  747.                 if not char then continue end
  748.  
  749.                 for _, child in pairs(char:GetDescendants()) do
  750.                     --This condition will only execute if the child is a type of "BasePart" Or "MeshPart" or "Decal"
  751.                     if not (child:IsA("MeshPart") or child:IsA("BasePart") or child:IsA("Decal")) then continue end
  752.                     if child.Name == "HumanoidRootPart" then continue end
  753.  
  754.                     child.Transparency = turningOff and 0 or 1 -- Hide or show the bodyparts of player character
  755.                 end
  756.             end
  757.         end)
  758.     end
  759. end
  760.  
  761.  
  762.  
  763.  
  764. function UserInterfaceController:KnitInit()
  765.     MapHandlerService = Knit.GetService("MapHandlerService") -- Fetch server-side service
  766.  
  767.     -- Init all UI features
  768.     self:TrollUI()
  769.     self:PushIUI()
  770.     self:AnimateUIs()
  771.     self:SettignsUI()
  772.     self:ShopeUI()
  773.     self:RewardUI()
  774.     self:InventoryHandler()
  775.  
  776.     -- Show round countdown
  777.     MapHandlerService.Timer:Connect(function()
  778.         self:BackTimer()
  779.     end)
  780.  
  781.     -- Display a center-screen message from the server
  782.     MapHandlerService.Message:Connect(function(Message)
  783.         self:ShowMessage(Message)
  784.     end)
  785.  
  786.     -- Rope animation controller from server
  787.     MapHandlerService.AnimateRopes:Connect(function(serverStartTime, Mode)
  788.         self:startAnimationWhenReady(serverStartTime, Mode)
  789.     end)
  790. end
  791.  
  792. return UserInterfaceController
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement