--[[ NOVA MENU - LocalScript Emplacement : StarterPlayer > StarterPlayerScripts > LocalScript Pour TES jeux / tests dans Roblox Studio. Touches : Insert ou M : afficher / cacher le menu Haut / Bas : naviguer Gauche/Droite : changer une valeur (ou sortir / entrer dans un sous-menu) Entree : valider / activer Retour arriere: revenir en arriere Q / E : changer d'onglet F : voler (raccourci) G : freecam (clic droit = regarder, WASD, Espace/Shift, Ctrl = rapide) C (maintenu) : zoom ]] local Players = game:GetService("Players") local UIS = game:GetService("UserInputService") local RunService = game:GetService("RunService") local TweenService = game:GetService("TweenService") local Lighting = game:GetService("Lighting") local CAS = game:GetService("ContextActionService") local TeleportService = game:GetService("TeleportService") local HttpService = game:GetService("HttpService") local ReplicatedStorage = game:GetService("ReplicatedStorage") -- Mets ici l'id d'une image de banniere si tu veux, ex : "rbxassetid://123456789" local BANNER_IMAGE = "" local player = Players.LocalPlayer local camera = workspace.CurrentCamera local mouse = player:GetMouse() local conns = {} local function connect(signal, fn) local c = signal:Connect(fn) table.insert(conns, c) return c end local BLACK, WHITE = Color3.new(0, 0, 0), Color3.new(1, 1, 1) local THEME_NAMES = { "Orange", "Blue", "Purple", "Green", "Red", "Pink" } local THEMES = { Orange = Color3.fromRGB(255, 125, 0), Blue = Color3.fromRGB(60, 125, 255), Purple = Color3.fromRGB(150, 85, 255), Green = Color3.fromRGB(45, 200, 110), Red = Color3.fromRGB(230, 60, 70), Pink = Color3.fromRGB(255, 95, 180), } local ESP_COLOR_NAMES = { "Red", "Green", "Blue", "White", "Orange", "Purple", "Rainbow" } local ESP_COLORS = { Red = Color3.fromRGB(255, 60, 60), Green = Color3.fromRGB(60, 255, 100), Blue = Color3.fromRGB(70, 140, 255), White = Color3.fromRGB(255, 255, 255), Orange = Color3.fromRGB(255, 150, 40), Purple = Color3.fromRGB(170, 100, 255), } ---------------------------------------------------------------- -- ETAT ---------------------------------------------------------------- local origGravity = workspace.Gravity local origFov = camera.FieldOfView local origZoom = player.CameraMaxZoomDistance local S = { -- self fly = false, flySpeed = 60, noclip = false, customSpeed = false, walkSpeed = 32, customJump = false, jumpPower = 100, infJump = false, clickTP = false, spin = false, spinSpeed = 10, -- visual esp = false, espBox = true, espSkeleton = true, espName = true, espDistance = true, espHealth = true, espTracer = false, espChams = false, espTeamCheck = false, espTeamColors = false, espColor = "Red", espMaxDist = 1500, fov = math.floor(origFov + 0.5), crosshair = false, crossSize = 10, customFov = false, zoomOn = true, zoomFov = 30, freecam = false, freecamSpeed = 60, freecamSens = 1, freecamFreeze = true, -- combat aim = false, aimKey = "Right Click", aimPart = "Head", aimFov = 150, aimShowFov = true, aimStrength = 0.25, aimWall = true, aimTeam = false, aimMaxDist = 1000, -- online target = nil, spectate = false, -- world fullbright = false, noFog = false, gravity = math.floor(origGravity + 0.5), clock = math.floor(Lighting.ClockTime), zoom = false, -- misc / settings antiAfk = false, showFps = true, theme = "Orange", scale = 1, cfgSlot = "Slot 1", cfgAuto = false, } local menuOpen = true local unloaded = false local render -- declaration anticipee local function new(class, props, parent) local o = Instance.new(class) for k, v in pairs(props) do o[k] = v end o.Parent = parent return o end local function getChar() local c = player.Character return c, c and c:FindFirstChild("HumanoidRootPart"), c and c:FindFirstChildOfClass("Humanoid") end ---------------------------------------------------------------- -- GUIS ---------------------------------------------------------------- local pg = player:WaitForChild("PlayerGui") for _, n in ipairs({ "NovaMenu", "NovaESP" }) do local old = pg:FindFirstChild(n) if old then old:Destroy() end end local espGui = new("ScreenGui", { Name = "NovaESP", ResetOnSpawn = false, IgnoreGuiInset = true, DisplayOrder = 1 }, pg) local gui = new("ScreenGui", { Name = "NovaMenu", ResetOnSpawn = false, IgnoreGuiInset = true, DisplayOrder = 10 }, pg) ---------------------------------------------------------------- -- VOL ---------------------------------------------------------------- local flyBV, flyBG, flyConn local function stopFly() if flyConn then flyConn:Disconnect() flyConn = nil end if flyBV then flyBV:Destroy() flyBV = nil end if flyBG then flyBG:Destroy() flyBG = nil end local _, _, hum = getChar() if hum then hum.PlatformStand = false end end local function startFly() stopFly() local _, root, hum = getChar() if not (root and hum) then S.fly = false return end hum.PlatformStand = true flyBV = new("BodyVelocity", { MaxForce = Vector3.one * 1e5, Velocity = Vector3.zero }, root) flyBG = new("BodyGyro", { MaxTorque = Vector3.one * 1e5, P = 1e4, CFrame = root.CFrame }, root) flyConn = RunService.RenderStepped:Connect(function() local dir, cf = Vector3.zero, camera.CFrame if UIS:IsKeyDown(Enum.KeyCode.W) then dir += cf.LookVector end if UIS:IsKeyDown(Enum.KeyCode.S) then dir -= cf.LookVector end if UIS:IsKeyDown(Enum.KeyCode.D) then dir += cf.RightVector end if UIS:IsKeyDown(Enum.KeyCode.A) then dir -= cf.RightVector end if UIS:IsKeyDown(Enum.KeyCode.Space) then dir += Vector3.yAxis end if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then dir -= Vector3.yAxis end if S.freecam then dir = Vector3.zero end if dir.Magnitude > 0 then dir = dir.Unit end flyBV.Velocity = dir * S.flySpeed flyBG.CFrame = cf end) end local function setFly(v) S.fly = v if v then startFly() else stopFly() end if render then render() end end ---------------------------------------------------------------- -- MOUVEMENT (noclip, vitesse, saut, spin) ---------------------------------------------------------------- connect(RunService.Stepped, function() if S.noclip then local c = player.Character if c then for _, p in ipairs(c:GetDescendants()) do if p:IsA("BasePart") then p.CanCollide = false end end end end end) connect(RunService.Heartbeat, function() local _, root, hum = getChar() if not hum then return end if S.customSpeed then hum.WalkSpeed = S.walkSpeed end if S.customJump then hum.UseJumpPower = true hum.JumpPower = S.jumpPower end if S.spin and root and not S.fly then root.CFrame *= CFrame.Angles(0, math.rad(S.spinSpeed), 0) end end) connect(UIS.JumpRequest, function() if S.infJump then local _, _, hum = getChar() if hum then hum:ChangeState(Enum.HumanoidStateType.Jumping) end end end) connect(player.Idled, function() if S.antiAfk then pcall(function() local vu = game:GetService("VirtualUser") vu:CaptureController() vu:ClickButton2(Vector2.new()) end) end end) ---------------------------------------------------------------- -- ESP ---------------------------------------------------------------- local espData = {} local BONES_R15 = { { "Head", "UpperTorso" }, { "UpperTorso", "LowerTorso" }, { "UpperTorso", "LeftUpperArm" }, { "LeftUpperArm", "LeftLowerArm" }, { "LeftLowerArm", "LeftHand" }, { "UpperTorso", "RightUpperArm" }, { "RightUpperArm", "RightLowerArm" }, { "RightLowerArm", "RightHand" }, { "LowerTorso", "LeftUpperLeg" }, { "LeftUpperLeg", "LeftLowerLeg" }, { "LeftLowerLeg", "LeftFoot" }, { "LowerTorso", "RightUpperLeg" }, { "RightUpperLeg", "RightLowerLeg" }, { "RightLowerLeg", "RightFoot" }, } local BONES_R6 = { { "Head", "Torso" }, { "Torso", "Left Arm" }, { "Torso", "Right Arm" }, { "Torso", "Left Leg" }, { "Torso", "Right Leg" }, } local function espColor() if S.espColor == "Rainbow" then return Color3.fromHSV((os.clock() * 0.3) % 1, 1, 1) end return ESP_COLORS[S.espColor] end local function newLine(parent) return new("Frame", { AnchorPoint = Vector2.new(0.5, 0.5), BorderSizePixel = 0, BackgroundColor3 = WHITE, Visible = false, }, parent) end local function setLine(f, a, b, thick, col) local d = b - a f.Visible = true f.BackgroundColor3 = col f.Size = UDim2.fromOffset(d.Magnitude, thick) f.Position = UDim2.fromOffset((a.X + b.X) / 2, (a.Y + b.Y) / 2) f.Rotation = math.deg(math.atan2(d.Y, d.X)) end local function createESP(plr) local folder = new("Folder", { Name = plr.Name }, espGui) local d = { folder = folder } d.box = new("Frame", { BackgroundTransparency = 1, BorderSizePixel = 0, Visible = false }, folder) d.boxStroke = new("UIStroke", { Thickness = 1.5 }, d.box) d.name = new("TextLabel", { BackgroundTransparency = 1, AnchorPoint = Vector2.new(0.5, 1), Size = UDim2.fromOffset(200, 16), Font = Enum.Font.GothamBold, TextSize = 14, TextStrokeTransparency = 0.4, Visible = false, }, folder) d.dist = new("TextLabel", { BackgroundTransparency = 1, AnchorPoint = Vector2.new(0.5, 0), Size = UDim2.fromOffset(200, 14), Font = Enum.Font.GothamMedium, TextSize = 12, TextStrokeTransparency = 0.4, Visible = false, }, folder) d.hpBack = new("Frame", { BackgroundColor3 = BLACK, BackgroundTransparency = 0.3, BorderSizePixel = 0, Visible = false, }, folder) d.hpFill = new("Frame", { AnchorPoint = Vector2.new(0, 1), BorderSizePixel = 0, Visible = false }, folder) d.tracer = newLine(folder) d.bones = {} for i = 1, 14 do d.bones[i] = newLine(folder) end espData[plr] = d return d end local function hideESP(d) d.box.Visible = false d.name.Visible = false d.dist.Visible = false d.hpBack.Visible = false d.hpFill.Visible = false d.tracer.Visible = false for _, b in ipairs(d.bones) do b.Visible = false end if d.hl then d.hl.Enabled = false end end local function removeESP(plr) local d = espData[plr] if d then if d.hl then d.hl:Destroy() end d.folder:Destroy() espData[plr] = nil end end local function updateESP() local camPos = camera.CFrame.Position local vp = camera.ViewportSize for _, plr in ipairs(Players:GetPlayers()) do if plr ~= player then local d = espData[plr] or createESP(plr) local char = plr.Character local hum = char and char:FindFirstChildOfClass("Humanoid") local root = char and char:FindFirstChild("HumanoidRootPart") local show = S.esp and hum ~= nil and root ~= nil and hum.Health > 0 if show and S.espTeamCheck and plr.Team ~= nil and plr.Team == player.Team then show = false end local dist = 0 if show then dist = (root.Position - camPos).Magnitude if dist > S.espMaxDist then show = false end end local top, bot if show then local t = camera:WorldToViewportPoint(root.Position + Vector3.new(0, 2.9, 0)) local b = camera:WorldToViewportPoint(root.Position - Vector3.new(0, 3.1, 0)) if t.Z > 0 and b.Z > 0 then top, bot = Vector2.new(t.X, t.Y), Vector2.new(b.X, b.Y) else show = false end end if not show then hideESP(d) else local col = espColor() if S.espTeamColors and plr.Team then col = plr.TeamColor.Color end local h = math.max(bot.Y - top.Y, 4) local w = h * 0.55 local cx = (top.X + bot.X) / 2 -- box d.box.Visible = S.espBox if S.espBox then d.box.Position = UDim2.fromOffset(cx - w / 2, top.Y) d.box.Size = UDim2.fromOffset(w, h) d.boxStroke.Color = col end -- nom d.name.Visible = S.espName if S.espName then d.name.Text = plr.DisplayName d.name.TextColor3 = col d.name.Position = UDim2.fromOffset(cx, top.Y - 2) end -- distance d.dist.Visible = S.espDistance if S.espDistance then d.dist.Text = math.floor(dist) .. " m" d.dist.TextColor3 = WHITE d.dist.Position = UDim2.fromOffset(cx, bot.Y + 2) end -- barre de vie d.hpBack.Visible = S.espHealth d.hpFill.Visible = S.espHealth if S.espHealth then local frac = math.clamp(hum.Health / math.max(hum.MaxHealth, 1), 0, 1) local x = cx - w / 2 - 6 d.hpBack.Position = UDim2.fromOffset(x - 1, top.Y - 1) d.hpBack.Size = UDim2.fromOffset(4, h + 2) d.hpFill.Position = UDim2.fromOffset(x, bot.Y) d.hpFill.Size = UDim2.fromOffset(2, h * frac) d.hpFill.BackgroundColor3 = Color3.fromHSV(frac * 0.33, 1, 1) end -- tracer if S.espTracer then setLine(d.tracer, Vector2.new(vp.X / 2, vp.Y), Vector2.new(cx, bot.Y), 1.5, col) else d.tracer.Visible = false end -- squelette local bones = hum.RigType == Enum.HumanoidRigType.R15 and BONES_R15 or BONES_R6 for i = 1, #d.bones do local line = d.bones[i] local pair = S.espSkeleton and bones[i] local drawn = false if pair then local a, b = char:FindFirstChild(pair[1]), char:FindFirstChild(pair[2]) if a and b then local pa = camera:WorldToViewportPoint(a.Position) local pb = camera:WorldToViewportPoint(b.Position) if pa.Z > 0 and pb.Z > 0 then setLine(line, Vector2.new(pa.X, pa.Y), Vector2.new(pb.X, pb.Y), 1.5, col) drawn = true end end end if not drawn then line.Visible = false end end -- chams if S.espChams then if not d.hl or d.hl.Parent ~= char then if d.hl then d.hl:Destroy() end d.hl = new("Highlight", { Adornee = char, FillTransparency = 0.55, OutlineColor = WHITE, DepthMode = Enum.HighlightDepthMode.AlwaysOnTop, }, char) end d.hl.FillColor = col d.hl.Enabled = true elseif d.hl then d.hl.Enabled = false end end end end end connect(Players.PlayerRemoving, function(plr) removeESP(plr) if render then render() end end) connect(Players.PlayerAdded, function() if render then render() end end) ---------------------------------------------------------------- -- VISEE ASSISTEE ---------------------------------------------------------------- local fovCircle = new("Frame", { AnchorPoint = Vector2.new(0.5, 0.5), BackgroundTransparency = 1, Visible = false, }, espGui) new("UICorner", { CornerRadius = UDim.new(1, 0) }, fovCircle) new("UIStroke", { Color = WHITE, Thickness = 1.5, Transparency = 0.3 }, fovCircle) local function aimHeld() local k = S.aimKey if k == "Right Click" then return UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton2) elseif k == "Left Click" then return UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) elseif k == "Left Alt" then return UIS:IsKeyDown(Enum.KeyCode.LeftAlt) end return true end local function isVisible(part, char) local params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = { player.Character } local origin = camera.CFrame.Position local result = workspace:Raycast(origin, part.Position - origin, params) return result == nil or result.Instance:IsDescendantOf(char) end local function getTarget() local m = UIS:GetMouseLocation() local camPos = camera.CFrame.Position local best, bestD = nil, S.aimFov for _, plr in ipairs(Players:GetPlayers()) do local char = plr ~= player and plr.Character if char and not (S.aimTeam and plr.Team ~= nil and plr.Team == player.Team) then local hum = char:FindFirstChildOfClass("Humanoid") local part = char:FindFirstChild(S.aimPart == "Head" and "Head" or "HumanoidRootPart") if hum and part and hum.Health > 0 and (part.Position - camPos).Magnitude <= S.aimMaxDist then local p, onScreen = camera:WorldToViewportPoint(part.Position) if onScreen then local d = (Vector2.new(p.X, p.Y) - m).Magnitude if d < bestD and (not S.aimWall or isVisible(part, char)) then best, bestD = part, d end end end end end return best end local function updateAim() fovCircle.Visible = S.aim and S.aimShowFov if not S.aim or S.freecam then return end local m = UIS:GetMouseLocation() fovCircle.Position = UDim2.fromOffset(m.X, m.Y) fovCircle.Size = UDim2.fromOffset(S.aimFov * 2, S.aimFov * 2) if aimHeld() then local target = getTarget() if target then local cf = camera.CFrame camera.CFrame = cf:Lerp(CFrame.lookAt(cf.Position, target.Position), S.aimStrength) end end end ---------------------------------------------------------------- -- FOV (personnalise + zoom) ---------------------------------------------------------------- local fovTouched = false local function updateFov() local zoom = S.zoomOn and UIS:GetFocusedTextBox() == nil and UIS:IsKeyDown(Enum.KeyCode.C) local goal = nil if zoom then goal = S.zoomFov elseif S.customFov then goal = S.fov end if goal then fovTouched = true elseif fovTouched then goal = origFov else return end local cur = camera.FieldOfView local nxt = cur + (goal - cur) * 0.3 if math.abs(goal - nxt) < 0.1 then nxt = goal if not (zoom or S.customFov) then fovTouched = false end end camera.FieldOfView = nxt end ---------------------------------------------------------------- -- FREECAM ---------------------------------------------------------------- local fcPos, fcPitch, fcYaw = Vector3.zero, 0, 0 local fcAnchored = false local function stepFreecam(dt) if UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton2) then UIS.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition local d = UIS:GetMouseDelta() fcYaw -= d.X * 0.0035 * S.freecamSens fcPitch = math.clamp(fcPitch - d.Y * 0.0035 * S.freecamSens, -1.5, 1.5) else UIS.MouseBehavior = Enum.MouseBehavior.Default end local rot = CFrame.fromOrientation(fcPitch, fcYaw, 0) local move = Vector3.zero if UIS:GetFocusedTextBox() == nil then if UIS:IsKeyDown(Enum.KeyCode.W) then move += rot.LookVector end if UIS:IsKeyDown(Enum.KeyCode.S) then move -= rot.LookVector end if UIS:IsKeyDown(Enum.KeyCode.D) then move += rot.RightVector end if UIS:IsKeyDown(Enum.KeyCode.A) then move -= rot.RightVector end if UIS:IsKeyDown(Enum.KeyCode.Space) then move += Vector3.yAxis end if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then move -= Vector3.yAxis end end if move.Magnitude > 0 then local speed = S.freecamSpeed * (UIS:IsKeyDown(Enum.KeyCode.LeftControl) and 3 or 1) fcPos += move.Unit * speed * dt end camera.CFrame = CFrame.new(fcPos) * rot end local function stopFreecam() pcall(function() RunService:UnbindFromRenderStep("NovaFreecam") end) UIS.MouseBehavior = Enum.MouseBehavior.Default local _, root, hum = getChar() if root and fcAnchored then root.Anchored = false end fcAnchored = false camera.CameraType = Enum.CameraType.Custom if hum then camera.CameraSubject = hum end end local function startFreecam() stopFreecam() local cf = camera.CFrame fcPos = cf.Position fcPitch, fcYaw = cf:ToOrientation() if S.freecamFreeze then local _, root = getChar() if root then root.Anchored = true fcAnchored = true end end camera.CameraType = Enum.CameraType.Scriptable RunService:BindToRenderStep("NovaFreecam", Enum.RenderPriority.Camera.Value + 2, stepFreecam) end local function setFreecam(v) S.freecam = v if v then startFreecam() else stopFreecam() end if render then render() end end RunService:BindToRenderStep("NovaOverlay", Enum.RenderPriority.Camera.Value + 1, function() updateESP() updateAim() updateFov() end) ---------------------------------------------------------------- -- VIEWE / HUD / MONDE ---------------------------------------------------------------- local chH = new("Frame", { AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), BorderSizePixel = 0, BackgroundColor3 = WHITE, Visible = false, }, espGui) local chV = new("Frame", { AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), BorderSizePixel = 0, BackgroundColor3 = WHITE, Visible = false, }, espGui) local function updateCrosshair() chH.Visible, chV.Visible = S.crosshair, S.crosshair chH.Size = UDim2.fromOffset(S.crossSize * 2, 2) chV.Size = UDim2.fromOffset(2, S.crossSize * 2) end local origLight = { Brightness = Lighting.Brightness, Ambient = Lighting.Ambient, OutdoorAmbient = Lighting.OutdoorAmbient, GlobalShadows = Lighting.GlobalShadows, FogEnd = Lighting.FogEnd, FogStart = Lighting.FogStart, } local function applyLighting() if S.fullbright then Lighting.Brightness = 2 Lighting.Ambient = Color3.fromRGB(190, 190, 190) Lighting.OutdoorAmbient = Color3.fromRGB(190, 190, 190) Lighting.GlobalShadows = false else Lighting.Brightness = origLight.Brightness Lighting.Ambient = origLight.Ambient Lighting.OutdoorAmbient = origLight.OutdoorAmbient Lighting.GlobalShadows = origLight.GlobalShadows end if S.noFog then Lighting.FogEnd = 1e6 else Lighting.FogEnd = origLight.FogEnd Lighting.FogStart = origLight.FogStart end end local function otherPlayerNames() local names = {} for _, p in ipairs(Players:GetPlayers()) do if p ~= player then table.insert(names, p.Name) end end return names end local function setSpectate(v) if v then local p = S.target and Players:FindFirstChild(S.target) local h = p and p.Character and p.Character:FindFirstChildOfClass("Humanoid") if h then camera.CameraSubject = h else S.spectate = false end else local _, _, h = getChar() if h then camera.CameraSubject = h end end end connect(player.CharacterAdded, function() S.spectate = false if S.freecam then S.freecam = false stopFreecam() end if S.fly then S.fly = false stopFly() end if render then render() end end) ---------------------------------------------------------------- -- UI : CONSTRUCTION ---------------------------------------------------------------- local W, BANNER_H, TITLE_H, TAB_H, ROW_H, VISIBLE, FOOT_H = 380, 110, 34, 40, 44, 7, 40 local TITLE_Y = BANNER_H + 3 local TAB_Y = TITLE_Y + TITLE_H local LIST_Y = TAB_Y + TAB_H local LIST_H = ROW_H * VISIBLE local FOOT_Y = LIST_Y + LIST_H local H = FOOT_Y + FOOT_H local ROW_W = W - 24 local main = new("Frame", { Name = "Main", Size = UDim2.fromOffset(W, H), AnchorPoint = Vector2.new(0, 0.5), Position = UDim2.new(0, 30, 0.5, 0), BackgroundColor3 = Color3.fromRGB(6, 6, 8), BorderSizePixel = 0, ClipsDescendants = true, Active = true, Draggable = true, }, gui) new("UICorner", { CornerRadius = UDim.new(0, 14) }, main) local mainStroke = new("UIStroke", { Thickness = 2 }, main) local uiScale = new("UIScale", { Scale = 1 }, main) -- banniere local banner = new("Frame", { Size = UDim2.new(1, 0, 0, BANNER_H), BackgroundColor3 = WHITE, BorderSizePixel = 0 }, main) local bannerGrad = new("UIGradient", { Offset = Vector2.new(-0.3, 0) }, banner) if BANNER_IMAGE ~= "" then new("ImageLabel", { Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, Image = BANNER_IMAGE, ScaleType = Enum.ScaleType.Crop, }, banner) end local bannerTitle = new("TextLabel", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 66), Position = UDim2.fromOffset(0, 12), Font = Enum.Font.GothamBlack, TextSize = 54, Text = "NOVA", TextColor3 = WHITE, }, banner) local bannerStroke = new("UIStroke", { Thickness = 2.5 }, bannerTitle) new("TextLabel", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 20), Position = UDim2.fromOffset(0, 78), Font = Enum.Font.GothamMedium, TextSize = 14, Text = "M E N U", TextColor3 = WHITE, TextTransparency = 0.15, }, banner) TweenService:Create(bannerGrad, TweenInfo.new(3, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true), { Offset = Vector2.new(0.3, 0) }):Play() local accentLine = new("Frame", { Size = UDim2.new(1, 0, 0, 3), Position = UDim2.fromOffset(0, BANNER_H), BorderSizePixel = 0 }, main) -- titre de section local titleLabel = new("TextLabel", { Size = UDim2.new(1, 0, 0, TITLE_H), Position = UDim2.fromOffset(0, TITLE_Y), BackgroundColor3 = BLACK, BorderSizePixel = 0, Font = Enum.Font.GothamBold, TextSize = 18, TextColor3 = WHITE, Text = "MAIN", }, main) -- onglets local TAB_NAMES = { "MAIN", "MISC", "SETTINGS" } local tabButtons = {} for i, name in ipairs(TAB_NAMES) do local btn = new("TextButton", { Size = UDim2.new(1 / 3, 0, 0, TAB_H), Position = UDim2.new((i - 1) / 3, 0, 0, TAB_Y), BorderSizePixel = 0, AutoButtonColor = false, Font = Enum.Font.GothamBold, TextSize = 16, Text = name, }, main) local line = new("Frame", { Size = UDim2.new(1, 0, 0, 3), Position = UDim2.new(0, 0, 1, -3), BorderSizePixel = 0 }, btn) tabButtons[i] = { btn = btn, line = line } end local function badge(text, x) local f = new("Frame", { Size = UDim2.fromOffset(26, 26), Position = UDim2.fromOffset(x, TAB_Y + 7), BackgroundColor3 = Color3.fromRGB(40, 40, 46), BorderSizePixel = 0, ZIndex = 3, }, main) new("UICorner", { CornerRadius = UDim.new(0, 6) }, f) new("TextLabel", { Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, Text = text, Font = Enum.Font.GothamBold, TextSize = 14, TextColor3 = Color3.fromRGB(190, 190, 190), ZIndex = 4, }, f) end badge("Q", 8) badge("E", W - 34) -- liste local listFrame = new("Frame", { Size = UDim2.fromOffset(W, LIST_H), Position = UDim2.fromOffset(0, LIST_Y), BackgroundColor3 = BLACK, BorderSizePixel = 0, ClipsDescendants = true, }, main) local track = new("Frame", { Size = UDim2.fromOffset(5, LIST_H - 8), Position = UDim2.fromOffset(7, 4), BackgroundColor3 = Color3.fromRGB(28, 28, 32), BorderSizePixel = 0, }, listFrame) new("UICorner", { CornerRadius = UDim.new(1, 0) }, track) local thumb = new("Frame", { Size = UDim2.fromScale(1, 1), BorderSizePixel = 0 }, track) new("UICorner", { CornerRadius = UDim.new(1, 0) }, thumb) local rows = {} local rowHandlers = {} for i = 1, VISIBLE do local r = {} r.frame = new("TextButton", { Size = UDim2.fromOffset(ROW_W, ROW_H), Position = UDim2.fromOffset(18, (i - 1) * ROW_H), BorderSizePixel = 0, AutoButtonColor = false, Text = "", }, listFrame) r.icon = new("TextLabel", { Size = UDim2.fromOffset(30, ROW_H), Position = UDim2.fromOffset(12, 0), BackgroundTransparency = 1, Font = Enum.Font.Gotham, TextSize = 20, Text = "", }, r.frame) r.name = new("TextLabel", { Size = UDim2.fromOffset(250, ROW_H), Position = UDim2.fromOffset(52, 0), BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 17, TextXAlignment = Enum.TextXAlignment.Left, Text = "", }, r.frame) r.value = new("TextLabel", { Size = UDim2.fromOffset(64, ROW_H), Position = UDim2.fromOffset(214, 0), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 15, TextColor3 = Color3.fromRGB(210, 210, 215), TextXAlignment = Enum.TextXAlignment.Right, Text = "", }, r.frame) r.pill = new("Frame", { Size = UDim2.fromOffset(54, 24), Position = UDim2.fromOffset(ROW_W - 14 - 54, ROW_H / 2 - 12), BorderSizePixel = 0, }, r.frame) new("UICorner", { CornerRadius = UDim.new(0, 8) }, r.pill) r.pillText = new("TextLabel", { Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 13, TextColor3 = WHITE, Text = "", }, r.pill) r.track = new("Frame", { Size = UDim2.fromOffset(58, 4), Position = UDim2.fromOffset(ROW_W - 14 - 58, ROW_H / 2 - 2), BackgroundColor3 = Color3.fromRGB(50, 50, 56), BorderSizePixel = 0, }, r.frame) new("UICorner", { CornerRadius = UDim.new(1, 0) }, r.track) r.fill = new("Frame", { Size = UDim2.fromScale(0.5, 1), BorderSizePixel = 0 }, r.track) new("UICorner", { CornerRadius = UDim.new(1, 0) }, r.fill) r.arrow = new("TextLabel", { Size = UDim2.fromOffset(24, ROW_H), Position = UDim2.fromOffset(ROW_W - 14 - 24, 0), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 18, TextColor3 = WHITE, Text = ">", }, r.frame) rows[i] = r end -- pied de page local foot = new("Frame", { Size = UDim2.fromOffset(W, FOOT_H), Position = UDim2.fromOffset(0, FOOT_Y), BackgroundColor3 = Color3.fromRGB(14, 14, 17), BorderSizePixel = 0, }, main) local footLine = new("Frame", { Size = UDim2.new(1, 0, 0, 2), BorderSizePixel = 0 }, foot) local footLogo = new("TextLabel", { Size = UDim2.fromOffset(30, FOOT_H), Position = UDim2.fromOffset(14, 0), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 20, Text = "⚡", }, foot) new("TextLabel", { Size = UDim2.fromOffset(60, FOOT_H), Position = UDim2.fromOffset(46, 0), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 17, TextColor3 = WHITE, TextXAlignment = Enum.TextXAlignment.Left, Text = "v1.0", }, foot) local fpsLabel = new("TextLabel", { Size = UDim2.fromOffset(100, FOOT_H), Position = UDim2.new(0.5, -50, 0, 0), BackgroundTransparency = 1, Font = Enum.Font.Gotham, TextSize = 13, TextColor3 = Color3.fromRGB(150, 150, 160), Text = "", }, foot) local indexLabel = new("TextLabel", { Size = UDim2.fromOffset(80, FOOT_H), Position = UDim2.new(1, -94, 0, 0), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 18, TextColor3 = WHITE, TextXAlignment = Enum.TextXAlignment.Right, Text = "1/1", }, foot) ---------------------------------------------------------------- -- MENUS : DEFINITIONS ---------------------------------------------------------------- local registry = {} -- tous les reglages (pour les configs) local applyingConfig = false local function reg(key, it) registry[key] = it return it end local function T(name, icon, key, cb) return reg(key, { type = "toggle", name = name, icon = icon, get = function() return S[key] end, set = function(v) S[key] = v if cb then cb(v) end end, }) end local function N(name, icon, key, min, max, step, cb, fmt) return reg(key, { type = "slider", name = name, icon = icon, min = min, max = max, step = step, fmt = fmt or "%d", get = function() return S[key] end, set = function(v) S[key] = v if cb then cb(v) end end, }) end local function L(name, icon, key, options, cb) return reg(key, { type = "list", name = name, icon = icon, options = options, get = function() return S[key] end, set = function(v) S[key] = v if cb then cb(v) end end, }) end local function B(name, icon, fn) return { type = "button", name = name, icon = icon, run = fn } end local function M(name, icon, title, items) return { type = "menu", name = name, icon = icon, menu = { title = title, items = items } } end local function I(name, icon, textfn) return { type = "info", name = name, icon = icon, text = textfn } end local function resetMovement() S.customSpeed, S.customJump = false, false local _, _, h = getChar() if h then h.WalkSpeed = 16 h.UseJumpPower = true h.JumpPower = 50 end end local selfMenu = M("Self", "👤", "Self", { T("Fly (F)", "🕊", "fly", function(v) if v then startFly() else stopFly() end end), N("Fly speed", "💨", "flySpeed", 10, 300, 10), T("Noclip", "👻", "noclip"), T("Custom speed", "⚡", "customSpeed", function(v) if not v then local _, _, h = getChar() if h then h.WalkSpeed = 16 end end end), N("Walk speed", "🏃", "walkSpeed", 16, 300, 4), T("Custom jump", "🦘", "customJump", function(v) if not v then local _, _, h = getChar() if h then h.UseJumpPower = true h.JumpPower = 50 end end end), N("Jump power", "⬆", "jumpPower", 50, 500, 10), T("Infinite jump", "♾", "infJump"), T("Click TP (Ctrl+Click)", "📍", "clickTP"), T("Spin", "🌀", "spin"), N("Spin speed", "🔄", "spinSpeed", 1, 60, 1), }) local visualMenu = M("Visual", "👁", "Visual", { M("ESP", "🔎", "ESP", { T("Enable ESP", "👁", "esp"), T("Box", "⬜", "espBox"), T("Skeleton", "💀", "espSkeleton"), T("Names", "🏷", "espName"), T("Distance", "📏", "espDistance"), T("Health bar", "❤", "espHealth"), T("Tracers", "➖", "espTracer"), T("Chams", "✨", "espChams"), T("Team check", "🛡", "espTeamCheck"), T("Team colors", "🎨", "espTeamColors"), L("ESP color", "🌈", "espColor", ESP_COLOR_NAMES), N("Max distance", "↔", "espMaxDist", 100, 5000, 100), }), M("HUD", "🖥", "HUD", { T("Crosshair", "➕", "crosshair", updateCrosshair), N("Crosshair size", "📐", "crossSize", 4, 40, 2, updateCrosshair), }), }) local onlineMenu = M("Online", "👥", "Online", { I("Players", "👥", function() return #Players:GetPlayers() .. "/" .. Players.MaxPlayers end), L("Player", "🧍", "target", otherPlayerNames), B("TP to player", "📍", function() local p = S.target and Players:FindFirstChild(S.target) local tr = p and p.Character and p.Character:FindFirstChild("HumanoidRootPart") local _, root = getChar() if tr and root then root.CFrame = tr.CFrame * CFrame.new(0, 0, 3) end end), T("Spectate player", "📺", "spectate", setSpectate), }) local combatMenu = M("Combat", "🎯", "Combat", { T("Aim assist", "🎯", "aim"), L("Hold key", "🖱", "aimKey", { "Right Click", "Left Click", "Left Alt", "Always" }), L("Target part", "🧠", "aimPart", { "Head", "Torso" }), N("FOV size", "⭕", "aimFov", 50, 500, 25), T("Show FOV circle", "◯", "aimShowFov"), N("Strength", "💪", "aimStrength", 0.05, 1, 0.05, nil, "%.2f"), T("Wall check", "🧱", "aimWall"), T("Team check", "🛡", "aimTeam"), N("Max distance", "↔", "aimMaxDist", 100, 3000, 100), }) local worldMenu = M("World", "🌍", "World", { T("Fullbright", "💡", "fullbright", applyLighting), T("No fog", "🌫", "noFog", applyLighting), N("Time of day", "🕒", "clock", 0, 24, 1, function(v) Lighting.ClockTime = v end), N("Gravity", "🪐", "gravity", 0, 400, 10, function(v) workspace.Gravity = v end), T("Unlimited zoom", "🔭", "zoom", function(v) player.CameraMaxZoomDistance = v and 2000 or origZoom end), }) -- Give items : necessite NovaServer.lua (Script dans ServerScriptService) local itemNames, itemStatus = {}, "Not loaded" local function refreshItems() local rf = ReplicatedStorage:FindFirstChild("NovaList") if not rf then itemNames, itemStatus = {}, "No server" return end local ok, res = pcall(function() return rf:InvokeServer() end) if ok and type(res) == "table" then itemNames = res itemStatus = #res .. " items" if not S.item or not table.find(res, S.item) then S.item = res[1] end else itemStatus = "Error" end end local function fireItems(action, name) local ev = ReplicatedStorage:FindFirstChild("NovaGive") if ev then ev:FireServer(action, name) else itemStatus = "No server" end end local toolsMenu = M("Items", "🧰", "Items & Tools", { I("Status", "ℹ", function() return itemStatus end), L("Item", "📦", "item", function() return itemNames end), B("Give item", "🎁", function() if S.item then fireItems("give", S.item) end end), B("Give all items", "🎁", function() fireItems("giveAll") end), B("Clear tools", "🗑", function() fireItems("clear") end), B("Refresh list", "🔄", function() task.spawn(function() refreshItems() render() end) end), B("Equip next tool", "🗡", function() local _, _, h = getChar() local bp = player:FindFirstChildOfClass("Backpack") local t = bp and bp:FindFirstChildOfClass("Tool") if h and t then h:EquipTool(t) end end), B("Unequip tools", "🎒", function() local _, _, h = getChar() if h then h:UnequipTools() end end), }) local cameraMenu = M("Camera", "📷", "Camera", { T("Freecam (G)", "📷", "freecam", function(v) if v then startFreecam() else stopFreecam() end end), N("Freecam speed", "🚀", "freecamSpeed", 10, 500, 10), N("Sensitivity", "🖱", "freecamSens", 0.1, 3, 0.1, nil, "%.1f"), T("Freeze character", "🧊", "freecamFreeze"), T("Custom FOV", "🎥", "customFov"), N("Field of view", "🔭", "fov", 20, 120, 2, function() if not applyingConfig then S.customFov = true end end), T("Zoom key (C)", "🔍", "zoomOn"), N("Zoom FOV", "🎯", "zoomFov", 10, 60, 5), B("Reset FOV", "♻", function() S.customFov = false S.fov = math.floor(origFov + 0.5) end), }) local mainRoot = { title = "Main", items = { selfMenu, visualMenu, cameraMenu, onlineMenu, combatMenu, worldMenu, toolsMenu } } local miscRoot = { title = "Misc", items = { B("Respawn", "💥", function() local c = player.Character if c then c:BreakJoints() end end), B("Sit", "🪑", function() local _, _, h = getChar() if h then h.Sit = true end end), B("Reset speed / jump", "♻", resetMovement), T("Anti-AFK", "⏱", "antiAfk"), B("Rejoin server", "🔁", function() pcall(function() TeleportService:Teleport(game.PlaceId, player) end) end), } } ---------------------------------------------------------------- -- CONFIGS (slots + export / import JSON) ---------------------------------------------------------------- local SLOT_NAMES = { "Slot 1", "Slot 2", "Slot 3", "Slot 4", "Slot 5" } local EXCLUDED = { fly = true, freecam = true, spectate = true, target = true, item = true, cfgSlot = true, cfgAuto = true } local sessionSlots, defaults = {}, {} local cfgStatus = "Ready" local function serializeConfig() local data = {} for k in pairs(registry) do if not EXCLUDED[k] then data[k] = S[k] end end return data end local function applyConfig(data) applyingConfig = true for k, v in pairs(data) do local item = registry[k] if item and not EXCLUDED[k] and type(v) == type(S[k]) then local okValue = true if item.type == "slider" then v = math.clamp(v, item.min, item.max) elseif item.type == "list" and type(item.options) == "table" and not table.find(item.options, v) then okValue = false end if okValue then pcall(item.set, v) end end end applyingConfig = false render() end local function callConfig(action, slot, data) local rf = ReplicatedStorage:FindFirstChild("NovaConfig") if not rf then return false end local ok, res = pcall(function() return rf:InvokeServer(action, slot, data) end) return ok and res end local function saveConfig() local slot, data = S.cfgSlot, serializeConfig() sessionSlots[slot] = data cfgStatus = "Saved (local)" render() task.spawn(function() if callConfig("save", slot, data) == true then cfgStatus = "Saved (server)" end render() end) end local function loadConfig() task.spawn(function() local slot = S.cfgSlot local data = sessionSlots[slot] if not data then local prof = callConfig("get") if type(prof) == "table" and type(prof.slots) == "table" then data = prof.slots[slot] end end if type(data) == "table" then applyConfig(data) cfgStatus = "Loaded" else cfgStatus = "Empty slot" end render() end) end local function deleteConfig() local slot = S.cfgSlot sessionSlots[slot] = nil cfgStatus = "Deleted" render() task.spawn(function() callConfig("delete", slot) end) end local function resetDefaults() applyConfig(defaults) cfgStatus = "Defaults" render() end -- panneau texte (export / import) local panelOpen = false local panel = new("Frame", { Size = UDim2.fromOffset(330, 230), Position = UDim2.new(0, 30 + W + 14, 0.5, -115), BackgroundColor3 = Color3.fromRGB(10, 10, 13), BorderSizePixel = 0, Visible = false, Active = true, Draggable = true, }, gui) new("UICorner", { CornerRadius = UDim.new(0, 12) }, panel) local panelStroke = new("UIStroke", { Thickness = 2 }, panel) local panelTitle = new("TextLabel", { Size = UDim2.new(1, -20, 0, 30), Position = UDim2.fromOffset(10, 4), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 13, TextColor3 = WHITE, TextXAlignment = Enum.TextXAlignment.Left, Text = "", }, panel) local panelBox = new("TextBox", { Size = UDim2.new(1, -20, 1, -90), Position = UDim2.fromOffset(10, 36), BackgroundColor3 = Color3.fromRGB(22, 22, 28), BorderSizePixel = 0, ClearTextOnFocus = false, MultiLine = true, TextWrapped = true, TextEditable = true, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, Font = Enum.Font.Code, TextSize = 12, TextColor3 = WHITE, PlaceholderText = "Paste JSON here", Text = "", }, panel) new("UICorner", { CornerRadius = UDim.new(0, 8) }, panelBox) local function updatePanel() panel.Visible = panelOpen and menuOpen panelStroke.Color = THEMES[S.theme] end local function importJson(text) local ok, data = pcall(function() return HttpService:JSONDecode(text) end) if ok and type(data) == "table" then applyConfig(data) cfgStatus = "Imported" else cfgStatus = "Invalid JSON" end render() end local lastCode = nil local panelMode = "import" local loadByCode -- declaration anticipee local function panelButton(text, x, w, fn) local b = new("TextButton", { Size = UDim2.fromOffset(w, 32), Position = UDim2.new(0, x, 1, -42), BackgroundColor3 = Color3.fromRGB(40, 40, 48), BorderSizePixel = 0, Font = Enum.Font.GothamBold, TextSize = 14, TextColor3 = WHITE, Text = text, }, panel) new("UICorner", { CornerRadius = UDim.new(0, 8) }, b) b.Activated:Connect(fn) return b end local applyBtn = panelButton("Apply", 10, 150, function() if panelMode == "import" then importJson(panelBox.Text) elseif panelMode == "code" then loadByCode(panelBox.Text) end end) panelButton("Close", 170, 150, function() panelOpen = false updatePanel() end) local function openPanel(mode) panelOpen = true panelMode = mode applyBtn.Visible = (mode == "import" or mode == "code") applyBtn.Text = mode == "code" and "Load" or "Apply" if mode == "export" then panelTitle.Text = "EXPORT - Ctrl+A puis Ctrl+C pour copier" panelBox.Text = HttpService:JSONEncode(serializeConfig()) elseif mode == "showcode" then panelTitle.Text = "YOUR CODE - copie-le (Ctrl+A, Ctrl+C)" panelBox.Text = lastCode or "" elseif mode == "code" then panelTitle.Text = "ENTER CODE (ex : NOVA-7K2P9X) puis Load" panelBox.Text = "" else panelTitle.Text = "IMPORT - colle le JSON puis Apply" panelBox.Text = "" end updatePanel() end -- codes : sauvegarde en ligne (DataStore via NovaServer.lua) local function saveCode() cfgStatus = "Saving..." render() task.spawn(function() local res = callConfig("codeSave", nil, serializeConfig()) if type(res) == "string" then lastCode = res cfgStatus = "Code ready" openPanel("showcode") else cfgStatus = "Save failed" end render() end) end loadByCode = function(text) cfgStatus = "Loading..." render() task.spawn(function() local res = callConfig("codeLoad", text) if type(res) == "table" then applyConfig(res) cfgStatus = "Code loaded" panelOpen = false updatePanel() elseif res == "notfound" then cfgStatus = "Invalid code" else cfgStatus = "No server" end render() end) end local unload -- declaration anticipee local settingsRoot = { title = "Settings", items = { L("Theme", "🎨", "theme", THEME_NAMES), N("Menu scale", "🔍", "scale", 0.7, 1.3, 0.1, nil, "%.1f"), T("Show FPS", "📊", "showFps"), M("Config", "💾", "Config", { I("Status", "ℹ", function() return cfgStatus end), B("Save as code", "🔑", saveCode), B("Load from code", "🔓", function() openPanel("code") end), I("Last code", "🏷", function() return lastCode or "—" end), L("Slot", "📁", "cfgSlot", SLOT_NAMES), B("Save config", "💾", saveConfig), B("Load config", "📂", loadConfig), B("Delete config", "🗑", deleteConfig), T("Auto-load slot", "⏩", "cfgAuto", function(v) local slot = S.cfgSlot task.spawn(function() callConfig("autoload", v and slot or nil) end) end), B("Export (JSON)", "📤", function() openPanel("export") end), B("Import (JSON)", "📥", function() openPanel("import") end), B("Reset defaults", "♻", resetDefaults), }), M("Controls", "⌨", "Controls", { I("Up / Down", "↕", function() return "Navigate" end), I("Left / Right", "↔", function() return "Change value" end), I("Enter", "⏎", function() return "Select" end), I("Backspace", "⌫", function() return "Back" end), I("Q / E", "🗂", function() return "Switch tab" end), I("Insert / M", "👁", function() return "Show / hide" end), I("F", "🕊", function() return "Fly" end), I("G", "📷", function() return "Freecam" end), I("Hold C", "🔍", function() return "Zoom" end), I("Freecam", "🎮", function() return "WASD + RMB" end), }), B("Unload menu", "⛔", function() unload() end), } } ---------------------------------------------------------------- -- NAVIGATION ---------------------------------------------------------------- local tabRoots = { mainRoot, miscRoot, settingsRoot } local tabStacks = {} for i, root in ipairs(tabRoots) do tabStacks[i] = { { menu = root, index = 1, scroll = 0 } } end local currentTab = 1 local function top() local st = tabStacks[currentTab] return st[#st] end local function getItems(menu) if type(menu.items) == "function" then return menu.items() end return menu.items end local function cycle(item, dir) local opts = type(item.options) == "function" and item.options() or item.options if #opts == 0 then return end local idx = table.find(opts, item.get()) or 0 idx = ((idx - 1 + dir) % #opts) + 1 item.set(opts[idx]) end local function adjust(item, dir) if item.type == "slider" then local v = item.get() + dir * item.step v = math.floor(v / item.step + 0.5) * item.step v = math.clamp(v, item.min, item.max) item.set(tonumber(string.format("%.4f", v))) elseif item.type == "list" then cycle(item, dir) elseif item.type == "toggle" then item.set(not item.get()) end end local function currentItem() local cur = top() return getItems(cur.menu)[cur.index] end local function activate() local item = currentItem() if not item then return end local t = item.type if t == "toggle" then item.set(not item.get()) elseif t == "menu" then table.insert(tabStacks[currentTab], { menu = item.menu, index = 1, scroll = 0 }) elseif t == "button" then item.run() elseif t == "list" then cycle(item, 1) end render() end local function back() local st = tabStacks[currentTab] if #st > 1 then table.remove(st) end render() end local function move(dir) local cur = top() local total = #getItems(cur.menu) if total == 0 then return end local idx = cur.index + dir if idx < 1 then idx = total elseif idx > total then idx = 1 end cur.index = idx render() end local function changeValue(dir) local item = currentItem() if not item then return end if item.type == "menu" then if dir > 0 then activate() else back() end return end adjust(item, dir) render() end local function switchTab(dir) currentTab = ((currentTab - 1 + dir) % #TAB_NAMES) + 1 render() end ---------------------------------------------------------------- -- RENDU ---------------------------------------------------------------- render = function() local acc = THEMES[S.theme] mainStroke.Color = acc bannerStroke.Color = acc bannerGrad.Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, Color3.fromRGB(8, 8, 10)), ColorSequenceKeypoint.new(1, acc), }) accentLine.BackgroundColor3 = acc footLine.BackgroundColor3 = acc thumb.BackgroundColor3 = acc footLogo.TextColor3 = acc uiScale.Scale = S.scale for i, tb in ipairs(tabButtons) do local active = i == currentTab tb.btn.BackgroundColor3 = active and acc:Lerp(BLACK, 0.7) or BLACK tb.btn.TextColor3 = active and WHITE or Color3.fromRGB(190, 190, 190) tb.line.Visible = active tb.line.BackgroundColor3 = acc end local cur = top() local items = getItems(cur.menu) local total = #items cur.index = math.clamp(cur.index, 1, math.max(total, 1)) if cur.index <= cur.scroll then cur.scroll = cur.index - 1 end if cur.index > cur.scroll + VISIBLE then cur.scroll = cur.index - VISIBLE end cur.scroll = math.clamp(cur.scroll, 0, math.max(total - VISIBLE, 0)) titleLabel.Text = string.upper(cur.menu.title) indexLabel.Text = cur.index .. "/" .. total for i = 1, VISIBLE do local r = rows[i] local item = items[cur.scroll + i] if not item then r.frame.Visible = false else local sel = (cur.scroll + i) == cur.index r.frame.Visible = true r.frame.BackgroundColor3 = acc:Lerp(BLACK, 0.62) r.frame.BackgroundTransparency = sel and 0 or 1 r.icon.Text = item.icon or "•" r.name.Text = item.name r.name.TextColor3 = sel and WHITE or Color3.fromRGB(215, 215, 220) r.value.Visible, r.pill.Visible, r.track.Visible, r.arrow.Visible = false, false, false, false r.name.Size = UDim2.fromOffset(250, ROW_H) r.value.Position = UDim2.fromOffset(214, 0) r.value.Size = UDim2.fromOffset(64, ROW_H) local t = item.type if t == "toggle" then local on = item.get() r.pill.Visible = true r.pill.BackgroundColor3 = on and acc or Color3.fromRGB(45, 45, 50) r.pillText.Text = on and "ON" or "OFF" elseif t == "slider" then local v = item.get() r.name.Size = UDim2.fromOffset(160, ROW_H) r.value.Visible = true r.value.Text = string.format(item.fmt, v) r.track.Visible = true r.fill.BackgroundColor3 = acc r.fill.Size = UDim2.fromScale(math.clamp((v - item.min) / (item.max - item.min), 0, 1), 1) elseif t == "list" then r.name.Size = UDim2.fromOffset(148, ROW_H) r.value.Visible = true r.value.Position = UDim2.fromOffset(200, 0) r.value.Size = UDim2.fromOffset(142, ROW_H) r.value.Text = "‹ " .. tostring(item.get() or "—") .. " ›" elseif t == "menu" then r.arrow.Visible = true r.arrow.Text = ">" elseif t == "button" then r.arrow.Visible = true r.arrow.Text = "▶" elseif t == "info" then r.name.Size = UDim2.fromOffset(160, ROW_H) r.value.Visible = true r.value.Position = UDim2.fromOffset(200, 0) r.value.Size = UDim2.fromOffset(142, ROW_H) r.value.Text = item.text() end end end local frac = total > VISIBLE and (VISIBLE / total) or 1 thumb.Size = UDim2.fromScale(1, frac) thumb.Position = UDim2.fromScale(0, total > 0 and cur.scroll / total or 0) end -- clics souris for i = 1, VISIBLE do rows[i].frame.Activated:Connect(function() local cur = top() cur.index = cur.scroll + i activate() end) end for i, tb in ipairs(tabButtons) do tb.btn.Activated:Connect(function() currentTab = i render() end) end ---------------------------------------------------------------- -- CLAVIER ---------------------------------------------------------------- local actions = { [Enum.KeyCode.Up] = function() move(-1) end, [Enum.KeyCode.Down] = function() move(1) end, [Enum.KeyCode.Left] = function() changeValue(-1) end, [Enum.KeyCode.Right] = function() changeValue(1) end, [Enum.KeyCode.Return] = activate, [Enum.KeyCode.KeypadEnter] = activate, [Enum.KeyCode.Backspace] = back, [Enum.KeyCode.Q] = function() switchTab(-1) end, [Enum.KeyCode.E] = function() switchTab(1) end, } local repeatable = { [Enum.KeyCode.Up] = true, [Enum.KeyCode.Down] = true, [Enum.KeyCode.Left] = true, [Enum.KeyCode.Right] = true, } local heldToken = 0 local function startRepeat(fn) heldToken += 1 local token = heldToken task.spawn(function() task.wait(0.35) while heldToken == token and menuOpen and not unloaded do fn() task.wait(0.06) end end) end local function onNav(_, state, input) if not menuOpen then return Enum.ContextActionResult.Pass end if state == Enum.UserInputState.Begin then local fn = actions[input.KeyCode] if fn then fn() if repeatable[input.KeyCode] then startRepeat(fn) end end else heldToken += 1 end return Enum.ContextActionResult.Sink end local navKeys = {} for key in pairs(actions) do table.insert(navKeys, key) end CAS:BindActionAtPriority("NovaNav", onNav, false, Enum.ContextActionPriority.High.Value, table.unpack(navKeys)) local function toggleMenu() menuOpen = not menuOpen main.Visible = menuOpen updatePanel() heldToken += 1 end connect(UIS.InputBegan, function(input, processed) if processed then return end if input.UserInputType == Enum.UserInputType.MouseButton1 then if S.clickTP and UIS:IsKeyDown(Enum.KeyCode.LeftControl) then local _, root = getChar() if root and mouse.Hit then root.CFrame = CFrame.new(mouse.Hit.Position + Vector3.new(0, 3, 0)) end end elseif input.KeyCode == Enum.KeyCode.F then setFly(not S.fly) elseif input.KeyCode == Enum.KeyCode.G then setFreecam(not S.freecam) elseif input.KeyCode == Enum.KeyCode.Insert or input.KeyCode == Enum.KeyCode.M then toggleMenu() end end) ---------------------------------------------------------------- -- FPS ---------------------------------------------------------------- local fpsAcc, fpsFrames = 0, 0 connect(RunService.RenderStepped, function(dt) fpsAcc += dt fpsFrames += 1 if fpsAcc >= 0.5 then fpsLabel.Text = S.showFps and (math.floor(fpsFrames / fpsAcc + 0.5) .. " FPS") or "" fpsAcc, fpsFrames = 0, 0 end end) ---------------------------------------------------------------- -- DECHARGER ---------------------------------------------------------------- unload = function() unloaded = true if S.freecam then S.freecam = false stopFreecam() end setFly(false) S.noclip, S.spin, S.esp, S.aim, S.fullbright, S.noFog = false, false, false, false, false, false if S.spectate then setSpectate(false) end resetMovement() applyLighting() workspace.Gravity = origGravity camera.FieldOfView = origFov player.CameraMaxZoomDistance = origZoom for plr in pairs(espData) do removeESP(plr) end RunService:UnbindFromRenderStep("NovaOverlay") CAS:UnbindAction("NovaNav") for _, c in ipairs(conns) do c:Disconnect() end gui:Destroy() espGui:Destroy() end ---------------------------------------------------------------- -- DEMARRAGE ---------------------------------------------------------------- for k in pairs(registry) do if not EXCLUDED[k] then defaults[k] = S[k] end end updateCrosshair() render() task.spawn(function() task.wait(2) if unloaded then return end refreshItems() local prof = callConfig("get") if type(prof) == "table" and prof.autoload and type(prof.slots) == "table" then local data = prof.slots[prof.autoload] if type(data) == "table" then S.cfgSlot = prof.autoload S.cfgAuto = true applyConfig(data) cfgStatus = "Loaded" end end render() end)