[Dev Build] Singularity

Other [Dev Build] Singularity

Нет прав для скачивания
Lua:
-- Made by @yaw_for_real (AWeirDKiD | UID: 192341)

-- SETTINGS START
local menu_accents_color = color_t(161/255, 110/255, 228/255, 1)

local manuals_distance = 65 -- Default: 65

local Wallbang_Helper_Settings = {
    line_width = 1.5, -- Default: 1.5
    normal_color = color_t(1, 1, 1, 0.4), -- Default: (1, 1, 1, 0.4)
    reverse_color_from = color_t(0, 1, 0, 0.4), -- Default: (0, 1, 0, 0.4)
    reverse_color_to = color_t(1, 0, 0, 0.4), -- Default: (1, 0, 0, 0.4)
    endpoint_radius = 20, -- Size of dot at the end of the line | Default: 20
}

-- Weapon Names: glock, hkp2000, usp_silencer, elite, p250, tec9, fiveseven, cz75a, deagle, revolver, nova, mag7, sawedoff, xm1014, m249, negev, mp5sd, p90, mp7, mac10, mp9, bizon, ump45, galilar, famas, ak47, m4a1, m4a1_silencer, ssg08, aug, sg556, awp, g3sg1, scar20, vest, vesthelm, taser, defuser, flashbang, smokegrenade, hegrenade, molotov, incgrenade, decoy

local killsay_phrases = {
    "Get good, get Singularity.lua",
    "I'd tell you to shoot yourself, but I bet you'd miss",
    "Are you always this slow? I thought it was just server lag!",
    "You should let your chair play, at least it knows how to support.",
    "Don't worry, just a few thousand more hours, and you’ll be almost like me.",
    "Guys, it’s not my fault your screens can’t react as fast as mine!",
    "The only thing lower than your k/d ratio is your I.Q.",
    "Looks like you’ve got a chance! Take a screenshot for the memories.",
    "Trying to play carefully so I don’t make you feel too bad ",
    "Did you know sharks only kill 5 people each year? Looks like you got some competition",
    "My knife is well-worn, just like your mother.",
    "Singularity.lua on top!",
    "Options -> How To Play ",
    "My dead dad has better aim than you, it only took him one bullet",
    "Some babies were dropped on their heads but you were clearly thrown at a wall",
    "Internet Explorer is faster than your reactions.",
    "Oops, sorry, I think I accidentally turned on ‘God mode’!",
    "I'm surprised you've got the brain power to keep your heart beating",
    "You're about as useful as pedals on a wheelchair. ",
    "You define autism",
    "The only thing you carry is an extra chromosome.",
    "Are you doing alright there, or should I slow down?",
    "You don't deserve to play this game. Go back to playing with crayons and shitting yourself",
    "Yo mama so fat when she plays Overpass, you can shoot her on Mirage.",
    "You’ve got a long way to go before you catch up to me.",
    "Singularity.lua is the only thing that can save you now.",
    "Sorry if I’m too fast for you it’s just my reflexes!",
    "Why you miss im not you're girlfriend",
    "The only thing you can throw are rounds.",
    "Why you miss im not your girlfriend",
    "Get good, get Singularity.lua",
    "Are you guys penguins? Moving so slow!",
    "Try to guess where I’ll pop up... or just don’t bother.",
    "I'm not trash talking, I'm talking to trash.",
    "If you were a CSGO match, your mother would have a 7day cooldown all the time, because she kept abandoning you.",
    "Someone here isn’t on my level... and it’s not me.",
    "Seems like you’re on pause the whole time, or is it just me?",
    "You do know this is a match and not just a chat lobby, right?",
    "I could beat you even without chat. Want to test that?",
    "When are you guys going to start trying? I’m waiting!",
    "Even with my eyes closed, I’d still be faster.",
    "Guess I’ll have to lower my difficulty to give you a chance.",
    "Get good, get Singularity.lua",
    "You can surrender now I won’t mind!",
    "If CS2 is too hard for you maybe consider a game that requires less skill, like idk.... solitaire?",
    "Oops, I must have chosen easy bots by accident...",
    "Don't be a loser, buy a rope and hang yourself.",
    "If I were to commit suicide, I would jump from your ego to your elo.",
    "Do you feel special? Please try suicide again... Hopefully you will be successful this time.",
    "Idk if u know but it's mouse1 to shoot.",
    "You are the reason why people say the CS2 community sucks.",
    "Get good, get Singularity.lua",
    "Sell your computer and buy a Wii.",
    "error: ur resolver is trash",
    "Studies show that aiming gives you better chances of hitting your target.",
    "There are about 37 trillion cells working together in your body right now, and you are disappointing every single one of them."
}
-- SETTINGS END
-- Do not modify anything below this line unless you know what you are doing.

local ffi = require("ffi")
local bit = require("bit")

ffi.cdef[[
    short GetAsyncKeyState(int vKey);
]]

local default_yaw_offset = menu.ragebot_anti_aim_base_yaw_offset
local default_auto_strafer = menu.ragebot_auto_strafer

-- GUI CODE BASE BY sigmacord.lua and winter.lua | Heavily Modified
local settingList = {}

local font14 = render.setup_font("C:/Windows/Fonts/verdana.ttf", 12)
local font16 = render.setup_font("C:/Windows/Fonts/verdana.ttf", 13)
local titleFont = render.setup_font("C:/Windows/Fonts/verdana.ttf", 22)

local function newSetting(type, name, value, minValue, maxValue, increment, text, callback, customFont)
    local s = {
        type = type,
        name = name, 
        value = value,
        minValue = minValue,
        maxValue = maxValue,
        increment = increment,
        text = text,
        callback = callback,
        font = customFont
    }
    table.insert(settingList, s)
    return s
end

local function newCheckbox(name, value, has_color_picker, default_color)
    local s = newSetting("checkbox", name, value)
    if has_color_picker then
        s.has_color_picker = true
        s.color_value = default_color or color_t(1, 1, 1, 1)
        s.is_color_open = false
        s.hue = 0
        s.picker_pos = vec2_t(0, 0)
        s.last_selected_color_pos = nil
        s.picker_alpha = 0
    end
    return s
end
local function newSlider(name, value, minValue, maxValue, increment)
    return newSetting("slider", name, value, minValue, maxValue, increment)
end
local function newText(text, font)
    return newSetting("text", nil, nil, nil, nil, nil, text, nil, font)
end
local function newKeybind(name, callback, mode)
    local kb = newSetting("keybind", name, "none", nil, nil, nil, nil, callback)
    kb.mode = mode or 1
    return kb
end
local function newDropdown(name, values, default_index)
    local s = newSetting("dropdown", name, default_index or 1, 1, #values)
    s.values = values
    return s
end
local function newCombobox(name, values, default_selections)
    local selections = {}
    default_selections = default_selections or {}
    for i = 1, #values do
        selections[i] = default_selections[i] or false
    end
    local s = newSetting("combobox", name, selections, 1, #values)
    s.values = values
    return s
end

local function color_from_hsv(h, s, v, a)
    local r, g, b
    
    local i = math.floor(h * 6)
    local f = h * 6 - i
    local p = v * (1 - s)
    local q = v * (1 - f * s)
    local t = v * (1 - (1 - f) * s)
    
    i = i % 6
    
    if i == 0 then r, g, b = v, t, p
    elseif i == 1 then r, g, b = q, v, p
    elseif i == 2 then r, g, b = p, v, t
    elseif i == 3 then r, g, b = p, q, v
    elseif i == 4 then r, g, b = t, p, v
    elseif i == 5 then r, g, b = v, p, q
    end
    
    return color_t(r, g, b, a or 1)
end

local gui = {
    x = 320, y = 320,
    width = 260, height = 550,
    isOpen = true,
    isDragging = false,
    dragOffset = {x = 0, y = 0},
    waitingForKey = false,
    activeKeybind = nil,
    currentTab = "Anti-Aim",
    targetWidth = 300,
    targetHeight = 590,
    alpha = 1,
    tabAlpha = 1,
    activeDropdown = nil,
    dropdownOptions = {"Hold", "Toggle"},
    activeInputBox = nil,
    inputBuffer = "",
    isTyping = false,
    originalInputValue = ""
}

local tabSettings = {
    ["Anti-Aim"] = {},
    ["Rage"] = {},
    ["Misc"] = {}
}

local function round(exact, quantum)
    local quant = math.floor(exact/quantum)
    return quantum * (quant + (exact/quantum - quant > 0.5 and 1 or 0))
end

ffi.cdef[[
    typedef struct {
        long x;
        long y;
    } POINT;
    int GetCursorPos(POINT* lpPoint);
    int ScreenToClient(void* hWnd, POINT* lpPoint);
    short GetAsyncKeyState(int vKey);
    void* GetForegroundWindow();
    unsigned long GetTickCount();
    static const int VK_INSERT = 0x2D;
    static const int VK_LBUTTON = 0x01;
    static const int VK_UP = 0x26;
    static const int VK_DOWN = 0x28;
    static const int VK_PRIOR = 0x21;
    static const int VK_NEXT = 0x22;
    typedef struct Vector {
        float x, y, z;
    } Vector;
    unsigned short GetKeyState(int nVirtKey);

    unsigned long GetWindowThreadProcessId(void* hWnd, unsigned long* lpdwProcessId);
    unsigned long GetCurrentProcessId();
]]

local user32 = ffi.load("user32")
-- local kernel32 = ffi.load("kernel32")
local VK = {INSERT = 0x2D, LBUTTON = 0x01, UP = 0x26, DOWN = 0x28, PRIOR = 0x21, NEXT = 0x22}
local prev = {insert = false, mouse = false}
local function get_mouse_pos()
    local point = ffi.new("POINT[1]")
    user32.GetCursorPos(point)
    user32.ScreenToClient(user32.GetForegroundWindow(), point)
    return vec2_t(point[0].x, point[0].y)
end

local function lerp(a, b, t) return a + (b - a) * t end

local function clamp(val, min, max) return math.max(min, math.min(val, max)) end

local function is_game_window_focused()
    local foreground_hwnd = user32.GetForegroundWindow()
    if foreground_hwnd == nil or foreground_hwnd == ffi.NULL then
        return false
    end
    
    local process_id = ffi.new("unsigned long[1]")
    user32.GetWindowThreadProcessId(foreground_hwnd, process_id)
    
    local current_process_id = ffi.C.GetCurrentProcessId()
    
    return process_id[0] == current_process_id
end

local function is_key_pressed(key) 
    if type(key) == "string" or key == "none" or not key then
        return false
    end
    if not is_game_window_focused() then
        return false
    end
    return bit.band(user32.GetAsyncKeyState(key), 0x8000) ~= 0 
end

local function get_key_name(vKey)
    local keyNames = {
        [0x01] = "M1", [0x02] = "M2", [0x04] = "M3", [0x05] = "M4", [0x06] = "M5",
        [0x08] = "BACKSPACE", [0x09] = "TAB", [0x0D] = "ENTER", [0x10] = "SHIFT",
        [0x11] = "CTRL", [0x12] = "ALT", [0x14] = "CAPS", [0x1B] = "ESC",
        [0x20] = "SPACE", [0x25] = "LEFT", [0x26] = "UP", [0x27] = "RIGHT",
        [0x28] = "DOWN", [0x2D] = "INS", [0x2E] = "DEL"
    }
    if keyNames[vKey] then return keyNames[vKey] end
    local char = string.char(vKey)
    if char:match("%w") then return char end
    return string.format("0x%02X", vKey)
end
local key_states = {}
local function check_keys()
    if not gui.waitingForKey then return end
    for i = 1, 255 do
        if i ~= VK.LBUTTON and i ~= VK.RBUTTON and is_key_pressed(i) then
            gui.waitingForKey = false
            if gui.activeKeybind then
                gui.activeKeybind.value = i
            end
            return
        end
    end
end

local function find_text_files()
    local scripts_path = get_game_directory() .. "\\nix\\scripts"
    local files = {}
    
    local dir = io.popen('dir "' .. scripts_path .. '" /b')
    if not dir then return {} end
    
    for file in dir:lines() do
        if file:match("%.txt$") then
            table.insert(files, file)
        end
    end
    dir:close()
    
    table.sort(files)
    
    if #files == 0 then
        table.insert(files, "No text files found")
    end
    
    return files
end

-- DEFAULT COLOR (menu_accents_color): color_t(161/255, 110/255, 228/255, 1)

-- Anti-Aim Tab
menu_anti_aim_builder_enabled = newCheckbox("Anti-Aim Builder", true)
menu_conditions_selector = {"Stand", "Run", "In-Air", "Air-Duck", "Duck", "Duck-Walk"}
menu_anti_aim_builder_conditions = newDropdown("Condition", menu_conditions_selector, 1)
menu_anti_aim_yaw_modifier_values = {"None", "Center", "Offset", "Random", "3-Way", "5-Way", "Spin"}
menu_anti_aim_pitch = newDropdown("Pitch [Global]", {"None", "Down", "Fake"}, 2)
menu_random_yaw_enabled = newCheckbox("Random Base Yaw", false)
menu_random_yaw_deviance = newSlider("Randomiser Offset", 25, 1, 180, 1)
menu_randomness_mode = newSlider("Randomiser Mode", 1, 1, 2, 1)
menu_manual_aa_enabled = newCheckbox("Manual AA", true, true, color_t(161/255, 110/255, 228/255, 1))
menu_manual_right_key = newKeybind("Manuals Right Key", function() end, 2)
menu_manual_right_key.value = 0x43
menu_manual_left_key = newKeybind("Manuals Left Key", function() end, 2)
menu_manual_left_key.value = 0x5A
menu_pitch_jitter_enabled = newCheckbox("Pitch Jitter on Manuals", true)
menu_pitch_jitter_chance = newSlider("Pitch Jitter Down %", 90, 1, 100, 1)
menu_0_pitch_on_land_enabled = newCheckbox("0 Pitch on Land", true)
menu_0_pitch_on_land_duration = newSlider("0 Pitch Duration", 3, 1, 64, 1)
menu_air_flick_enabled = newCheckbox("Air Flick", true)
menu_air_flick_trigger_rate = newSlider("Air Flick Rate (Ticks)", 32, 0, 63, 1)

-- Rage Tab
menu_default_min_dmg = newSlider("Min Damage", 100, 1, 120, 1)
menu_default_override_min_dmg_key = newKeybind("Min Damage Override Key", function() end, 2)
menu_default_override_min_dmg_key.value = 0x06
menu_default_override_min_dmg = newSlider("Min Damage Override", 10, 1, 120, 1)

menu_duck_peek_assist_enabled = newCheckbox("Duck Peek Assist", true)
menu_duck_peek_assist_key = newKeybind("Duck Peek Assist Key", function() end, 2)
menu_duck_peek_assist_key.value = 0x58

menu_ai_peek_enabled = newCheckbox("AI Peek", false)
menu_ai_peek_key = newKeybind("AI Peek Key", function() end, 1)
menu_ai_peek_key.value = 0x05
menu_ai_peek_offset = newSlider("AI Peek Offset", 55, 1, 200, 1)
menu_ai_peek_limit = newSlider("AI Peek Limit (M)", 0.5, 0.1, 2, 0.1)

menu_wallbang_helper_enabled = newCheckbox("Wallbang Helper", false)
menu_wallbang_helper_minimum_distance_to_draw = newSlider("Min Draw Distance", 500, 200, 2000, 1)
wallbang_helper_files = find_text_files()
menu_wallbang_helper_file = newDropdown("Wallbang Helper Config", wallbang_helper_files, 1)

menu_disable_ragebot_in_air_enabled = newCheckbox("Disable Ragebot in Air", false)
menu_adaptive_auto_strafer_enabled = newCheckbox("Adaptive Auto Strafer", true)
menu_buybot = newCheckbox("Buybot", true)
menu_buybot_options_gui = {"SSG08", "Auto", "AWP", "Revolver", "Deagle", "VestHelm", "Grenade", "Smoke", "Molotov", "Defuser", "Taser"}
buybot_cmd_names = {"ssg08", "scar20; buy g3sg1", "awp", "revolver", "deagle", "vest; buy vesthelm", "hegrenade", "smokegrenade", "molotov; buy incgrenade", "defuser", "taser"}
menu_buybot_selector = newCombobox("Buybot Settings", menu_buybot_options_gui, {false, false, false, false, false, false, false, false, false, false, false})

-- Misc Tab
menu_custom_menu_color_enabled = newCheckbox("Custom Menu Color", false, true, color_t(161/255, 110/255, 228/255, 1))
menu_thirdperson_distance = newSlider("Thirdperson Distance", 100, 1, 150, 1)
menu_fov_value = newSlider("FOV Changer", 90, 60, 160, 1)
menu_slowdown_indicator = newCheckbox("Slowdown Indicator", true)
menu_firstperson_on_utilities = newCheckbox("Auto Firstperson on Utilities", false)
menu_watermark_enabled = newCheckbox("Watermark", true, true, color_t(161/255, 110/255, 228/255, 1))
menu_watermark_styles = {"Basic", "Default", "Modern", "OldSchool"}
menu_watermark_style = newDropdown("Watermark Style", menu_watermark_styles, 2)
menu_custom_scope_enabled = newCheckbox("Custom Scope", true, true, color_t(161/255, 110/255, 228/255, 1))
menu_custom_scope_offset = newSlider("Custom Scope Offset", 20, 10, 100, 1)
menu_custom_scope_length = newSlider("Custom Scope Length", 80, 20, 200, 1)
menu_visuals_combobox = {"Conditions", "Manuals", "Hotkey List"}
menu_indicators = newCombobox("Indicators", menu_visuals_combobox, {true, true, true})
menu_auto_thirdperson_spectate_enabled = newCheckbox("Auto Thirdperson on Spectate", true)
menu_killsay_enabled = newCheckbox("Killsay", false) -- off by default because its annoying as hell

if menu_custom_menu_color_enabled.value then
    menu_accents_color = menu_custom_menu_color_enabled.color_value
else
    menu_accents_color = color_t(161/255, 110/255, 228/255, 1)
end

local condition_settings = {}
for i, condition in ipairs(menu_conditions_selector) do
    condition_settings[i] = {
        yaw_modifier = newDropdown(condition .. " Yaw Modifier", menu_anti_aim_yaw_modifier_values, 1),
        yaw_offset = newSlider(condition .. " Yaw Offset", 0, 0, 180, 1)
    }
end

local menu_anti_aim_yaw_modifier = nil
local menu_anti_aim_yaw_modifier_offset = nil

local function updateActiveSettings()
    local condition_idx = menu_anti_aim_builder_conditions.value
    menu_anti_aim_yaw_modifier = condition_settings[condition_idx].yaw_modifier
    menu_anti_aim_yaw_modifier_offset = condition_settings[condition_idx].yaw_offset
end

local settings_path = get_game_directory() .. "\\nix\\scripts\\singularity.settings"

local function saveSettings()
    local file = io.open(settings_path, "w")
    if file then
        for _, setting in ipairs(settingList) do
            if setting.name then
                if setting.type == "slider" then
                    file:write(setting.name .. "=" .. tostring(setting.value) .. "\n")
                elseif setting.type == "checkbox" then
                    file:write(setting.name .. "=" .. tostring(setting.value) .. "\n")
                    if setting.has_color_picker then
                        file:write(setting.name .. "_color_r=" .. tostring(setting.color_value.r) .. "\n")
                        file:write(setting.name .. "_color_g=" .. tostring(setting.color_value.g) .. "\n")
                        file:write(setting.name .. "_color_b=" .. tostring(setting.color_value.b) .. "\n")
                        file:write(setting.name .. "_color_a=" .. tostring(setting.color_value.a) .. "\n")
                    end
                elseif setting.type == "keybind" then
                    file:write(setting.name .. "=" .. tostring(setting.value) .. "\n")
                    if setting.mode then
                        file:write(setting.name .. "_mode=" .. tostring(setting.mode) .. "\n")
                    end
                elseif setting.type == "dropdown" then
                    file:write(setting.name .. "=" .. tostring(setting.value) .. "\n")
                elseif setting.type == "combobox" then
                    for i, selected in ipairs(setting.value) do
                        file:write(setting.name .. "_" .. i .. "=" .. tostring(selected) .. "\n")
                    end
                end
            end
        end
        file:close()
    end
end

local function loadSettings()
    local file = io.open(settings_path, "r")
    if file then
        for line in file:lines() do
            local name, value = line:match("([^=]+)=([^=]+)")
            for _, setting in ipairs(settingList) do
                if setting.name == name then
                    if setting.type == "slider" then
                        setting.value = tonumber(value)
                    elseif setting.type == "checkbox" then
                        setting.value = value == "true"
                    elseif setting.type == "keybind" then
                        setting.value = tonumber(value) or "none"
                    elseif setting.type == "dropdown" then
                        setting.value = tonumber(value) or 1
                    end
                end
                if setting.type == "keybind" and name == setting.name .. "_mode" then
                    setting.mode = tonumber(value) or 1
                end
                if setting.type == "combobox" then
                    local comboIndex = name:match(setting.name .. "_(%d+)")
                    if comboIndex then
                        comboIndex = tonumber(comboIndex)
                        if comboIndex and comboIndex >= 1 and comboIndex <= #setting.value then
                            setting.value[comboIndex] = value == "true"
                        end
                    end
                end
                if setting.type == "checkbox" and setting.has_color_picker then
                    if name:match(setting.name .. "_color_r$") then
                        setting.color_value.r = tonumber(value) or 1
                    elseif name:match(setting.name .. "_color_g$") then
                        setting.color_value.g = tonumber(value) or 1
                    elseif name:match(setting.name .. "_color_b$") then
                        setting.color_value.b = tonumber(value) or 1
                    elseif name:match(setting.name .. "_color_a$") then
                        setting.color_value.a = tonumber(value) or 1
                    end
                end
            end
        end
        file:close()
    end
    
    if menu_wallbang_helper_file.value > #wallbang_helper_files then
        menu_wallbang_helper_file.value = 1
        print("[Singularity] Wallbang helper file index was out of bounds, reset to 1")
    end

    updateActiveSettings()
end

local function categorizeSettings()
    for tab, _ in pairs(tabSettings) do
        tabSettings[tab] = {}
    end

    table.insert(tabSettings["Anti-Aim"], menu_anti_aim_builder_enabled)
    table.insert(tabSettings["Anti-Aim"], menu_anti_aim_builder_conditions)
    local condition_idx = menu_anti_aim_builder_conditions.value
    table.insert(tabSettings["Anti-Aim"], condition_settings[condition_idx].yaw_modifier)
    table.insert(tabSettings["Anti-Aim"], condition_settings[condition_idx].yaw_offset)
    table.insert(tabSettings["Anti-Aim"], menu_anti_aim_pitch)
    table.insert(tabSettings["Anti-Aim"], menu_random_yaw_enabled)
    table.insert(tabSettings["Anti-Aim"], menu_random_yaw_deviance)
    table.insert(tabSettings["Anti-Aim"], menu_manual_aa_enabled)
    table.insert(tabSettings["Anti-Aim"], menu_manual_right_key)
    table.insert(tabSettings["Anti-Aim"], menu_manual_left_key)
    table.insert(tabSettings["Anti-Aim"], menu_pitch_jitter_enabled)
    table.insert(tabSettings["Anti-Aim"], menu_pitch_jitter_chance)
    table.insert(tabSettings["Anti-Aim"], menu_0_pitch_on_land_enabled)
    table.insert(tabSettings["Anti-Aim"], menu_0_pitch_on_land_duration)
    table.insert(tabSettings["Anti-Aim"], menu_air_flick_enabled)
    table.insert(tabSettings["Anti-Aim"], menu_air_flick_trigger_rate)
    
    table.insert(tabSettings["Rage"], menu_default_min_dmg)
    table.insert(tabSettings["Rage"], menu_default_override_min_dmg_key)
    table.insert(tabSettings["Rage"], menu_default_override_min_dmg)

    table.insert(tabSettings["Rage"], menu_ai_peek_enabled)
    table.insert(tabSettings["Rage"], menu_ai_peek_key)
    table.insert(tabSettings["Rage"], menu_ai_peek_offset)
    table.insert(tabSettings["Rage"], menu_ai_peek_limit)

    table.insert(tabSettings["Rage"], menu_duck_peek_assist_enabled)
    table.insert(tabSettings["Rage"], menu_duck_peek_assist_key)

    table.insert(tabSettings["Rage"], menu_wallbang_helper_enabled)
    table.insert(tabSettings["Rage"], menu_wallbang_helper_minimum_distance_to_draw)
    table.insert(tabSettings["Rage"], menu_wallbang_helper_file)
    
    table.insert(tabSettings["Rage"], menu_disable_ragebot_in_air_enabled)
    table.insert(tabSettings["Rage"], menu_adaptive_auto_strafer_enabled)
    table.insert(tabSettings["Rage"], menu_buybot)
    table.insert(tabSettings["Rage"], menu_buybot_selector)
    
    table.insert(tabSettings["Misc"], menu_custom_menu_color_enabled)
    table.insert(tabSettings["Misc"], menu_thirdperson_distance)
    table.insert(tabSettings["Misc"], menu_fov_value)
    table.insert(tabSettings["Misc"], menu_slowdown_indicator)
    table.insert(tabSettings["Misc"], menu_firstperson_on_utilities)
    table.insert(tabSettings["Misc"], menu_watermark_enabled)
    table.insert(tabSettings["Misc"], menu_watermark_style)
    table.insert(tabSettings["Misc"], menu_custom_scope_enabled)
    table.insert(tabSettings["Misc"], menu_custom_scope_offset)
    table.insert(tabSettings["Misc"], menu_custom_scope_length)
    table.insert(tabSettings["Misc"], menu_indicators)
    table.insert(tabSettings["Misc"], menu_auto_thirdperson_spectate_enabled)
    table.insert(tabSettings["Misc"], menu_killsay_enabled)
end

local menu_prev_condition = 1
local function handleConditionChange()
    local menu_current_condition = menu_anti_aim_builder_conditions.value
    if menu_current_condition ~= menu_prev_condition then
        categorizeSettings()
        updateActiveSettings()
        menu_prev_condition = menu_current_condition
    end
end

register_callback("paint", function()
    handleConditionChange()
end)

local VK = {INSERT = 0x2D, LBUTTON = 0x01, RBUTTON = 0x02, UP = 0x26, DOWN = 0x28, PRIOR = 0x21, NEXT = 0x22}
local prev = {insert = false, mouse = false, right_mouse = false}

local function renderGui()
    local insert_down = is_key_pressed(VK.INSERT)
    if insert_down and not prev.insert then gui.isOpen = not gui.isOpen end
    prev.insert = insert_down
    
    gui.alpha = lerp(gui.alpha, gui.isOpen and 1 or 0, render.frame_time() * 10)
    
    if gui.alpha <= 0 then 
        engine.execute_client_cmd("bind MOUSE1 +attack") 
        engine.execute_client_cmd("bind MOUSE2 +attack2")
        return 
    end
    
    if not gui.isOpen then 
        engine.execute_client_cmd("bind MOUSE1 +attack") 
        engine.execute_client_cmd("bind MOUSE2 +attack2")
        return 
    end
    
    check_keys()
    
    gui.width = lerp(gui.width, gui.targetWidth, render.frame_time() * 10)
    gui.height = lerp(gui.height, gui.targetHeight, render.frame_time() * 10)
    
    local mouse = {
        pos = get_mouse_pos(), 
        down = is_key_pressed(VK.LBUTTON), 
        click = false,
        right_down = is_key_pressed(VK.RBUTTON),
        right_click = false
    }
    mouse.click = mouse.down and not prev.mouse
    mouse.right_click = mouse.right_down and not prev.right_mouse
    
    local isMouseOverMenu = mouse.pos.x >= gui.x and mouse.pos.x <= gui.x + gui.width and mouse.pos.y >= gui.y and mouse.pos.y <= gui.y + gui.height
    if isMouseOverMenu then engine.execute_client_cmd("unbind mouse1") else engine.execute_client_cmd("bind MOUSE1 +attack") end
    if isMouseOverMenu then 
        engine.execute_client_cmd("unbind mouse1")
        engine.execute_client_cmd("unbind mouse2")
    else 
        engine.execute_client_cmd("bind MOUSE1 +attack") 
        engine.execute_client_cmd("bind MOUSE2 +attack2") 
    end
    
    if mouse.click and isMouseOverMenu and mouse.pos.y <= gui.y + 30 then
        gui.isDragging = true
        gui.dragOffset.x = mouse.pos.x - gui.x
        gui.dragOffset.y = mouse.pos.y - gui.y
    end
    
    if not mouse.down then 
        gui.isDragging = false 
    end
    
    if gui.isDragging then
        gui.x = mouse.pos.x - gui.dragOffset.x
        gui.y = mouse.pos.y - gui.dragOffset.y
    end
    
    prev.mouse = mouse.down
    prev.right_mouse = mouse.right_down
    
    local background_color = color_t(24/255, 24/255, 24/255, gui.alpha)
    local outline_color = menu_accents_color
    
    render.rect_filled(vec2_t(gui.x, gui.y), vec2_t(gui.x + gui.width, gui.y + gui.height), background_color, 8)
    render.rect(vec2_t(gui.x, gui.y), vec2_t(gui.x + gui.width, gui.y + gui.height), outline_color, 8, 0)

    local title_text = "~ Singularity.lua ~"
    local title_size = render.calc_text_size(title_text, titleFont)
    render.text(title_text, titleFont, vec2_t(gui.x + (gui.width - title_size.x) / 2, gui.y + 10), color_t(1, 1, 1, gui.alpha))
    
    local icon_size = 20
    local icon_x = gui.x + gui.width - icon_size - 10
    local icon_y = gui.y + 10
    
    render.rect_filled(
        vec2_t(icon_x, icon_y),
        vec2_t(icon_x + icon_size, icon_y + icon_size),
        color_t(outline_color.r, outline_color.g, outline_color.b, gui.alpha),
        4
    )
    
    render.rect_filled(
        vec2_t(icon_x + 4, icon_y + 4),
        vec2_t(icon_x + icon_size - 4, icon_y + icon_size - 4),
        color_t(1, 1, 1, gui.alpha),
        2
    )
    
    render.rect_filled(
        vec2_t(icon_x + 6, icon_y + 6),
        vec2_t(icon_x + icon_size - 6, icon_y + 8),
        color_t(outline_color.r, outline_color.g, outline_color.b, gui.alpha),
        1
    )
    
    render.rect_filled(
        vec2_t(icon_x + 7, icon_y + 12),
        vec2_t(icon_x + icon_size - 7, icon_y + icon_size - 7),
        color_t(outline_color.r, outline_color.g, outline_color.b, gui.alpha * 0.7),
        1
    )
    
    if mouse.click and 
       mouse.pos.x >= icon_x and 
       mouse.pos.x <= icon_x + icon_size and
       mouse.pos.y >= icon_y and 
       mouse.pos.y <= icon_y + icon_size then
        saveSettings()
        print("[Singularity] Settings saved!")
    end

    local tabWidth = 86.6
    local tabHeight = 25
    local tabX = gui.x + 10
    local tabY = gui.y + 40
    local tabs = {"Anti-Aim", "Rage", "Misc"}
    
    for i, tab in ipairs(tabs) do
        local tab_background_color = gui.currentTab == tab and outline_color or color_t(34/255, 34/255, 34/255, gui.alpha)
        render.rect_filled(
            vec2_t(tabX + (i-1) * (tabWidth + 10), tabY), 
            vec2_t(tabX + (i-1) * (tabWidth + 10) + tabWidth, tabY + tabHeight), 
            tab_background_color, 
            4
        )
        
        render.text(
            tab, 
            font14, 
            vec2_t(tabX + (i-1) * (tabWidth + 10) + tabWidth/2 - render.calc_text_size(tab, font14).x/2, tabY + 5), 
            color_t(1, 1, 1, gui.alpha)
        )
        
        if mouse.click and 
           mouse.pos.x >= tabX + (i-1) * (tabWidth + 10) and 
           mouse.pos.x <= tabX + (i-1) * (tabWidth + 10) + tabWidth and
           mouse.pos.y >= tabY and 
           mouse.pos.y <= tabY + tabHeight then
            gui.currentTab = tab
        end
    end
    
    local activeDropdownInfo = nil
    local y = gui.y + 90
    local isOverControl = false
    local isClickBlockedByDropdown = false

    if gui.activeDropdown then
        local setting = gui.activeDropdown
        local dropX, dropY
        
        if setting.type == "dropdown" then
            dropX = gui.x + gui.width - 80
            local dropWidth = 72
            dropY = 0
            
            local tempY = gui.y + 90
            for _, s in ipairs(tabSettings[gui.currentTab]) do
                if s == setting then
                    dropY = tempY
                    break
                end
                tempY = tempY + 28
            end
            
            if mouse.click and
                mouse.pos.x >= dropX and 
                mouse.pos.x <= dropX + dropWidth and
                mouse.pos.y >= dropY + 18 and
                mouse.pos.y <= dropY + 18 + (#setting.values * 20) then
                isClickBlockedByDropdown = true
            end
        elseif setting.type == "keybind" then
            dropX = gui.x + gui.width - 60 + 20
            local dropWidth = 60
            dropY = 0
            
            local tempY = gui.y + 90
            for _, s in ipairs(tabSettings[gui.currentTab]) do
                if s == setting then
                    dropY = tempY
                    break
                end
                tempY = tempY + 28
            end
            
            if mouse.click and
                mouse.pos.x >= dropX and 
                mouse.pos.x <= dropX + dropWidth and
                mouse.pos.y >= dropY + 18 and
                mouse.pos.y <= dropY + 18 + (#gui.dropdownOptions * 20) then
                isClickBlockedByDropdown = true
            end
        end
    end

    y = gui.y + 90
    
    for _, setting in ipairs(settingList) do
        local is_open_picker = (setting.type == "checkbox" and setting.has_color_picker and setting.is_color_open)

        if is_open_picker then
            local picker_pos = setting.picker_pos
            local picker_size = vec2_t(150, 150)
            local bar_width = 20
            local bar_pos = picker_pos + vec2_t(picker_size.x + 5, 0)
            
            setting.picker_alpha = lerp(setting.picker_alpha, 1, render.frame_time() * 10)
            
            render.rect_filled(picker_pos, picker_pos + picker_size, color_t(0.1, 0.1, 0.1, setting.picker_alpha), 4)
            
            for x = 0, picker_size.x, 2 do
                for y = 0, picker_size.y, 2 do
                    local saturation = x / picker_size.x
                    local value = 1 - (y / picker_size.y)
                    local color = color_from_hsv(setting.hue, saturation, value, setting.picker_alpha)
                    render.rect_filled(picker_pos + vec2_t(x, y), picker_pos + vec2_t(x + 2, y + 2), color, 1)
                end
            end

            local alpha_slider_height = 15
            local alpha_slider_y = picker_pos.y + picker_size.y + 5
            local alpha_slider_width = picker_size.x
            
            render.rect_filled(
                vec2_t(picker_pos.x, alpha_slider_y),
                vec2_t(picker_pos.x + alpha_slider_width, alpha_slider_y + alpha_slider_height),
                color_t(0.1, 0.1, 0.1, setting.picker_alpha),
                2
            )
            
            for x = 0, alpha_slider_width, 2 do
                local alpha_value = x / alpha_slider_width
                local current_color = color_t(
                    setting.color_value.r, 
                    setting.color_value.g, 
                    setting.color_value.b, 
                    alpha_value
                )
                render.rect_filled(
                    vec2_t(picker_pos.x + x, alpha_slider_y),
                    vec2_t(picker_pos.x + x + 2, alpha_slider_y + alpha_slider_height),
                    current_color,
                    0
                )
            end
            
            local alpha_handle_pos = picker_pos.x + (setting.color_value.a * alpha_slider_width)
            render.rect_filled(
                vec2_t(alpha_handle_pos - 2, alpha_slider_y - 2),
                vec2_t(alpha_handle_pos + 2, alpha_slider_y + alpha_slider_height + 2),
                color_t(1, 1, 1, setting.picker_alpha),
                2
            )
            
            if mouse.down then
                if mouse.pos.x >= picker_pos.x and mouse.pos.x <= picker_pos.x + alpha_slider_width and
                   mouse.pos.y >= alpha_slider_y and mouse.pos.y <= alpha_slider_y + alpha_slider_height then
                    local alpha_value = (mouse.pos.x - picker_pos.x) / alpha_slider_width
                    setting.color_value.a = clamp(alpha_value, 0, 1)
                end
            end
            
            render.rect_filled(bar_pos, bar_pos + vec2_t(bar_width, picker_size.y), color_t(0.1, 0.1, 0.1, setting.picker_alpha), 4)
            for y = 0, picker_size.y, 2 do
                local hue = y / picker_size.y
                local color = color_from_hsv(hue, 1, 1, setting.picker_alpha)
                render.rect_filled(bar_pos + vec2_t(0, y), bar_pos + vec2_t(bar_width, y + 2), color, 1)
            end
            
            if mouse.down then
                if mouse.pos.x >= picker_pos.x and mouse.pos.x <= picker_pos.x + picker_size.x and
                  mouse.pos.y >= picker_pos.y and mouse.pos.y <= picker_pos.y + picker_size.y then
                    local x = mouse.pos.x - picker_pos.x
                    local y = mouse.pos.y - picker_pos.y
                    local saturation = x / picker_size.x
                    local value = 1 - (y / picker_size.y)
                    
                    local new_color = color_from_hsv(setting.hue, saturation, value, 1)
                    
                    setting.color_value.r = new_color.r
                    setting.color_value.g = new_color.g
                    setting.color_value.b = new_color.b
                    setting.color_value.a = 1
                    
                    setting.last_selected_color_pos = vec2_t(mouse.pos.x, mouse.pos.y)
                elseif mouse.pos.x >= bar_pos.x and mouse.pos.x <= bar_pos.x + bar_width and
                       mouse.pos.y >= bar_pos.y and mouse.pos.y <= bar_pos.y + picker_size.y then
                    local y = mouse.pos.y - picker_pos.y
                    setting.hue = y / picker_size.y
                end
            end
            
            if setting.last_selected_color_pos then
                local constrained_pos = vec2_t(
                    clamp(setting.last_selected_color_pos.x, picker_pos.x, picker_pos.x + picker_size.x),
                    clamp(setting.last_selected_color_pos.y, picker_pos.y, picker_pos.y + picker_size.y)
                )
                render.circle_filled(constrained_pos, 4, 32, color_t(1, 1, 1, setting.picker_alpha))
                
                local x = setting.last_selected_color_pos.x - picker_pos.x
                local y = setting.last_selected_color_pos.y - picker_pos.y
                local saturation = x / picker_size.x
                local value = 1 - (y / picker_size.y)
                
                local new_color = color_from_hsv(setting.hue, saturation, value, 1)
                setting.color_value.r = new_color.r
                setting.color_value.g = new_color.g
                setting.color_value.b = new_color.b
                --setting.color_value.a = 1
            end
            
            local selected_hue_pos = vec2_t(
                bar_pos.x + bar_width / 2,
                picker_pos.y + (setting.hue * picker_size.y)
            )
            
            render.filled_polygon({
                selected_hue_pos + vec2_t(-5, 0),
                selected_hue_pos + vec2_t(5, 0),
                selected_hue_pos + vec2_t(0, 10)
            }, color_t(1, 1, 1, setting.picker_alpha))
            
            local reset_button_width = picker_size.x + 2
            local reset_button_height = 20
            local reset_button_x = picker_pos.x
            local reset_button_y = picker_pos.y - reset_button_height - 5
            
            render.rect_filled(
                vec2_t(reset_button_x, reset_button_y),
                vec2_t(reset_button_x + reset_button_width, reset_button_y + reset_button_height),
                color_t(1, 1, 1, setting.picker_alpha),
                0
            )
            
            render.rect(
                vec2_t(reset_button_x, reset_button_y),
                vec2_t(reset_button_x + reset_button_width, reset_button_y + reset_button_height),
                color_t(0, 0, 0, setting.picker_alpha),
                0,
                2
            )
            
            local reset_text = "Reset"
            local reset_text_size = render.calc_text_size(reset_text, font14)
            render.text(
                reset_text, 
                font14, 
                vec2_t(
                    reset_button_x + (reset_button_width - reset_text_size.x) / 2, 
                    reset_button_y + (reset_button_height - reset_text_size.y) / 2
                ), 
                color_t(0, 0, 0, setting.picker_alpha)
            )
            
            if mouse.click and
               mouse.pos.x >= reset_button_x and
               mouse.pos.x <= reset_button_x + reset_button_width and
               mouse.pos.y >= reset_button_y and
               mouse.pos.y <= reset_button_y + reset_button_height then
               
                setting.color_value = color_t(161/255, 110/255, 228/255, 1)

                if setting == menu_custom_menu_color_enabled then
                    menu_accents_color = setting.color_value
                end
                
                local r, g, b = menu_accents_color.r, menu_accents_color.g, menu_accents_color.b
                local max = math.max(r, g, b)
                local min = math.min(r, g, b)
                local delta = max - min
                
                local h = 0
                if max == r then
                    h = ((g - b) / delta) % 6
                elseif max == g then
                    h = (b - r) / delta + 2
                elseif max == b then
                    h = (r - g) / delta + 4
                end
                h = h / 6
                
                local s = max == 0 and 0 or delta / max
                local v = max
                
                setting.hue = h
                setting.last_selected_color_pos = vec2_t(
                    picker_pos.x + (s * picker_size.x),
                    picker_pos.y + ((1 - v) * picker_size.y)
                )
                
                isOverControl = true
            end
            
            local isClickingOnResetButton = mouse.click and
            mouse.pos.x >= reset_button_x and
            mouse.pos.x <= reset_button_x + reset_button_width and
            mouse.pos.y >= reset_button_y and
            mouse.pos.y <= reset_button_y + reset_button_height;

            if mouse.click and not isClickingOnResetButton and
                (mouse.pos.x < picker_pos.x - 5 or mouse.pos.x > bar_pos.x + bar_width + 5 or
                 mouse.pos.y < picker_pos.y - reset_button_height - 10 or 
                 mouse.pos.y > alpha_slider_y + alpha_slider_height + 5) then
                setting.is_color_open = false
            end
        end
    end

    for _, setting in ipairs(tabSettings[gui.currentTab]) do
        if setting.type == "text" then
            local usedFont = setting.font or font14
            local textColor = setting.color or color_t(1, 1, 1, gui.alpha)
            local textWidth = render.calc_text_size(setting.text, usedFont).x
            local xPos = gui.x + 8
            
            if setting.align and setting.align == "center" then
                xPos = gui.x + (gui.width - textWidth) / 2
            end
            
            render.text(setting.text, usedFont, vec2_t(xPos, y), textColor)
            
        elseif setting.type == "checkbox" then
            render.text(setting.name, font14, vec2_t(gui.x + 25, y), color_t(1, 1, 1, gui.alpha)) 
            local boxX, boxY = gui.x + 8, y 
            local boxColor = setting.value and outline_color or color_t(34/255, 34/255, 34/255, 1)
            
            render.rect_filled(vec2_t(boxX, boxY), vec2_t(boxX + 12, boxY + 12), boxColor, 0)
            
            if mouse.click and 
               mouse.pos.x >= boxX and 
               mouse.pos.x <= boxX + 12 and 
               mouse.pos.y >= boxY and 
               mouse.pos.y <= boxY + 12 then
                setting.value = not setting.value
                isOverControl = true
            end
            
            if setting.has_color_picker then
                local colorBoxX = gui.x + gui.width - 30
                local colorBoxSize = 15
                
                render.rect_filled(
                    vec2_t(colorBoxX, boxY),
                    vec2_t(colorBoxX + colorBoxSize, boxY + colorBoxSize),
                    setting.color_value,
                    3
                )
                
                render.rect(
                    vec2_t(colorBoxX, boxY),
                    vec2_t(colorBoxX + colorBoxSize, boxY + colorBoxSize),
                    color_t(0, 0, 0, gui.alpha),
                    3,
                    1
                )
                
                if mouse.click and
                   mouse.pos.x >= colorBoxX and
                   mouse.pos.x <= colorBoxX + colorBoxSize and
                   mouse.pos.y >= boxY and
                   mouse.pos.y <= boxY + colorBoxSize then
                   
                    setting.is_color_open = not setting.is_color_open
                    
                    setting.picker_pos = vec2_t(
                        gui.x + gui.width + 10,
                        y
                    )
                    
                    if setting.is_color_open then
                        local picker_size = vec2_t(150, 150)
                        local r, g, b = setting.color_value.r, setting.color_value.g, setting.color_value.b
                        local max = math.max(r, g, b)
                        local min = math.min(r, g, b)
                        local delta = max - min
                        
                        local h = 0
                        if delta > 0 then
                            if max == r then
                                h = ((g - b) / delta) % 6
                            elseif max == g then
                                h = (b - r) / delta + 2
                            elseif max == b then
                                h = (r - g) / delta + 4
                            end
                            h = h / 6
                        end
                        
                        local s = max == 0 and 0 or delta / max
                        local v = max
                        
                        setting.hue = h
                        setting.last_selected_color_pos = vec2_t(
                            setting.picker_pos.x + (s * picker_size.x),
                            setting.picker_pos.y + ((1 - v) * picker_size.y)
                        )
                    end

                    for _, s in ipairs(settingList) do
                        if s ~= setting and ((s.type == "checkbox" and s.has_color_picker) or s.type == "colorpicker") then
                            s.is_color_open = false
                        end
                    end
                    
                    isOverControl = true
                end
            end
            
        elseif setting.type == "keybind" then
            render.text(setting.name, font14, vec2_t(gui.x + 8, y), color_t(1, 1, 1, gui.alpha))
            local bindX, bindY = gui.x + gui.width - 60, y
            
            render.rect_filled(
                vec2_t(bindX, bindY), 
                vec2_t(bindX + 52, bindY + 12),
                color_t(34/255, 34/255, 34/255, 1), 
                0
            )
            
            local text = gui.waitingForKey and setting == gui.activeKeybind and "..." or 
                        (setting.value == "none" and "none" or get_key_name(setting.value))
            
            render.text(
                text, 
                font14, 
                vec2_t(bindX + 26 - render.calc_text_size(text, font14).x/2, y), 
                color_t(1, 1, 1, gui.alpha)
            )
            
            if not isClickBlockedByDropdown and 
                mouse.click and 
                mouse.pos.x >= bindX and 
                mouse.pos.x <= bindX + 52 and 
                mouse.pos.y >= bindY and 
                mouse.pos.y <= bindY + 12 then
                    if mouse.click and 
                        mouse.pos.x >= bindX and 
                        mouse.pos.x <= bindX + 52 and 
                        mouse.pos.y >= bindY and 
                        mouse.pos.y <= bindY + 12 then
                        gui.waitingForKey = true
                        gui.activeKeybind = setting
                        gui.activeDropdown = nil
                        isOverControl = true
                    end
            end

            if not isClickBlockedByDropdown and 
                mouse.right_click and 
                mouse.pos.x >= bindX and 
                mouse.pos.x <= bindX + 52 and 
                mouse.pos.y >= bindY and 
                mouse.pos.y <= bindY + 12 then
                    if mouse.right_click and 
                        mouse.pos.x >= bindX and 
                        mouse.pos.x <= bindX + 52 and 
                        mouse.pos.y >= bindY and 
                        mouse.pos.y <= bindY + 12 then
                    if gui.activeDropdown == setting then
                        gui.activeDropdown = nil
                    else
                        gui.activeDropdown = setting
                        gui.waitingForKey = false
                        gui.activeKeybind = nil
                    end
                    isOverControl = true
                    end
            end
            
            if gui.activeDropdown == setting then
                activeDropdownInfo = {
                    setting = setting,
                    x = bindX,
                    y = bindY
                }
            end
            
        elseif setting.type == "slider" then
            local function round_increment(value, increment)
                return math.floor(value / increment + 0.5) * increment
            end
            
            local function round_display(value, increment)
                if increment >= 1 then
                    return tostring(math.floor(value + 0.5))
                else
                    local decimals = math.abs(math.floor(math.log10(increment)))
                    return string.format("%." .. decimals .. "f", value)
                end
            end
            
            render.text(setting.name, font14, vec2_t(gui.x + 8, y), color_t(1, 1, 1, gui.alpha))
            
            local sliderX, sliderY = gui.x + gui.width - 170, y
            local sliderWidth = 130
            
            render.rect_filled(
                vec2_t(sliderX, sliderY), 
                vec2_t(sliderX + sliderWidth, sliderY + 12), 
                color_t(34/255, 34/255, 34/255, 1), 
                3
            )
            
            local progress = (setting.value - setting.minValue) / (setting.maxValue - setting.minValue)
        
            if progress > 0 then
                local min_width_for_corners = 6
                local fill_width = math.max(min_width_for_corners, sliderWidth * progress)
                
                if progress > 0.97 then
                    fill_width = sliderWidth
                end
                
                render.rect_filled(
                    vec2_t(sliderX, sliderY), 
                    vec2_t(sliderX + fill_width, sliderY + 12), 
                    outline_color, 
                    3
                )
            end
        
            local inputX = sliderX + sliderWidth + 5

            if mouse.down and 
                mouse.pos.x >= sliderX and 
                mouse.pos.x <= sliderX + sliderWidth and
                mouse.pos.y >= sliderY and 
                mouse.pos.y <= sliderY + 12 and
                gui.activeInputBox ~= setting then
                local t = clamp((mouse.pos.x - sliderX) / sliderWidth, 0, 1)
                
                local raw_value = lerp(setting.minValue, setting.maxValue, t)
                
                local increments = (setting.maxValue - setting.minValue) / setting.increment
                local step_index = math.floor(t * increments + 0.5)
                local precise_value = setting.minValue + (step_index * setting.increment)
                
                setting.value = clamp(precise_value, setting.minValue, setting.maxValue)
                
                if t < 0.01 then
                    setting.value = setting.minValue
                elseif t > 0.99 then
                    setting.value = setting.maxValue
            end
    
    isOverControl = true
end
            
            local inputX = sliderX + sliderWidth + 5
            local inputWidth = 30
            local inputColor = gui.activeInputBox == setting and outline_color or color_t(34/255, 34/255, 34/255, 1)
            
            render.rect_filled(
                vec2_t(inputX, sliderY), 
                vec2_t(inputX + inputWidth, sliderY + 12), 
                color_t(20/255, 20/255, 20/255, 1), 
                3
            )
            
            render.rect(
                vec2_t(inputX, sliderY), 
                vec2_t(inputX + inputWidth, sliderY + 12), 
                inputColor, 
                3,
                1
            )
            
            local displayText = gui.activeInputBox == setting and gui.inputBuffer or round_display(setting.value, setting.increment)
            render.text(
                displayText, 
                font14, 
                vec2_t(inputX + inputWidth/2 - render.calc_text_size(displayText, font14).x/2, sliderY), 
                color_t(1, 1, 1, gui.alpha)
            )
            
            if mouse.click and 
                mouse.pos.x >= inputX and 
                mouse.pos.x <= inputX + inputWidth and
                mouse.pos.y >= sliderY and 
                mouse.pos.y <= sliderY + 12 then
                if gui.activeInputBox ~= setting then
                    gui.activeInputBox = setting
                    gui.originalInputValue = tostring(setting.value)
                    gui.inputBuffer = ""
                    gui.isTyping = true
                end
                isOverControl = true
            elseif mouse.click and gui.activeInputBox == setting then
                local number = tonumber(gui.inputBuffer)
                if number then
                    number = round_increment(number, setting.increment)
                    setting.value = clamp(number, setting.minValue, setting.maxValue)
                elseif gui.inputBuffer == "" then
                    setting.value = tonumber(gui.originalInputValue)
                end
                gui.activeInputBox = nil
                gui.isTyping = false
            end
        
            function handle_keyboard_input()
                if not gui.activeInputBox or not gui.isTyping then return end
                
                for key = 0x30, 0x39 do -- Numbers 0-9
                    if is_key_pressed(key) and not key_states[key] then
                        gui.inputBuffer = gui.inputBuffer .. string.char(key)
                        key_states[key] = true
                    elseif not is_key_pressed(key) then
                        key_states[key] = false
                    end
                end
                
                if is_key_pressed(0xBE) and not key_states[0xBE] then
                    if not gui.inputBuffer:find("%.") then
                        gui.inputBuffer = gui.inputBuffer .. "."
                    end
                    key_states[0xBE] = true
                elseif not is_key_pressed(0xBE) then
                    key_states[0xBE] = false
                end
                
                if is_key_pressed(0xBD) and not key_states[0xBD] then
                    if #gui.inputBuffer == 0 then
                        gui.inputBuffer = "-"
                    end
                    key_states[0xBD] = true
                elseif not is_key_pressed(0xBD) then
                    key_states[0xBD] = false
                end
                
                -- Backspace
                if is_key_pressed(0x08) and not key_states[0x08] then
                    gui.inputBuffer = gui.inputBuffer:sub(1, -2)
                    key_states[0x08] = true
                elseif not is_key_pressed(0x08) then
                    key_states[0x08] = false
                end
                
                -- Enter
                if is_key_pressed(0x0D) and not key_states[0x0D] then
                    local number = tonumber(gui.inputBuffer)
                    if number then
                        gui.activeInputBox.value = clamp(number, gui.activeInputBox.minValue, gui.activeInputBox.maxValue)
                    elseif gui.inputBuffer == "" then
                        gui.activeInputBox.value = tonumber(gui.originalInputValue)
                    end
                    gui.activeInputBox = nil
                    gui.isTyping = false
                    key_states[0x0D] = true
                elseif not is_key_pressed(0x0D) then
                    key_states[0x0D] = false
                end
                
                -- Escape
                if is_key_pressed(0x1B) and not key_states[0x1B] then
                    gui.activeInputBox = nil
                    gui.isTyping = false
                    key_states[0x1B] = true
                elseif not is_key_pressed(0x1B) then
                    key_states[0x1B] = false
                end
            end
        elseif setting.type == "combobox" then
            render.text(setting.name, font14, vec2_t(gui.x + 8, y), color_t(1, 1, 1, gui.alpha))
        
            local boxX, boxY = gui.x + gui.width - 108, y
            local boxWidth = 100
        
            render.rect_filled(
                vec2_t(boxX, boxY), 
                vec2_t(boxX + boxWidth, boxY + 18),
                color_t(34/255, 34/255, 34/255, 1), 
                3
            )
        
            local selected_text = ""
            local selected_count = 0
            for i, selected in ipairs(setting.value) do
                if selected then
                    if selected_count > 0 then
                        selected_text = selected_text .. ", "
                    end
                    selected_text = selected_text .. setting.values[i]:sub(1, 3)
                    selected_count = selected_count + 1
                end
            end
            
            if selected_count == 0 then
                selected_text = "None"
            elseif selected_count > 2 then
                selected_text = selected_count .. " selected"
            end
        
            if render.calc_text_size(selected_text, font14).x > boxWidth - 20 then
                selected_text = selected_count .. " selected"
            end
        
            render.text(
                selected_text, 
                font14, 
                vec2_t(boxX + 5, boxY + 3), 
                color_t(1, 1, 1, gui.alpha)
            )
        
            render.text(
                "^", 
                font16, 
                vec2_t(boxX + boxWidth - 15, boxY + 3), 
                color_t(1, 1, 1, gui.alpha)
            )
        
            if not isClickBlockedByDropdown and 
               mouse.click and 
               mouse.pos.x >= boxX and 
               mouse.pos.x <= boxX + boxWidth and
               mouse.pos.y >= boxY and 
               mouse.pos.y <= boxY + 18 then
                if gui.activeDropdown == setting then
                    gui.activeDropdown = nil
                else
                    gui.activeDropdown = setting
                    gui.waitingForKey = false
                    gui.activeKeybind = nil
                end
                isOverControl = true
            end
        
            if gui.activeDropdown == setting then
                activeDropdownInfo = {
                    setting = setting,
                    x = boxX,
                    y = boxY
                }
            end
        elseif setting.type == "dropdown" then
            render.text(setting.name, font14, vec2_t(gui.x + 8, y), color_t(1, 1, 1, gui.alpha))
        
            local dropX, dropY = gui.x + gui.width - 108, y
            local dropWidth = 100
        
            render.rect_filled(
                vec2_t(dropX, dropY), 
                vec2_t(dropX + dropWidth, dropY + 18),
                color_t(34/255, 34/255, 34/255, 1), 
                3
            )
        
            local selectedText = setting.values[setting.value] or "Select"
            render.text(
                selectedText, 
                font14, 
                vec2_t(dropX + 5, dropY + 3), 
                color_t(1, 1, 1, gui.alpha)
            )
        
            render.text(
                "^", 
                font16, 
                vec2_t(dropX + dropWidth - 15, dropY + 3), 
                color_t(1, 1, 1, gui.alpha)
            )

            if not isClickBlockedByDropdown and 
               mouse.click and 
               mouse.pos.x >= dropX and 
               mouse.pos.x <= dropX + dropWidth and
               mouse.pos.y >= dropY and 
               mouse.pos.y <= dropY + 18 then
                if mouse.click and 
               mouse.pos.x >= dropX and 
               mouse.pos.x <= dropX + dropWidth and
               mouse.pos.y >= dropY and 
               mouse.pos.y <= dropY + 18 then
                if gui.activeDropdown == setting then
                    gui.activeDropdown = nil
                else
                    gui.activeDropdown = setting
                    gui.waitingForKey = false
                    gui.activeKeybind = nil
                end
                isOverControl = true
            end
            end

            if gui.activeDropdown == setting then
                activeDropdownInfo = {
                    setting = setting,
                    x = dropX,
                    y = dropY
                }
            end
        end
        y = y + 28
    end
    
    if activeDropdownInfo then
        local dropdownX = activeDropdownInfo.x
        local dropdownY = activeDropdownInfo.y + 18
        local dropdownWidth = 100
        local setting = activeDropdownInfo.setting
        
        if setting.type == "keybind" then
            dropdownX = activeDropdownInfo.x + 20
            dropdownWidth = 80
            local dropdownHeight = #gui.dropdownOptions * 20
            
            render.rect_filled(
                vec2_t(dropdownX, dropdownY),
                vec2_t(dropdownX + dropdownWidth, dropdownY + dropdownHeight),
                color_t(24/255, 24/255, 24/255, 1),
                4
            )
            
            for i, option in ipairs(gui.dropdownOptions) do
                local optionY = dropdownY + (i-1) * 20
                local isSelected = activeDropdownInfo.setting.mode == i
                
                if isSelected then
                    render.rect_filled(
                        vec2_t(dropdownX + 2, optionY + 2),
                        vec2_t(dropdownX + dropdownWidth - 2, optionY + 18),
                        color_t(outline_color.r, outline_color.g, outline_color.b, 0.5),
                        2
                    )
                end
                
                render.text(
                    option,
                    font14,
                    vec2_t(dropdownX + 10, optionY + 4),
                    color_t(1, 1, 1, 1)
                )
                
                if mouse.click and 
                    mouse.pos.x >= dropdownX and
                    mouse.pos.x <= dropdownX + dropdownWidth and
                    mouse.pos.y >= optionY and
                    mouse.pos.y <= optionY + 20 then
                    activeDropdownInfo.setting.mode = i
                    gui.activeDropdown = nil
                end
            end
        else
            local dropdownHeight = #setting.values * 20
            
            render.rect_filled(
                vec2_t(dropdownX, dropdownY),
                vec2_t(dropdownX + dropdownWidth, dropdownY + dropdownHeight),
                color_t(24/255, 24/255, 24/255, 1),
                4
            )
            
            for i, option in ipairs(setting.values) do
                local optionY = dropdownY + (i-1) * 20
                local isSelected = setting.value == i
                
                if setting.type == "dropdown" then
                    isSelected = setting.value == i
                elseif setting.type == "combobox" then
                    isSelected = setting.value[i]
                end

                if isSelected then
                    render.rect_filled(
                        vec2_t(dropdownX + 2, optionY + 2),
                        vec2_t(dropdownX + dropdownWidth - 2, optionY + 18),
                        color_t(outline_color.r, outline_color.g, outline_color.b, 0.5),
                        2
                    )
                end
                
                render.text(
                    option,
                    font14,
                    vec2_t(dropdownX + 10, optionY + 4),
                    color_t(1, 1, 1, 1)
                )
                
                if mouse.click and 
                    mouse.pos.x >= dropdownX and
                    mouse.pos.x <= dropdownX + dropdownWidth and
                    mouse.pos.y >= optionY and
                    mouse.pos.y <= optionY + 20 then
                    if setting.type == "dropdown" then
                        setting.value = i
                        gui.activeDropdown = nil
                    elseif setting.type == "combobox" then
                        setting.value[i] = not setting.value[i]
                    end
                end
            end
        end
    end
end

categorizeSettings()
register_callback("paint", renderGui)

local prev_on_ground = true
local in_air = false
local just_landed = false
local is_crouching = false
local is_walking = false
local is_standing = false

local current_state = "unknown"

local FL_ONGROUND = bit.lshift(1, 0)
local FL_DUCKING = bit.lshift(1, 1)

local state_font = render.setup_font("C:/windows/fonts/verdana.ttf", 18, 600)

local function check_player_state()
    local player_controller = entitylist.get_local_player_controller()
    if not player_controller then return end
    
    local pawn = player_controller.m_hPlayerPawn
    if not pawn then return end
    
    local flags = pawn.m_fFlags
    local velocity = pawn.m_vecAbsVelocity
    local vel_length_2d = math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y)
    
    local on_ground = bit.band(flags, FL_ONGROUND) ~= 0
    in_air = not on_ground
    just_landed = not prev_on_ground and on_ground
    prev_on_ground = on_ground
    
    is_crouching = bit.band(flags, FL_DUCKING) ~= 0
    
    if on_ground then
        is_walking = vel_length_2d > 0
        is_standing = vel_length_2d == 0 and not is_crouching
    else
        is_walking = false
        is_standing = false
    end
    
    if just_landed then
        current_state = "landed"
    elseif in_air then
        current_state = "air"
        if is_crouching then
            current_state = "air_duck"
        end
    elseif is_crouching then
        if is_walking then
            current_state = "crouch_walk"
        else
            current_state = "crouch"
        end
    elseif is_walking then
        current_state = "walk"
    elseif is_standing then
        current_state = "stand"
    else
        current_state = "unknown"
    end
end

local function get_random_yaw()
    if math.random(0, 1) == 0 then
        return math.random(-180, -180+menu_random_yaw_deviance.value)
    else
        return math.random(180-menu_random_yaw_deviance.value, 180)
    end
end

local state_to_condition_map = {
    ["stand"] = 1,
    ["walk"] = 2,
    ["air"] = 3,
    ["crouch"] = 4,
    ["air_duck"] = 5,
    ["crouch_walk"] = 6,
}

local manuals_toggle = nil 
local last_left_state = false
local last_right_state = false

local last_manuals_toggle = nil
local pitch_needs_reset = false

spin_prev_offset = 0

local function anti_aim_handler()
    if menu_anti_aim_builder_enabled.value then
        local condition_idx = state_to_condition_map[current_state] or 1
        
        yaw_modifier = condition_settings[condition_idx].yaw_modifier.value
        yaw_offset = condition_settings[condition_idx].yaw_offset.value
        
        if yaw_modifier == 7 then
            spin_prev_offset = spin_prev_offset + yaw_offset
            if spin_prev_offset > 180 then
                spin_prev_offset = -180
            end
            menu.ragebot_anti_aim_base_yaw_offset = spin_prev_offset
            menu.ragebot_anti_aim_base_yaw_modifier = 0
            menu.ragebot_anti_aim_base_yaw_modifier_offset = 0
        else
            menu.ragebot_anti_aim_base_yaw_modifier = yaw_modifier - 1
            menu.ragebot_anti_aim_base_yaw_modifier_offset = yaw_offset
        end
    end

    if menu_manual_aa_enabled.value then
        local left_state = is_key_pressed(menu_manual_left_key.value)
        local right_state = is_key_pressed(menu_manual_right_key.value)

        if left_state and not last_left_state then
            if manuals_toggle == 90 then
                manuals_toggle = nil
                pitch_needs_reset = true
            else
                manuals_toggle = 90
            end
        end

        if right_state and not last_right_state then
            if manuals_toggle == -90 then
                manuals_toggle = nil
                pitch_needs_reset = true
            else
                manuals_toggle = -90
            end
        end

        last_left_state = left_state
        last_right_state = right_state
    end

    if manuals_toggle ~= last_manuals_toggle then
        if manuals_toggle == nil and last_manuals_toggle ~= nil then
            pitch_needs_reset = true
        end
        last_manuals_toggle = manuals_toggle
    end

    if manuals_toggle then
        menu.ragebot_anti_aim_base_yaw_offset = manuals_toggle
        if menu_pitch_jitter_enabled.value then
            if math.random(1, 100) <= menu_pitch_jitter_chance.value then
                menu.ragebot_anti_aim_pitch = menu_anti_aim_pitch.value - 1
            else
                menu.ragebot_anti_aim_pitch = 0
            end
        end
    else
        if yaw_modifier == 7 then
            return
        else
            if menu_random_yaw_enabled.value then
                menu.ragebot_anti_aim_base_yaw_offset = get_random_yaw()
            else
                menu.ragebot_anti_aim_base_yaw_offset = 180
            end

            if pitch_needs_reset then
                menu.ragebot_anti_aim_pitch = menu_anti_aim_pitch.value - 1
                pitch_needs_reset = false
            end
        end
    end
end

local function disable_ragebot_in_air()
    if current_state == "air" or current_state == "air_duck" then
        menu.ragebot_aimbot = false
    else
        menu.ragebot_aimbot = true
    end
end

local function buybot_run()
    --local player_controller = entitylist.get_local_player_controller()
    --if not player_controller then return end
    local player_pawn = entitylist.get_local_player_pawn()
    if not player_pawn then return end

    for i = 1, #menu_buybot_selector.value do
        if menu_buybot_selector.value[i] then
            engine.execute_client_cmd("buy " .. buybot_cmd_names[i])
        end
    end
end

VK_W = 0x57
VK_A = 0x41
VK_S = 0x53
VK_D = 0x44

local function is_wasd_pressed()
    w_pressed = is_key_pressed(VK_W)
    a_pressed = is_key_pressed(VK_A)
    s_pressed = is_key_pressed(VK_S)
    d_pressed = is_key_pressed(VK_D)
end

local function adaptive_autostrafe()
    if menu_adaptive_auto_strafer_enabled.value then
        if w_pressed or a_pressed or s_pressed or d_pressed then
            menu.ragebot_auto_strafer = true
        else
            menu.ragebot_auto_strafer = false
        end
    end
end

-- SKIDDED VELOCITY INDICATOR CODE BELOW | credits to Shinryu (Nix UID: 134794)
function math.lerp(a, b, t) return a + (b - a) * t end

local ColorMod = function(perc)
    local r = (124 * 2 - 124 * perc) / 255
    local g = (195 * perc) / 255 
    local b = 13 / 255
    return color_t(r, g, b, 1)
end
local FixedNumber = function(number)
    return string.format("%d", (1 - number) * 100)
end

local is_connected = function(ply_controller)
    local connected = ply_controller.m_iConnected
    return connected == 1
end

local is_alive = function(ply_controller)
    local alive = ply_controller.m_bPawnIsAlive
    return alive == 1
end

local font = render.setup_font("C:/windows/fonts/verdana.ttf", 12, 400)
local warningfont = render.setup_font("C:/windows/fonts/verdana.ttf", 27, 400)
local animation = {x_add = 0, rectfill = 0, alpha = 0}

function toDraw()

    local player_controller = entitylist.get_local_player_controller()
    if player_controller == nil then return end

    local localpawn = player_controller.m_hPlayerPawn
    if not localpawn then return end

    local game_scene_node = localpawn.m_pGameSceneNode
    if game_scene_node == nil then return end
    
    local sx = render.screen_size().x
    local sy = render.screen_size().y
    local position = {
        x = sx / 2,
        y = sy / 2 - 170
    }

    local velmodifier = localpawn.m_flVelocityModifier
    local text = "Slowed down " .. FixedNumber(velmodifier) .. "%"
    local textsize = render.calc_text_size(text, font, 12)

    local colorrect = ColorMod(velmodifier)

    if animation.rectfill == 0 then 
        animation.rectfill = velmodifier * 105 
    end

    animation.alpha = math.lerp(
        animation.alpha, 
        (velmodifier ~= 1 and is_connected(player_controller) and is_alive(player_controller)) and 1 or 0, 
        10 * render.frame_time()
    )
    animation.rectfill = math.lerp(animation.rectfill, velmodifier * 105, 10 * render.frame_time())

    
    if velmodifier == 1 then
        return
    end

    render.text(text, font, vec2_t(position.x - 50, position.y), 12, color_t(1, 1, 1, animation.alpha))

    render.rect_filled(
        vec2_t(position.x - 50 - 1, position.y + textsize.y + 2),
        vec2_t(position.x - 50 + 105 + 1, position.y + textsize.y + 4 + 9),
        color_t(0, 0, 0, 0.2)
    )

    if animation.rectfill > 0 then
        render.rect_filled(
            vec2_t(position.x - 50, position.y + textsize.y + 3),
            vec2_t(position.x - 50 + animation.rectfill, position.y + textsize.y + 3 + 9),
            color_t(colorrect.r, colorrect.g, colorrect.b, 1)
        )
    end

    local shadowpoints = { 
        vec2_t(position.x - (50 + 55) + 8 + 20, position.y - 4),
        vec2_t(position.x - (50 + 55) + 8 + 40, position.y - 4 + 35),
        vec2_t(position.x - (50 + 55) + 8, position.y - 4 + 35)
    }

    local filledpoints = { 
        vec2_t(position.x - (50 + 55) + 8 + 20, position.y - 4 + 3),
        vec2_t(position.x - (50 + 55) + 8 + 40 - 3, position.y - 4 + 35 - 2),
        vec2_t(position.x - (50 + 55) + 8 + 3, position.y - 4 + 35 - 2)
    }

    local triangle_center = {
        x = (shadowpoints[1].x + shadowpoints[2].x + shadowpoints[3].x) / 3,
        y = (shadowpoints[1].y + shadowpoints[2].y + shadowpoints[3].y) / 3
    }

    local exclamation_size = render.calc_text_size("!", warningfont, 27)

    render.filled_polygon(
        shadowpoints,
        color_t(0, 0, 0, 0.5)
    )

    render.filled_polygon(
        filledpoints,
        color_t(
            colorrect.r, 
            colorrect.g, 
            colorrect.b, 
            0.8
        )
    )

    render.text("!", warningfont, vec2_t(triangle_center.x - (exclamation_size.x / 2), triangle_center.y - (exclamation_size.y / 2)), 
        27, 
        color_t(0, 0, 0, 0.5)
    )
end

-- SKIDDED MANUAL AA INDICATOR CODE BELOW | Heavily Modified
local manualaaind = {}

function manualaaind.draw_indicator()
    if not menu_manual_aa_enabled.value then
        return
    end

    local local_player = entitylist.get_local_player_pawn()
    if not local_player then 
        return 
    end

    local screen_center = vec2_t(
        render.screen_size().x / 2,
        render.screen_size().y / 2
    )

    local current_yaw_offset = manuals_toggle or 0

    local manual = 0
    if current_yaw_offset >= 45 and current_yaw_offset <= 145 then
        manual = 2
    elseif current_yaw_offset <= -75 and current_yaw_offset >= -145 then
        manual = 1
    end

    local arrow_left = {
        vec2_t(screen_center.x - (manuals_distance + 23), screen_center.y),
        vec2_t(screen_center.x - (manuals_distance + 6), screen_center.y - 6),
        vec2_t(screen_center.x - (manuals_distance + 11), screen_center.y),
        vec2_t(screen_center.x - (manuals_distance + 6), screen_center.y + 6)
    }

    local arrow_right = {
        vec2_t(screen_center.x + (manuals_distance + 23), screen_center.y),
        vec2_t(screen_center.x + (manuals_distance + 6), screen_center.y - 6),
        vec2_t(screen_center.x + (manuals_distance + 11), screen_center.y),
        vec2_t(screen_center.x + (manuals_distance + 6), screen_center.y + 6)
    }

    render.filled_polygon(arrow_left, manual == 2 and menu_manual_aa_enabled.color_value or color_t(0, 0, 0, 0.4))
    render.filled_polygon(arrow_right, manual == 1 and menu_manual_aa_enabled.color_value or color_t(0, 0, 0, 0.4))
end

local randomness_modes = {os.time(), os.time() + tonumber(tostring({}):sub(8))}
math.randomseed(randomness_modes[menu_randomness_mode.value])

register_callback("round_start", function()
    if menu_buybot.value then
        buybot_run()
    end
    bClear = true;
    last_count_bullet = 0
end)

local killsay_counter = 0
register_callback("player_death", function(event)
    if menu_killsay_enabled.value then
        if event:get_pawn("attacker") == entitylist.get_local_player_pawn() then
            engine.execute_client_cmd("say " .. killsay_phrases[killsay_counter % #killsay_phrases + 1])
            killsay_counter = killsay_counter + 1
        end
    end
end)

local zero_pitch_tick_counter = 0
local is_in_0_pitch = false
local function zero_pitch_on_land()
    if current_state == "landed" then
        is_in_0_pitch = true
    end
    if is_in_0_pitch then
        if zero_pitch_tick_counter >= menu_0_pitch_on_land_duration.value then
            is_in_0_pitch = false
            zero_pitch_tick_counter = 0
            menu.ragebot_anti_aim_pitch = menu_anti_aim_pitch.value - 1
        else
            zero_pitch_tick_counter = zero_pitch_tick_counter + 1
            menu.ragebot_anti_aim_pitch = 0
        end
    end
end

local air_flick_tick_counter = 0
local function air_flick()
    local flick_trigger_rate = menu_air_flick_trigger_rate.value
    if current_state == "air" or current_state == "air_duck" then
        if air_flick_tick_counter >= 64-flick_trigger_rate then
            air_flick_tick_counter = 0
            menu.ragebot_anti_aim_pitch = 0
            local yaw_flick_side = math.random(1, 2)
            if yaw_flick_side == 1 then
                menu.ragebot_anti_aim_base_yaw_offset = math.random(80, 110)
            else
                menu.ragebot_anti_aim_base_yaw_offset = math.random(-110, -80)
            end
        else
            menu.ragebot_anti_aim_pitch = menu_anti_aim_pitch.value - 1
        end
        air_flick_tick_counter = air_flick_tick_counter + 1
    end
end

-- SKIDDED WATERMARK CODE | credits to Frnxx:44440 | !! Code converted by Claude 3.7 Sonnet to not use external libraries && fixed by me !!

local function lerp(a, b, t)
    return a + (b - a) * t
end

local verdana = render.setup_font("C:/Windows/Fonts/verdana.ttf", 12, 0)

local cheat_name = "Singularity.lua" 
local custom_username = false
local custom_username_text = "JuicyChann"

local colors = {
    accent = menu_watermark_enabled.color_value,
    bg = color_t(0.06, 0.06, 0.06, 0.4)
}

local frame_count_for_fps, current_fps = 0, 0
local last_time_for_fps = os.clock()

local anim = {
    x = 0,
    w = 0
}

local function draw_glow(x, y, w, h, color, radius, intensity)
    local alpha_step = color.a / intensity
    for i = 1, intensity do
        local expanded_size = i * radius / intensity
        local alpha = color.a - (i * alpha_step)
        render.rect(
            vec2_t(x - expanded_size, y - expanded_size),
            vec2_t(x + w + expanded_size, y + h + expanded_size),
            color_t(color.r, color.g, color.b, alpha),
            radius,
            0
        )
    end
end

local function draw_arc(x, y, radius, start_angle, end_angle, segments, color, thickness)
    local step = (end_angle - start_angle) / segments
    for i = 0, segments - 1 do
        local angle1 = math.rad(start_angle + i * step)
        local angle2 = math.rad(start_angle + (i + 1) * step)
        local x1, y1 = x + radius * math.cos(angle1), y + radius * math.sin(angle1)
        local x2, y2 = x + radius * math.cos(angle2), y + radius * math.sin(angle2)
        render.line(vec2_t(x1, y1), vec2_t(x2, y2), color, thickness)
    end
end

local function draw_rect_filled_fade(x, y, w, h, color1, color2, color3, color4)
    local steps = 20
    local step_h = h / steps
    
    for i = 0, steps - 1 do
        local t = i / (steps - 1)
        
        local r = color1.r + (color2.r - color1.r) * t
        local g = color1.g + (color2.g - color1.g) * t
        local b = color1.b + (color2.b - color1.b) * t
        local a = color1.a + (color2.a - color1.a) * t
        
        local y_pos = y + (i * step_h)
        render.rect_filled(
            vec2_t(x, y_pos),
            vec2_t(x + w, y_pos + step_h + 1),
            color_t(r, g, b, a),
            0
        )
    end
end

local function create_window(x, y, w, h, bg_clr, accent_clr, watermark_style)
    if watermark_style == 1 then
        render.rect_filled(vec2_t(x, y), vec2_t(x + w, y + h), bg_clr, 0)
        render.rect_filled(vec2_t(x, y), vec2_t(x + w, y + 2), accent_clr, 0)

    elseif watermark_style == 2 then
        render.rect_filled(vec2_t(x, y), vec2_t(x + w, y + h), bg_clr, 5)
        render.rect_filled(vec2_t(x, y + 7), vec2_t(x + 2, y + h - 7), accent_clr, 0)
        render.rect_filled(vec2_t(x + w - 2, y + 7), vec2_t(x + w, y + h - 7), accent_clr, 0)
        draw_glow(x, y + 7, 2, h - 14, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0.25), 3, 30)
        draw_glow(x + w - 2, y + 7, 2, h - 14, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0.25), 3, 30)
    
    elseif watermark_style == 3 then
        draw_glow(x, y, w, h, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0.25), 5, 30)
        render.rect_filled(vec2_t(x, y), vec2_t(x + w, y + h), bg_clr, 6)
        render.rect(vec2_t(x, y), vec2_t(x + w, y + h), color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0.35), 5, 0)
        draw_arc(x + 5, y + 5, 4, 3, 5, 10, accent_clr, 1)
        render.rect_filled(vec2_t(x + 4, y), vec2_t(x + w - 4, y + 1), accent_clr, 0)
        draw_arc(x + w - 5, y + 5, 4, 6, 5, 10, accent_clr, 1)
        draw_rect_filled_fade(x, y + 4, 1, h - 6, accent_clr, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0), accent_clr, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0))
        draw_rect_filled_fade(x + w - 1, y + 4, 1, h - 6, accent_clr, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0), accent_clr, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0))
    
    elseif watermark_style == 4 then
        draw_glow(x - 4, y, w + 8, h, color_t(accent_clr.r, accent_clr.g, accent_clr.b, 0.25), 0, 30)
        render.rect_filled(vec2_t(x - 4, y), vec2_t(x - 4 + w + 8, y + h), color_t(bg_clr.r, bg_clr.g, bg_clr.b, 0.5), 0)
        render.rect_filled(vec2_t(x, y + 5), vec2_t(x + w, y + 5 + h - 8), color_t(bg_clr.r, bg_clr.g, bg_clr.b, 0.5), 0)
        render.rect(vec2_t(x - 4, y), vec2_t(x - 4 + w + 8, y + h), color_t(bg_clr.r, bg_clr.g, bg_clr.b, 0.25), 0, 0)
        render.rect_filled(vec2_t(x, y + 4), vec2_t(x + w, y + 5), accent_clr, 0)
    end
end

local function draw_watermark()
    local current_time = os.clock()
    frame_count_for_fps = frame_count_for_fps + 1

    if current_time - last_time_for_fps >= 1 then
        current_fps = frame_count_for_fps
        frame_count_for_fps = 0
        last_time_for_fps = current_time
    end

    local controller = entitylist.get_local_player_controller()
    if controller == nil then return end

    local screen_size = render.screen_size()
    local username = custom_username and custom_username_text or get_user_name()

    local text = string.format("%s | %s | ping: %sms | fps: %s | %s", cheat_name, username, controller.m_iPing, current_fps, os.date("%H:%M:%S"))
    local text_size = render.calc_text_size(text, verdana, 12)
    
    anim.x = lerp(anim.x, screen_size.x - text_size.x - 20, 0.1)
    anim.w = lerp(anim.w, text_size.x, 0.25)
    
    local y = 10
    local h = 23

    create_window(anim.x - 6, y, anim.w + 12, h, colors.bg, colors.accent, menu_watermark_style.value)
    render.text(text, verdana, vec2_t(anim.x, y + h/2 - 6), color_t(1, 1, 1, 1), 12)
end

-- SKIDDED DUCK PEEK ASSIST CODE BELOW | credits to PaveKyz (UID: 1422)
local duck_assist_toggle = false
local min_dmg_toggle = false
local last_duck_key_state = false
local last_min_dmg_key_state = false
local visualize = true

local vecViewOffset = engine.get_netvar_offset("client.dll", "C_BaseModelEntity", "m_vecViewOffset")
local pGameSceneNode = engine.get_netvar_offset("client.dll", "C_BaseEntity", "m_pGameSceneNode")
local modelState = engine.get_netvar_offset("client.dll", "CSkeletonInstance", "m_modelState")
local pBoneMatrix = 0x80
local bone_spacing = 0x20

local function is_key_held(key)
    if type(key) == "string" or key == "none" or not key then
        return false
    end
    if not is_game_window_focused() then
        return false
    end
    return bit.band(ffi.C.GetKeyState(key), 0x8000) ~= 0
end

base_entity_t.is_alive = function(entity)
    return entity.m_lifeState == 0 and entity.m_iHealth > 0
end

base_entity_t.is_on_ground = function(entity)
    return bit.band(entity.m_fFlags, 1) == 1
end

base_entity_t.is_teammate = function(entity1, entity2)
    return not cvars.mp_teammates_are_enemies:get_bool() and entity1.m_iTeamNum == entity2.m_iTeamNum
end

base_entity_t.get_eye_position = function(entity, standing)
    local abs_origin = entity:get_abs_origin()
    local view_offset = ffi.cast("struct Vector*", ffi.cast("uintptr_t", entity[0]) + vecViewOffset)[0]
    local position = vec3_t(abs_origin.x + view_offset.x, abs_origin.y + view_offset.y, abs_origin.z + view_offset.z)
    if standing then
        position.z = position.z - entity.m_pMovementServices.m_flDuckOffset
    end
    return position
end

base_entity_t.get_bone_pos = function(entity, bone)
    local game_scene_node = ffi.cast("uintptr_t*", ffi.cast("uintptr_t", entity[0]) + pGameSceneNode)[0]
    local bone_matrix = ffi.cast("uintptr_t*", ffi.cast("uintptr_t", game_scene_node) + (modelState + pBoneMatrix))[0]
    local position = ffi.cast("struct Vector*", ffi.cast("uintptr_t", bone_matrix) + (bone * bone_spacing))[0]
    return vec3_t(position.x, position.y, position.z)
end

render.point = function(pos, bool)
    pos = render.world_to_screen(pos)
    if not pos then return end
    render.circle_fade(pos, 4, color_t(1, bool and 0 or 1, bool and 0 or 1, 0.8), color_t(1, bool and 0 or 1, bool and 0 or 1, 0))
end

engine.trace_bullet_team_check = function(from_entity, from, to) -- :)
    local eye_pos = from_entity:get_eye_position()
    local calc_angle = math.calc_angle(from, to)
    local distance = from:dist_to(to)
    local mate = nil
    local max_distance = 0
    entitylist.get_entities("C_CSPlayerPawn", function(entity)
        if not entity or entity == from_entity or not entity:is_alive() or not from_entity:is_teammate(entity) or entity.m_iTeamNum == 0 then return end
        local ent_eye_pos = entity:get_eye_position()
        local ent_distance = from:dist_to(ent_eye_pos)
        local calc_fov = math.calc_fov(calc_angle, math.calc_angle(eye_pos, ent_eye_pos))
        if ent_distance > max_distance and ent_distance + 35 < distance and calc_fov < 40 then
            max_distance = ent_distance
            mate = entity
        end
    end)
    if not mate then return false end
    local mate_eye_pos = mate:get_eye_position()
    local mate_distance = from:dist_to(mate_eye_pos)
    local forward, right, up = math.angle_vectors(calc_angle)
    local trace = engine.trace_bullet(from_entity, from + forward * (mate_distance + 15), from)
    if trace then return true end
    return false
end

local view_angles = angle_t(0, 0, 0)

register_callback("override_view", function(view_setup)
    view_angles = view_setup.angles
end)

local can_shoot = false
local is_ducking = false
local bones = {6, 4, 0}

local function update_min_dmg_toggle()
    local min_dmg_key_pressed = is_key_pressed(menu_default_override_min_dmg_key.value)

    if menu_default_override_min_dmg_key.mode == 2 then -- Toggle mode
        if min_dmg_key_pressed and not last_min_dmg_key_state then
            min_dmg_toggle = not min_dmg_toggle
        end
    else
        min_dmg_toggle = is_key_held(menu_default_override_min_dmg_key.value)
    end

    last_min_dmg_key_state = min_dmg_key_pressed
end

local function update_duck_assist_toggles()
    local duck_key_pressed = is_key_pressed(menu_duck_peek_assist_key.value)
    
    if menu_duck_peek_assist_key.mode == 2 then -- Toggle mode
        if duck_key_pressed and not last_duck_key_state then
            duck_assist_toggle = not duck_assist_toggle
        end
    else
        duck_assist_toggle = is_key_held(menu_duck_peek_assist_key.value)
    end
    
    last_duck_key_state = duck_key_pressed
end

local function handle_duck_assist()
    update_duck_assist_toggles()
    
    can_shoot = false
    local local_player_pawn = entitylist.get_local_player_pawn()
    if not local_player_pawn then
        return
    end
    local local_player_controller = entitylist.get_local_player_controller()
    if not local_player_controller then
        return
    end
    local health = local_player_pawn.m_iHealth
    if not health or health <= 0 then return end;
    
    if not duck_assist_toggle or not local_player_pawn or not local_player_controller or not local_player_pawn:is_alive() or not local_player_pawn:is_on_ground() then
        if is_ducking then
            engine.execute_client_cmd("-duck")
            is_ducking = false
        end
        return
    end
    
    local eye_pos = local_player_pawn:get_eye_position(true)
    local target = nil
    local min_fov = math.huge
    entitylist.get_entities("C_CSPlayerPawn", function(entity)
        if not entity or entity == local_player_pawn or not entity:is_alive() or local_player_pawn:is_teammate(entity) or entity.m_iTeamNum == 0 then return end
        local enemy_eye_pos = entity:get_eye_position()
        local fov = math.calc_fov(view_angles, math.calc_angle(eye_pos, enemy_eye_pos))
        if fov < min_fov then
            min_fov = fov
            target = entity
        end
    end)
    if target then
        local min_damage = math.min(min_dmg_toggle and menu_default_override_min_dmg.value or menu_default_min_dmg.value, target.m_iHealth)
        for _, bone in pairs(bones) do
            local bone_pos = target:get_bone_pos(bone)
            if bone == 6 then bone_pos.z = bone_pos.z + 4 end
            local trace = engine.trace_bullet(local_player_pawn, eye_pos, bone_pos)
            local team_check = engine.trace_bullet_team_check(local_player_pawn, eye_pos, bone_pos)
            if visualize then render.point(bone_pos, (trace and trace >= min_damage) and not team_check) end
            if (trace and trace >= min_damage) and not team_check then
                can_shoot = true
            end
        end
    end
    local duck_offset = local_player_pawn.m_pMovementServices.m_flDuckOffset
    local duck_speed = local_player_pawn.m_pMovementServices.m_flDuckSpeed
    local tick_base = local_player_controller.m_nTickBase
    
    local weapon_entity = local_player_pawn.m_pWeaponServices.m_hActiveWeapon
    if not weapon_entity then return end
    local next_attack_tick = local_player_pawn.m_pWeaponServices.m_hActiveWeapon.m_nNextPrimaryAttackTick
    if can_shoot and tick_base > next_attack_tick then
        if is_ducking and duck_speed >= 8 then
            engine.execute_client_cmd("-duck")
            is_ducking = false
        end
    elseif not is_ducking and (duck_offset >= 0 or duck_offset == -18 or tick_base < next_attack_tick) then
        engine.execute_client_cmd("+duck")
        is_ducking = true
    end
end

local function draw_under_crosshair_keybinds_list()
    local screen_size = render.screen_size()
    local screen_center_x = screen_size.x / 2
    local screen_center_y = screen_size.y / 2
    local status_items = {}
    local base_y_offset = 65
        
    if min_dmg_toggle then
        local min_damage_value = min_dmg_toggle and menu_default_override_min_dmg.value or menu_default_min_dmg.value
        table.insert(status_items, {
            text = "min dmg (" .. min_damage_value .. ")",
            font = state_font,
            size = 11
        })
    end

    if menu_ai_peek_enabled.value and ai_peek_toggle then
        table.insert(status_items, {
            text = "ai peek",
            font = state_font,
            size = 11
        })
    end

    if menu_duck_peek_assist_enabled.value and duck_assist_toggle then
        table.insert(status_items, {
            text = "duck assist",
            font = state_font,
            size = 11
        })
    end
        
    for i, item in ipairs(status_items) do
        local y_position = screen_center_y + base_y_offset + ((i - 1) * 12)
        local item_text_size = render.calc_text_size(item.text, item.font, item.size)
        
        render.text(item.text, item.font, 
            vec2_t(screen_center_x - item_text_size.x / 2 + 1, y_position + 1), 
            color_t(0, 0, 0, 1), item.size)
        
        render.text(item.text, item.font, 
            vec2_t(screen_center_x - item_text_size.x / 2, y_position), 
            color_t(1, 1, 1, 1), item.size)
    end
end

local function draw_player_state()
    local display_states = {
        ["landed"] = "landed",
        ["air"] = "~in-air~",
        ["air_duck"] = "~air-ducking~",
        ["crouch_walk"] = "~duck-walking~",
        ["crouch"] = "~ducking~",
        ["walk"] = "~walking~",
        ["stand"] = "~standing~",
        ["unknown"] = "~unknown~"
    }
    
    if current_state ~= "unknown" then
        local screen_size = render.screen_size()
        local screen_center_x = screen_size.x / 2
        local screen_center_y = screen_size.y / 2
        
        local state_text = display_states[current_state] or current_state
        local text_size = render.calc_text_size(state_text, state_font, 12)

        render.text(state_text, state_font, vec2_t(screen_center_x - text_size.x / 2 + 1, screen_center_y + 45 + 1), color_t(0, 0, 0, 1), 12)
        render.text(state_text, state_font, vec2_t(screen_center_x - text_size.x / 2, screen_center_y + 45), color_t(1, 1, 1, 1), 12)
    end
end

-- SKIDDED CUSTOM SCOPE CODE BELOW | credits to n1zex (UID: refund) && SYR (UID: 335676)
local Abs = function(addr, pre, post)
    addr = addr + (pre or 1)
    addr = addr + ffi.sizeof("int") + ffi.cast("int64_t", ffi.cast("int*", addr)[0])
    addr = addr + (post or 0)
    return addr
end;
assert(ffi, "syr1337 hook lib error: ffi is not open, please open ffi");
if not pcall(ffi.sizeof, "struct Thread32Entry") then
        ffi.cdef([[
            typedef struct Thread32Entry {
                uint32_t dwSize;
                uint32_t cntUsage;
                uint32_t th32ThreadID;
                uint32_t th32OwnerProcessID;
                long tpBasePri;
                long tpDeltaPri;
                uint32_t dwFlags;
            } Thread32Entry;
            
            int CloseHandle(void*);
            uint32_t ResumeThread(void*);
            uint32_t GetCurrentThreadId();
            uint32_t SuspendThread(void*);
            uint32_t GetCurrentProcessId();
            void* OpenThread(uint32_t, int, uint32_t);
            void* GetProcAddress(uintptr_t, const char*);
            int Thread32Next(void*, struct Thread32Entry*);
            int Thread32First(void*, struct Thread32Entry*);
            void* CreateToolhelp32Snapshot(uint32_t, uint32_t);
            int VirtualProtect(void*, uint64_t, uint32_t, uint32_t*);
        ]])
end
local vecScreenSize = render.screen_size() * 0.5
local flAnim = 0.1;
local m_bIsScoped = engine.get_netvar_offset("client.dll", "C_CSPlayerPawn", "m_bIsScoped");
local arrHooks = {}
local arrThreads = {}
local NULLPTR = ffi.cast("void*", 0)
local INVALID_HANDLE = ffi.cast("void*", - 1)
local colMain_ = menu_custom_scope_enabled.color_value
local colAlpha = color_t(colMain_.r, colMain_.g, colMain_.b, 0);
local fnDrawScope = Abs(ffi.cast("uintptr_t", find_pattern("client.dll", "E8 ? ? ? ? 80 7C 24 ? ? 74 25")), 1, 0);
local Lerp = function(a, b, t)
    return a + (b - a) * t;
end;
local function Thread(nTheardID)
        local hThread = ffi.C.OpenThread(0x0002, 0, nTheardID)
        if hThread == NULLPTR or hThread == INVALID_HANDLE then
            return false
        end

        return setmetatable({
            bValid = true,
            nId = nTheardID,
            hThread = hThread,
            bIsSuspended = false
        }, {
            __index = {
                Suspend = function(self)
                    if self.bIsSuspended or not self.bValid then
                        return false
                    end

                    if ffi.C.SuspendThread(self.hThread) ~= - 1 then
                        self.bIsSuspended = true
                        return true
                    end

                    return false
                end,

                Resume = function(self)
                    if not self.bIsSuspended or not self.bValid then
                        return false
                    end

                    if ffi.C.ResumeThread(self.hThread) ~= - 1 then
                        self.bIsSuspended = false
                        return true
                    end

                    return false
                end,

                Close = function(self)
                    if not self.bValid then
                        return
                    end

                    self:Resume()
                    self.bValid = false
                    ffi.C.CloseHandle(self.hThread)
                end
            }
        })
end
local function UpdateThreadList()
        arrThreads = {}
        local hSnapShot = ffi.C.CreateToolhelp32Snapshot(0x00000004, 0)
        if hSnapShot == INVALID_HANDLE then
            return false
        end

        local pThreadEntry = ffi.new("struct Thread32Entry[1]")
        pThreadEntry[0].dwSize = ffi.sizeof("struct Thread32Entry")
        if ffi.C.Thread32First(hSnapShot, pThreadEntry) == 0 then
            ffi.C.CloseHandle(hSnapShot)
            return false
        end

        local nCurrentThreadID = ffi.C.GetCurrentThreadId()
        local nCurrentProcessID = ffi.C.GetCurrentProcessId()
        while ffi.C.Thread32Next(hSnapShot, pThreadEntry) > 0 do
            if pThreadEntry[0].dwSize >= 20 and pThreadEntry[0].th32OwnerProcessID == nCurrentProcessID and pThreadEntry[0].th32ThreadID ~= nCurrentThreadID then
                local hThread = Thread(pThreadEntry[0].th32ThreadID)
                if not hThread then
                    for _, pThread in pairs(arrThreads) do
                        pThread:Close()
                    end

                    arrThreads = {}
                    ffi.C.CloseHandle(hSnapShot)
                    return false
                end

                table.insert(arrThreads, hThread)
            end
        end

        ffi.C.CloseHandle(hSnapShot)
        return true
end
local function SuspendThreads()
        if not UpdateThreadList() then
            return false
        end

        for _, hThread in pairs(arrThreads) do
            hThread:Suspend()
        end

        return true
end
local function ResumeThreads()
        for _, hThread in pairs(arrThreads) do
            hThread:Resume()
            hThread:Close()
        end
end
local function CreateHook(pTarget, pDetour, szType)
        assert(type(pDetour) == "function", "syr1337 hook lib error: invalid detour function")
        assert(type(pTarget) == "cdata" or type(pTarget) == "number" or type(pTarget) == "function", "syr1337 hook lib error: invalid target function")
        if not SuspendThreads() then
            ResumeThreads()
            print("syr1337 hook lib error: failed suspend threads")
            return false
        end

        local arrBackUp = ffi.new("uint8_t[14]")
        local pTargetFn = ffi.cast(szType, pTarget)
        local arrShellCode = ffi.new("uint8_t[14]", {
            0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        })

        local __Object = {
            bValid = true,
            bAttached = false,
            pBackup = arrBackUp,
            pTarget = pTargetFn,
            pOldProtect = ffi.new("uint32_t[1]")
        }

        ffi.copy(arrBackUp, pTargetFn, ffi.sizeof(arrBackUp))
        ffi.cast("uintptr_t*", arrShellCode + 0x6)[0] = ffi.cast("uintptr_t", ffi.cast(szType, function(...)
            local bSuccessfully, pResult = pcall(pDetour, __Object, ...)
            if not bSuccessfully then
                __Object:Remove()
                print(("[syr1337 hook lib]: unexception runtime error -> %s"):format(pResult))
                return pTargetFn(...)
            end

            return pResult
        end))

        __Object.__index = setmetatable(__Object, {
            __call = function(self, ...)
                if not self.bValid then
                    return nil
                end

                self:Detach()
                local bSuccessfully, pResult = pcall(self.pTarget, ...)
                if not bSuccessfully then
                    self.bValid = false
                    print(("[syr1337 hook lib]: runtime error -> %s"):format(pResult))
                    return nil
                end

                self:Attach()
                return pResult
            end,

            __index = {
                Attach = function(self)
                    if self.bAttached or not self.bValid then
                        return false
                    end

                    self.bAttached = true
                    ffi.C.VirtualProtect(self.pTarget, ffi.sizeof(arrBackUp), 0x40, self.pOldProtect)
                    ffi.copy(self.pTarget, arrShellCode, ffi.sizeof(arrBackUp))
                    ffi.C.VirtualProtect(self.pTarget, ffi.sizeof(arrBackUp), self.pOldProtect[0], self.pOldProtect)
                    return true
                end,

                Detach = function(self)
                    if not self.bAttached or not self.bValid then
                        return false
                    end

                    self.bAttached = false
                    ffi.C.VirtualProtect(self.pTarget, ffi.sizeof(arrBackUp), 0x40, self.pOldProtect)
                    ffi.copy(self.pTarget, self.pBackup, ffi.sizeof(arrBackUp))
                    ffi.C.VirtualProtect(self.pTarget, ffi.sizeof(arrBackUp), self.pOldProtect[0], self.pOldProtect)
                    return true
                end,

                Remove = function(self)
                    if not self.bValid then
                        return false
                    end

                    SuspendThreads()
                    self:Detach()
                    ResumeThreads()
                    self.bValid = false
                end
            }
        })

        __Object:Attach()
        table.insert(arrHooks, __Object)
        ResumeThreads()
        return __Object
end
local function customeScope()
    local pLocalPawn = entitylist.get_local_player_pawn();
    if not pLocalPawn then return end;

    local health = pLocalPawn.m_iHealth
    if not health or health <= 0 then return end;

    menu.misc_removals = bit32.band(menu.misc_removals, bit32.bnot(bit32.lshift(1, 3)))

    local bIsScoped = ffi.cast("bool*", pLocalPawn[m_bIsScoped])[0];
    local colMain = colMain_;
    flAnim = Lerp(flAnim, bIsScoped and 1 or 0, 20 * render.frame_time());
    local flOffset = menu_custom_scope_offset.value * flAnim;
    local flLength = menu_custom_scope_length.value * flAnim;
    local sum = (flOffset + flLength);
    if flAnim > 0.001 then
        render.rect_filled_fade(vec2_t(vecScreenSize.x - sum, vecScreenSize.y), vec2_t(vecScreenSize.x - flOffset, vecScreenSize.y + 1), colAlpha, colMain, colMain, colAlpha);
        render.rect_filled_fade(vec2_t(vecScreenSize.x + flOffset, vecScreenSize.y), vec2_t(vecScreenSize.x + sum, vecScreenSize.y + 1), colMain, colAlpha, colAlpha, colMain);
        render.rect_filled_fade(vec2_t(vecScreenSize.x, vecScreenSize.y + flOffset), vec2_t(vecScreenSize.x + 1, vecScreenSize.y + sum), colMain, colMain, colAlpha, colAlpha);
        render.rect_filled_fade(vec2_t(vecScreenSize.x, vecScreenSize.y - sum), vec2_t(vecScreenSize.x + 1, vecScreenSize.y - flOffset), colAlpha, colAlpha, colMain, colMain);
    end
end

CreateHook(fnDrawScope, function(pObject, pRcx, pUnk) end, "void(__fastcall*)(void*, void*)")
register_callback("unload", function() for _, pObject in pairs(arrHooks) do pObject:Remove() end end)

local function auto_thirdperson_spectate()
    local local_player_controller = entitylist.get_local_player_controller()
    if not local_player_controller then return end
    
    local local_pawn = entitylist.get_local_player_pawn()
    local is_spectating = not local_pawn or (local_pawn and local_pawn.m_iHealth and local_pawn.m_iHealth <= 0)
    if is_spectating then
        engine.execute_client_cmd("spec_mode 3")
    end
end

local function apply_custom_fov()
    local m_iDesiredFOV = engine.get_netvar_offset("client.dll", "CBasePlayerController", "m_iDesiredFOV")
    local local_player_controller = entitylist.get_local_player_controller()
    if local_player_controller then
        ffi.cast("int*", local_player_controller[m_iDesiredFOV])[0] = menu_fov_value.value
    end
end

local font = render.setup_font("C:/Windows/Fonts/verdana.ttf", 25)
local small_font = render.setup_font("C:/Windows/Fonts/verdana.ttf", 12)

minimum_distance_to_draw = menu_wallbang_helper_minimum_distance_to_draw.value

local state = {
    locations = {},
    current_map = "",
    menu_open = false,
    loaded = false
}

local function load_locations()
    wallbangs_file_path = "nix\\scripts\\" .. wallbang_helper_files[menu_wallbang_helper_file.value]
    local file = io.open(wallbangs_file_path, "r")
    if not file then
        print("[Singularity:WallbangHelper] Failed to load config file (" .. wallbang_helper_files[menu_wallbang_helper_file.value] .. "). Please select a different one from the dropdown!")
        return false
    end
    
    local content = file:read("*all")
    file:close()
    
    -- Simple JSON parsing function (Thanks Claude, god bless AI!)
    local function parse_json_value(str, pos)
        -- Skip whitespace
        pos = str:find("[^%s]", pos) or pos
        
        local first = str:sub(pos, pos)
        if first == "{" then -- Object
            local obj = {}
            local key, value
            pos = pos + 1
            
            -- Skip initial whitespace
            pos = str:find("[^%s]", pos) or pos
            
            -- Check for empty object
            if str:sub(pos, pos) == "}" then
                return obj, pos + 1
            end
            
            while true do
                -- Parse key (should be a string)
                key, pos = parse_json_value(str, pos)
                
                -- Skip whitespace to colon
                pos = str:find("[^%s]", pos) or pos
                
                -- Expect colon
                if str:sub(pos, pos) ~= ":" then
                    error("Expected colon at position " .. pos)
                end
                pos = pos + 1
                
                -- Parse value
                value, pos = parse_json_value(str, pos)
                
                -- Store key-value pair
                obj[key] = value
                
                -- Skip whitespace to comma or closing brace
                pos = str:find("[^%s]", pos) or pos
                
                local c = str:sub(pos, pos)
                if c == "}" then
                    return obj, pos + 1
                elseif c == "," then
                    pos = pos + 1
                else
                    error("Expected comma or closing brace at position " .. pos)
                end
                
                -- Skip whitespace after comma
                pos = str:find("[^%s]", pos) or pos
                
                -- Check for closing brace after comma (trailing comma case)
                if str:sub(pos, pos) == "}" then
                    return obj, pos + 1
                end
            end
        elseif first == "[" then -- Array
            local arr = {}
            local value
            pos = pos + 1
            
            -- Skip initial whitespace
            pos = str:find("[^%s]", pos) or pos
            
            -- Check for empty array
            if str:sub(pos, pos) == "]" then
                return arr, pos + 1
            end
            
            while true do
                -- Parse value
                value, pos = parse_json_value(str, pos)
                
                -- Add to array
                table.insert(arr, value)
                
                -- Skip whitespace to comma or closing bracket
                pos = str:find("[^%s]", pos) or pos
                
                local c = str:sub(pos, pos)
                if c == "]" then
                    return arr, pos + 1
                elseif c == "," then
                    pos = pos + 1
                else
                    error("Expected comma or closing bracket at position " .. pos)
                end
                
                -- Skip whitespace after comma
                pos = str:find("[^%s]", pos) or pos
                
                -- Check for closing bracket after comma (trailing comma case)
                if str:sub(pos, pos) == "]" then
                    return arr, pos + 1
                end
            end
        elseif first == '"' then -- String
            local endPos = pos + 1
            local escaped = false
            
            while true do
                local c = str:sub(endPos, endPos)
                if c == "" then
                    error("Unterminated string at position " .. pos)
                elseif c == "\\" then
                    escaped = not escaped
                elseif c == '"' and not escaped then
                    break
                else
                    escaped = false
                end
                endPos = endPos + 1
            end
            
            -- Extract string and handle escape sequences
            local strValue = str:sub(pos + 1, endPos - 1)
            strValue = strValue:gsub('\\"', '"'):gsub("\\\\", "\\"):gsub("\\n", "\n"):gsub("\\t", "\t")
            
            return strValue, endPos + 1
        elseif first:match("[%-%d]") then -- Number
            local endPos = str:find("[^%d%-%+%.eE]", pos) or #str + 1
            local numStr = str:sub(pos, endPos - 1)
            return tonumber(numStr), endPos
        elseif str:sub(pos, pos + 3) == "true" then -- Boolean true
            return true, pos + 4
        elseif str:sub(pos, pos + 4) == "false" then -- Boolean false
            return false, pos + 5
        elseif str:sub(pos, pos + 3) == "null" then -- Null
            return nil, pos + 4
        else
            error("Unexpected character at position " .. pos .. ": " .. first)
        end
    end
    
    local function parse_json(jsonStr)
        local result, _ = parse_json_value(jsonStr, 1)
        return result
    end
    
    local success, parsed
    success, parsed = pcall(function()
        return parse_json(content)
    end)
    
    if not success or not parsed then
        print("[Singularity:WallbangHelper] Failed to parse config file: " .. (parsed or "unknown error"))
        return false
    end
    
    local locations_array = {}
    for id, location in pairs(parsed) do
        location.id = id
        table.insert(locations_array, location)
    end
    
    state.locations = locations_array
    state.loaded = true
    print("[Singularity:WallbangHelper] Loaded " .. #state.locations .. " locations")
    return true
end

local function draw_wallbangs()
    local local_player = entitylist.get_local_player_pawn()
    if not local_player then return end

    local health = local_player.m_iHealth
    if not health or health <= 0 then return end;
    
    local current_map = engine.get_level_name()
    if current_map ~= state.current_map then
        state.current_map = current_map
        print("[Singularity:WallbangHelper] Current Map: " .. current_map)
    end
    
    local local_pos = local_player.m_pGameSceneNode.m_vecAbsOrigin
    
    local weapon_entity = local_player.m_pWeaponServices.m_hActiveWeapon
    if not weapon_entity then return end
    
    local weapon_entity_str = tostring(weapon_entity)
    local weapon_name = ""
    
    if weapon_entity_str then
        -- Extract just the first part before any comma (thanks AI, regex is annoying)
        weapon_name = weapon_entity_str:match("^C_Weapon([^,]+)") or 
                        weapon_entity_str:match("^C_([^,]+)") or
                        weapon_entity_str
        
        weapon_name = weapon_name:gsub("^C_Weapon", ""):gsub("^C_", "")
    end
    
    local weapon_type = ""
    weapon_name = weapon_name:lower()
    
    if weapon_name:find("awp") then
        weapon_type = "awp"
    elseif weapon_name:find("ssg08") or weapon_name:find("scout") then
        weapon_type = "scout"
    elseif weapon_name:find("scar20") or weapon_name:find("g3sg1") then
        weapon_type = "auto"
    elseif weapon_name:find("revolver") then
        weapon_type = "revolver"
    end
    
    if weapon_type == "" then
        return
    end
    
    for _, location in ipairs(state.locations) do
        if location.map == current_map then
            if not location.from or not location.from.position or not location.to or not location.to.position then
                goto continue
            end
            
            if #location.from.position < 3 or #location.to.position < 3 then
                goto continue
            end
            
            local weapon_supported = false
            if location.weapon then
                for _, supported_weapon in ipairs(location.weapon) do
                    if supported_weapon == weapon_type then
                        weapon_supported = true
                        break
                    end
                end
                
                if not weapon_supported then
                    goto continue
                end
            end
            
            local from_pos = vec3_t(
                location.from.position[1], 
                location.from.position[2], 
                location.from.position[3]
            )
            
            local to_pos = vec3_t(
                location.to.position[1], 
                location.to.position[2], 
                location.to.position[3]
            )
            
            local reference_point_1
            local reference_point_2
            if location.reverse == true then
                reference_point_1 = from_pos
                reference_point_2 = to_pos
            else
                reference_point_1 = from_pos
                reference_point_2 = to_pos
            end
            
            local distance_1 = local_pos:dist_to(reference_point_1)
            local distance_2 = local_pos:dist_to(reference_point_2)
            
            if (distance_1 <= minimum_distance_to_draw) or (distance_2 <= minimum_distance_to_draw) then
                local line_color
                if location.reverse == true then
                    local distance_from = local_pos:dist_to(from_pos)
                    local distance_to = local_pos:dist_to(to_pos)
                    
                    if distance_to < distance_from then
                        line_color = Wallbang_Helper_Settings.reverse_color_to
                    else
                        line_color = Wallbang_Helper_Settings.reverse_color_from
                    end
                else
                    line_color = Wallbang_Helper_Settings.normal_color
                end
                
                local screen_from = render.world_to_screen(from_pos)
                local screen_to = render.world_to_screen(to_pos)
                
                if screen_from and screen_to then
                    render.line(screen_from, screen_to, line_color, Wallbang_Helper_Settings.line_width)
                    
                    if location.reverse then
                        local tick_size = 9
                        render.line(
                            vec2_t(screen_from.x - tick_size, screen_from.y), 
                            vec2_t(screen_from.x, screen_from.y + tick_size), 
                            line_color, 
                            2
                        )
                        render.line(
                            vec2_t(screen_from.x, screen_from.y + tick_size), 
                            vec2_t(screen_from.x + tick_size, screen_from.y - tick_size), 
                            line_color, 
                            2
                        )
                        
                        local cross_size = 6
                        render.line(
                            vec2_t(screen_to.x - cross_size, screen_to.y - cross_size), 
                            vec2_t(screen_to.x + cross_size, screen_to.y + cross_size), 
                            line_color, 
                            2
                        )
                        render.line(
                            vec2_t(screen_to.x - cross_size, screen_to.y + cross_size), 
                            vec2_t(screen_to.x + cross_size, screen_to.y - cross_size), 
                            line_color, 
                            2
                        )
                    else
                        render.circle_fade(screen_from, Wallbang_Helper_Settings.endpoint_radius, line_color, color_t(0, 0, 0, 0))
                        render.circle_fade(screen_to, Wallbang_Helper_Settings.endpoint_radius, line_color, color_t(0, 0, 0, 0))
                    end
                end
                
                if location.to.radius and type(location.to.radius) == "number" then
                    local radius = location.to.radius
                    local segments = 30
                    local prev_point = nil
                    
                    for i = 0, segments do
                        local angle = (i / segments) * 2 * math.pi
                        local x = to_pos.x + radius * math.cos(angle)
                        local y = to_pos.y + radius * math.sin(angle)
                        
                        local point_pos = vec3_t(x, y, to_pos.z)
                        local screen_point = render.world_to_screen(point_pos)
                        
                        if screen_point and prev_point then
                            render.line(prev_point, screen_point, line_color, Wallbang_Helper_Settings.line_width)
                        end
                        
                        prev_point = screen_point
                    end
                end
                
                local segment_count = 20
                local prev_screen = nil
                
                for i = 0, segment_count do
                    local fraction = i / segment_count
                    local segment_pos = vec3_t(
                        from_pos.x + (to_pos.x - from_pos.x) * fraction,
                        from_pos.y + (to_pos.y - from_pos.y) * fraction,
                        from_pos.z + (to_pos.z - from_pos.z) * fraction
                    )
                    
                    local segment_screen = render.world_to_screen(segment_pos)
                    if segment_screen and prev_screen then
                        render.line(prev_screen, segment_screen, line_color, Wallbang_Helper_Settings.line_width)
                    end
                    prev_screen = segment_screen
                end
            end
            
            ::continue::
        end
    end
end

local function wallbang_helper()
    if not state.loaded then
        load_locations()
    end
    
    draw_wallbangs()
end

local function is_utility(weapon_name)
    if not weapon_name then return false end
    
    weapon_name = weapon_name:lower()
    return weapon_name:find("flash") or 
            weapon_name:find("smoke") or 
            weapon_name:find("grenade") or 
            weapon_name:find("molotov") or 
            weapon_name:find("decoy") or 
            weapon_name:find("incendiary")
end

local prev_thirdperson_state = false
local was_holding_utility = false

local function firstperson_on_utilities()
    local local_player = entitylist.get_local_player_pawn()
    if not local_player then return end

    local health = local_player.m_iHealth
    if not health or health <= 0 then return end;
    
    local weapon_entity = local_player.m_pWeaponServices.m_hActiveWeapon
    if not weapon_entity then return end
    
    local weapon_entity_str = tostring(weapon_entity)
    local is_holding_utility = is_utility(weapon_entity_str)
    
    if is_holding_utility and not was_holding_utility then
        prev_thirdperson_state = menu.misc_thirdperson
        menu.misc_thirdperson = false
    elseif not is_holding_utility and was_holding_utility then
        menu.misc_thirdperson = prev_thirdperson_state
    end
    
    was_holding_utility = is_holding_utility
end

-- SKIDDED AI PEEK CODE BELOW | credits to @dfgfgddfggdf_62135 on Discord (Nebula Ai peek.lua)
ffi.cdef[[
    short GetAsyncKeyState(int vKey);
    void keybd_event(unsigned char bVk, unsigned char bScan, unsigned long dwFlags, unsigned long dwExtraInfo);
]]

ai_peek_toggle = false
local ai_peek_toggle_last = false
local ai_peek_state = "idle"
local ai_peek_dir = 0
local ai_peek_start_pos = nil
local ai_view_angles = angle_t(0, 0, 0)
local ai_bones = {6, 4, 0} -- head, chest, pelvis
local ai_sqrt = math.sqrt
local ai_min = math.min

local function ai_press_key(vk) ffi.C.keybd_event(vk, 0, 0, 0) end
local function ai_release_key(vk) ffi.C.keybd_event(vk, 0, 2, 0) end

local function ai_get_eye_position(ent)
    local abs = ent:get_abs_origin()
    local vo = ffi.cast("struct Vector*", ffi.cast("uintptr_t", ent[0]) + vecViewOffset)[0]
    return vec3_t(abs.x + vo.x, abs.y + vo.y, abs.z + vo.z)
end

local function ai_get_bone_pos(ent, bone)
    local node = ffi.cast("uintptr_t*", ffi.cast("uintptr_t", ent[0]) + pGameSceneNode)[0]
    local bm = ffi.cast("uintptr_t*", node + modelState + pBoneMatrix)[0]
    local p = ffi.cast("struct Vector*", bm + (bone * bone_spacing))[0]
    return vec3_t(p.x, p.y, p.z)
end

local function ai_vec_sub(a, b) return vec3_t(a.x - b.x, a.y - b.y, a.z - b.z) end
local function ai_vec_length(v) return ai_sqrt(v.x * v.x + v.y * v.y + v.z * v.z) end

local last_ai_peek_key_state = false
local function handle_ai_key_state()
    local ai_peek_key_pressed = is_key_pressed(menu_ai_peek_key.value)

    if menu_ai_peek_key.mode == 2 then -- Toggle mode
        if ai_peek_key_pressed and not last_ai_peek_key_state then
            ai_peek_toggle = not ai_peek_toggle
        end
    else -- Hold mode
        ai_peek_toggle = is_key_held(menu_ai_peek_key.value)
    end

    last_ai_peek_key_state = ai_peek_key_pressed
end

register_callback("override_view", function(view)
    ai_view_angles = view.angles
end)

local function ai_peek_on_paint()
    handle_ai_key_state()
    
    if not menu_ai_peek_enabled.value then
        if ai_peek_state ~= "idle" then
            if ai_peek_dir == -1 then ai_release_key(0x41) else ai_release_key(0x44) end
            ai_peek_state, ai_peek_start_pos = "idle", nil
        end
        return
    end

    local ply = entitylist.get_local_player_pawn()
    local ctrl = entitylist.get_local_player_controller()
    if not ply or not ctrl then
        return
    end

    ai_peek_active = ai_peek_toggle

    if not ai_peek_active then
        if ai_peek_state ~= "idle" then
            if ai_peek_dir == -1 then ai_release_key(0x41) else ai_release_key(0x44) end
            ai_peek_state, ai_peek_start_pos = "idle", nil
        end
        return
    end

    if ply.m_lifeState ~= 0 or not ply.m_fFlags or bit.band(ply.m_fFlags, 1) ~= 1 then
        if ai_peek_state ~= "idle" then
            if ai_peek_dir == -1 then ai_release_key(0x41) else ai_release_key(0x44) end
            ai_peek_state, ai_peek_start_pos = "idle", nil
        end
        return
    end

    local wep = ply.m_pWeaponServices.m_hActiveWeapon
    if wep and (wep.m_bInReload or (wep.m_nNextPrimaryAttackTick and ctrl.m_nTickBase < wep.m_nNextPrimaryAttackTick)) then
        if ai_peek_state ~= "idle" then
            if ai_peek_dir == -1 then ai_release_key(0x41) else ai_release_key(0x44) end
            ai_peek_state, ai_peek_start_pos = "idle", nil
        end
        return
    end

    local eye_pos = ai_get_eye_position(ply)
    local _, rvec = math.angle_vectors(ai_view_angles)
    local left_org = eye_pos - rvec * menu_ai_peek_offset.value
    local right_org = eye_pos + rvec * menu_ai_peek_offset.value

    local left_ok, right_ok = false, false

    min_damage_value = min_dmg_toggle and menu_default_override_min_dmg.value or menu_default_min_dmg.value

    entitylist.get_entities("C_CSPlayerPawn", function(target)
        if not target or target == ply or not target:is_alive() or ply:is_teammate(target) or target.m_iTeamNum == 0 then return end
        
        local need = ai_min(min_damage_value, target.m_iHealth)
        for _, b in ipairs(ai_bones) do
            local p = ai_get_bone_pos(target, b)
            if b == 6 then p.z = p.z + 4 end
            local hl = engine.trace_bullet(ply, left_org, p)
            local hr = engine.trace_bullet(ply, right_org, p)
            if visualize then render.point(p, (hl and hl>=need) or (hr and hr>=need)) end
            if hl and hl >= need then left_ok = true end
            if hr and hr >= need then right_ok = true end
        end
    end)

    local peek_limit_units = menu_ai_peek_limit.value * (1 / 0.0254)

    if ai_peek_state == "idle" then
        if ai_peek_active and (left_ok or right_ok) then
            ai_peek_state = "peeking"
            ai_peek_dir = left_ok and -1 or 1
            ai_peek_start_pos = ply:get_abs_origin()
            if ai_peek_dir == -1 then ai_press_key(0x41) else ai_press_key(0x44) end
        end
    elseif ai_peek_state == "peeking" then
        if not ai_peek_active then
            if ai_peek_dir == -1 then ai_release_key(0x41) else ai_release_key(0x44) end
            ai_peek_state, ai_peek_start_pos = "idle", nil
        else
            local moved_dist = ai_vec_length(ai_vec_sub(ply:get_abs_origin(), ai_peek_start_pos))
            if moved_dist >= peek_limit_units then
                if ai_peek_dir == -1 then ai_release_key(0x41) else ai_release_key(0x44) end
                ai_peek_state, ai_peek_start_pos = "idle", nil
            end
        end
    end
end

local last_pitch_value = nil

print("[Singularity] Script loaded!")

register_callback("paint", function()
    if menu_anti_aim_pitch.value ~= last_pitch_value then
        menu.ragebot_anti_aim_pitch = menu_anti_aim_pitch.value - 1
    end
    last_pitch_value = menu_anti_aim_pitch.value

    update_min_dmg_toggle()

    check_player_state()

    is_wasd_pressed()

    if menu_indicators.value[1] then
        draw_player_state()
    end

    if menu_indicators.value[3] then
        draw_under_crosshair_keybinds_list()
    end

    anti_aim_handler()

    if menu_ai_peek_enabled.value then
        ai_peek_on_paint()
    end

    if menu_duck_peek_assist_enabled then
        handle_duck_assist()
    end

    if menu_slowdown_indicator.value then
        toDraw()
    end

    if menu_adaptive_auto_strafer_enabled.value then
        adaptive_autostrafe()
    end

    if menu_firstperson_on_utilities.value then
        firstperson_on_utilities()
    end

    prev_wallbangs_file_path = wallbangs_file_path
    if prev_wallbangs_file_path ~= "nix\\scripts\\" .. wallbang_helper_files[menu_wallbang_helper_file.value] then
        load_locations()
        wallbangs_file_path = "nix\\scripts\\" .. wallbang_helper_files[menu_wallbang_helper_file.value]
    end
    if menu_wallbang_helper_enabled.value then
        wallbang_helper()
    end

    if menu_0_pitch_on_land_enabled.value then
        zero_pitch_on_land()
    end

    if menu_air_flick_enabled.value then
        air_flick()
    end

    if menu_watermark_enabled.value then
        draw_watermark()
    end

    if menu_disable_ragebot_in_air_enabled.value then
        disable_ragebot_in_air()
    end

    if menu_custom_scope_enabled.value then
        customeScope()
    end

    if menu_thirdperson_distance then
        engine.execute_client_cmd("cam_idealdist " .. menu_thirdperson_distance.value)
    end

    if menu_indicators.value[2] then
        manualaaind.draw_indicator()
    end

    if menu_auto_thirdperson_spectate_enabled.value then
        auto_thirdperson_spectate()
    end

    if menu_custom_menu_color_enabled.value then
        menu_accents_color = menu_custom_menu_color_enabled.color_value
    else
        menu_accents_color = color_t(161/255, 110/255, 228/255, 1)
    end

    apply_custom_fov()
    handle_keyboard_input()
end)

loadSettings()

register_callback("unload", function()
    saveSettings()
    bClear = true;
    if is_ducking then engine.execute_client_cmd("-duck") end
    menu.ragebot_anti_aim_base_yaw_offset = default_yaw_offset
    menu.ragebot_auto_strafer = default_auto_strafer

    ai_release_key(0x41)
    ai_release_key(0x44)

    local m_iDesiredFOV = engine.get_netvar_offset("client.dll", "CBasePlayerController", "m_iDesiredFOV")
    local local_player_controller = entitylist.get_local_player_controller()
    if local_player_controller then
        ffi.cast("int*", local_player_controller[m_iDesiredFOV])[0] = 90
    end

    print("[Singularity] Script unloaded!")
end)
Назад
Сверху