2773 lines
80 KiB
Lua
2773 lines
80 KiB
Lua
if type(_G.RainbowEliteRuntime) == "table" and type(_G.RainbowEliteRuntime.Cleanup) == "function" then
|
|
pcall(_G.RainbowEliteRuntime.Cleanup)
|
|
end
|
|
|
|
local runtime = {connections = {}, drawings = {}}
|
|
|
|
function runtime.Cleanup()
|
|
if type(runtime.restoreNoclip) == "function" then
|
|
pcall(runtime.restoreNoclip)
|
|
end
|
|
|
|
if type(runtime.restoreVisibility) == "function" then
|
|
pcall(runtime.restoreVisibility)
|
|
end
|
|
|
|
pcall(function()
|
|
local inputService = game:GetService("UserInputService")
|
|
inputService.MouseBehavior = Enum.MouseBehavior.Default
|
|
inputService.MouseIconEnabled = true
|
|
end)
|
|
|
|
for _, connection in ipairs(runtime.connections) do
|
|
pcall(function()
|
|
if connection and connection.Connected then
|
|
connection:Disconnect()
|
|
end
|
|
end)
|
|
end
|
|
|
|
if runtime.gui then
|
|
pcall(function()
|
|
runtime.gui:Destroy()
|
|
end)
|
|
end
|
|
|
|
for _, drawing in ipairs(runtime.drawings) do
|
|
pcall(function()
|
|
if drawing and drawing.Remove then
|
|
drawing:Remove()
|
|
end
|
|
end)
|
|
end
|
|
|
|
runtime.connections = {}
|
|
runtime.drawings = {}
|
|
end
|
|
|
|
_G.RainbowEliteRuntime = runtime
|
|
|
|
local function trackConnection(connection)
|
|
table.insert(runtime.connections, connection)
|
|
return connection
|
|
end
|
|
|
|
local function trackDrawing(drawing)
|
|
table.insert(runtime.drawings, drawing)
|
|
return drawing
|
|
end
|
|
|
|
local Players = game:GetService("Players")
|
|
local UserInputService = game:GetService("UserInputService")
|
|
local RunService = game:GetService("RunService")
|
|
local HttpService = game:GetService("HttpService")
|
|
local CoreGui = game:GetService("CoreGui")
|
|
|
|
local LocalPlayer = Players.LocalPlayer
|
|
local Camera = workspace.CurrentCamera
|
|
local Mouse = LocalPlayer:GetMouse()
|
|
|
|
trackConnection(workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
|
|
Camera = workspace.CurrentCamera
|
|
end))
|
|
|
|
local SETTINGS_FILE = "rainbow_elite_settings.json"
|
|
local MAX_TELEPORT_POINTS = 60
|
|
local HIDDEN_PARK_OFFSET = Vector3.new(1800, 2200, 1800)
|
|
|
|
local DEFAULT_SETTINGS = {
|
|
uiVisible = true,
|
|
uiToggleKey = "LeftControl",
|
|
|
|
aimEnabled = false,
|
|
aimFOV = 150,
|
|
aimKey = "E",
|
|
aimShowFovCircle = true,
|
|
aimUseRightMouse = false,
|
|
autoStopEnabled = false,
|
|
ignoreTeam = true,
|
|
|
|
thirdPerson = false,
|
|
speedEnabled = false,
|
|
walkSpeed = 50,
|
|
highHealthEnabled = false,
|
|
highHealthValue = 500,
|
|
playerVisible = true,
|
|
|
|
espEnabled = false,
|
|
espToggleKey = "P",
|
|
espShowName = true,
|
|
espShowDistance = true,
|
|
espShowTracers = false,
|
|
espShowBox = false,
|
|
espDistanceIndicator = false,
|
|
espIgnoreTeam = true,
|
|
espTextSize = 15,
|
|
espRefreshMs = 150,
|
|
espMaxDistance = 1500,
|
|
espInactiveDetection = false,
|
|
multiSelectMode = false,
|
|
|
|
teleportViewKey = "V",
|
|
teleportPointKey = "Equals",
|
|
birdTeleportKey = "Minus",
|
|
sniperKillKey = "BackSlash",
|
|
sniperStayHidden = false,
|
|
sniperRandomDeltaMagnitude = 0,
|
|
sniperReturnDelayMs = 10,
|
|
cursorReleaseKey = "RightAlt",
|
|
teleportPoints = {}
|
|
}
|
|
|
|
local settings = {}
|
|
|
|
local function copyTeleportPoints(points)
|
|
local copied = {}
|
|
|
|
if type(points) ~= "table" then
|
|
return copied
|
|
end
|
|
|
|
for index, point in ipairs(points) do
|
|
if index > MAX_TELEPORT_POINTS then
|
|
break
|
|
end
|
|
|
|
if type(point) == "table" then
|
|
local name = type(point.name) == "string" and point.name:sub(1, 32) or ("Point " .. tostring(index))
|
|
local x = tonumber(point.x)
|
|
local y = tonumber(point.y)
|
|
local z = tonumber(point.z)
|
|
|
|
if x and y and z then
|
|
copied[#copied + 1] = {name = name, x = x, y = y, z = z}
|
|
end
|
|
end
|
|
end
|
|
|
|
return copied
|
|
end
|
|
|
|
local function applyDefaultSettings()
|
|
for key, value in pairs(DEFAULT_SETTINGS) do
|
|
if key == "teleportPoints" then
|
|
settings[key] = copyTeleportPoints(value)
|
|
else
|
|
settings[key] = value
|
|
end
|
|
end
|
|
end
|
|
|
|
applyDefaultSettings()
|
|
|
|
local canPersist = type(readfile) == "function" and type(writefile) == "function"
|
|
|
|
local function clampNumber(value, minValue, maxValue, fallback)
|
|
if type(value) ~= "number" then
|
|
return fallback
|
|
end
|
|
|
|
return math.clamp(value, minValue, maxValue)
|
|
end
|
|
|
|
local function readBoolean(value, fallback)
|
|
if type(value) == "boolean" then
|
|
return value
|
|
end
|
|
|
|
return fallback
|
|
end
|
|
|
|
local function normaliseKeyName(value, fallback)
|
|
if type(value) ~= "string" then
|
|
return fallback
|
|
end
|
|
|
|
local enumItem = Enum.KeyCode[value]
|
|
if enumItem and enumItem ~= Enum.KeyCode.Unknown then
|
|
return value
|
|
end
|
|
|
|
return fallback
|
|
end
|
|
|
|
local function loadSettings()
|
|
if not canPersist then
|
|
return
|
|
end
|
|
|
|
local fileOk, rawData = pcall(readfile, SETTINGS_FILE)
|
|
if not fileOk or type(rawData) ~= "string" or rawData == "" then
|
|
return
|
|
end
|
|
|
|
local decodeOk, parsed = pcall(function()
|
|
return HttpService:JSONDecode(rawData)
|
|
end)
|
|
|
|
if not decodeOk or type(parsed) ~= "table" then
|
|
return
|
|
end
|
|
|
|
settings.uiVisible = readBoolean(parsed.uiVisible, settings.uiVisible)
|
|
settings.uiToggleKey = normaliseKeyName(parsed.uiToggleKey, settings.uiToggleKey)
|
|
|
|
settings.aimEnabled = readBoolean(parsed.aimEnabled, settings.aimEnabled)
|
|
settings.aimFOV = math.floor(clampNumber(parsed.aimFOV, 25, 600, settings.aimFOV) + 0.5)
|
|
settings.aimKey = normaliseKeyName(parsed.aimKey, settings.aimKey)
|
|
settings.aimShowFovCircle = readBoolean(parsed.aimShowFovCircle, settings.aimShowFovCircle)
|
|
settings.aimUseRightMouse = readBoolean(parsed.aimUseRightMouse, settings.aimUseRightMouse)
|
|
settings.autoStopEnabled = readBoolean(parsed.autoStopEnabled, settings.autoStopEnabled)
|
|
settings.ignoreTeam = readBoolean(parsed.ignoreTeam, settings.ignoreTeam)
|
|
|
|
settings.thirdPerson = readBoolean(parsed.thirdPerson, settings.thirdPerson)
|
|
settings.speedEnabled = readBoolean(parsed.speedEnabled, settings.speedEnabled)
|
|
settings.walkSpeed = math.floor(clampNumber(parsed.walkSpeed, 16, 200, settings.walkSpeed) + 0.5)
|
|
settings.highHealthEnabled = readBoolean(parsed.highHealthEnabled, settings.highHealthEnabled)
|
|
settings.highHealthValue = math.floor(clampNumber(parsed.highHealthValue, 100, 50000, settings.highHealthValue) + 0.5)
|
|
settings.playerVisible = readBoolean(parsed.playerVisible, settings.playerVisible)
|
|
|
|
settings.espEnabled = readBoolean(parsed.espEnabled, settings.espEnabled)
|
|
settings.espToggleKey = normaliseKeyName(parsed.espToggleKey, settings.espToggleKey)
|
|
settings.espShowName = readBoolean(parsed.espShowName, settings.espShowName)
|
|
settings.espShowDistance = readBoolean(parsed.espShowDistance, settings.espShowDistance)
|
|
settings.espShowTracers = readBoolean(parsed.espShowTracers, settings.espShowTracers)
|
|
settings.espShowBox = readBoolean(parsed.espShowBox, settings.espShowBox)
|
|
settings.espDistanceIndicator = readBoolean(parsed.espDistanceIndicator, settings.espDistanceIndicator)
|
|
settings.espIgnoreTeam = readBoolean(parsed.espIgnoreTeam, settings.espIgnoreTeam)
|
|
settings.espTextSize = math.floor(clampNumber(parsed.espTextSize, 10, 22, settings.espTextSize) + 0.5)
|
|
settings.espRefreshMs = math.floor(clampNumber(parsed.espRefreshMs, 33, 500, settings.espRefreshMs) + 0.5)
|
|
settings.espMaxDistance = math.floor(clampNumber(parsed.espMaxDistance, 50, 10000, settings.espMaxDistance) + 0.5)
|
|
settings.espInactiveDetection = readBoolean(parsed.espInactiveDetection, settings.espInactiveDetection)
|
|
settings.multiSelectMode = readBoolean(parsed.multiSelectMode, settings.multiSelectMode)
|
|
|
|
settings.teleportViewKey = normaliseKeyName(parsed.teleportViewKey, settings.teleportViewKey)
|
|
settings.teleportPointKey = normaliseKeyName(parsed.teleportPointKey, settings.teleportPointKey)
|
|
|
|
local loadedBirdKey = normaliseKeyName(parsed.birdTeleportKey, settings.birdTeleportKey)
|
|
if loadedBirdKey == "B" then
|
|
loadedBirdKey = "Minus"
|
|
end
|
|
settings.birdTeleportKey = loadedBirdKey
|
|
|
|
settings.sniperKillKey = normaliseKeyName(parsed.sniperKillKey, settings.sniperKillKey)
|
|
settings.sniperStayHidden = readBoolean(parsed.sniperStayHidden, settings.sniperStayHidden)
|
|
|
|
local randomDeltaMagnitude = clampNumber(parsed.sniperRandomDeltaMagnitude, 0, 0.25, settings.sniperRandomDeltaMagnitude)
|
|
if type(parsed.sniperRandomDeltaEnabled) == "boolean" and parsed.sniperRandomDeltaEnabled and randomDeltaMagnitude <= 0 then
|
|
randomDeltaMagnitude = 0.08
|
|
end
|
|
settings.sniperRandomDeltaMagnitude = randomDeltaMagnitude
|
|
|
|
settings.sniperReturnDelayMs = math.floor(clampNumber(parsed.sniperReturnDelayMs, 0, 2000, settings.sniperReturnDelayMs) + 0.5)
|
|
settings.cursorReleaseKey = normaliseKeyName(parsed.cursorReleaseKey, settings.cursorReleaseKey)
|
|
settings.teleportPoints = copyTeleportPoints(parsed.teleportPoints)
|
|
end
|
|
|
|
local function saveSettings()
|
|
if not canPersist then
|
|
return
|
|
end
|
|
|
|
local payload = {}
|
|
for key, value in pairs(settings) do
|
|
if key == "teleportPoints" then
|
|
payload[key] = copyTeleportPoints(value)
|
|
else
|
|
payload[key] = value
|
|
end
|
|
end
|
|
|
|
local encodeOk, encoded = pcall(function()
|
|
return HttpService:JSONEncode(payload)
|
|
end)
|
|
|
|
if not encodeOk then
|
|
return
|
|
end
|
|
|
|
pcall(writefile, SETTINGS_FILE, encoded)
|
|
end
|
|
|
|
loadSettings()
|
|
|
|
local existingGui = CoreGui:FindFirstChild("RainbowEliteStandardUI")
|
|
if existingGui then
|
|
existingGui:Destroy()
|
|
end
|
|
|
|
local ScreenGui = Instance.new("ScreenGui")
|
|
ScreenGui.Name = "RainbowEliteStandardUI"
|
|
ScreenGui.ResetOnSpawn = false
|
|
ScreenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
|
|
ScreenGui.Parent = CoreGui
|
|
runtime.gui = ScreenGui
|
|
|
|
local ModeOverlay = Instance.new("TextLabel")
|
|
ModeOverlay.Size = UDim2.new(0, 360, 0, 24)
|
|
ModeOverlay.Position = UDim2.new(0.5, -180, 0, 14)
|
|
ModeOverlay.BackgroundColor3 = Color3.fromRGB(30, 30, 35)
|
|
ModeOverlay.BackgroundTransparency = 0.2
|
|
ModeOverlay.BorderSizePixel = 0
|
|
ModeOverlay.Font = Enum.Font.GothamSemibold
|
|
ModeOverlay.TextSize = 12
|
|
ModeOverlay.TextColor3 = Color3.fromRGB(255, 224, 170)
|
|
ModeOverlay.Text = ""
|
|
ModeOverlay.Visible = false
|
|
ModeOverlay.Parent = ScreenGui
|
|
|
|
local modeOverlayCorner = Instance.new("UICorner")
|
|
modeOverlayCorner.CornerRadius = UDim.new(0, 6)
|
|
modeOverlayCorner.Parent = ModeOverlay
|
|
|
|
local modeOverlayStroke = Instance.new("UIStroke")
|
|
modeOverlayStroke.Thickness = 1
|
|
modeOverlayStroke.Color = Color3.fromRGB(92, 78, 54)
|
|
modeOverlayStroke.Parent = ModeOverlay
|
|
|
|
local MainFrame = Instance.new("Frame")
|
|
MainFrame.Size = UDim2.new(0, 560, 0, 420)
|
|
MainFrame.Position = UDim2.new(0.5, -280, 0.5, -210)
|
|
MainFrame.BackgroundColor3 = Color3.fromRGB(24, 24, 28)
|
|
MainFrame.BorderSizePixel = 0
|
|
MainFrame.Active = true
|
|
MainFrame.Draggable = true
|
|
MainFrame.Visible = settings.uiVisible
|
|
MainFrame.Parent = ScreenGui
|
|
|
|
local mainCorner = Instance.new("UICorner")
|
|
mainCorner.CornerRadius = UDim.new(0, 8)
|
|
mainCorner.Parent = MainFrame
|
|
|
|
local mainStroke = Instance.new("UIStroke")
|
|
mainStroke.Thickness = 1
|
|
mainStroke.Color = Color3.fromRGB(66, 66, 74)
|
|
mainStroke.Parent = MainFrame
|
|
|
|
local TopBar = Instance.new("Frame")
|
|
TopBar.Size = UDim2.new(1, 0, 0, 44)
|
|
TopBar.BackgroundColor3 = Color3.fromRGB(30, 30, 35)
|
|
TopBar.BorderSizePixel = 0
|
|
TopBar.Parent = MainFrame
|
|
|
|
local topCorner = Instance.new("UICorner")
|
|
topCorner.CornerRadius = UDim.new(0, 8)
|
|
topCorner.Parent = TopBar
|
|
|
|
local Title = Instance.new("TextLabel")
|
|
Title.Size = UDim2.new(1, -16, 1, 0)
|
|
Title.Position = UDim2.new(0, 12, 0, 0)
|
|
Title.BackgroundTransparency = 1
|
|
Title.TextXAlignment = Enum.TextXAlignment.Left
|
|
Title.Font = Enum.Font.GothamSemibold
|
|
Title.TextSize = 14
|
|
Title.TextColor3 = Color3.fromRGB(245, 245, 245)
|
|
Title.Text = "Rainbow Elite"
|
|
Title.Parent = TopBar
|
|
|
|
local Hint = Instance.new("TextLabel")
|
|
Hint.Size = UDim2.new(1, -16, 0, 18)
|
|
Hint.Position = UDim2.new(0, 12, 1, -20)
|
|
Hint.BackgroundTransparency = 1
|
|
Hint.TextXAlignment = Enum.TextXAlignment.Left
|
|
Hint.Font = Enum.Font.Gotham
|
|
Hint.TextSize = 11
|
|
Hint.TextColor3 = Color3.fromRGB(170, 170, 180)
|
|
Hint.Parent = TopBar
|
|
|
|
local ModeStatus = Instance.new("TextLabel")
|
|
ModeStatus.Size = UDim2.new(0, 250, 0, 18)
|
|
ModeStatus.Position = UDim2.new(1, -258, 0, 4)
|
|
ModeStatus.BackgroundTransparency = 1
|
|
ModeStatus.TextXAlignment = Enum.TextXAlignment.Right
|
|
ModeStatus.Font = Enum.Font.GothamSemibold
|
|
ModeStatus.TextSize = 11
|
|
ModeStatus.TextColor3 = Color3.fromRGB(245, 196, 120)
|
|
ModeStatus.Text = ""
|
|
ModeStatus.Parent = TopBar
|
|
|
|
local TabBar = Instance.new("Frame")
|
|
TabBar.Size = UDim2.new(1, -20, 0, 34)
|
|
TabBar.Position = UDim2.new(0, 10, 0, 56)
|
|
TabBar.BackgroundTransparency = 1
|
|
TabBar.Parent = MainFrame
|
|
|
|
local tabLayout = Instance.new("UIListLayout")
|
|
tabLayout.FillDirection = Enum.FillDirection.Horizontal
|
|
tabLayout.HorizontalAlignment = Enum.HorizontalAlignment.Left
|
|
tabLayout.VerticalAlignment = Enum.VerticalAlignment.Center
|
|
tabLayout.Padding = UDim.new(0, 8)
|
|
tabLayout.Parent = TabBar
|
|
|
|
local Pages = Instance.new("Frame")
|
|
Pages.Size = UDim2.new(1, -20, 1, -106)
|
|
Pages.Position = UDim2.new(0, 10, 0, 96)
|
|
Pages.BackgroundTransparency = 1
|
|
Pages.Parent = MainFrame
|
|
|
|
local function createButton(parent, text)
|
|
local button = Instance.new("TextButton")
|
|
button.AutoButtonColor = false
|
|
button.Text = text
|
|
button.Font = Enum.Font.GothamSemibold
|
|
button.TextSize = 12
|
|
button.TextColor3 = Color3.fromRGB(235, 235, 235)
|
|
button.BackgroundColor3 = Color3.fromRGB(36, 36, 42)
|
|
button.BorderSizePixel = 0
|
|
button.Parent = parent
|
|
|
|
local corner = Instance.new("UICorner")
|
|
corner.CornerRadius = UDim.new(0, 6)
|
|
corner.Parent = button
|
|
|
|
local stroke = Instance.new("UIStroke")
|
|
stroke.Thickness = 1
|
|
stroke.Color = Color3.fromRGB(66, 66, 74)
|
|
stroke.Parent = button
|
|
|
|
return button
|
|
end
|
|
|
|
local function createPage(name)
|
|
local page = Instance.new("ScrollingFrame")
|
|
page.Name = name .. "Page"
|
|
page.Size = UDim2.new(1, 0, 1, 0)
|
|
page.BackgroundTransparency = 1
|
|
page.BorderSizePixel = 0
|
|
page.Visible = false
|
|
page.ScrollBarThickness = 5
|
|
page.ScrollBarImageColor3 = Color3.fromRGB(80, 80, 88)
|
|
page.ScrollingDirection = Enum.ScrollingDirection.Y
|
|
page.AutomaticCanvasSize = Enum.AutomaticSize.Y
|
|
page.CanvasSize = UDim2.new(0, 0, 0, 0)
|
|
page.Parent = Pages
|
|
|
|
local padding = Instance.new("UIPadding")
|
|
padding.PaddingTop = UDim.new(0, 4)
|
|
padding.PaddingBottom = UDim.new(0, 4)
|
|
padding.PaddingRight = UDim.new(0, 2)
|
|
padding.Parent = page
|
|
|
|
local listLayout = Instance.new("UIListLayout")
|
|
listLayout.Padding = UDim.new(0, 8)
|
|
listLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
|
|
listLayout.Parent = page
|
|
|
|
return page
|
|
end
|
|
|
|
local function createRow(page, labelText)
|
|
local row = Instance.new("Frame")
|
|
row.Size = UDim2.new(1, -6, 0, 38)
|
|
row.BackgroundColor3 = Color3.fromRGB(30, 30, 35)
|
|
row.BorderSizePixel = 0
|
|
row.Parent = page
|
|
|
|
local corner = Instance.new("UICorner")
|
|
corner.CornerRadius = UDim.new(0, 6)
|
|
corner.Parent = row
|
|
|
|
local stroke = Instance.new("UIStroke")
|
|
stroke.Thickness = 1
|
|
stroke.Color = Color3.fromRGB(58, 58, 64)
|
|
stroke.Parent = row
|
|
|
|
local label = Instance.new("TextLabel")
|
|
label.Size = UDim2.new(0.56, 0, 1, 0)
|
|
label.Position = UDim2.new(0, 10, 0, 0)
|
|
label.BackgroundTransparency = 1
|
|
label.TextXAlignment = Enum.TextXAlignment.Left
|
|
label.Font = Enum.Font.Gotham
|
|
label.TextSize = 12
|
|
label.TextColor3 = Color3.fromRGB(235, 235, 235)
|
|
label.Text = labelText
|
|
label.Parent = row
|
|
|
|
local control = Instance.new("Frame")
|
|
control.Size = UDim2.new(0, 180, 1, -8)
|
|
control.Position = UDim2.new(1, -188, 0, 4)
|
|
control.BackgroundTransparency = 1
|
|
control.Parent = row
|
|
|
|
return control
|
|
end
|
|
|
|
local tabButtons = {}
|
|
local tabPages = {}
|
|
|
|
local function switchTab(tabName)
|
|
for name, page in pairs(tabPages) do
|
|
local isActive = name == tabName
|
|
page.Visible = isActive
|
|
|
|
local button = tabButtons[name]
|
|
if button then
|
|
button.BackgroundColor3 = isActive and Color3.fromRGB(58, 58, 64) or Color3.fromRGB(36, 36, 42)
|
|
button.TextColor3 = isActive and Color3.fromRGB(255, 255, 255) or Color3.fromRGB(205, 205, 210)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function addTab(name)
|
|
local button = createButton(TabBar, name)
|
|
button.Size = UDim2.new(0, 68, 1, 0)
|
|
|
|
local page = createPage(name)
|
|
|
|
tabButtons[name] = button
|
|
tabPages[name] = page
|
|
|
|
trackConnection(button.MouseButton1Click:Connect(function()
|
|
switchTab(name)
|
|
end))
|
|
|
|
return page
|
|
end
|
|
|
|
local refreshers = {}
|
|
|
|
local function refreshAll()
|
|
for _, refresh in ipairs(refreshers) do
|
|
refresh()
|
|
end
|
|
end
|
|
|
|
local function addToggleRow(page, labelText, getter, setter)
|
|
local control = createRow(page, labelText)
|
|
local button = createButton(control, "")
|
|
button.Size = UDim2.new(1, 0, 1, 0)
|
|
|
|
local function refresh()
|
|
local state = getter()
|
|
button.Text = state and "ON" or "OFF"
|
|
button.BackgroundColor3 = state and Color3.fromRGB(46, 132, 82) or Color3.fromRGB(68, 68, 76)
|
|
end
|
|
|
|
trackConnection(button.MouseButton1Click:Connect(function()
|
|
setter(not getter())
|
|
refreshAll()
|
|
end))
|
|
|
|
table.insert(refreshers, refresh)
|
|
refresh()
|
|
|
|
return button
|
|
end
|
|
|
|
local function addNumberRow(page, labelText, getter, setter, minValue, maxValue)
|
|
local control = createRow(page, labelText)
|
|
|
|
local box = Instance.new("TextBox")
|
|
box.Size = UDim2.new(1, 0, 1, 0)
|
|
box.BackgroundColor3 = Color3.fromRGB(36, 36, 42)
|
|
box.BorderSizePixel = 0
|
|
box.Font = Enum.Font.GothamSemibold
|
|
box.TextSize = 12
|
|
box.TextColor3 = Color3.fromRGB(240, 240, 240)
|
|
box.ClearTextOnFocus = false
|
|
box.Parent = control
|
|
|
|
local corner = Instance.new("UICorner")
|
|
corner.CornerRadius = UDim.new(0, 6)
|
|
corner.Parent = box
|
|
|
|
local stroke = Instance.new("UIStroke")
|
|
stroke.Thickness = 1
|
|
stroke.Color = Color3.fromRGB(66, 66, 74)
|
|
stroke.Parent = box
|
|
|
|
local function refresh()
|
|
box.Text = tostring(getter())
|
|
end
|
|
|
|
trackConnection(box.FocusLost:Connect(function()
|
|
local parsed = tonumber(box.Text:match("[%d%.]+"))
|
|
if parsed then
|
|
local clamped = math.floor(math.clamp(parsed, minValue, maxValue) + 0.5)
|
|
setter(clamped)
|
|
end
|
|
refresh()
|
|
end))
|
|
|
|
table.insert(refreshers, refresh)
|
|
refresh()
|
|
|
|
return box
|
|
end
|
|
|
|
local function addDecimalRow(page, labelText, getter, setter, minValue, maxValue, decimals)
|
|
local control = createRow(page, labelText)
|
|
|
|
local box = Instance.new("TextBox")
|
|
box.Size = UDim2.new(1, 0, 1, 0)
|
|
box.BackgroundColor3 = Color3.fromRGB(36, 36, 42)
|
|
box.BorderSizePixel = 0
|
|
box.Font = Enum.Font.GothamSemibold
|
|
box.TextSize = 12
|
|
box.TextColor3 = Color3.fromRGB(240, 240, 240)
|
|
box.ClearTextOnFocus = false
|
|
box.Parent = control
|
|
|
|
local corner = Instance.new("UICorner")
|
|
corner.CornerRadius = UDim.new(0, 6)
|
|
corner.Parent = box
|
|
|
|
local stroke = Instance.new("UIStroke")
|
|
stroke.Thickness = 1
|
|
stroke.Color = Color3.fromRGB(66, 66, 74)
|
|
stroke.Parent = box
|
|
|
|
local precision = math.floor(math.clamp(tonumber(decimals) or 3, 0, 4))
|
|
local formatString = "%." .. tostring(precision) .. "f"
|
|
|
|
local function refresh()
|
|
local value = tonumber(getter()) or minValue
|
|
box.Text = string.format(formatString, value)
|
|
end
|
|
|
|
trackConnection(box.FocusLost:Connect(function()
|
|
local parsed = tonumber(box.Text:match("[-%d%.]+"))
|
|
if parsed then
|
|
local clamped = math.clamp(parsed, minValue, maxValue)
|
|
setter(clamped)
|
|
end
|
|
refresh()
|
|
end))
|
|
|
|
table.insert(refreshers, refresh)
|
|
refresh()
|
|
|
|
return box
|
|
end
|
|
|
|
local function addActionRow(page, labelText, buttonText, callback)
|
|
local control = createRow(page, labelText)
|
|
local button = createButton(control, buttonText)
|
|
button.Size = UDim2.new(1, 0, 1, 0)
|
|
|
|
trackConnection(button.MouseButton1Click:Connect(callback))
|
|
|
|
return button
|
|
end
|
|
|
|
local function addDynamicActionRow(page, labelText, getButtonText, callback)
|
|
local control = createRow(page, labelText)
|
|
local button = createButton(control, "")
|
|
button.Size = UDim2.new(1, 0, 1, 0)
|
|
|
|
local function refresh()
|
|
button.Text = getButtonText()
|
|
end
|
|
|
|
trackConnection(button.MouseButton1Click:Connect(function()
|
|
callback()
|
|
refreshAll()
|
|
end))
|
|
|
|
table.insert(refreshers, refresh)
|
|
refresh()
|
|
|
|
return button
|
|
end
|
|
|
|
local currentAimKey = Enum.KeyCode.E
|
|
local currentEspToggleKey = Enum.KeyCode.P
|
|
local currentUiToggleKey = Enum.KeyCode.LeftControl
|
|
local currentTeleportViewKey = Enum.KeyCode.V
|
|
local currentTeleportPointKey = Enum.KeyCode.Equals
|
|
local currentBirdTeleportKey = Enum.KeyCode.Minus
|
|
local currentSniperKillKey = Enum.KeyCode.BackSlash
|
|
local currentCursorReleaseKey = Enum.KeyCode.RightAlt
|
|
|
|
local bindingTarget = nil
|
|
|
|
local aimHoldingKeyboard = false
|
|
local aimHoldingMouse = false
|
|
local isHoldingAim = false
|
|
local autoStopHolding = false
|
|
local cursorReleased = false
|
|
local birdTeleportActive = false
|
|
|
|
local birdProxyModel = nil
|
|
local birdProxyRootPart = nil
|
|
local birdProxyHumanoid = nil
|
|
local birdParkPosition = nil
|
|
local birdMaintenanceAccumulator = 0
|
|
|
|
local function recomputeAimHolding()
|
|
isHoldingAim = aimHoldingKeyboard or (settings.aimUseRightMouse and aimHoldingMouse)
|
|
end
|
|
|
|
local function isBoundKeyPressed(inputKeyCode, targetKeyCode)
|
|
if inputKeyCode == targetKeyCode then
|
|
return true
|
|
end
|
|
|
|
if targetKeyCode == Enum.KeyCode.Minus and inputKeyCode == Enum.KeyCode.KeypadMinus then
|
|
return true
|
|
end
|
|
|
|
if targetKeyCode == Enum.KeyCode.BackSlash and inputKeyCode == Enum.KeyCode.Slash then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local function refreshKeyObjects()
|
|
currentAimKey = Enum.KeyCode[settings.aimKey] or Enum.KeyCode.E
|
|
currentEspToggleKey = Enum.KeyCode[settings.espToggleKey] or Enum.KeyCode.P
|
|
currentUiToggleKey = Enum.KeyCode[settings.uiToggleKey] or Enum.KeyCode.LeftControl
|
|
currentTeleportViewKey = Enum.KeyCode[settings.teleportViewKey] or Enum.KeyCode.V
|
|
currentTeleportPointKey = Enum.KeyCode[settings.teleportPointKey] or Enum.KeyCode.Equals
|
|
currentBirdTeleportKey = Enum.KeyCode[settings.birdTeleportKey] or Enum.KeyCode.Minus
|
|
currentSniperKillKey = Enum.KeyCode[settings.sniperKillKey] or Enum.KeyCode.BackSlash
|
|
currentCursorReleaseKey = Enum.KeyCode[settings.cursorReleaseKey] or Enum.KeyCode.RightAlt
|
|
end
|
|
|
|
refreshKeyObjects()
|
|
|
|
local trackedPlayers = {}
|
|
local selectedTeleportPlayerUserId = nil
|
|
local selectedTeleportPlayerUserIds = {}
|
|
|
|
local function rebuildTrackedPlayers()
|
|
trackedPlayers = {}
|
|
for _, player in ipairs(Players:GetPlayers()) do
|
|
if player ~= LocalPlayer then
|
|
trackedPlayers[#trackedPlayers + 1] = player
|
|
end
|
|
end
|
|
end
|
|
|
|
local function removeTrackedPlayer(player)
|
|
if player and selectedTeleportPlayerUserId == player.UserId then
|
|
selectedTeleportPlayerUserId = nil
|
|
end
|
|
|
|
if player then
|
|
selectedTeleportPlayerUserIds[player.UserId] = nil
|
|
end
|
|
|
|
for index = #trackedPlayers, 1, -1 do
|
|
if trackedPlayers[index] == player then
|
|
table.remove(trackedPlayers, index)
|
|
if selectedTeleportPlayerIndex > #trackedPlayers then
|
|
selectedTeleportPlayerIndex = math.max(#trackedPlayers, 1)
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
rebuildTrackedPlayers()
|
|
|
|
local selectedTeleportPointIndex = 1
|
|
local selectedTeleportPlayerIndex = 1
|
|
selectedTeleportPlayerUserId = nil
|
|
|
|
local function normaliseSelectedTeleportPointIndex()
|
|
local count = #settings.teleportPoints
|
|
if count < 1 then
|
|
selectedTeleportPointIndex = 1
|
|
return
|
|
end
|
|
|
|
if selectedTeleportPointIndex < 1 then
|
|
selectedTeleportPointIndex = count
|
|
elseif selectedTeleportPointIndex > count then
|
|
selectedTeleportPointIndex = 1
|
|
end
|
|
end
|
|
|
|
local function getSelectedTeleportPoint()
|
|
normaliseSelectedTeleportPointIndex()
|
|
return settings.teleportPoints[selectedTeleportPointIndex]
|
|
end
|
|
|
|
local function getSelectedTeleportPointLabel()
|
|
local point = getSelectedTeleportPoint()
|
|
if not point then
|
|
return "None"
|
|
end
|
|
|
|
return string.format("%d/%d %s", selectedTeleportPointIndex, #settings.teleportPoints, point.name)
|
|
end
|
|
|
|
local function cycleTeleportPoint()
|
|
if #settings.teleportPoints < 1 then
|
|
return
|
|
end
|
|
|
|
selectedTeleportPointIndex = selectedTeleportPointIndex + 1
|
|
normaliseSelectedTeleportPointIndex()
|
|
end
|
|
|
|
local function getLocalRootPart()
|
|
local character = LocalPlayer.Character
|
|
if not character then
|
|
return nil
|
|
end
|
|
|
|
return character:FindFirstChild("HumanoidRootPart")
|
|
end
|
|
|
|
local function teleportToPosition(targetPosition)
|
|
local rootPart = getLocalRootPart()
|
|
if not rootPart then
|
|
return false
|
|
end
|
|
|
|
rootPart.CFrame = CFrame.new(targetPosition + Vector3.new(0, 3, 0))
|
|
pcall(function()
|
|
rootPart.AssemblyLinearVelocity = Vector3.zero
|
|
rootPart.AssemblyAngularVelocity = Vector3.zero
|
|
end)
|
|
|
|
return true
|
|
end
|
|
|
|
local function addTeleportPoint()
|
|
local rootPart = getLocalRootPart()
|
|
if not rootPart then
|
|
return false
|
|
end
|
|
|
|
if #settings.teleportPoints >= MAX_TELEPORT_POINTS then
|
|
table.remove(settings.teleportPoints, 1)
|
|
end
|
|
|
|
local pointName = "Point " .. tostring(#settings.teleportPoints + 1)
|
|
local position = rootPart.Position
|
|
|
|
settings.teleportPoints[#settings.teleportPoints + 1] = {
|
|
name = pointName,
|
|
x = position.X,
|
|
y = position.Y,
|
|
z = position.Z
|
|
}
|
|
|
|
selectedTeleportPointIndex = #settings.teleportPoints
|
|
return true
|
|
end
|
|
|
|
local function deleteSelectedTeleportPoint()
|
|
local point = getSelectedTeleportPoint()
|
|
if not point then
|
|
return false
|
|
end
|
|
|
|
table.remove(settings.teleportPoints, selectedTeleportPointIndex)
|
|
normaliseSelectedTeleportPointIndex()
|
|
return true
|
|
end
|
|
|
|
local function teleportToSelectedPoint()
|
|
local point = getSelectedTeleportPoint()
|
|
if not point then
|
|
return false
|
|
end
|
|
|
|
return teleportToPosition(Vector3.new(point.x, point.y, point.z))
|
|
end
|
|
|
|
local function normaliseSelectedTeleportPlayerIndex()
|
|
local count = #trackedPlayers
|
|
if count < 1 then
|
|
selectedTeleportPlayerIndex = 1
|
|
return
|
|
end
|
|
|
|
if selectedTeleportPlayerIndex < 1 then
|
|
selectedTeleportPlayerIndex = count
|
|
elseif selectedTeleportPlayerIndex > count then
|
|
selectedTeleportPlayerIndex = 1
|
|
end
|
|
end
|
|
|
|
local function resolveSelectedTeleportPlayer()
|
|
local count = #trackedPlayers
|
|
if count < 1 then
|
|
selectedTeleportPlayerIndex = 1
|
|
selectedTeleportPlayerUserId = nil
|
|
return nil, 0
|
|
end
|
|
|
|
if selectedTeleportPlayerUserId then
|
|
for index, player in ipairs(trackedPlayers) do
|
|
if player.UserId == selectedTeleportPlayerUserId then
|
|
selectedTeleportPlayerIndex = index
|
|
return player, index
|
|
end
|
|
end
|
|
end
|
|
|
|
normaliseSelectedTeleportPlayerIndex()
|
|
|
|
local selectedPlayer = trackedPlayers[selectedTeleportPlayerIndex]
|
|
selectedTeleportPlayerUserId = selectedPlayer and selectedPlayer.UserId or nil
|
|
return selectedPlayer, selectedTeleportPlayerIndex
|
|
end
|
|
|
|
local function getSelectedTeleportPlayer()
|
|
local selectedPlayer = resolveSelectedTeleportPlayer()
|
|
return selectedPlayer
|
|
end
|
|
|
|
local function getSelectedTeleportPlayerLabel()
|
|
local player, index = resolveSelectedTeleportPlayer()
|
|
if not player then
|
|
return "No players"
|
|
end
|
|
|
|
local suffix = ""
|
|
if settings.multiSelectMode and selectedTeleportPlayerUserIds[player.UserId] then
|
|
suffix = " [Selected]"
|
|
end
|
|
|
|
return string.format("%d/%d %s%s", index, #trackedPlayers, player.Name, suffix)
|
|
end
|
|
|
|
local function cycleTeleportPlayer()
|
|
local _, index = resolveSelectedTeleportPlayer()
|
|
if #trackedPlayers < 1 then
|
|
return
|
|
end
|
|
|
|
selectedTeleportPlayerIndex = index + 1
|
|
normaliseSelectedTeleportPlayerIndex()
|
|
|
|
local selectedPlayer = trackedPlayers[selectedTeleportPlayerIndex]
|
|
selectedTeleportPlayerUserId = selectedPlayer and selectedPlayer.UserId or nil
|
|
end
|
|
|
|
local function isTeleportPlayerInSelection(player)
|
|
if not player then
|
|
return false
|
|
end
|
|
|
|
return selectedTeleportPlayerUserIds[player.UserId] == true
|
|
end
|
|
|
|
local function toggleSelectedTeleportPlayerInSelection()
|
|
local player = getSelectedTeleportPlayer()
|
|
if not player then
|
|
return false
|
|
end
|
|
|
|
local userId = player.UserId
|
|
if selectedTeleportPlayerUserIds[userId] then
|
|
selectedTeleportPlayerUserIds[userId] = nil
|
|
else
|
|
selectedTeleportPlayerUserIds[userId] = true
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
local function clearTeleportPlayerSelection()
|
|
selectedTeleportPlayerUserIds = {}
|
|
end
|
|
|
|
local function getMultiSelectedTeleportPlayers()
|
|
local selectedPlayers = {}
|
|
|
|
for _, player in ipairs(trackedPlayers) do
|
|
if selectedTeleportPlayerUserIds[player.UserId] then
|
|
selectedPlayers[#selectedPlayers + 1] = player
|
|
end
|
|
end
|
|
|
|
return selectedPlayers
|
|
end
|
|
|
|
local function getMultiSelectedTeleportPlayersLabel()
|
|
if not settings.multiSelectMode then
|
|
return "Mode Off"
|
|
end
|
|
|
|
local selectedPlayers = getMultiSelectedTeleportPlayers()
|
|
if #selectedPlayers < 1 then
|
|
return "None"
|
|
end
|
|
|
|
if #selectedPlayers == 1 then
|
|
return selectedPlayers[1].Name
|
|
end
|
|
|
|
return tostring(#selectedPlayers) .. " players"
|
|
end
|
|
|
|
local function getCurrentSelectionActionLabel()
|
|
if not settings.multiSelectMode then
|
|
return "Mode Off"
|
|
end
|
|
|
|
local player = getSelectedTeleportPlayer()
|
|
if not player then
|
|
return "No players"
|
|
end
|
|
|
|
if isTeleportPlayerInSelection(player) then
|
|
return "Remove"
|
|
end
|
|
|
|
return "Add"
|
|
end
|
|
|
|
local function getSniperTargetPlayers()
|
|
if settings.multiSelectMode then
|
|
return getMultiSelectedTeleportPlayers()
|
|
end
|
|
|
|
local selectedPlayer = getSelectedTeleportPlayer()
|
|
if selectedPlayer then
|
|
return {selectedPlayer}
|
|
end
|
|
|
|
return {}
|
|
end
|
|
|
|
local function teleportToSelectedPlayer()
|
|
local player = getSelectedTeleportPlayer()
|
|
if not player then
|
|
return false
|
|
end
|
|
|
|
local character = player.Character
|
|
local rootPart = character and character:FindFirstChild("HumanoidRootPart")
|
|
if not rootPart then
|
|
return false
|
|
end
|
|
|
|
return teleportToPosition(rootPart.Position)
|
|
end
|
|
|
|
local function getTargetAimPart(character)
|
|
if not character then
|
|
return nil
|
|
end
|
|
|
|
return character:FindFirstChild("Head") or character:FindFirstChild("HumanoidRootPart")
|
|
end
|
|
|
|
local function getSniperAttackOffset(targetRootPart)
|
|
local offset = (targetRootPart.CFrame.LookVector * -2) + Vector3.new(0, 1.6, 0)
|
|
|
|
local randomDeltaMagnitude = math.clamp(tonumber(settings.sniperRandomDeltaMagnitude) or 0, 0, 0.25)
|
|
if randomDeltaMagnitude <= 0 then
|
|
return offset
|
|
end
|
|
|
|
local randomDirection = Vector3.new(
|
|
(math.random() * 2) - 1,
|
|
(math.random() * 2) - 1,
|
|
(math.random() * 2) - 1
|
|
)
|
|
|
|
if randomDirection.Magnitude < 0.001 then
|
|
randomDirection = Vector3.new(1, 0, 0)
|
|
end
|
|
|
|
return offset + (randomDirection.Unit * randomDeltaMagnitude)
|
|
end
|
|
|
|
local function fireSingleShot()
|
|
local character = LocalPlayer.Character
|
|
local equippedTool = character and character:FindFirstChildOfClass("Tool")
|
|
|
|
if equippedTool and type(equippedTool.Activate) == "function" then
|
|
pcall(function()
|
|
equippedTool:Activate()
|
|
end)
|
|
end
|
|
|
|
if type(mouse1press) == "function" and type(mouse1release) == "function" then
|
|
mouse1press()
|
|
task.wait(0.03)
|
|
mouse1release()
|
|
return true
|
|
end
|
|
|
|
if type(mouse1click) == "function" then
|
|
mouse1click()
|
|
return true
|
|
end
|
|
|
|
local ok = pcall(function()
|
|
local virtualInputManager = game:GetService("VirtualInputManager")
|
|
virtualInputManager:SendMouseButtonEvent(0, 0, 0, true, game, 0)
|
|
task.wait(0.10) -- not sure if this is enough
|
|
virtualInputManager:SendMouseButtonEvent(0, 0, 0, false, game, 0)
|
|
end)
|
|
|
|
return ok
|
|
end
|
|
|
|
local function sniperKillPlayer(player)
|
|
if birdTeleportActive then
|
|
return false
|
|
end
|
|
|
|
if not player then
|
|
return false
|
|
end
|
|
|
|
local localRootPart = getLocalRootPart()
|
|
if not localRootPart then
|
|
return false
|
|
end
|
|
|
|
local targetCharacter = player.Character
|
|
local targetHumanoid = targetCharacter and targetCharacter:FindFirstChildOfClass("Humanoid")
|
|
local targetRootPart = targetCharacter and targetCharacter:FindFirstChild("HumanoidRootPart")
|
|
local targetAimPart = getTargetAimPart(targetCharacter)
|
|
|
|
if not targetHumanoid or targetHumanoid.Health <= 0 or not targetRootPart or not targetAimPart then
|
|
return false
|
|
end
|
|
|
|
local originalCFrame = localRootPart.CFrame
|
|
local activeCamera = workspace.CurrentCamera or Camera
|
|
|
|
task.wait(0.01)
|
|
|
|
local returnDelay = math.max(settings.sniperReturnDelayMs or 0, 0) / 1000
|
|
local burstDeadline = os.clock() + returnDelay
|
|
local shotCount = 0
|
|
|
|
repeat
|
|
if not localRootPart.Parent then
|
|
break
|
|
end
|
|
|
|
targetCharacter = player.Character
|
|
targetHumanoid = targetCharacter and targetCharacter:FindFirstChildOfClass("Humanoid")
|
|
targetRootPart = targetCharacter and targetCharacter:FindFirstChild("HumanoidRootPart")
|
|
targetAimPart = getTargetAimPart(targetCharacter)
|
|
|
|
if not targetHumanoid or targetHumanoid.Health <= 0 or not targetRootPart or not targetAimPart then
|
|
break
|
|
end
|
|
|
|
local attackOffset = getSniperAttackOffset(targetRootPart)
|
|
local attackPosition = targetRootPart.Position + attackOffset
|
|
localRootPart.CFrame = CFrame.new(attackPosition, targetAimPart.Position)
|
|
|
|
pcall(function()
|
|
localRootPart.AssemblyLinearVelocity = Vector3.zero
|
|
localRootPart.AssemblyAngularVelocity = Vector3.zero
|
|
end)
|
|
|
|
if activeCamera then
|
|
activeCamera.CFrame = CFrame.new(activeCamera.CFrame.Position, targetAimPart.Position)
|
|
end
|
|
|
|
fireSingleShot()
|
|
shotCount = shotCount + 1
|
|
|
|
local remaining = burstDeadline - os.clock()
|
|
if remaining > 0 then
|
|
task.wait(math.min(0.015, remaining))
|
|
end
|
|
until os.clock() >= burstDeadline and shotCount >= 3
|
|
|
|
if localRootPart.Parent then
|
|
if settings.sniperStayHidden then
|
|
localRootPart.CFrame = CFrame.new(originalCFrame.Position + HIDDEN_PARK_OFFSET)
|
|
else
|
|
localRootPart.CFrame = originalCFrame
|
|
end
|
|
|
|
pcall(function()
|
|
localRootPart.AssemblyLinearVelocity = Vector3.zero
|
|
localRootPart.AssemblyAngularVelocity = Vector3.zero
|
|
end)
|
|
end
|
|
|
|
return shotCount > 0
|
|
end
|
|
|
|
local function sniperKillSelectedPlayers()
|
|
local targetPlayers = getSniperTargetPlayers()
|
|
if #targetPlayers < 1 then
|
|
return false
|
|
end
|
|
|
|
local didAny = false
|
|
for _, player in ipairs(targetPlayers) do
|
|
if sniperKillPlayer(player) then
|
|
didAny = true
|
|
end
|
|
end
|
|
|
|
return didAny
|
|
end
|
|
|
|
local function teleportToView()
|
|
local hit = Mouse and Mouse.Hit
|
|
if not hit then
|
|
return false
|
|
end
|
|
|
|
return teleportToPosition(hit.Position)
|
|
end
|
|
|
|
local currentHumanoid
|
|
local speedWatcher
|
|
local visibilityWatcher
|
|
local humanoidMaxHealthState = nil
|
|
|
|
local partTransparencyStates = setmetatable({}, {__mode = "k"})
|
|
local partLocalTransparencyStates = setmetatable({}, {__mode = "k"})
|
|
local decalTextureStates = setmetatable({}, {__mode = "k"})
|
|
local enabledStates = setmetatable({}, {__mode = "k"})
|
|
local collisionStates = setmetatable({}, {__mode = "k"})
|
|
|
|
local humanoidDisplayTypeState = nil
|
|
|
|
local function shouldPlayerBeVisible()
|
|
return settings.playerVisible and not birdTeleportActive
|
|
end
|
|
|
|
local function applyHumanoidVisibility(visible)
|
|
if not currentHumanoid then
|
|
return
|
|
end
|
|
|
|
if humanoidDisplayTypeState == nil then
|
|
humanoidDisplayTypeState = currentHumanoid.DisplayDistanceType
|
|
end
|
|
|
|
if visible then
|
|
if humanoidDisplayTypeState then
|
|
currentHumanoid.DisplayDistanceType = humanoidDisplayTypeState
|
|
end
|
|
else
|
|
currentHumanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
|
|
end
|
|
end
|
|
|
|
local function applyVisibilityToDescendant(descendant, visible)
|
|
if descendant:IsA("BasePart") then
|
|
if partTransparencyStates[descendant] == nil then
|
|
partTransparencyStates[descendant] = descendant.Transparency
|
|
end
|
|
|
|
if partLocalTransparencyStates[descendant] == nil then
|
|
partLocalTransparencyStates[descendant] = descendant.LocalTransparencyModifier
|
|
end
|
|
|
|
if visible then
|
|
local originalTransparency = partTransparencyStates[descendant]
|
|
local originalLocalTransparency = partLocalTransparencyStates[descendant]
|
|
|
|
descendant.Transparency = type(originalTransparency) == "number" and originalTransparency or 0
|
|
descendant.LocalTransparencyModifier = type(originalLocalTransparency) == "number" and originalLocalTransparency or 0
|
|
else
|
|
descendant.Transparency = 1
|
|
descendant.LocalTransparencyModifier = 1
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
if descendant:IsA("Decal") or descendant:IsA("Texture") then
|
|
if decalTextureStates[descendant] == nil then
|
|
decalTextureStates[descendant] = descendant.Transparency
|
|
end
|
|
|
|
if visible then
|
|
local original = decalTextureStates[descendant]
|
|
descendant.Transparency = type(original) == "number" and original or 0
|
|
else
|
|
descendant.Transparency = 1
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
if descendant:IsA("ParticleEmitter")
|
|
or descendant:IsA("Trail")
|
|
or descendant:IsA("Beam")
|
|
or descendant:IsA("Smoke")
|
|
or descendant:IsA("Fire")
|
|
or descendant:IsA("Sparkles")
|
|
or descendant:IsA("BillboardGui")
|
|
or descendant:IsA("SurfaceGui")
|
|
or descendant:IsA("Highlight") then
|
|
if enabledStates[descendant] == nil then
|
|
enabledStates[descendant] = descendant.Enabled
|
|
end
|
|
|
|
if visible then
|
|
local original = enabledStates[descendant]
|
|
descendant.Enabled = type(original) == "boolean" and original or true
|
|
else
|
|
descendant.Enabled = false
|
|
end
|
|
end
|
|
end
|
|
|
|
local function applyNoclipToDescendant(descendant, enabled)
|
|
if not descendant:IsA("BasePart") then
|
|
return
|
|
end
|
|
|
|
if collisionStates[descendant] == nil then
|
|
collisionStates[descendant] = descendant.CanCollide
|
|
end
|
|
|
|
if enabled then
|
|
descendant.CanCollide = false
|
|
else
|
|
local original = collisionStates[descendant]
|
|
if type(original) == "boolean" then
|
|
descendant.CanCollide = original
|
|
else
|
|
descendant.CanCollide = true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function applyVisibilityToTree(rootInstance, visible)
|
|
if not rootInstance then
|
|
return
|
|
end
|
|
|
|
for _, descendant in ipairs(rootInstance:GetDescendants()) do
|
|
applyVisibilityToDescendant(descendant, visible)
|
|
end
|
|
end
|
|
|
|
local function applyLocalCloneVisibility(visible)
|
|
local character = LocalPlayer.Character
|
|
|
|
for _, candidate in ipairs(workspace:GetChildren()) do
|
|
if candidate:IsA("Model") and candidate ~= character and candidate.Name == LocalPlayer.Name then
|
|
if candidate:FindFirstChildOfClass("Humanoid") then
|
|
applyVisibilityToTree(candidate, visible)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function applyPlayerVisibility()
|
|
local character = LocalPlayer.Character
|
|
if not character then
|
|
return
|
|
end
|
|
|
|
local visible = shouldPlayerBeVisible()
|
|
applyHumanoidVisibility(visible)
|
|
applyVisibilityToTree(character, visible)
|
|
applyLocalCloneVisibility(visible)
|
|
|
|
local currentCamera = workspace.CurrentCamera
|
|
if currentCamera then
|
|
applyVisibilityToTree(currentCamera, visible)
|
|
end
|
|
end
|
|
|
|
local function applyCharacterNoclip(enabled)
|
|
local character = LocalPlayer.Character
|
|
if not character then
|
|
return
|
|
end
|
|
|
|
for _, descendant in ipairs(character:GetDescendants()) do
|
|
applyNoclipToDescendant(descendant, enabled)
|
|
end
|
|
end
|
|
|
|
local BIRD_FLY_SPEED = 95
|
|
local BIRD_PARK_OFFSET = HIDDEN_PARK_OFFSET
|
|
|
|
local function destroyBirdProxy()
|
|
if birdProxyModel then
|
|
pcall(function()
|
|
birdProxyModel:Destroy()
|
|
end)
|
|
end
|
|
|
|
birdProxyModel = nil
|
|
birdProxyRootPart = nil
|
|
birdProxyHumanoid = nil
|
|
end
|
|
|
|
local function createBirdProxy()
|
|
local character = LocalPlayer.Character
|
|
local rootPart = getLocalRootPart()
|
|
if not character or not rootPart then
|
|
return false
|
|
end
|
|
|
|
local originalArchivable = character.Archivable
|
|
character.Archivable = true
|
|
|
|
local cloneOk, proxyModel = pcall(function()
|
|
return character:Clone()
|
|
end)
|
|
|
|
character.Archivable = originalArchivable
|
|
|
|
if not cloneOk or not proxyModel then
|
|
return false
|
|
end
|
|
|
|
for _, descendant in ipairs(proxyModel:GetDescendants()) do
|
|
if descendant:IsA("Script") or descendant:IsA("LocalScript") or descendant:IsA("ModuleScript") then
|
|
descendant:Destroy()
|
|
elseif descendant:IsA("BasePart") then
|
|
descendant.Anchored = true
|
|
descendant.CanCollide = false
|
|
descendant.CastShadow = false
|
|
descendant.Massless = true
|
|
descendant.Transparency = 1
|
|
descendant.LocalTransparencyModifier = 1
|
|
elseif descendant:IsA("Decal") or descendant:IsA("Texture") then
|
|
descendant.Transparency = 1
|
|
elseif descendant:IsA("ParticleEmitter")
|
|
or descendant:IsA("Trail")
|
|
or descendant:IsA("Beam")
|
|
or descendant:IsA("Smoke")
|
|
or descendant:IsA("Fire")
|
|
or descendant:IsA("Sparkles")
|
|
or descendant:IsA("BillboardGui")
|
|
or descendant:IsA("SurfaceGui")
|
|
or descendant:IsA("Highlight") then
|
|
descendant.Enabled = false
|
|
end
|
|
end
|
|
|
|
local proxyHumanoid = proxyModel:FindFirstChildOfClass("Humanoid")
|
|
if proxyHumanoid then
|
|
pcall(function()
|
|
proxyHumanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
|
|
proxyHumanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff
|
|
end)
|
|
end
|
|
|
|
local proxyRootPart = proxyModel:FindFirstChild("HumanoidRootPart") or proxyModel.PrimaryPart
|
|
if not proxyRootPart then
|
|
proxyModel:Destroy()
|
|
return false
|
|
end
|
|
|
|
proxyModel.Name = LocalPlayer.Name .. "_BirdProxy"
|
|
proxyModel.PrimaryPart = proxyRootPart
|
|
proxyModel.Parent = workspace
|
|
proxyModel:PivotTo(rootPart.CFrame)
|
|
|
|
birdProxyModel = proxyModel
|
|
birdProxyRootPart = proxyRootPart
|
|
birdProxyHumanoid = proxyHumanoid
|
|
|
|
return true
|
|
end
|
|
|
|
local function getBirdControlRootPart()
|
|
if birdTeleportActive and birdProxyRootPart then
|
|
return birdProxyRootPart
|
|
end
|
|
|
|
return getLocalRootPart()
|
|
end
|
|
|
|
local function applyBirdCameraTarget()
|
|
local activeCamera = workspace.CurrentCamera or Camera
|
|
if not activeCamera then
|
|
return
|
|
end
|
|
|
|
if birdTeleportActive then
|
|
activeCamera.CameraType = Enum.CameraType.Custom
|
|
if birdProxyHumanoid then
|
|
activeCamera.CameraSubject = birdProxyHumanoid
|
|
elseif birdProxyRootPart then
|
|
activeCamera.CameraSubject = birdProxyRootPart
|
|
end
|
|
return
|
|
end
|
|
|
|
local character = LocalPlayer.Character
|
|
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
|
|
if humanoid then
|
|
activeCamera.CameraType = Enum.CameraType.Custom
|
|
activeCamera.CameraSubject = humanoid
|
|
end
|
|
end
|
|
|
|
local function updateBirdParkedCharacter()
|
|
if not birdTeleportActive or not birdParkPosition then
|
|
return
|
|
end
|
|
|
|
local rootPart = getLocalRootPart()
|
|
if rootPart then
|
|
rootPart.CFrame = CFrame.new(birdParkPosition)
|
|
rootPart.AssemblyLinearVelocity = Vector3.zero
|
|
rootPart.AssemblyAngularVelocity = Vector3.zero
|
|
end
|
|
|
|
if currentHumanoid then
|
|
currentHumanoid:Move(Vector3.zero, true)
|
|
end
|
|
end
|
|
|
|
local function getNormalisedHorizontal(vector)
|
|
local horizontal = Vector3.new(vector.X, 0, vector.Z)
|
|
if horizontal.Magnitude > 0 then
|
|
return horizontal.Unit
|
|
end
|
|
|
|
return Vector3.zero
|
|
end
|
|
|
|
local function getBirdMoveDirection()
|
|
local direction = Vector3.zero
|
|
local activeCamera = workspace.CurrentCamera or Camera
|
|
if not activeCamera then
|
|
return Vector3.zero
|
|
end
|
|
|
|
local forward = getNormalisedHorizontal(activeCamera.CFrame.LookVector)
|
|
local right = getNormalisedHorizontal(activeCamera.CFrame.RightVector)
|
|
|
|
if UserInputService:IsKeyDown(Enum.KeyCode.W) then
|
|
direction = direction + forward
|
|
end
|
|
|
|
if UserInputService:IsKeyDown(Enum.KeyCode.S) then
|
|
direction = direction - forward
|
|
end
|
|
|
|
if UserInputService:IsKeyDown(Enum.KeyCode.D) then
|
|
direction = direction + right
|
|
end
|
|
|
|
if UserInputService:IsKeyDown(Enum.KeyCode.A) then
|
|
direction = direction - right
|
|
end
|
|
|
|
if UserInputService:IsKeyDown(Enum.KeyCode.Space) then
|
|
direction = direction + Vector3.new(0, 1, 0)
|
|
end
|
|
|
|
if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift)
|
|
or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
|
|
or UserInputService:IsKeyDown(Enum.KeyCode.Q) then
|
|
direction = direction - Vector3.new(0, 1, 0)
|
|
end
|
|
|
|
if direction.Magnitude > 0 then
|
|
return direction.Unit
|
|
end
|
|
|
|
if currentHumanoid then
|
|
local moveDirection = currentHumanoid.MoveDirection
|
|
local fallback = Vector3.new(moveDirection.X, 0, moveDirection.Z)
|
|
if fallback.Magnitude > 0 then
|
|
return fallback.Unit
|
|
end
|
|
end
|
|
|
|
return Vector3.zero
|
|
end
|
|
|
|
local function applyBirdHumanoidState(enabled)
|
|
if not currentHumanoid then
|
|
return
|
|
end
|
|
|
|
if enabled then
|
|
currentHumanoid.AutoRotate = false
|
|
pcall(function()
|
|
currentHumanoid:ChangeState(Enum.HumanoidStateType.Physics)
|
|
end)
|
|
else
|
|
currentHumanoid.AutoRotate = true
|
|
pcall(function()
|
|
currentHumanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function applyBirdFlight(deltaTime)
|
|
if not birdTeleportActive then
|
|
return
|
|
end
|
|
|
|
local rootPart = getBirdControlRootPart()
|
|
if not rootPart then
|
|
return
|
|
end
|
|
|
|
local direction = getBirdMoveDirection()
|
|
local displacement = direction * (BIRD_FLY_SPEED * math.max(deltaTime, 0.016))
|
|
|
|
rootPart.AssemblyLinearVelocity = Vector3.zero
|
|
rootPart.AssemblyAngularVelocity = Vector3.zero
|
|
|
|
if currentHumanoid then
|
|
currentHumanoid:Move(Vector3.zero, true)
|
|
end
|
|
|
|
if displacement.Magnitude > 0 then
|
|
rootPart.CFrame = rootPart.CFrame + displacement
|
|
end
|
|
end
|
|
|
|
local function setBirdTeleportActive(state)
|
|
if birdTeleportActive == state then
|
|
return
|
|
end
|
|
|
|
if state then
|
|
if not createBirdProxy() then
|
|
return
|
|
end
|
|
|
|
local rootPart = getLocalRootPart()
|
|
if rootPart then
|
|
birdParkPosition = rootPart.Position + BIRD_PARK_OFFSET
|
|
else
|
|
birdParkPosition = nil
|
|
end
|
|
|
|
birdTeleportActive = true
|
|
birdMaintenanceAccumulator = 0
|
|
applyBirdHumanoidState(true)
|
|
applyCharacterNoclip(true)
|
|
updateBirdParkedCharacter()
|
|
applyBirdCameraTarget()
|
|
applyPlayerVisibility()
|
|
refreshAll()
|
|
return
|
|
end
|
|
|
|
local exitPosition = birdProxyRootPart and birdProxyRootPart.Position or nil
|
|
|
|
birdTeleportActive = false
|
|
birdMaintenanceAccumulator = 0
|
|
birdParkPosition = nil
|
|
destroyBirdProxy()
|
|
|
|
applyBirdHumanoidState(false)
|
|
applyCharacterNoclip(false)
|
|
runtime.restoreVisibility()
|
|
applyBirdCameraTarget()
|
|
|
|
if exitPosition then
|
|
teleportToPosition(exitPosition)
|
|
end
|
|
|
|
refreshAll()
|
|
end
|
|
|
|
runtime.restoreVisibility = function()
|
|
local character = LocalPlayer.Character
|
|
if character then
|
|
applyHumanoidVisibility(true)
|
|
applyVisibilityToTree(character, true)
|
|
end
|
|
|
|
applyLocalCloneVisibility(true)
|
|
|
|
local currentCamera = workspace.CurrentCamera
|
|
if currentCamera then
|
|
applyVisibilityToTree(currentCamera, true)
|
|
end
|
|
end
|
|
|
|
runtime.restoreNoclip = function()
|
|
birdTeleportActive = false
|
|
birdMaintenanceAccumulator = 0
|
|
birdParkPosition = nil
|
|
destroyBirdProxy()
|
|
applyBirdHumanoidState(false)
|
|
applyCharacterNoclip(false)
|
|
applyBirdCameraTarget()
|
|
end
|
|
|
|
local function applyCursorMode()
|
|
if cursorReleased then
|
|
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
|
|
UserInputService.MouseIconEnabled = true
|
|
return
|
|
end
|
|
|
|
if settings.thirdPerson then
|
|
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
|
|
UserInputService.MouseIconEnabled = true
|
|
else
|
|
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
|
|
UserInputService.MouseIconEnabled = false
|
|
end
|
|
end
|
|
|
|
local function applyCameraMode()
|
|
if settings.thirdPerson then
|
|
LocalPlayer.CameraMode = Enum.CameraMode.Classic
|
|
LocalPlayer.CameraMinZoomDistance = 0.5
|
|
LocalPlayer.CameraMaxZoomDistance = 12
|
|
else
|
|
LocalPlayer.CameraMode = Enum.CameraMode.LockFirstPerson
|
|
LocalPlayer.CameraMinZoomDistance = 0.5
|
|
LocalPlayer.CameraMaxZoomDistance = 0.5
|
|
end
|
|
|
|
applyCursorMode()
|
|
end
|
|
|
|
local function applySpeed()
|
|
if not currentHumanoid then
|
|
return
|
|
end
|
|
|
|
local desiredSpeed = settings.speedEnabled and settings.walkSpeed or 16
|
|
if currentHumanoid.WalkSpeed ~= desiredSpeed then
|
|
currentHumanoid.WalkSpeed = desiredSpeed
|
|
end
|
|
end
|
|
|
|
local function applyHealth()
|
|
if not currentHumanoid then
|
|
return
|
|
end
|
|
|
|
if humanoidMaxHealthState == nil then
|
|
humanoidMaxHealthState = currentHumanoid.MaxHealth
|
|
end
|
|
|
|
if settings.highHealthEnabled then
|
|
local desiredHealth = math.max(settings.highHealthValue or 500, 100)
|
|
if currentHumanoid.MaxHealth ~= desiredHealth then
|
|
currentHumanoid.MaxHealth = desiredHealth
|
|
end
|
|
if currentHumanoid.Health < desiredHealth then
|
|
currentHumanoid.Health = desiredHealth
|
|
end
|
|
return
|
|
end
|
|
|
|
local originalMaxHealth = humanoidMaxHealthState or 100
|
|
if currentHumanoid.MaxHealth ~= originalMaxHealth then
|
|
currentHumanoid.MaxHealth = originalMaxHealth
|
|
end
|
|
|
|
if currentHumanoid.Health > currentHumanoid.MaxHealth then
|
|
currentHumanoid.Health = currentHumanoid.MaxHealth
|
|
end
|
|
end
|
|
|
|
local function applyAutoStop()
|
|
local rootPart = getLocalRootPart()
|
|
if not rootPart then
|
|
return
|
|
end
|
|
|
|
rootPart.AssemblyLinearVelocity = Vector3.zero
|
|
rootPart.AssemblyAngularVelocity = Vector3.zero
|
|
|
|
if currentHumanoid then
|
|
currentHumanoid:Move(Vector3.zero, true)
|
|
end
|
|
end
|
|
|
|
local function bindCharacter(character)
|
|
if speedWatcher and speedWatcher.Connected then
|
|
speedWatcher:Disconnect()
|
|
end
|
|
|
|
if visibilityWatcher and visibilityWatcher.Connected then
|
|
visibilityWatcher:Disconnect()
|
|
end
|
|
|
|
local humanoid = character:FindFirstChildOfClass("Humanoid") or character:WaitForChild("Humanoid", 5)
|
|
currentHumanoid = humanoid
|
|
humanoidDisplayTypeState = nil
|
|
|
|
if birdTeleportActive then
|
|
birdTeleportActive = false
|
|
birdMaintenanceAccumulator = 0
|
|
birdParkPosition = nil
|
|
destroyBirdProxy()
|
|
applyBirdCameraTarget()
|
|
refreshAll()
|
|
end
|
|
|
|
if currentHumanoid then
|
|
applySpeed()
|
|
applyHealth()
|
|
|
|
speedWatcher = currentHumanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
|
|
if settings.speedEnabled and currentHumanoid and currentHumanoid.WalkSpeed ~= settings.walkSpeed then
|
|
currentHumanoid.WalkSpeed = settings.walkSpeed
|
|
end
|
|
end)
|
|
table.insert(runtime.connections, speedWatcher)
|
|
end
|
|
|
|
visibilityWatcher = character.DescendantAdded:Connect(function(descendant)
|
|
if not shouldPlayerBeVisible() then
|
|
task.defer(function()
|
|
applyVisibilityToDescendant(descendant, false)
|
|
end)
|
|
end
|
|
|
|
if birdTeleportActive then
|
|
task.defer(function()
|
|
applyNoclipToDescendant(descendant, true)
|
|
end)
|
|
end
|
|
end)
|
|
table.insert(runtime.connections, visibilityWatcher)
|
|
|
|
task.defer(applyCameraMode)
|
|
task.defer(applyPlayerVisibility)
|
|
task.defer(function()
|
|
applyBirdHumanoidState(birdTeleportActive)
|
|
applyCharacterNoclip(birdTeleportActive)
|
|
end)
|
|
end
|
|
|
|
if LocalPlayer.Character then
|
|
task.spawn(bindCharacter, LocalPlayer.Character)
|
|
end
|
|
trackConnection(LocalPlayer.CharacterAdded:Connect(bindCharacter))
|
|
|
|
local hasDrawing = type(Drawing) == "table" and type(Drawing.new) == "function"
|
|
|
|
local fovCircle
|
|
if hasDrawing then
|
|
fovCircle = trackDrawing(Drawing.new("Circle"))
|
|
fovCircle.Visible = false
|
|
fovCircle.Color = Color3.fromRGB(255, 255, 255)
|
|
fovCircle.Thickness = 1.4
|
|
fovCircle.NumSides = 64
|
|
fovCircle.Filled = false
|
|
fovCircle.Transparency = 0.9
|
|
end
|
|
|
|
local espEntries = {}
|
|
local espAccumulator = 0
|
|
local espWasEnabledLastTick = false
|
|
local espActivityStates = {}
|
|
|
|
local ESP_INACTIVE_TIMEOUT_SECONDS = 60
|
|
local ESP_INACTIVE_POSITION_EPSILON = 0.35
|
|
|
|
local function clearEspActivityState(player)
|
|
espActivityStates[player] = nil
|
|
end
|
|
|
|
local function isEspPlayerInactive(player, rootPart, nowTime)
|
|
local state = espActivityStates[player]
|
|
local position = rootPart.Position
|
|
|
|
if not state then
|
|
espActivityStates[player] = {
|
|
lastPosition = position,
|
|
lastMovedAt = nowTime
|
|
}
|
|
return false
|
|
end
|
|
|
|
if (position - state.lastPosition).Magnitude > ESP_INACTIVE_POSITION_EPSILON then
|
|
state.lastPosition = position
|
|
state.lastMovedAt = nowTime
|
|
return false
|
|
end
|
|
|
|
state.lastPosition = position
|
|
return (nowTime - state.lastMovedAt) >= ESP_INACTIVE_TIMEOUT_SECONDS
|
|
end
|
|
|
|
local function hideEspEntry(entry)
|
|
if not entry then
|
|
return
|
|
end
|
|
|
|
if entry.text then
|
|
entry.text.Visible = false
|
|
end
|
|
|
|
if entry.line then
|
|
entry.line.Visible = false
|
|
end
|
|
|
|
if entry.box then
|
|
entry.box.Visible = false
|
|
end
|
|
end
|
|
|
|
local function hideAllEspEntries()
|
|
for _, entry in pairs(espEntries) do
|
|
hideEspEntry(entry)
|
|
end
|
|
end
|
|
|
|
local function destroyEspEntry(player)
|
|
local entry = espEntries[player]
|
|
if not entry then
|
|
return
|
|
end
|
|
|
|
if entry.text then
|
|
pcall(function()
|
|
entry.text:Remove()
|
|
end)
|
|
end
|
|
|
|
if entry.line then
|
|
pcall(function()
|
|
entry.line:Remove()
|
|
end)
|
|
end
|
|
|
|
if entry.box then
|
|
pcall(function()
|
|
entry.box:Remove()
|
|
end)
|
|
end
|
|
|
|
espEntries[player] = nil
|
|
clearEspActivityState(player)
|
|
end
|
|
|
|
local function getEspEntry(player)
|
|
local existing = espEntries[player]
|
|
if existing then
|
|
return existing
|
|
end
|
|
|
|
if not hasDrawing then
|
|
return nil
|
|
end
|
|
|
|
local text = trackDrawing(Drawing.new("Text"))
|
|
text.Visible = false
|
|
text.Color = Color3.fromRGB(255, 255, 255)
|
|
text.Size = settings.espTextSize
|
|
text.Center = true
|
|
text.Outline = true
|
|
text.OutlineColor = Color3.fromRGB(0, 0, 0)
|
|
text.Font = 2
|
|
text.Transparency = 1
|
|
|
|
local line = trackDrawing(Drawing.new("Line"))
|
|
line.Visible = false
|
|
line.Color = Color3.fromRGB(255, 255, 255)
|
|
line.Thickness = 1
|
|
line.Transparency = 0.9
|
|
|
|
local box = trackDrawing(Drawing.new("Square"))
|
|
box.Visible = false
|
|
box.Color = Color3.fromRGB(255, 255, 255)
|
|
box.Thickness = 1
|
|
box.Filled = false
|
|
box.Transparency = 0.9
|
|
|
|
local entry = {text = text, line = line, box = box}
|
|
espEntries[player] = entry
|
|
|
|
return entry
|
|
end
|
|
|
|
local function shouldSkipEspPlayer(player)
|
|
if not settings.espIgnoreTeam then
|
|
return false
|
|
end
|
|
|
|
if not LocalPlayer.Team or not player.Team then
|
|
return false
|
|
end
|
|
|
|
return LocalPlayer.Team == player.Team
|
|
end
|
|
|
|
local function updateEsp()
|
|
if not hasDrawing then
|
|
return
|
|
end
|
|
|
|
if not settings.espEnabled then
|
|
if espWasEnabledLastTick then
|
|
hideAllEspEntries()
|
|
end
|
|
espActivityStates = {}
|
|
espWasEnabledLastTick = false
|
|
return
|
|
end
|
|
|
|
local showText = settings.espShowName or settings.espShowDistance
|
|
local showTracers = settings.espShowTracers
|
|
local showBox = settings.espShowBox
|
|
|
|
if not showText and not showTracers and not showBox then
|
|
if espWasEnabledLastTick then
|
|
hideAllEspEntries()
|
|
end
|
|
espWasEnabledLastTick = true
|
|
return
|
|
end
|
|
|
|
espWasEnabledLastTick = true
|
|
|
|
local viewportSize = Camera.ViewportSize
|
|
local tracerOrigin = Vector2.new(viewportSize.X * 0.5, viewportSize.Y - 3)
|
|
local cameraPosition = Camera.CFrame.Position
|
|
local maxDistance = settings.espMaxDistance
|
|
local textSize = settings.espTextSize
|
|
local useDistanceIndicator = showTracers and settings.espDistanceIndicator
|
|
local nowTime = os.clock()
|
|
local inactivePlayers = settings.espInactiveDetection and {} or nil
|
|
local trackedLookup = {}
|
|
|
|
for _, trackedPlayer in ipairs(trackedPlayers) do
|
|
trackedLookup[trackedPlayer] = true
|
|
end
|
|
|
|
local nearestDistance = nil
|
|
local furthestDistance = nil
|
|
|
|
if useDistanceIndicator then
|
|
for _, player in ipairs(trackedPlayers) do
|
|
if not shouldSkipEspPlayer(player) then
|
|
local character = player.Character
|
|
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
|
|
local rootPart = character and character:FindFirstChild("HumanoidRootPart")
|
|
|
|
if humanoid and humanoid.Health > 0 and rootPart then
|
|
local isInactive = false
|
|
if inactivePlayers then
|
|
isInactive = isEspPlayerInactive(player, rootPart, nowTime)
|
|
inactivePlayers[player] = isInactive
|
|
end
|
|
|
|
if not isInactive then
|
|
local distance = (rootPart.Position - cameraPosition).Magnitude
|
|
if distance <= maxDistance then
|
|
if not nearestDistance or distance < nearestDistance then
|
|
nearestDistance = distance
|
|
end
|
|
if not furthestDistance or distance > furthestDistance then
|
|
furthestDistance = distance
|
|
end
|
|
end
|
|
end
|
|
elseif inactivePlayers then
|
|
clearEspActivityState(player)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, player in ipairs(trackedPlayers) do
|
|
local entry = getEspEntry(player)
|
|
if entry then
|
|
if shouldSkipEspPlayer(player) then
|
|
hideEspEntry(entry)
|
|
else
|
|
local character = player.Character
|
|
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
|
|
local head = character and character:FindFirstChild("Head")
|
|
local rootPart = character and character:FindFirstChild("HumanoidRootPart")
|
|
|
|
if humanoid and humanoid.Health > 0 and head and rootPart then
|
|
local isInactive = false
|
|
if inactivePlayers then
|
|
if inactivePlayers[player] == nil then
|
|
inactivePlayers[player] = isEspPlayerInactive(player, rootPart, nowTime)
|
|
end
|
|
isInactive = inactivePlayers[player]
|
|
end
|
|
|
|
if isInactive then
|
|
hideEspEntry(entry)
|
|
else
|
|
local distance = (rootPart.Position - cameraPosition).Magnitude
|
|
if distance <= maxDistance then
|
|
local rootPosition, rootOnScreen = Camera:WorldToViewportPoint(rootPart.Position)
|
|
local headPosition, headOnScreen = Camera:WorldToViewportPoint(head.Position + Vector3.new(0, 0.5, 0))
|
|
|
|
if rootOnScreen and headOnScreen and rootPosition.Z > 0 and headPosition.Z > 0 then
|
|
if showText then
|
|
local roundedDistance = math.floor(distance + 0.5)
|
|
|
|
if settings.espShowName and settings.espShowDistance then
|
|
entry.text.Text = player.Name .. " [" .. roundedDistance .. "m]"
|
|
elseif settings.espShowName then
|
|
entry.text.Text = player.Name
|
|
else
|
|
entry.text.Text = roundedDistance .. "m"
|
|
end
|
|
|
|
entry.text.Size = textSize
|
|
entry.text.Position = Vector2.new(headPosition.X, headPosition.Y - 18)
|
|
entry.text.Visible = true
|
|
else
|
|
entry.text.Visible = false
|
|
end
|
|
|
|
if showTracers then
|
|
entry.line.From = tracerOrigin
|
|
entry.line.To = Vector2.new(headPosition.X, headPosition.Y)
|
|
|
|
if useDistanceIndicator then
|
|
if nearestDistance and furthestDistance and furthestDistance > nearestDistance then
|
|
local ratio = math.clamp((distance - nearestDistance) / (furthestDistance - nearestDistance), 0, 1)
|
|
entry.line.Color = Color3.new(1, ratio, ratio)
|
|
else
|
|
entry.line.Color = Color3.fromRGB(255, 64, 64)
|
|
end
|
|
else
|
|
entry.line.Color = Color3.fromRGB(255, 255, 255)
|
|
end
|
|
|
|
entry.line.Visible = true
|
|
else
|
|
entry.line.Visible = false
|
|
end
|
|
|
|
if showBox then
|
|
local height = math.max(math.abs(rootPosition.Y - headPosition.Y) * 2.2, 16)
|
|
local width = math.max(height * 0.62, 10)
|
|
|
|
entry.box.Size = Vector2.new(width, height)
|
|
entry.box.Position = Vector2.new(rootPosition.X - width * 0.5, rootPosition.Y - height * 0.9)
|
|
entry.box.Visible = true
|
|
else
|
|
entry.box.Visible = false
|
|
end
|
|
else
|
|
hideEspEntry(entry)
|
|
end
|
|
else
|
|
hideEspEntry(entry)
|
|
end
|
|
end
|
|
else
|
|
clearEspActivityState(player)
|
|
hideEspEntry(entry)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for player in pairs(espEntries) do
|
|
if not trackedLookup[player] or player.Parent ~= Players then
|
|
destroyEspEntry(player)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function isSameTeam(otherPlayer)
|
|
if not settings.ignoreTeam then
|
|
return false
|
|
end
|
|
|
|
if not LocalPlayer.Team or not otherPlayer.Team then
|
|
return false
|
|
end
|
|
|
|
return LocalPlayer.Team == otherPlayer.Team
|
|
end
|
|
|
|
local function findClosestTarget(maxFov)
|
|
local bestHead = nil
|
|
local bestDistance = maxFov
|
|
local screenCentre = Vector2.new(Camera.ViewportSize.X * 0.5, Camera.ViewportSize.Y * 0.5)
|
|
|
|
for _, player in ipairs(trackedPlayers) do
|
|
if not isSameTeam(player) then
|
|
local character = player.Character
|
|
if character then
|
|
local humanoid = character:FindFirstChildOfClass("Humanoid")
|
|
local head = character:FindFirstChild("Head")
|
|
|
|
if humanoid and humanoid.Health > 0 and head then
|
|
local position, onScreen = Camera:WorldToViewportPoint(head.Position)
|
|
if onScreen and position.Z > 0 then
|
|
local distance = (Vector2.new(position.X, position.Y) - screenCentre).Magnitude
|
|
if distance < bestDistance then
|
|
bestDistance = distance
|
|
bestHead = head
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return bestHead
|
|
end
|
|
|
|
local function updateFovCircle()
|
|
if not fovCircle then
|
|
return
|
|
end
|
|
|
|
if settings.aimEnabled and settings.aimShowFovCircle then
|
|
local viewportSize = Camera.ViewportSize
|
|
fovCircle.Position = Vector2.new(viewportSize.X * 0.5, viewportSize.Y * 0.5)
|
|
fovCircle.Radius = settings.aimFOV
|
|
fovCircle.Visible = true
|
|
else
|
|
fovCircle.Visible = false
|
|
end
|
|
end
|
|
|
|
local CombatPage = addTab("Combat")
|
|
local MovementPage = addTab("Movement")
|
|
local PlayersPage = addTab("Players")
|
|
local TeleportPage = addTab("Teleport")
|
|
local KeybindsPage = addTab("Keybinds")
|
|
local ConfigPage = addTab("Config")
|
|
|
|
addToggleRow(CombatPage, "Aimlock", function()
|
|
return settings.aimEnabled
|
|
end, function(state)
|
|
settings.aimEnabled = state
|
|
|
|
if not state then
|
|
aimHoldingKeyboard = false
|
|
aimHoldingMouse = false
|
|
end
|
|
|
|
recomputeAimHolding()
|
|
saveSettings()
|
|
end)
|
|
|
|
addNumberRow(CombatPage, "Aim FOV", function()
|
|
return settings.aimFOV
|
|
end, function(value)
|
|
settings.aimFOV = value
|
|
saveSettings()
|
|
end, 25, 600)
|
|
|
|
addToggleRow(CombatPage, "Show FOV Circle", function()
|
|
return settings.aimShowFovCircle
|
|
end, function(state)
|
|
settings.aimShowFovCircle = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(CombatPage, "Aim with Right Click", function()
|
|
return settings.aimUseRightMouse
|
|
end, function(state)
|
|
settings.aimUseRightMouse = state
|
|
if not state then
|
|
aimHoldingMouse = false
|
|
recomputeAimHolding()
|
|
end
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(CombatPage, "Auto Stop on M1", function()
|
|
return settings.autoStopEnabled
|
|
end, function(state)
|
|
settings.autoStopEnabled = state
|
|
if not state then
|
|
autoStopHolding = false
|
|
end
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(CombatPage, "Ignore Team", function()
|
|
return settings.ignoreTeam
|
|
end, function(state)
|
|
settings.ignoreTeam = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(CombatPage, "Third Person", function()
|
|
return settings.thirdPerson
|
|
end, function(state)
|
|
settings.thirdPerson = state
|
|
applyCameraMode()
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(MovementPage, "Speed", function()
|
|
return settings.speedEnabled
|
|
end, function(state)
|
|
settings.speedEnabled = state
|
|
applySpeed()
|
|
saveSettings()
|
|
end)
|
|
|
|
addNumberRow(MovementPage, "Walk Speed", function()
|
|
return settings.walkSpeed
|
|
end, function(value)
|
|
settings.walkSpeed = value
|
|
applySpeed()
|
|
saveSettings()
|
|
end, 16, 200)
|
|
|
|
addToggleRow(MovementPage, "Player Visibility", function()
|
|
return settings.playerVisible
|
|
end, function(state)
|
|
settings.playerVisible = state
|
|
applyPlayerVisibility()
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "ESP", function()
|
|
return settings.espEnabled
|
|
end, function(state)
|
|
settings.espEnabled = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Show Name", function()
|
|
return settings.espShowName
|
|
end, function(state)
|
|
settings.espShowName = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Show Distance", function()
|
|
return settings.espShowDistance
|
|
end, function(state)
|
|
settings.espShowDistance = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Tracer Lines", function()
|
|
return settings.espShowTracers
|
|
end, function(state)
|
|
settings.espShowTracers = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Distance Indicator", function()
|
|
return settings.espDistanceIndicator
|
|
end, function(state)
|
|
settings.espDistanceIndicator = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Bounding Box", function()
|
|
return settings.espShowBox
|
|
end, function(state)
|
|
settings.espShowBox = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Ignore Team", function()
|
|
return settings.espIgnoreTeam
|
|
end, function(state)
|
|
settings.espIgnoreTeam = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addNumberRow(PlayersPage, "Text Size", function()
|
|
return settings.espTextSize
|
|
end, function(value)
|
|
settings.espTextSize = value
|
|
saveSettings()
|
|
end, 10, 22)
|
|
|
|
addNumberRow(PlayersPage, "Refresh (ms)", function()
|
|
return settings.espRefreshMs
|
|
end, function(value)
|
|
settings.espRefreshMs = value
|
|
saveSettings()
|
|
end, 33, 500)
|
|
|
|
addNumberRow(PlayersPage, "Max Distance", function()
|
|
return settings.espMaxDistance
|
|
end, function(value)
|
|
settings.espMaxDistance = value
|
|
saveSettings()
|
|
end, 50, 10000)
|
|
|
|
addToggleRow(PlayersPage, "Inactive player detection", function()
|
|
return settings.espInactiveDetection
|
|
end, function(state)
|
|
settings.espInactiveDetection = state
|
|
espActivityStates = {}
|
|
saveSettings()
|
|
end)
|
|
|
|
addToggleRow(PlayersPage, "Multi Select Mode", function()
|
|
return settings.multiSelectMode
|
|
end, function(state)
|
|
settings.multiSelectMode = state
|
|
saveSettings()
|
|
end)
|
|
|
|
if not hasDrawing then
|
|
addActionRow(PlayersPage, "Drawing API", "Unavailable", function()
|
|
end)
|
|
|
|
addActionRow(CombatPage, "FOV Circle", "Unavailable", function()
|
|
end)
|
|
end
|
|
|
|
addToggleRow(TeleportPage, "Bird Teleport Mode", function()
|
|
return birdTeleportActive
|
|
end, function(state)
|
|
setBirdTeleportActive(state)
|
|
end)
|
|
|
|
addDynamicActionRow(TeleportPage, "Multi Select Mode", function()
|
|
return settings.multiSelectMode and "ON" or "OFF"
|
|
end, function()
|
|
settings.multiSelectMode = not settings.multiSelectMode
|
|
saveSettings()
|
|
end)
|
|
|
|
addActionRow(TeleportPage, "Add Point at Current Pos", "Add Point", function()
|
|
if addTeleportPoint() then
|
|
saveSettings()
|
|
refreshAll()
|
|
end
|
|
end)
|
|
|
|
addDynamicActionRow(TeleportPage, "Selected Teleport Point", function()
|
|
return getSelectedTeleportPointLabel()
|
|
end, function()
|
|
cycleTeleportPoint()
|
|
end)
|
|
|
|
addActionRow(TeleportPage, "Teleport to Selected Point", "Teleport", function()
|
|
teleportToSelectedPoint()
|
|
end)
|
|
|
|
addActionRow(TeleportPage, "Delete Selected Point", "Delete", function()
|
|
if deleteSelectedTeleportPoint() then
|
|
saveSettings()
|
|
refreshAll()
|
|
end
|
|
end)
|
|
|
|
addDynamicActionRow(TeleportPage, "Selected Player", function()
|
|
return getSelectedTeleportPlayerLabel()
|
|
end, function()
|
|
cycleTeleportPlayer()
|
|
end)
|
|
|
|
addDynamicActionRow(TeleportPage, "Selection Action", function()
|
|
return getCurrentSelectionActionLabel()
|
|
end, function()
|
|
if settings.multiSelectMode then
|
|
toggleSelectedTeleportPlayerInSelection()
|
|
end
|
|
end)
|
|
|
|
addDynamicActionRow(TeleportPage, "Selected Players", function()
|
|
return getMultiSelectedTeleportPlayersLabel()
|
|
end, function()
|
|
if settings.multiSelectMode then
|
|
clearTeleportPlayerSelection()
|
|
end
|
|
end)
|
|
|
|
addActionRow(TeleportPage, "Teleport to Selected Player", "Teleport", function()
|
|
teleportToSelectedPlayer()
|
|
end)
|
|
|
|
addActionRow(TeleportPage, "Sniper Kill Selected Player", "Execute", function()
|
|
task.spawn(sniperKillSelectedPlayers)
|
|
end)
|
|
|
|
addToggleRow(TeleportPage, "Sniper Stay Hidden", function()
|
|
return settings.sniperStayHidden
|
|
end, function(state)
|
|
settings.sniperStayHidden = state
|
|
saveSettings()
|
|
end)
|
|
|
|
addDecimalRow(TeleportPage, "Sniper Random Delta", function()
|
|
return settings.sniperRandomDeltaMagnitude
|
|
end, function(value)
|
|
settings.sniperRandomDeltaMagnitude = value
|
|
saveSettings()
|
|
end, 0, 0.25, 3)
|
|
|
|
addNumberRow(TeleportPage, "Sniper Return Delay (ms)", function()
|
|
return settings.sniperReturnDelayMs
|
|
end, function(value)
|
|
settings.sniperReturnDelayMs = value
|
|
saveSettings()
|
|
end, 0, 2000)
|
|
|
|
addActionRow(TeleportPage, "Teleport to View", "Use Keybind", function()
|
|
teleportToView()
|
|
end)
|
|
|
|
local function addKeybindRow(page, labelText, settingKey)
|
|
local control = createRow(page, labelText)
|
|
local button = createButton(control, "")
|
|
button.Size = UDim2.new(1, 0, 1, 0)
|
|
|
|
local function refresh()
|
|
if bindingTarget == settingKey then
|
|
button.Text = "Press a key"
|
|
else
|
|
button.Text = settings[settingKey]
|
|
end
|
|
end
|
|
|
|
trackConnection(button.MouseButton1Click:Connect(function()
|
|
bindingTarget = settingKey
|
|
refreshAll()
|
|
end))
|
|
|
|
table.insert(refreshers, refresh)
|
|
refresh()
|
|
|
|
return button
|
|
end
|
|
|
|
addKeybindRow(KeybindsPage, "Aim Hold Key", "aimKey")
|
|
addKeybindRow(KeybindsPage, "ESP Toggle Key", "espToggleKey")
|
|
addKeybindRow(KeybindsPage, "UI Toggle Key", "uiToggleKey")
|
|
addKeybindRow(KeybindsPage, "Teleport View Key", "teleportViewKey")
|
|
addKeybindRow(KeybindsPage, "Teleport Point Key", "teleportPointKey")
|
|
addKeybindRow(KeybindsPage, "Bird Teleport Key", "birdTeleportKey")
|
|
addKeybindRow(KeybindsPage, "Sniper Kill Key", "sniperKillKey")
|
|
addKeybindRow(KeybindsPage, "Cursor Release Key", "cursorReleaseKey")
|
|
|
|
addActionRow(ConfigPage, "Save Settings", "Save Now", function()
|
|
saveSettings()
|
|
end)
|
|
|
|
addActionRow(ConfigPage, "Reset", "Defaults", function()
|
|
applyDefaultSettings()
|
|
refreshKeyObjects()
|
|
|
|
bindingTarget = nil
|
|
aimHoldingKeyboard = false
|
|
aimHoldingMouse = false
|
|
autoStopHolding = false
|
|
cursorReleased = false
|
|
birdTeleportActive = false
|
|
birdMaintenanceAccumulator = 0
|
|
birdParkPosition = nil
|
|
destroyBirdProxy()
|
|
recomputeAimHolding()
|
|
|
|
espAccumulator = 0
|
|
espWasEnabledLastTick = false
|
|
espActivityStates = {}
|
|
selectedTeleportPointIndex = 1
|
|
selectedTeleportPlayerIndex = 1
|
|
selectedTeleportPlayerUserId = nil
|
|
selectedTeleportPlayerUserIds = {}
|
|
|
|
MainFrame.Visible = settings.uiVisible
|
|
applyCameraMode()
|
|
applyBirdCameraTarget()
|
|
applySpeed()
|
|
applyBirdHumanoidState(false)
|
|
applyCharacterNoclip(false)
|
|
applyPlayerVisibility()
|
|
hideAllEspEntries()
|
|
saveSettings()
|
|
|
|
refreshAll()
|
|
end)
|
|
|
|
addToggleRow(ConfigPage, "UI Visible", function()
|
|
return settings.uiVisible
|
|
end, function(state)
|
|
settings.uiVisible = state
|
|
MainFrame.Visible = state
|
|
saveSettings()
|
|
end)
|
|
|
|
local function refreshHint()
|
|
Hint.Text = "UI: " .. settings.uiToggleKey .. " | ESP: " .. settings.espToggleKey .. " | TP View: " .. settings.teleportViewKey .. " | TP Point: " .. settings.teleportPointKey .. " | Bird: " .. settings.birdTeleportKey .. " | Sniper: " .. settings.sniperKillKey .. " | Cursor: " .. settings.cursorReleaseKey
|
|
end
|
|
|
|
local function refreshModeStatus()
|
|
local birdText = birdTeleportActive and "Bird Mode: ACTIVE" or "Bird Mode: OFF"
|
|
local invisibilityActive = birdTeleportActive
|
|
local invisText = invisibilityActive and "Invisibility: ACTIVE" or "Invisibility: OFF"
|
|
local anyActive = birdTeleportActive or invisibilityActive
|
|
|
|
local statusText = birdText .. " | " .. invisText
|
|
ModeStatus.Text = statusText
|
|
ModeStatus.TextColor3 = anyActive and Color3.fromRGB(255, 204, 128) or Color3.fromRGB(170, 170, 180)
|
|
|
|
ModeOverlay.Visible = anyActive
|
|
ModeOverlay.Text = statusText
|
|
end
|
|
|
|
table.insert(refreshers, refreshHint)
|
|
table.insert(refreshers, refreshModeStatus)
|
|
|
|
switchTab("Combat")
|
|
applyCameraMode()
|
|
applySpeed()
|
|
applyPlayerVisibility()
|
|
refreshAll()
|
|
|
|
trackConnection(Players.PlayerAdded:Connect(function(player)
|
|
if player ~= LocalPlayer then
|
|
trackedPlayers[#trackedPlayers + 1] = player
|
|
refreshAll()
|
|
end
|
|
end))
|
|
|
|
trackConnection(Players.PlayerRemoving:Connect(function(player)
|
|
removeTrackedPlayer(player)
|
|
destroyEspEntry(player)
|
|
refreshAll()
|
|
end))
|
|
|
|
trackConnection(UserInputService.InputBegan:Connect(function(input, gameProcessed)
|
|
if bindingTarget then
|
|
if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode ~= Enum.KeyCode.Unknown then
|
|
settings[bindingTarget] = input.KeyCode.Name
|
|
bindingTarget = nil
|
|
refreshKeyObjects()
|
|
saveSettings()
|
|
refreshAll()
|
|
end
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode == currentUiToggleKey then
|
|
settings.uiVisible = not settings.uiVisible
|
|
MainFrame.Visible = settings.uiVisible
|
|
saveSettings()
|
|
refreshAll()
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode == currentCursorReleaseKey then
|
|
cursorReleased = not cursorReleased
|
|
applyCursorMode()
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.Keyboard and isBoundKeyPressed(input.KeyCode, currentBirdTeleportKey) then
|
|
setBirdTeleportActive(not birdTeleportActive)
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.Keyboard and isBoundKeyPressed(input.KeyCode, currentSniperKillKey) then
|
|
task.spawn(sniperKillSelectedPlayers)
|
|
return
|
|
end
|
|
|
|
if gameProcessed then
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.Keyboard then
|
|
if input.KeyCode == currentEspToggleKey then
|
|
settings.espEnabled = not settings.espEnabled
|
|
if not settings.espEnabled then
|
|
hideAllEspEntries()
|
|
end
|
|
saveSettings()
|
|
refreshAll()
|
|
return
|
|
end
|
|
|
|
if input.KeyCode == currentTeleportViewKey then
|
|
teleportToView()
|
|
return
|
|
end
|
|
|
|
if input.KeyCode == currentTeleportPointKey then
|
|
teleportToSelectedPoint()
|
|
return
|
|
end
|
|
|
|
if settings.aimEnabled and input.KeyCode == currentAimKey then
|
|
aimHoldingKeyboard = true
|
|
recomputeAimHolding()
|
|
return
|
|
end
|
|
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
|
|
if settings.autoStopEnabled then
|
|
autoStopHolding = true
|
|
applyAutoStop()
|
|
end
|
|
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
|
|
if settings.aimEnabled and settings.aimUseRightMouse then
|
|
aimHoldingMouse = true
|
|
recomputeAimHolding()
|
|
end
|
|
end
|
|
end))
|
|
|
|
trackConnection(UserInputService.InputEnded:Connect(function(input)
|
|
if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode == currentAimKey then
|
|
aimHoldingKeyboard = false
|
|
recomputeAimHolding()
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
|
autoStopHolding = false
|
|
return
|
|
end
|
|
|
|
if input.UserInputType == Enum.UserInputType.MouseButton2 then
|
|
aimHoldingMouse = false
|
|
recomputeAimHolding()
|
|
end
|
|
end))
|
|
|
|
trackConnection(RunService.RenderStepped:Connect(function(deltaTime)
|
|
updateFovCircle()
|
|
|
|
if birdTeleportActive then
|
|
applyBirdFlight(deltaTime)
|
|
end
|
|
|
|
if not settings.aimEnabled or not isHoldingAim then
|
|
return
|
|
end
|
|
|
|
local targetHead = findClosestTarget(settings.aimFOV)
|
|
if targetHead then
|
|
local cameraPosition = Camera.CFrame.Position
|
|
Camera.CFrame = CFrame.new(cameraPosition, targetHead.Position)
|
|
end
|
|
end))
|
|
|
|
trackConnection(RunService.Stepped:Connect(function()
|
|
if birdTeleportActive then
|
|
updateBirdParkedCharacter()
|
|
end
|
|
end))
|
|
|
|
trackConnection(RunService.Heartbeat:Connect(function(deltaTime)
|
|
if settings.autoStopEnabled and autoStopHolding then
|
|
applyAutoStop()
|
|
end
|
|
|
|
if birdTeleportActive then
|
|
birdMaintenanceAccumulator = birdMaintenanceAccumulator + deltaTime
|
|
if birdMaintenanceAccumulator >= 0.25 then
|
|
birdMaintenanceAccumulator = 0
|
|
applyBirdHumanoidState(true)
|
|
applyCharacterNoclip(true)
|
|
applyBirdCameraTarget()
|
|
applyPlayerVisibility()
|
|
end
|
|
else
|
|
birdMaintenanceAccumulator = 0
|
|
end
|
|
|
|
espAccumulator = espAccumulator + deltaTime
|
|
|
|
local refreshInterval = math.max(settings.espRefreshMs / 1000, 0.033)
|
|
if espAccumulator < refreshInterval then
|
|
return
|
|
end
|
|
|
|
espAccumulator = 0
|
|
updateEsp()
|
|
end))
|
|
|