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")
- -- 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
- 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
- wait(1)
- player.PlayerGui.Timer.TextLabel.Text = "Run!" -- Final message
- task.delay(1.5, function()
- player.PlayerGui.Timer.TextLabel.Visible = false
- end)
- end
- 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
- -- 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()
- 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
- task.delay(1, function()
- Controls:Enable()
- end)
- 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)
- 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
- -- Applies hover/click logic and manages showing/hiding UIs like Shop, Inventory, etc.
- function UserInterfaceController:AnimateUIs()
- local UIButtons = player.PlayerGui.Buttons
- local Debounce = false -- prevents spam clicking
- for i, button in pairs(UIButtons:GetChildren()) do
- if button:IsA("Frame") then
- local Button = button:FindFirstChildOfClass("TextButton") -- Find the clickable button
- if Button then
- 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 Frame.Name ~= "Modes" then
- -- if Normal UIs not Modes then use Frame.Canvas
- local CloseButton:ImageButton = Frame.Canvas.Container.Main.Close
- local Canavs = Frame:FindFirstChild("Canvas")
- -- 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
- self:onClick(button, originalSize)
- Debounce = true
- if Frame then
- if not OpenedUI then -- No UI open yet
- OpenedUI = Canavs --Defines the current open UI
- Canavs.Visible = true
- --Tweens the position of the UI
- 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)
- -- Zoom FOV and apply blur
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 100}):Play()
- TweenService:Create(Blur, tweenInfoUI, {Size = 20}):Play()
- task.delay(0.3, function()
- Debounce = false
- end)
- elseif OpenedUI and OpenedUI ~= Canavs then-- Switching from one UI to another
- Canavs.Visible = true
- OpenedUI:TweenPosition(UDim2.new(0.5, 0, 1.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3)
- OpenedUI = Canavs
- 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)
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 100}):Play()
- TweenService:Create(Blur, tweenInfoUI, {Size = 20}):Play()
- task.delay(0.3, function()
- Debounce = false
- end)
- elseif OpenedUI and 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
- 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()
- task.delay(0.3, function()
- Debounce = false
- end)
- end
- 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
- Canavs:TweenPosition(UDim2.new(0.5, 0, 1.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3)
- -- Reset camera FOV and continblur
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 70}):Play()
- TweenService:Create(Blur, tweenInfoUI, {Size = 0}):Play()
- task.delay(0.3, function()
- Debounce = false
- end)
- end)
- else -- This handles the "Modes" frame specifically
- local CloseButton:ImageButton = Frame.Frame.Close -- Close button in a different hierarchy
- local Canavs = Frame:FindFirstChild("Frame") -- Canvas is named "Frame" here
- -- Hover events
- button.MouseEnter:Connect(function()
- self:onHover(button, originalSize)
- end)
- button.MouseLeave:Connect(function()
- self:onUnhover(button, originalSize)
- end)
- -- Button clicked (toggle Modes UI)
- Button.MouseButton1Click:Connect(function()
- if Debounce then return end
- self:onClick(button, originalSize)
- Debounce = true
- if Frame then
- if not OpenedUI then -- First time opening
- OpenedUI = Canavs
- 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)
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 100}):Play()
- TweenService:Create(Blur, tweenInfoUI, {Size = 20}):Play()
- task.delay(0.3, function()
- Debounce = false
- end)
- elseif OpenedUI and OpenedUI ~= Canavs then -- Switching from another UI to this one
- Canavs.Visible = true
- OpenedUI:TweenPosition(UDim2.new(0.5, 0, 1.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.3)
- OpenedUI = Canavs
- 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)
- TweenService:Create(camera, tweenInfoUI, {FieldOfView = 100}):Play()
- TweenService:Create(Blur, tweenInfoUI, {Size = 20}):Play()
- task.delay(0.3, function()
- Debounce = false
- end)
- elseif OpenedUI and OpenedUI == Canavs then -- Close Modes UI
- Debounce = true
- OpenedUI = nil
- 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()
- task.delay(0.3, function()
- Debounce = false
- end)
- end
- end
- end)
- --Handles closeButton functionality
- CloseButton.MouseButton1Click:Connect(function()
- if Debounce then return end
- Debounce = true
- OpenedUI = nil
- 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()
- task.delay(0.3, function()
- Debounce = false
- end)
- end)
- end
- end
- end
- end
- end
- --Handles working of troll UI
- function UserInterfaceController:TrollUI()
- local UIStroke
- -- Loop through each troll button (ImageButton inside Main Container)
- for i, trolls in pairs(TrollUI.Canvas.Container.Main.Container:GetChildren()) do
- if trolls:IsA("ImageButton") then
- trolls.MouseEnter:Connect(function() -- When hovered, add purple UIStroke around "Default" image
- print("Entered")
- if not UIStroke then
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = trolls:FindFirstChild("Default")
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = trolls:FindFirstChild("Default")
- end
- end)
- -- Remove stroke on mouse leave
- trolls.MouseLeave:Connect(function()
- UIStroke.Parent = nil
- 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
- if ClickedTrollName == "EliminatePlayers" then
- MPS:PromptProductPurchase(player, Products.EliminatePlayers)
- elseif ClickedTrollName == "SpeedTroll" then
- MPS:PromptProductPurchase(player, Products.SpeedTroll)
- elseif ClickedTrollName == "KillRandomPersonTroll" then
- MPS:PromptProductPurchase(player, Products.KillRandomPersonTroll)
- elseif ClickedTrollName == "TakeCoinsTroll" then
- MPS:PromptProductPurchase(player, Products.TakeCoinsTroll)
- end
- end)
- end
- end
- end
- function UserInterfaceController:PushIUI()
- local UIStroke
- -- Loop through each push product (Push1, Push2, etc.)
- for i, trolls in pairs(PushUI.Canvas.Container.Main.Container:GetChildren()) do
- if trolls:IsA("ImageButton") then
- trolls.MouseEnter:Connect(function()-- Same hover stroke logic as TrollUI
- print("Entered")
- if not UIStroke then
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = trolls:FindFirstChild("Default")
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = trolls:FindFirstChild("Default")
- end
- end)
- trolls.MouseLeave:Connect(function()
- UIStroke.Parent = nil
- end)
- -- Find Buy button
- local BuyButton:ImageButton = trolls.Equipped:FindFirstChild("Buy") or trolls.Default:FindFirstChild("Buy")
- -- Trigger MarketplaceService purchase when clickedcont
- BuyButton.MouseButton1Click:Connect(function()
- local ClickedButtonName = BuyButton.Parent.Parent.Name
- if 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)
- end
- end
- end
- local ClonedPopupUI
- function UserInterfaceController:ShopeUI()
- local UIStroke
- local NavigationList = ShopUI.Canvas.Container.Navigation.List
- local PopupUI = player.PlayerGui.Popup -- Refrence to popup UI
- 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
- NavigationList.Gamepass.MouseButton1Click:Connect(function()
- if Container2.Visible == true or Container3.Visible == true then
- Container2.Visible = false -- Hide other tabs
- Container3.Visible = false
- Container1.Visible = true -- Show gamepasses Tab
- -- Change looking style of tab buttons
- GamepassButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255) --Change background color to white so UI gradient get clearly visible
- GamepassButton:FindFirstChild("UIGradient").Enabled = true --Enable UI gradient
- GamepassButton.Text.TextColor3 = Color3.new(255, 255, 255) --Change text color to white too
- DeveloperProductsButton.BackgroundColor3 = Color3.fromRGB(31, 31, 31)--Change background color to black
- DeveloperProductsButton:FindFirstChild("UIGradient").Enabled = false--Disble UI gradient
- DeveloperProductsButton.Text.TextColor3 = Color3.new(113, 113, 113)--Change text color to white
- StoreButton.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Change background color to black
- StoreButton:FindFirstChild("UIGradient").Enabled = false --Disble UI gradient
- StoreButton.Text.TextColor3 = Color3.new(113, 113, 113) --Change text color to white
- end
- end)
- --Developer Products tab Button logic
- NavigationList.DeveloperProducts.MouseButton1Click:Connect(function()
- if Container1.Visible == true or Container3.Visible == true then
- Container2.Visible = true
- Container3.Visible = false
- Container1.Visible = false
- DeveloperProductsButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255)--Change background color to white so UI gradient get clearly visible
- DeveloperProductsButton:FindFirstChild("UIGradient").Enabled = true--Enable UI gradient
- DeveloperProductsButton.Text.TextColor3 = Color3.new(255, 255, 255) --Change text color to white too
- GamepassButton.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Change background color to black
- GamepassButton:FindFirstChild("UIGradient").Enabled = false --Disble UI gradient
- GamepassButton.Text.TextColor3 = Color3.new(113, 113, 113) --Change text color to white
- StoreButton.BackgroundColor3 = Color3.fromRGB(31, 31, 31)--Change background color to black
- StoreButton:FindFirstChild("UIGradient").Enabled = false --Disble UI gradient
- StoreButton.Text.TextColor3 = Color3.new(113, 113, 113) --Change text color to white
- end
- end)
- -- Store tab button logic
- NavigationList.Store.MouseButton1Click:Connect(function()
- if Container1.Visible == true or Container2.Visible == true then
- Container3.Visible = true
- Container1.Visible = false
- Container2.Visible = false
- StoreButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255)--Change background color to white so UI gradient get clearly visible
- StoreButton:FindFirstChild("UIGradient").Enabled = true --Enable UI gradient
- StoreButton.Text.TextColor3 = Color3.new(255, 255, 255) --Change text color to white too
- GamepassButton.BackgroundColor3 = Color3.fromRGB(31, 31, 31) --Change background color to black
- GamepassButton:FindFirstChild("UIGradient").Enabled = false--Disble UI gradient
- GamepassButton.Text.TextColor3 = Color3.new(113, 113, 113)--Change text color to white
- DeveloperProductsButton.BackgroundColor3 = Color3.fromRGB(31, 31, 31)--Change background color to black
- DeveloperProductsButton:FindFirstChild("UIGradient").Enabled = false--Disble UI gradient
- DeveloperProductsButton.Text.TextColor3 = Color3.new(113, 113, 113)--Change text color to white
- end
- end)
- -- Loop through items in Container1 (Gamepasses)
- for i, Gamepass in pairs(Container1:GetChildren()) do
- if Gamepass:IsA("ImageButton") then
- -- Hover effect
- Gamepass.MouseEnter:Connect(function()
- if not UIStroke then
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = Gamepass:FindFirstChild("Default")
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = Gamepass:FindFirstChild("Default")
- end
- end)
- Gamepass.MouseLeave:Connect(function()
- UIStroke.Parent = nil
- end)
- -- Giving refrence to buy button
- local BuyButton:ImageButton = Gamepass.Equipped:FindFirstChild("Buy") or Gamepass.Default:FindFirstChild("Buy")
- -- Handle Gamepass purchase via MarketplaceService after clicking buy button
- BuyButton.MouseButton1Click:Connect(function()
- local ClickedButtonName = BuyButton.Parent.Parent.Name
- if ClickedButtonName == "Coins2x" then
- MPS:PromptGamePassPurchase(player, 1272744022)
- elseif ClickedButtonName == "Sprint" then
- MPS:PromptGamePassPurchase(player, 1273130340)
- elseif ClickedButtonName == "RainbowNameTag" then
- MPS:PromptGamePassPurchase(player, 1274510513)
- end
- end)
- end
- end
- for i, Gamepass in pairs(Container2:GetChildren()) do
- if Gamepass:IsA("ImageButton") then
- Gamepass.MouseEnter:Connect(function()
- -- Same UIStroke hover logic
- if not UIStroke then
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = Gamepass:FindFirstChild("Default")
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = Gamepass:FindFirstChild("Default")
- end
- end)
- Gamepass.MouseLeave:Connect(function()
- UIStroke.Parent = nil
- end)
- local BuyButton:ImageButton = Gamepass.Equipped:FindFirstChild("Buy") or Gamepass.Default:FindFirstChild("Buy")
- -- Trigger product purchases
- BuyButton.MouseButton1Click:Connect(function()
- local ClickedButtonName = BuyButton.Parent.Parent.Name
- if ClickedButtonName == "Coins50" then
- MPS:PromptProductPurchase(player, 3314212399)
- elseif ClickedButtonName == "Coins100" then
- MPS:PromptProductPurchase(player, 3314212620)
- elseif ClickedButtonName == "Coins300" then
- MPS:PromptProductPurchase(player, 3314213085)
- elseif ClickedButtonName == "Coins500" then
- MPS:PromptProductPurchase(player, 3314213295)
- elseif ClickedButtonName == "Coins1000" then
- MPS:PromptProductPurchase(player, 3314214142)
- end
- end)
- end
- end
- for i, Gamepass in pairs(Container3:GetChildren()) do
- if Gamepass:IsA("ImageButton") then
- Gamepass.MouseEnter:Connect(function()
- -- Hover stroke (same as above)
- if not UIStroke then
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = Gamepass:FindFirstChild("Default")
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = Gamepass:FindFirstChild("Default")
- end
- end)
- Gamepass.MouseLeave:Connect(function()
- UIStroke.Parent = nil
- end)
- -- Button purchase logic
- local BuyButton:ImageButton = Gamepass.Equipped:FindFirstChild("Buy") or Gamepass.Default:FindFirstChild("Buy")
- BuyButton.MouseButton1Click:Connect(function()
- -- Clone and display popup
- ClonedPopupUI = PopupUI:Clone()
- ClonedPopupUI.Parent = player.PlayerGui
- ClonedPopupUI.Canvas.Visible = true
- -- open ColourWheel if buy button is of NameTags template
- if BuyButton.Parent.Parent.Name == "NameTags" then
- player.PlayerGui.ColourWheelGui.Enabled = true
- end
- -- Handle purchase proccess if player has enough coins
- ClonedPopupUI.Canvas.Main.YesButton.MouseButton1Click:Connect(function()
- local PlayerCoins = player:FindFirstChild("leaderstats"):WaitForChild("Coins")
- if PlayerCoins and PlayerCoins.Value >= BuyButton.Cost.Value then
- PlayerCoins.Value -= BuyButton.Cost.Value
- -- Handle NameTags (with color)
- if BuyButton.Parent.Parent.Name == "NameTags" then
- local NameTag = ReplicatedStorage.Assets:FindFirstChild("nametagui"):Clone()
- MapHandlerService:GiveNameTags(player.PlayerGui.ColourWheelGui.ColourDisplay.BackgroundColor3)
- player.PlayerGui.ColourWheelGui.Enabled = false
- ClonedPopupUI:Destroy()
- else
- -- Add cloned template to Inventory
- local CloneTemplate = BuyButton.Parent.Parent:Clone()
- CloneTemplate.Parent = InventoryUI.Canvas.Container.Main.Container
- CloneTemplate.Default.Buy:Destroy()
- ClonedPopupUI:Destroy()
- end
- else
- -- Not enough coins message
- ClonedPopupUI.Canvas.Main.YesButton.Main.TextLabel.Text = "Not Enough Coins!"
- task.delay(2, function()
- ClonedPopupUI.Canvas.Main.YesButton.Main.TextLabel.Text = "Buy"
- end)
- end
- end)
- -- Popup close logic (X button or "Close")
- ClonedPopupUI.Canvas.Main.Closebutton.MouseButton1Click:Connect(function()
- ClonedPopupUI:Destroy()
- end)
- ClonedPopupUI.Canvas.Main.Close.MouseButton1Click:Connect(function()
- ClonedPopupUI:Destroy()
- end)
- -- gives player option to buy with robux if player don't have enough coins
- ClonedPopupUI.Canvas.Main.BuyWithRobux.MouseButton1Click:Connect(function()
- local itemName = BuyButton.Parent.Parent.Name
- if itemName == "ExtraLifes" then
- MPS:PromptProductPurchase(player, 3314996213)
- elseif itemName == "LessGravity" then
- MPS:PromptProductPurchase(player, 3314996574)
- elseif itemName == "NameTags" then
- MPS:PromptProductPurchase(player, 3314996930)
- end
- end)
- end)
- end
- end
- 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 -- 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()
- if SidePanel.ItemName.Text == "ExtraLifes" then
- MapHandlerService:ExtraLifes() --Calls "ExtraLifes" function
- 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)
- -- When new item added to inventory
- Container.ChildAdded:Connect(function(child:ImageButton)
- child.MouseButton1Click:Connect(function()
- if not SelectedChild or SelectedChild ~= child then
- 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
- 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:RewardUI()
- local UIStroke
- local StartTime = tick() --returns the number of seconds since January 1st, 1970 UTC, useful for time elapsed calculations
- -- Update timer every second
- spawn(function()
- while wait(1) do
- for i, rewards in pairs(RewardUI.Canvas.Container.Main.Container:GetChildren()) do
- if rewards:IsA("ImageButton") then
- if rewards.Equipped.TextLabel.Text == "Unlock in: 00:00" then continue end
- 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
- rewards.Equipped.Buy.Backing.Text.Text = "Equip" --if timer is reached 0 sec it changes rewards button text to equip
- end
- end
- end
- end
- end)
- --loop through all the rewards available in reward UI container/scrolling Frame
- for i, Rewards in pairs(RewardUI.Canvas.Container.Main.Container:GetChildren()) do
- if Rewards:IsA("ImageButton") then
- Rewards.MouseEnter:Connect(function()
- --same UIStroke logic
- if not UIStroke then
- UIStroke = Instance.new("UIStroke")
- UIStroke.Parent = Rewards:FindFirstChild("Default")
- UIStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
- UIStroke.Color = Color3.fromRGB(126, 36, 233)
- UIStroke.Thickness = 2
- else
- UIStroke.Parent = Rewards:FindFirstChild("Default")
- end
- end)
- --remove UIStroke after player leaves the button
- Rewards.MouseLeave:Connect(function()
- UIStroke.Parent = nil
- end)
- --refrence to buy button
- local EquipButton:ImageButton = Rewards.Equipped:FindFirstChild("Buy") or Rewards.Default:FindFirstChild("Buy")
- 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()
- if EquipButton.Backing.Text.Text == "Locked yet!" then return end --if item is currently lock then stop execution of event immediately
- if EquipButton.Backing.Text.Text == "Unequip" then --if player has already equipped item then unEquip it
- local Success, errorMessage = MapHandlerService:WearBrainRot(Rewards:FindFirstChild("AssetId").Value, Rewards)
- if Success then
- EquipButton.Backing.Text.Text = "Equip"
- end
- else --if player has not equipped item then equip it
- local Success, errorMessage = MapHandlerService:WearBrainRot(Rewards:FindFirstChild("AssetId").Value, "Wear", Rewards)
- if Success then
- EquipButton.Backing.Text.Text = "Unequip"
- end
- end
- end)
- end
- end
- end
- --handles logics of setting UI
- function UserInterfaceController:SettignsUI()
- for i, Settings in pairs(SettingsUI.Canvas.Container.Main.Container:GetChildren()) do
- if Settings:IsA("ImageLabel") then
- local ToggleButton = Settings:FindFirstChild("ToggleButton")
- if ToggleButton then
- --Event which runs upon toggle button is clicked using left mouse button
- ToggleButton.MouseButton1Click:Connect(function()
- -- Determine toggle state
- local turningOff = Settings.Background.Toggle.ActiveFrame.Visible == true
- Settings.Background.Toggle.ActiveFrame.Visible = not turningOff
- Settings.Background.Toggle.InactiveFrame.Visible = 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 return end
- for _, child in pairs(char:GetDescendants()) do
- if child:IsA("MeshPart") or child:IsA("BasePart") or child:IsA("Decal") then --This condition will only execute if the child is a type of "BasePart" Or "MeshPart" or "Decal"
- if child.Name == "HumanoidRootPart" then continue end
- child.Transparency = turningOff and 0 or 1 -- Hide or show
- end
- end
- end
- end)
- end
- 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)
- --blocks player from returning back into the track after he has ended the round
- MapHandlerService.BlockGoingBack:Connect(function(mode)
- if mode == "Easy" then
- workspace.Maps.EasyRopemap:WaitForChild("FinishPoint").CanCollide = true
- else
- workspace.Maps.HadRopeMap:WaitForChild("FinishPoint").CanCollide = true
- end
- end)
- MapHandlerService.UpdateRewardStatus:Connect(function(RewardTemplate)
- for i, reward in pairs(player.PlayerGui.Reward.Canvas.Container.Main.Container:GetChildren()) do
- if reward:IsA("ImageButton") then
- -- Don’t change text if equip button text is "Locked yet!"
- if reward.Equipped.Buy.Backing.Text.Text == "Locked yet!" then continue end
- -- Deselect all others if the same asset type is equipped/it changes text back to equip if the same asset type has text "Unequip"
- if reward:FindFirstChild("AssetType").Value == "Hat" and reward ~= RewardTemplate then
- reward.Equipped.Buy.Backing.Text.Text = "Equip"
- end
- end
- end
- end)
- --calls the server function for adding nametags to player head so it is visible to everyone
- MapHandlerService.NameTag:Connect(function()
- if ClonedPopupUI then
- ClonedPopupUI:Destroy()
- end
- player.PlayerGui.ColourWheelGui.Enabled = false
- MapHandlerService:GiveNameTags(player.PlayerGui.ColourWheelGui.ColourDisplay.BackgroundColor3)
- end)
- --Handles music playing/stopping with tween/amimation
- MapHandlerService.MusicEvent:Connect(function(argument)
- if argument == "Play" then
- player.PlayerGui.Buttons.ModesButton.Visible = true
- BackgroundMusic:Play()
- BackgroundMusic.Volume = 0
- TweenService:Create(BackgroundMusic, tweenInfoForMusic, {Volume = 0.25}):Play()
- elseif argument == "Stop" then
- player.PlayerGui.Buttons.ModesButton.Visible = false
- OpenedUI = nil
- player.PlayerGui.Modes.Frame: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()
- TweenService:Create(BackgroundMusic, tweenInfoForMusic, {Volume = 0}):Play()
- -- Stop after fade-out
- task.delay(1.5, function()
- wait(1.5)
- BackgroundMusic:Stop()
- end)
- end
- end)
- -- Handles squid game music playing/stopping with the round start/ends
- MapHandlerService.SquidMusic:Connect(function(argument)
- if argument == "Play" then
- SquidMusic:Play()
- SquidMusic.Volume = 0
- TweenService:Create(SquidMusic, tweenInfoForMusic, {Volume = 0.25}):Play()
- elseif argument == "Stop" then
- TweenService:Create(SquidMusic, tweenInfoForMusic, {Volume = 0}):Play()
- task.delay(1.5, function()
- wait(1.5)
- SquidMusic:Stop()
- end)
- end
- end)
- MapHandlerService.RoundEnd:Connect(function(mode)
- if RopeAnimationConnection then
- RopeAnimationConnection:Disconnect()
- Rope:PivotTo(initialCFrame)
- if mode == "Easy" then --change the easy/hard map finish point's CanCollide property to false depending on mode
- workspace.Maps.EasyRopemap:WaitForChild("FinishPoint").CanCollide = false
- else
- workspace.Maps.HadRopeMap:WaitForChild("FinishPoint").CanCollide = false
- end
- workspace.Gravity = 196.2 -- Restore normal gravity for those who have bought "LessGravity" Developer product
- end
- end)
- end
- return UserInterfaceController
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement