Vector Based Aim *it
Key RequiredUniversal

Vector Based Aim *it

Universal ScriptMediorceExploiterMediorceExploiter 1K views 125 executesUpdated Dec 25, 2025
Unrated
00
Lua Script•572 lines (16215 chars)
-- Aim Assist (for YOUR Roblox game) + GUI + Target Dropdown (fixed layering + stays open)
-- StarterPlayerScripts (LocalScript)

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local localPlayer = Players.LocalPlayer
local camera = workspace.CurrentCamera

-- =========================
-- KEYBINDS (CHANGE ONLY HERE)
-- =========================
local KEY_TOGGLE_UI = Enum.KeyCode.P
local KEY_DELETE_UI = Enum.KeyCode.M

-- =========================
-- SETTINGS
-- =========================
local Settings = {
	Enabled = true,
	MaxFOV = 8,         -- degrees
	Smoothing = 0.18,   -- 0..1
	LeadTime = 0.12,    -- seconds
	MaxDistance = 600,  -- studs
	TargetPartName = "HumanoidRootPart", -- or "Head"
	RequireRightMouse = false,
}

-- Target selection
local SelectedTargetUserId: number? = nil -- nil = Auto (closest in FOV)

-- =========================
-- Helpers
-- =========================
local function clampNumber(n, min, max)
	n = tonumber(n)
	if not n then return nil end
	if n < min then return min end
	if n > max then return max end
	return n
end

local function safeGetCharacter(plr)
	if plr and plr.Character and plr.Character.Parent then
		return plr.Character
	end
end

local function getTargetPart(char)
	return char:FindFirstChild(Settings.TargetPartName) or char:FindFirstChild("Head")
end

local function angleBetween(a, b)
	local d = math.clamp(a:Dot(b), -1, 1)
	return math.deg(math.acos(d))
end

local function isAssistActive()
	if not Settings.Enabled then return false end
	if not Settings.RequireRightMouse then return true end
	return UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton2)
end

local function isValidTarget(plr, part)
	if not plr or plr == localPlayer then return false end
	if not part then return false end
	local hum = part.Parent and part.Parent:FindFirstChildOfClass("Humanoid")
	return hum and hum.Health > 0
end

local function getPlayerByUserId(userId: number?)
	if not userId then return nil end
	for _, p in ipairs(Players:GetPlayers()) do
		if p.UserId == userId then return p end
	end
	return nil
end

local function predictAimPoint(targetPart)
	local pos = targetPart.Position
	local v = targetPart.AssemblyLinearVelocity or Vector3.zero
	return pos + (v * Settings.LeadTime)
end

-- =========================
-- GUI + Connections
-- =========================
local connections = {}
local destroyed = false

local gui: ScreenGui? = nil
local frame: Frame? = nil

local dropdownList: Frame? = nil
local dropdownBtn: TextButton? = nil
local dropdownOpen = false

local function connect(sig, fn)
	local c = sig:Connect(fn)
	table.insert(connections, c)
	return c
end

local function disconnectAll()
	for _, c in ipairs(connections) do
		pcall(function() c:Disconnect() end)
	end
	table.clear(connections)
end

local function setUIVisible(visible: boolean)
	if frame and frame.Parent then
		frame.Visible = visible
		if not visible and dropdownList then
			dropdownList.Visible = false
			dropdownOpen = false
		end
	end
end

local function toggleUI()
	if frame and frame.Parent then
		setUIVisible(not frame.Visible)
	end
end

local function deleteUI()
	if destroyed then return end
	destroyed = true
	disconnectAll()
	if gui then pcall(function() gui:Destroy() end) end
	gui, frame, dropdownList, dropdownBtn = nil, nil, nil, nil
end

local function createGUI()
	gui = Instance.new("ScreenGui")
	gui.Name = "AimAssistGUI"
	gui.ResetOnSpawn = false
	gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling -- IMPORTANT: lets ZIndex work across siblings
	gui.Parent = localPlayer:WaitForChild("PlayerGui")

	frame = Instance.new("Frame")
	frame.Name = "Panel"
	frame.Size = UDim2.new(0, 370, 0, 280)
	frame.Position = UDim2.new(0, 20, 0, 120)
	frame.BackgroundTransparency = 0.15
	frame.BorderSizePixel = 0
	frame.ZIndex = 1
	frame.Parent = gui

	local corner = Instance.new("UICorner")
	corner.CornerRadius = UDim.new(0, 12)
	corner.Parent = frame

	local stroke = Instance.new("UIStroke")
	stroke.Thickness = 1
	stroke.Transparency = 0.4
	stroke.Parent = frame

	local title = Instance.new("TextLabel")
	title.Size = UDim2.new(1, -46, 0, 28)
	title.Position = UDim2.new(0, 8, 0, 6)
	title.BackgroundTransparency = 1
	title.TextXAlignment = Enum.TextXAlignment.Left
	title.Font = Enum.Font.GothamBold
	title.TextSize = 16
	title.Text = "Aim Assist (Owner Tools)"
	title.ZIndex = 2
	title.Parent = frame

	local closeBtn = Instance.new("TextButton")
	closeBtn.Size = UDim2.new(0, 28, 0, 28)
	closeBtn.Position = UDim2.new(1, -34, 0, 6)
	closeBtn.BorderSizePixel = 0
	closeBtn.BackgroundTransparency = 0.05
	closeBtn.Font = Enum.Font.GothamBold
	closeBtn.TextSize = 16
	closeBtn.Text = "X"
	closeBtn.ZIndex = 2
	closeBtn.Parent = frame

	local closeCorner = Instance.new("UICorner")
	closeCorner.CornerRadius = UDim.new(0, 8)
	closeCorner.Parent = closeBtn

	local hint = Instance.new("TextLabel")
	hint.Size = UDim2.new(1, -12, 0, 18)
	hint.Position = UDim2.new(0, 8, 0, 34)
	hint.BackgroundTransparency = 1
	hint.TextXAlignment = Enum.TextXAlignment.Left
	hint.Font = Enum.Font.Gotham
	hint.TextSize = 12
	hint.TextTransparency = 0.2
	hint.Text = ("Keys: %s hide/show, %s delete UI. Dropdown refreshes every 10s.")
		:format(KEY_TOGGLE_UI.Name, KEY_DELETE_UI.Name)
	hint.ZIndex = 2
	hint.Parent = frame

	local function row(y, labelText, defaultText)
		local label = Instance.new("TextLabel")
		label.Size = UDim2.new(0, 180, 0, 26)
		label.Position = UDim2.new(0, 8, 0, y)
		label.BackgroundTransparency = 1
		label.TextXAlignment = Enum.TextXAlignment.Left
		label.Font = Enum.Font.Gotham
		label.TextSize = 13
		label.Text = labelText
		label.ZIndex = 2
		label.Parent = frame

		local box = Instance.new("TextBox")
		box.Size = UDim2.new(0, 160, 0, 26)
		box.Position = UDim2.new(0, 200, 0, y)
		box.BackgroundTransparency = 0.05
		box.BorderSizePixel = 0
		box.ClearTextOnFocus = false
		box.Font = Enum.Font.Gotham
		box.TextSize = 13
		box.Text = defaultText
		box.ZIndex = 2
		box.Parent = frame

		local boxCorner = Instance.new("UICorner")
		boxCorner.CornerRadius = UDim.new(0, 8)
		boxCorner.Parent = box

		local boxStroke = Instance.new("UIStroke")
		boxStroke.Thickness = 1
		boxStroke.Transparency = 0.6
		boxStroke.Parent = box

		return box
	end

	-- Enabled toggle
	local enabledBtn = Instance.new("TextButton")
	enabledBtn.Size = UDim2.new(0, 160, 0, 28)
	enabledBtn.Position = UDim2.new(0, 200, 0, 58)
	enabledBtn.BorderSizePixel = 0
	enabledBtn.Font = Enum.Font.GothamBold
	enabledBtn.TextSize = 13
	enabledBtn.ZIndex = 2
	enabledBtn.Parent = frame

	local btnCorner = Instance.new("UICorner")
	btnCorner.CornerRadius = UDim.new(0, 8)
	btnCorner.Parent = enabledBtn

	local function refreshEnabledButton()
		enabledBtn.Text = Settings.Enabled and "Enabled: ON" or "Enabled: OFF"
		enabledBtn.BackgroundTransparency = Settings.Enabled and 0.05 or 0.2
	end
	refreshEnabledButton()

	-- Dropdown label
	local ddLabel = Instance.new("TextLabel")
	ddLabel.Size = UDim2.new(0, 180, 0, 26)
	ddLabel.Position = UDim2.new(0, 8, 0, 92)
	ddLabel.BackgroundTransparency = 1
	ddLabel.TextXAlignment = Enum.TextXAlignment.Left
	ddLabel.Font = Enum.Font.Gotham
	ddLabel.TextSize = 13
	ddLabel.Text = "Target (dropdown)"
	ddLabel.ZIndex = 2
	ddLabel.Parent = frame

	-- Dropdown button (base layer)
	dropdownBtn = Instance.new("TextButton")
	dropdownBtn.Size = UDim2.new(0, 160, 0, 26)
	dropdownBtn.Position = UDim2.new(0, 200, 0, 92)
	dropdownBtn.BackgroundTransparency = 0.05
	dropdownBtn.BorderSizePixel = 0
	dropdownBtn.Font = Enum.Font.Gotham
	dropdownBtn.TextSize = 13
	dropdownBtn.TextXAlignment = Enum.TextXAlignment.Left
	dropdownBtn.Text = "  Auto (closest in FOV)  ▾"
	dropdownBtn.ZIndex = 5
	dropdownBtn.Parent = frame

	local ddCorner = Instance.new("UICorner")
	ddCorner.CornerRadius = UDim.new(0, 8)
	ddCorner.Parent = dropdownBtn

	local ddStroke = Instance.new("UIStroke")
	ddStroke.Thickness = 1
	ddStroke.Transparency = 0.6
	ddStroke.Parent = dropdownBtn

	-- Dropdown list (HIGH ZINDEX so it overlays everything)
	dropdownList = Instance.new("Frame")
	dropdownList.Name = "DropdownList"
	dropdownList.Size = UDim2.new(0, 160, 0, 0)
	dropdownList.Position = UDim2.new(0, 200, 0, 120)
	dropdownList.BackgroundTransparency = 0.05
	dropdownList.BorderSizePixel = 0
	dropdownList.Visible = false
	dropdownList.ClipsDescendants = true
	dropdownList.ZIndex = 50
	dropdownList.Parent = frame

	local listCorner = Instance.new("UICorner")
	listCorner.CornerRadius = UDim.new(0, 8)
	listCorner.Parent = dropdownList

	local listStroke = Instance.new("UIStroke")
	listStroke.Thickness = 1
	listStroke.Transparency = 0.6
	listStroke.Parent = dropdownList

	local uiList = Instance.new("UIListLayout")
	uiList.SortOrder = Enum.SortOrder.LayoutOrder
	uiList.Padding = UDim.new(0, 2)
	uiList.Parent = dropdownList

	local function setDropdownText(labelText)
		if dropdownBtn then
			dropdownBtn.Text = "  " .. labelText .. "  ▾"
		end
	end

	local function makeOption(text, onClick)
		local opt = Instance.new("TextButton")
		opt.Size = UDim2.new(1, -6, 0, 24)
		opt.BackgroundTransparency = 0.1
		opt.BorderSizePixel = 0
		opt.Font = Enum.Font.Gotham
		opt.TextSize = 13
		opt.TextXAlignment = Enum.TextXAlignment.Left
		opt.Text = "  " .. text
		opt.ZIndex = 51
		opt.Parent = dropdownList

		local optCorner = Instance.new("UICorner")
		optCorner.CornerRadius = UDim.new(0, 6)
		optCorner.Parent = opt

		connect(opt.MouseButton1Click, onClick)
		return opt
	end

	-- IMPORTANT: Rebuild WITHOUT closing if it's open
	local function rebuildDropdownOptions()
		if not dropdownList or not dropdownList.Parent then return end

		-- keep open/size state
		local wasVisible = dropdownList.Visible
		local priorSize = dropdownList.Size

		-- clear old buttons only
		for _, c in ipairs(dropdownList:GetChildren()) do
			if c:IsA("TextButton") then c:Destroy() end
		end

		local options = {}
		table.insert(options, {name = "Auto (closest in FOV)", userId = nil})
		for _, p in ipairs(Players:GetPlayers()) do
			if p ~= localPlayer then
				table.insert(options, {name = p.DisplayName .. " (@" .. p.Name .. ")", userId = p.UserId})
			end
		end

		for i, opt in ipairs(options) do
			local btn = makeOption(opt.name, function()
				SelectedTargetUserId = opt.userId
				setDropdownText(opt.name)

				-- close on user selection (but NOT on auto-refresh)
				dropdownList.Visible = false
				dropdownOpen = false
				dropdownList.Size = UDim2.new(0, 160, 0, 0)
			end)
			btn.LayoutOrder = i
		end

		local rows = #options
		local h = math.min(rows * 26 + 4, 200)

		-- if it was open, keep it open and keep it expanded
		if wasVisible then
			dropdownList.Visible = true
			dropdownOpen = true
			dropdownList.Size = UDim2.new(0, 160, 0, h)
		else
			-- if it was closed, keep it closed (don’t pop open)
			dropdownList.Visible = false
			dropdownOpen = false
			dropdownList.Size = priorSize -- usually 0 height
		end
	end

	-- Dropdown click toggle
	connect(dropdownBtn.MouseButton1Click, function()
		if not dropdownList then return end
		dropdownOpen = not dropdownOpen
		dropdownList.Visible = dropdownOpen
		if dropdownOpen then
			rebuildDropdownOptions()
		else
			dropdownList.Size = UDim2.new(0, 160, 0, 0)
		end
	end)

	-- Auto refresh every 10 seconds (doesn't close it)
	task.spawn(function()
		while not destroyed do
			task.wait(10)
			if destroyed then break end
			rebuildDropdownOptions()
		end
	end)

	-- If selected target leaves, revert to Auto (and keep dropdown open state unchanged)
	connect(Players.PlayerRemoving, function(p)
		if SelectedTargetUserId and p.UserId == SelectedTargetUserId then
			SelectedTargetUserId = nil
			setDropdownText("Auto (closest in FOV)")
		end
	end)

	-- Numeric controls
	local fovBox = row(128, "Max FOV (degrees)", tostring(Settings.MaxFOV))
	local smoothBox = row(158, "Smoothing (0..1)", tostring(Settings.Smoothing))
	local leadBox = row(188, "Lead Time (seconds)", tostring(Settings.LeadTime))
	local distBox = row(218, "Max Distance (studs)", tostring(Settings.MaxDistance))

	connect(enabledBtn.MouseButton1Click, function()
		Settings.Enabled = not Settings.Enabled
		refreshEnabledButton()
	end)

	connect(fovBox.FocusLost, function()
		local v = clampNumber(fovBox.Text, 0.5, 60)
		if v then Settings.MaxFOV = v; fovBox.Text = tostring(v) else fovBox.Text = tostring(Settings.MaxFOV) end
	end)

	connect(smoothBox.FocusLost, function()
		local v = clampNumber(smoothBox.Text, 0, 1)
		if v then Settings.Smoothing = v; smoothBox.Text = tostring(v) else smoothBox.Text = tostring(Settings.Smoothing) end
	end)

	connect(leadBox.FocusLost, function()
		local v = clampNumber(leadBox.Text, 0, 1.5)
		if v then Settings.LeadTime = v; leadBox.Text = tostring(v) else leadBox.Text = tostring(Settings.LeadTime) end
	end)

	connect(distBox.FocusLost, function()
		local v = clampNumber(distBox.Text, 20, 5000)
		if v then Settings.MaxDistance = v; distBox.Text = tostring(v) else distBox.Text = tostring(Settings.MaxDistance) end
	end)

	-- Dragging
	local dragging = false
	local dragStart, startPos
	connect(title.InputBegan, function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragging = true
			dragStart = input.Position
			startPos = frame.Position
			connect(input.Changed, function()
				if input.UserInputState == Enum.UserInputState.End then
					dragging = false
				end
			end)
		end
	end)

	connect(UserInputService.InputChanged, function(input)
		if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
			local delta = input.Position - dragStart
			frame.Position = UDim2.new(
				startPos.X.Scale, startPos.X.Offset + delta.X,
				startPos.Y.Scale, startPos.Y.Offset + delta.Y
			)
		end
	end)

	-- X hides UI
	connect(closeBtn.MouseButton1Click, function()
		setUIVisible(false)
	end)

	-- Keybinds
	connect(UserInputService.InputBegan, function(input, gameProcessed)
		if gameProcessed then return end
		if input.KeyCode == KEY_TOGGLE_UI then
			toggleUI()
		elseif input.KeyCode == KEY_DELETE_UI then
			deleteUI()
		end
	end)
end

createGUI()

-- =========================
-- Target selection + Aim logic
-- =========================
local function getBestTargetAuto()
	local camPos = camera.CFrame.Position
	local camLook = camera.CFrame.LookVector.Unit

	local bestPart = nil
	local bestAngle = Settings.MaxFOV

	for _, plr in ipairs(Players:GetPlayers()) do
		if plr ~= localPlayer then
			local char = safeGetCharacter(plr)
			if char then
				local part = getTargetPart(char)
				if isValidTarget(plr, part) then
					local toTarget = (part.Position - camPos)
					local dist = toTarget.Magnitude
					if dist <= Settings.MaxDistance then
						local ang = angleBetween(camLook, toTarget.Unit)
						if ang < bestAngle then
							bestAngle = ang
							bestPart = part
						end
					end
				end
			end
		end
	end

	return bestPart
end

local function getLockedTargetPart()
	local plr = getPlayerByUserId(SelectedTargetUserId)
	if not plr then return nil end

	local char = safeGetCharacter(plr)
	if not char then return nil end

	local part = getTargetPart(char)
	if not isValidTarget(plr, part) then return nil end

	-- gating (no yanking)
	local camPos = camera.CFrame.Position
	local camLook = camera.CFrame.LookVector.Unit

	local toTarget = part.Position - camPos
	if toTarget.Magnitude > Settings.MaxDistance then return nil end
	if angleBetween(camLook, toTarget.Unit) > Settings.MaxFOV then return nil end

	return part
end

connect(RunService.RenderStepped, function()
	if destroyed then return end
	if not isAssistActive() then return end

	local targetPart
	if SelectedTargetUserId then
		targetPart = getLockedTargetPart()
	else
		targetPart = getBestTargetAuto()
	end
	if not targetPart then return end

	local camPos = camera.CFrame.Position
	local aimPoint = predictAimPoint(targetPart)

	local desiredDir = (aimPoint - camPos).Unit
	local currentDir = camera.CFrame.LookVector.Unit

	if angleBetween(currentDir, desiredDir) > Settings.MaxFOV then return end

	local newDir = currentDir:Lerp(desiredDir, Settings.Smoothing)
	camera.CFrame = CFrame.new(camPos, camPos + newDir)
end)

Features & Information

Automatically aims at a target with configurable options, higher smoothing means locking on faster & harder to the target's future position, and lead time changes that. (Made by ChatGPT 5.2)
#aimbot#hax#universal#ai#aigenerated

Community Comments (1)

GrokaimasterGrokaimasterDec 25, 2025

Tell me your prompt

More Scripts for Universal Scripts