local function ref(obj)
	local ok, cloned = pcall(function()
		return cloneref(obj)
	end)
	return (ok and cloned) or obj
end

local Players = ref(game:GetService("Players"))
local RunService = ref(game:GetService("RunService"))
local UserInputService = ref(game:GetService("UserInputService"))
local CoreGui = ref(game:GetService("CoreGui"))
local HttpService = ref(game:GetService("HttpService"))
local Lighting = ref(game:GetService("Lighting"))
local TweenService = ref(game:GetService("TweenService"))

local LocalPlayer = Players.LocalPlayer

local function rndName(prefix)
	local suffix = HttpService:GenerateGUID(false):gsub("-", ""):sub(1, 12)
	return (prefix or "") .. suffix
end

local SESSION = rndName("s")
local BIND_NAME = rndName("rb")
local GUI_NAME = rndName("ui")
local HOLDER_NAME = rndName("hd")

local COLOR_PRESETS = {
	{ name = "Red", color = Color3.fromRGB(255, 70, 70) },
	{ name = "Orange", color = Color3.fromRGB(255, 140, 40) },
	{ name = "Yellow", color = Color3.fromRGB(255, 220, 60) },
	{ name = "Green", color = Color3.fromRGB(60, 220, 100) },
	{ name = "Cyan", color = Color3.fromRGB(60, 220, 230) },
	{ name = "Blue", color = Color3.fromRGB(70, 170, 255) },
	{ name = "Purple", color = Color3.fromRGB(170, 90, 255) },
	{ name = "Pink", color = Color3.fromRGB(255, 90, 180) },
	{ name = "White", color = Color3.fromRGB(240, 240, 245) },
	{ name = "Black", color = Color3.fromRGB(20, 20, 24) },
}

local Settings = {
	Enabled = true,
	ShowTeammates = false,
	Skeleton = true,
	Box = true,
	Health = true,
	Name = true,
	Glow = true,
	EnemyColor = Color3.fromRGB(255, 70, 70),
	TeamColor = Color3.fromRGB(70, 170, 255),
	SkeletonThickness = 1.4,
	BoxThickness = 1.4,
	-- Misc
	AntiFlash = false,
	RemoveSmoke = false,
	CustomEnv = false,
	CustomSky = false,
	EnvColor = Color3.fromRGB(128, 128, 128),
	SkyColor = Color3.fromRGB(80, 140, 220),
	MenuAccent = Color3.fromRGB(47, 128, 255),
}

-- Original lighting snapshot for restore
local LightingBackup = {
	Ambient = Lighting.Ambient,
	OutdoorAmbient = Lighting.OutdoorAmbient,
	ColorShift_Top = Lighting.ColorShift_Top,
	ColorShift_Bottom = Lighting.ColorShift_Bottom,
	Brightness = Lighting.Brightness,
	FogColor = Lighting.FogColor,
}


----------------------------------------------------------------
-- Languages (en default, tr, ru, vi)
----------------------------------------------------------------

local LANGUAGE_OPTIONS = {
	{ code = "en", label = "English" },
	{ code = "tr", label = "Türkçe" },
	{ code = "ru", label = "Русский" },
	{ code = "vi", label = "Tiếng Việt" },
}

local LANGUAGE_FILE = "DedeHub/Language.txt"

local Locales = {
	en = {
		hub_name = "DEDE HUB",
		nav_vision = "Vision",
		nav_entities = "Entities",
		nav_misc = "Misc",
		nav_settings = "Settings",
		sec_esp = "ESP",
		sec_esp_sub = "Wall vision overlays",
		tog_skeleton = "Bone / Skeleton",
		tog_skeleton_desc = "Joint line overlay",
		tog_box = "Box",
		tog_box_desc = "2D bounding box",
		tog_health = "Health",
		tog_health_desc = "Side health bar",
		tog_name = "Name",
		tog_name_desc = "Player name tag",
		tog_glow = "Glow",
		tog_glow_desc = "Filled body glow",
		sec_filters = "Filters",
		tog_teammates = "Show teammates",
		tog_teammates_desc = "Include same team",
		tog_master = "Master ESP",
		tog_master_desc = "Enable all overlays",
		sec_players = "Players",
		sec_players_sub = "Who appears on ESP",
		tog_teammates_ent_desc = "Same team players",
		tog_master_ent_desc = "Global ESP switch",
		sec_protection = "Protection",
		sec_protection_sub = "Visual countermeasures",
		tog_antiflash = "Anti Flash",
		tog_antiflash_desc = "Lighting + screen flash block",
		tog_smoke = "Remove Smoke",
		tog_smoke_desc = "Smoke / fog / particles",
		sec_world = "World",
		sec_world_sub = "Lighting & atmosphere",
		tog_env = "Environment color",
		tog_env_desc = "Tint ambient lighting",
		tog_sky = "Sky color",
		tog_sky_desc = "Tint sky / atmosphere",
		color_env = "Environment tint",
		color_sky = "Sky tint",
		sec_esp_colors = "ESP Colors",
		sec_esp_colors_sub = "Overlay palette",
		color_enemy = "Enemy color",
		color_team = "Teammate color",
		sec_interface = "Interface",
		sec_interface_sub = "Menu controls",
		tip_controls = "• DEL — hide / show menu\n• Drag from the top to move\n• Use the left sidebar to switch tabs",
		sec_appearance = "Appearance",
		sec_appearance_sub = "Menu accent color",
		color_menu = "Menu color",
		sec_language = "Language",
		sec_language_sub = "UI language",
		sec_session = "Session",
		sec_session_sub = "Unload cheat completely",
		btn_destroy = "Destroy  —  kill script",
		btn_closing = "Closing...",
	},
	tr = {
		hub_name = "DEDE HUB",
		nav_vision = "Görüş",
		nav_entities = "Varlıklar",
		nav_misc = "Diğer",
		nav_settings = "Ayarlar",
		sec_esp = "ESP",
		sec_esp_sub = "Duvar arkası görüş",
		tog_skeleton = "Kemik / Skeleton",
		tog_skeleton_desc = "Eklem çizgileri",
		tog_box = "Kutu",
		tog_box_desc = "2D sınır kutusu",
		tog_health = "Can",
		tog_health_desc = "Yan can barı",
		tog_name = "İsim",
		tog_name_desc = "Oyuncu isim etiketi",
		tog_glow = "Parlama",
		tog_glow_desc = "Gövde dolgu parlaması",
		sec_filters = "Filtreler",
		tog_teammates = "Takımı göster",
		tog_teammates_desc = "Aynı takımı dahil et",
		tog_master = "Ana ESP",
		tog_master_desc = "Tüm overlay'leri aç",
		sec_players = "Oyuncular",
		sec_players_sub = "ESP'de kimler görünsün",
		tog_teammates_ent_desc = "Aynı takım oyuncuları",
		tog_master_ent_desc = "Global ESP anahtarı",
		sec_protection = "Koruma",
		sec_protection_sub = "Görsel karşı önlemler",
		tog_antiflash = "Anti Flash",
		tog_antiflash_desc = "Işık + ekran flash engeli",
		tog_smoke = "Smoke Kaldır",
		tog_smoke_desc = "Duman / sis / particle",
		sec_world = "Dünya",
		sec_world_sub = "Işık ve atmosfer",
		tog_env = "Çevre rengi",
		tog_env_desc = "Ortam ışığını renklendir",
		tog_sky = "Gökyüzü rengi",
		tog_sky_desc = "Gökyüzü / atmosfer tonu",
		color_env = "Çevre tonu",
		color_sky = "Gökyüzü tonu",
		sec_esp_colors = "ESP Renkleri",
		sec_esp_colors_sub = "Overlay paleti",
		color_enemy = "Düşman rengi",
		color_team = "Takım rengi",
		sec_interface = "Arayüz",
		sec_interface_sub = "Menü kontrolleri",
		tip_controls = "• DEL — menüyü gizle / göster\n• Üstten tutup sürükle\n• Sol menüden sekmeler arasında geç",
		sec_appearance = "Görünüm",
		sec_appearance_sub = "Menü vurgu rengi",
		color_menu = "Menü rengi",
		sec_language = "Dil",
		sec_language_sub = "Arayüz dili",
		sec_session = "Oturum",
		sec_session_sub = "Hileyi tamamen kapat",
		btn_destroy = "Destroy  —  scripti kapat",
		btn_closing = "Kapatılıyor...",
	},
	ru = {
		hub_name = "DEDE HUB",
		nav_vision = "Обзор",
		nav_entities = "Сущности",
		nav_misc = "Разное",
		nav_settings = "Настройки",
		sec_esp = "ESP",
		sec_esp_sub = "Обзор сквозь стены",
		tog_skeleton = "Кости / Skeleton",
		tog_skeleton_desc = "Линии суставов",
		tog_box = "Бокс",
		tog_box_desc = "2D рамка",
		tog_health = "Здоровье",
		tog_health_desc = "Полоска здоровья",
		tog_name = "Имя",
		tog_name_desc = "Имя игрока",
		tog_glow = "Свечение",
		tog_glow_desc = "Заливка тела",
		sec_filters = "Фильтры",
		tog_teammates = "Показывать команду",
		tog_teammates_desc = "Включать союзников",
		tog_master = "Главный ESP",
		tog_master_desc = "Включить все оверлеи",
		sec_players = "Игроки",
		sec_players_sub = "Кто виден в ESP",
		tog_teammates_ent_desc = "Игроки своей команды",
		tog_master_ent_desc = "Глобальный ESP",
		sec_protection = "Защита",
		sec_protection_sub = "Визуальные контрмеры",
		tog_antiflash = "Anti Flash",
		tog_antiflash_desc = "Блок вспышек света / экрана",
		tog_smoke = "Убрать дым",
		tog_smoke_desc = "Дым / туман / частицы",
		sec_world = "Мир",
		sec_world_sub = "Освещение и атмосфера",
		tog_env = "Цвет окружения",
		tog_env_desc = "Оттенок ambient света",
		tog_sky = "Цвет неба",
		tog_sky_desc = "Оттенок неба / атмосферы",
		color_env = "Тон окружения",
		color_sky = "Тон неба",
		sec_esp_colors = "Цвета ESP",
		sec_esp_colors_sub = "Палитра оверлея",
		color_enemy = "Цвет врага",
		color_team = "Цвет союзника",
		sec_interface = "Интерфейс",
		sec_interface_sub = "Управление меню",
		tip_controls = "• DEL — скрыть / показать меню\n• Тяни за верх, чтобы переместить\n• Вкладки слева",
		sec_appearance = "Оформление",
		sec_appearance_sub = "Акцентный цвет меню",
		color_menu = "Цвет меню",
		sec_language = "Язык",
		sec_language_sub = "Язык интерфейса",
		sec_session = "Сессия",
		sec_session_sub = "Полностью выгрузить чит",
		btn_destroy = "Destroy  —  закрыть скрипт",
		btn_closing = "Закрытие...",
	},
	vi = {
		hub_name = "DEDE HUB",
		nav_vision = "Tầm nhìn",
		nav_entities = "Thực thể",
		nav_misc = "Khác",
		nav_settings = "Cài đặt",
		sec_esp = "ESP",
		sec_esp_sub = "Nhìn xuyên tường",
		tog_skeleton = "Xương / Skeleton",
		tog_skeleton_desc = "Đường khớp xương",
		tog_box = "Hộp",
		tog_box_desc = "Khung 2D",
		tog_health = "Máu",
		tog_health_desc = "Thanh máu bên cạnh",
		tog_name = "Tên",
		tog_name_desc = "Nhãn tên người chơi",
		tog_glow = "Phát sáng",
		tog_glow_desc = "Tô sáng cơ thể",
		sec_filters = "Bộ lọc",
		tog_teammates = "Hiện đồng đội",
		tog_teammates_desc = "Bao gồm cùng đội",
		tog_master = "ESP chính",
		tog_master_desc = "Bật mọi overlay",
		sec_players = "Người chơi",
		sec_players_sub = "Ai hiện trên ESP",
		tog_teammates_ent_desc = "Người cùng đội",
		tog_master_ent_desc = "Công tắc ESP toàn cục",
		sec_protection = "Bảo vệ",
		sec_protection_sub = "Chống hiệu ứng thị giác",
		tog_antiflash = "Anti Flash",
		tog_antiflash_desc = "Chặn flash ánh sáng / màn hình",
		tog_smoke = "Xóa khói",
		tog_smoke_desc = "Khói / sương / particle",
		sec_world = "Thế giới",
		sec_world_sub = "Ánh sáng & bầu khí quyển",
		tog_env = "Màu môi trường",
		tog_env_desc = "Tô màu ánh sáng ambient",
		tog_sky = "Màu bầu trời",
		tog_sky_desc = "Tông bầu trời / atmosphere",
		color_env = "Tông môi trường",
		color_sky = "Tông bầu trời",
		sec_esp_colors = "Màu ESP",
		sec_esp_colors_sub = "Bảng màu overlay",
		color_enemy = "Màu địch",
		color_team = "Màu đồng đội",
		sec_interface = "Giao diện",
		sec_interface_sub = "Điều khiển menu",
		tip_controls = "• DEL — ẩn / hiện menu\n• Kéo từ trên để di chuyển\n• Đổi tab ở thanh bên trái",
		sec_appearance = "Giao diện màu",
		sec_appearance_sub = "Màu nhấn menu",
		color_menu = "Màu menu",
		sec_language = "Ngôn ngữ",
		sec_language_sub = "Ngôn ngữ giao diện",
		sec_session = "Phiên",
		sec_session_sub = "Tắt hoàn toàn cheat",
		btn_destroy = "Destroy  —  tắt script",
		btn_closing = "Đang đóng...",
	},
}

local function normalizeLanguage(code)
	code = tostring(code or "en"):lower()
	if Locales[code] then
		return code
	end
	return "en"
end

local function readSavedLanguage()
	local fromEnv = nil
	pcall(function()
		if typeof(getgenv) == "function" then
			fromEnv = getgenv().DedeHubLanguage
		end
	end)
	if type(fromEnv) == "string" and #fromEnv > 0 then
		return fromEnv
	end
	if typeof(isfile) == "function" and typeof(readfile) == "function" then
		local ok, content = pcall(function()
			if isfile(LANGUAGE_FILE) then
				return readfile(LANGUAGE_FILE)
			end
			return nil
		end)
		if ok and type(content) == "string" and #content > 0 then
			return content:match("%S+")
		end
	end
	return "en"
end

local function persistLanguage(code)
	pcall(function()
		if typeof(getgenv) == "function" then
			getgenv().DedeHubLanguage = code
		end
	end)
	if typeof(writefile) == "function" then
		pcall(function()
			if typeof(makefolder) == "function" and typeof(isfolder) == "function" and not isfolder("DedeHub") then
				makefolder("DedeHub")
			end
			writefile(LANGUAGE_FILE, code)
		end)
	end
end

local currentLanguage = normalizeLanguage(readSavedLanguage())
persistLanguage(currentLanguage)

local function t(key, ...)
	local pack = Locales[currentLanguage] or Locales.en
	local str = pack[key] or Locales.en[key] or tostring(key)
	if select("#", ...) > 0 then
		local ok, formatted = pcall(string.format, str, ...)
		if ok then
			return formatted
		end
	end
	return str
end

local localeBindings = {}

local function bindLocale(inst, key, opts)
	opts = opts or {}
	localeBindings[#localeBindings + 1] = {
		inst = inst,
		key = key,
		prop = opts.prop or "Text",
		upper = opts.upper == true,
		prefix = opts.prefix,
		suffix = opts.suffix,
		icon = opts.icon,
	}
	local str = t(key)
	if opts.upper then
		str = string.upper(str)
	end
	if opts.icon then
		str = "  " .. opts.icon .. "   " .. str
	end
	if opts.prefix then
		str = opts.prefix .. str
	end
	if opts.suffix then
		str = str .. opts.suffix
	end
	inst[opts.prop or "Text"] = str
end

local function applyLocaleToUI()
	for i = 1, #localeBindings do
		local b = localeBindings[i]
		if b.inst and b.inst.Parent then
			local str = t(b.key)
			if b.upper then
				str = string.upper(str)
			end
			if b.icon then
				str = "  " .. b.icon .. "   " .. str
			end
			if b.prefix then
				str = b.prefix .. str
			end
			if b.suffix then
				str = str .. b.suffix
			end
			b.inst[b.prop] = str
		end
	end
end

local function setLanguage(code)
	currentLanguage = normalizeLanguage(code)
	persistLanguage(currentLanguage)
	applyLocaleToUI()
	return currentLanguage
end


----------------------------------------------------------------
-- Script body
----------------------------------------------------------------

local function getHiddenUiParent()
	local parent
	pcall(function()
		if typeof(gethui) == "function" then
			parent = gethui()
		end
	end)
	if not parent then
		parent = CoreGui
	end
	return parent
end

local function protect(gui)
	pcall(function()
		if syn and syn.protect_gui then
			syn.protect_gui(gui)
		elseif protect_gui then
			protect_gui(gui)
		elseif typeof(protectgui) == "function" then
			protectgui(gui)
		end
	end)
end

-- Tear down previous session markers stored weakly via attribute on holder
local uiParent = getHiddenUiParent()
pcall(function()
	for _, child in ipairs(uiParent:GetChildren()) do
		if child:GetAttribute("_sid") == true then
			child:Destroy()
		end
	end
end)

local holder = Instance.new("Folder")
holder.Name = HOLDER_NAME
holder:SetAttribute("_sid", true)
holder.Parent = uiParent


local tracked = {}
local connections = {}
local alive = true
local DRAWING_OK = typeof(Drawing) == "table" and typeof(Drawing.new) == "function"

local R15_PAIRS = {
	{ "Head", "UpperTorso" },
	{ "UpperTorso", "LowerTorso" },
	{ "UpperTorso", "LeftUpperArm" },
	{ "LeftUpperArm", "LeftLowerArm" },
	{ "LeftLowerArm", "LeftHand" },
	{ "UpperTorso", "RightUpperArm" },
	{ "RightUpperArm", "RightLowerArm" },
	{ "RightLowerArm", "RightHand" },
	{ "LowerTorso", "LeftUpperLeg" },
	{ "LeftUpperLeg", "LeftLowerLeg" },
	{ "LeftLowerLeg", "LeftFoot" },
	{ "LowerTorso", "RightUpperLeg" },
	{ "RightUpperLeg", "RightLowerLeg" },
	{ "RightLowerLeg", "RightFoot" },
}

local R6_PAIRS = {
	{ "Head", "Torso" },
	{ "Torso", "Left Arm" },
	{ "Torso", "Right Arm" },
	{ "Torso", "Left Leg" },
	{ "Torso", "Right Leg" },
}

local boundBuf = { x = 0, y = 0, w = 0, h = 0 }
local camCache = nil
local frameId = 0
local playerList = {} -- flat list for staggered updates
local playerListDirty = true

local function rebuildPlayerList()
	table.clear(playerList)
	for player in pairs(tracked) do
		playerList[#playerList + 1] = player
	end
	playerListDirty = false
end

local function trackConn(conn)
	connections[#connections + 1] = conn
	return conn
end

local function safeRemove(obj)
	if not obj then return end
	pcall(function()
		obj.Visible = false
		obj:Remove()
	end)
end

local function isTeammate(player)
	local a, b = player.Team, LocalPlayer.Team
	return a ~= nil and b ~= nil and a == b
end

local function shouldShow(player)
	if not Settings.Enabled or not alive then return false end
	if player == LocalPlayer then return false end
	if not Settings.ShowTeammates and isTeammate(player) then return false end
	return true
end

local function getColor(player)
	return isTeammate(player) and Settings.TeamColor or Settings.EnemyColor
end

local function w2s(pos)
	local cam = camCache
	if not cam then return nil, false end
	local v, onScreen = cam:WorldToViewportPoint(pos)
	if (not onScreen) or v.Z <= 0 then return nil, false end
	return v, true
end

local function healthColor(ratio)
	ratio = math.clamp(ratio, 0, 1)
	return Color3.fromRGB(
		math.floor(255 * (1 - ratio)),
		math.floor(255 * ratio),
		35
	)
end

local function getCharacterBounds(entry)
	local cam = camCache
	local hrp = entry.hrp
	if not cam or not hrp or not hrp.Parent then return nil end

	local head = entry.head
	local topPos = (head and head.Parent)
		and (head.Position + Vector3.new(0, 0.4, 0))
		or (hrp.Position + Vector3.new(0, 2.6, 0))
	local footPos = hrp.Position - Vector3.new(0, 3.05, 0)

	-- Don't require onScreen flag — Z depth alone; keeps size stable at range
	local top = cam:WorldToViewportPoint(topPos)
	local bottom = cam:WorldToViewportPoint(footPos)
	if top.Z <= 0 or bottom.Z <= 0 then return nil end

	local height = math.abs(top.Y - bottom.Y)
	local dist = (cam.CFrame.Position - hrp.Position).Magnitude

	-- Fallback if projection collapses (edge angles)
	if height < 6 then
		local vh = cam.ViewportSize.Y
		height = (5 / math.max(dist, 1)) * (vh * 0.55)
	end

	-- Hard clamps so boxes never explode from accessories / angles
	height = math.clamp(height, 6, math.min(cam.ViewportSize.Y * 0.55, 260))
	local width = math.clamp(height * 0.5, 4, math.min(cam.ViewportSize.X * 0.28, 140))

	local cx = (top.X + bottom.X) * 0.5
	local topY = math.min(top.Y, bottom.Y)

	boundBuf.x = cx - width * 0.5
	boundBuf.y = topY
	boundBuf.w = width
	boundBuf.h = height
	return boundBuf
end

local function hideDrawings(entry)
	if not entry or not entry.drawn then return end
	entry.drawn = false
	if entry.box then
		for i = 1, 4 do entry.box[i].Visible = false end
	end
	if entry.skeleton then
		for i = 1, #entry.skeleton do entry.skeleton[i].Visible = false end
	end
	if entry.glow then entry.glow.Visible = false end
	if entry.healthBg then entry.healthBg.Visible = false end
	if entry.healthFg then entry.healthFg.Visible = false end
	if entry.nameText then entry.nameText.Visible = false end
end

local function destroyDrawings(entry)
	if not entry then return end
	if entry.box then
		for i = 1, #entry.box do safeRemove(entry.box[i]) end
		entry.box = nil
	end
	if entry.skeleton then
		for i = 1, #entry.skeleton do safeRemove(entry.skeleton[i]) end
		entry.skeleton = nil
	end
	safeRemove(entry.glow)
	safeRemove(entry.healthBg)
	safeRemove(entry.healthFg)
	safeRemove(entry.nameText)
	entry.glow = nil
	entry.healthBg = nil
	entry.healthFg = nil
	entry.nameText = nil
	entry.drawn = false
end

local function removePlayer(player)
	local entry = tracked[player]
	if not entry then return end
	destroyDrawings(entry)
	local ec = entry.connections
	if ec then
		for i = 1, #ec do
			pcall(function() ec[i]:Disconnect() end)
		end
	end
	tracked[player] = nil
	playerListDirty = true
end

local function newLine(thickness)
	local line = Drawing.new("Line")
	line.Thickness = thickness
	line.Transparency = 1
	line.Visible = false
	return line
end

local function ensureDrawings(entry)
	if not DRAWING_OK then return false end

	if Settings.Box and not entry.box then
		entry.box = {
			newLine(Settings.BoxThickness),
			newLine(Settings.BoxThickness),
			newLine(Settings.BoxThickness),
			newLine(Settings.BoxThickness),
		}
	end

	if Settings.Skeleton and not entry.skeleton then
		local n = math.max(1, entry.boneLive or entry.boneCount or #R15_PAIRS)
		entry.skeleton = table.create(n)
		for i = 1, n do
			entry.skeleton[i] = newLine(Settings.SkeletonThickness)
		end
	end

	if Settings.Glow and not entry.glow then
		local g = Drawing.new("Square")
		g.Filled = true
		g.Thickness = 0
		g.Transparency = 0.72
		g.Visible = false
		entry.glow = g
	end

	if Settings.Health and not entry.healthBg then
		local bg = Drawing.new("Square")
		bg.Filled = true
		bg.Thickness = 0
		bg.Transparency = 1
		bg.Color = Color3.fromRGB(15, 15, 15)
		bg.Visible = false
		entry.healthBg = bg

		local fg = Drawing.new("Square")
		fg.Filled = true
		fg.Thickness = 0
		fg.Transparency = 1
		fg.Visible = false
		entry.healthFg = fg
	end

	if Settings.Name and not entry.nameText then
		local text = Drawing.new("Text")
		text.Center = true
		text.Outline = true
		text.Size = 13
		text.Font = 2
		text.Transparency = 1
		text.Visible = false
		entry.nameText = text
	end

	return true
end

local function cacheCharacter(entry, character)
	entry.char = character
	entry.hum = character:FindFirstChildOfClass("Humanoid")
	entry.hrp = character:FindFirstChild("HumanoidRootPart")
	entry.head = character:FindFirstChild("Head")

	local pairsDef = character:FindFirstChild("UpperTorso") and R15_PAIRS or R6_PAIRS
	entry.boneCount = #pairsDef
	local bones = table.create(#pairsDef)
	local count = 0
	for i = 1, #pairsDef do
		local a = character:FindFirstChild(pairsDef[i][1])
		local b = character:FindFirstChild(pairsDef[i][2])
		if a and b and a:IsA("BasePart") and b:IsA("BasePart") then
			count += 1
			bones[count] = { a, b }
		end
	end
	entry.bones = bones
	entry.boneLive = count

	if entry.skeleton and #entry.skeleton ~= count and count > 0 then
		for i = 1, #entry.skeleton do safeRemove(entry.skeleton[i]) end
		entry.skeleton = nil
	end
end

local function setBox(entry, bounds, color, visible)
	local box = entry.box
	if not box then return end
	if not visible or not bounds then
		for i = 1, 4 do box[i].Visible = false end
		return
	end
	local x, y, w, h = bounds.x, bounds.y, bounds.w, bounds.h
	local x2, y2 = x + w, y + h
	local l1, l2, l3, l4 = box[1], box[2], box[3], box[4]
	l1.From = Vector2.new(x, y);   l1.To = Vector2.new(x2, y);  l1.Color = color; l1.Visible = true
	l2.From = Vector2.new(x2, y);  l2.To = Vector2.new(x2, y2); l2.Color = color; l2.Visible = true
	l3.From = Vector2.new(x2, y2); l3.To = Vector2.new(x, y2);  l3.Color = color; l3.Visible = true
	l4.From = Vector2.new(x, y2);  l4.To = Vector2.new(x, y);   l4.Color = color; l4.Visible = true
end

local function setGlow(entry, bounds, color, visible)
	local g = entry.glow
	if not g then return end
	if not visible or not bounds then
		g.Visible = false
		return
	end
	g.Position = Vector2.new(bounds.x, bounds.y)
	g.Size = Vector2.new(bounds.w, bounds.h)
	g.Color = color
	g.Visible = true
end

local function setSkeleton(entry, color, visible)
	local lines = entry.skeleton
	local bones = entry.bones
	if not lines or not bones then return end
	if not visible then
		for i = 1, #lines do lines[i].Visible = false end
		return
	end
	local n = math.min(#lines, entry.boneLive or 0)
	for i = 1, n do
		local bone = bones[i]
		local line = lines[i]
		local v1, ok1 = w2s(bone[1].Position)
		local v2, ok2 = w2s(bone[2].Position)
		if ok1 and ok2 then
			line.From = Vector2.new(v1.X, v1.Y)
			line.To = Vector2.new(v2.X, v2.Y)
			line.Color = color
			line.Visible = true
		else
			line.Visible = false
		end
	end
	for i = n + 1, #lines do
		lines[i].Visible = false
	end
end

local function setHealth(entry, hum, bounds, visible)
	local bg, fg = entry.healthBg, entry.healthFg
	if not bg or not fg then return end
	if not visible or not bounds or not hum then
		bg.Visible = false
		fg.Visible = false
		return
	end
	local ratio = math.clamp(hum.Health / math.max(1, hum.MaxHealth), 0, 1)
	local x = bounds.x - 6
	local y, h = bounds.y, bounds.h
	local filled = h * ratio
	bg.Position = Vector2.new(x, y)
	bg.Size = Vector2.new(3, h)
	bg.Visible = true
	fg.Position = Vector2.new(x, y + (h - filled))
	fg.Size = Vector2.new(3, filled)
	fg.Color = healthColor(ratio)
	fg.Visible = true
end

local function setName(entry, player, bounds, head, color, visible)
	local text = entry.nameText
	if not text then return end
	if not visible then
		text.Visible = false
		return
	end

	local posX, posY
	if bounds then
		posX = bounds.x + bounds.w * 0.5
		posY = bounds.y - 15
	elseif head then
		local v, ok = w2s(head.Position + Vector3.new(0, 1.15, 0))
		if not ok then
			text.Visible = false
			return
		end
		posX, posY = v.X, v.Y
	else
		text.Visible = false
		return
	end

	if entry.nameStr == nil then
		local dn, nm = player.DisplayName, player.Name
		entry.nameStr = (dn ~= nm) and (dn .. " @" .. nm) or nm
		text.Text = entry.nameStr
	end
	text.Position = Vector2.new(posX, posY)
	text.Color = color
	text.Visible = true
end

local function updatePlayer(player, entry)
	local character = player.Character
	if not character then
		hideDrawings(entry)
		entry.char = nil
		return
	end

	-- Re-cache when character is new OR parts weren't ready on first cache
	if character ~= entry.char
		or not entry.hrp or entry.hrp.Parent ~= character
		or not entry.hum or entry.hum.Parent ~= character
	then
		cacheCharacter(entry, character)
	end

	local hum = entry.hum
	if not hum or hum.Health <= 0 then
		hideDrawings(entry)
		return
	end

	if not shouldShow(player) then
		hideDrawings(entry)
		return
	end

	local hrp = entry.hrp
	if not hrp or hrp.Parent ~= character then
		hideDrawings(entry)
		return
	end

	local _, onHrp = w2s(hrp.Position)
	if not onHrp then
		hideDrawings(entry)
		return
	end

	if not ensureDrawings(entry) then return end
	entry.drawn = true

	local color = getColor(player)
	local needBounds = Settings.Box or Settings.Health or Settings.Name or Settings.Glow
	local bounds = needBounds and getCharacterBounds(entry) or nil
	local onScreen = bounds ~= nil

	if Settings.Glow then
		setGlow(entry, bounds, color, onScreen)
	elseif entry.glow then
		entry.glow.Visible = false
	end

	if Settings.Box then
		setBox(entry, bounds, color, onScreen)
	elseif entry.box then
		for i = 1, 4 do entry.box[i].Visible = false end
	end

	if Settings.Skeleton then
		-- Refresh bones if still incomplete (R15 parts stream in late)
		if (entry.boneLive or 0) < 5 then
			cacheCharacter(entry, character)
		end
		setSkeleton(entry, color, true)
	elseif entry.skeleton then
		for i = 1, #entry.skeleton do entry.skeleton[i].Visible = false end
	end

	if Settings.Health then
		setHealth(entry, hum, bounds, onScreen)
	elseif entry.healthBg then
		entry.healthBg.Visible = false
		if entry.healthFg then entry.healthFg.Visible = false end
	end

	if Settings.Name then
		setName(entry, player, bounds, entry.head, color, true)
	elseif entry.nameText then
		entry.nameText.Visible = false
	end
end

local function hookPlayer(player)
	if player == LocalPlayer or tracked[player] then return end

	local entry = {
		drawn = false,
		connections = {},
		nameStr = nil,
	}
	tracked[player] = entry
	playerListDirty = true

	local function onCharacter(char)
		if typeof(char) ~= "Instance" then return end
		task.spawn(function()
			if tracked[player] ~= entry or not alive then return end
			char:WaitForChild("Humanoid", 8)
			char:WaitForChild("HumanoidRootPart", 8)
			char:WaitForChild("Head", 8)
			if tracked[player] ~= entry or not alive then return end
			if player.Character ~= char then return end
			cacheCharacter(entry, char)
			entry.nameStr = nil
			playerListDirty = true

			-- Parts can appear slightly later (R15)
			task.wait(0.35)
			if tracked[player] == entry and alive and player.Character == char then
				cacheCharacter(entry, char)
			end
		end)
	end

	if player.Character then
		onCharacter(player.Character)
	end

	entry.connections[#entry.connections + 1] = player.CharacterAdded:Connect(onCharacter)
	entry.connections[#entry.connections + 1] = player.CharacterRemoving:Connect(function()
		hideDrawings(entry)
		entry.char = nil
		entry.hrp = nil
		entry.hum = nil
		entry.head = nil
		entry.bones = nil
	end)

	pcall(function()
		entry.connections[#entry.connections + 1] = player.CharacterAppearanceLoaded:Connect(function(char)
			if tracked[player] == entry and alive then
				cacheCharacter(entry, char)
				entry.nameStr = nil
			end
		end)
	end)
end

for _, player in ipairs(Players:GetPlayers()) do
	hookPlayer(player)
end
trackConn(Players.PlayerAdded:Connect(function(player)
	hookPlayer(player)
end))
trackConn(Players.PlayerRemoving:Connect(removePlayer))

----------------------------------------------------------------
-- Misc visuals — universal Anti Flash / Anti Smoke
----------------------------------------------------------------

local miscAtm = nil
local miscSkyCC = nil

local smokeConn = nil
local smokeLoop = nil
local smokeWatched = setmetatable({}, { __mode = "k" })
local FogBackup = {
	FogStart = Lighting.FogStart,
	FogEnd = Lighting.FogEnd,
}

local antiFlashConn = nil
local antiFlashBrightConn = nil
local antiFlashExposureConn = nil
local antiFlashGuiConn = nil
local antiFlashLoop = nil
local antiFlashFxConns = {}
local flashGuiWatched = setmetatable({}, { __mode = "k" })
local flashFxHooked = setmetatable({}, { __mode = "k" })

local SMOKE_WORDS = {
	"smoke", "smok", "fog", "mist", "dust", "cloud", "steam",
	"haze", "gas", "smokescreen", "smokegrenade", "smoke_nade",
	"particle_smoke", "smokeparticle", "vapor", "fume",
}

local FLASH_WORDS = {
	"flash", "blind", "whiteout", "stun", "flashbang", "flashed",
	"flashgui", "blindness", "screenflash", "whitflash", "impactflash",
}

local function textHasWord(text, words)
	if not text or text == "" then return false end
	local t = string.lower(text)
	for i = 1, #words do
		if string.find(t, words[i], 1, true) then
			return true
		end
	end
	return false
end

local function pathLooksSmoke(inst)
	local cur = inst
	for _ = 1, 5 do
		if not cur then break end
		if textHasWord(cur.Name, SMOKE_WORDS) then return true end
		cur = cur.Parent
	end
	return false
end

local function isSmokeLike(inst)
	if not inst or not inst.Parent then return false end
	if inst:IsA("Smoke") then return true end
	if inst:IsA("ParticleEmitter") then
		if pathLooksSmoke(inst) then return true end
		local ok, tex = pcall(function()
			return tostring(inst.Texture)
		end)
		if ok and textHasWord(tex, SMOKE_WORDS) then return true end
		-- Large soft gray clouds often used as smoke without keywords
		local ok2, size = pcall(function()
			return inst.Size
		end)
		if ok2 and typeof(size) == "NumberSequence" then
			local keypoints = size.Keypoints
			local maxSz = 0
			for i = 1, #keypoints do
				if keypoints[i].Value > maxSz then maxSz = keypoints[i].Value end
			end
			if maxSz >= 4 and inst.Rate >= 12 and pathLooksSmoke(inst.Parent) then
				return true
			end
		end
		return false
	end
	if inst:IsA("Fire") then
		return pathLooksSmoke(inst)
	end
	return false
end

local function neutralizeSmoke(inst)
	if not inst then return end
	pcall(function()
		if inst:IsA("Smoke") then
			inst.Enabled = false
			inst.Opacity = 0
			inst.Size = 0
		elseif inst:IsA("ParticleEmitter") then
			inst.Enabled = false
			inst.Rate = 0
			pcall(function()
				inst.Lifetime = NumberRange.new(0)
			end)
		elseif inst:IsA("Fire") then
			inst.Enabled = false
			inst.Size = 0
		end
	end)

	if smokeWatched[inst] then return end
	smokeWatched[inst] = true

	if inst:IsA("ParticleEmitter") or inst:IsA("Smoke") or inst:IsA("Fire") then
		local c1 = inst:GetPropertyChangedSignal("Enabled"):Connect(function()
			if Settings.RemoveSmoke and inst.Parent and inst.Enabled then
				inst.Enabled = false
			end
		end)
		table.insert(connections, c1)
		if inst:IsA("ParticleEmitter") then
			local c2 = inst:GetPropertyChangedSignal("Rate"):Connect(function()
				if Settings.RemoveSmoke and inst.Parent and inst.Rate > 0 then
					inst.Rate = 0
				end
			end)
			table.insert(connections, c2)
		end
	end
end

local function sweepSmokeIn(root)
	if not root then return end
	task.spawn(function()
		local list = root:GetDescendants()
		local i, n = 1, #list
		while i <= n and Settings.RemoveSmoke and alive do
			local last = math.min(i + 100, n)
			for j = i, last do
				local inst = list[j]
				if isSmokeLike(inst) then
					neutralizeSmoke(inst)
				end
			end
			i = last + 1
			task.wait()
		end
	end)
end

local function setRemoveSmoke(on)
	if smokeLoop then
		pcall(function() task.cancel(smokeLoop) end)
		smokeLoop = nil
	end
	-- disconnect only the DescendantAdded we stored on smokeConn
	if smokeConn then
		pcall(function() smokeConn:Disconnect() end)
		smokeConn = nil
	end

	if not on then
		pcall(function()
			Lighting.FogStart = FogBackup.FogStart
			Lighting.FogEnd = FogBackup.FogEnd
		end)
		return
	end

	FogBackup.FogStart = Lighting.FogStart
	FogBackup.FogEnd = Lighting.FogEnd
	pcall(function()
		Lighting.FogStart = 0
		Lighting.FogEnd = 1e6
	end)
	if miscAtm and miscAtm.Parent then
		pcall(function()
			miscAtm.Haze = 0
			miscAtm.Density = math.min(miscAtm.Density, 0.15)
		end)
	else
		local atm = Lighting:FindFirstChildOfClass("Atmosphere")
		if atm then
			pcall(function()
				atm.Haze = 0
			end)
		end
	end

	sweepSmokeIn(workspace)
	local cam = workspace.CurrentCamera
	if cam then sweepSmokeIn(cam) end

	smokeConn = workspace.DescendantAdded:Connect(function(inst)
		if not Settings.RemoveSmoke or not alive then return end
		if inst:IsA("Smoke") or inst:IsA("ParticleEmitter") or inst:IsA("Fire") then
			task.defer(function()
				if isSmokeLike(inst) then
					neutralizeSmoke(inst)
				end
			end)
		end
	end)

	smokeLoop = task.spawn(function()
		while Settings.RemoveSmoke and alive do
			task.wait(1.25)
			if not Settings.RemoveSmoke or not alive then break end
			sweepSmokeIn(workspace)
			local c = workspace.CurrentCamera
			if c then sweepSmokeIn(c) end
			pcall(function()
				if Lighting.FogEnd < 1e5 then
					Lighting.FogEnd = 1e6
				end
			end)
		end
	end)
end

local function clearAntiFlashHooks()
	if antiFlashConn then
		pcall(function() antiFlashConn:Disconnect() end)
		antiFlashConn = nil
	end
	if antiFlashBrightConn then
		pcall(function() antiFlashBrightConn:Disconnect() end)
		antiFlashBrightConn = nil
	end
	if antiFlashExposureConn then
		pcall(function() antiFlashExposureConn:Disconnect() end)
		antiFlashExposureConn = nil
	end
	if antiFlashGuiConn then
		pcall(function() antiFlashGuiConn:Disconnect() end)
		antiFlashGuiConn = nil
	end
	if antiFlashLoop then
		pcall(function() task.cancel(antiFlashLoop) end)
		antiFlashLoop = nil
	end
	for i = 1, #antiFlashFxConns do
		pcall(function() antiFlashFxConns[i]:Disconnect() end)
	end
	table.clear(antiFlashFxConns)
	table.clear(flashFxHooked)
end

local function neutralizeFlashGui(gui)
	if not gui or not gui.Parent then return end
	pcall(function()
		gui.Visible = false
		if gui:IsA("GuiObject") then
			gui.BackgroundTransparency = 1
		end
		if gui:IsA("ImageLabel") or gui:IsA("ImageButton") then
			gui.ImageTransparency = 1
		end
		if gui:IsA("Frame") or gui:IsA("ImageLabel") then
			-- collapse so layout can't re-cover screen
			gui.Size = UDim2.fromOffset(0, 0)
		end
	end)
	if flashGuiWatched[gui] then return end
	flashGuiWatched[gui] = true
	pcall(function()
		local c = gui:GetPropertyChangedSignal("Visible"):Connect(function()
			if Settings.AntiFlash and gui.Visible then
				gui.Visible = false
			end
		end)
		table.insert(connections, c)
	end)
end

local function isFullscreenFlash(gui)
	if not gui:IsA("GuiObject") then return false end
	if gui.BackgroundTransparency >= 0.55 and not (gui:IsA("ImageLabel") and gui.ImageTransparency < 0.55) then
		return false
	end
	local cam = workspace.CurrentCamera
	if not cam then return false end
	local vp = cam.ViewportSize
	local size = gui.AbsoluteSize
	if size.X < vp.X * 0.7 or size.Y < vp.Y * 0.7 then
		return false
	end
	local c = gui.BackgroundColor3
	local bright = (c.R + c.G + c.B) / 3
	if bright >= 0.75 then return true end
	if gui:IsA("ImageLabel") and gui.ImageTransparency < 0.4 then
		return true
	end
	return false
end

local function maybeFlashGui(gui)
	if not gui or not gui:IsA("GuiObject") then return end
	if textHasWord(gui.Name, FLASH_WORDS) then
		neutralizeFlashGui(gui)
		return
	end
	if isFullscreenFlash(gui) then
		neutralizeFlashGui(gui)
	end
end

local function scanFlashGuisLight()
	local pg = LocalPlayer:FindFirstChild("PlayerGui")
	if not pg then return end
	local cam = workspace.CurrentCamera
	local vp = cam and cam.ViewportSize
	for _, screen in ipairs(pg:GetChildren()) do
		if screen:IsA("ScreenGui") or screen:IsA("BillboardGui") or screen:IsA("LayerCollector") then
			if textHasWord(screen.Name, FLASH_WORDS) then
				screen.Enabled = false
			end
			-- only direct children + one nested level (cheap, covers most flash UIs)
			for _, child in ipairs(screen:GetChildren()) do
				maybeFlashGui(child)
				if child:IsA("Frame") or child:IsA("CanvasGroup") then
					for _, nested in ipairs(child:GetChildren()) do
						if nested:IsA("GuiObject") then
							if textHasWord(nested.Name, FLASH_WORDS) or (vp and nested.AbsoluteSize.X >= vp.X * 0.7) then
								maybeFlashGui(nested)
							end
						end
					end
				end
			end
		end
	end
end

local function hookFlashFx(fx)
	if not fx or fx == miscSkyCC or flashFxHooked[fx] then return end
	if not (fx:IsA("BloomEffect") or fx:IsA("ColorCorrectionEffect") or fx:IsA("BlurEffect")
		or fx:IsA("DepthOfFieldEffect") or fx:IsA("SunRaysEffect")) then
		return
	end
	flashFxHooked[fx] = true

	local function watchNumber(prop, maxKeep, setTo)
		antiFlashFxConns[#antiFlashFxConns + 1] = fx:GetPropertyChangedSignal(prop):Connect(function()
			if not Settings.AntiFlash or fx == miscSkyCC or not fx.Parent then return end
			if fx[prop] > maxKeep then
				fx[prop] = setTo
			end
		end)
	end

	local function watchDisable()
		antiFlashFxConns[#antiFlashFxConns + 1] = fx:GetPropertyChangedSignal("Enabled"):Connect(function()
			if Settings.AntiFlash and fx.Parent and fx.Enabled then
				fx.Enabled = false
			end
		end)
	end

	if fx:IsA("BloomEffect") then
		fx.Enabled = false
		fx.Intensity = 0
		fx.Size = 0
		watchDisable()
		watchNumber("Intensity", 0, 0)
	elseif fx:IsA("ColorCorrectionEffect") then
		if fx.Brightness > 0 then fx.Brightness = 0 end
		if fx.Contrast > 0.35 then fx.Contrast = 0 end
		watchNumber("Brightness", 0.02, 0)
		watchNumber("Contrast", 0.35, 0)
	elseif fx:IsA("BlurEffect") then
		if fx.Size > 0 then fx.Size = 0 end
		watchNumber("Size", 1, 0)
	elseif fx:IsA("DepthOfFieldEffect") then
		fx.Enabled = false
		watchDisable()
	elseif fx:IsA("SunRaysEffect") then
		if fx.Intensity > 0.05 then fx.Intensity = 0.05 end
		watchNumber("Intensity", 0.05, 0.05)
	end
end

local function clampLightingFlash()
	pcall(function()
		if Lighting.Brightness > 1.2 then
			Lighting.Brightness = 1.2
		end
		if Lighting.ExposureCompensation > 0.2 then
			Lighting.ExposureCompensation = 0.2
		end
	end)
	for _, fx in ipairs(Lighting:GetChildren()) do
		if fx:IsA("BloomEffect") then
			fx.Enabled = false
			fx.Intensity = 0
		elseif fx:IsA("ColorCorrectionEffect") and fx ~= miscSkyCC then
			if fx.Brightness > 0.02 then fx.Brightness = 0 end
			if fx.Contrast > 0.35 then fx.Contrast = 0 end
		elseif fx:IsA("BlurEffect") and fx.Size > 1 then
			fx.Size = 0
		elseif fx:IsA("DepthOfFieldEffect") then
			fx.Enabled = false
		elseif fx:IsA("SunRaysEffect") and fx.Intensity > 0.05 then
			fx.Intensity = 0.05
		end
		hookFlashFx(fx)
	end
end

local function setAntiFlash(on)
	clearAntiFlashHooks()
	if not on then return end

	clampLightingFlash()

	antiFlashBrightConn = Lighting:GetPropertyChangedSignal("Brightness"):Connect(function()
		if Settings.AntiFlash and Lighting.Brightness > 1.2 then
			Lighting.Brightness = 1.2
		end
	end)

	pcall(function()
		antiFlashExposureConn = Lighting:GetPropertyChangedSignal("ExposureCompensation"):Connect(function()
			if Settings.AntiFlash and Lighting.ExposureCompensation > 0.2 then
				Lighting.ExposureCompensation = 0.2
			end
		end)
	end)

	antiFlashConn = Lighting.ChildAdded:Connect(function(fx)
		if Settings.AntiFlash then
			hookFlashFx(fx)
		end
	end)

	local pg = LocalPlayer:FindFirstChild("PlayerGui") or LocalPlayer:WaitForChild("PlayerGui", 2)
	if pg then
		antiFlashGuiConn = pg.DescendantAdded:Connect(function(gui)
			if not Settings.AntiFlash or not alive then return end
			if not gui:IsA("Frame") and not gui:IsA("ImageLabel") and not gui:IsA("CanvasGroup") then
				return
			end
			-- Name hit is instant; size check deferred (avoids layout thrash)
			if textHasWord(gui.Name, FLASH_WORDS) then
				neutralizeFlashGui(gui)
			else
				task.defer(function()
					if Settings.AntiFlash and isFullscreenFlash(gui) then
						neutralizeFlashGui(gui)
					end
				end)
			end
		end)
	end

	antiFlashLoop = task.spawn(function()
		while Settings.AntiFlash and alive do
			clampLightingFlash()
			scanFlashGuisLight()
			task.wait(0.35)
		end
	end)
end

local function applyAntiFlash()
	if Settings.AntiFlash then
		clampLightingFlash()
		scanFlashGuisLight()
	end
end

local function applyEnvColor()
	if Settings.CustomEnv then
		local c = Settings.EnvColor
		Lighting.Ambient = c
		Lighting.OutdoorAmbient = c
		Lighting.ColorShift_Top = c
		Lighting.ColorShift_Bottom = c
		Lighting.FogColor = c
	else
		Lighting.Ambient = LightingBackup.Ambient
		Lighting.OutdoorAmbient = LightingBackup.OutdoorAmbient
		Lighting.ColorShift_Top = LightingBackup.ColorShift_Top
		Lighting.ColorShift_Bottom = LightingBackup.ColorShift_Bottom
		Lighting.FogColor = LightingBackup.FogColor
	end
end

local function applySkyColor()
	if Settings.CustomSky then
		if not miscAtm or not miscAtm.Parent then
			miscAtm = Lighting:FindFirstChildOfClass("Atmosphere")
			if not miscAtm then
				miscAtm = Instance.new("Atmosphere")
				miscAtm.Name = rndName("a")
				miscAtm.Parent = Lighting
			end
		end
		local c = Settings.SkyColor
		miscAtm.Color = c
		miscAtm.Decay = Color3.new(
			math.clamp(c.R * 0.55, 0, 1),
			math.clamp(c.G * 0.55, 0, 1),
			math.clamp(c.B * 0.55, 0, 1)
		)
		miscAtm.Density = 0.35
		miscAtm.Haze = 1.4
		miscAtm.Glare = 0.1

		if not miscSkyCC or not miscSkyCC.Parent then
			miscSkyCC = Instance.new("ColorCorrectionEffect")
			miscSkyCC.Name = rndName("cc")
			miscSkyCC.Parent = Lighting
		end
		miscSkyCC.Enabled = true
		miscSkyCC.TintColor = Color3.new(
			0.55 + c.R * 0.45,
			0.55 + c.G * 0.45,
			0.55 + c.B * 0.45
		)
		miscSkyCC.Brightness = 0
		miscSkyCC.Contrast = 0.05
		miscSkyCC.Saturation = 0.1
	else
		if miscSkyCC then
			pcall(function() miscSkyCC:Destroy() end)
			miscSkyCC = nil
		end
		if miscAtm and miscAtm.Parent then
			pcall(function()
				miscAtm.Density = 0
				miscAtm.Haze = 0
			end)
		end
	end
end

pcall(function()
	RunService:UnbindFromRenderStep(BIND_NAME)
end)

-- Heartbeat is cheaper than Camera-priority RenderStep for overlays
trackConn(RunService.Heartbeat:Connect(function()
	if not alive then return end
	frameId += 1
	camCache = workspace.CurrentCamera
	if not camCache then return end

	if not Settings.Enabled then
		if frameId % 10 == 0 then
			for _, entry in pairs(tracked) do
				hideDrawings(entry)
			end
		end
		return
	end

	if playerListDirty then
		rebuildPlayerList()
	end

	-- Catch late joiners if PlayerAdded was missed
	if frameId % 90 == 0 then
		for _, player in ipairs(Players:GetPlayers()) do
			if player ~= LocalPlayer and not tracked[player] then
				hookPlayer(player)
			end
		end
		if playerListDirty then
			rebuildPlayerList()
		end
	end

	local n = #playerList
	if n == 0 then return end

	-- Stagger: process ~half the roster each frame when crowded
	local step = (n > 12) and 2 or 1
	local start = ((frameId - 1) % step) + 1
	for i = start, n, step do
		local player = playerList[i]
		local entry = tracked[player]
		if entry then
			updatePlayer(player, entry)
		end
	end
end))

----------------------------------------------------------------
-- Menu (DEDE HUB)
----------------------------------------------------------------
local Theme = {
	Bg = Color3.fromRGB(18, 18, 20),
	Sidebar = Color3.fromRGB(22, 22, 24),
	Card = Color3.fromRGB(28, 28, 32),
	NavIdle = Color3.fromRGB(22, 22, 24),
	NavActive = Color3.fromRGB(40, 40, 44),
	Text = Color3.fromRGB(245, 245, 247),
	Muted = Color3.fromRGB(150, 150, 160),
	Section = Color3.fromRGB(120, 120, 130),
	Accent = Settings.MenuAccent,
	ToggleOff = Color3.fromRGB(55, 55, 62),
	Stroke = Color3.fromRGB(45, 45, 52),
}

local themeRefreshers = {}

local gui = Instance.new("ScreenGui")
gui.Name = GUI_NAME
gui.ResetOnSpawn = false
gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
gui.IgnoreGuiInset = true
gui.DisplayOrder = math.random(40, 90)
gui:SetAttribute("_sid", true)
protect(gui)
gui.Parent = uiParent

local window = Instance.new("Frame")
window.Name = rndName("w")
window.AnchorPoint = Vector2.new(0.5, 0.5)
window.Position = UDim2.fromScale(0.5, 0.5)
window.Size = UDim2.fromOffset(720, 420)
window.BackgroundColor3 = Theme.Bg
window.BackgroundTransparency = 0.06
window.BorderSizePixel = 0
window.Parent = gui

local windowCorner = Instance.new("UICorner")
windowCorner.CornerRadius = UDim.new(0, 14)
windowCorner.Parent = window

local windowStroke = Instance.new("UIStroke")
windowStroke.Color = Theme.Stroke
windowStroke.Thickness = 1
windowStroke.Transparency = 0.25
windowStroke.Parent = window

local accentBar = Instance.new("Frame")
accentBar.Name = rndName("ab")
accentBar.BorderSizePixel = 0
accentBar.BackgroundColor3 = Theme.Accent
accentBar.Size = UDim2.new(1, 0, 0, 3)
accentBar.Position = UDim2.fromOffset(0, 0)
accentBar.ZIndex = 25
accentBar.Parent = window

local accentBarCorner = Instance.new("UICorner")
accentBarCorner.CornerRadius = UDim.new(0, 14)
accentBarCorner.Parent = accentBar

-- Soft shadow
local shadow = Instance.new("ImageLabel")
shadow.Name = rndName("sh")
shadow.BackgroundTransparency = 1
shadow.Image = "rbxassetid://5028857084"
shadow.ImageColor3 = Color3.new(0, 0, 0)
shadow.ImageTransparency = 0.45
shadow.ScaleType = Enum.ScaleType.Slice
shadow.SliceCenter = Rect.new(24, 24, 276, 276)
shadow.Size = UDim2.new(1, 36, 1, 36)
shadow.Position = UDim2.fromOffset(-18, -14)
shadow.ZIndex = 0
shadow.Parent = window

-- Drag handle (top bar across window)
local dragBar = Instance.new("TextButton")
dragBar.Name = rndName("dg")
dragBar.BackgroundTransparency = 1
dragBar.Size = UDim2.new(1, 0, 0, 36)
dragBar.Position = UDim2.fromOffset(0, 0)
dragBar.Text = ""
dragBar.ZIndex = 20
dragBar.Parent = window

do
	local dragging = false
	local dragStart, startPos

	dragBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1
			or input.UserInputType == Enum.UserInputType.Touch then
			dragging = true
			dragStart = input.Position
			startPos = window.Position
		end
	end)

	trackConn(UserInputService.InputChanged:Connect(function(input)
		if not dragging then return end
		if input.UserInputType == Enum.UserInputType.MouseMovement
			or input.UserInputType == Enum.UserInputType.Touch then
			local delta = input.Position - dragStart
			window.Position = UDim2.new(
				startPos.X.Scale, startPos.X.Offset + delta.X,
				startPos.Y.Scale, startPos.Y.Offset + delta.Y
			)
		end
	end))

	trackConn(UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1
			or input.UserInputType == Enum.UserInputType.Touch then
			dragging = false
		end
	end))
end

-- Sidebar
local sidebar = Instance.new("Frame")
sidebar.Name = rndName("sb")
sidebar.Size = UDim2.new(0, 168, 1, 0)
sidebar.BackgroundColor3 = Theme.Sidebar
sidebar.BackgroundTransparency = 0.15
sidebar.BorderSizePixel = 0
sidebar.ZIndex = 2
sidebar.Parent = window

local sidebarCorner = Instance.new("UICorner")
sidebarCorner.CornerRadius = UDim.new(0, 14)
sidebarCorner.Parent = sidebar

local sidebarClip = Instance.new("Frame")
sidebarClip.BackgroundColor3 = Theme.Sidebar
sidebarClip.BackgroundTransparency = 0.15
sidebarClip.BorderSizePixel = 0
sidebarClip.Position = UDim2.new(1, -14, 0, 0)
sidebarClip.Size = UDim2.new(0, 14, 1, 0)
sidebarClip.ZIndex = 2
sidebarClip.Parent = sidebar

local brand = Instance.new("TextLabel")
brand.BackgroundTransparency = 1
brand.Position = UDim2.fromOffset(18, 18)
brand.Size = UDim2.new(1, -28, 0, 24)
brand.Font = Enum.Font.GothamBold
brand.TextSize = 16
brand.TextXAlignment = Enum.TextXAlignment.Left
brand.TextColor3 = Theme.Text
brand.ZIndex = 3
brand.Parent = sidebar
bindLocale(brand, "hub_name")

local navList = Instance.new("Frame")
navList.BackgroundTransparency = 1
navList.Position = UDim2.fromOffset(10, 56)
navList.Size = UDim2.new(1, -20, 1, -110)
navList.ZIndex = 3
navList.Parent = sidebar

local navLayout = Instance.new("UIListLayout")
navLayout.Padding = UDim.new(0, 4)
navLayout.SortOrder = Enum.SortOrder.LayoutOrder
navLayout.Parent = navList

local pages = {}
local navButtons = {}
local currentPage = "Vision"

local function setPage(name)
	currentPage = name
	for id, page in pairs(pages) do
		page.Visible = (id == name)
	end
	for id, btn in pairs(navButtons) do
		local active = id == name
		btn.BackgroundColor3 = active and Theme.NavActive or Theme.NavIdle
		btn.BackgroundTransparency = active and 0 or 1
		btn.TextColor3 = active and Theme.Text or Theme.Muted
	end
end

local function makeNav(id, labelKey, order, icon)
	local btn = Instance.new("TextButton")
	btn.Name = rndName("n")
	btn.LayoutOrder = order
	btn.Size = UDim2.new(1, 0, 0, 34)
	btn.BackgroundColor3 = Theme.NavIdle
	btn.BackgroundTransparency = 1
	btn.AutoButtonColor = false
	btn.Font = Enum.Font.Gotham
	btn.TextSize = 13
	btn.TextXAlignment = Enum.TextXAlignment.Left
	btn.TextColor3 = Theme.Muted
	btn.ZIndex = 4
	btn.Parent = navList
	bindLocale(btn, labelKey, { icon = icon })

	local c = Instance.new("UICorner")
	c.CornerRadius = UDim.new(0, 8)
	c.Parent = btn

	btn.MouseButton1Click:Connect(function()
		setPage(id)
	end)

	navButtons[id] = btn
	return btn
end

makeNav("Vision", "nav_vision", 1, "◇")
makeNav("Entities", "nav_entities", 2, "◎")
makeNav("Misc", "nav_misc", 3, "✦")

local settingsNav = Instance.new("TextButton")
settingsNav.Name = rndName("n")
settingsNav.AutoButtonColor = false
settingsNav.BackgroundColor3 = Theme.NavIdle
settingsNav.BackgroundTransparency = 1
settingsNav.Position = UDim2.new(0, 10, 1, -42)
settingsNav.Size = UDim2.new(1, -20, 0, 34)
settingsNav.Font = Enum.Font.Gotham
settingsNav.TextSize = 13
settingsNav.TextXAlignment = Enum.TextXAlignment.Left
settingsNav.TextColor3 = Theme.Muted
settingsNav.ZIndex = 4
settingsNav.Parent = sidebar
bindLocale(settingsNav, "nav_settings", { icon = "⚙" })

local settingsNavCorner = Instance.new("UICorner")
settingsNavCorner.CornerRadius = UDim.new(0, 8)
settingsNavCorner.Parent = settingsNav

settingsNav.MouseButton1Click:Connect(function()
	setPage("Settings")
end)
navButtons["Settings"] = settingsNav

-- Content
local content = Instance.new("Frame")
content.Name = rndName("ct")
content.BackgroundTransparency = 1
content.Position = UDim2.fromOffset(168, 36)
content.Size = UDim2.new(1, -180, 1, -48)
content.ZIndex = 2
content.Parent = window

local function makePage(id)
	local page = Instance.new("ScrollingFrame")
	page.Name = rndName("p")
	page.BackgroundTransparency = 1
	page.BorderSizePixel = 0
	page.Size = UDim2.fromScale(1, 1)
	page.CanvasSize = UDim2.fromOffset(0, 0)
	page.AutomaticCanvasSize = Enum.AutomaticSize.Y
	page.ScrollBarThickness = 3
	page.ScrollBarImageColor3 = Theme.Muted
	page.Visible = false
	page.ZIndex = 3
	page.Parent = content

	local pad = Instance.new("UIPadding")
	pad.PaddingLeft = UDim.new(0, 8)
	pad.PaddingRight = UDim.new(0, 8)
	pad.PaddingTop = UDim.new(0, 4)
	pad.PaddingBottom = UDim.new(0, 12)
	pad.Parent = page

	local layout = Instance.new("UIListLayout")
	layout.Padding = UDim.new(0, 18)
	layout.SortOrder = Enum.SortOrder.LayoutOrder
	layout.Parent = page

	pages[id] = page
	return page
end

local function sectionHeader(parent, titleKey, subKey, order)
	local wrap = Instance.new("Frame")
	wrap.BackgroundTransparency = 1
	wrap.Size = UDim2.new(1, 0, 0, subKey and 36 or 20)
	wrap.LayoutOrder = order
	wrap.ZIndex = 4
	wrap.Parent = parent

	local h = Instance.new("TextLabel")
	h.BackgroundTransparency = 1
	h.Size = UDim2.new(1, 0, 0, 16)
	h.Font = Enum.Font.GothamBold
	h.TextSize = 11
	h.TextXAlignment = Enum.TextXAlignment.Left
	h.TextColor3 = Theme.Section
	h.ZIndex = 5
	h.Parent = wrap
	bindLocale(h, titleKey, { upper = true })

	if subKey then
		local s = Instance.new("TextLabel")
		s.BackgroundTransparency = 1
		s.Position = UDim2.fromOffset(0, 16)
		s.Size = UDim2.new(1, 0, 0, 16)
		s.Font = Enum.Font.Gotham
		s.TextSize = 11
		s.TextXAlignment = Enum.TextXAlignment.Left
		s.TextColor3 = Theme.Muted
		s.ZIndex = 5
		s.Parent = wrap
		bindLocale(s, subKey)
	end

	return wrap
end

local function makeToggleRow(parent, labelKey, key, descKey, order, onChange)
	local row = Instance.new("TextButton")
	row.Name = rndName("tg")
	row.AutoButtonColor = false
	row.BackgroundTransparency = 1
	row.Size = UDim2.new(1, 0, 0, descKey and 44 or 32)
	row.LayoutOrder = order
	row.Text = ""
	row.ZIndex = 4
	row.Parent = parent

	local nameLbl = Instance.new("TextLabel")
	nameLbl.BackgroundTransparency = 1
	nameLbl.Size = UDim2.new(1, -64, 0, 18)
	nameLbl.Position = UDim2.fromOffset(0, descKey and 2 or 7)
	nameLbl.Font = Enum.Font.Gotham
	nameLbl.TextSize = 13
	nameLbl.TextXAlignment = Enum.TextXAlignment.Left
	nameLbl.TextColor3 = Theme.Text
	nameLbl.ZIndex = 5
	nameLbl.Parent = row
	bindLocale(nameLbl, labelKey)

	if descKey then
		local d = Instance.new("TextLabel")
		d.BackgroundTransparency = 1
		d.Position = UDim2.fromOffset(0, 22)
		d.Size = UDim2.new(1, -64, 0, 16)
		d.Font = Enum.Font.Gotham
		d.TextSize = 11
		d.TextXAlignment = Enum.TextXAlignment.Left
		d.TextColor3 = Theme.Muted
		d.ZIndex = 5
		d.Parent = row
		bindLocale(d, descKey)
	end

	local track = Instance.new("Frame")
	track.AnchorPoint = Vector2.new(1, 0.5)
	track.Position = UDim2.new(1, -2, 0.5, 0)
	track.Size = UDim2.fromOffset(42, 24)
	track.BackgroundColor3 = Theme.ToggleOff
	track.BorderSizePixel = 0
	track.ZIndex = 5
	track.Parent = row

	local trackCorner = Instance.new("UICorner")
	trackCorner.CornerRadius = UDim.new(1, 0)
	trackCorner.Parent = track

	local knob = Instance.new("Frame")
	knob.Size = UDim2.fromOffset(18, 18)
	knob.Position = UDim2.fromOffset(3, 3)
	knob.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
	knob.BorderSizePixel = 0
	knob.ZIndex = 6
	knob.Parent = track

	local knobCorner = Instance.new("UICorner")
	knobCorner.CornerRadius = UDim.new(1, 0)
	knobCorner.Parent = knob

	local function refresh()
		local on = Settings[key] == true
		track.BackgroundColor3 = on and Theme.Accent or Theme.ToggleOff
		knob.Position = on and UDim2.fromOffset(21, 3) or UDim2.fromOffset(3, 3)
	end

	row.MouseButton1Click:Connect(function()
		Settings[key] = not Settings[key]
		refresh()
		if onChange then
			onChange(Settings[key])
		end
	end)

	themeRefreshers[#themeRefreshers + 1] = refresh
	refresh()
	return row
end

local function applyMenuTheme(accent)
	Settings.MenuAccent = accent
	Theme.Accent = accent
	Theme.Stroke = Color3.new(
		math.clamp(accent.R * 0.25 + 0.14, 0, 1),
		math.clamp(accent.G * 0.25 + 0.14, 0, 1),
		math.clamp(accent.B * 0.25 + 0.16, 0, 1)
	)
	Theme.NavActive = Color3.new(
		math.clamp(accent.R * 0.18 + 0.12, 0, 1),
		math.clamp(accent.G * 0.18 + 0.12, 0, 1),
		math.clamp(accent.B * 0.18 + 0.14, 0, 1)
	)

	if accentBar then
		accentBar.BackgroundColor3 = accent
	end
	if windowStroke then
		windowStroke.Color = Theme.Stroke
	end

	-- Refresh active nav highlight + toggles
	if currentPage and setPage then
		setPage(currentPage)
	end
	for i = 1, #themeRefreshers do
		pcall(themeRefreshers[i])
	end
end

local function makeColorRow(parent, titleKey, getColor, setColor, order)
	local wrap = Instance.new("Frame")
	wrap.BackgroundTransparency = 1
	wrap.Size = UDim2.new(1, 0, 0, 56)
	wrap.LayoutOrder = order
	wrap.ZIndex = 4
	wrap.Parent = parent

	local label = Instance.new("TextLabel")
	label.BackgroundTransparency = 1
	label.Size = UDim2.new(1, -40, 0, 18)
	label.Font = Enum.Font.Gotham
	label.TextSize = 13
	label.TextXAlignment = Enum.TextXAlignment.Left
	label.TextColor3 = Theme.Text
	label.ZIndex = 5
	label.Parent = wrap
	bindLocale(label, titleKey)

	local preview = Instance.new("Frame")
	preview.AnchorPoint = Vector2.new(1, 0)
	preview.Position = UDim2.new(1, 0, 0, 0)
	preview.Size = UDim2.fromOffset(22, 22)
	preview.BackgroundColor3 = getColor()
	preview.BorderSizePixel = 0
	preview.ZIndex = 5
	preview.Parent = wrap
	local pc = Instance.new("UICorner")
	pc.CornerRadius = UDim.new(0, 6)
	pc.Parent = preview

	local row = Instance.new("Frame")
	row.BackgroundTransparency = 1
	row.Position = UDim2.fromOffset(0, 28)
	row.Size = UDim2.new(1, 0, 0, 24)
	row.ZIndex = 5
	row.Parent = wrap

	local list = Instance.new("UIListLayout")
	list.FillDirection = Enum.FillDirection.Horizontal
	list.Padding = UDim.new(0, 6)
	list.Parent = row

	for i = 1, #COLOR_PRESETS do
		local preset = COLOR_PRESETS[i]
		local sw = Instance.new("TextButton")
		sw.AutoButtonColor = false
		sw.Text = ""
		sw.Size = UDim2.fromOffset(22, 22)
		sw.BackgroundColor3 = preset.color
		sw.BorderSizePixel = 0
		sw.ZIndex = 6
		sw.Parent = row
		local sc = Instance.new("UICorner")
		sc.CornerRadius = UDim.new(0, 6)
		sc.Parent = sw
		local ss = Instance.new("UIStroke")
		ss.Thickness = 1
		ss.Color = Color3.fromRGB(255, 255, 255)
		ss.Transparency = 0.7
		ss.Parent = sw
		sw.MouseButton1Click:Connect(function()
			setColor(preset.color)
			preview.BackgroundColor3 = preset.color
		end)
	end

	return wrap
end

local function twoColumn(parent, order)
	local wrap = Instance.new("Frame")
	wrap.BackgroundTransparency = 1
	wrap.Size = UDim2.new(1, 0, 0, 0)
	wrap.AutomaticSize = Enum.AutomaticSize.Y
	wrap.LayoutOrder = order
	wrap.ZIndex = 4
	wrap.Parent = parent

	local left = Instance.new("Frame")
	left.BackgroundTransparency = 1
	left.Size = UDim2.new(0.5, -10, 0, 0)
	left.AutomaticSize = Enum.AutomaticSize.Y
	left.ZIndex = 5
	left.Parent = wrap

	local leftLayout = Instance.new("UIListLayout")
	leftLayout.Padding = UDim.new(0, 6)
	leftLayout.Parent = left

	local right = Instance.new("Frame")
	right.BackgroundTransparency = 1
	right.Position = UDim2.new(0.5, 10, 0, 0)
	right.Size = UDim2.new(0.5, -10, 0, 0)
	right.AutomaticSize = Enum.AutomaticSize.Y
	right.ZIndex = 5
	right.Parent = wrap

	local rightLayout = Instance.new("UIListLayout")
	rightLayout.Padding = UDim.new(0, 6)
	rightLayout.Parent = right

	local function syncHeight()
		wrap.Size = UDim2.new(1, 0, 0, math.max(left.AbsoluteSize.Y, right.AbsoluteSize.Y))
	end
	left:GetPropertyChangedSignal("AbsoluteSize"):Connect(syncHeight)
	right:GetPropertyChangedSignal("AbsoluteSize"):Connect(syncHeight)

	return left, right
end

-- Vision page
local visionPage = makePage("Vision")
sectionHeader(visionPage, "sec_esp", "sec_esp_sub", 1)
local vLeft, vRight = twoColumn(visionPage, 2)
makeToggleRow(vLeft, "tog_skeleton", "Skeleton", "tog_skeleton_desc", 1)
makeToggleRow(vLeft, "tog_box", "Box", "tog_box_desc", 2)
makeToggleRow(vLeft, "tog_health", "Health", "tog_health_desc", 3)
makeToggleRow(vRight, "tog_name", "Name", "tog_name_desc", 1)
makeToggleRow(vRight, "tog_glow", "Glow", "tog_glow_desc", 2)

sectionHeader(visionPage, "sec_filters", nil, 3)
local fLeft = Instance.new("Frame")
fLeft.BackgroundTransparency = 1
fLeft.Size = UDim2.new(0.5, -10, 0, 0)
fLeft.AutomaticSize = Enum.AutomaticSize.Y
fLeft.LayoutOrder = 4
fLeft.Parent = visionPage
local fLayout = Instance.new("UIListLayout")
fLayout.Padding = UDim.new(0, 6)
fLayout.Parent = fLeft
makeToggleRow(fLeft, "tog_teammates", "ShowTeammates", "tog_teammates_desc", 1)
makeToggleRow(fLeft, "tog_master", "Enabled", "tog_master_desc", 2)

-- Entities page
local entitiesPage = makePage("Entities")
sectionHeader(entitiesPage, "sec_players", "sec_players_sub", 1)
local eLeft, eRight = twoColumn(entitiesPage, 2)
makeToggleRow(eLeft, "tog_teammates", "ShowTeammates", "tog_teammates_ent_desc", 1)
makeToggleRow(eRight, "tog_master", "Enabled", "tog_master_ent_desc", 1)

-- Misc page
local miscPage = makePage("Misc")
sectionHeader(miscPage, "sec_protection", "sec_protection_sub", 1)
local mLeft, mRight = twoColumn(miscPage, 2)
makeToggleRow(mLeft, "tog_antiflash", "AntiFlash", "tog_antiflash_desc", 1, function(on)
	setAntiFlash(on)
end)
makeToggleRow(mRight, "tog_smoke", "RemoveSmoke", "tog_smoke_desc", 1, function(on)
	setRemoveSmoke(on)
end)

sectionHeader(miscPage, "sec_world", "sec_world_sub", 3)
local wLeft, wRight = twoColumn(miscPage, 4)
makeToggleRow(wLeft, "tog_env", "CustomEnv", "tog_env_desc", 1, function()
	applyEnvColor()
end)
makeToggleRow(wRight, "tog_sky", "CustomSky", "tog_sky_desc", 1, function()
	applySkyColor()
end)

makeColorRow(miscPage, "color_env", function()
	return Settings.EnvColor
end, function(c)
	Settings.EnvColor = c
	if Settings.CustomEnv then applyEnvColor() end
end, 5)

makeColorRow(miscPage, "color_sky", function()
	return Settings.SkyColor
end, function(c)
	Settings.SkyColor = c
	if Settings.CustomSky then applySkyColor() end
end, 6)

sectionHeader(miscPage, "sec_esp_colors", "sec_esp_colors_sub", 7)
makeColorRow(miscPage, "color_enemy", function()
	return Settings.EnemyColor
end, function(c)
	Settings.EnemyColor = c
end, 8)

makeColorRow(miscPage, "color_team", function()
	return Settings.TeamColor
end, function(c)
	Settings.TeamColor = c
end, 9)

-- Settings page
local settingsPage = makePage("Settings")
sectionHeader(settingsPage, "sec_interface", "sec_interface_sub", 1)
local tip = Instance.new("TextLabel")
tip.BackgroundTransparency = 1
tip.Size = UDim2.new(1, 0, 0, 60)
tip.LayoutOrder = 2
tip.Font = Enum.Font.Gotham
tip.TextSize = 13
tip.TextXAlignment = Enum.TextXAlignment.Left
tip.TextYAlignment = Enum.TextYAlignment.Top
tip.TextColor3 = Theme.Muted
tip.TextWrapped = true
tip.ZIndex = 5
tip.Parent = settingsPage
bindLocale(tip, "tip_controls")

sectionHeader(settingsPage, "sec_appearance", "sec_appearance_sub", 3)
makeColorRow(settingsPage, "color_menu", function()
	return Settings.MenuAccent
end, function(c)
	applyMenuTheme(c)
end, 4)

sectionHeader(settingsPage, "sec_language", "sec_language_sub", 5)
local langRow = Instance.new("Frame")
langRow.BackgroundTransparency = 1
langRow.Size = UDim2.new(1, 0, 0, 34)
langRow.LayoutOrder = 6
langRow.ZIndex = 4
langRow.Parent = settingsPage

local langLayout = Instance.new("UIListLayout")
langLayout.FillDirection = Enum.FillDirection.Horizontal
langLayout.Padding = UDim.new(0, 8)
langLayout.Parent = langRow

local langButtons = {}
local function refreshLangButtons()
	for code, btn in pairs(langButtons) do
		local on = code == currentLanguage
		btn.BackgroundColor3 = on and Theme.Accent or Color3.fromRGB(32, 32, 38)
		btn.TextColor3 = on and Color3.fromRGB(255, 255, 255) or Theme.Muted
	end
end

for i = 1, #LANGUAGE_OPTIONS do
	local opt = LANGUAGE_OPTIONS[i]
	local btn = Instance.new("TextButton")
	btn.AutoButtonColor = false
	btn.Size = UDim2.fromOffset(110, 32)
	btn.BackgroundColor3 = Color3.fromRGB(32, 32, 38)
	btn.BorderSizePixel = 0
	btn.Font = Enum.Font.Gotham
	btn.TextSize = 12
	btn.Text = opt.label
	btn.TextColor3 = Theme.Muted
	btn.ZIndex = 5
	btn.Parent = langRow
	local bc = Instance.new("UICorner")
	bc.CornerRadius = UDim.new(0, 8)
	bc.Parent = btn
	langButtons[opt.code] = btn
	btn.MouseButton1Click:Connect(function()
		setLanguage(opt.code)
		refreshLangButtons()
	end)
end
refreshLangButtons()
themeRefreshers[#themeRefreshers + 1] = refreshLangButtons

sectionHeader(settingsPage, "sec_session", "sec_session_sub", 7)

local destroying = false
local function destroyAll()
	if destroying then return end
	destroying = true
	alive = false

	pcall(function() RunService:UnbindFromRenderStep(BIND_NAME) end)

	Settings.Enabled = false
	Settings.CustomEnv = false
	Settings.CustomSky = false
	Settings.RemoveSmoke = false
	Settings.AntiFlash = false

	pcall(applyEnvColor)
	pcall(applySkyColor)
	pcall(function() setRemoveSmoke(false) end)
	pcall(function() setAntiFlash(false) end)

	if miscAtm then pcall(function() miscAtm:Destroy() end) miscAtm = nil end
	if miscSkyCC then pcall(function() miscSkyCC:Destroy() end) miscSkyCC = nil end

	for player in pairs(tracked) do
		pcall(removePlayer, player)
	end
	table.clear(tracked)

	for i = 1, #connections do
		pcall(function() connections[i]:Disconnect() end)
	end
	table.clear(connections)

	pcall(function()
		if gui then gui:Destroy() end
	end)
	pcall(function()
		if holder then holder:Destroy() end
	end)
end

local destroyBtn = Instance.new("TextButton")
destroyBtn.Name = rndName("x")
destroyBtn.LayoutOrder = 8
destroyBtn.Size = UDim2.new(1, 0, 0, 44)
destroyBtn.BackgroundColor3 = Color3.fromRGB(160, 45, 55)
destroyBtn.AutoButtonColor = false
destroyBtn.Font = Enum.Font.GothamBold
destroyBtn.TextSize = 14
destroyBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
destroyBtn.ZIndex = 5
destroyBtn.Parent = settingsPage
bindLocale(destroyBtn, "btn_destroy")

local destroyCorner = Instance.new("UICorner")
destroyCorner.CornerRadius = UDim.new(0, 10)
destroyCorner.Parent = destroyBtn

local destroyStroke = Instance.new("UIStroke")
destroyStroke.Color = Color3.fromRGB(220, 80, 90)
destroyStroke.Thickness = 1
destroyStroke.Transparency = 0.4
destroyStroke.Parent = destroyBtn

destroyBtn.MouseEnter:Connect(function()
	if destroying then return end
	destroyBtn.BackgroundColor3 = Color3.fromRGB(190, 55, 65)
end)
destroyBtn.MouseLeave:Connect(function()
	if destroying then return end
	destroyBtn.BackgroundColor3 = Color3.fromRGB(160, 45, 55)
end)

destroyBtn.MouseButton1Click:Connect(function()
	destroyBtn.Text = t("btn_closing")
	destroyBtn.BackgroundColor3 = Color3.fromRGB(90, 30, 35)
	task.defer(destroyAll)
end)

setPage("Vision")

local menuVisible = true
trackConn(UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed or not alive then return end
	if input.KeyCode == Enum.KeyCode.Delete then
		menuVisible = not menuVisible
		window.Visible = menuVisible
	end
end))

trackConn(holder.Destroying:Connect(function()
	destroyAll()
end))
Universal Script 🎭
undefined *OP* | Universal ESP Script 🌍 | DEDE HUB
Mobile Friendly
135 views
8 hours ago

*OP* | Universal ESP Script 🌍 | DEDE HUB

WORKING
Free

Description

[+] Draggable menu

[+] DEL to show/hide menu

[+] Language support: English / Turkish / Russian / Vietnamese

[+] Custom menu accent color

[+] Destroy (fully unload script)

[+] Master ESP toggle

[+] Bone / Skeleton ESP

[+] Box ESP (distance-scaled)

[+] Health bar

[+] Name tag

[+] Glow

[+] Show/hide teammates

[+] Enemy / teammate ESP colors

[+] Auto ESP

[+] Anti Flash

[+] Remove Smoke

[+] Environment color

[+] Sky / atmosphere color

[+] Performance-optimized ESP

[+] Stealth-oriented design

Features

  • esp
  • menu
  • show hide
  • show
  • hide
  • language
  • menu color
  • destroy
  • master esp
  • bone
  • skeleton
  • box
  • box esp
  • health
  • health bar
  • name
  • name tag
  • glow
  • show teammates
  • hide teammates
  • enemy color
  • auto esp
  • anti flash
  • remove smoke
  • smoke
  • environment color
  • sky color
  • performance optimize
  • stealth
  • design

Related Scripts