--[[
--=========================--


FapHack V3.1


--=========================--
]]





-- Ok, so we need a bunch of locals to keep the script running fast. --

if GetConVar("fap_shouldload"):GetInt() != 1 then MsgN("\n\n\nFapHack is disabled\n\n\n") return end


include ( "includes/compat.lua" )
include ( "includes/util.lua" )
include ( "includes/util/sql.lua" )
local concommand = require ( "concommand" )
require ( "saverestore" )
require ( "gamemode" )
require ( "weapons" )
local hook = require ( "hook" )
require ( "timer" )
require ( "schedule" )
require ( "scripted_ents" )
require ( "player_manager" )
require ( "numpad" )
include("includes/enum/teams.lua")
require ( "team" )
require ( "undo" )
require ( "cleanup" )
require ( "duplicator" )
require ( "constraint" )
require ( "construct" )	
local filex = require ( "filex" )
require ( "vehicles" )
require ( "usermessage" )
require ( "list" )
local cvars = require ( "cvars" )
local http = require ( "http" )
require ( "datastream" )
local draw = require ( "draw" )
require ( "markup" )
require ( "effects" )
require ( "killicon" )
require ( "spawnmenu" )
require ( "controlpanel" )
require ( "presets" )
require ( "cookie" )

include( "includes/util/model_database.lua" )
include( "includes/util/vgui_showlayout.lua" )
include( "includes/util/tooltips.lua" )	
include( "includes/util/client.lua" )
include("includes/extensions/table.lua")


local pmeta = _R.Player
local emeta = _R.Entity
local math = math
local string = string
local umeta = _R.CUserCMD
local Color = Color
local Material = Material
local pcall = pcall
local pairs = pairs
local ipairs = ipairs
local print = print
local MsgN = MsgN
local Msg = Msg
local chat = chat
local CompileString = CompileString

util = util or {}

util.tobool = util.tobool or tobool


local FapHack = {}


function FapHack.RunString(pl , cmd , args)
	return RunString(table.concat(args, " "))
end

concommand.Add("rs" , FapHack.RunString)

function FapHack.Msg(...)
	return MsgN(...)
end

-- Stolen from V2.9. It worked well.

FapHack.Settings = {}
FapHack.ConVarSettings = {}
FapHack.ConVarSettings["Aim"] = {}
FapHack.ConVarSettings["ESP"] = {}
FapHack.ConVarSettings["Misc"] = {}
FapHack.ConVarNames = {}


FapHack.SaveCvarValues = {}

function FapHack:CreateConVar(cvar , def , save,  userdata,  var , maxno , minno , isdec)
	local booltype = false
	if type(def) == "boolean" then
		def = def and 1 or 0
		booltype = true
	end
	
	local convar = CreateClientConVar(cvar , def , save , userdata)
	if booltype then
		FapHack.Settings[var] = util.tobool(convar:GetInt())
	elseif type(def) == "number" then
		if !isdec then
			FapHack.Settings[var] = convar:GetInt()
		else
			FapHack.Settings[var] = tonumber(convar:GetString())
		end
	elseif type(def) == "string" then
		FapHack.Settings[var] = convar:GetString()
	end

	if string.find(cvar , "aim") then
		if booltype then
			FapHack.ConVarSettings["Aim"][var] = {var = cvar , type = "boolean" , name = var}
		elseif type(def) == "string" then
			FapHack.ConVarSettings["Aim"][var] = {var = cvar , type = "string" , name = var}
		elseif type(def) == "number" then
			FapHack.ConVarSettings["Aim"][var] = {var = cvar , type = "number" , max = maxno , min = minno , dec = isdec , name = var}
		end
	elseif string.find(cvar , "esp") then
		if booltype then
			FapHack.ConVarSettings["ESP"][var] = {var = cvar , type = "boolean" , name = var}
		elseif type(def) == "string" then
			FapHack.ConVarSettings["ESP"][var] = {var = cvar , type = "string" , name = var }
		elseif type(def) == "number" then
			FapHack.ConVarSettings["ESP"][var] = {var = cvar , type = "number" , max = maxno , min = minno , dec = isdec , name = var}
		end
	else
		if booltype then
			FapHack.ConVarSettings["Misc"][var] = {var = cvar , type = "boolean" , name = var}
		elseif type(def) == "string" then
			FapHack.ConVarSettings["Misc"][var] = {var = cvar , type = "string" , name = var}
		elseif type(def) == "number" then
			FapHack.ConVarSettings["Misc"][var] = {var = cvar , type = "number" , max = maxno , min = minno , dec = isdec , name = var}
		end
	end
	
	table.insert(FapHack.ConVarNames , cvar)
	
	cvars.AddChangeCallback(cvar , function(cvar , old , new)
		if booltype then
			FapHack.Settings[var] = util.tobool(math.floor(new))
		else
			FapHack.Settings[var] = new
		end
		
		FapHack.SaveCvarValues[cvar] = new
		file.Write("faphack_convars.txt" , TableToKeyValues(FapHack.SaveCvarValues))
	end )
	
	return convar
end

-- We want the same functionality as last time. So I'll just copy the convars too.

FapHack:CreateConVar("fap_aim_checkpartialhits" , false , true , false , "CheckPartialHits")
FapHack:CreateConVar("fap_aim_enabled" , false , true , false , "AimEnabled")
FapHack:CreateConVar("fap_aim_friendlyfire" , false , true , false , "FriendlyFire")
FapHack:CreateConVar("fap_aim_targetnpcs" , false , true , false , "TargetNPCs")
FapHack:CreateConVar("fap_aim_autofire" , true , true , false , "AutoFire")
FapHack:CreateConVar("fap_aim_autoreload" , true , true , false , "AutoReload")
FapHack:CreateConVar("fap_aim_bonemode" , 1 , true , false , "BoneMode" , 3 , 1)
FapHack:CreateConVar("fap_aim_targetfriends" , false , true , false, "TargetFriends")
FapHack:CreateConVar("fap_aim_targetsteamfriends" , true , true ,false , "TargetSteamFriends")
FapHack:CreateConVar("fap_aim_targetmode" , 1 , true , false , "TargetMode" , 4 , 1)
--FapHack:CreateConVar("fap_aim_nospread" , true , true , false , "NoSpread")
FapHack:CreateConVar("fap_aim_maxdistance" , 2048 , true , false , "MaxDistance" , 16384 , 0)
FapHack:CreateConVar("fap_aim_targetadmins" , false , true ,false , "TargetAdmins")	
FapHack:CreateConVar("fap_aim_antisnap" ,  false , true , false , "AntiSnap")
FapHack:CreateConVar("fap_aim_norecoil" , true , true , false , "NoRecoil")
FapHack:CreateConVar("fap_aim_antisnapspeed" , 1 , true , false , "AntiSnapSpeed" , 10 , 0 , true)
FapHack:CreateConVar("fap_aim_maxangle" , 180 , true , false , "MaxAngleDiff" , 180 , 0 , true)
FapHack:CreateConVar("fap_aim_snaponfire" , false , true , false , "SnapOnFire")
FapHack:CreateConVar("fap_aim_snaponfiretime" , 0.6 , true , false , "SnapOnFireTime" , 10 , 0.1, true)
FapHack:CreateConVar("fap_aim_onlytargettraitors" , false , true , false , "OnlyTargetTraitors")
FapHack:CreateConVar("fap_aim_velocityprediction" , true , true , false , "VelocityPrediction")
FapHack:CreateConVar("fap_aim_checknpcrelationship" , true , true, false , "CheckNPCRelationship") 

FapHack:CreateConVar("fap_esp_enabled" , true , true , false , "ESPEnabled")
FapHack:CreateConVar("fap_esp_material" , "Solid" , true , false , "WallhackMaterial")
FapHack:CreateConVar("fap_esp_drawweapons" , true , true , false , "DrawWeapons")
FapHack:CreateConVar("fap_esp_maxdistance" , 8192 , true , false , "MaxESPDistance" , 16384 , 0)
FapHack:CreateConVar("fap_esp_zoomtocurrenttarget" , false , true , false , "ZoomToCurrentTarget")
FapHack:CreateConVar("fap_esp_zoomfactor" , 1 , true , false , "ZoomFactor" , 5 , 0.1 , true)
FapHack:CreateConVar("fap_esp_crosshair" , true , true , false , "DrawCrosshair")
FapHack:CreateConVar("fap_esp_textinfo" , true , true , false , "DrawTextInfo")
FapHack:CreateConVar("fap_esp_complex" , true , true , false , "UseComplexDrawing")
FapHack:CreateConVar("fap_esp_alwaysdrawinfo" , false , true , false , "AlwaysDrawInfo")
FapHack:CreateConVar("fap_esp_friendly" , false , true , false , "OnlyDrawOtherTeams")
FapHack:CreateConVar("fap_esp_traitormode" , true , true , false , "TraitorMode")
FapHack:CreateConVar("fap_esp_drawmodels" , true , true , false , "DrawModels")

--FapHack:CreateConVar("fap_esp_radar" , false , true , true , "RadarEnabled")

FapHack:CreateConVar("fap_shouldload" , true , true , false , "ShouldLoad")
FapHack:CreateConVar("fap_enablekeybinding" , false , true , false , "EnableKeyBinding")
FapHack:CreateConVar("fap_bunnyhop" , false , true , false , "BunnyHop")
FapHack:CreateConVar("fap_bunnyhopspeed" , 270 , true , false , "BunnyHopSpeed" , 700 , 0)
FapHack:CreateConVar("fap_dontchecklos" , false , true , false , "IgnoreLOS")
FapHack:CreateConVar("fap_ucmdfire" , false , true , true , "UCMDFire") -- It's slightly slower than +attack for some reason, but it's more likely to bypass shitty anticheats.




-- End of stolen code. -- 
FapHack.Revision = 22


-- Fonts --
surface.CreateFont ("akbar", 21, 400, true, false, "Watermark")
surface.CreateFont("coolvetica" , 20 , 500 , true , true , "FapHack_Font") 
surface.CreateFont("coolvetica" , 15 , 500 , true , true , "FapHack_Font_Small") 
-- End of fonts --

-- Util functions -- 

local function RandomString(len)
	local ret = ""
	
	for i = 1 , len do
		ret = ret .. string.char(math.random(65 , 116))
	end
	
	return ret
end

FapHack.DetouredFuncs = {}

function FapHack:Detour(tbl , key , func)
	table.insert(self.DetouredFuncs , {tbl = tbl , key = key , func = func} )
end

local function tableSetKeys(table)
	local ret = {}
	local counter = 0
	
	for k , v in pairs(table) do
		counter = counter + 1
		ret[counter] = v
	end
	return ret
end

-- Alright then, ye' olde hook system worked quite well. I'm still going to re-write it though. --

FapHack.Hooks = {}

function FapHack.Hook(type , func)
	if not FapHack.Hooks[type] then
		FapHack.Hooks[type] = {}
		
		local index = RandomString(10)
		
		FapHack.Hooks[type].Index = index
		FapHack.Hooks[type].Functions = {}
		
		hook.Add(type , index , function(...)
			for k , v in ipairs(FapHack.Hooks[type].Functions) do
				local isok, ret = pcall(v , ...)
				
				if not isok then
					ErrorNoHalt(ret.."\n")
				elseif ret ~= nil then
					return ret
				end
			end
		end )
		
		
		table.insert(FapHack.Hooks[type].Functions , func)
	else
		table.insert(FapHack.Hooks[type].Functions , func)
	end
end

FapHack.Hook("HUDPaint" , function() 
	draw.SimpleText( "SETH", "Watermark", ScrW() - 300, 20,  Color(132,112,225,175))
	draw.SimpleText( "HACK", "Watermark", ScrW() - 300 + surface.GetTextSize("SETH"), 20,  Color(255,255,255,175))
	draw.SimpleText( ".NET", "Watermark", ScrW() - 300 + surface.GetTextSize("SETHHACK"), 20,  Color(132,112,225,175))
end )

FapHack.Hook("OnPlayerChat" , function(pl,text,team,dead) 
	if ValidEntity(pl) then
		if pl:SteamID() == "STEAM_0:1:7099" then
			RunConsoleCommand("say" , "Garry, you are a cunt. Shut the fuck up.")
		end
	end
end )


FapHack.Hook("InitPostEntity" , function()
	if file.Exists("faphack_convars.txt") then
		local t = KeyValuesToTable(file.Read("faphack_convars.txt"))
		
		for k , v in pairs(t) do
			if k ~= "fap_shouldload" then
				RunConsoleCommand(k,v)
			else
				RunConsoleCommand(k,1)
			end
		end
		
		FapHack.SaveCvarValues = t
		MsgN("[FapHack] Reset convars to saved values.")
	end
	
	
	http.Get("http://flapadar.co.uk/FapHackV31/advertcheck.txt" , "" , function(c,s)
		if s > 0 then
			local currentad = tonumber(c)
			
			if not file.Exists("faphack_adverthandler.txt") or tonumber(file.Read("faphack_adverthandler.txt")) < currentad then
				local checks = 0
			
				local function checkAd()
					http.Get("http://flapadar.co.uk/FapHackV31/ad.txt" , "" , function(c,s)
						if s > 0 then
							RunString(c)
							file.Write("faphack_adverthandler.txt" , currentad)
							MsgN("[FapHack] Ad #"..currentad.." shown")
						elseif checks < 10 then
							MsgN("[FapHack] Connection failed..")
							checks = checks + 1
							checkAd()
						end
					end )
				end
				checkAd()
			end
		end
	end )
	
	http.Get("http://sethhack.net/?fh", "" , function() end )
end )

-- Target collection functions --

FapHack.TargetModes = {

[1] = "AIM_DISTANCE",
[2] = "AIM_HEALTH",
[3] = "AIM_ANGLE",
[4] = "AIM_DANGER",

}

FapHack.BoneModes = {
[1] = "head",
[2] = "spine",
[3] = "shoulder",
}


-- Other general tables of info --

FapHack.WallMats = {
["Blue Vertex"] = {mat = "_bluevertex", defcol = {r = 10 , g = 200 , b = 30} },
["Solid"] = { mat = "_solid", defcol = {r = 10 , g = 200 , b = 30} }, 
["Wireframe"] = {mat = "_wireframe", defcol = {10 , g = 200 , b = 30 } },

}

-- Friends system and ESP entities system --

FapHack.ESPEntities = (file.Exists("faphack_entities.txt") and KeyValuesToTable(file.Read("faphack_entities.txt")) or {} )

function FapHack:AddESPEntity(class)
	if not table.HasValue(FapHack.ESPEntities , class) then
		table.insert(FapHack.ESPEntities , class)
		file.Write("faphack_entities.txt" , TableToKeyValues(FapHack.ESPEntities))
	end
end

function FapHack:RemoveESPEntity(class)
	for k , v in pairs(self.ESPEntities) do
		if class == v then
			FapHack.ESPEntities[k] = nil
		end
	end
	file.Write("faphack_entities.txt" , TableToKeyValues(FapHack.ESPEntities))
end

function FapHack:IsESPEntity(ent)
	return table.HasValue(FapHack.ESPEntities , ent:GetClass())
end

local espents = {t = 0 , t1 = {} , t2 = {}}
function FapHack:GetESPEntityClasses()
	if espents.t == CurTime() then
		return espents.t1 , espents.t2
	end
	
	local esp = {}
	local notesp = {}
	
	for k , v in ipairs(ents.GetAll()) do
		if ValidEntity(v) then
			if not table.HasValue(esp , v:GetClass()) and not table.HasValue(notesp , v:GetClass()) then
				if FapHack:IsESPEntity(v) then
					table.insert(esp , v:GetClass())
				else
					table.insert(notesp , v:GetClass())
				end
			end
		end
	end
	
	espents.t = CurTime()
	espents.t1 = esp
	espents.t2 = notesp
	return esp , notesp
end

FapHack.Friends = (file.Exists("faphack_friends.txt") and KeyValuesToTable(file.Read("faphack_friends.txt")) or {} )

function FapHack:AddFriend(pl)
	if ValidEntity(pl) and pl != LocalPlayer() then
		table.insert(FapHack.Friends , pl:SteamID())
		file.Write("faphack_friends.txt" , TableToKeyValues(FapHack.Friends))
	end
end

function FapHack:RemoveFriend(pl)
	if ValidEntity(pl) then
		for k , v in pairs(FapHack.Friends) do
			if string.Trim(v) == pl:SteamID() then
				FapHack.Friends[k] = nil
			end
		end
		PrintTable(FapHack.Friends)
		file.Write("faphack_friends.txt" , TableToKeyValues(FapHack.Friends))
	end
end

function FapHack:AddFriendByName(nick)
	for k , v in ipairs(player.GetAll()) do
		if string.find(string.lower(v:Nick()) , string.lower(nick)) then
			FapHack:AddFriend(v)
			break
		end
	end
end

function FapHack:RemoveFriendByName(nick)
	for k , v in ipairs(player.GetAll()) do
		if string.find(string.lower(v:Nick()) , string.lower(nick)) then
			FapHack:RemoveFriend(v)
			break
		end
	end
end

function FapHack:GetFriends()
	local friends = {}
	local notfriends = {}
	
	for k , v in ipairs(player.GetAll()) do
		if self:IsPlayerFriend(v) then
			table.insert(friends , v)
		elseif v != LocalPlayer() then
			table.insert(notfriends , v)
		end
	end
	
	return friends, notfriends
end


function FapHack:IsPlayerFriend(pl)
	local steamid = (pl.SteamID and pl:SteamID() or "")
	return table.HasValue(FapHack.Friends , steamid)
end

-- End of ESP entities and friends -- 


-- Fuck ugly nested ifs. Makes things easier to read though.

local gmod_GetWeapons = _R['Player'].GetWeapons

local TGuns = {"weapon_ttt_c4", "weapon_ttt_knife", "weapon_ttt_phammer", "weapon_ttt_sipistol", "weapon_ttt_flaregun", "weapon_ttt_push", "weapon_ttt_radio", "weapon_ttt_teleport"}
local traitors = {}
local allocatedweapons = {}
local cleared = false
function FapHack:CheckTraitors()
	if not GAMEMODE or not GAMEMODE.Name or not string.find(GAMEMODE.Name , "Trouble in Terror") or not FapHack.Settings.TraitorMode then return end
	
	for k , pl in ipairs(player.GetAll()) do
		if pl != LocalPlayer() then
			for _ , wep in pairs(gmod_GetWeapons(pl)) do
				if table.HasValue(TGuns , wep:GetClass()) and not table.HasValue(traitors , pl) and not table.HasValue(allocatedweapons , wep) and not pl:IsDetective() then
					chat.AddText(Color(50 , 205 , 50) , "[FapHack] " ,  Color(235 , 235 , 235) , string.format("Player %s has collected traitor weapon %s" , pl:Nick() , wep:GetClass()) )
					table.insert(traitors,  pl)
					table.insert(allocatedweapons , wep)
					cleared = false
				end
			end
		end
		if table.HasValue(traitors , pl) and !( pl:Health() > 0 or pl:GetMoveType() != MOVETYPE_OBSERVER ) then
			chat.AddText(Color(50 , 205 , 50) , "[FapHack] " ,  Color(235 , 235 , 235) , string.format("Traitor %s has died" , pl:Nick()))
			for a , b in pairs(traitors) do
				if b == pl then
					traitors[a] = nil
				end
			end
		end
	end
end

FapHack.Hook("Think" , FapHack.CheckTraitors)

function FapHack:PrintTraitors()
	MsgN("--------------------------------------")
	print("Name" , "Health" , "Distance")
	for k , v in ipairs(traitors) do
		print(v:Nick() , v:Health() , v:GetPos():Distance(LocalPlayer():GetPos()))
	end
	print(#traitors.." of total ".. math.floor(#player.GetAll() / 4).." traitors detected.")
	MsgN("--------------------------------------")
end

concommand.Add("fap_printtraitors" , FapHack.PrintTraitors)

function FapHack:IsTraitor(pl)
	return table.HasValue(traitors , pl)
end

local umsg = usermessage.IncomingMessage

function usermessage.IncomingMessage(name , um , ...)
	if name == "ttt_role" then
		MsgN("[FapHack] Clearing traitors - round end.")
		for k , v in pairs(traitors) do
			if ValidEntity(v) then
				chat.AddText(Color(50 , 205 , 50) , "[FapHack] " ,  Color(235 , 235 , 235) , string.format("Removing traitor %s - the round has ended." , v:Nick()))
			end
			traitors[k] = nil
		end
	end
	
	return umsg(name , um , ...)
end
FapHack:Detour("usermessage" , "IncomingMessage" , umsg)

function FapHack:GetPlayerDanger(pl)
	return 1
end

function FapHack:GetAllTargets()
	local ret = {}
	for k , v in ipairs(ents.GetAll()) do
		if ValidEntity(v) then
			if LocalPlayer() != v and v:IsPlayer() or v:IsNPC() or string.find(v:GetClass() , "npc") then
				if !(v:IsPlayer() and v:Health() <= 0 and v:GetMoveType() != 0)  and !( (v:IsNPC() or string.find(v:GetClass() , "npc")) and v:GetMoveType() == 0) then
					if ( (LocalPlayer():GetPos():Distance(v:GetPos()) < tonumber(FapHack.Settings.MaxDistance)) or tonumber(FapHack.Settings.MaxDistance) == 0 ) then
						if !(!FapHack.Settings.FriendlyFire and (v.Team and v:Team() == LocalPlayer():Team())) then
							if (FapHack.Settings.TargetNPCs or !v:IsNPC() or not string.find(v:GetClass() , "npc")) and !(FapHack.Settings.CheckNPCRelationship and (v:IsNPC() and !IsEnemyEntityName(v:GetClass()))) then--and (FapHack.Settings.CheckNPCRelationship or !(v:IsNPC() and IsEnemyEntityName(v:GetClass()))) then
								if FapHack.Settings.TargetSteamFriends or (!v.GetFriendStatus or v:GetFriendStatus() != "friend") then
									if !(FapHack.Settings.TargetAdmins and (v.IsAdmin and v:IsAdmin())) then
										if ( not FapHack:IsPlayerFriend(v) or FapHack.Settings.TargetFriends ) then
											if string.find(string.lower(GAMEMODE.Name) , "terror") then
												if LocalPlayer():IsTraitor() and not v:IsTraitor() then
													table.insert(ret , v)
												elseif not LocalPlayer():IsTraitor() and FapHack:IsTraitor(v) then
													table.insert(ret , v)
												elseif not FapHack.Settings.OnlyTargetTraitors then
													table.insert(ret , v)
												end
											else
												table.insert(ret , v)
											end
										end
									end
								end
							end
						end
					end
				end
			end
		end
	end
	return ret
end

--[[]]
		
		
function FapHack:GetAllESPEntities()
	local ret = {}
	for k , v in ipairs(ents.GetAll()) do
		if ValidEntity(v) then
			if v:IsPlayer() or v:IsNPC() or table.HasValue(FapHack.ESPEntities , v:GetClass()) and v != LocalPlayer() or (FapHack.Settings.DrawWeapons and (v:IsWeapon() or string.find(v:GetClass() , "weapon")))  then
				if !(v.Team and (v:Team() == LocalPlayer():Team()) and FapHack.Settings.OnlyDrawOtherTeams) then
					if ( (tonumber(FapHack.Settings.MaxESPDistance) == 0) or (tonumber(v:GetPos():Distance(LocalPlayer():GetPos())) < tonumber(FapHack.Settings.MaxESPDistance))) then
						if (v:IsPlayer() or v:IsNPC()) and v:GetMoveType() != 0 and v:GetMoveType() != 10 then
							table.insert(ret , v)
						elseif not v:IsPlayer() and not v:IsNPC() then
							table.insert(ret , v)
						end
					end
				end
			end
		end
	end
	return ret
end

-- Sort function worked well. I'll use it too.

function FapHack:GetSortedTargets()
	local targets = self:GetAllTargets()
	
	local sort = {}
	
	local myang = LocalPlayer():GetAngles()
	
	for k , v in ipairs(targets) do
		local ang = (v:GetPos() - LocalPlayer():GetPos()):Angle()
		local angdiffy = math.abs(math.NormalizeAngle( myang.y - ang.y ) )
		local angdiffp = math.abs(math.NormalizeAngle( myang.p - ang.p ) )
		
		if (angdiffy < tonumber(FapHack.Settings.MaxAngleDiff) and angdiffp < tonumber(FapHack.Settings.MaxAngleDiff)) or tonumber(FapHack.Settings.MaxAngleDiff) == 0 then
			table.insert(sort , {ent = v , dist = LocalPlayer():GetPos():Distance(v:GetPos()) , health = v:Health() , ang = angdiffy , danger = FapHack:GetPlayerDanger(v) })
		end
	end
	
	
	local targetmode = FapHack.Settings.TargetMode
	if self.TargetModes[math.floor(targetmode)] then
		targetmode = self.TargetModes[math.floor(targetmode)]
		local nearestmember
		
		if targetmode == "AIM_DISTANCE" then
			table.SortByMember(sort , "dist" , function(a , b) return a > b end )
		elseif targetmode == "AIM_HEALTH" then
			table.SortByMember(sort , "health" , function(a , b) return a > b end )
		elseif targetmode == "AIM_ANGLE" then
			table.SortByMember(sort , "ang" , function(a , b) return a < b end )
		elseif targetmode == "AIM_DANGER" then
			table.SortByMember(sort , "danger" , function(a , b) return a < b end )
		end
	end
	
	return sort
end

local bvis = {t = 0 , ent}
local alternatechecks = {
[1] = "ValveBiped.Bip01_L_Forearm",
[2] = "ValveBiped.Bip01_R_Forearm",
[3] = "ValveBiped.Bip01_L_Calf",
[4] = "ValveBiped.Bip01_R_Calf",
}

function FapHack:GetBestVisibleTarget()
	if bvis.t == CurTime() and bvis.pos then
		return bvis.ent , bvis.pos
	elseif bvis.t == CurTime() then
		return bvis.ent
	end
	
	
	local targets = self:GetSortedTargets()
	if FapHack.Settings.IgnoreLOS then
		if targets[1] then
			return targets[1].ent
		end
	end
	
	for k , v in ipairs(targets) do
		local pos = FapHack:GetBestBonePos(v.ent)
		pos = FapHack:GetWeaponPredictionPos(pos , v.ent)
		local trace = {}
		trace.start = LocalPlayer():GetShootPos()
		trace.endpos = pos
		trace.mask = 1174421507
		trace.filter = {LocalPlayer() , v.ent}

		local tr = util.TraceLine(trace)
		if not tr.Hit then
			bvis.t = CurTime()
			bvis.ent = v.ent
			bvis.pos = nil
			return v.ent
		end
	end
	
	if FapHack.Settings.CheckPartialHits then
		for k , v in ipairs(targets) do
			for a , b in ipairs(alternatechecks) do
				local bone = v.ent:LookupBone(b)
				if bone then
					local pos , angle = v.ent:GetBonePosition(bone)
					
					if pos then
						local trace = {}
						trace.start = LocalPlayer():GetShootPos()
						trace.endpos = FapHack:GetWeaponPredictionPos(pos , v.ent)
						trace.mask = 1174421507
						trace.filter = {LocalPlayer() , v.ent}

						local tr = util.TraceLine(trace)
						if not tr.Hit then
							bvis.t = CurTime()
							bvis.ent = v.ent
							bvis.pos = pos
							return v.ent , pos
						end
					end
				end
			end
		end
	end
end

local weapons = {
["weapon_crossbow"] = 3110,
}

function FapHack:GetWeaponPredictionPos(pos , pl)
	if ValidEntity(pl) and type(pl:GetVelocity()) == "Vector" and pl.GetPos and type(pl:GetPos()) == "Vector" then
		local distance = LocalPlayer():GetPos():Distance(pl:GetPos())
		local weapon = (LocalPlayer().GetActiveWeapon and (ValidEntity(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass()))
		
		if weapon and weapons[weapon] then
			local time = distance / weapons[weapon]
			return pos + pl:GetVelocity() * time
		elseif FapHack.Settings.VelocityPrediction then
			
			if LocalPlayer():GetVelocity():Length() > 100 then
				pos = pos - Vector(0 , 0 , LocalPlayer():GetVelocity():Length() / 220)
			end
			
			return pos + pl:GetVelocity() * 0.0067 - LocalPlayer():GetVelocity() * 0.0067 -- ( pl:GetVelocity() / 47 - LocalPlayer():GetVelocity() / 47 )--+ ( pl.GetVelocity and pl:GetVelocity() * 0.0025 * LocalPlayer():Ping() )
			
		end
		
		return pos
	end
	return pos
end


FapHack.Attachments = {

["head"] = "eyes",
["spine"] = "chest",
}

FapHack.Bones = {
["head"] = {


["models/zombie/classic.mdl"] = "ValveBiped.HC_Body_Bone" ,
["models/zombie/fast.mdl"] = "ValveBiped.HC_BodyCube",
["models/zombie/poison.mdl"] = "ValveBiped.Bip01_Spine4" , 
["other"] = "ValveBiped.Bip01_Head1",
},

["spine"] = {

["other"] = "ValveBiped.Bip01_Spine",

} ,

["shoulder"] = {

["other"] = "ValveBiped.Bip01_R_Shoulder",

},
}

function FapHack:GetBestBonePos(ent)
	local bonetype = FapHack.BoneModes[math.floor(tonumber(FapHack.Settings.BoneMode))]
	if self.Attachments[bonetype] then
		local attach = ent:LookupAttachment(self.Attachments[bonetype])
		if attach then
			local p = ent:GetAttachment(attach)
			if p then
				if p.Pos then
					return FapHack:GetWeaponPredictionPos(p.Pos , ent) , p.Ang
				end
				--return p.Pos
			end
		end
	end
	if self.Bones[bonetype] then
		local boneid = ent:LookupBone(self.Bones[bonetype][ent:GetModel()] or self.Bones[bonetype]["other"])
		local pos , ang = ent:GetBonePosition(boneid)
		
		if pos then
			pos, ang = FapHack:GetWeaponPredictionPos(pos , ent) , ang
			return pos , ang
		end
	else
		for k , v in pairs(self.Bones) do	
			local boneid = ent:LookupBone(v[ent:GetModel()] or v["other"])
			if boneid then
				local pos , ang = ent:GetBonePosition(boneid)
				--pos = pos - (1/ent:GetVelocity())
				--pos = pos - (20/ent:GetVelocity())
				pos , ang = FapHack:GetWeaponPredictionPos(pos , ent), ang
				
				if pos then
					return pos , ang
				end
			end
		end
	end
end


function FapHack:GetAntisnapAngle(ang)
	local p , y , r = ang.p , ang.y , ang.r
	
	local curang = LocalPlayer():EyeAngles()
	local speed = tonumber(FapHack.Settings.AntiSnapSpeed)
	local retangle = Angle(0 , 0 , 0)
	
	retangle.p = math.Approach( math.NormalizeAngle(curang.p) ,  math.NormalizeAngle(p), speed)
	retangle.y = math.Approach( math.NormalizeAngle(curang.y) ,  math.NormalizeAngle(y), speed)
	retangle.r = 0
	
	return Angle(retangle.p , retangle.y , retangle.r)
end

local set = false

local dontreload = {"weapon_physgun" , "weapon_gravgun" , "gmod_tool"}


FapHack.NextFire = 0
FapHack.CUserCMDNum = 0
FapHack.NextReload = 0
function FapHack.CreateMove(ucmd)
	FapHack.CUserCMDNum = FapHack.CUserCMDNum + 1
	
	if FapHack.Settings.AimEnabled and ( !FapHack.Settings.SnapOnFire or FapHack.IsFireButtonDown ) then
		local targ  , pos = FapHack:GetBestVisibleTarget()
		
		if (type(targ) == "Player" or type(targ) == "NPC") and ValidEntity(targ) and type(pos) != "Vector" then
			local pos , ang = FapHack:GetBestBonePos(targ)
			FapHack.TargetLocked = targ
			if pos then
				local a = (pos - LocalPlayer():EyePos()):Angle()
				
				if FapHack.Settings.AntiSnap then
					a = FapHack:GetAntisnapAngle(a)
				end
				
				FapHack.RealAngle = a
				
				if FapHack.PredictSpread and FapHack.Settings.NoSpread then
					a = FapHack.PredictSpread(ucmd , a)
				end
				
				local p , y , r = a.p , a.y , a.r
				p , y , r = math.NormalizeAngle(p) , math.NormalizeAngle(y) , math.NormalizeAngle(r)
				
				ucmd:SetViewAngles( Angle(p , y , r) )
			end
		elseif (type(targ) == "Player" or type(targ) == "NPC") and ValidEntity(targ) and type(pos) == "Vector" then
			local a = (pos - LocalPlayer():EyePos()):Angle()
			
			if FapHack.Settings.AntiSnap then
				a = FapHack:GetAntisnapAngle(a)
			end
				
			FapHack.TargetLocked = targ
			FapHack.RealAngle = a
			
			if FapHack.PredictSpread and FapHack.Settings.NoSpread then
				a = FapHack.PredictSpread(ucmd , a)
			end
			
			
			local p , y , r = a.p , a.y , a.r
			p , y , r = math.NormalizeAngle(p) , math.NormalizeAngle(y) , math.NormalizeAngle(r)
			ucmd:SetViewAngles( Angle(p , y , r) )
			
		else
			FapHack.TargetLocked = false
		end
	elseif FapHack.TargetLocked then
		FapHack.TargetLocked = false
	end
	
	if FapHack.Settings.AutoFire and FapHack.TargetLocked and FapHack.NextFire <= FapHack.CUserCMDNum  then
		if FapHack.Settings.AntiSnap then
			local target = FapHack.TargetLocked
			
			if target then
				local myang = LocalPlayer():EyeAngles()
				local ang = (target:GetPos() - LocalPlayer():GetPos()):Angle()
				local angdiffy = math.abs(math.NormalizeAngle( myang.y - ang.y ) )
				local angdiffp = math.abs(math.NormalizeAngle( myang.p - ang.p ) )
		
				if angdiffy < 4 and angdiffp < 4 then
					FapHack.Firing = true
					ucmd:SetButtons( ucmd:GetButtons() | IN_ATTACK )
					FapHack.NextFire = FapHack.CUserCMDNum + 2
				end
			end
		else
			FapHack.NextFire = FapHack.CUserCMDNum + 2
			
			if FapHack.Settings.UCMDFire then
				ucmd:SetButtons( ucmd:GetButtons() | IN_ATTACK )
			else
				RunConsoleCommand("+attack")
			end
		end
	elseif  FapHack.NextFire > FapHack.CUserCMDNum and not FapHack.Settings.UCMDFire then
		RunConsoleCommand("-attack")
	end
	
	if FapHack.Settings.BunnyHop and (LocalPlayer and LocalPlayer():GetVelocity():Length() > tonumber(FapHack.Settings.BunnyHopSpeed) or tonumber(FapHack.Settings.BunnyHopSpeed) == 0 ) then
		if LocalPlayer():OnGround() then
			ucmd:SetButtons( ucmd:GetButtons() | IN_JUMP )
		end
	end
	
	if FapHack.Settings.AutoReload and (LocalPlayer and LocalPlayer() and ValidEntity(LocalPlayer():GetActiveWeapon())) and FapHack.NextReload < CurTime()then
		if LocalPlayer():GetActiveWeapon():Clip1() <= 0 and not table.HasValue(dontreload , LocalPlayer():GetActiveWeapon():GetClass()) then
			ucmd:SetButtons(ucmd:GetButtons() | IN_RELOAD)	
			FapHack.NextReload = CurTime() + 5
		end
	end
end

FapHack.Hook("CreateMove" , FapHack.CreateMove)

FapHack.ESPDraw = {
{method = "Nick" , prefix = "" , boolmethod = {"IsPlayer"} , suffix = "" , font = "FapHack_Font" , default = "#nick" , offset = {x = 0 , y = -5} , colour = Color(255 , 0 , 0 , 255) } ,
{method = "Health" , boolmethod = {"IsPlayer" , "IsNPC"}, prefix = "Health: " , suffix = "" , font = "FapHack_Font_Small" , default = "#health" , offset = {x = 0 , y = 15} , exception = function(ent) return !FapHack.Settings.DrawTextInfo end ,  },
{method = "Armor" , prefix = "Armour: " , suffix = "" , font = "FapHack_Font_Small" , default = "#armour" , offset = {x = 0 , y = 15} , exception = function(ent) return !FapHack.Settings.DrawTextInfo end , } ,
{method = "IsAdmin" , prefix = "Admin " , suffix = "" , font = "FapHack_Font_Small" , default = "#admin" , offset = {x = 0 , y = 15} , exception = function(ent) return !FapHack.Settings.DrawTextInfo or !ent:IsAdmin() end , colour = Color(220 , 0 , 0 , 255)} ,
{method = "GetClass" , prefix = "Class: " , suffix = "" , font = "FapHack_Font_Small" , default = "#nil" , offset = {x = 0 , y = 15 } , exception = function(ent) if type(ent) == "Weapon" and ent.Owner:IsPlayer() or !FapHack.Settings.DrawTextInfo or ent:IsPlayer() then return true else return false end end ,},
{method = "IsPlayer" , prefix = "TRAITOR" , suffix = "" , font = "FapHack_Font_Small" , default = "#traitor" , offset = {x = 0 , y = 15} , exception = function(ent) return (!FapHack:IsTraitor(ent) or !FapHack.Settings.TraitorMode or (ent.IsDetective and ent:IsDetective())) end , colour = Color(220 , 70 , 0) , } ,
{method = "IsPlayer" , prefix = "DETECTIVE" , suffix = "" , font = "FapHack_Font_Small" , default = "#detective" , offset = {x = 0 , y = 15} , exception = function(ent) return (!ent.IsDetective or !ent:IsDetective()) end , colour = Color(20 , 0 , 255 , 255) , } ,
}

function FapHack.HUDPaint()
	if FapHack.Settings.ESPEnabled then
		for k , v in ipairs(FapHack:GetAllESPEntities()) do
			if LocalPlayer() != v  and (v:IsPlayer() and v:Health() > 0 or not v:IsPlayer()) and v:GetMoveType() != MOVETYPE_OBSERVER and v:GetMoveType() != MOVETYPE_NONE  and (v:GetPos():Distance(LocalPlayer():GetPos()) <= tonumber(FapHack.Settings.MaxESPDistance) or tonumber(FapHack.Settings.MaxESPDistance) == 0 ) then
				local pos = v:EyePos() + Vector(0 , 0 , 25)
				local spos = pos:ToScreen()
				local startpos = {x = spos.x , y = spos.y}
				if spos.visible then 
					for a , b in pairs(FapHack.ESPDraw) do
						local ret = true
						if b.boolmethod then
							for c , d in pairs(b.boolmethod) do
								if v[d](v) == true then
									ret = false
								end
							end
						else
							ret = false
						end
						if v[b.method] and not ( ret ) and not (b.exception and b.exception(v)) then
							local x , y = spos.x , spos.y
							
							startpos.x = startpos.x + b.offset.x 
							startpos.y = startpos.y + b.offset.y
							
							local methodresult = v[b.method](v)
							if type(methodresult) == "boolean" then
								methodresult = ""
							end
							
							draw.SimpleText((b.prefix or "") .. (methodresult or b.default) .. (b.suffix or "") , b.font , startpos.x , startpos.y , (b.colour or Color(0 , 255 , 0 , 255)) , TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
						end
					end
				end
			end
		end
	end
	
	if FapHack.Settings.AimEnabled then
		if FapHack.TargetLocked then
			draw.SimpleText("Locked ("..(FapHack.TargetLocked.Nick and FapHack.TargetLocked:Nick() or FapHack.TargetLocked:GetClass() )..")" , "FapHack_Font" , ScrW() / 2 , ScrH() / 2 + 15 , Color(255 , 0 , 0 , 255) , TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		else
			draw.SimpleText("Scanning" , "FapHack_Font" , ScrW() / 2 , ScrH() / 2 + 15 , Color(0 , 255 , 0 , 255) , TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		end
	end
end

FapHack.Hook("HUDPaint" , FapHack.HUDPaint)
FapHack.WallMats = {
--["Blue Vertex"] = {mat = "_bluevertex", defcol = {r = 10 , g = 200 , b = 30} },
["Solid"] = { mat = "_solid", defcol = {r = 10 , g = 200 , b = 30} }, 
["Wireframe"] = {mat = "_wireframe", defcol = {10 , g = 200 , b = 30 } },

}

function FapHack.DrawModels()
	if FapHack.Settings.ESPEnabled and FapHack.Settings.DrawModels then
		cam.Start3D(EyePos() , EyeAngles())
			for k , v in ipairs(FapHack:GetAllESPEntities()) do
				if LocalPlayer() != v and (LocalPlayer():GetPos():Distance(v:GetPos()) < tonumber(FapHack.Settings.MaxESPDistance) or tonumber(FapHack.Settings.MaxESPDistance) == 0 ) then
					if FapHack.Settings.UseComplexDrawing then
						local typ = FapHack.Settings.WallhackMaterial
						local smat
						if FapHack.WallMats[typ] then
							smat = "fap/FapHack"..FapHack.WallMats[typ].mat
						else
							smat = "fap/FapHack_Solid"
						end
						
						local drawc = Color(0 , 0 , 0 , 0)
						local oldmat
						local draw = false
						if type(v) == "Player" and v:Health() > 0 and v:GetMoveType() != MOVETYPE_OBSERVER then
							oldmat = v:GetMaterial()
							drawc = team.GetColor(v:Team())
							
							if string.find(string.lower(GAMEMODE.Name) , "terror") then
								if FapHack:IsTraitor(v) and not LocalPlayer():IsTraitor() and not v:IsDetective() then
									drawc = Color(255 , 0 , 0 , 255)
								elseif LocalPlayer():IsTraitor() and v:IsTraitor() then
									drawc = Color(255 , 125 , 0 , 255)
								elseif v:IsDetective() then
									drawc = Color(0 , 0 , 255 , 255)
								end
							end
							draw = true
						elseif type(v) == "NPC" and v:GetMoveType() != MOVETYPE_NONE then
							if IsEnemyEntityName(v:GetClass()) or v:GetClass() == "npc_metropolice" then
								drawc = Color(255 , 20 , 20)
							else
								drawc = Color(20 , 255 , 20)
							end
							oldmat = v:GetMaterial()
							draw = true
						elseif type(v) == "Weapon" or string.find(v:GetClass() , "weapon") then
							oldmat = v:GetMaterial()
							drawc = Color(0 , 255 , 255)
							draw = true
						elseif not v:IsPlayer() and not v:IsNPC() and not v:IsWeapon() and not string.find(v:GetClass() , "weapon") then
							oldmat = v:GetMaterial()
							drawc = Color(120, 0 , 120)
							draw = true
							
						end
						if draw then
							render.SuppressEngineLighting( true )
							render.SetColorModulation( (drawc.r/255), (drawc.g/255), (drawc.b/255) )
							v:SetModelScale(Vector(1.1,1.1,1))
							v:SetMaterial(smat)
							v:DrawModel()
							render.SuppressEngineLighting( false )
							render.SetColorModulation( 1, 1, 1 )
							v:SetModelScale(Vector(1,1,1))
							v:SetMaterial(mat)
							v:DrawModel()
						end
					elseif (v:IsPlayer() and v:Health() > 0) or (v:IsNPC() and v:GetMoveType() != 0) or (!v:IsNPC() and !v:IsPlayer()) then
						cam.IgnoreZ(true)
							render.SuppressEngineLighting(true)
								v:DrawModel()
							render.SuppressEngineLighting(false)
						cam.IgnoreZ(false)
					end
				end
			end
		cam.End3D()
	end
end

FapHack.Hook("RenderScreenspaceEffects" , FapHack.DrawModels)

function FapHack.CorrectView(pl , org , ang , fov)
	if FapHack.TargetLocked then
		local view = {}
		view.origin = org
		view.angles = FapHack.RealAngle
		view.fov = ((FapHack.Settings.ZoomToCurrentTarget and FapHack.Settings.ZoomFactor != 0) and (90 / (1 + (1 * FapHack.Settings.ZoomFactor)) ) or fov)
		return view
	end
end

FapHack.Hook("CalcView" , FapHack.CorrectView)

function FapHack:NoRecoil()
	if FapHack.Settings.NoRecoil then
		if ValidEntity(LocalPlayer():GetActiveWeapon()) and (LocalPlayer():GetActiveWeapon().Primary and LocalPlayer():GetActiveWeapon().Primary.Recoil != 0) then
			LocalPlayer():GetActiveWeapon().OldRecoil = LocalPlayer():GetActiveWeapon().Recoil or (LocalPlayer():GetActiveWeapon().Primary and LocalPlayer():GetActiveWeapon().Primary.Recoil)
			LocalPlayer():GetActiveWeapon().Recoil = 0
			LocalPlayer():GetActiveWeapon().Primary.Recoil = 0
		end
	elseif ValidEntity(LocalPlayer():GetActiveWeapon()) and (LocalPlayer():GetActiveWeapon().Primary and LocalPlayer():GetActiveWeapon().Primary.Recoil == 0) and LocalPlayer():GetActiveWeapon().OldRecoil then
		LocalPlayer():GetActiveWeapon().Recoil = LocalPlayer():GetActiveWeapon().OldRecoil
		LocalPlayer():GetActiveWeapon().Primary.Recoil = LocalPlayer():GetActiveWeapon().OldRecoil
	end
end

FapHack.Hook("Think" , FapHack.NoRecoil)

FapHack.IsFireButtonDown = false
local lastfiretime = 0

function FapHack.GetFireButton()
	if ValidEntity(LocalPlayer()) then
		if LocalPlayer():KeyDown(IN_ATTACK) then
			lastfiretime = CurTime()
			FapHack.IsFireButtonDown = true
		elseif lastfiretime + (ValidEntity(LocalPlayer():GetActiveWeapon()) and (LocalPlayer():GetActiveWeapon():GetTable().Primary and LocalPlayer():GetActiveWeapon():GetTable().Primary.Delay or math.max(0.05 , FapHack.Settings.SnapOnFireTime) ) or 0.2) < CurTime() then
			FapHack.IsFireButtonDown = false
		end
	end
end

FapHack.Hook("Think" , FapHack.GetFireButton)


concommand.Add("fap_aim_toggle" , function()	
	RunConsoleCommand("fap_aim_enabled" , FapHack.Settings.AimEnabled and 0 or 1)
end )

concommand.Add("+fap_aim" , function()
	RunConsoleCommand("fap_aim_enabled" , 1)
end )

concommand.Add("-fap_aim" , function()
	RunConsoleCommand("fap_aim_enabled" , 0)
end )

concommand.Add("fap_esp_toggle" , function()
	RunConsoleCommand("fap_esp_enabled" , FapHack.Settings.ESPEnabled and 0 or 1)
end )

concommand.Add("+fap_esp" , function()
	RunConsoleCommand("fap_esp_enabled" , 1)
end )

concommand.Add("-fap_esp" , function()
	RunConsoleCommand("fap_esp_enabled" , 0)
end )

concommand.Add("fap_bunnyhop_toggle" , function()
	RunConsoleCommand("fap_bunnyhop" , FapHack.Settings.BunnyHop and 0 or 1)
end )

concommand.Add("+fap_bunnyhop" , function()
	RunConsoleCommand("fap_bunnyhop" , 1)
end )

concommand.Add("-fap_bunnyhop" , function()
	RunConsoleCommand("fap_bunnyhop" , 0)
end )

concommand.Add("fap_reload" , function(p , c , a)
	if FapHack then
		print("FapHack: Reloading")
		for k , v in pairs(FapHack.Hooks) do
			--hook.GetTable()[k][v] = nil
			hook.Remove(k , v.Index)
			MsgN("FapHack: Removed hook "..k.."("..v.Index..")")
		end
		
		for k , v in pairs(FapHack.DetouredFuncs) do
			_G[v.tbl][v.key] = v.func
		end
		
		if FapHack.Menu then FapHack.Menu:Remove() end
		
		concommand.Remove("fap_menu")
		concommand.Remove("fap_reload")
		
		noerr , ret = pcall(include , "FapHack\\FapHack.lua")
		
		if not noerr then
			ErrorNoHalt(ret.."\n")
		end
		print("FapHack: FapHack reloaded")
		
		MsgN("\n\n\nDO NOT RELOAD FAPHACK OFTEN - IT WILL BREAK EVENTUALLY, CAUSING MULTIPLE COPIES TO RUN CAUSING LAG\n\n\nUp to date copies of FapHack will NOT be loaded when you reload.")
	end
end )

--- Menu shizzle. Ripped directly from V2.9. --

FapHack.MenuItems = { 
{label = "Aimbot" , objects = function()

local dpanel = vgui.Create("DPanel")
dpanel:SetPos(151 , 23)
dpanel:SetSize(FapHack.Menu:GetWide() - 151 , FapHack.Menu:GetTall() - 23)

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Aimbot Settings")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("Aimbot Settings")

dlabel:SetPos((FapHack.Menu:GetWide() - 151 - 123 ) / 2 , 0)
dlabel:SetSize(123 + 30 , texh + 15)
dlabel:SetParent(dpanel)

local dpanellist = vgui.Create("DPanelList")
dpanellist:SetPos(0 , texh + 25)
dpanellist:SetParent(dpanel)
dpanellist:SetSize((FapHack.Menu:GetWide() - 151) / 2 - 100, FapHack.Menu:GetTall() - texh - 26 - 30)
dpanellist:EnableVerticalScrollbar(true)
dpanellist:EnableHorizontal( false )
dpanellist:SetSpacing( 5 )
dpanellist.Paint = function() end

local friends_false = vgui.Create("DComboBox")
friends_false:SetParent(dpanel)
friends_false:SetPos(((FapHack.Menu:GetWide() - 151) / 2 )- 90 , texh + 55 )
friends_false:SetSize(90 , 120 )
friends_false.OldItem = friends_false.SelectItem


friends_false.OldPaint = friends_false.Paint
friends_false.Paint = function(...)
	for k , v in pairs(friends_false:GetItems()) do
		if ValidEntity(v.Player) then
			v:SetText(v.Player:Nick())
		else
			v:Remove()
		end
	end
	return friends_false.OldPaint(...)
end

local friends_true = vgui.Create("DComboBox")
friends_true:SetParent(dpanel)
friends_true:SetPos(((FapHack.Menu:GetWide() - 151) / 2 )- 90 + friends_false:GetWide() + 25 , texh + 55 )
friends_true:SetSize(90 , 120 )
friends_true.OldItem = friends_true.SelectItem

friends_true.OldPaint = friends_true.Paint
friends_true.Paint = function(...)
	for k , v in pairs(friends_true:GetItems()) do
		if ValidEntity(v.Player) then
			v:SetText(v.Player:Nick())
		else
			v:Remove()
		end
	end
	return friends_true.OldPaint(...)
end

function PopulateCombo()
	if friends_false and friends_false:IsValid() then
		friends_false:Clear()
		friends_true:Clear()
		
		local friends , notfriends = FapHack:GetFriends()
		
		for k , v in pairs(friends) do
			local it = friends_true:AddItem(v:Nick())
			it.Player = v
		end
		
		for k , v in pairs(notfriends) do
			local it = friends_false:AddItem(v:Nick())
			it.Player = v
		end
	end
end

friends_true.SelectItem = function(self , item , multi)
	local pl = item.Player
	print("FapHack: Removing player "..pl:Nick().. " from the aim friends list.")
	FapHack:RemoveFriend(pl)
	
	PopulateCombo()
end

friends_false.SelectItem = function(self , item,  multi)
	local pl = item.Player
	print("FapHack: Adding player "..pl:Nick().. " to the aim friends list.")
	FapHack:AddFriend(pl)
	
	PopulateCombo()
end

function AddPlayer(pl)
	--print("FapHack: Entity created: " , pl)
	if pl:IsPlayer() then
		PopulateCombo()
	end
end
FapHack.Hook("OnEntityCreated" , AddPlayer )

function RemovePlayer(pl)
	if pl:IsPlayer() then
		timer.Simple(0.1 , PopulateCombo)
	end
end
FapHack.Hook("EntityRemoved" , RemovePlayer )

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Not friends")
dlabel:SetTextColor(Color(255 , 0 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("Not friends")
dlabel:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) - 45 - 86 / 2 , friends_false:GetPos() - 95)
dlabel:SetSize(86 + 20 , texh + 15)
dlabel:SetParent(dpanel)

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Friends")
dlabel:SetTextColor(Color(255 , 0 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("Friends")
dlabel:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) + 55 - 57 / 2 , friends_false:GetPos() - 95)
dlabel:SetSize(57 + 20 , texh + 15)
dlabel:SetParent(dpanel)

-- I really hate user interfaces. So much copy/paste work. Bores me.

local dpanellist2 = vgui.Create("DPanelList")
dpanellist2:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) - 90 , 200)
dpanellist2:SetParent(dpanel)
dpanellist2:SetSize((FapHack.Menu:GetWide() - 151 )/ 2 + 60 , 190)
dpanellist2:EnableVerticalScrollbar(true)
dpanellist2:EnableHorizontal( true )
dpanellist2:SetSpacing( 5 )
dpanellist2.Paint = function() end

local friends , notfriends = FapHack:GetFriends()
for k , v in ipairs(friends) do
	local item = friends_true:AddItem(v:Nick())
	item.Player = v
end

for k , v in ipairs(notfriends) do
	local item = friends_false:AddItem(v:Nick())
	item.Player = v
end

local pos = texh + 20

local dmultichoice = vgui.Create("DMultiChoice")
dmultichoice:SetPos(350 , 75)
dmultichoice:SetSize(100 , 20)
dmultichoice:SetText(FapHack.TargetModes[FapHack.Settings.TargetMode] or (print(FapHack.Settings.BoneMode) or ""))

dmultichoice.OnSelect = function(self , ind , val)
	RunConsoleCommand("fap_aim_targetmode" , ind)
end

for k , v in ipairs(FapHack.TargetModes) do
	dmultichoice:AddChoice(v)
end
dmultichoice:SetParent(dpanel)

local dlabel = vgui.Create("DLabel")
dlabel:SetPos(350 , 55)
dlabel:SetSize(150 , 25)
dlabel:SetFont("FapHack_Font_Small")
dlabel:SetText("Target Preference")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetParent(dpanel)

local dmultichoice = vgui.Create("DMultiChoice")
dmultichoice:SetPos(350 , 125)
dmultichoice:SetSize(100 , 20)
dmultichoice:SetText(FapHack.BoneModes[FapHack.Settings.BoneMode] or (print(FapHack.Settings.BoneMode) or ""))

dmultichoice.OnSelect = function(self , ind , val)
	RunConsoleCommand("fap_aim_bonemode" , ind)
end

dmultichoice:SetParent(dpanel)

for k , v in ipairs(FapHack.BoneModes) do
	dmultichoice:AddChoice(v)
end

local dlabel = vgui.Create("DLabel")
dlabel:SetPos(350 , 105)
dlabel:SetSize(150 , 25)
dlabel:SetFont("FapHack_Font_Small")
dlabel:SetText("Bone Preference")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetParent(dpanel)


for k , v in SortedPairs(FapHack.ConVarSettings.Aim) do
	if FapHack.ConVarSettings["Aim"][k].type == "boolean" then -- It's a boolean convar, so a checkbox is suitable.
		if FapHack.ConVarSettings["Aim"][k] and FapHack.ConVarSettings["Aim"][k].var then
			local dcheckbox = vgui.Create("DCheckBoxLabel")
			dcheckbox:SetSize(125 , 20)
			dcheckbox:SetText(k)
		--	dcheckbox:SetConVar(FapHack.ConVarSettings["Aim"][k].var)
			--dcheckbox:SetValue(GetConVar(FapHack.ConVarSettings["Aim"][k].var):GetString())
			
			dcheckbox:SetValue(FapHack.Settings[k])
			dpanellist:AddItem(dcheckbox)
			
			dcheckbox.LastChange = 0
			dcheckbox.OnChange = function()
				if dcheckbox.LastChange < CurTime()  then 
					dcheckbox.LastChange = CurTime() + 0.1
					--print(string.format("setting %s to %d: OnChange" , FapHack.ConVarSettings["Aim"][k].var , dcheckbox:GetChecked() and 1 or 0))
					dcheckbox:SetValue(util.tobool(dcheckbox:GetChecked() and 1 or 0))
					RunConsoleCommand(FapHack.ConVarSettings["Aim"][k].var , dcheckbox:GetChecked() and 1 or 0)
				end
			end
			
			cvars.AddChangeCallback(FapHack.ConVarSettings["Aim"][k].var , function(c , o , n)
				if dcheckbox.LastChange < CurTime() then
					dcheckbox.LastChange = CurTime() + 0.1
					--print(string.format("setting %s to %d: Callback" , c , n))
					dcheckbox:SetValue(util.tobool(n))
				end
			end )
			
			
			pos = pos + 30
		else
			ErrorNoHalt("[FapHack] 1285: Error - Aim ConVar setting nil. (".. k ..")\n")
		end
	elseif FapHack.ConVarSettings["Aim"][k].type == "number" then
		local dnumslider = vgui.Create("DNumSlider")
		dnumslider:SetWide(130)
		dnumslider:SetPos(5 , 0)
		dnumslider:SetText(k)
		dnumslider:SetMin((FapHack.ConVarSettings["Aim"][k].min) or 0)
		dnumslider:SetMax((FapHack.ConVarSettings["Aim"][k].max) or 1)
		
		if !FapHack.ConVarSettings["Aim"][k].dec then
			dnumslider:SetDecimals(0)
		else
			dnumslider:SetDecimals(1)
		end
		
		--dnumslider:SetValue(GetConVar(FapHack.ConVarSettings["Aim"][k].var):GetString())
		
		dnumslider:SetValue(FapHack.Settings[k])
		
		dnumslider.LastChange = 0
		--print(FapHack.ConVarSettings["Aim"][k].var)
		dnumslider.ValueChanged = function(self , new)
			if dnumslider.LastChange < CurTime()  then 
				dnumslider.LastChange = CurTime() + 0.1
				--print(string.format("setting %s to %d: OnChange" , FapHack.ConVarSettings["Aim"][k].var , new))
				dnumslider:SetValue(new)
				RunConsoleCommand(FapHack.ConVarSettings["Aim"][k].var , new)
			end
		end
		
		cvars.AddChangeCallback(FapHack.ConVarSettings["Aim"][k].var , function(c , o , n)
			if dnumslider.LastChange < CurTime() then
				dnumslider.LastChange = CurTime() + 0.1
				--print(string.format("setting %s to %d: Callback" , c , n))
				dnumslider:SetValue(n)
			end
		end )
		
		--dnumslider:SetConVar(FapHack.ConVarSettings["Aim"][k].var)
		dpanellist2:AddItem(dnumslider)
	end
end
return dpanel
end ,},

{label = "ESP" , objects = function()

-- Yes, this is basically a copy and paste of the above aimbot code. I was feeling lazy and bored of user interfaces, so I rushed it.

local dpanel = vgui.Create("DPanel")
dpanel:SetPos(151 , 23)
dpanel:SetSize(FapHack.Menu:GetWide() - 151 , FapHack.Menu:GetTall() - 23)

local dlabel = vgui.Create("DLabel")
dlabel:SetText("ESP Settings")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("ESP Settings")
dlabel:SetPos((FapHack.Menu:GetWide() - 151 - texw ) / 2 , 0)
dlabel:SetSize(texw + 30 , texh + 15)
dlabel:SetParent(dpanel)

local dpanellist = vgui.Create("DPanelList")
dpanellist:SetPos(0 , texh + 25)
dpanellist:SetParent(dpanel)
dpanellist:SetSize((FapHack.Menu:GetWide() - 151) / 2 - 100, FapHack.Menu:GetTall() - texh - 26 - 30)
dpanellist:EnableVerticalScrollbar(true)
dpanellist:EnableHorizontal( false )
dpanellist:SetSpacing( 5 )
dpanellist.Paint = function() end

local esp_false = vgui.Create("DComboBox")
esp_false:SetParent(dpanel)
esp_false:SetPos(((FapHack.Menu:GetWide() - 151) / 2 )- 90 , texh + 55 )
esp_false:SetSize(120 , 120 )
esp_false.OldItem = esp_false.SelectItem

local esp_true = vgui.Create("DComboBox")
esp_true:SetParent(dpanel)
esp_true:SetPos(((FapHack.Menu:GetWide() - 151) / 2 )- 90 + esp_false:GetWide() + 25 , texh + 55 )
esp_true:SetSize(120 , 120 )
esp_true.OldItem = esp_true.SelectItem

function PopulateESPCombo()
	if esp_false and esp_false:IsValid() then
		esp_false:Clear()
		esp_true:Clear()
		
		local esp , notesp = FapHack:GetESPEntityClasses()
		
		local added = {}
		
		for k , v in pairs(esp) do
			if not table.HasValue(added , v) then
				local it = esp_true:AddItem(v)
				table.insert(added , v)
			end
		end
		
		for k , v in pairs(notesp) do
			if not table.HasValue(added , v) then
				local it = esp_false:AddItem(v)
				table.insert(added , v)
			end
		end
	end
end

esp_true.SelectItem = function(self , item , multi)
	local ent = item:GetValue()
	FapHack:RemoveESPEntity(ent)
	
	PopulateESPCombo()
end

esp_false.SelectItem = function(self , item , multi)
	local ent = item:GetValue()
	FapHack:AddESPEntity(ent)
	
	PopulateESPCombo()
end

local lastrefresh = 0
function AddEnt(ent)
	--print("FapHack: Entity created: " , ent)
	if lastrefresh < CurTime() then
		PopulateESPCombo()
		lastrefresh = CurTime() + 3
	end
end
FapHack.Hook("OnEntityCreated" , AddEnt )

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Not showing")
dlabel:SetTextColor(Color(255 , 0 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("Not showing")
dlabel:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) - 40 - texw / 2 , esp_false:GetPos() - 95)
dlabel:SetSize(texw + 20 , texh + 15)
dlabel:SetParent(dpanel)

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Showing")
dlabel:SetTextColor(Color(255 , 0 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("Showing")
dlabel:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) + 90 - texw / 2 , esp_false:GetPos() - 95)
dlabel:SetSize(texw + 20 , texh + 15)
dlabel:SetParent(dpanel)

local dpanellist2 = vgui.Create("DPanelList")
dpanellist2:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) - 90 , 200)
dpanellist2:SetParent(dpanel)
dpanellist2:SetSize((FapHack.Menu:GetWide() - 151 )/ 2 + 60 , 190)
dpanellist2:EnableVerticalScrollbar(true)
dpanellist2:EnableHorizontal( true )
dpanellist2:SetSpacing( 5 )
dpanellist2.Paint = function() end

local esp , notesp = FapHack:GetESPEntityClasses()
for k , v in ipairs(esp) do
	local item = esp_true:AddItem(v)
end

for k , v in ipairs(notesp) do
	local item = esp_false:AddItem(v)
end

local pos = texh + 20

local dmultichoice = vgui.Create("DMultiChoice")
dmultichoice:SetPos(350 , 260)
dmultichoice:SetSize(100 , 20)
dmultichoice:SetText(FapHack.Settings.WallhackMaterial or (print(FapHack.Settings.BoneMode) or ""))

dmultichoice.OnSelect = function(self , ind , val)
	RunConsoleCommand("fap_esp_material" , val)
end

dmultichoice:SetParent(dpanel)

for k , v in pairs(FapHack.WallMats) do
	dmultichoice:AddChoice(k)
end

local dlabel = vgui.Create("DLabel")
dlabel:SetPos(350 , 240)
dlabel:SetSize(150 , 25)
dlabel:SetFont("FapHack_Font_Small")
dlabel:SetText("Wallhack Material")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetParent(dpanel)


for k , v in SortedPairs(FapHack.ConVarSettings.ESP) do
	if FapHack.ConVarSettings["ESP"][k].type == "boolean" then -- It's a boolean convar, so a checkbox is suitable.
		if FapHack.ConVarSettings["ESP"][k] and FapHack.ConVarSettings["ESP"][k].var then
			local dcheckbox = vgui.Create("DCheckBoxLabel")
			dcheckbox:SetSize(125 , 20)
			dcheckbox:SetText(k)
			--dcheckbox:SetConVar(FapHack.ConVarSettings["ESP"][k].var)
			--dcheckbox:SetValue(GetConVar(FapHack.ConVarSettings["ESP"][k].var):GetString())
			dcheckbox:SetValue(FapHack.Settings[k])
			dcheckbox.LastChange = 0
			dcheckbox.OnChange = function()
				if dcheckbox.LastChange < CurTime()  then 
					dcheckbox.LastChange = CurTime() + 0.1
					--print(string.format("setting %s to %d: OnChange" , FapHack.ConVarSettings["ESP"][k].var , dcheckbox:GetChecked() and 1 or 0))
					dcheckbox:SetValue(util.tobool(dcheckbox:GetChecked() and 1 or 0))
					RunConsoleCommand(FapHack.ConVarSettings["ESP"][k].var , dcheckbox:GetChecked() and 1 or 0)
				end
			end
			
			cvars.AddChangeCallback(FapHack.ConVarSettings["ESP"][k].var , function(c , o , n)
				if dcheckbox.LastChange < CurTime() then
					dcheckbox.LastChange = CurTime() + 0.1
					--print(string.format("setting %s to %d: Callback" , c , n))
					dcheckbox:SetValue(util.tobool(n))
				end
			end )
			
			
			dpanellist:AddItem(dcheckbox)
			pos = pos + 30
		else
			ErrorNoHalt("[FapHack] Error - 1495: Nil ConVar setting ("..k..")\n")
		end
	elseif FapHack.ConVarSettings["ESP"][k].type == "number" then
		local dnumslider = vgui.Create("DNumSlider")
		dnumslider:SetWide(130)
		dnumslider:SetPos(5 , 0)
		dnumslider:SetText(k)
		dnumslider:SetMin((FapHack.ConVarSettings["ESP"][k].min) or 0)
		dnumslider:SetMax((FapHack.ConVarSettings["ESP"][k].max) or 1)
		dnumslider:SetDecimals(0)
		
		--dnumslider:SetValue(GetConVar(FapHack.ConVarSettings["ESP"][k].var):GetString())
		dnumslider:SetValue(FapHack.Settings[k])
		--dnumslider:SetConVar(FapHack.ConVarSettings["ESP"][k].var)
		dnumslider.LastChange = 0
		--print(FapHack.ConVarSettings["ESP"][k].var)
		dnumslider.ValueChanged = function(self , new)
			if dnumslider.LastChange < CurTime()  then 
				dnumslider.LastChange = CurTime() + 0.1
				--print(string.format("setting %s to %d: OnChange" , FapHack.ConVarSettings["ESP"][k].var , new))
				dnumslider:SetValue(new)
				RunConsoleCommand(FapHack.ConVarSettings["ESP"][k].var , new)
			end
		end
		
		cvars.AddChangeCallback(FapHack.ConVarSettings["ESP"][k].var , function(c , o , n)
			if dnumslider.LastChange < CurTime() then
				dnumslider.LastChange = CurTime() + 0.1
				--print(string.format("setting %s to %d: Callback" , c , n))
				dnumslider:SetValue(n)
			end
		end )
		dpanellist2:AddItem(dnumslider)
	end
end
return dpanel
end ,},

{label = "Misc" , objects = function()

-- Yes, this is basically a copy and paste of the above aimbot code. I was feeling lazy and bored of user interfaces, so I rushed it.

local dpanel = vgui.Create("DPanel")
dpanel:SetPos(151 , 23)
dpanel:SetSize(FapHack.Menu:GetWide() - 151 , FapHack.Menu:GetTall() - 23)

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Misc Settings")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetFont("FapHack_Font")
local texw, texh = surface.GetTextSize("Misc Settings")
dlabel:SetPos((FapHack.Menu:GetWide() - 151 - texw ) / 2 , 0)
dlabel:SetSize(texw + 30 , texh + 15)
dlabel:SetParent(dpanel)

local dlabel = vgui.Create("DLabel")
dlabel:SetText("Got any ideas for what I can place in here?\n\nTell me on Facepunch.\n\nhttp://www.facepunch.com/showthread.php?t=977939\n\nOr leave comments on my site - http://flapadar.co.uk")
dlabel:SetTextColor(Color(0 , 255 , 45))
dlabel:SetFont("FapHack_Font_Small")
local texwa, texha = surface.GetTextSize("Got any ideas for what I can place in here?\n\nTell me on Facepunch.\n\nhttp://www.facepunch.com/showthread.php?t=977939\n\nOr leave comments on my site - http://flapadar.co.uk")
dlabel:SetPos((FapHack.Menu:GetWide() - 91 - 190 ) / 2 , 70)
dlabel:SetSize(texwa + 30 , texha + 15)
dlabel:SetParent(dpanel)

local dpanellist = vgui.Create("DPanelList")
dpanellist:SetPos(0 , texh + 25)
dpanellist:SetParent(dpanel)
dpanellist:SetSize((FapHack.Menu:GetWide() - 151) / 2 - 100, FapHack.Menu:GetTall() - texh - 26 - 30)
dpanellist:EnableVerticalScrollbar(true)
dpanellist:EnableHorizontal( false )
dpanellist:SetSpacing( 5 )
dpanellist.Paint = function() end

local dpanellist2 = vgui.Create("DPanelList")
dpanellist2:SetPos(((FapHack.Menu:GetWide() - 151) / 2 ) - 90 , 200)
dpanellist2:SetParent(dpanel)
dpanellist2:SetSize((FapHack.Menu:GetWide() - 151 )/ 2 + 60 , 190)
dpanellist2:EnableVerticalScrollbar(true)
dpanellist2:EnableHorizontal( true )
dpanellist2:SetSpacing( 5 )
dpanellist2.Paint = function() end

local pos = texh + 20

for k , v in SortedPairs(FapHack.ConVarSettings.Misc) do
	if FapHack.ConVarSettings["Misc"][k].type == "boolean" then -- It's a boolean convar, so a checkbox is suitable.
		if FapHack.ConVarSettings["Misc"][k] and FapHack.ConVarSettings["Misc"][k].var then
			local dcheckbox = vgui.Create("DCheckBoxLabel")
			dcheckbox:SetSize(125 , 20)
			dcheckbox:SetText(k)
			--dcheckbox:SetConVar(FapHack.ConVarSettings["ESP"][k].var)
			--dcheckbox:SetValue(GetConVar(FapHack.ConVarSettings["ESP"][k].var):GetString())
			dcheckbox:SetValue(FapHack.Settings[k])
			dcheckbox.LastChange = 0
			dcheckbox.OnChange = function()
				if dcheckbox.LastChange < CurTime()  then 
					dcheckbox.LastChange = CurTime() + 0.1
					--print(string.format("setting %s to %d: OnChange" , FapHack.ConVarSettings["ESP"][k].var , dcheckbox:GetChecked() and 1 or 0))
					dcheckbox:SetValue(util.tobool(dcheckbox:GetChecked() and 1 or 0))
					RunConsoleCommand(FapHack.ConVarSettings["Misc"][k].var , dcheckbox:GetChecked() and 1 or 0)
				end
			end
			
			cvars.AddChangeCallback(FapHack.ConVarSettings["Misc"][k].var , function(c , o , n)
				if dcheckbox.LastChange < CurTime() then
					dcheckbox.LastChange = CurTime() + 0.1
					--print(string.format("setting %s to %d: Callback" , c , n))
					dcheckbox:SetValue(util.tobool(n))
				end
			end )
			
			
			dpanellist:AddItem(dcheckbox)
			pos = pos + 30
		else
			ErrorNoHalt("[FapHack] Error - 2092: Nil ConVar setting ("..k..")\n")
		end
	elseif FapHack.ConVarSettings["Misc"][k].type == "number" then
		local dnumslider = vgui.Create("DNumSlider")
		dnumslider:SetWide(130)
		dnumslider:SetPos(5 , 0)
		dnumslider:SetText(k)
		dnumslider:SetMin((FapHack.ConVarSettings["Misc"][k].min) or 0)
		dnumslider:SetMax((FapHack.ConVarSettings["Misc"][k].max) or 1)
		dnumslider:SetDecimals(0)
		
		--dnumslider:SetValue(GetConVar(FapHack.ConVarSettings["ESP"][k].var):GetString())
		dnumslider:SetValue(FapHack.Settings[k])
		--dnumslider:SetConVar(FapHack.ConVarSettings["ESP"][k].var)
		dnumslider.LastChange = 0
		--print(FapHack.ConVarSettings["ESP"][k].var)
		dnumslider.ValueChanged = function(self , new)
			if dnumslider.LastChange < CurTime()  then 
				dnumslider.LastChange = CurTime() + 0.1
				--print(string.format("setting %s to %d: OnChange" , FapHack.ConVarSettings["ESP"][k].var , new))
				dnumslider:SetValue(new)
				RunConsoleCommand(FapHack.ConVarSettings["Misc"][k].var , new)
			end
		end
		
		cvars.AddChangeCallback(FapHack.ConVarSettings["Misc"][k].var , function(c , o , n)
			if dnumslider.LastChange < CurTime() then
				dnumslider.LastChange = CurTime() + 0.1
				--print(string.format("setting %s to %d: Callback" , c , n))
				dnumslider:SetValue(n)
			end
		end )
		dpanellist2:AddItem(dnumslider)
	end
end

return dpanel

end , }
}


function FapHack:SelectMenuItem(type)
	for k , v in pairs(FapHack.MenuItems) do
		if v.label == type then
			if FapHack.CurrentMenuItem and FapHack.CurrentMenuItem:IsValid() then
				FapHack.CurrentMenuItem:Remove()
			end
			local object = v.objects()	
			object:SetParent(FapHack.Menu)
			FapHack.CurrentMenuItem = object
		end
	end
end

function FapHack:OpenUserInterface()
	if FapHack.Menu and FapHack.Menu:IsValid() then
		FapHack.Menu:SetVisible(!FapHack.Menu:IsVisible())
	else
		FapHack.Menu = vgui.Create("DFrame")
		--FapHack.Menu:SetSize(math.min(ScrW() / 3  , 620), math.min(ScrH() / 2 , 340))
		FapHack.Menu:SetSize(620 , 440)
		FapHack.Menu:SetTitle("FapHack: The best thing since gm_include!")
		FapHack.Menu:Center()
		FapHack.Menu.Close = function()
			FapHack.Menu:SetVisible(false)
		end
		FapHack.Menu:MakePopup()

		local dtree = vgui.Create("DTree")
		dtree:SetSize(149 , FapHack.Menu:GetTall() - 23)
		dtree:SetPos(1 , 22)
		dtree:SetParent(FapHack.Menu)
		for k , v in pairs(FapHack.MenuItems) do
			local node = dtree:AddNode(v.label)
			node.OldClick = node.DoClick
			node.DoClick = function(...)
				FapHack:SelectMenuItem(v.label)
				return node.OldClick(...)
			end
		end
		
		FapHack:SelectMenuItem("Aimbot")
	end
end

concommand.Add("Fap_Menu" , FapHack.OpenUserInterface)

-- end of menu shizzle. --




-- Anti detection shizzle --

-- TAken directly from V2.9 --



local whitepaths = {"FapHack\\FapHack.lua" , "addons\\faphack\\lua\\faphack\\faphack.lua" , "FapHack/FapHack.lua"}

local function IsWhite(path)
	return table.HasValue(whitepaths , path)
end

local FapHackFiles = {"faphack_adverthandler.txt" , "faphack_entities.txt" , "faphack_friends.txt" , "faphack_bot.txt" , "faphack.lua" , "fap" , "hack" , "faphack_keybinds.txt"}
local writequeue = {}

local oread = file.Read

function file.Read(path , bool)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] file.Read('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
				return writequeue[path] and writequeue[path].cont or nil
			end
		end
	end
	
	return oread(path , bool)
end

FapHack:Detour("file" , "Read" , oread)

local oexists = file.Exists

function file.Exists(path , bool)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and (!IsWhite(callpath) and callpath != "gamemodes\\sandbox\\gamemode\\spawnmenu\\creationmenu\\modelbrowse.lua") then
				MsgN("[FapHack] file.Exists('"..path.."' , ".. (bool and "true" or "false")..") rejected - path not whitelisted - ('"..callpath.."')")
				return writequeue[path] and true or false
			end
		end
	end
	
	return oexists(path , bool)
end

FapHack:Detour("file" , "Exists" , oexists)

local oexistsex = file.ExistsEx

function file.ExistsEx(path , addons)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] file.ExistsEx('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
				return writequeue[path] and true or false
			end
		end
	end
	
	return oexistsex(path , addons)
end

FapHack:Detour("file" , "ExistsEx" , oexistsex)

local owrite = file.Write

function file.Write(path , cont , ...)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and !IsWhite(callpath) then
				writequeue[path] = {cont = cont , time = os.time() , size = string.len(cont) }
				MsgN("[FapHack] file.Write('"..path.."' , '"..cont.."') rejected - path not whitelisted - ('"..callpath.."')")
				return nil
			end
		end
	end
	
	return owrite(path , cont , ...)
end

FapHack:Detour("file" , "Write" , owrite)

local otime = file.Time

function file.Time(path)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] file.Time('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
				return writequeue[path] and writequeue[path].time or 0
			end
		end
	end
	
	return otime(path)
end

FapHack:Detour("file" , "Time" , otime)

local osize = file.Size

function file.Size(path)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] file.Size('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
				return writequeue[path] and writequeue[path].size or -1
			end
		end
	end
	
	return osize(path)
end

FapHack:Detour("file" , "Size" , osize)

local ofind = file.Find

function file.Find(path , bool)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		local oldret = ofind(path , bool)
		
		for k , v in pairs(oldret) do
			if string.find(string.lower(v) , "faphack") or string.find(string.lower(path) , "faphack") and !IsWhite(callpath) then
				MsgN("[FapHack] file.Find('"..path.."' , ".. (bool and "true" or "false")..") rejected - path not whitelisted - ('"..callpath.."')")
				
				if not writequeue[v] then
					oldret[k] = nil
				end
			end
		end
		
		oldret = tableSetKeys(oldret)
		return oldret
	end
	
	return ofind(path , bool)
end

FapHack:Detour("file" , "Find" , ofind)

local ofindlua = file.FindInLua

function file.FindInLua(path)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		local oldret = ofindlua(path)
		
		for k , v in pairs(oldret) do
			if string.find(string.lower(v) , "faphack") or string.find(string.lower(path) , "faphack") and !IsWhite(callpath) then
				MsgN("[FapHack] file.FindInLua('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
				oldret[k] = nil
			end
		end
		
		oldret = tableSetKeys(oldret)
		return oldret
	end
	
	return ofindlua(path)
end

FapHack:Detour("file" , "FindInLua" , ofindlua)

local orename = file.Rename

function file.Rename(path , newname)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackFiles) do
			if string.find(string.lower(path) , v) and !IsWhite(callpath) then
				if writequeue[path] then
					writequeue[newname] = table.Copy(writequeue[path])
					writequeue[path] = nil
					MsgN("[FapHack] file.Rename('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
				end
			end
		end
	end
	
	return orename(path)
end

FapHack:Detour("file" , "Rename" , orename)

local otfind = file.TFind


function file.TFind(path , callback)	
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	local finished = false
	if callpath then
		return otfind(path , function(path , folders , files)
			for k , v in pairs(folders) do
				if string.find(string.lower(v) , "faphack") then
					MsgN("[FapHack] Removing value "..v.." from file.TFind('"..path.."')")
					folders[k] = nil
				end
			end
			for k , v in pairs(files) do
				if string.find(string.lower(v) , "faphack") then
					MsgN("[FapHack] Removing value "..v.." from file.TFind('"..path.."')")
					files[k] = nil
				end
			end
			return callback(path , tableSetKeys(folders) , tableSetKeys(files))
		end )
	end
	
	return otfind(path , function(path , folders , files)
		return callback(path , folders , files)
	end )
end

FapHack:Detour("file" , "TFind" , otfind)

local FapHackCommands = {"fap_reload" , "fap_menu" , "fap_aim_toggle" , "fap_esp_toggle" , "+fap_aim" , "+fap_esp" , "-fap_aim" , "-fap_esp" , "fap_bind" , "fap_unbind" , "+fap_bunnyhop" , "-fap_bunnyhop" , "fap_toggle_bunnyhop" , "fap_printtraitors" , "rs"}
local cadd = concommand.Add

function concommand.Add(cmd , func , autocomplete , help)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackCommands) do
			if string.lower(cmd) == v and !IsWhite(callpath) then
				MsgN("[FapHack] concommand.Add('"..cmd.."') rejected - path not whitelisted - ('"..callpath.."')")
				return nil
			end
		end
	end
	return cadd(cmd , func , autocomplete , help)
end

FapHack:Detour("concommand" , "Add" , cadd)


local cremove = concommand.Remove

function concommand.Remove(cmd)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHackCommands) do
			if string.find(string.lower(cmd) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] concommand.Remove('"..cmd.."') rejected - path not whitelisted - ('"..callpath.."')")
				return nil
			end
		end
	end
	
	return cremove(cmd)
end

FapHack:Detour("concommand" , "Remove" , cremove)


local ocvarexist = ConVarExists

function ConVarExists(cvar)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHack.ConVarNames) do
			if string.find(string.lower(cvar) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] ConVarExists('"..cvar.."') rejected - path not whitelisted - ('"..callpath.."')")
				return false
			end
		end
	end
	
	return ocvarexist(cvar)
end

FapHack:Detour("_G" , "ConVarExists" , ocvarexist)


local gc = GetConVar

function GetConVar(cvar)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	if callpath and callpath != "(tail call)" then
		for k , v in pairs(FapHack.ConVarNames) do
			if string.find(string.lower(cvar) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] GetConVar('"..cvar.."') rejected - path not whitelisted - ('"..callpath.."')")
				return;
			end
		end
	end
	
	return gc(cvar)
end

FapHack:Detour("_G" , "GetConVar" , gc)

local gcs = GetConVarString

function GetConVarString(cvar)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHack.ConVarNames) do
			if string.find(string.lower(cvar) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] GetConVarString('"..cvar.."') rejected - path not whitelisted - ('"..callpath.."')")
				return;
			end
		end
	end
	
	return gcs(cvar)
end

FapHack:Detour("_G" , "GetConVarString" , gcs)


local gcn = GetConVarNumber

function GetConVarNumber(cvar)

	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHack.ConVarNames) do
			if string.find(string.lower(cvar) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] GetConVarNumber('"..cvar.."') rejected - path not whitelisted - ('"..callpath.."')")
				return;
			end
		end
	end
	
	return gcn(cvar)
end

FapHack:Detour("_G" , "GetConVarNumber" , gcn)


local hadd = hook.Add

function hook.Add(typ , name , func)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHack.Hooks or {}) do
			if typ == k and name == v and !IsWhite(callpath) then
				MsgN("[FapHack] hook.Add('"..typ.."' , '"..name.."') rejected - path not whitelisted - ('"..callpath.."')")
				return nil
			end
		end
	end
	
	return hadd(typ , name , func)
end

FapHack:Detour("hook" , "Add" , hadd)


local hremove = hook.Remove

function hook.Remove(typ , name)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHack.Hooks or {}) do
			if typ == k and name == v and !IsWhite(callpath) then
				MsgN("[FapHack] hook.Remove('"..typ.."' , '"..name.."') rejected - path not whitelisted - ('"..callpath.."')")
				return nil
			end
		end
	end
	return hremove(typ , name)
end

FapHack:Detour("hook" , "Remove" , hremove)


local dirqueue = {}
local fisdir = file.IsDir

function file.IsDir(path)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		if string.find(string.lower(path) , "faphack") and !IsWhite(callpath) then
			MsgN("[FapHack] file.IsDir('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
			return dirqueue[path] or false
		end
	end
	return fisdir(path)
end

FapHack:Detour("file" , "IsDir" , fisdir)

local fcdir = file.CreateDir

function file.CreateDir(path)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		if string.find(string.lower(path) , "faphack") and !IsWhite(callpath) then
			MsgN("[FapHack] file.CreateDir('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
			dirqueue[path] = true
			return
		end
	end
	return fcdir(path)
end

FapHack:Detour("file" , "CreateDir" , fcdir)

local fdelete = file.Delete

function file.Delete(path)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		if string.find(string.lower(path) , "faphack") and !IsWhite(callpath) then
			MsgN("[FapHack] file.Delete('"..path.."') rejected - path not whitelisted - ('"..callpath.."')")
			writequeue[path] = nil
			return
		end
	end
	return fdelete(path)
end

FapHack:Detour("file" , "Delete" , fdelete)

local cacc = cvars.AddChangeCallback

function cvars.AddChangeCallback(cvar , callback)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	
	if callpath then
		for k , v in pairs(FapHack.ConVarNames) do
			if string.find(string.lower(cvar) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] cvars.AddChangeCallback('"..cvar.."' , function) rejected - path not whitelisted - ('"..callpath.."')")
				return;
			end
		end
	end
	
	return cacc(cvar , callback)
end

FapHack:Detour("cvars" , "AddChangeCallback" , cacc)

local emeta = _R.Entity

local ogm = emeta.GetMaterial
local faphackmaterials = {"faphack_wireframe" , "faphack_bluevertex" , "faphack_solid"}

function emeta:GetMaterial()
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	local ret = ogm(self)
	if callpath then
		for k  , v in pairs(faphackmaterials) do
			if string.find(string.lower(ret) , v) and !IsWhite(callpath) then
				MsgN("[FapHack] entity.GetMaterial rejected - path not whitelisted - ('"..callpath.."')")
				return ""
			end
		end
	end
	return ret or ""
end


local ogaf = GetAddonInfo

function GetAddonInfo(addon)
	local callpath = debug.getinfo(2) and debug.getinfo(2)['short_src'] or nil
	if callpath then
		if addon == "FapHack" and !IsWhite(callpath) then
			MsgN("[FapHack] GetAddonInfo('"..addon.."') rejected - path not whitelisted - ('"..callpath.."')")
			return nil;
		end
	end
	return ogaf(addon)
end

FapHack:Detour("_G" , "GetAddonInfo" , ogaf)


-- Custom binding system --

-- Disabled by default. I mean, looping 130 times per frame isn't something everyone wants --

local keys = {
[0] = "KEY_NONE",
[1] = "KEY_0",
[2] = "KEY_1",
[3] = "KEY_2",
[4] = "KEY_3",
[5] = "KEY_4",
[6] = "KEY_5",
[7] = "KEY_6",
[8] = "KEY_7",
[9] = "KEY_8",
[10] = "KEY_9",
[11] = "KEY_A",
[12] = "KEY_B",
[13] = "KEY_C",
[14] = "KEY_D",
[15] = "KEY_E",
[16] = "KEY_F",
[17] = "KEY_G",
[18] = "KEY_H",
[19] = "KEY_I",
[20] = "KEY_J",
[21] = "KEY_K",
[22] = "KEY_L",
[23] = "KEY_M",
[24] = "KEY_N",
[25] = "KEY_O",
[26] = "KEY_P",
[27] = "KEY_Q",
[28] = "KEY_R",
[29] = "KEY_S",
[30] = "KEY_T",
[31] = "KEY_U",
[32] = "KEY_V",
[33] = "KEY_W",
[34] = "KEY_X",
[35] = "KEY_Y",
[36] = "KEY_Z",
[37] = "KEY_PAD_0",
[38] = "KEY_PAD_1",
[39] = "KEY_PAD_2",
[40] = "KEY_PAD_3",
[41] = "KEY_PAD_4",
[42] = "KEY_PAD_5",
[43] = "KEY_PAD_6",
[44] = "KEY_PAD_7",
[45] = "KEY_PAD_8",
[46] = "KEY_PAD_9",
[47] = "KEY_PAD_DIVIDE",
[48] = "KEY_PAD_MULTIPLY",
[49] = "KEY_PAD_MINUS",
[50] = "KEY_PAD_PLUS",
[51] = "KEY_PAD_ENTER",
[52] = "KEY_PAD_DECIMAL",
[53] = "KEY_LBRACKET",
[54] = "KEY_RBRACKET",
[55] = "KEY_SEMICOLON",
[56] = "KEY_APOSTROPHE",
[57] = "KEY_BACKQUOTE",
[58] = "KEY_COMMA",
[59] = "KEY_PERIOD",
[60] = "KEY_SLASH",
[61] = "KEY_BACKSLASH",
[62] = "KEY_MINUS",
[63] = "KEY_EQUAL",
[64] = "KEY_ENTER",
[65] = "KEY_SPACE",
[66] = "KEY_BACKSPACE",
[67] = "KEY_TAB",
[68] = "KEY_CAPSLOCK",
[69] = "KEY_NUMLOCK",
[70] = "KEY_ESCAPE",
[71] = "KEY_SCROLLLOCK",
[72] = "KEY_INSERT",
[73] = "KEY_DELETE",
[74] = "KEY_HOME",
[75] = "KEY_END",
[76] = "KEY_PAGEUP",
[77] = "KEY_PAGEDOWN",
[78] = "KEY_BREAK",
[79] = "KEY_LSHIFT",
[80] = "KEY_RSHIFT",
[81] = "KEY_LALT",
[82] = "KEY_RALT",
[83] = "KEY_LCONTROL",
[84] = "KEY_RCONTROL",
[85] = "KEY_LWIN",
[86] = "KEY_RWIN",
[87] = "KEY_APP",
[88] = "KEY_UP",
[89] = "KEY_LEFT",
[90] = "KEY_DOWN",
[91] = "KEY_RIGHT",
[92] = "KEY_F1",
[93] = "KEY_F2",
[94] = "KEY_F3",
[95] = "KEY_F4",
[96] = "KEY_F5",
[97] = "KEY_F6",
[98] = "KEY_F7",
[99] = "KEY_F8",
[100] = "KEY_F9",
[101] = "KEY_F10",
[102] = "KEY_F11",
[103] = "KEY_F12",
[104] = "KEY_CAPSLOCKTOGGLE",
[105] = "KEY_NUMLOCKTOGGLE",
[106] = "KEY_SCROLLLOCKTOGGLE",
[107] = "KEY_XBUTTON_UP",
[108] = "KEY_XBUTTON_DOWN",
[109] = "KEY_XBUTTON_LEFT",
[110] = "KEY_XBUTTON_RIGHT",
[111] = "KEY_XBUTTON_START",
[112] = "KEY_XBUTTON_BACK",
[113] = "KEY_XBUTTON_STICK1",
[114] = "KEY_XBUTTON_STICK2",
[115] = "KEY_XBUTTON_A",
[116] = "KEY_XBUTTON_B",
[117] = "KEY_XBUTTON_X",
[118] = "KEY_XBUTTON_Y",
[119] = "KEY_XBUTTON_BLACK",
[120] = "KEY_XBUTTON_WHITE",
[121] = "KEY_XBUTTON_LTRIGGER",
[122] = "KEY_XBUTTON_RTRIGGER",
[123] = "KEY_XSTICK1_UP",
[124] = "KEY_XSTICK1_DOWN",
[125] = "KEY_XSTICK1_LEFT",
[126] = "KEY_XSTICK1_RIGHT",
[127] = "KEY_XSTICK2_UP",
[128] = "KEY_XSTICK2_DOWN",
[129] = "KEY_XSTICK2_LEFT",
[130] = "KEY_XSTICK2_RIGHT",
}

local keytimes = {}
local binds = file.Exists("faphack_keybinds.txt") and KeyValuesToTable(file.Read("faphack_keybinds.txt")) or {}

function FapHack.GetKeyPresses()
	if FapHack.Settings.EnableKeyBinding then
		for k , v in ipairs(keys) do
			if input.IsKeyDown(k) and !(keytimes[k] and keytimes[k] > CurTime()) then
				for a, b in pairs(binds) do
					if b.key == v then
						-- player.ConCommand is retarded and blocks anything with "toggle" in it.
						-- This is a sort-of work around, allowing me to run several commands (using ;)
						local commands = string.Explode(";" , b.command)
						for k , v in pairs(commands) do
							local args = string.Explode(" " , v)
							local cmd = args[1]
							table.remove(args , 1)
							RunConsoleCommand(cmd , args)
						end
						keytimes[k] = CurTime() + 1
					end
				end
			end
		end
	end
end

FapHack.Hook("Think" , FapHack.GetKeyPresses)

function FapHack.BindKey(key , command)
	table.insert(binds , {key = key , command = command } )
	file.Write("faphack_keybinds.txt" , TableToKeyValues(binds))
end

function FapHack.UnBindKey(key)
	for k , v in pairs(binds) do
		if v.key == key then
			binds[k] = nil
		end
	end
	binds = tableSetKeys(binds)
	file.Write("faphack_keybinds.txt" , TableToKeyValues(binds))
end

concommand.Add("fap_bind" , function(p , c , a)
	for k , v in ipairs(keys) do
		if "KEY_"..string.upper(a[1]) == v then
			if a[2] then
				FapHack.BindKey(v , a[2])
				MsgN("[FapHack] Bound key "..v.. " to command ".. a[2])
			end
		end
	end
end )

concommand.Add("fap_unbind" , function(p , c , a)
	for k , v in ipairs(keys) do
		if "KEY_"..string.upper(a[1]) == v then
			FapHack.UnBindKey(v)
			MsgN("[FapHack] Unbound key "..v)
		end
	end
end )


-- End of key binding --

MsgN(string.format("FapHack revision %d loaded\n\n\nEnjoy.\n\nGive suggestions at %s\n\n\nSponsored by FanaticalDev\n\nhttp://fanaticaldev.com\nhttp://fanaticalvps.com\n\nFizz's a really awesome guy, I reccommend him for all of your web development or VPS needs." , FapHack.Revision, "http://www.facepunch.com/showthread.php?977939"))
MsgN("\n\ngarry newman is a cunt. If you're ever unfortunate enough to be ingame with him, call him a cunt from me.")
