-- WOLF HUB STAGE-0 v1.4.04 / GLOBAL RE-EXECUTE + BOUND CONTEXT COMPAT + KEY SYSTEM UI -- WOLF_DYNAMIC_ERROR_UI_V2 -- Public launcher only. This file contains no protected Loader/menu source and no server secret. -- It validates the local WolfHub license/device, obtains a 20-second one-time ticket, -- retrieves the full Loader over the same executor HTTP/TLS transport, compiles it, and releases the source string. local API = "https://wolfhub-api.lol2k12.workers.dev" local RELEASE_CHANNEL = "production" local LOADER_VERSION = "7" local SECURITY_VERSION = "6.5" local EXECUTOR_GATE_VERSION = "2" local DEVICE_FOLDER = "WolfHub" local DEVICE_FILE = "WolfHub/device_id.txt" local KEY_FILE = "WolfHub/WolfHub_Key.txt" local LEGACY_KEY_FILES = { "WolfHub/WolfHub_Key", "WolfHub/license.txt", "WolfHub_Key.txt", "WolfHub_Key", } local HttpService = game:GetService("HttpService") local Players = game:GetService("Players") local LP = Players.LocalPlayer local UIS = game:GetService("UserInputService") local IS_TOUCH_DEVICE = UIS.TouchEnabled == true local ENV = (typeof(getgenv) == "function" and getgenv()) or _G local WOLF_WARN_SHIELD_KEY = "WOLF_LOADER_WARN_SHIELD_V1" do local shield = rawget(ENV, WOLF_WARN_SHIELD_KEY) if type(shield) ~= "table" or type(shield.wrapper) ~= "function" or type(shield.native) ~= "function" then local nativeWarn = warn shield = { native = nativeWarn, wrapper = nil, suppressed = 0, last = "" } local function wrapper(...) local count = select("#", ...) local parts = {} for i = 1, count do parts[i] = tostring(select(i, ...)) end local message = table.concat(parts, " ") -- Legacy Loader builds emitted their own [WOLF HUB] warning from -- LogService.MessageOut. On RE-EXECUTE those orphan listeners can -- call themselves recursively. Keep WolfHub errors in the in-game -- error UI/trace and never feed them back into LogService. if message:find("[WOLF HUB]", 1, true) then shield.suppressed = (tonumber(shield.suppressed) or 0) + 1 shield.last = message return end return nativeWarn(...) end shield.wrapper = wrapper rawset(ENV, WOLF_WARN_SHIELD_KEY, shield) end pcall(function() rawset(ENV, "warn", shield.wrapper) end) pcall(function() if type(_G) == "table" then rawset(_G, "warn", shield.wrapper) end end) -- Remove stale WolfHub error surfaces left by an older Execute. The new -- run will recreate a single error UI only if a real current-run failure occurs. pcall(function() local parents = {} if typeof(gethui) == "function" then local ok, hui = pcall(gethui) if ok and hui then parents[#parents + 1] = hui end end local okCore, core = pcall(function() return game:GetService("CoreGui") end) if okCore and core then parents[#parents + 1] = core end local okPlayers, players = pcall(function() return game:GetService("Players") end) local localPlayer = okPlayers and players and players.LocalPlayer or nil local playerGui = localPlayer and localPlayer:FindFirstChildOfClass("PlayerGui") or nil if playerGui then parents[#parents + 1] = playerGui end local names = { "WOLF_HUB_DYNAMIC_ERROR", "WOLF_HUB_MENU_ERROR", "WOLF_HUB_STAGE0_ERROR", "WOLF_HUB_STARTUP_ERROR", } for _, parent in ipairs(parents) do for _, name in ipairs(names) do local stale = parent:FindFirstChild(name, true) if stale then pcall(function() stale:Destroy() end) end end end end) end -- WOLF_DYNAMIC_ERROR_UI_V2 -- WolfHub fixed compact error surface. Only the visual error-window implementation is changed. local WOLF_ERROR_IMAGE_ID = "rbxassetid://95674357937819" local WOLF_ERROR_ENTRIES = WOLF_ERROR_ENTRIES or {} local WOLF_ERROR_GUI = nil local WOLF_ERROR_CARD = nil local WOLF_ERROR_SCROLL = nil local WOLF_ERROR_TEXT = nil local WOLF_ERROR_COPY = nil local WOLF_ERROR_SCALE = nil local WOLF_ERROR_VIEWPORT_CONNECTION = nil local function wolfErrorGuiParent() local parent = nil pcall(function() if typeof(gethui) == "function" then local value = gethui() if value then parent = value end end end) if not parent then pcall(function() parent = game:GetService("CoreGui") end) end if not parent and LP then pcall(function() parent = LP:FindFirstChildOfClass("PlayerGui") or LP:WaitForChild("PlayerGui", 5) end) end return parent end local function wolfCopyAllErrors(value) local text = tostring(value or "") if text == "" then return false end local candidates = {} local function add(fn) if typeof(fn) == "function" then candidates[#candidates + 1] = fn end end pcall(function() add(setclipboard) end) pcall(function() add(toclipboard) end) pcall(function() if typeof(getgenv) == "function" then local env = getgenv() if type(env) == "table" then add(rawget(env, "setclipboard")) add(rawget(env, "toclipboard")) add(rawget(env, "set_clipboard")) end end end) for _, fn in ipairs(candidates) do local ok = pcall(fn, text) if ok then return true end end return false end local function wolfBuildErrorText() if #WOLF_ERROR_ENTRIES <= 1 then return tostring(WOLF_ERROR_ENTRIES[1] or "Unknown WolfHub error") end local out = {} for index, entry in ipairs(WOLF_ERROR_ENTRIES) do out[#out + 1] = string.format("ERROR %02d\n%s", index, tostring(entry)) end return table.concat(out, "\n\n") end local function wolfDestroyErrorUi() if WOLF_ERROR_VIEWPORT_CONNECTION then pcall(function() WOLF_ERROR_VIEWPORT_CONNECTION:Disconnect() end) WOLF_ERROR_VIEWPORT_CONNECTION = nil end if WOLF_ERROR_GUI then pcall(function() WOLF_ERROR_GUI:Destroy() end) end WOLF_ERROR_GUI = nil WOLF_ERROR_CARD = nil WOLF_ERROR_SCROLL = nil WOLF_ERROR_TEXT = nil WOLF_ERROR_COPY = nil WOLF_ERROR_SCALE = nil end local function wolfEnsureDynamicErrorUi() if WOLF_ERROR_GUI and WOLF_ERROR_GUI.Parent and WOLF_ERROR_CARD and WOLF_ERROR_CARD.Parent then return true end wolfDestroyErrorUi() local parent = wolfErrorGuiParent() if not parent then return false end for _, oldName in ipairs({ "WOLF_HUB_DYNAMIC_ERROR", "WOLF_HUB_STAGE0_ERROR", "WOLF_HUB_STARTUP_ERROR", }) do pcall(function() local old = parent:FindFirstChild(oldName) if old then old:Destroy() end end) end local gui = Instance.new("ScreenGui") gui.Name = "WOLF_HUB_DYNAMIC_ERROR" gui.ResetOnSpawn = false gui.IgnoreGuiInset = false gui.ZIndexBehavior = Enum.ZIndexBehavior.Global gui.DisplayOrder = 2147483646 gui.Parent = parent local card = Instance.new("ImageLabel") card.Name = "ErrorCard" card.AnchorPoint = Vector2.new(0.5, 0.5) card.Position = UDim2.fromScale(0.5, 0.5) card.Size = UDim2.fromOffset(860, 319) card.BackgroundTransparency = 1 card.BorderSizePixel = 0 card.Image = WOLF_ERROR_IMAGE_ID card.ScaleType = Enum.ScaleType.Stretch card.ClipsDescendants = true card.Active = true card.Draggable = true card.ZIndex = 100 card.Parent = gui -- Exact marked error area in the 2048x760 artwork: -- X 84..1963, Y 266..503. local scroll = Instance.new("ScrollingFrame") scroll.Name = "ErrorScroll" scroll.BackgroundTransparency = 1 scroll.BorderSizePixel = 0 scroll.Position = UDim2.fromScale(84 / 2048, 266 / 760) scroll.Size = UDim2.fromScale(1880 / 2048, 238 / 760) scroll.CanvasSize = UDim2.fromOffset(0, 0) scroll.ScrollBarThickness = 5 scroll.ScrollBarImageColor3 = Color3.fromRGB(0, 210, 255) scroll.ScrollingDirection = Enum.ScrollingDirection.Y scroll.ZIndex = 103 scroll.Parent = card local body = Instance.new("TextLabel") body.Name = "ErrorText" body.BackgroundTransparency = 1 body.Position = UDim2.fromOffset(10, 6) body.Size = UDim2.new(1, -24, 0, 40) body.Text = "" body.TextColor3 = Color3.fromRGB(238, 244, 255) body.TextSize = IS_TOUCH_DEVICE and 13 or 15 body.Font = Enum.Font.Code body.TextWrapped = true body.TextXAlignment = Enum.TextXAlignment.Left body.TextYAlignment = Enum.TextYAlignment.Top body.ZIndex = 104 body.Parent = scroll -- Exact marked button area in the 2048x760 artwork: -- X 1646..1929, Y 627..666. local copy = Instance.new("TextButton") copy.Name = "CopyAll" copy.Position = UDim2.fromScale(1646 / 2048, 627 / 760) copy.Size = UDim2.fromScale(284 / 2048, 40 / 760) copy.BackgroundTransparency = 1 copy.BorderSizePixel = 0 copy.Text = "COPY" copy.TextColor3 = Color3.fromRGB(238, 247, 255) copy.TextSize = 13 copy.Font = Enum.Font.GothamBold copy.AutoButtonColor = true copy.ZIndex = 105 copy.Parent = card -- Compact close control, kept inside the top-right frame. local close = Instance.new("TextButton") close.Name = "CloseError" close.AnchorPoint = Vector2.new(1, 0) close.Position = UDim2.fromScale(0.974, 0.055) close.Size = UDim2.fromScale(0.042, 0.09) close.BackgroundColor3 = Color3.fromRGB(6, 15, 32) close.BackgroundTransparency = 0.12 close.BorderSizePixel = 0 close.Text = "X" close.TextColor3 = Color3.fromRGB(255, 238, 247) close.TextSize = IS_TOUCH_DEVICE and 13 or 15 close.Font = Enum.Font.GothamBold close.AutoButtonColor = true close.ZIndex = 106 close.Parent = card local closeCorner = Instance.new("UICorner") closeCorner.CornerRadius = UDim.new(0, 7) closeCorner.Parent = close local closeStroke = Instance.new("UIStroke") closeStroke.Thickness = 1.4 closeStroke.Color = Color3.fromRGB(255, 48, 133) closeStroke.Transparency = 0.04 closeStroke.Parent = close copy.Activated:Connect(function() local copied = wolfCopyAllErrors(wolfBuildErrorText()) copy.Text = copied and "COPIED!" or "NO CLIPBOARD" task.delay(1.35, function() if copy.Parent then copy.Text = "COPY" end end) end) close.Activated:Connect(function() wolfDestroyErrorUi() end) WOLF_ERROR_GUI = gui WOLF_ERROR_CARD = card WOLF_ERROR_SCROLL = scroll WOLF_ERROR_TEXT = body WOLF_ERROR_COPY = copy return true end local function wolfRefreshDynamicErrorUi() if not wolfEnsureDynamicErrorUi() then return end local text = wolfBuildErrorText() WOLF_ERROR_TEXT.Text = text local camera = workspace.CurrentCamera local viewport = camera and camera.ViewportSize or Vector2.new(1280, 720) local width if IS_TOUCH_DEVICE then width = math.min( viewport.X - 12, math.max(320, math.floor(viewport.X * 0.92)) ) else width = math.min( 880, viewport.X - 42, math.max(600, math.floor(viewport.X * 0.52)) ) end local maxHeight = math.max( 190, math.floor(viewport.Y * (IS_TOUCH_DEVICE and 0.82 or 0.58)) ) local targetHeight = math.floor(width / (2048 / 760) + 0.5) if targetHeight > maxHeight then targetHeight = maxHeight width = math.floor(targetHeight * (2048 / 760) + 0.5) end local textWidth = math.max( 180, math.floor(width * (1880 / 2048)) - 30 ) local bounds = Vector2.new(textWidth, 40) pcall(function() bounds = game:GetService("TextService"):GetTextSize( text, WOLF_ERROR_TEXT.TextSize, WOLF_ERROR_TEXT.Font, Vector2.new(textWidth, 100000) ) end) local bodyHeight = math.max(38, math.ceil(bounds.Y) + 10) WOLF_ERROR_CARD.Size = UDim2.fromOffset(width, targetHeight) WOLF_ERROR_SCROLL.Position = UDim2.fromScale(84 / 2048, 266 / 760) WOLF_ERROR_SCROLL.Size = UDim2.fromScale(1880 / 2048, 238 / 760) WOLF_ERROR_TEXT.Size = UDim2.new(1, -24, 0, bodyHeight) WOLF_ERROR_SCROLL.CanvasSize = UDim2.fromOffset(0, bodyHeight + 8) WOLF_ERROR_COPY.TextSize = math.clamp( math.floor(width * 24 / 2048 + 0.5), 11, 15 ) if camera and not WOLF_ERROR_VIEWPORT_CONNECTION then WOLF_ERROR_VIEWPORT_CONNECTION = camera:GetPropertyChangedSignal("ViewportSize"):Connect(function() task.defer(wolfRefreshDynamicErrorUi) end) end end local function wolfPushDynamicError(message) local text = tostring(message or "Unknown WolfHub error") text = text:gsub("^%s+", ""):gsub("%s+$", "") if text == "" then text = "Unknown WolfHub error" end if WOLF_ERROR_ENTRIES[#WOLF_ERROR_ENTRIES] ~= text then WOLF_ERROR_ENTRIES[#WOLF_ERROR_ENTRIES + 1] = text while #WOLF_ERROR_ENTRIES > 40 do table.remove(WOLF_ERROR_ENTRIES, 1) end end warn("[WOLF HUB] " .. text) pcall(wolfRefreshDynamicErrorUi) end local function showStage0Error(message) wolfPushDynamicError(message) end local function stage0Fail(message) showStage0Error(message) return nil end local function requestFunction() if typeof(request) == "function" then return request end if typeof(http_request) == "function" then return http_request end if type(syn) == "table" and typeof(syn.request) == "function" then return syn.request end return nil end local REQUEST = requestFunction() if not REQUEST then stage0Fail("Executor does not support HTTP requests with headers.") return end local function normalizeKey(value) return tostring(value or "") :gsub("[%z\1-\31\127]", "") :gsub("%s+", "") :upper() end local function plausibleKey(value) local key = normalizeKey(value) return key ~= "" and #key >= 12 and #key <= 160 and key:sub(1, 3) == "WH-" end local function ensureFolder() if typeof(makefolder) ~= "function" then return end pcall(function() if typeof(isfolder) ~= "function" or not isfolder(DEVICE_FOLDER) then makefolder(DEVICE_FOLDER) end end) end local function readFile(path) if typeof(isfile) ~= "function" or typeof(readfile) ~= "function" then return "" end local okExists, exists = pcall(isfile, path) if not okExists or not exists then return "" end local okRead, value = pcall(readfile, path) return okRead and type(value) == "string" and value or "" end local function writeFile(path, value) if typeof(writefile) ~= "function" then return false end ensureFolder() return pcall(writefile, path, tostring(value or "")) end local function deleteKeyFiles() if typeof(delfile) ~= "function" or typeof(isfile) ~= "function" then return end local paths = { KEY_FILE, table.unpack(LEGACY_KEY_FILES) } for _, path in ipairs(paths) do pcall(function() if isfile(path) then delfile(path) end end) end end local function loadDeviceId() ensureFolder() local stored = readFile(DEVICE_FILE):gsub("%s+", "") if #stored >= 12 and #stored <= 128 then return stored end local id = "WDEV-" .. HttpService:GenerateGUID(false):gsub("%-", "") .. HttpService:GenerateGUID(false):gsub("%-", "") writeFile(DEVICE_FILE, id) return id end local function setSharedKey(key) key = normalizeKey(key) pcall(function() ENV.script_key = key end) pcall(function() _G.script_key = key end) pcall(function() script_key = key end) end local function findInitialKey() local candidates = {} pcall(function() table.insert(candidates, script_key) end) pcall(function() table.insert(candidates, ENV.script_key) end) pcall(function() table.insert(candidates, _G.script_key) end) table.insert(candidates, readFile(KEY_FILE)) for _, path in ipairs(LEGACY_KEY_FILES) do table.insert(candidates, readFile(path)) end for _, value in ipairs(candidates) do if plausibleKey(value) then return normalizeKey(value) end end return "" end local function getGuiParent() return LP:WaitForChild("PlayerGui") end local function licensePromptMessage(reason, detail) local primary = tostring(reason or ""):upper() local extra = tostring(detail or ""):upper() local combined = primary .. " | " .. extra if combined:find("DEVICE_MISMATCH", 1, true) or primary == "BOOTSTRAP_DEVICE_MISMATCH" or primary == "SESSION_DEVICE_MISMATCH" then return "DEVICE ID MISMATCH - USE RESET HWID" end if primary == "INVALID_LICENSE" then return "INVALID KEY - CHECK IT AND TRY AGAIN" end if primary == "LICENSE_EXPIRED" then return "KEY EXPIRED - USE AN ACTIVE KEY" end if primary == "LICENSE_DISABLED" then return "THIS KEY IS DISABLED" end if primary == "LICENSE_REVOKED" then return "THIS KEY HAS BEEN REVOKED" end if primary == "LICENSE_BANNED" then return "THIS KEY IS BANNED" end if primary == "LICENSE_LOCKED" or primary == "LICENSE_REVIEW_LOCKED" then return "THIS KEY IS LOCKED - CONTACT WOLFHUB SUPPORT" end if primary == "" then return "" end return "ACCESS DENIED - " .. primary end local function askForLicense(initialError) local parent = getGuiParent() local old = parent:FindFirstChild("WOLF_BOOTSTRAP_LICENSE") if old then old:Destroy() end local gui = Instance.new("ScreenGui") gui.Name = "WOLF_BOOTSTRAP_LICENSE" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.ZIndexBehavior = Enum.ZIndexBehavior.Global gui.DisplayOrder = 900000 gui.Parent = parent local shade = Instance.new("Frame") shade.Name = "Shade" shade.Size = UDim2.fromScale(1, 1) shade.BackgroundColor3 = Color3.fromRGB(0, 0, 0) shade.BackgroundTransparency = 0.34 shade.BorderSizePixel = 0 shade.Active = true shade.Parent = gui -- Clean WolfHub KEY SYSTEM artwork uploaded by the owner. -- All interactive text/buttons below are real Roblox UI layered on top. local LICENSE_BACKGROUND_ID = "rbxassetid://133189119148693" local PANEL_W, PANEL_H = 768, 512 -- exact 3:2 artwork ratio local panel = Instance.new("Frame") panel.Name = "LicensePanel" panel.AnchorPoint = Vector2.new(0.5, 0.5) panel.Position = UDim2.fromScale(0.5, 0.5) panel.Size = UDim2.fromOffset(PANEL_W, PANEL_H) panel.BackgroundColor3 = Color3.fromRGB(2, 7, 18) panel.BorderSizePixel = 0 panel.ClipsDescendants = true panel.Parent = shade local panelCorner = Instance.new("UICorner") panelCorner.CornerRadius = UDim.new(0, 16) panelCorner.Parent = panel local artwork = Instance.new("ImageLabel") artwork.Name = "LicenseArtwork" artwork.BackgroundTransparency = 1 artwork.Position = UDim2.fromScale(0, 0) artwork.Size = UDim2.fromScale(1, 1) artwork.Image = LICENSE_BACKGROUND_ID artwork.ScaleType = Enum.ScaleType.Stretch artwork.ZIndex = 1 artwork.Parent = panel local panelScale = Instance.new("UIScale") panelScale.Scale = 1 panelScale.Parent = panel local viewportConnection = nil local cameraChangedConnection = nil local function rescaleLicensePanel() local camera = workspace.CurrentCamera if not camera then panelScale.Scale = 1 return end local viewport = camera.ViewportSize local marginX = IS_TOUCH_DEVICE and 12 or 28 local marginY = IS_TOUCH_DEVICE and 12 or 28 local maxW = math.max(1, viewport.X - marginX * 2) local maxH = math.max(1, viewport.Y - marginY * 2) panelScale.Scale = math.clamp( math.min(maxW / PANEL_W, maxH / PANEL_H, 1), IS_TOUCH_DEVICE and 0.42 or 0.50, 1 ) end local function bindViewport() if viewportConnection then pcall(function() viewportConnection:Disconnect() end) viewportConnection = nil end local camera = workspace.CurrentCamera if camera then viewportConnection = camera:GetPropertyChangedSignal("ViewportSize"):Connect(rescaleLicensePanel) end end rescaleLicensePanel() bindViewport() cameraChangedConnection = workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function() task.defer(function() bindViewport() rescaleLicensePanel() end) end) -- Real input placed inside the empty glowing LICENSE KEY frame in the artwork. local input = Instance.new("TextBox") input.Name = "LicenseInput" input.Position = UDim2.fromScale(0.392, 0.423) input.Size = UDim2.fromScale(0.545, 0.073) input.BackgroundTransparency = 1 input.BorderSizePixel = 0 input.ClearTextOnFocus = false input.Font = Enum.Font.GothamBold input.Text = "" input.PlaceholderText = "WH-XXXXX-XXXXX-XXXXX-XXXXX" input.PlaceholderColor3 = Color3.fromRGB(92, 119, 185) input.TextColor3 = Color3.fromRGB(232, 243, 255) input.TextSize = 16 input.TextXAlignment = Enum.TextXAlignment.Center input.TextYAlignment = Enum.TextYAlignment.Center input.ZIndex = 50 input.Parent = panel -- Runtime status is kept on the right so it does not cover the baked -- "Enter your license" helper text on the left side of the artwork. local status = Instance.new("TextLabel") status.Name = "LicenseStatus" status.BackgroundTransparency = 1 status.Position = UDim2.fromScale(0.635, 0.518) status.Size = UDim2.fromScale(0.300, 0.040) status.Font = Enum.Font.GothamMedium status.Text = "" status.TextSize = 10 status.TextColor3 = Color3.fromRGB(84, 210, 255) status.TextXAlignment = Enum.TextXAlignment.Right status.TextYAlignment = Enum.TextYAlignment.Center status.ZIndex = 60 status.Parent = panel if initialError and tostring(initialError) ~= "" then status.Text = tostring(initialError) status.TextColor3 = Color3.fromRGB(255, 103, 135) end local authenticate = Instance.new("TextButton") authenticate.Name = "Authenticate" authenticate.Position = UDim2.fromScale(0.369, 0.584) authenticate.Size = UDim2.fromScale(0.592, 0.106) authenticate.BackgroundTransparency = 1 authenticate.BorderSizePixel = 0 authenticate.AutoButtonColor = false authenticate.Font = Enum.Font.GothamBlack authenticate.Text = "AUTHENTICATE" authenticate.TextSize = 18 authenticate.TextColor3 = Color3.fromRGB(255, 255, 255) authenticate.TextStrokeColor3 = Color3.fromRGB(15, 91, 255) authenticate.TextStrokeTransparency = 0.72 authenticate.ZIndex = 70 authenticate.Parent = panel local discordButton = Instance.new("TextButton") discordButton.Name = "JoinDiscord" discordButton.Position = UDim2.fromScale(0.369, 0.721) discordButton.Size = UDim2.fromScale(0.200, 0.090) discordButton.BackgroundTransparency = 1 discordButton.BorderSizePixel = 0 discordButton.AutoButtonColor = false discordButton.Text = "" discordButton.ZIndex = 70 discordButton.Parent = panel local discordIcon = Instance.new("Frame") discordIcon.Name = "DiscordIcon" discordIcon.AnchorPoint = Vector2.new(0, 0.5) discordIcon.Position = UDim2.fromScale(0.060, 0.5) discordIcon.Size = UDim2.fromScale(0.155, 0.58) discordIcon.BackgroundColor3 = Color3.fromRGB(91, 103, 255) discordIcon.BorderSizePixel = 0 discordIcon.ZIndex = 71 discordIcon.Parent = discordButton local discordIconCorner = Instance.new("UICorner") discordIconCorner.CornerRadius = UDim.new(0, 8) discordIconCorner.Parent = discordIcon local discordEyes = Instance.new("TextLabel") discordEyes.BackgroundTransparency = 1 discordEyes.Size = UDim2.fromScale(1, 1) discordEyes.Font = Enum.Font.GothamBlack discordEyes.Text = "••" discordEyes.TextSize = 15 discordEyes.TextColor3 = Color3.fromRGB(255, 255, 255) discordEyes.ZIndex = 72 discordEyes.Parent = discordIcon local discordText = Instance.new("TextLabel") discordText.Name = "DiscordText" discordText.BackgroundTransparency = 1 discordText.Position = UDim2.fromScale(0.245, 0) discordText.Size = UDim2.fromScale(0.735, 1) discordText.Font = Enum.Font.GothamBold discordText.Text = "JOIN DISCORD" discordText.TextSize = 12 discordText.TextColor3 = Color3.fromRGB(248, 249, 255) discordText.TextXAlignment = Enum.TextXAlignment.Center discordText.ZIndex = 71 discordText.Parent = discordButton local getKeyButton = Instance.new("TextButton") getKeyButton.Name = "GetKey" getKeyButton.Position = UDim2.fromScale(0.582, 0.721) getKeyButton.Size = UDim2.fromScale(0.190, 0.090) getKeyButton.BackgroundTransparency = 1 getKeyButton.BorderSizePixel = 0 getKeyButton.AutoButtonColor = false getKeyButton.Text = "" getKeyButton.ZIndex = 70 getKeyButton.Parent = panel -- Small neon key icon built from UI primitives so no extra asset is required. local keyRing = Instance.new("Frame") keyRing.Name = "KeyRing" keyRing.AnchorPoint = Vector2.new(0, 0.5) keyRing.Position = UDim2.fromScale(0.075, 0.43) keyRing.Size = UDim2.fromOffset(18, 18) keyRing.BackgroundTransparency = 1 keyRing.BorderSizePixel = 0 keyRing.Rotation = -35 keyRing.ZIndex = 71 keyRing.Parent = getKeyButton local keyRingCorner = Instance.new("UICorner") keyRingCorner.CornerRadius = UDim.new(1, 0) keyRingCorner.Parent = keyRing local keyRingStroke = Instance.new("UIStroke") keyRingStroke.Thickness = 3 keyRingStroke.Color = Color3.fromRGB(24, 220, 255) keyRingStroke.Parent = keyRing local keyShaft = Instance.new("Frame") keyShaft.AnchorPoint = Vector2.new(0, 0.5) keyShaft.Position = UDim2.fromScale(0.16, 0.64) keyShaft.Size = UDim2.fromOffset(24, 4) keyShaft.Rotation = -35 keyShaft.BackgroundColor3 = Color3.fromRGB(24, 220, 255) keyShaft.BorderSizePixel = 0 keyShaft.ZIndex = 71 keyShaft.Parent = getKeyButton local keyTooth = Instance.new("Frame") keyTooth.Position = UDim2.new(1, -7, 0, 2) keyTooth.Size = UDim2.fromOffset(7, 4) keyTooth.BackgroundColor3 = Color3.fromRGB(24, 220, 255) keyTooth.BorderSizePixel = 0 keyTooth.ZIndex = 72 keyTooth.Parent = keyShaft local getKeyText = Instance.new("TextLabel") getKeyText.Name = "GetKeyText" getKeyText.BackgroundTransparency = 1 getKeyText.Position = UDim2.fromScale(0.27, 0) getKeyText.Size = UDim2.fromScale(0.69, 1) getKeyText.Font = Enum.Font.GothamBold getKeyText.Text = "GET KEY" getKeyText.TextSize = 12 getKeyText.TextColor3 = Color3.fromRGB(248, 249, 255) getKeyText.TextXAlignment = Enum.TextXAlignment.Center getKeyText.ZIndex = 71 getKeyText.Parent = getKeyButton local closeButton = Instance.new("TextButton") closeButton.Name = "Close" closeButton.Position = UDim2.fromScale(0.783, 0.721) closeButton.Size = UDim2.fromScale(0.178, 0.090) closeButton.BackgroundTransparency = 1 closeButton.BorderSizePixel = 0 closeButton.AutoButtonColor = false closeButton.Font = Enum.Font.GothamBold closeButton.Text = "CLOSE" closeButton.TextSize = 12 closeButton.TextColor3 = Color3.fromRGB(248, 249, 255) closeButton.ZIndex = 70 closeButton.Parent = panel -- Transparent click target over the X that is already baked into the artwork. local xButton = Instance.new("TextButton") xButton.Name = "TopClose" xButton.AnchorPoint = Vector2.new(1, 0) xButton.Position = UDim2.fromScale(0.980, 0.028) xButton.Size = UDim2.fromScale(0.055, 0.070) xButton.BackgroundTransparency = 1 xButton.BorderSizePixel = 0 xButton.Text = "" xButton.AutoButtonColor = false xButton.ZIndex = 80 xButton.Parent = panel -- Make the license UI usable even when the executor entered Roblox with a -- locked mouse. Restore the user's previous input state on close/submit. local oldMouseBehavior = nil local oldMouseIconEnabled = nil pcall(function() oldMouseBehavior = UIS.MouseBehavior end) pcall(function() oldMouseIconEnabled = UIS.MouseIconEnabled end) pcall(function() UIS.MouseBehavior = Enum.MouseBehavior.Default end) pcall(function() UIS.MouseIconEnabled = true end) local DISCORD_INVITE = "https://discord.gg/w4bK9K6f8S" local done = Instance.new("BindableEvent") local busy = false local function cleanupPrompt() if viewportConnection then pcall(function() viewportConnection:Disconnect() end) viewportConnection = nil end if cameraChangedConnection then pcall(function() cameraChangedConnection:Disconnect() end) cameraChangedConnection = nil end if oldMouseBehavior ~= nil then pcall(function() UIS.MouseBehavior = oldMouseBehavior end) end if oldMouseIconEnabled ~= nil then pcall(function() UIS.MouseIconEnabled = oldMouseIconEnabled end) end end local function setStatus(textValue, ok) if not status.Parent then return end status.Text = tostring(textValue or "") status.TextColor3 = ok and Color3.fromRGB(67, 224, 255) or Color3.fromRGB(255, 103, 135) end local function wolfGlobal(name) local environments = {} pcall(function() if typeof(getgenv) == "function" then environments[#environments + 1] = getgenv() end end) pcall(function() if typeof(getfenv) == "function" then environments[#environments + 1] = getfenv() end end) pcall(function() environments[#environments + 1] = _G end) for _, env in ipairs(environments) do if type(env) == "table" then local ok, candidate = pcall(function() return env[name] end) if ok and candidate ~= nil then return candidate end for _, namespaceName in ipairs({"syn", "executor", "clipboard", "Clipboard", "utils", "Utility"}) do local okNs, namespace = pcall(function() return env[namespaceName] end) if okNs and type(namespace) == "table" then local okValue, value = pcall(function() return namespace[name] end) if okValue and value ~= nil then return value end end end end end return nil end local function copyDiscordInvite() local candidates = { setclipboard, toclipboard, wolfGlobal("setclipboard"), wolfGlobal("toclipboard"), wolfGlobal("set_clipboard"), wolfGlobal("writeclipboard"), wolfGlobal("write_clipboard"), wolfGlobal("copytoclipboard"), wolfGlobal("copy_to_clipboard"), } for _, copier in ipairs(candidates) do if typeof(copier) == "function" then local ok = pcall(copier, DISCORD_INVITE) if ok then return true end end end return false end local function tryOpenExternalUrl(url) local names = { "open_url", "openurl", "openUrl", "OpenUrl", "OpenURL", "openURL", "open_browser", "openbrowser", "openBrowser", "OpenBrowser", "open_link", "openlink", "openLink", "OpenLink", "launch_url", "launchurl", "launchUrl", "LaunchUrl", "open_external", "openexternal", "openExternal", "OpenExternal", } for _, name in ipairs(names) do local fn = wolfGlobal(name) if typeof(fn) == "function" then local ok, result = pcall(fn, url) if ok and result ~= false then return true end end end return false end local function closePrompt() if busy then return end done:Fire("__WOLF_LICENSE_CLOSE__") end local function submit() if busy then return end local key = normalizeKey(input.Text) if key == "" then setStatus("LICENSE REQUIRED", false) return end if not plausibleKey(key) then setStatus("INVALID KEY - CHECK IT AND TRY AGAIN", false) return end busy = true setStatus("CHECKING...", true) done:Fire(key) end local getKeyBusy = false local function activateGetKey() if busy or getKeyBusy then return end getKeyBusy = true local copied = copyDiscordInvite() if copied then getKeyText.Text = "COPIED!" setStatus("Discord invite copied.", true) else getKeyText.Text = "GET KEY" setStatus("Clipboard is not supported by this executor.", false) end task.delay(2.5, function() if getKeyText.Parent then getKeyText.Text = "GET KEY" end getKeyBusy = false end) end local discordBusy = false local function activateDiscord() if busy or discordBusy then return end discordBusy = true discordText.Text = "OPENING..." local copied = copyDiscordInvite() local opened = tryOpenExternalUrl("discord://-/invite/w4bK9K6f8S") if not opened then opened = tryOpenExternalUrl(DISCORD_INVITE) end if opened then discordText.Text = "DISCORD OPENED" setStatus(copied and "Discord opened + invite copied." or "Discord opened.", true) elseif copied then discordText.Text = "LINK COPIED" setStatus("Discord invite copied.", true) else discordText.Text = "JOIN DISCORD" setStatus("Could not open Discord on this executor.", false) end task.delay(2.8, function() if discordText.Parent then discordText.Text = "JOIN DISCORD" end discordBusy = false end) end authenticate.Activated:Connect(submit) input.FocusLost:Connect(function(enterPressed) if enterPressed then submit() end end) discordButton.Activated:Connect(activateDiscord) getKeyButton.Activated:Connect(activateGetKey) closeButton.Activated:Connect(closePrompt) xButton.Activated:Connect(closePrompt) local result = done.Event:Wait() cleanupPrompt() done:Destroy() gui:Destroy() return result end local function perform(options) local ok, response = pcall(REQUEST, options) if not ok or type(response) ~= "table" then return nil, 0, "REQUEST_FAILED" end local status = tonumber(response.StatusCode or response.Status or response.status_code or 0) or 0 local body = response.Body or response.body or "" return tostring(body or ""), status, nil end local function decodeJson(body) local ok, data = pcall(HttpService.JSONDecode, HttpService, tostring(body or "")) return ok and type(data) == "table" and data or {} end local deviceId = loadDeviceId() local gameId = tostring(game.GameId or "") local placeId = tostring(game.PlaceId or "") local license = findInitialKey() local lastReason = nil local replaceable = { INVALID_LICENSE = true, LICENSE_EXPIRED = true, LICENSE_DISABLED = true, LICENSE_REVOKED = true, LICENSE_BANNED = true, LICENSE_LOCKED = true, LICENSE_REVIEW_LOCKED = true, } local ticket = nil while not ticket do if not plausibleKey(license) then license = askForLicense(lastReason) if license == "__WOLF_LICENSE_CLOSE__" then return end lastReason = nil end local nonce = HttpService:GenerateGUID(false):gsub("%-", "") .. HttpService:GenerateGUID(false):gsub("%-", "") local headers = { ["Content-Type"] = "application/json", ["Accept"] = "application/json", ["X-Wolf-License"] = license, ["X-Wolf-Device"] = deviceId, ["X-Wolf-Loader-Version"] = LOADER_VERSION, ["X-Wolf-Security-Version"] = SECURITY_VERSION, ["X-Wolf-Executor-Gate"] = EXECUTOR_GATE_VERSION, ["X-Wolf-Release-Channel"] = RELEASE_CHANNEL, ["X-Wolf-Game-ID"] = gameId, ["X-Wolf-Place-ID"] = placeId, ["X-Wolf-Nonce"] = nonce, ["X-Wolf-Timestamp"] = tostring(os.time()), } local body, status, requestErr = perform({ Url = API .. "/bootstrap/ticket", Method = "POST", Headers = headers, Body = "{}", }) local data = decodeJson(body) if status == 200 and data.ok == true and type(data.ticket) == "string" and #data.ticket >= 24 then ticket = data.ticket setSharedKey(license) writeFile(KEY_FILE, license) else local reason = tostring(data.error or requestErr or "BOOTSTRAP_AUTH_FAILED") local detail = tostring(data.reason or data.message or "") local upperDetail = detail:upper() local deviceMismatch = reason == "BOOTSTRAP_DEVICE_MISMATCH" or reason == "SESSION_DEVICE_MISMATCH" or upperDetail:find("DEVICE_MISMATCH", 1, true) ~= nil if replaceable[reason] or deviceMismatch then -- Invalid/expired/disabled keys are removed from the local key cache. -- A DEVICE ID mismatch keeps the valid key file intact; the player -- only needs to use RESET HWID in the WolfHub User Panel. if not deviceMismatch then deleteKeyFiles() end license = "" lastReason = licensePromptMessage(reason, detail) else local friendly = reason if reason == "BOOTSTRAP_VERSION_REQUIRED" then friendly = "LOADER UPDATE REQUIRED - USE THE LATEST WOLFHUB LOADER" elseif reason == "BOOTSTRAP_RATE_LIMIT" then friendly = "TOO MANY START ATTEMPTS - WAIT A MOMENT AND TRY AGAIN" elseif reason == "BOOTSTRAP_DEVICE_INVALID" then friendly = "DEVICE ID INVALID - USE RESET HWID AND TRY AGAIN" elseif reason == "BOOTSTRAP_DEVICE_MISMATCH" then friendly = "DEVICE ID MISMATCH - USE RESET HWID" elseif reason == "FREE_KEY_REGULAR_LOADER_ONLY" then friendly = "FREE KEY - USE THE REGULAR WOLFHUB LOADER" elseif reason == "PREMIUM_LOADER_REQUIRED" then friendly = "PREMIUM KEY - USE THE WOLFHUB PREMIUM LOADER" elseif reason == "LIFETIME_REQUIRED_FOR_TESTER" then friendly = "LOADER TESTER REQUIRES A LIFETIME LICENSE" elseif reason == "TESTER_ROLE_REQUIRED_FOR_TESTER" then friendly = "LOADER TESTER REQUIRES THE TESTER ROLE - REFRESH YOUR DISCORD LICENSE" end stage0Fail(friendly) return end end end local fullSource, fetchStatus, fetchErr = perform({ Url = API .. "/bootstrap/fetch", Method = "POST", Headers = { ["Content-Type"] = "application/json", ["Accept"] = "text/plain", ["X-Wolf-Bootstrap-Ticket"] = ticket, ["X-Wolf-Device"] = deviceId, ["X-Wolf-Release-Channel"] = RELEASE_CHANNEL, ["X-Wolf-Game-ID"] = gameId, ["X-Wolf-Place-ID"] = placeId, }, Body = "{}", }) ticket = nil if fetchStatus ~= 200 or type(fullSource) ~= "string" or #fullSource < 1000 then local data = decodeJson(fullSource) fullSource = nil stage0Fail("Full Loader ticket rejected: " .. tostring(data.error or fetchErr or fetchStatus)) return end local chunk, compileError = loadstring(fullSource) fullSource = nil if not chunk then stage0Fail("Full Loader compile failed: " .. tostring(compileError)) return end local runOk, runResult = pcall(chunk) chunk = nil if not runOk then stage0Fail("Full Loader runtime failed: " .. tostring(runResult)) return end return runResult