-- TURBOBOT 386 NTLDR

include("includes/enum/ac_ob1.lua")
require("eradicate")

concommand.Add("mh_unlock", function()
	teh.ToggleFlag("sv_cheats", 8192)
	teh.ToggleFlag("host_timescale", 8192)
end)

concommand.Add("mh_toggleflag", function(_,__,args)
	teh.ToggleFlag(args[1], tonumber(args[2]))
end)

concommand.Add("mh_keypad", function()
   include("kp.lua")
end)

print("*presses the turbo button on your 386 pc*")

local vars = {
	abEnabled = CreateClientConVar("mh_ab_enabled", "1", true, false),
	abFFA = CreateClientConVar("mh_ab_ffa", "0",  true, false),
	abNospread = CreateClientConVar("mh_ab_nospread", "0",  true, false),
	abPriority = CreateClientConVar("mh_ab_priority", "Closest to crosshair",  true, false),
	abFOV = CreateClientConVar("mh_ab_fov", "90",  true, false),
	abOffset = CreateClientConVar("mh_ab_offset", "0",  true, false),
    abAuto = CreateClientConVar("mh_ab_auto", "0",  true, false),
	
	espEnabled = CreateClientConVar("mh_esp_enabled", "1",  true, false),
	espMode = CreateClientConVar("mh_esp_mode", "Solid Unlit",  true, false),
	espNames = CreateClientConVar("mh_esp_names", "0",  true, false),
	espHealth = CreateClientConVar("mh_esp_health", "0",  true, false),
	espReveal = CreateClientConVar("mh_esp_reveal", "0",  true, false),
	espRevEntity = CreateClientConVar("mh_esp_revent", "ttt_c4 weapon_ttt_knife weapon_ttt_sipistol weapon_ttt_c4 weapon_ttt_push", true, false),
    espFOV = CreateClientConVar("mh_esp_fov", "0", false, false),
	
	rearview = CreateClientConVar("mh_rearview", "0", false, false),
    ulxungag = CreateClientConVar("mh_ungag", "0", false, false) 
}

-- ##################
-- # ui initializer #
-- ##################
hook.Add("Initialize", "\1\2", function()
	dpanel = vgui.Create("DFrame")
	dpanel:SetPos(64,64)
	dpanel:SetSize(256,512)
	dpanel:SetTitle("")
	dpanel:SetDraggable(true)
	dpanel:ShowCloseButton(true)
	dpanel:SetDeleteOnClose(false)
	dpanel:SetVisible(false)

	local psheet = vgui.Create("DPropertySheet")
	psheet:SetParent(dpanel)
	psheet:SetPos(2,22)
	psheet:SetSize(252,488)

	-- aimbot config

	local abform = vgui.Create("DPanelList", psheet)
	abform:SetPadding(8)
	abform:SetSpacing(4)

	local abtoggle = vgui.Create("DCheckBoxLabel")
	abtoggle:SetText("Enabled")
	abtoggle:SetValue(1)
	abtoggle:SetConVar("mh_ab_enabled")
	abform:AddItem(abtoggle)

	local abffa = vgui.Create("DCheckBoxLabel")
	abffa:SetText("Free-for-all")
	abffa:SetConVar("mh_ab_ffa")
	abform:AddItem(abffa)

	local abspread = vgui.Create("DCheckBoxLabel")
	abspread:SetText("NoSpread (buggy)")
	abspread:SetConVar("mh_ab_nospread")
	abform:AddItem(abspread)

	abform:AddItem((function() local _ = vgui.Create("DLabel") _:SetText("Aiming priority:") _:SetFont("DefaultBold") return _ end)())

	local abmode = vgui.Create("DMultiChoice")
	abmode:AddChoice("Closest to crosshair")
    abmode:AddChoice("Closest to crosshair v2")
	abmode:AddChoice("Closest to player")
	abmode:ChooseOptionID(1)
	abmode:SetEditable(false)
	abmode:SetConVar("mh_ab_priority")
	abform:AddItem(abmode)
	
	local abfov = vgui.Create("DNumSlider")
	abfov:SetText("Max FOV")
	abfov:SetMin(5)
	abfov:SetMax(360)
	abfov:SetDecimals(0)
	abfov:SetConVar("mh_ab_fov")
	abform:AddItem(abfov)

	-- esp/chams config

	local visform = vgui.Create("DPanelList", psheet)
	visform:SetPadding(8)
	visform:SetSpacing(4)

	local esptoggle = vgui.Create("DCheckBoxLabel")
	esptoggle:SetText("Enabled")
	esptoggle:SetValue(1)
	esptoggle:SetConVar("mh_esp_enabled")
	visform:AddItem(esptoggle)

	local espnames = vgui.Create("DCheckBoxLabel")
	espnames:SetText("Show player names")
	espnames:SetValue(0)
	espnames:SetConVar("mh_esp_names")
	visform:AddItem(espnames)

	local espweps = vgui.Create("DCheckBoxLabel")
	espweps:SetText("Show player health")
	espweps:SetValue(0)
	espweps:SetConVar("mh_esp_health")
	visform:AddItem(espweps)
	
	local espreveal = vgui.Create("DCheckBoxLabel")
	espreveal:SetText("Reveal custom ents")
	espreveal:SetValue(0)
	espreveal:SetConVar("mh_esp_reveal")
	visform:AddItem(espreveal)
	
	visform:AddItem((function() local _ = vgui.Create("DLabel") _:SetText("Custom ents:") _:SetFont("DefaultBold") return _ end)())
	
	local espent = vgui.Create("DTextEntry")
	espent:SetConVar("mh_esp_revent")
	visform:AddItem(espent)
	
	visform:AddItem((function() local _ = vgui.Create("DLabel") _:SetText("Cham mode:") _:SetFont("DefaultBold") return _ end)())

	local vismode = vgui.Create("DMultiChoice")
	vismode:AddChoice("Solid Unlit")
	vismode:AddChoice("Wireframe")
	vismode:ChooseOptionID(2)
	vismode:SetEditable(false)
	vismode:SetConVar("mh_esp_mode")
	visform:AddItem(vismode)

	-- sheets

	psheet:AddSheet("Aiming", abform, false, false, false, "Automatic aiming configuration")
	psheet:AddSheet("Vision", visform, false, false, false, "Vision enhancement configuration")
end)

concommand.Add("mh_open", function()
	dpanel:SetVisible(true)
	dpanel:MakePopup()
end)

-- ###############
-- # aimbot core #
-- ###############

function math.dist(ax, ay, bx, by)
	local dx, dy = ax-bx, ay-by
	return math.sqrt(dx*dx+dy*dy)
end

local OrigSVA = _R["CUserCmd"].SetViewAngles

local OtherBones = {
	["models/zombie/classic.mdl"] = "ValveBiped.HC_Body_Bone",
	["models/zombie/fast.mdl"] = "ValveBiped.HC_BodyCube",
	["models/zombie/poison.mdl"] = "ValveBiped.Bip01_Spine4"
}
		
local function IsOpponent(p)
	return LocalPlayer():Team() ~= p:Team() or vars.abFFA:GetBool()
end

local AimModes = {
	-- multichoice setconvar sucks
	["Closest to player"] = function(s,b)
		return s:Distance(b)
	end,
	["Closest to crosshair"] = function(s,b)
		--local bs = b:ToScreen()
		--return math.dist(bs.x, bs.y, ScrW()/2, ScrH()/2)
		--return math.acos(b:DotProduct(s))
		local plang = LocalPlayer():GetAngles()
		local ang = (b-s):Angle()
		local dy = math.abs(math.NormalizeAngle(plang.y - ang.y))
		local dp = math.abs(math.NormalizeAngle(plang.p - ang.p))
		return math.sqrt(dy*dy+dp*dp)
	end,
    ["Closest to crosshair v2"] = function(s,b)
        local pang = LocalPlayer():GetAngles()
        local ang = (b-s):Angle()
        return math.acos(
            math.sin(math.rad(pang.p)) * math.sin(math.rad(ang.p)) +
            math.cos(math.rad(pang.p)) * math.cos(math.rad(ang.p)) +
            math.cos(math.rad(ang.y - pang.y)))
    end,
}

local OrigFireBullets = _R["Entity"].FireBullets
local spread = Vector(0,0,0)
_R["Entity"].FireBullets = function(ent, bullet)
	spread = bullet.Spread
	return OrigFireBullets(ent, bullet)
end

local function findTarget() 

	local OptimalBone = false
	
	for _, v in pairs(player.GetAll()) do
		if v ~= LocalPlayer() and v:Alive() and IsOpponent(v) then
		
			local ShootPos = LocalPlayer():GetShootPos()
			local BonePos = v:GetBonePosition(v:LookupBone(OtherBones[v:GetModel()] or "ValveBiped.Bip01_Head1"))
			local BoneDist = AimModes[vars.abPriority:GetString()](ShootPos, BonePos)
			
			if BoneDist < vars.abFOV:GetFloat()/2 then
				local VisTrace = util.TraceLine{start = ShootPos, endpos = BonePos}
				if VisTrace.Entity:IsPlayer() and (not OptimalBone or OptimalBone.dist > BoneDist) then
					OptimalBone = { player = v, pos = BonePos, dist = BoneDist }
				end
			end
			
		end
	end
	return OptimalBone
	
end

local function AimCore(ucmd)
	if vars.rearview:GetBool() then
		local fm, sm = ucmd:GetForwardMove(), ucmd:GetSideMove()
		ucmd:SetForwardMove(-fm)
		ucmd:SetSideMove(-sm)
	end
	
	if ucmd:KeyDown( IN_ATTACK ) and vars.abEnabled:GetBool() or vars.abAuto:GetBool() then
		local optimal = findTarget()
		if optimal then
			optimal.pos = optimal.pos + optimal.player:GetVelocity() * (1/66) - LocalPlayer():GetVelocity() * (1/66)
			optimal.pos = optimal.pos + Vector(0,0,vars.abOffset:GetFloat())
			
			local ShootPos = LocalPlayer():GetShootPos()
			local ShootAng = (optimal.pos - ShootPos):Normalize()
			local offset = ShootAng
			
			if vars.abNospread:GetBool() and teh.GetSpread then
				teh.SetPredictionSeed(ucmd)
				offset = Vector(0,0,0)
				teh.GetSpread(offset, ShootAng, Vector(0,0,0)-spread)
			end
			
         if vars.abAuto:GetBool() then ucmd:SetButtons(ucmd:GetButtons() | IN_ATTACK) end
			OrigSVA(ucmd, offset:Angle())
		end
	end
	
end

hook.Add("CreateMove", "\2\3", AimCore)

-- ############
-- # esp core #
-- ############
local ChamParams = { 
	["$basetexture"] = "models/debug/debugwhite", 
	["$model"] = 1, 
	["$ignorez"] = 1
}
	
local mats = {
	["Solid Unlit"]  = CreateMaterial("chamsolid","UnlitGeneric",ChamParams),
	["Wireframe"] = CreateMaterial("chamwire","Wireframe",ChamParams)
}

local function RevealEntity(e, c)

	SetMaterialOverride(mats[vars.espMode:GetString()])
	render.SetColorModulation(c.r/255, c.g/255, c.b/255)
	render.SetBlend(0.75)
	if vars.espMode:GetString() == "Wireframe" then
		render.SetBlend(1)
	end
	e:DrawModel() 
					
	SetMaterialOverride() 
	render.SetColorModulation(1, 1, 1)
	render.SetBlend(1)
	e:DrawModel()
	
end
	
local function ChamCore()

	if vars.espEnabled:GetBool() then
		render.SuppressEngineLighting(true)
		cam.Start3D( EyePos(), EyeAngles() ) 
			
		for k, v in pairs( player.GetAll() ) do
			if v:Alive() and v:GetMoveType() ~= MOVETYPE_OBSERVER and v:GetMoveType() ~= MOVETYPE_NONE then 
				local c = team.GetColor(v:Team())
				RevealEntity(v, c)
			end
		end
		cam.End3D()
		render.SuppressEngineLighting(false)
	end
	
end

hook.Add("RenderScreenspaceEffects", "\3\4", ChamCore)

--hook.Add("PostDrawOpaqueRenderables", "\3\4", ChamCore)

local realIsAdmin = _R["Player"].IsAdmin -- some admin mods hook isadmin and totally break it

local function lowlim( a, b )
	if a < b then
		return b
	end
	return a
end

local function ESPCore( )

	if vars.espNames:GetBool() then
		for k,v in pairs(player:GetAll()) do
			if v:Alive() and v ~= LocalPlayer() and v:GetMoveType() ~= MOVETYPE_OBSERVER and v:GetMoveType() ~= MOVETYPE_NONE then
				local BonePos = v:GetBonePosition( v:LookupBone("ValveBiped.Bip01_Head1") )
				local HeadScreen = (BonePos+Vector(0,0,8)):ToScreen()
					
				local namecol = (function(ply) if realIsAdmin and realIsAdmin(ply) then return Color(255,255,0,255) else return Color(255,255,255,255) end end)(v) 
				draw.SimpleTextOutlined(string.Left(v:Name(), 16), "DefaultSmall", HeadScreen.x, HeadScreen.y-10, namecol, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, 1, Color(0,0,0,255))
				
				if vars.espHealth:GetBool() then
					local hp = (function(n) if n < 0 then return 0 else return n end end)(v:Health()) 
					draw.SimpleTextOutlined(hp, "DefaultSmall", HeadScreen.x, HeadScreen.y, Color(255,hp*2.55,hp*2.55,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, 1, Color(0,0,0,255))
				end
			end
		end
	end 
	
	if vars.espReveal:GetBool() then
		for _,e in pairs(string.Explode(" ", vars.espRevEntity:GetString())) do
			for k,v in pairs(ents.FindByClass(e)) do
				local scr = (v:GetPos()):ToScreen()
				local rad = (LocalPlayer():GetPos()):Distance(v:GetPos())
				rad = lowlim(24-(rad/32), 4)
				
				surface.SetDrawColor(255,128,128,192)
				surface.DrawOutlinedRect( scr.x-rad, scr.y-rad, rad*2, rad*2)
				surface.SetDrawColor(170,0,0,192)
				surface.DrawOutlinedRect( scr.x-rad+2, scr.y-rad+2, rad*2-4, rad*2-4)
			end
		end
	end
	
end

hook.Add( "HUDPaint", "\4\5", ESPCore )

-- sometimes, shitty admin scripts break the esp.
concommand.Add("mh_esp_rehook", function()
	hook.Add("HUDPaint", "\4\5", ESPCore)
end)

--- ttt stuff

local GetWeps = _R['Player'].GetWeapons

concommand.Add("mh_owners", function(_,__,args)
	for k,v in pairs(ents.FindByClass(args[1])) do
		print(v:EntIndex() .. " -> " .. v:GetOwner():Name())
	end
end)

concommand.Add("mh_turn180", function() LocalPlayer():SetEyeAngles(LocalPlayer():EyeAngles()+Angle(0,180,0)) end)

hook.Add("CalcView", "\5\6", function(_,a,b,c)
    local fov = vars.espFOV:GetInt()
    c = (fov > 0 and fov) or c
	if vars.rearview:GetBool() then b = b + Angle(0,180,0) end
	return GAMEMODE:CalcView(_,a,b,c)
end)

local origBool = _R["ConVar"].GetBool
_R["ConVar"].GetBool = function(cvar)
	if cvar:GetName() == "sv_cheats" then return false end
	return origBool(cvar)
end

hook.Add("Think", "\6\9", function()
    if ulx and ulx.gagUser and vars.ulxungag:GetBool() then 
        ulx.gagUser( false )
        hook.Remove( "PlayerBindPress", "ULXGagForce" )
        timer.Destroy( "GagLocalPlayer" )
    end
end)