-- [[ Rscripts Risk Notice ]] -- This script is not verified by rscripts.net. Deal with caution. -- -- Stay safe: -- • Never log in on unofficial Roblox sites or lookalike domains. -- • Real Roblox links use roblox.com (check the .com ending). -- • Treat fake Roblox login / "claim reward" pages as phishing. -- [[ End Rscripts Risk Notice ]] --[[ CLIENT TRAINING FRAMEWORK v3.0 "POLISHED" Single LocalScript Place in: StarterPlayer > StarterPlayerScripts Main goals: - Modern, polished UI - Better module organization - Cached target registry - Throttled target acquisition - Centralized ESP renderer - Proper cleanup/unload - Respawn-safe movement modules - No external loaders ]] --================================================== -- SERVICES --================================================== local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local Lighting = game:GetService("Lighting") local TweenService = game:GetService("TweenService") local LocalPlayer = Players.LocalPlayer if not LocalPlayer then return end --================================================== -- STATE --================================================== local UNLOADED = false local Character = nil local Humanoid = nil local RootPart = nil local Camera = workspace.CurrentCamera local function RefreshCharacter() Character = LocalPlayer.Character Humanoid = Character and Character:FindFirstChildOfClass("Humanoid") or nil RootPart = Character and Character:FindFirstChild("HumanoidRootPart") or nil Camera = workspace.CurrentCamera end RefreshCharacter() --================================================== -- THEME --================================================== local THEME = { Background = Color3.fromRGB(10, 11, 15), Sidebar = Color3.fromRGB(15, 17, 22), Card = Color3.fromRGB(20, 22, 29), CardHover = Color3.fromRGB(27, 30, 39), Accent = Color3.fromRGB(95, 126, 255), AccentLight = Color3.fromRGB(132, 157, 255), AccentDark = Color3.fromRGB(65, 90, 190), Text = Color3.fromRGB(245, 246, 250), Secondary = Color3.fromRGB(175, 179, 192), Muted = Color3.fromRGB(103, 107, 121), Border = Color3.fromRGB(40, 43, 53), Green = Color3.fromRGB(82, 220, 125), Red = Color3.fromRGB(247, 82, 96), Yellow = Color3.fromRGB(255, 190, 76), Blue = Color3.fromRGB(84, 165, 255), } --================================================== -- CONFIG --================================================== local CONFIG = { Combat = { { ID="AimAssist", Name="Aim Assist", Type="Toggle", Desc="Smoothly follow the best target" }, { ID="AimSmooth", Name="Smoothness", Type="Slider", Min=1, Max=20, Default=8 }, { ID="AimFOV", Name="Aim FOV", Type="Slider", Min=50, Max=500, Default=180 }, { ID="FOVCircle", Name="FOV Circle", Type="Toggle", Desc="Display the target radius" }, { ID="TargetLock", Name="Target Lock", Type="Toggle", Desc="Keep the current target" }, { ID="TargetPlayers", Name="Target Players", Type="Toggle", Desc="Allow player characters" }, { ID="TargetNPCs", Name="Target NPCs", Type="Toggle", Desc="Allow NPC characters" }, { ID="TeamCheck", Name="Team Check", Type="Toggle", Desc="Ignore teammates" }, { ID="TriggerTool", Name="Training Trigger", Type="Toggle", Desc="Activate equipped tools over targets" }, }, Movement = { { ID="WalkSpeed", Name="WalkSpeed", Type="Toggle", Desc="Override local movement speed" }, { ID="WalkSpeedValue", Name="Speed", Type="Slider", Min=8, Max=100, Default=24 }, { ID="JumpPower", Name="JumpPower", Type="Toggle", Desc="Override local jump power" }, { ID="JumpPowerValue", Name="Jump", Type="Slider", Min=20, Max=150, Default=55 }, { ID="InfiniteJump", Name="Infinite Jump", Type="Toggle", Desc="Allow repeated jumping" }, { ID="Fly", Name="Fly", Type="Toggle", Desc="Client-side free movement" }, { ID="FlySpeed", Name="Fly Speed", Type="Slider", Min=10, Max=150, Default=45 }, { ID="Noclip", Name="Noclip", Type="Toggle", Desc="Disable local collisions" }, { ID="ClickTeleport", Name="Click Teleport", Type="Toggle", Desc="Ctrl + click to teleport" }, }, Visuals = { { ID="Fullbright", Name="Fullbright", Type="Toggle", Desc="Increase local scene visibility" }, { ID="ThirdPerson", Name="Third Person", Type="Toggle", Desc="Force third-person camera mode" }, { ID="CameraZoom", Name="Camera Zoom", Type="Toggle", Desc="Increase maximum zoom" }, { ID="CameraZoomValue", Name="Zoom Distance", Type="Slider", Min=10, Max=100, Default=30 }, }, ESP = { { ID="ESPEnabled", Name="ESP", Type="Toggle", Desc="Enable visual debug rendering" }, { ID="ESPBoxes", Name="Boxes", Type="Toggle", Desc="Draw 2D boxes" }, { ID="ESPNames", Name="Names", Type="Toggle", Desc="Display names" }, { ID="ESPDistance", Name="Distance", Type="Toggle", Desc="Display distance" }, { ID="ESPHealth", Name="Health", Type="Toggle", Desc="Display health bars" }, { ID="ESPTracers", Name="Tracers", Type="Toggle", Desc="Draw tracers from screen bottom" }, { ID="ESPNPC", Name="NPCs", Type="Toggle", Desc="Display NPCs" }, { ID="ESPTeamCheck", Name="Team Check", Type="Toggle", Desc="Hide teammates" }, { ID="ESPMaxDistance", Name="Max Distance", Type="Slider", Min=50, Max=2000, Default=500 }, }, Utility = { { ID="PerformanceMode", Name="Performance Mode", Type="Toggle", Desc="Lower renderer workload" }, { ID="ShowStats", Name="Performance Stats",Type="Toggle", Desc="Show FPS and target stats" }, { ID="MenuCompact", Name="Compact Menu", Type="Toggle", Desc="Use a tighter UI layout" }, }, } local TAB_ORDER = {"Combat", "Movement", "Visuals", "ESP", "Utility"} local TAB_ICONS = { Combat = "◈", Movement = "↗", Visuals = "◉", ESP = "□", Utility = "⚙", } --================================================== -- CONNECTION MANAGEMENT --================================================== local GLOBAL_CONNECTIONS = {} local function Track(connection) if connection then table.insert(GLOBAL_CONNECTIONS, connection) end return connection end local function DisconnectAll() for i = #GLOBAL_CONNECTIONS, 1, -1 do local connection = GLOBAL_CONNECTIONS[i] if connection then pcall(function() connection:Disconnect() end) end GLOBAL_CONNECTIONS[i] = nil end end --================================================== -- UTILITIES --================================================== local function Clamp(value, minValue, maxValue) return math.max(minValue, math.min(maxValue, value)) end local function GetCamera() Camera = workspace.CurrentCamera return Camera end local function AddCorner(parent, radius) local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, radius) corner.Parent = parent return corner end local function AddStroke(parent, color, thickness, transparency) local stroke = Instance.new("UIStroke") stroke.Color = color or THEME.Border stroke.Thickness = thickness or 1 stroke.Transparency = transparency or 0 stroke.Parent = parent return stroke end local function Tween(instance, properties, duration) local tween = TweenService:Create( instance, TweenInfo.new( duration or 0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out ), properties ) tween:Play() return tween end local function IsAlive(model) if not model or not model.Parent then return false end local humanoid = model:FindFirstChildOfClass("Humanoid") local root = model:FindFirstChild("HumanoidRootPart") return humanoid ~= nil and humanoid.Health > 0 and root ~= nil end local function IsPlayerCharacter(model) return Players:GetPlayerFromCharacter(model) ~= nil end local function GetPlayer(model) return Players:GetPlayerFromCharacter(model) end local function GetRoot(model) return model and model:FindFirstChild("HumanoidRootPart") end local function IsTeammate(model) local player = GetPlayer(model) if not player then return false end if LocalPlayer.Team == nil or player.Team == nil then return false end return player.Team == LocalPlayer.Team end --================================================== -- MODULE SYSTEM --================================================== local Modules = {} local ModuleRegistry = {} local GUI local function CreateModule(id, definition) local module = { ID = id, Name = definition.Name or id, Type = definition.Type, Desc = definition.Desc or "", Enabled = false, Min = definition.Min or 0, Max = definition.Max or 100, Value = definition.Default or 0, Connections = {}, Original = {}, } function module:Track(connection) if connection then table.insert(self.Connections, connection) end return connection end function module:ClearConnections() for i = #self.Connections, 1, -1 do local connection = self.Connections[i] if connection then pcall(function() connection:Disconnect() end) end self.Connections[i] = nil end end function module:Enable() if UNLOADED or self.Enabled then return end self.Enabled = true if self.OnEnable then local ok, err = pcall(self.OnEnable, self) if not ok then warn("[Module]", self.ID, err) end end if GUI then GUI:UpdateToggle(self.ID, true) end end function module:Disable() if not self.Enabled then return end self.Enabled = false self:ClearConnections() if self.OnDisable then local ok, err = pcall(self.OnDisable, self) if not ok then warn("[Module Disable]", self.ID, err) end end if GUI then GUI:UpdateToggle(self.ID, false) end end function module:SetValue(value) value = Clamp(value, self.Min, self.Max) self.Value = value if self.OnValue then pcall(self.OnValue, self, value) end if GUI then GUI:UpdateSlider(self.ID, value) end end ModuleRegistry[id] = module Modules[id] = module end for _, items in pairs(CONFIG) do for _, item in ipairs(items) do CreateModule(item.ID, item) end end --================================================== -- TARGET REGISTRY --================================================== local Targets = {} local CurrentTarget = nil local function AddTarget(model) if not model or not model:IsA("Model") then return end if model == Character then return end if not model:FindFirstChildOfClass("Humanoid") then return end Targets[model] = true end local function RemoveTarget(model) Targets[model] = nil end local function RegisterCharacter(character) if not character then return end task.defer(function() if UNLOADED or not character.Parent then return end local humanoid = character:FindFirstChildOfClass("Humanoid") if not humanoid then humanoid = character:WaitForChild("Humanoid", 3) end if humanoid then AddTarget(character) end end) end for _, player in ipairs(Players:GetPlayers()) do if player ~= LocalPlayer then if player.Character then RegisterCharacter(player.Character) end Track(player.CharacterAdded:Connect(function(character) RegisterCharacter(character) end)) end end Track(Players.PlayerAdded:Connect(function(player) if player == LocalPlayer then return end Track(player.CharacterAdded:Connect(function(character) RegisterCharacter(character) end)) if player.Character then RegisterCharacter(player.Character) end end)) Track(Players.PlayerRemoving:Connect(function(player) if player.Character then RemoveTarget(player.Character) end end)) Track(workspace.DescendantAdded:Connect(function(object) if object:IsA("Humanoid") then local model = object.Parent if model and model:IsA("Model") and not IsPlayerCharacter(model) then RegisterCharacter(model) end end end)) Track(workspace.DescendantRemoving:Connect(function(object) if object:IsA("Model") then RemoveTarget(object) end end)) local function IsValidTarget(model) if not IsAlive(model) or model == Character then return false end local player = GetPlayer(model) if player then if not ModuleRegistry.TargetPlayers.Enabled then return false end if ModuleRegistry.TeamCheck.Enabled and IsTeammate(model) then return false end return true end return ModuleRegistry.TargetNPCs.Enabled end local function FindBestTarget() local camera = GetCamera() if not camera or not RootPart then return nil end local viewport = camera.ViewportSize local center = Vector2.new(viewport.X / 2, viewport.Y / 2) local maxFOV = ModuleRegistry.AimFOV.Value local best = nil local bestScore = math.huge for model in pairs(Targets) do if not model.Parent then Targets[model] = nil continue end if not IsValidTarget(model) then continue end local root = GetRoot(model) if not root then continue end local screen, visible = camera:WorldToViewportPoint(root.Position) if not visible or screen.Z <= 0 then continue end local screenPos = Vector2.new(screen.X, screen.Y) local score = (screenPos - center).Magnitude if score <= maxFOV and score < bestScore then best = model bestScore = score end end return best end --================================================== -- FOV CIRCLE --================================================== local FOVGui = Instance.new("ScreenGui") FOVGui.Name = "TrainingFOV" FOVGui.IgnoreGuiInset = true FOVGui.ResetOnSpawn = false FOVGui.DisplayOrder = 25 FOVGui.Parent = LocalPlayer:WaitForChild("PlayerGui") local FOVCircle = Instance.new("Frame") FOVCircle.AnchorPoint = Vector2.new(0.5, 0.5) FOVCircle.Position = UDim2.fromScale(0.5, 0.5) FOVCircle.Size = UDim2.fromOffset( ModuleRegistry.AimFOV.Value * 2, ModuleRegistry.AimFOV.Value * 2 ) FOVCircle.BackgroundTransparency = 1 FOVCircle.Visible = false FOVCircle.Parent = FOVGui AddCorner(FOVCircle, 999) AddStroke(FOVCircle, THEME.Accent, 1, 0.15) ModuleRegistry.AimFOV.OnValue = function(_, value) FOVCircle.Size = UDim2.fromOffset(value * 2, value * 2) end ModuleRegistry.FOVCircle.OnEnable = function() FOVCircle.Visible = true end ModuleRegistry.FOVCircle.OnDisable = function() FOVCircle.Visible = false end --================================================== -- AIM ASSIST --================================================== local aimSearchTimer = 0 Track(RunService.RenderStepped:Connect(function(delta) if UNLOADED then return end local camera = GetCamera() if not camera then return end if FOVCircle.Visible then local viewport = camera.ViewportSize FOVCircle.Position = UDim2.fromOffset( viewport.X / 2, viewport.Y / 2 ) end if not ModuleRegistry.AimAssist.Enabled then CurrentTarget = nil return end aimSearchTimer += delta -- Target acquisition is throttled. local searchInterval = ModuleRegistry.PerformanceMode.Enabled and 0.12 or 0.06 if aimSearchTimer >= searchInterval then aimSearchTimer = 0 if not ModuleRegistry.TargetLock.Enabled or not CurrentTarget or not IsValidTarget(CurrentTarget) then CurrentTarget = FindBestTarget() end end if not CurrentTarget or not IsValidTarget(CurrentTarget) then return end local targetRoot = GetRoot(CurrentTarget) if not targetRoot then CurrentTarget = nil return end local desired = CFrame.lookAt( camera.CFrame.Position, targetRoot.Position + Vector3.new(0, 1.5, 0) ) local smooth = ModuleRegistry.AimSmooth.Value local alpha = Clamp(1 / math.max(smooth, 1), 0.025, 0.5) camera.CFrame = camera.CFrame:Lerp(desired, alpha) end)) --================================================== -- TRIGGER TOOL --================================================== local triggerTimer = 0 Track(RunService.Heartbeat:Connect(function(delta) if not ModuleRegistry.TriggerTool.Enabled then return end triggerTimer += delta if triggerTimer < 0.08 then return end triggerTimer = 0 local mouse = LocalPlayer:GetMouse() local hit = mouse.Target if not hit then return end local model = hit while model and model ~= workspace do if model:IsA("Model") and model:FindFirstChildOfClass("Humanoid") then break end model = model.Parent end if model and IsValidTarget(model) then local tool = Character and Character:FindFirstChildOfClass("Tool") if tool then pcall(function() tool:Activate() end) end end end)) --================================================== -- MOVEMENT --================================================== local function ApplyWalkSpeed() if not Humanoid or Humanoid.Health <= 0 then return end if ModuleRegistry.WalkSpeed.Enabled then local desired = ModuleRegistry.WalkSpeedValue.Value if Humanoid.WalkSpeed ~= desired then Humanoid.WalkSpeed = desired end end end local function ApplyJumpPower() if not Humanoid or Humanoid.Health <= 0 then return end if ModuleRegistry.JumpPower.Enabled then local desired = ModuleRegistry.JumpPowerValue.Value if Humanoid.UseJumpPower ~= true then Humanoid.UseJumpPower = true end if Humanoid.JumpPower ~= desired then Humanoid.JumpPower = desired end end end ModuleRegistry.WalkSpeed.OnEnable = function(module) if Humanoid then module.Original.Humanoid = Humanoid module.Original.WalkSpeed = Humanoid.WalkSpeed end ApplyWalkSpeed() if Humanoid then module:Track(Humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function() if module.Enabled then ApplyWalkSpeed() end end)) end end ModuleRegistry.WalkSpeedValue.OnValue = function() ApplyWalkSpeed() end ModuleRegistry.WalkSpeed.OnDisable = function(module) local hum = module.Original.Humanoid local original = module.Original.WalkSpeed if hum and hum.Parent and original then hum.WalkSpeed = original end module.Original = {} end ModuleRegistry.JumpPower.OnEnable = function(module) if Humanoid then module.Original.Humanoid = Humanoid module.Original.JumpPower = Humanoid.JumpPower module.Original.UseJumpPower = Humanoid.UseJumpPower end ApplyJumpPower() if Humanoid then module:Track(Humanoid:GetPropertyChangedSignal("JumpPower"):Connect(function() if module.Enabled then ApplyJumpPower() end end)) module:Track(Humanoid:GetPropertyChangedSignal("UseJumpPower"):Connect(function() if module.Enabled then Humanoid.UseJumpPower = true ApplyJumpPower() end end)) end end ModuleRegistry.JumpPowerValue.OnValue = function() ApplyJumpPower() end ModuleRegistry.JumpPower.OnDisable = function(module) local hum = module.Original.Humanoid if hum and hum.Parent then if module.Original.JumpPower then hum.JumpPower = module.Original.JumpPower end if module.Original.UseJumpPower ~= nil then hum.UseJumpPower = module.Original.UseJumpPower end end module.Original = {} end Track(RunService.Heartbeat:Connect(function() if UNLOADED then return end ApplyWalkSpeed() ApplyJumpPower() end)) --================================================== -- INFINITE JUMP --================================================== ModuleRegistry.InfiniteJump.OnEnable = function(module) module:Track(UserInputService.JumpRequest:Connect(function() if not module.Enabled or not Humanoid then return end if Humanoid.Health > 0 then Humanoid:ChangeState(Enum.HumanoidStateType.Jumping) end end)) end --================================================== -- FLY --================================================== local function StopFly() if RootPart then RootPart.AssemblyLinearVelocity = Vector3.zero end end ModuleRegistry.Fly.OnEnable = function(module) module:Track(RunService.RenderStepped:Connect(function() if not module.Enabled or not RootPart then return end local camera = GetCamera() if not camera then return end local direction = Vector3.zero if UserInputService:IsKeyDown(Enum.KeyCode.W) then direction += camera.CFrame.LookVector end if UserInputService:IsKeyDown(Enum.KeyCode.S) then direction -= camera.CFrame.LookVector end if UserInputService:IsKeyDown(Enum.KeyCode.A) then direction -= camera.CFrame.RightVector end if UserInputService:IsKeyDown(Enum.KeyCode.D) then direction += camera.CFrame.RightVector end if UserInputService:IsKeyDown(Enum.KeyCode.Space) then direction += Vector3.yAxis end if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then direction -= Vector3.yAxis end if direction.Magnitude > 0 then RootPart.AssemblyLinearVelocity = direction.Unit * ModuleRegistry.FlySpeed.Value else RootPart.AssemblyLinearVelocity = Vector3.zero end end)) end ModuleRegistry.Fly.OnDisable = function() StopFly() end --================================================== -- NOCLIP --================================================== local function ApplyNoclip() if not Character then return end for _, part in ipairs(Character:GetDescendants()) do if part:IsA("BasePart") then if part:GetAttribute("TrainingOriginalCollision") == nil then part:SetAttribute( "TrainingOriginalCollision", part.CanCollide ) end part.CanCollide = false end end end local function RestoreCollision() if not Character then return end for _, part in ipairs(Character:GetDescendants()) do if part:IsA("BasePart") then local original = part:GetAttribute("TrainingOriginalCollision") if original ~= nil then part.CanCollide = original part:SetAttribute( "TrainingOriginalCollision", nil ) end end end end Track(RunService.Stepped:Connect(function() if ModuleRegistry.Noclip.Enabled then ApplyNoclip() end end)) ModuleRegistry.Noclip.OnDisable = function() RestoreCollision() end --================================================== -- CLICK TELEPORT --================================================== ModuleRegistry.ClickTeleport.OnEnable = function(module) module:Track(UserInputService.InputBegan:Connect(function(input, processed) if processed or input.UserInputType ~= Enum.UserInputType.MouseButton1 or not UserInputService:IsKeyDown(Enum.KeyCode.LeftControl) then return end local mouse = LocalPlayer:GetMouse() if RootPart and mouse.Hit then RootPart.CFrame = mouse.Hit + Vector3.new(0, 3, 0) end end)) end --================================================== -- FULLBRIGHT --================================================== ModuleRegistry.Fullbright.OnEnable = function(module) if not module.Original.Saved then module.Original.Brightness = Lighting.Brightness module.Original.ClockTime = Lighting.ClockTime module.Original.Ambient = Lighting.Ambient module.Original.OutdoorAmbient = Lighting.OutdoorAmbient module.Original.GlobalShadows = Lighting.GlobalShadows module.Original.Saved = true end Lighting.Brightness = 2 Lighting.ClockTime = 14 Lighting.Ambient = Color3.new(1, 1, 1) Lighting.OutdoorAmbient = Color3.new(1, 1, 1) Lighting.GlobalShadows = false end ModuleRegistry.Fullbright.OnDisable = function(module) if not module.Original.Saved then return end Lighting.Brightness = module.Original.Brightness Lighting.ClockTime = module.Original.ClockTime Lighting.Ambient = module.Original.Ambient Lighting.OutdoorAmbient = module.Original.OutdoorAmbient Lighting.GlobalShadows = module.Original.GlobalShadows module.Original = {} end --================================================== -- THIRD PERSON --================================================== ModuleRegistry.ThirdPerson.OnEnable = function(module) if not module.Original.Saved then module.Original.CameraMode = LocalPlayer.CameraMode module.Original.MinZoom = LocalPlayer.CameraMinZoomDistance module.Original.MaxZoom = LocalPlayer.CameraMaxZoomDistance module.Original.Saved = true end LocalPlayer.CameraMode = Enum.CameraMode.Classic LocalPlayer.CameraMinZoomDistance = 5 end ModuleRegistry.ThirdPerson.OnDisable = function(module) if not module.Original.Saved then return end LocalPlayer.CameraMode = module.Original.CameraMode LocalPlayer.CameraMinZoomDistance = module.Original.MinZoom LocalPlayer.CameraMaxZoomDistance = module.Original.MaxZoom module.Original = {} end --================================================== -- CAMERA ZOOM --================================================== ModuleRegistry.CameraZoom.OnEnable = function(module) if not module.Original.Saved then module.Original.MaxZoom = LocalPlayer.CameraMaxZoomDistance module.Original.Saved = true end LocalPlayer.CameraMaxZoomDistance = ModuleRegistry.CameraZoomValue.Value end ModuleRegistry.CameraZoomValue.OnValue = function(_, value) if ModuleRegistry.CameraZoom.Enabled then LocalPlayer.CameraMaxZoomDistance = value end end ModuleRegistry.CameraZoom.OnDisable = function(module) if module.Original.MaxZoom then LocalPlayer.CameraMaxZoomDistance = module.Original.MaxZoom end module.Original = {} end --================================================== -- ESP --================================================== local ESPGui = Instance.new("ScreenGui") ESPGui.Name = "TrainingESP" ESPGui.IgnoreGuiInset = true ESPGui.ResetOnSpawn = false ESPGui.DisplayOrder = 20 ESPGui.Parent = LocalPlayer:WaitForChild("PlayerGui") local ESPObjects = {} local function DestroyESP(model) local data = ESPObjects[model] if not data then return end if data.Container then data.Container:Destroy() end ESPObjects[model] = nil end local function CreateESP(model) if ESPObjects[model] then return ESPObjects[model] end local container = Instance.new("Frame") container.BackgroundTransparency = 1 container.Visible = false container.Parent = ESPGui local box = Instance.new("Frame") box.BackgroundTransparency = 1 box.Visible = false box.Parent = container local boxStroke = AddStroke(box, THEME.Red, 1, 0) local name = Instance.new("TextLabel") name.BackgroundTransparency = 1 name.TextColor3 = THEME.Text name.TextStrokeTransparency = 0 name.Font = Enum.Font.GothamBold name.TextSize = 12 name.AnchorPoint = Vector2.new(0.5, 1) name.Visible = false name.Parent = container local distance = Instance.new("TextLabel") distance.BackgroundTransparency = 1 distance.TextColor3 = THEME.Secondary distance.TextStrokeTransparency = 0 distance.Font = Enum.Font.Gotham distance.TextSize = 11 distance.AnchorPoint = Vector2.new(0.5, 0) distance.Visible = false distance.Parent = container local healthBack = Instance.new("Frame") healthBack.BackgroundColor3 = Color3.fromRGB(26, 26, 30) healthBack.BorderSizePixel = 0 healthBack.Visible = false healthBack.Parent = container local health = Instance.new("Frame") health.BorderSizePixel = 0 health.AnchorPoint = Vector2.new(0, 1) health.Position = UDim2.fromScale(0, 1) health.Size = UDim2.fromScale(1, 1) health.Parent = healthBack local tracer = Instance.new("Frame") tracer.BorderSizePixel = 0 tracer.AnchorPoint = Vector2.new(0.5, 0.5) tracer.Visible = false tracer.Parent = container local data = { Container = container, Box = box, BoxStroke = boxStroke, Name = name, Distance = distance, HealthBack = healthBack, Health = health, Tracer = tracer, } ESPObjects[model] = data return data end local function HideESP(data) data.Container.Visible = false data.Box.Visible = false data.Name.Visible = false data.Distance.Visible = false data.HealthBack.Visible = false data.Tracer.Visible = false end local function UpdateESP(model, data) if not ModuleRegistry.ESPEnabled.Enabled then HideESP(data) return end if not IsAlive(model) then HideESP(data) return end local isPlayer = IsPlayerCharacter(model) if not isPlayer and not ModuleRegistry.ESPNPC.Enabled then HideESP(data) return end if isPlayer and ModuleRegistry.ESPTeamCheck.Enabled and IsTeammate(model) then HideESP(data) return end if not RootPart then HideESP(data) return end local root = GetRoot(model) if not root then HideESP(data) return end local distance = (RootPart.Position - root.Position).Magnitude if distance > ModuleRegistry.ESPMaxDistance.Value then HideESP(data) return end local camera = GetCamera() if not camera then HideESP(data) return end local top = camera:WorldToViewportPoint( root.Position + Vector3.new(0, 3, 0) ) local bottom = camera:WorldToViewportPoint( root.Position - Vector3.new(0, 3, 0) ) if top.Z <= 0 or bottom.Z <= 0 then HideESP(data) return end local height = math.abs(bottom.Y - top.Y) if height < 3 then HideESP(data) return end local width = height * 0.55 local x = top.X - width / 2 local y = math.min(top.Y, bottom.Y) local playerColor = IsTeammate(model) and THEME.Blue or THEME.Red data.Container.Visible = true -- Box if ModuleRegistry.ESPBoxes.Enabled then data.Box.Position = UDim2.fromOffset(x, y) data.Box.Size = UDim2.fromOffset(width, height) data.BoxStroke.Color = playerColor data.Box.Visible = true else data.Box.Visible = false end -- Name if ModuleRegistry.ESPNames.Enabled then local player = GetPlayer(model) data.Name.Text = player and player.DisplayName or model.Name data.Name.Position = UDim2.fromOffset(x + width / 2, y - 3) data.Name.Size = UDim2.fromOffset(width + 120, 18) data.Name.Visible = true else data.Name.Visible = false end -- Distance if ModuleRegistry.ESPDistance.Enabled then data.Distance.Text = string.format("%d studs", math.floor(distance)) data.Distance.Position = UDim2.fromOffset(x + width / 2, y + height + 3) data.Distance.Size = UDim2.fromOffset(width + 120, 18) data.Distance.Visible = true else data.Distance.Visible = false end -- Health if ModuleRegistry.ESPHealth.Enabled then local humanoid = model:FindFirstChildOfClass("Humanoid") if humanoid then local ratio = Clamp( humanoid.Health / math.max(humanoid.MaxHealth, 1), 0, 1 ) data.HealthBack.Position = UDim2.fromOffset(x - 7, y) data.HealthBack.Size = UDim2.fromOffset(4, height) data.Health.Size = UDim2.new(1, 0, ratio, 0) data.Health.BackgroundColor3 = Color3.new(1 - ratio, ratio, 0) data.HealthBack.Visible = true else data.HealthBack.Visible = false end else data.HealthBack.Visible = false end -- Tracer if ModuleRegistry.ESPTracers.Enabled then local viewport = camera.ViewportSize local start = Vector2.new( viewport.X / 2, viewport.Y ) local finish = Vector2.new( bottom.X, bottom.Y ) local delta = finish - start local length = delta.Magnitude data.Tracer.Size = UDim2.fromOffset(length, 1) data.Tracer.Position = UDim2.fromOffset( (start.X + finish.X) / 2, (start.Y + finish.Y) / 2 ) data.Tracer.Rotation = math.deg(math.atan2(delta.Y, delta.X)) data.Tracer.BackgroundColor3 = playerColor data.Tracer.Visible = true else data.Tracer.Visible = false end end local espTimer = 0 Track(RunService.RenderStepped:Connect(function(delta) if not ModuleRegistry.ESPEnabled.Enabled then return end espTimer += delta local interval = ModuleRegistry.PerformanceMode.Enabled and (1 / 20) or (1 / 30) if espTimer < interval then return end espTimer = 0 for model in pairs(Targets) do if not model.Parent then Targets[model] = nil DestroyESP(model) continue end if not ESPObjects[model] then CreateESP(model) end end for model, data in pairs(ESPObjects) do if model.Parent then UpdateESP(model, data) else DestroyESP(model) end end end)) ModuleRegistry.ESPEnabled.OnDisable = function() for model in pairs(ESPObjects) do DestroyESP(model) end end --================================================== -- PERFORMANCE STATS --================================================== local StatsGui = Instance.new("ScreenGui") StatsGui.Name = "TrainingStats" StatsGui.IgnoreGuiInset = true StatsGui.ResetOnSpawn = false StatsGui.DisplayOrder = 100 StatsGui.Parent = LocalPlayer:WaitForChild("PlayerGui") local Stats = Instance.new("Frame") Stats.Size = UDim2.fromOffset(200, 78) Stats.Position = UDim2.fromOffset(12, 12) Stats.BackgroundColor3 = THEME.Background Stats.BackgroundTransparency = 0.08 Stats.Visible = false Stats.Parent = StatsGui AddCorner(Stats, 8) AddStroke(Stats, THEME.Border, 1) local StatsText = Instance.new("TextLabel") StatsText.Size = UDim2.new(1, -14, 1, -10) StatsText.Position = UDim2.fromOffset(7, 5) StatsText.BackgroundTransparency = 1 StatsText.TextColor3 = THEME.Text StatsText.Font = Enum.Font.Code StatsText.TextSize = 12 StatsText.TextXAlignment = Enum.TextXAlignment.Left StatsText.TextYAlignment = Enum.TextYAlignment.Top StatsText.Text = "FPS: --\nTargets: 0\nTarget: None" StatsText.Parent = Stats ModuleRegistry.ShowStats.OnEnable = function() Stats.Visible = true end ModuleRegistry.ShowStats.OnDisable = function() Stats.Visible = false end local statTimer = 0 local statFrames = 0 Track(RunService.RenderStepped:Connect(function(delta) if not Stats.Visible then return end statTimer += delta statFrames += 1 if statTimer >= 1 then local targetName = CurrentTarget and CurrentTarget.Name or "None" local targetCount = 0 for model in pairs(Targets) do if model.Parent then targetCount += 1 end end StatsText.Text = string.format( "FPS: %d\nTargets: %d\nTarget: %s", math.floor(statFrames / statTimer), targetCount, targetName ) statTimer = 0 statFrames = 0 end end)) --================================================== -- GUI --================================================== GUI = { ScreenGui = nil, Main = nil, Content = nil, Pages = {}, Tabs = {}, ToggleRefs = {}, SliderRefs = {}, Visible = true, } function GUI:CreatePage(name) local page = Instance.new("ScrollingFrame") page.Name = name page.Size = UDim2.fromScale(1, 1) page.BackgroundTransparency = 1 page.BorderSizePixel = 0 page.ScrollBarThickness = 3 page.ScrollBarImageColor3 = THEME.Accent page.Visible = false page.Parent = self.Content local layout = Instance.new("UIListLayout") layout.Padding = UDim.new(0, 9) layout.Parent = page local padding = Instance.new("UIPadding") padding.PaddingTop = UDim.new(0, 4) padding.PaddingBottom = UDim.new(0, 12) padding.Parent = page self.Pages[name] = page return page end function GUI:SectionTitle(parent, text) local label = Instance.new("TextLabel") label.Size = UDim2.new(1, -10, 0, 24) label.BackgroundTransparency = 1 label.Text = text label.TextColor3 = THEME.Muted label.Font = Enum.Font.GothamBold label.TextSize = 10 label.TextXAlignment = Enum.TextXAlignment.Left label.Parent = parent end function GUI:CreateToggle(parent, module) local row = Instance.new("Frame") row.Size = UDim2.new( 1, -8, 0, module.Desc ~= "" and 64 or 48 ) row.BackgroundColor3 = THEME.Card row.BorderSizePixel = 0 row.Parent = parent AddCorner(row, 9) local rowStroke = AddStroke(row, THEME.Border, 1, 0.35) local title = Instance.new("TextLabel") title.Size = UDim2.new(1, -100, 0, 20) title.Position = UDim2.fromOffset( 14, module.Desc ~= "" and 8 or 14 ) title.BackgroundTransparency = 1 title.Text = module.Name title.TextColor3 = THEME.Text title.Font = Enum.Font.GothamBold title.TextSize = 13 title.TextXAlignment = Enum.TextXAlignment.Left title.Parent = row if module.Desc ~= "" then local desc = Instance.new("TextLabel") desc.Size = UDim2.new(1, -105, 0, 16) desc.Position = UDim2.fromOffset(14, 32) desc.BackgroundTransparency = 1 desc.Text = module.Desc desc.TextColor3 = THEME.Muted desc.Font = Enum.Font.Gotham desc.TextSize = 10 desc.TextXAlignment = Enum.TextXAlignment.Left desc.Parent = row end local button = Instance.new("TextButton") button.Size = UDim2.fromOffset(48, 26) button.Position = UDim2.new(1, -62, 0.5, -13) button.BackgroundColor3 = module.Enabled and THEME.Accent or THEME.Background button.BorderSizePixel = 0 button.Text = "" button.AutoButtonColor = false button.Parent = row AddCorner(button, 20) local knob = Instance.new("Frame") knob.Size = UDim2.fromOffset(20, 20) knob.Position = module.Enabled and UDim2.new(1, -23, 0.5, -10) or UDim2.new(0, 3, 0.5, -10) knob.BackgroundColor3 = THEME.Text knob.BorderSizePixel = 0 knob.Parent = button AddCorner(knob, 20) local function Update(enabled) button.BackgroundColor3 = enabled and THEME.Accent or THEME.Background rowStroke.Color = enabled and THEME.AccentDark or THEME.Border Tween( knob, { Position = enabled and UDim2.new(1, -23, 0.5, -10) or UDim2.new(0, 3, 0.5, -10) }, 0.13 ) end self.ToggleRefs[module.ID] = Update Track(button.Activated:Connect(function() if module.Enabled then module:Disable() else module:Enable() end end)) end function GUI:CreateSlider(parent, module) local row = Instance.new("Frame") row.Size = UDim2.new(1, -8, 0, 72) row.BackgroundColor3 = THEME.Card row.BorderSizePixel = 0 row.Parent = parent AddCorner(row, 9) local title = Instance.new("TextLabel") title.Size = UDim2.new(0.65, 0, 0, 20) title.Position = UDim2.fromOffset(14, 9) title.BackgroundTransparency = 1 title.Text = module.Name title.TextColor3 = THEME.Text title.Font = Enum.Font.GothamBold title.TextSize = 13 title.TextXAlignment = Enum.TextXAlignment.Left title.Parent = row local value = Instance.new("TextLabel") value.Size = UDim2.new(0.25, 0, 0, 20) value.Position = UDim2.new(0.75, -14, 0, 9) value.BackgroundTransparency = 1 value.TextColor3 = THEME.AccentLight value.Font = Enum.Font.GothamBold value.TextSize = 12 value.TextXAlignment = Enum.TextXAlignment.Right value.Text = tostring(module.Value) value.Parent = row local hitbox = Instance.new("TextButton") hitbox.Size = UDim2.new(1, -28, 0, 18) hitbox.Position = UDim2.fromOffset(14, 43) hitbox.BackgroundTransparency = 1 hitbox.Text = "" hitbox.Parent = row local track = Instance.new("Frame") track.Size = UDim2.new(1, 0, 0, 7) track.Position = UDim2.new(0, 0, 0.5, -3.5) track.BackgroundColor3 = THEME.Background track.BorderSizePixel = 0 track.Parent = hitbox AddCorner(track, 10) local fill = Instance.new("Frame") fill.BackgroundColor3 = THEME.Accent fill.BorderSizePixel = 0 fill.Parent = track AddCorner(fill, 10) local thumb = Instance.new("Frame") thumb.Size = UDim2.fromOffset(14, 14) thumb.AnchorPoint = Vector2.new(0.5, 0.5) thumb.Position = UDim2.new(1, 0, 0.5, 0) thumb.BackgroundColor3 = THEME.Text thumb.BorderSizePixel = 0 thumb.Parent = fill AddCorner(thumb, 20) local function Update(newValue) local ratio = Clamp( (newValue - module.Min) / math.max(module.Max - module.Min, 1), 0, 1 ) fill.Size = UDim2.new(ratio, 0, 1, 0) value.Text = tostring(newValue) end self.SliderRefs[module.ID] = Update Update(module.Value) local dragging = false local function UpdateFromPosition(position) local width = track.AbsoluteSize.X if width <= 0 then return end local ratio = Clamp( (position.X - track.AbsolutePosition.X) / width, 0, 1 ) local newValue = module.Min + ratio * (module.Max - module.Min) module:SetValue(math.floor(newValue + 0.5)) end Track(hitbox.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = true UpdateFromPosition(input.Position) end end)) Track(UserInputService.InputChanged:Connect(function(input) if not dragging then return end if input.UserInputType == Enum.UserInputType.MouseMovement then UpdateFromPosition(input.Position) end end)) Track(UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false end end)) end function GUI:UpdateToggle(id, enabled) local callback = self.ToggleRefs[id] if callback then callback(enabled) end end function GUI:UpdateSlider(id, value) local callback = self.SliderRefs[id] if callback then callback(value) end end function GUI:ShowTab(name) for tabName, page in pairs(self.Pages) do page.Visible = tabName == name end for tabName, button in pairs(self.Tabs) do local active = tabName == name button.BackgroundColor3 = active and THEME.Accent or THEME.Sidebar button.TextColor3 = active and THEME.Text or THEME.Secondary end end function GUI:Build() local screen = Instance.new("ScreenGui") screen.Name = "ClientTrainingMenu" screen.ResetOnSpawn = false screen.IgnoreGuiInset = true screen.DisplayOrder = 200 screen.Parent = LocalPlayer:WaitForChild("PlayerGui") self.ScreenGui = screen local main = Instance.new("Frame") main.Name = "Main" main.Size = UDim2.fromOffset(790, 520) main.Position = UDim2.fromScale(0.5, 0.5) main.AnchorPoint = Vector2.new(0.5, 0.5) main.BackgroundColor3 = THEME.Background main.BorderSizePixel = 0 main.ClipsDescendants = true main.Parent = screen AddCorner(main, 13) AddStroke(main, THEME.Border, 1, 0.05) self.Main = main -- top accent line local accentLine = Instance.new("Frame") accentLine.Size = UDim2.new(1, 0, 0, 2) accentLine.Position = UDim2.fromOffset(0, 0) accentLine.BackgroundColor3 = THEME.Accent accentLine.BorderSizePixel = 0 accentLine.Parent = main -- header local header = Instance.new("Frame") header.Size = UDim2.new(1, 0, 0, 64) header.BackgroundColor3 = THEME.Sidebar header.BorderSizePixel = 0 header.Parent = main local title = Instance.new("TextLabel") title.Size = UDim2.new(0.6, 0, 0, 24) title.Position = UDim2.fromOffset(20, 10) title.BackgroundTransparency = 1 title.Text = "CLIENT TRAINING" title.TextColor3 = THEME.Text title.Font = Enum.Font.GothamBold title.TextSize = 18 title.TextXAlignment = Enum.TextXAlignment.Left title.Parent = header local subtitle = Instance.new("TextLabel") subtitle.Size = UDim2.new(0.7, 0, 0, 16) subtitle.Position = UDim2.fromOffset(20, 36) subtitle.BackgroundTransparency = 1 subtitle.Text = "Polished client-side control center" subtitle.TextColor3 = THEME.Muted subtitle.Font = Enum.Font.Gotham subtitle.TextSize = 10 subtitle.TextXAlignment = Enum.TextXAlignment.Left subtitle.Parent = header local status = Instance.new("Frame") status.Size = UDim2.fromOffset(92, 26) status.Position = UDim2.new(1, -145, 0, 19) status.BackgroundColor3 = Color3.fromRGB(17, 40, 27) status.BorderSizePixel = 0 status.Parent = header AddCorner(status, 14) local statusDot = Instance.new("Frame") statusDot.Size = UDim2.fromOffset(7, 7) statusDot.Position = UDim2.fromOffset(10, 9) statusDot.BackgroundColor3 = THEME.Green statusDot.BorderSizePixel = 0 statusDot.Parent = status AddCorner(statusDot, 10) local statusText = Instance.new("TextLabel") statusText.Size = UDim2.new(1, -24, 1, 0) statusText.Position = UDim2.fromOffset(20, 0) statusText.BackgroundTransparency = 1 statusText.Text = "ACTIVE" statusText.TextColor3 = THEME.Green statusText.Font = Enum.Font.GothamBold statusText.TextSize = 10 statusText.TextXAlignment = Enum.TextXAlignment.Left statusText.Parent = status -- close/unload local close = Instance.new("TextButton") close.Size = UDim2.fromOffset(30, 30) close.Position = UDim2.new(1, -42, 0, 17) close.BackgroundColor3 = THEME.Red close.BorderSizePixel = 0 close.Text = "×" close.TextColor3 = THEME.Text close.Font = Enum.Font.GothamBold close.TextSize = 18 close.Parent = header AddCorner(close, 7) Track(close.Activated:Connect(function() if self.Unload then self.Unload() end end)) -- drag local dragging = false local dragStart local startPosition Track(header.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = true dragStart = input.Position startPosition = main.Position end end)) Track(header.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false end end)) Track(UserInputService.InputChanged:Connect(function(input) if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then local delta = input.Position - dragStart main.Position = UDim2.new( startPosition.X.Scale, startPosition.X.Offset + delta.X, startPosition.Y.Scale, startPosition.Y.Offset + delta.Y ) end end)) -- sidebar local sidebar = Instance.new("Frame") sidebar.Size = UDim2.new(0, 175, 1, -64) sidebar.Position = UDim2.fromOffset(0, 64) sidebar.BackgroundColor3 = THEME.Sidebar sidebar.BorderSizePixel = 0 sidebar.Parent = main local sidebarPadding = Instance.new("UIPadding") sidebarPadding.PaddingTop = UDim.new(0, 14) sidebarPadding.PaddingLeft = UDim.new(0, 10) sidebarPadding.PaddingRight = UDim.new(0, 10) sidebarPadding.Parent = sidebar local sidebarLayout = Instance.new("UIListLayout") sidebarLayout.Padding = UDim.new(0, 7) sidebarLayout.Parent = sidebar -- content local content = Instance.new("Frame") content.Size = UDim2.new(1, -190, 1, -80) content.Position = UDim2.fromOffset(185, 73) content.BackgroundTransparency = 1 content.Parent = main self.Content = content for index, tabName in ipairs(TAB_ORDER) do local button = Instance.new("TextButton") button.Size = UDim2.new(1, 0, 0, 42) button.BackgroundColor3 = THEME.Sidebar button.BorderSizePixel = 0 button.AutoButtonColor = false button.Text = "" button.LayoutOrder = index button.Parent = sidebar AddCorner(button, 8) local icon = Instance.new("TextLabel") icon.Size = UDim2.fromOffset(26, 42) icon.Position = UDim2.fromOffset(9, 0) icon.BackgroundTransparency = 1 icon.Text = TAB_ICONS[tabName] or "•" icon.TextColor3 = THEME.Secondary icon.Font = Enum.Font.GothamBold icon.TextSize = 14 icon.Parent = button local text = Instance.new("TextLabel") text.Size = UDim2.new(1, -46, 1, 0) text.Position = UDim2.fromOffset(40, 0) text.BackgroundTransparency = 1 text.Text = tabName text.TextColor3 = THEME.Secondary text.Font = Enum.Font.GothamMedium text.TextSize = 12 text.TextXAlignment = Enum.TextXAlignment.Left text.Parent = button self.Tabs[tabName] = button local page = self:CreatePage(tabName) self:SectionTitle(page, string.upper(tabName)) for _, item in ipairs(CONFIG[tabName]) do local module = ModuleRegistry[item.ID] if module then if item.Type == "Toggle" then self:CreateToggle(page, module) elseif item.Type == "Slider" then self:CreateSlider(page, module) end end end Track(button.Activated:Connect(function() self:ShowTab(tabName) end)) end self:ShowTab(TAB_ORDER[1]) end function GUI:Toggle() self.Visible = not self.Visible if self.Main then self.Main.Visible = self.Visible end end function GUI:Destroy() if self.ScreenGui then self.ScreenGui:Destroy() end self.ScreenGui = nil self.Main = nil end --================================================== -- REAL UNLOAD --================================================== local DestroyFramework GUI.Unload = function() if DestroyFramework then DestroyFramework() end end DestroyFramework = function() if UNLOADED then return end UNLOADED = true for _, module in pairs(ModuleRegistry) do if module.Enabled then pcall(function() module:Disable() end) end end RestoreCollision() StopFly() for model in pairs(ESPObjects) do DestroyESP(model) end if GUI then GUI:Destroy() end if FOVGui then FOVGui:Destroy() end if ESPGui then ESPGui:Destroy() end if StatsGui then StatsGui:Destroy() end table.clear(Targets) DisconnectAll() print("[Client Training] Unloaded cleanly.") end --================================================== -- MENU KEY --================================================== Track(UserInputService.InputBegan:Connect(function(input, processed) if processed or UNLOADED then return end if input.KeyCode == Enum.KeyCode.RightShift then GUI:Toggle() end end)) --================================================== -- RESPAWN --================================================== Track(LocalPlayer.CharacterAdded:Connect(function(character) Character = character Humanoid = character:WaitForChild("Humanoid", 5) RootPart = character:WaitForChild("HumanoidRootPart", 5) CurrentTarget = nil if ModuleRegistry.WalkSpeed.Enabled then ModuleRegistry.WalkSpeed.Original = {} end if ModuleRegistry.JumpPower.Enabled then ModuleRegistry.JumpPower.Original = {} end RegisterCharacter(character) end)) --================================================== -- BUILD / DEFAULTS --================================================== GUI:Build() ModuleRegistry.TargetPlayers:Enable() ModuleRegistry.TargetNPCs:Enable() ModuleRegistry.ESPEnabled:Enable() ModuleRegistry.ESPBoxes:Enable() ModuleRegistry.ESPNames:Enable() ModuleRegistry.ESPDistance:Enable() ModuleRegistry.ESPHealth:Enable() ModuleRegistry.FOVCircle:Enable() print("========================================") print("[Client Training] v3.0 POLISHED") print("RightShift = Toggle Menu") print("X = Full Unload") print("========================================")