--[[
	lua/autorun/client/scripts/no_v3l.lua
	Akorcharlie | (STEAM_0:1:34029133)
	===DStream===
]]

/* * * * * * * * * * * * * * * * 
 * 	 ______     __  __     ______     __  __     ______     ______     __  __    
 *	/\  __ \   /\ \/\ \   /\  == \   /\ \_\ \   /\  __ \   /\  ___\   /\ \/ /    
 *	\ \ \/\ \  \ \ \_\ \  \ \  __<   \ \  __ \  \ \  __ \  \ \ \____  \ \  _"-.  
 *	 \ \_____\  \ \_____\  \ \_____\  \ \_\ \_\  \ \_\ \_\  \ \_____\  \ \_\ \_\ 
 *	  \/_____/   \/_____/   \/_____/   \/_/\/_/   \/_/\/_/   \/_____/   \/_/\/_/ 
 *
 *  - Version : 3L
 *  - By Oubliette
 * * * * * * * * * * * * * * * */

// Font = Banner

// TEMP 

require( "oubhack" );

// TEMP

local IOubHack = OH_CPP_INTERFACE;

// Clean-up global
IOubHack.CleanUpGlobals();
OH_CPP_INTERFACE = nil;

local g, r, OH = {}, {}, {};
local me;

local tCopy = function( t, copied, f ) 

	local new = {};
	copied = copied or {};

	for k, v in pairs( t ) do 

		if ( istable( v ) && !copied[ v ] ) then 

			copied[ v ] = true;
			new[ k ] = f( t[ k ], copied, f );

		else 

			new[ k ] = v;

		end


	end

	return table.Copy( new );

end;

g = tCopy( _G, {}, tCopy ); r = tCopy( debug.getregistry(), {}, tCopy );

/*
	 #####                                                                                                 
	#     # #       ####  #####    ##   #         ###### #    # #    #  ####  ##### #  ####  #    #  ####  
	#       #      #    # #    #  #  #  #         #      #    # ##   # #    #   #   # #    # ##   # #      
	#  #### #      #    # #####  #    # #         #####  #    # # #  # #        #   # #    # # #  #  ####  
	#     # #      #    # #    # ###### #         #      #    # #  # # #        #   # #    # #  # #      # 
	#     # #      #    # #    # #    # #         #      #    # #   ## #    #   #   # #    # #   ## #    # 
	 #####  ######  ####  #####  #    # ######    #       ####  #    #  ####    #   #  ####  #    #  ####  
*/
// By global I mean it fits under no category or is used by more than one category, the functions are still local.

// Nice function to test if a number is equal to another within a certain range, used with Lerps
function OH.Within( x, y, threshold )

	return g.math.abs( x - y ) <= threshold;

end

// Usesd to draw invisible panels, if debugging mode is on outlines are drawn
function OH.DrawInvisible( x, y, w, h )

	if ( OH.Get( "GUI", "debug" ) ) then 

		g.surface.SetDrawColor( g.Color( 0, 0, 0, 255 ) );
		g.surface.DrawOutlinedRect( x, y, w, h );

		g.surface.SetDrawColor( g.Color( 0, 0, 0, 255 ) );
		g.surface.DrawOutlinedRect( x + 3, y + 3, w - 6, h - 6 );

	end

end

// Generates a random string of a specified length, for timers
function OH.RandomString( len )

	str = "";

	for i = 0, len do 

		str = str .. string.char( math.random(97,122) );

	end

	return str;

end

// Returns true if a character is upper case 
function OH.IsUpper( char )

	return g.string.byte( char ) >= 65 && g.string.byte( char ) <= 90;

end

// Returns true if a character is lower case 
function OH.IsLower( char )

	return g.string.byte( char ) >= 97 && g.string.byte( char ) <= 122;

end


// Converts one string to another string's case pattern arg1 -> arg2
function OH.MatchCase( str, str2 )

	// sug, text
	local newStr = "";

	for i = 1, str:len() do 

		if ( str2[ i ] == "" ) then newStr = newStr .. str:sub( i, str:len() ); break; end

		if ( OH.IsUpper( str2[ i ] ) ) then newStr = newStr .. g.string.upper( str[ i ] ); continue; end 
		if ( OH.IsLower( str2[ i ] ) ) then newStr = newStr .. g.string.lower( str[ i ] ); continue; end
		newStr = newStr .. str[ i ];

	end

	return newStr;

end


/*
	 #####                                                                               #####                                                        
	#     #  ####  #    # ###### #  ####  #    # #####    ##   ##### #  ####  #    #    #     # ##### #####  #    #  ####  #    # ##### #####  ###### 
	#       #    # ##   # #      # #    # #    # #    #  #  #    #   # #    # ##   #    #         #   #    # #    # #    # #    #   #   #    # #      
	#       #    # # #  # #####  # #      #    # #    # #    #   #   # #    # # #  #     #####    #   #    # #    # #      #    #   #   #    # #####  
	#       #    # #  # # #      # #  ### #    # #####  ######   #   # #    # #  # #          #   #   #####  #    # #      #    #   #   #####  #      
	#     # #    # #   ## #      # #    # #    # #   #  #    #   #   # #    # #   ##    #     #   #   #   #  #    # #    # #    #   #   #   #  #      
	 #####   ####  #    # #      #  ####   ####  #    # #    #   #   #  ####  #    #     #####    #   #    #  ####   ####   ####    #   #    # ###### 
*/

OH.Keys = {
	
	{ "A", KEY_A, "" }, { "B", KEY_B, "" }, { "C", KEY_C, "" }, { "D", KEY_D, "" }, { "E", KEY_E, "" }, { "F", KEY_F, "" },
	{ "G", KEY_G, "" }, { "H", KEY_H, "" }, { "I", KEY_I, "" }, { "J", KEY_J, "" }, { "K", KEY_K, "" }, { "L", KEY_L, "" },
	{ "M", KEY_M, "" }, { "N", KEY_N, "" }, { "O", KEY_O, "" }, { "P", KEY_P, "" }, { "Q", KEY_Q, "" }, { "R", KEY_R, "" },
	{ "S", KEY_S, "" }, { "T", KEY_T, "" }, { "U", KEY_U, "" }, { "V", KEY_V, "" }, { "W", KEY_W, "" }, { "X", KEY_X, "" },
	{ "Y", KEY_Y, "" }, { "Z", KEY_Z, "" }, { "1", KEY_1, "" }, { "2", KEY_2, "" }, { "3", KEY_3, "" }, { "4", KEY_4, "" },
	{ "5", KEY_5, "" }, { "6", KEY_6, "" }, { "7", KEY_7, "" }, { "8", KEY_8, "" }, { "9", KEY_9, "" }, { "0", KEY_0, "" }, 

	{ ",", KEY_COMMA, "" }, { ".", KEY_PERIOD, "" }, { "/", KEY_SLASH, "" }, { ";", KEY_SEMICOLON, "" },
	{ "'", KEY_APOSTROPHE, "" }, { "\\", KEY_BACKSLASH, "" }, { "[", KEY_LBRACKET, "" }, { "]", KEY_RBRACKET, "" },
	{ "rclick", MOUSE_RIGHT, "" }, { "lclick", MOUSE_LEFT, "" }, { "rctrl", KEY_RCONTROL, "" },
	{ "lctrl", KEY_LCONTROL, "" }, { "ralt", KEY_LALT, "" }, { "lalt", KEY_RALT, "" },

	{ "lshift", KEY_LSHIFT, "" }, { "rshift", KEY_RSHIFT, "" }, { "enter", KEY_ENTER, "" },
	{ "up", KEY_UP, "" }, { "down", KEY_DOWN, "" }, { "left", KEY_LEFT, "" }, { "right", KEY_RIGHT, "" },
	{ "tab", KEY_TAB, "" }, { "backspace", KEY_BACKSPACE, "" }, { "equal", KEY_EQUAL, "" }, { "minus", KEY_MINUS, "" },
	{ "F1", KEY_F1, "" }, { "F2", KEY_F2, "" }, { "F3", KEY_F3, "" }, { "F4", KEY_F4, "" }, { "F5", KEY_F5, "" }, { "F6", KEY_F6, "" },

	{ "F7", KEY_7, "" }, { "F8", KEY_F8, "" }, { "F9", KEY_F9, "" }, { "F10", KEY_F10, "" }, { "F11", KEY_F11, "" }, { "F12", KEY_F12, "" },
	{ "scrlock", KEY_SCROLLLOCK, "" }, { "space", KEY_SPACE, "" }, { "insert", KEY_INSERT, "" }, { "del", KEY_DELETE, "" }
	
};

OH.ConfigurationStructure = {
	
	[ "Aimbot" ] = {

		reg = 0x01,

		enabled = true,
		trace_key = IN_ATTACK,
		trace_bone = "ValveBiped.Bip01_Head1",

		target_players = true,
		target_bots = true,
		target_npcs = true,

		target_admins = false,
		target_super_admins = false,

		target_ownteam = true,

		target_traitors_as_traitor = false,
		target_innocents_as_innocent = false,

		antisnap_enabled = false,
		antisnap_speed = 0.90,

	},
	[ "Triggerbot" ] = {

		reg = 0x02,

		FIRE_WHEN_VISISBLE = 0x01,
		FIRE_WHEN_HOVERED = 0x02,

		enabled = false,

		delay = 0,

	},
	[ "LaserEyes" ] = {

		reg = 0x03,

		ignorez = false,
		colour = Color( 255, 0, 0, 255 ),
		length = 500

	},
	[ "ESP" ] = {

		reg = 0x04,

		ESP_BOX_MDOE = "Box Mode",

	},
	[ "Wallhack" ] = {

		reg = 0x05,

	},
	[ "Utilities" ] = {

		reg = 0x06,

	},
	[ "AntiAC" ] = {

		reg = 0x07,

	},
	[ "Logging" ] = {

		reg = 0x08,

		log_errors = true,
		log_console = true,
		log_warnings = true,
		log_severes = true

	},
	[ "Console" ] = {

		reg = 0x09,

		history_length = 100

	},
	[ "GUI" ] = {

		reg = 0xA,

		debug = false

	},
	[ "Binds" ] = {

		reg = 0xB,

		key_down = g.table.Copy( OH.Keys ),
		key_up = g.table.Copy( OH.Keys ),
		key_down_think = g.table.Copy( OH.Keys ),
		key_up_think = g.table.Copy( OH.Keys )

	}

};

IOubHack.LoadDefaultConfig( OH.ConfigurationStructure );

function OH.Get( region, name )

	if ( !name ) then return OH.ConfigurationStructure[ region ]; end

	return OH.ConfigurationStructure[ region ][ name ];

end

function OH.Set( region, name, value )

	OH.ConfigurationStructure[ region ][ name ] = value;

end

function OH.MatchConfigCase( str )

	for name, config in g.pairs( OH.ConfigurationStructure ) do 

		if ( name:lower() == str:lower() ) then return name; end

	end

	return str;

end
/*

	#     #      ##        #####   #####     ###                                                        
	#     #     #  #      #     # #     #     #  #    # ##### ###### #####  ######   ##    ####  ###### 
	#     #      ##       #       #           #  ##   #   #   #      #    # #       #  #  #    # #      
	#######     ###       #       #           #  # #  #   #   #####  #    # #####  #    # #      #####  
	#     #    #   # #    #       #           #  #  # #   #   #      #####  #      ###### #      #      
	#     #    #    #     #     # #     #     #  #   ##   #   #      #   #  #      #    # #    # #      
	#     #     ###  #     #####   #####     ### #    #   #   ###### #    # #      #    #  ####  ###### 

*/

OH.Commands = {};
OH.Hooks = {};

function OH.AddHook( name, func )

	OH.Hooks[ name ] = func;

end

function OH.AddCmd( name, func, writeFunc )

	writeFunc = writeFunc or function() return ""; end

	OH.Commands[ name ] = { execute = func, onType = writeFunc };

end

function OH.ExecuteCommand( name, ... )

	if ( !OH.Commands[ name ] ) then return nil; end
	return OH.Commands[ name ].execute( ... );

end 

function OH.AutoCompleteCommand( name, ... )

	if ( !OH.Commands[ name ] ) then return ""; end 

	return OH.Commands[ name ].onType( ... );

end

function OH.ExecuteCommands( commands )

	for name, args in g.pairs( commands ) do 

		local targs = {};

		for _, arg in g.pairs( args ) do targs[ arg ] = true; end

		local result, err = OH.ExecuteCommand( name:lower(), args, targs );

		if ( OH.GUI.Console && OH.GUI.Console:IsVisible() ) then 

			//OH.Logging.Print( OH.Get( "Logging", "log_console" ), "> " .. name );

			if ( result == nil ) then 

				OH.Logging.Print( OH.Get( "Logging", "log_console" ), Color( 255, 0, 0, 225 ), "] No such command '" .. name .. "'!" );
				OH.GUI.ConsoleErrorFlash();

			elseif ( !result ) then

				OH.GUI.ConsoleErrorFlash();
				if ( err ) then 

					OH.Logging.Print( OH.Get( "Logging", "log_console" ), Color( 255, 0, 0, 225 ), "] ERROR: " .. err );

				else 

					OH.Logging.Print( OH.Get( "Logging", "log_console" ), Color( 255, 0, 0, 225 ), "] ERROR: Unknown error!" );

				end

			end

		end

	end

end

function OH.ParseCommands( com ) 

	// parse the command

	local isEncap = false;
	local commands = {};

	com = com .. " ";

	local name, _name, arg = "", "", "";
	for i = 1, com:len() do 

		if ( com[ i ] == "\"" ) then 

			// Check if there's another double quote before encapsulating the input 
			if ( !g.string.find( com, "\"", i + 1 ) && !isEncap ) then continue; end
			isEncap = !isEncap;

		elseif ( com[ i ] == ";" && !isEncap ) then 

			// name wasn't "finished" 
			if ( name == "" ) then commands[ _name ] = {}; end

			// Insert current argument 
			if ( arg != "" ) then 

				commands[ _name ][ #commands[ _name ] + 1 ] = arg;

				// Clear arg for next command
				arg = "";

			end

			// Establish a command name again
			name, _name = "", "";


		elseif ( com[ i ] == " " && !isEncap ) then 

			if ( name == "" ) then 

				name = _name; 
				commands[ name ] = {};

			else 

				commands[ name ][ #commands[ name ] + 1 ] = arg;
				arg = "";

			end


		else 

			if ( name == "" ) then 

				_name = _name .. com[ i ];

			else 

				arg = arg .. com[ i ];

			end 

		end

	end

	return commands;

end

/*
	#     #  #####  #     # ###    #######                                                 
	#     # #     # #     #  #     #       #      ###### #    # ###### #    # #####  ####  
	#     # #       #     #  #     #       #      #      ##  ## #      ##   #   #   #      
	#     # #  #### #     #  #     #####   #      #####  # ## # #####  # #  #   #    ####  
	 #   #  #     # #     #  #     #       #      #      #    # #      #  # #   #        # 
	  # #   #     # #     #  #     #       #      #      #    # #      #   ##   #   #    # 
	   #     #####   #####  ###    ####### ###### ###### #    # ###### #    #   #    ###
*/

OH.VGUI = {};
OH.VGUI.ElementFactory = {};

/* ======================================================================================================================================= */

local panel = {};

function panel:Init()

	self.colour = Color( 0, 0, 0, 0 );
	self.callback = function() end;
	self.isFaded = true;

end 

function panel:GetColour()

	return self.colour;

end 

function panel:Paint()

	OH.DrawInvisible( 0, 0, self:GetWide(), self:GetTall() );

end

function panel:ColorChanged()

	// Override

end

function panel:Think()

	if ( !self.targetPosX ) then self.targetPosX = self.x; end
	if ( !self.targetPosY ) then self.targetPosY = self.y; end

	// Colour 

	if ( self.isFaded && !OH.Within( self.colour.a, 0, 2 ) ) then 

		self.colour.a = g.Lerp( 0.70, self.colour.a, 0 );
		panel:ColorChanged( self.colour.a );

	elseif ( !self.isFaded && !OH.Within( self.colour.a, 255, 2 ) ) then 

		self.colour.a = g.Lerp( 0.70, self.colour.a, 255 );
		panel:ColorChanged( self.colour.a );

	end 

	// Position 

	if ( !OH.Within( self.x, self.targetPosX, 3 ) || !OH.Within( self.y, self.targetPosY, 3 ) ) then 

		self.x = g.Lerp( 0.70, self.x, self.targetPosX );
		self.y = g.Lerp( 0.70, self.y, self.targetPosY );

		self:SetPos( self.x, self.y );

		self.canCallCB = true;

	else 

		if ( self.canCallCB ) then self.callback(); end
		self.canCallCB = false;

	end 

end 

function panel:SetCallback( func )

	self.callback = func;

end

function panel:GoTo( x, y )

	self.targetPosX, self.targetPosY = x, y;

end 

function panel:FadeIn()

	self.isFaded = false;

end 

function panel:FadeOut() 

	self.isFaded = true;

end

g.timer.Simple( 0.1, function() OH.VGUI.RegisterElement( "OHSlidePanel", panel, "EditablePanel" ) end );

/* ======================================================================================================================================== */

// Element registration and creation
function OH.VGUI.RegisterElement( name, mtable, base )

	if ( !name || !mtable ) then return false; end

	mtable.Base = base or "Panel";
	OH.VGUI.ElementFactory[ name ] = mtable;

	return OH.VGUI.ElementFactory[ name ];

end

function OH.VGUI.CreateElement( name, parent )

	if ( OH.VGUI.ElementFactory[ name ] ) then 

		local tab = OH.VGUI.ElementFactory[ name ];
		local panel = OH.VGUI.CreateElement( tab.Base, parent );

		g.table.Merge( panel:GetTable(), tab );

		panel.ClassName, panel.BaseClass = name, OH.VGUI.ElementFactory[ tab.Base ];

		if ( panel.Init ) then 

			local st, err = g.pcall( panel.Init, panel );
			if ( !st ) then OH.Logging.ThrowError( "Panel " .. name .. " failed to initialize! - " .. err ); return nil; end

		end

		panel:Prepare(); return panel;

	end 

	return g.vgui.Create( name, parent );

end

/*
	 #####                                                        #     #                         ###                                                        
	#     # #####    ##   #####  #    # #  ####    ##   #         #     #  ####  ###### #####      #  #    # ##### ###### #####  ######   ##    ####  ###### 
	#       #    #  #  #  #    # #    # # #    #  #  #  #         #     # #      #      #    #     #  ##   #   #   #      #    # #       #  #  #    # #      
	#  #### #    # #    # #    # ###### # #      #    # #         #     #  ####  #####  #    #     #  # #  #   #   #####  #    # #####  #    # #      #####  
	#     # #####  ###### #####  #    # # #      ###### #         #     #      # #      #####      #  #  # #   #   #      #####  #      ###### #      #      
	#     # #   #  #    # #      #    # # #    # #    # #         #     # #    # #      #   #      #  #   ##   #   #      #   #  #      #    # #    # #      
	 #####  #    # #    # #      #    # #  ####  #    # ######     #####   ####  ###### #    #    ### #    #   #   ###### #    # #      #    #  ####  ######
*/

OH.GUI = {};
OH.GUI.ConsoleHistory = {};
OH.GUI.CurrentConsoleHistoryIndex = 1;

function OH.GUI.AppendConsoleHistory( com )

	OH.GUI.ConsoleHistory[ #OH.GUI.ConsoleHistory + 1 ] = com;

	if ( #OH.GUI.ConsoleHistory >= OH.Get( "Console", "history_length" ) ) then g.table.remove( 1, OH.GUI.ConsoleHistory ); end

end

function OH.GUI.ConsoleOnTextChanged( panel )

	local text = panel:GetValue();
	local sug = "";

	if ( OH.GUI.Console && OH.GUI.Console.SuggestionsList ) then OH.GUI.Console.SuggestionsList:Clear(); end

	for name, data in pairs( OH.Commands ) do 

		if ( text == "" ) then break; end 

		// Only allow incomplete command names
		if ( name:sub( 1, text:len() ):lower() == text:lower() && text:lower() != name:lower() ) then 

			if ( sug == "" ) then sug = name; end
			if ( OH.GUI.Console && OH.GUI.Console.SuggestionsList ) then OH.GUI.Console.SuggestionsList:AddLine( name ); end

		end

	end 

	if ( OH.GUI.Console && OH.GUI.Console.SuggestionOverlay && sug != "" ) then 

		OH.GUI.Console.SuggestionOverlay:SetText( OH.MatchCase( sug, text ) );
		OH.GUI.Console.SuggestionsList:SetVisible( true ); 

	elseif ( OH.Commands[ g.string.Explode( " ", text )[ 1 ] ] ) then 

		local command = g.string.Explode( " ", text )[ 1 ];

		local parsed = OH.ParseCommands( text )[ command ] or false;

		if ( parsed ) then 

			local sug, sugs =  OH.AutoCompleteCommand( g.string.Explode( " ", text )[ 1 ], command, parsed, text );

			if ( sugs && #sugs <= 0 ) then 

				OH.GUI.Console.SuggestionsList:SetVisible( false );

			elseif ( sugs ) then

				OH.GUI.Console.SuggestionsList:SetVisible( true );
				for _, data in g.pairs( sugs ) do 

					OH.GUI.Console.SuggestionsList:AddLine( data.display );
					OH.GUI.Console.SuggestionsList.Overrides = OH.GUI.Console.SuggestionsList.Overrides or {};
					OH.GUI.Console.SuggestionsList.Overrides[ data.display ] = data.text;

				end

			end


			OH.GUI.Console.SuggestionOverlay:SetText( sug );

		else // Should never happen

			OH.GUI.ConsoleErrorFlash();
			OH.Logging.Print( OH.Get( "Logging", "log_errors" ) , g.Color( 225, 0, 0, 255 ), "Internal command auto-complete parse error!" );

		end

	else 

		OH.GUI.Console.SuggestionsList:SetVisible( false );
		OH.GUI.Console.SuggestionOverlay:SetText("");

	end

end

function OH.GUI.ConsoleOnKey( panel, key )

	if ( key == KEY_UP || key == KEY_DOWN ) then 

		local inc = ( key == KEY_UP and -1 or 1 );
		local val = OH.GUI.CurrentConsoleHistoryIndex;

		if ( OH.GUI.ConsoleHistory[ val + inc ] ) then

			OH.GUI.CurrentConsoleHistoryIndex = val + inc; 

			panel:SetText( OH.GUI.ConsoleHistory[ OH.GUI.CurrentConsoleHistoryIndex ] );
			panel:SetCaretPos( panel:GetValue():len() );

		else 

			OH.GUI.ConsoleErrorFlash();

		end

	elseif ( key == KEY_ESCAPE ) then 

		OH.GUI.ConsoleClose();

	elseif ( key == KEY_ENTER ) then 

		OH.GUI.ConsoleOnCommand( panel );

	elseif ( key == KEY_TAB ) then 

		if ( OH.GUI.Console.SuggestionOverlay && OH.GUI.Console.SuggestionOverlay:GetText() != "" ) then 

			panel:SetText( OH.GUI.Console.SuggestionOverlay:GetText() );
			OH.GUI.ConsoleOnTextChanged( panel );

		end

		// For some reason pressing tab loses focus, let's give it back to us here
		g.timer.Simple( 0, function() 

			panel:RequestFocus();
			panel:SetCaretPos( isstring( panel:GetValue() ) and panel:GetValue():len() or 1 );

		end);

	end 

end

function OH.GUI.ConsoleOnCommand( panel )

	local com = panel:GetValue();
	

	OH.GUI.AppendConsoleHistory( com );
	OH.GUI.CurrentConsoleHistoryIndex = #OH.GUI.ConsoleHistory + 1;

	g.timer.Simple( 0, function() panel:RequestFocus(); panel:SetText(""); end );

	OH.ExecuteCommands( OH.ParseCommands( com ) );

end

function OH.GUI.ConsoleCreate()

	// Console back panel, never "visible" - there's no drawing done here
	OH.GUI.Console = OH.VGUI.CreateElement( "DPanel" )

	OH.GUI.Console:SetPos( g.ScrW() * 0.50, 0 );
	OH.GUI.Console:SetSize( g.ScrW() * 0.50, g.ScrH() );

	OH.GUI.Console:SetVisible( false );
	OH.GUI.Console.Paint = function( panel ) OH.DrawInvisible( 0, 0, panel:GetWide(), panel:GetTall() ) end;

	// Console parent, used as a nice way to achieve the slide effect
	OH.GUI.Console.SlidePanel = OH.VGUI.CreateElement( "OHSlidePanel" );
	OH.GUI.Console.SlidePanel:SetSize( OH.GUI.Console:GetWide() - 200, OH.GUI.Console:GetTall() - 200 );
	OH.GUI.Console.SlidePanel:SetVisible( false );

	// The back of the rich text panel
	OH.GUI.Console.RichTextBack = OH.VGUI.CreateElement( "DPanel", OH.GUI.Console.SlidePanel );

	OH.GUI.Console.RichTextBack:SetPos( 100 + 4, 1 );
	OH.GUI.Console.RichTextBack:SetSize( OH.GUI.Console.SlidePanel:GetWide() - 100, OH.GUI.Console.SlidePanel:GetTall() - 100 - 30 - 2 );

	// Flash panel

	OH.GUI.Console.FlashPanel = OH.VGUI.CreateElement( "DPanel", OH.GUI.Console.SlidePanel )

	OH.GUI.Console.FlashPanel:SetPos( 100 + 4, 1 );
	OH.GUI.Console.FlashPanel:SetSize( OH.GUI.Console.RichTextBack:GetSize() );

	OH.GUI.Console.FlashPanel.Paint = function( panel )

		if ( !panel.fCol ) then panel.fCol = g.Color( 0, 0, 0, 0 ); end 

		if ( panel.fCol.a > 0 ) then panel.fCol.a = g.math.Approach( panel.fCol.a, 0, 5 ); end 

		g.surface.SetDrawColor( panel.fCol );
		g.surface.DrawRect( 0, 0, panel:GetSize() );

	end

	// Console text handler
	OH.GUI.Console.RichText = OH.VGUI.CreateElement( "RichText", OH.GUI.Console.SlidePanel );

	OH.GUI.Console.RichText:SetPos( 100 + 4, 1 );
	OH.GUI.Console.RichText:SetSize( OH.GUI.Console.RichTextBack:GetSize() );

	OH.GUI.Console.RichText:SetVerticalScrollbarEnabled( true );

	// Text entry
	OH.GUI.Console.TextEntry = OH.VGUI.CreateElement( "DTextEntry", OH.GUI.Console.SlidePanel );

	OH.GUI.Console.TextEntry:SetPos( 100 + 4 , 1 + OH.GUI.Console.RichText:GetTall() + 2 );
	OH.GUI.Console.TextEntry:SetSize( OH.GUI.Console.RichText:GetWide() - 8, 30 );

	OH.GUI.Console.TextEntry:SetEnterAllowed( true );
	OH.GUI.Console.TextEntry:SetEditable( true );

	OH.GUI.Console.TextEntry.OnTextChanged = OH.GUI.ConsoleOnTextChanged;
	OH.GUI.Console.TextEntry.OnKeyCodeTyped = OH.GUI.ConsoleOnKey;
	OH.GUI.Console.TextEntry:SetFont( "default" )

	// Suggestion overlay
	OH.GUI.Console.SuggestionOverlay = OH.VGUI.CreateElement( "DLabel", OH.GUI.Console.TextEntry );

	OH.GUI.Console.SuggestionOverlay:SetPos( 3, 0 );
	OH.GUI.Console.SuggestionOverlay:SetSize( OH.GUI.Console.TextEntry:GetSize() );

	OH.GUI.Console.SuggestionOverlay:SetTextColor( g.Color( 130, 130, 130, 150 ) );
	OH.GUI.Console.SuggestionOverlay:SetText( "" );

	OH.GUI.Console.SuggestionOverlay:SetFont( "default" );

	// Suggestions list
	OH.GUI.Console.SuggestionsList = OH.VGUI.CreateElement( "DListView", OH.GUI.Console.SlidePanel );

	OH.GUI.Console.SuggestionsList:SetPos( 0, 1 );
	OH.GUI.Console.SuggestionsList:SetSize( 100, OH.GUI.Console.SlidePanel:GetTall() - 100 );
	OH.GUI.Console.SuggestionsList:AddColumn( "Name" );

	OH.GUI.Console.SuggestionsList:SetMultiSelect( false );
	OH.GUI.Console.SuggestionsList:SetVisible( false );

	OH.GUI.Console.SuggestionsList.OnRowSelected = function( panel, line )

		if ( OH.GUI.Console && OH.GUI.Console.SuggestionOverlay ) then 

			local text = panel:GetLine( line ):GetValue( 1 );

			if ( panel.Overrides && panel.Overrides[ text ] ) then text = panel.Overrides[ text ]; end

			OH.GUI.Console.SuggestionOverlay:SetText( text ); 

		end

	end

	OH.GUI.Console.SuggestionsList.DoDoubleClick = function( panel, line )

		if ( OH.GUI.Console && OH.GUI.Console.TextEntry ) then 

			local text = panel:GetLine( line ):GetValue( 1 );

			if ( panel.Overrides && panel.Overrides[ text ] ) then text = panel.Overrides[ text ]; end

			OH.GUI.Console.TextEntry:SetText( text ); 
			OH.GUI.Console.TextEntry:OnTextChanged();
			
		end

	end


end 

function OH.GUI.ConsoleErrorFlash()

	if ( !OH.GUI.Console || !OH.GUI.Console.FlashPanel ) then return; end

	OH.GUI.Console.FlashPanel.fCol = g.Color( 255, 0, 0, 255 );

end

function OH.GUI.ConsolePrint( ... )

	local arg = { ... };

	if ( !arg[ 1 ] ) then return false; end

	if ( OH.GUI.Console && OH.GUI.Console.RichText && g.IsValid( OH.GUI.Console.RichText ) ) then 

		for _, t in g.pairs( arg ) do 

			if ( isstring( t ) ) then 

				OH.GUI.Console.RichText:AppendText( t );

			elseif ( istable( t ) ) then 

				OH.GUI.Console.RichText:InsertColorChange( t.r, t.g, t.b, t.a );

			end

		end

	else 

		g.timer.Simple( 0.1, function( ... ) OH.GUI.ConsolePrint( ... ) end );

	end


end

function OH.GUI.ConsoleOpen()

	if ( !g.IsValid( OH.GUI.Console ) ) then OH.GUI.ConsoleCreate(); end

	OH.GUI.Console:SetVisible( true );
	OH.GUI.Console.SlidePanel:SetVisible( true );

	OH.GUI.Console.SlidePanel:SetCallback( function() end );
	OH.GUI.Console.SlidePanel:MakePopup();

	OH.GUI.Console.SlidePanel:FadeIn();
	OH.GUI.Console.SlidePanel:SetPos( ScrW() - 1, 100 );
	OH.GUI.Console.SlidePanel:GoTo( ( ScrW() * 0.50 ) + 100.0, 100.0 );

	OH.GUI.Console.TextEntry:RequestFocus();

	g.gui.EnableScreenClicker( true );


end

function OH.GUI.ConsoleClose()

	if ( !g.IsValid( OH.GUI.Console ) ) then OH.GUI.ConsoleCreate(); end

	OH.GUI.Console:SetVisible( true );

	OH.GUI.Console.SlidePanel:SetCallback( function() OH.GUI.Console:SetVisible( false ); OH.GUI.Console.SlidePanel:SetVisible( false ); end );

	OH.GUI.Console.SlidePanel:FadeOut();
	OH.GUI.Console.SlidePanel:GoTo( ScrW() - 1.0, 100.0 );

	g.gui.EnableScreenClicker( false );

end

function OH.GUI.ConsoleToggle()

	if ( !g.IsValid( OH.GUI.Console ) ) then OH.GUI.ConsoleCreate(); end
	OH.GUI[ "Console" .. ( OH.GUI.Console:IsVisible() and "Close" or "Open" ) ]();

end
concommand.Add("opens",OH.GUI.ConsoleToggle);

g.timer.Simple( 0.1, OH.GUI.ConsoleCreate );

/*
	 #####                                                #####                                                   
	#     #  ####  #    #  ####   ####  #      ######    #     #  ####  #    # #    #   ##   #    # #####   ####  
	#       #    # ##   # #      #    # #      #         #       #    # ##  ## ##  ##  #  #  ##   # #    # #      
	#       #    # # #  #  ####  #    # #      #####     #       #    # # ## # # ## # #    # # #  # #    #  ####  
	#       #    # #  # #      # #    # #      #         #       #    # #    # #    # ###### #  # # #    #      # 
	#     # #    # #   ## #    # #    # #      #         #     # #    # #    # #    # #    # #   ## #    # #    # 
	 #####   ####  #    #  ####   ####  ###### ######     #####   ####  #    # #    # #    # #    # #####   ####  
*/

/* ========================================================================================================================== */

OH.AddCmd( "help", function( args, targs )

	local text = ""

	for name, t in g.pairs( OH.Commands ) do 

		OH.Logging.Print( OH.Get( "Logging", "log_console" ), name );

	end

	return true;

end);

/* ========================================================================================================================== */

OH.AddCmd( "set", function( args, targs )

	local text = ""

	args[ 1 ] = OH.MatchConfigCase( args[ 1 ] or "" );

	if ( OH.ConfigurationStructure[ args[ 1 ] ] == nil ) then 

		return false, g.tostring( args[ 1 ] ) .. " doesn't exist!";

	end 

	if ( OH.ConfigurationStructure[ args[ 1 ] ][ args[ 2 ] ] == nil ) then 

		return false, g.tostring( args[ 1 ] ) .. "." .. g.tostring( args[ 2 ] ) .. " doesn't exist!";

	end 

	local value = args[ 3 ];

	if ( value == nil || ( g.isstring( value ) && ( value:lower() == "false" || value:lower() == "no") ) ) then value = false; end
	if ( g.isstring( value ) && ( value:lower() == "true" || value:lower() == "yes" ) ) then value = true; end
	if ( g.tonumber( value ) ) then value = g.tonumber( value ); end

	if ( g.type( OH.Get( args[ 1 ], args[ 2 ] ) ) != g.type( value ) ) then 

		return false, "Couldn't propagate value type!";

	end

	OH.Set( args[ 1 ], args[ 2 ], value );

	OH.Logging.Print( OH.Get( "Logging", "log_console" ), g.tostring( args[ 1 ] ) .. "." .. g.tostring( args[ 2 ] ) .. " = " .. g.tostring( args[ 3 ] ) );

	return true;

end,
function( fname, args, inp )

	local table = OH.ConfigurationStructure;
	local current = inp;

	if ( #args > 2 ) then return "", {}; end
	for _, arg in g.pairs( args ) do 

		local tabArg = OH.MatchConfigCase( arg );
		if ( table[ tabArg ] && istable( table[ tabArg ] ) ) then table = table[ tabArg ]; continue; end

		local ret, coms = "", {};
		for name, value in g.pairs( table ) do 

			if ( arg:lower() == name:sub( 1, arg:len() ):lower() && arg:lower() != name:lower() ) then 

				if ( ret == "" ) then ret = OH.MatchCase( current:sub( 1, current:len() - arg:len() ) .. name, current ); end
				coms[ #coms + 1 ] = { text = ( current .. name ), display = name };

			end

		end

		if ( ret != "" ) then return ret, coms; end

	end

	return "", {};

end);


/* ========================================================================================================================== */

OH.AddCmd( "get", function( args, targs )

	local text = ""

	args[ 1 ] = OH.MatchConfigCase( args[ 1 ] or "" );

	if ( OH.ConfigurationStructure[ args[ 1 ] ] == nil ) then 

		return false, g.tostring( args[ 1 ] ) .. " doesn't exist!";

	end 

	if ( args[ 2 ] && OH.ConfigurationStructure[ args[ 1 ] ][ args[ 2 ] ] == nil ) then 

		return false, g.tostring( args[ 1 ] ) .. "." .. g.tostring( args[ 2 ] ) .. " doesn't exist!";

	end 

	local value = OH.Get( args[ 1 ], args[ 2 ] );

	if ( g.istable( value ) ) then 

		for name, value in g.pairs( value ) do  

			OH.Logging.Print( OH.Get( "Logging", "log_console" ), g.tostring( args[ 1 ] ) .. "." .. name .. " = " .. g.tostring( value ) .. " | type = " .. g.type( value ) );

		end

	else 

		OH.Logging.Print( OH.Get( "Logging", "log_console" ), g.tostring( args[ 1 ] ) .. "." .. g.tostring( args[ 2 ] ) .. " = " .. g.tostring( value ) .. " | type = " .. g.type( value ) );

	end

	return true;

end, OH.Commands[ "set" ].onType );

/* ========================================================================================================================== */

OH.AddCmd( "bind_down", function( args, targs ) 

	local key = args[ 1 ] or "";
	local command = args[ 2 ] or "";

	for index, keydata in g.pairs( OH.Keys ) do 

		if ( keydata[ 1 ]:lower() == key:lower() ) then 

			local table = OH.Get( "Binds", "key_down" );

			table[ index ] = { keydata[ 1 ], keydata[ 2 ], command };

			OH.Logging.Print( OH.Get( "Logging", "log_console" ), ( command != "" and ( keydata[ 1 ] .. "_down bound to " .. command .. "!" ) or ( keydata[ 1 ] .. "_down unbound!" ) ) );

			OH.Set( "Binds", "key_down", table );

			OH.Binds.UpdateSafeBinds()

			return true;

		end

	end

	return false, "Key '" .. key .. "' not found!";

end, 
function( name, args, inp )

	local ret, coms = "", {};

	if ( !args[ 1 ] || #args != 1 ) then return ret, coms; end
	for index, keydata in g.pairs( OH.Keys ) do 

		local name = keydata[ 1 ];

		if ( args[ 1 ]:lower() == name:sub( 1, args[ 1 ]:len() ):lower() && args[ 1 ]:lower() != name:lower() ) then 

			if ( ret == "" ) then ret = inp:sub( 1, inp:len() - args[ 1 ]:len() ) .. name; end
			coms[ #coms + 1 ] = { text = ( inp .. name ), display = name };

		end

	end

	return ret, coms;

end);

/* ========================================================================================================================== */

OH.AddCmd( "bind_up", function( args, targs ) 

end, OH.Commands[ "bind_down" ].onType );

/* ========================================================================================================================== */

OH.AddCmd( "bind_dowm_think", function( args, targs ) 

end, OH.Commands[ "bind_down" ].onType );

/* ========================================================================================================================== */

OH.AddCmd( "bind_up_think", function( args, targs ) 

end, OH.Commands[ "bind_down" ].onType );

/* ========================================================================================================================== */

// Bind down macro
OH.AddCmd( "bind", OH.Commands[ "bind_down" ].execute, OH.Commands[ "bind_down" ].onType );

/* ========================================================================================================================== */

// Bind down macro
OH.AddCmd( "rcc", function( args, targs )

	local command = "";

	for _, com in g.pairs( args ) do 

		command = command .. com .. " ";

	end

	if ( command == "" ) then 

		return false, "Cannot run nothing!";

	end

	command = command:sub( 1, command:len() - 1 );

	r["Player"]["ConCommand"]( me, command );
	return true; 

end);

/* ========================================================================================================================== */

/*
	#     #                                  ##  #####                                #######                                                 ##   
	#     #  ####   ####  #    #  ####      #   #     # #    # ######   ##   #####    #       ######   ##   ##### #    # #####  ######  ####    #  
	#     # #    # #    # #   #  #         #    #       #    # #       #  #    #      #       #       #  #    #   #    # #    # #      #         # 
	####### #    # #    # ####    ####     #    #       ###### #####  #    #   #      #####   #####  #    #   #   #    # #    # #####   ####     # 
	#     # #    # #    # #  #        #    #    #       #    # #      ######   #      #       #      ######   #   #    # #####  #           #    # 
	#     # #    # #    # #   #  #    #     #   #     # #    # #      #    #   #      #       #      #    #   #   #    # #   #  #      #    #   #  
	#     #  ####   ####  #    #  ####       ##  #####  #    # ###### #    #   #      #       ###### #    #   #    ####  #    # ######  ####  ##   
*/

function _G.hook.Call( name, gm, ... )

	if OH.hooks[name] && me && IsValid( me ) && ( !OH.hidemode || hidemode_safehooks[ name ] ) then 

		g.hook.Call( name, gm, ... );
		return OH.hooks[ name ]( ... );

	else

		return g.hook.Call( name, gm, ... );

	end

end

// Aimbot 

// Wallhack

// ESP 

// Laser Eyes 

// Targetting utilities 

// Radar 

// Anti-cheat anti-detection & awareness 

// Binds
OH.Binds = {};
OH.Binds.SafeBinds = {};


function OH.Binds.CanRun()

	return true;

end

function OH.Binds.Handler()

	if ( !OH.Binds.CanRun() ) then return; end
	if ( g.input.IsKeyDown( KEY_Q ) ) then return; end

	for _, data in g.pairs( OH.Binds.SafeBinds ) do

		local index = data.index;

		if ( !OH.Keys[ index ] ) then continue; end

		if ( g.input.IsKeyDown( OH.Keys[ index ][ 2 ] ) ) then

			if ( OH.Get( "Binds", "key_down_think" )[ index ][ 3 ] != "" ) then OH.ExecuteCommands( OH.ParseCommands( OH.Get( "Binds", "key_down_think" )[ index ][ 3 ] ) ); end

			if ( !data.CalledKDF ) then 

				if ( OH.Get( "Binds", "key_down" )[ index ][ 3 ] != "" ) then OH.ExecuteCommands( OH.ParseCommands( OH.Get( "Binds", "key_down" )[ index ][ 3 ] ) ); end 

				data.CalledKDF = true; 
				data.CalledKRF = false;

			end

		else 

			if ( OH.Get( "Binds", "key_up_think" )[ index ][ 3 ] != "" ) then OH.ExecuteCommands( OH.ParseCommands( OH.Get( "Binds", "key_up_think" )[ index ][ 3 ] ) ); end

			if ( !data.CalledKRF ) then 

				if ( OH.Get( "Binds", "key_up" )[ index ][ 3 ] != "" ) then OH.ExecuteCommands( OH.ParseCommands( OH.Get( "Binds", "key_up" )[ index ][ 3 ] ) ); end 

				data.CalledKDF = false; 
				data.CalledKRF = true;

			end

		end

	end

end

function OH.Binds.UpdateSafeBinds()

	OH.Binds.SafeBinds = {};

	for index, keydata in g.pairs( OH.Keys ) do 

		for _, v in g.pairs( { "key_down", "key_up", "key_up_think", "key_down_think" } ) do 

			if ( OH.Get( "Binds", v )[ index ] && OH.Get( "Binds", v )[ index ][ 3 ] != "" ) then 

				OH.Binds.SafeBinds[ #OH.Binds.SafeBinds + 1 ] = { index = index, CalledKDF = false, CalledKRF = false };

			end

		end

	end

end

OH.Binds.UpdateSafeBinds();
OH.AddHook( "Tick", OH.Binds.Handler );

/*
	 #####                                        #######                                               ######                                           
	#     # #       ####  #####    ##   #         #       #    # #    #  ####  ##### #  ####  #    #    #     # ###### #####  ####  #    # #####   ####  
	#       #      #    # #    #  #  #  #         #       #    # ##   # #    #   #   # #    # ##   #    #     # #        #   #    # #    # #    # #      
	#  #### #      #    # #####  #    # #         #####   #    # # #  # #        #   # #    # # #  #    #     # #####    #   #    # #    # #    #  ####  
	#     # #      #    # #    # ###### #         #       #    # #  # # #        #   # #    # #  # #    #     # #        #   #    # #    # #####       # 
	#     # #      #    # #    # #    # #         #       #    # #   ## #    #   #   # #    # #   ##    #     # #        #   #    # #    # #   #  #    # 
	 #####  ######  ####  #####  #    # ######    #        ####  #    #  ####    #   #  ####  #    #    ######  ######   #    ####   ####  #    #  ####  
*/

/*
	 #                                                 ##        #####                                            
	 #        ####   ####   ####  # #    #  ####      #  #      #     #  ####  #    #  ####   ####  #      ###### 
	 #       #    # #    # #    # # ##   # #    #      ##       #       #    # ##   # #      #    # #      #      
	 #       #    # #      #      # # #  # #          ###       #       #    # # #  #  ####  #    # #      #####  
	 #       #    # #  ### #  ### # #  # # #  ###    #   # #    #       #    # #  # #      # #    # #      #      
	 #       #    # #    # #    # # #   ## #    #    #    #     #     # #    # #   ## #    # #    # #      #      
	 #######  ####   ####   ####  # #    #  ####      ###  #     #####   ####  #    #  ####   ####  ###### ###### 
*/                                                                                                              

OH.Logging = {};

// Throws a error - dark red, priority = high
function OH.Logging.ThrowError( t )

	OH.Logging.Print( OH.Get( "Logging", "log_errors" ), g.Color( 255, 0, 0, 255 ), "[E] ", t );

end 

// Throws a warning - yellow, priority = medium
function OH.Logging.ThrowWarning( t )

	OH.Logging.Print( OH.Get( "Logging", "log_warnings" ), g.Color( 255, 0, 255, 255 ), "[W] ", t );

end

// Throws a severe error causing OH to shutdown in 30 seconds, dark red, priority = highest
function OH.Logging.ThrowSevere( t  )

	OH.Logging.Print( OH.Get( "Logging", "log_severes" ), g.Color( 255, 0, 0, 255 ), "[S] ", t );

end

// Logs text to a file
function OH.Logging.LogToFile( t )

	//IOubHack.LogToFile( OH.Logging.GetTimeStamp() .. " " .. t .. '\n' );

end 

// Prints to the OubHack console, color, text, color, text, etc ...
function OH.Logging.Print( log, ... )

	local arg = { ... };

	arg[ #arg + 1 ] = '\n';

	OH.Logging.PrintPure( log, Color( 0, 0, 0, 255 ), OH.Logging.GetTimeStamp(), Color( 90, 90, 90 ), g.unpack( arg ) );

end 

// Returns the time stamp
function OH.Logging.GetTimeStamp()

	// Apparently %r crashes .. so this'll have to do
	return "[" .. g.string.Explode( " ", g.os.date() )[ 2 ] .. "] ";

end 

// Prints to the console without time stamps or new lines, color, text, color, text, etc ...
function OH.Logging.PrintPure( log, ... )

	local arg = { ... };

	if ( log ) then

		local text = "";

		for _, t in g.pairs( arg ) do

			if ( isstring( t ) ) then text = text .. t; end

		end 
		OH.Logging.LogToFile( t, true );

	end
	OH.GUI.ConsolePrint( ... );

end 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


g.timer.Simple( 1, function() 

	OH.Logging.Print( true, Color( 0, 225, 0, 255 ), "OubHack V3 Loaded!" );

end);

local name =  OH.RandomString( g.math.random( 5, 25 ) );
g.timer.Create( name, 0.1, 0, function()

	if ( g.LocalPlayer() && g.IsValid( g.LocalPlayer() ) ) then 

		me = g.LocalPlayer();
		g.timer.Destroy( name );

	end

end);