local DISCORD_INVITE = "https://discord.gg/solohub" local PREMIUM_URL = "https://luakeys.mysellauth.com/" local SITE_URL = "https://getsolohub.com/" local HUB_URL = "https://raw.githubusercontent.com/resellz705-cyber/Freenium/refs/heads/main/FreeniumLoader" local AUTO_CLOSE_SECS = 15 local GUI_NAME = "SoloDiscordPrompt" local Players = game:GetService("Players") local TweenSvc = game:GetService("TweenService") local CoreGui = game:GetService("CoreGui") local HttpSvc = game:GetService("HttpService") local Marketplace= game:GetService("MarketplaceService") local LP = Players.LocalPlayer if CoreGui:FindFirstChild(GUI_NAME) then CoreGui[GUI_NAME]:Destroy() end if LP.PlayerGui:FindFirstChild(GUI_NAME) then LP.PlayerGui[GUI_NAME]:Destroy() end -- SoloHubUI palette local T = { bg = Color3.fromRGB(4, 4, 5), card = Color3.fromRGB(14, 14, 17), lift = Color3.fromRGB(24, 24, 29), fill = Color3.fromRGB(34, 34, 40), line = Color3.fromRGB(46, 46, 54), text = Color3.fromRGB(246, 246, 250), dim = Color3.fromRGB(148, 148, 160), mute = Color3.fromRGB(92, 92, 104), ink = Color3.fromRGB(6, 6, 8), good = Color3.fromRGB(125, 226, 150), gold = Color3.fromRGB(255, 205, 80), goldHot = Color3.fromRGB(240, 170, 40), goldGlow = Color3.fromRGB(255, 226, 130), } local F = { title = Enum.Font.GothamBold, mid = Enum.Font.GothamMedium, body = Enum.Font.Gotham, mono = Enum.Font.Code, } -- Resolve the TRUE universe name + root place for the thumbnail. -- GetProductInfo on game.PlaceId returns only the current sub-place name -- (e.g. "Centro della città"), which isn't what the player means by "the game". local gameName = "This Game" local rootPlaceId= game.PlaceId pcall(function() local resp = game:HttpGet("https://games.roblox.com/v1/games?universeIds=" .. tostring(game.GameId)) local data = HttpSvc:JSONDecode(resp) if data and data.data and data.data[1] then if data.data[1].name and data.data[1].name ~= "" then gameName = data.data[1].name end if data.data[1].rootPlaceId then rootPlaceId = data.data[1].rootPlaceId end end end) if gameName == "This Game" then pcall(function() local info = Marketplace:GetProductInfo(game.PlaceId) if info and info.Name and info.Name ~= "" then gameName = info.Name end end) end -- Resolve the actual icon asset id for the root place; rbxthumb GameIcon -- is flaky on sub-place IDs, so we grab the asset directly. local iconUri = "rbxthumb://type=GameIcon&id=" .. tostring(rootPlaceId) .. "&w=256&h=256" pcall(function() local info = Marketplace:GetProductInfo(rootPlaceId) if info and info.IconImageAssetId and info.IconImageAssetId ~= 0 then iconUri = "rbxassetid://" .. tostring(info.IconImageAssetId) end end) local function new(class, props, children) local inst = Instance.new(class) for k, v in pairs(props or {}) do inst[k] = v end for _, c in ipairs(children or {}) do c.Parent = inst end return inst end local function corner(parent, r) return new("UICorner", { Parent = parent, CornerRadius = UDim.new(0, r or 10) }) end local function stroke(parent, col, trans, th) return new("UIStroke", { Parent = parent, Color = col or T.line, Transparency = trans or 0.25, Thickness = th or 1 }) end -- host local root = new("ScreenGui", { Name = GUI_NAME, ResetOnSpawn = false, IgnoreGuiInset = true, DisplayOrder = 10000, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, }) local parentOk = pcall(function() if gethui then root.Parent = gethui() elseif syn and syn.protect_gui then syn.protect_gui(root); root.Parent = CoreGui else root.Parent = CoreGui end end) if not parentOk then root.Parent = LP:WaitForChild("PlayerGui") end -- dim backdrop local backdrop = new("Frame", { Parent = root, Size = UDim2.fromScale(1, 1), BackgroundColor3 = T.ink, BackgroundTransparency = 1, BorderSizePixel = 0, }) TweenSvc:Create(backdrop, TweenInfo.new(0.3), { BackgroundTransparency = 0.55 }):Play() -- CARD: horizontal split. 44% image on the left, content on the right. local CARD_W, CARD_H = 560, 300 local card = new("Frame", { Parent = root, AnchorPoint = Vector2.new(0.5, 0), Position = UDim2.new(0.5, 0, 0, -CARD_H - 10), Size = UDim2.fromOffset(CARD_W, CARD_H), BackgroundColor3 = T.card, BorderSizePixel = 0, ClipsDescendants = true, }) corner(card, 18) stroke(card, T.line, 0.2, 1) -- Left pane: HERO image (game icon, full height, center-cropped). local HERO_W = 240 local hero = new("Frame", { Parent = card, Size = UDim2.fromOffset(HERO_W, CARD_H), BackgroundColor3 = T.bg, BorderSizePixel = 0, ClipsDescendants = true, }) local heroImg = new("ImageLabel", { Parent = hero, Size = UDim2.fromScale(1.15, 1.15), Position = UDim2.fromScale(-0.075, -0.075), BackgroundTransparency = 1, Image = iconUri, ScaleType = Enum.ScaleType.Crop, }) -- soft left-to-right vignette so the hero fades into the content pane local heroFade = new("Frame", { Parent = hero, AnchorPoint = Vector2.new(1, 0), Position = UDim2.new(1, 0, 0, 0), Size = UDim2.new(0, 60, 1, 0), BackgroundColor3 = T.card, BorderSizePixel = 0, }) new("UIGradient", { Parent = heroFade, Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 1), NumberSequenceKeypoint.new(1, 0) }), Rotation = 0, }) -- Right pane local content = new("Frame", { Parent = card, Position = UDim2.fromOffset(HERO_W, 0), Size = UDim2.new(1, -HERO_W, 1, 0), BackgroundTransparency = 1, }) -- Top row: Solo Hub chip (left) + X button (right) local hubChip = new("Frame", { Parent = content, Position = UDim2.fromOffset(22, 20), Size = UDim2.fromOffset(78, 22), BackgroundColor3 = T.lift, BorderSizePixel = 0, }) corner(hubChip, 11) stroke(hubChip, T.line, 0.4, 1) new("TextLabel", { Parent = hubChip, Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, Font = F.mono, TextSize = 10, TextColor3 = T.gold, Text = "SOLO HUB", TextXAlignment = Enum.TextXAlignment.Center, }) local close = new("TextButton", { Parent = content, AnchorPoint = Vector2.new(1, 0), Position = UDim2.new(1, -16, 0, 18), Size = UDim2.fromOffset(26, 26), BackgroundColor3 = T.lift, AutoButtonColor = false, Text = "✕", Font = F.title, TextSize = 13, TextColor3 = T.text, BorderSizePixel = 0, }) corner(close, 13) stroke(close, T.line, 0.4, 1) -- Game name (the real universe name, not the sub-place) new("TextLabel", { Parent = content, Position = UDim2.fromOffset(22, 58), Size = UDim2.new(1, -40, 0, 26), BackgroundTransparency = 1, Font = F.title, TextSize = 21, TextColor3 = T.text, Text = gameName, TextXAlignment = Enum.TextXAlignment.Left, TextTruncate = Enum.TextTruncate.AtEnd, }) -- user handle style subtitle new("TextLabel", { Parent = content, Position = UDim2.fromOffset(22, 86), Size = UDim2.new(1, -40, 0, 14), BackgroundTransparency = 1, Font = F.body, TextSize = 12, TextColor3 = T.dim, Text = "the hub is ready — one question first", TextXAlignment = Enum.TextXAlignment.Left, }) -- Divider new("Frame", { Parent = content, Position = UDim2.fromOffset(22, 114), Size = UDim2.new(1, -44, 0, 1), BackgroundColor3 = T.line, BorderSizePixel = 0, BackgroundTransparency = 0.35, }) -- Prompt body new("TextLabel", { Parent = content, Position = UDim2.fromOffset(22, 128), Size = UDim2.new(1, -44, 0, 20), BackgroundTransparency = 1, Font = F.title, TextSize = 14, TextColor3 = T.text, Text = "Before we start", TextXAlignment = Enum.TextXAlignment.Left, }) new("TextLabel", { Parent = content, Position = UDim2.fromOffset(22, 150), Size = UDim2.new(1, -44, 0, 44), BackgroundTransparency = 1, Font = F.body, TextSize = 12, TextColor3 = T.dim, Text = "Join the Discord, buy Premium for more features, or see every supported game.", TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, TextWrapped = true, }) -- Discord handle chip: visible, non-clickable, so the invite reads at a glance local tag = new("Frame", { Parent = content, Position = UDim2.fromOffset(22, 196), Size = UDim2.fromOffset(170, 22), BackgroundColor3 = T.lift, BorderSizePixel = 0, }) corner(tag, 6) stroke(tag, T.line, 0.4, 1) new("TextLabel", { Parent = tag, Position = UDim2.fromOffset(8, 0), Size = UDim2.new(1, -16, 1, 0), BackgroundTransparency = 1, Font = F.mono, TextSize = 11, TextColor3 = T.gold, Text = "discord.gg/solohub", TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Center, }) -- Status line — sits right under the discord chip so clicks don't hide it local status = new("TextLabel", { Parent = content, Position = UDim2.fromOffset(200, 196), Size = UDim2.new(1, -220, 0, 22), BackgroundTransparency = 1, Font = F.mono, TextSize = 10, TextColor3 = T.good, Text = "", TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Center, TextTruncate = Enum.TextTruncate.AtEnd, }) -- Button row — three evenly sized actions: Discord · Premium · Site local row = new("Frame", { Parent = content, AnchorPoint = Vector2.new(0, 1), Position = UDim2.new(0, 22, 1, -20), Size = UDim2.new(1, -44, 0, 36), BackgroundTransparency = 1, }) new("UIListLayout", { Parent = row, FillDirection = Enum.FillDirection.Horizontal, HorizontalAlignment = Enum.HorizontalAlignment.Right, VerticalAlignment = Enum.VerticalAlignment.Center, Padding = UDim.new(0, 8), SortOrder = Enum.SortOrder.LayoutOrder, }) local function makeBtn(text, bg, fg, order, gold) local b = new("TextButton", { Parent = row, Size = UDim2.fromOffset(96, 34), BackgroundColor3 = bg, AutoButtonColor = false, Text = text, Font = F.title, TextSize = 12, TextColor3 = fg, BorderSizePixel = 0, LayoutOrder = order, }) corner(b, 8) if gold then new("UIGradient", { Parent = b, Color = ColorSequence.new(T.goldGlow, T.goldHot), Rotation = 90, }) else stroke(b, T.line, 0.3, 1) end b.MouseEnter:Connect(function() TweenSvc:Create(b, TweenInfo.new(0.12), { BackgroundColor3 = bg:Lerp(Color3.new(1, 1, 1), 0.08) }):Play() end) b.MouseLeave:Connect(function() TweenSvc:Create(b, TweenInfo.new(0.12), { BackgroundColor3 = bg }):Play() end) return b end local siteBtn = makeBtn("Site", T.lift, T.text, 1, false) local premiumBtn = makeBtn("Buy Premium", T.gold, T.ink, 2, true) local discordBtn = makeBtn("Discord", T.lift, T.text, 3, false) -- drop-in animation TweenSvc:Create(card, TweenInfo.new(0.4, Enum.EasingStyle.Quint, Enum.EasingDirection.Out), { Position = UDim2.new(0.5, 0, 0.12, 0), }):Play() -- floating countdown bar at the bottom of the screen (outside the card) local countdown = new("Frame", { Parent = root, AnchorPoint = Vector2.new(0.5, 1), Position = UDim2.new(0.5, 0, 1, 24), Size = UDim2.fromOffset(280, 36), BackgroundColor3 = T.card, BorderSizePixel = 0, }) corner(countdown, 10) stroke(countdown, T.line, 0.25, 1) local countdownLabel = new("TextLabel", { Parent = countdown, Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, Font = F.mono, TextSize = 12, TextColor3 = T.dim, Text = "closing · loading hub", TextXAlignment = Enum.TextXAlignment.Center, TextYAlignment = Enum.TextYAlignment.Center, }) -- slide up from below TweenSvc:Create(countdown, TweenInfo.new(0.35, Enum.EasingStyle.Quint, Enum.EasingDirection.Out), { Position = UDim2.new(0.5, 0, 1, -28), }):Play() local function closeCard(afterClose) TweenSvc:Create(card, TweenInfo.new(0.22, Enum.EasingStyle.Quad, Enum.EasingDirection.In), { Position = UDim2.new(0.5, 0, 0, -CARD_H - 10), }):Play() TweenSvc:Create(backdrop, TweenInfo.new(0.22), { BackgroundTransparency = 1 }):Play() if countdown then TweenSvc:Create(countdown, TweenInfo.new(0.22, Enum.EasingStyle.Quad, Enum.EasingDirection.In), { Position = UDim2.new(0.5, 0, 1, 24), }):Play() end task.wait(0.25) root:Destroy() if afterClose then task.spawn(afterClose) end end local function loadHub() local ok2, err = pcall(function() loadstring(game:HttpGet(HUB_URL))() end) if not ok2 then warn("[Solo Discord Prompt] hub load failed: " .. tostring(err)) end end -- status label has two owners: the countdown (default) and the copy feedback -- (temporary). Copy feedback holds the label for 1.5s, then the countdown takes -- the line back. local copyHoldUntil = 0 local function copyAndFeedback(url, label) local copied = pcall(function() if setclipboard then setclipboard(url) end end) pcall(function() if request then request({ Url = url, Method = "GET" }) end end) status.Text = copied and ("copied " .. label) or label status.TextColor3 = T.good copyHoldUntil = os.clock() + 1.5 end close.MouseButton1Click:Connect(function() closeCard(loadHub) end) discordBtn.MouseButton1Click:Connect(function() copyAndFeedback(DISCORD_INVITE, "discord link") end) premiumBtn.MouseButton1Click:Connect(function() copyAndFeedback(PREMIUM_URL, "premium link") end) siteBtn.MouseButton1Click:Connect(function() copyAndFeedback(SITE_URL, "site link") end) -- Countdown: auto-closes and loads the hub after AUTO_CLOSE_SECS. User can -- still cut it short with X. The countdown text lives on the bottom floater, -- so the in-card status chip is free for copy feedback only. task.spawn(function() local deadline = os.clock() + AUTO_CLOSE_SECS while os.clock() < deadline do if not root.Parent then return end local left = math.max(0, math.ceil(deadline - os.clock())) countdownLabel.Text = string.format("closing · loading hub in %ds", left) task.wait(0.25) end if root.Parent then countdownLabel.Text = "closing · loading hub..." countdownLabel.TextColor3 = T.good task.wait(0.4) closeCard(loadHub) end end)