/* * * * * * * * * * * * * * * * 

 * 	 ______     __  __     ______     __  __     ______     ______     __  __    

 *	/\  __ \   /\ \/\ \   /\  == \   /\ \_\ \   /\  __ \   /\  ___\   /\ \/ /    

 *	\ \ \/\ \  \ \ \_\ \  \ \  __<   \ \  __ \  \ \  __ \  \ \ \____  \ \  _"-.  

 *	 \ \_____\  \ \_____\  \ \_____\  \ \_\ \_\  \ \_\ \_\  \ \_____\  \ \_\ \_\ 

 *	  \/_____/   \/_____/   \/_____/   \/_/\/_/   \/_/\/_/   \/_____/   \/_/\/_/ 

 *

 *  - Version : 3L

 *  - By Oubliette

 * * * * * * * * * * * * * * * */



IOubHack = OH_MENU_INTERFACE;

OH_MENU_INTERFACE = nil; // No real need to nil the global, but what the heck, why not..



local OH = {};



/*

	 #                                                 ##        #####                                            

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

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

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

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

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

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

*/                                                                                                              



OH.Logging = {};



// Throws a error - dark red, priority = high

function OH.Logging.ThrowError( t )



	OH.Logging.Print( OH.Get( "Logging", "log_errors" ), 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" ), 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" ), Color( 255, 0, 0, 255 ), "[S] ", t );



end



// Logs text to a file

function OH.Logging.LogToFile( t )



	IOubHack.LogToFile( 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 ), unpack( arg ) );



end 



// Print function used by console redirection

function OH.Logging.RedirectPrint( log, ... )



	local arg = { ... };



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



	OH.Logging.PrintPure( log, Color( 0, 0, 0, 255 ), OH.Logging.GetTimeStamp(), Color( 0, 215, 0, 255 ), "[CRedirect] ", Color( 90, 90, 90 ), unpack( arg ) );



end 



// Returns the time stamp

function OH.Logging.GetTimeStamp()



	// Apparently %r crashes .. so this'll have to do

	return "[" .. string.Explode( " ", 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 pairs( arg ) do



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



		end 

		OH.Logging.LogToFile( text:sub( 1, text:len() - 1 ), true );



	end

	OH.GUI.ConsolePrint( ... );



end 



OH.Commands = {};



// 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





// 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 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 ( false ) then 



		surface.SetDrawColor( Color( 0, 0, 0, 255 ) );

		surface.DrawOutlinedRect( x, y, w, h );



		surface.SetDrawColor( Color( 0, 0, 0, 255 ) );

		surface.DrawOutlinedRect( x + 3, y + 3, w - 6, h - 6 );



	end



end



OH.FormatFunctions = {

	["%rand10"] = function() return OH.RandomString( 10 ); end,

	["%rand25"] = function() return OH.RandomString( 25 ); end,

	["%rand100"] = function() return OH.RandomString( 100 ); end,

	["%rand255"] = function() return OH.RandomString( 255 ); end

}



// Formats a string's wildcards

function OH.FormatWildcards( str )



	for needle, replace in pairs( OH.FormatFunctions ) do 



		str = string.Replace( str, needle, replace() );



	end



	return str;



end





// Loads a config safely returning true if it was loaded and false if it wasn't

function OH.SafeLoadConfig( name )



	local struct = util.KeyValuesToTable( IOubHack.RawRead( "OubHack/configs/" .. name .. ".conf" ) );

	local newStruct = {};





	// Convert regions to their original character case



	for region, data in pairs( struct ) do 



		if ( region == "aimbot" ) then region = "Aimbot"; end

		if ( region == "triggerbot" ) then region = "Triggerbot"; end

		if ( region == "lasersights" ) then region = "LaserSights"; end

		if ( region == "lasereyes" ) then region = "LaserEyes"; end

		if ( region == "esp" ) then region = "ESP"; end

		if ( region == "wallhack" ) then region = "Wallhack"; end

		if ( region == "utilities" ) then region = "Utilities"; end

		if ( region == "antiac" ) then region = "AntiAC"; end

		if ( region == "logging" ) then region = "Logging"; end

		if ( region == "console" ) then region = "Console"; end

		if ( region == "gui" ) then region = "GUI"; end

		if ( region == "binds" ) then region = "Binds"; end

		if ( region == "radar" ) then region = "Radar"; end



		newStruct[ region ] = data;





	end



	OH.ConfigurationStructure = OH.FromKeySafe( newStruct );



	return true;



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" ] = {



		friends = {},



		enabled = true,



		trace_key = IN_ATTACK,

		trace_bone = "ValveBiped.Bip01_Head1",

		trace_fraction = 0.95,



		target_players = true,

		target_bots = true,

		target_steam_friends = true,

		target_vehicles = false,

		target_locking = false, 

		target_admins = false,

		target_super_admins = false,

		target_ownteam = true,

		target_traitors_as_traitor = false,

		target_innocents_as_innocent = false,

		target_detectives_as_innocent = false,



		antisnap_enabled = false,

		antisnap_speed = 0.90,



		check_ammo = true,

		bad_weapons = { ["gmod_tool"] = true },



		prediction_delta = 0.90,



		sa_enabled = true,

		sa_smooth = true,



		offset = 0



	},

	[ "Triggerbot" ] = {



		FIRE_WHEN_VISISBLE = 0x01,

		FIRE_WHEN_HOVERED = 0x02,



		enabled = false,



		mode = 0x01,



		delay = 0,



	},

	[ "LaserSights" ] = {



		enabled = true,



		draw_all = false,

		draw_visible = true,

		draw_target = true,

		draw_idle = true,



		length = 0,

		width = 10,



		all_colour = Color( 255, 255, 0, 255 ),

		visible_colour = Color( 0, 0, 255, 255 ),

		target_colour = Color( 255, 0, 0, 255 ),

		idle_colour = Color( 0, 255, 0, 255 ),



		check_ab_compat = true





	},

	[ "LaserEyes" ] = {



		ignorez = false,

		colour = Color( 255, 0, 0, 255 ),

		length = 500



	},

	[ "ESP" ] = {



		enabled = true,



		check_ab_compat = false,



		draw_mat = "wireframe", // Wireframe or solidbg

		draw_always = false,



		ntarget_colour = Color( 255, 255, 0, 255 ),

		friend_colour = Color( 0, 255, 0, 255 ),

		target_colour = Color( 255, 0, 0, 255 ),

		non_ent_colour = Color( 0, 0, 255, 255 ),



		max_distance = 0,



	},

	[ "Wallhack" ] = {



		reg = 0x05,



		enabled = true,



		check_ab_compat = false,



		width = 1,



		ntarget_colour = Color( 255, 255, 0, 255 ),

		friend_colour = Color( 0, 255, 0, 255 ),

		target_colour = Color( 255, 0, 0, 255 ),

		non_ent_colour = Color( 0, 0, 255, 255 ),



		text_font = "default",

		text_colour = Color( 255, 255, 255, 255 ),

		padding_amount = 10,



		max_distance = 0,



	},

	[ "Utilities" ] = {



		reformat_logs = true,

		blocked_files = {},



		dump_files = true,

		dump_runstring = true,

		dump_luacmd = true,



		block_runstring = false,

		block_luacmd = false



	},

	[ "AntiAC" ] = {



		reg = 0x07,



	},

	[ "Logging" ] = {



		log_errors = true,

		log_console = true,

		log_warnings = true,

		log_severes = true,



		lnet_messages = {},

		net_logall = false,



	},

	[ "Console" ] = {



		history_length = 100



	},

	[ "GUI" ] = {



		debug = false,



	},

	[ "Radar" ] = {



		enabled = true,



		size = 200,



		pixrat = 15,



		draw_outlines = true,

		draw_names = true,

		draw_cross = true



	},

	[ "Binds" ] = {



		key_down = table.Copy( OH.Keys ),

		key_up = table.Copy( OH.Keys ),

		key_down_think = table.Copy( OH.Keys ),

		key_up_think = table.Copy( OH.Keys )



	}



};

OH.DefaultConfigurationStructure = OH.ConfigurationStructure;





// Load our default config, save the default to file otherwise.

/*if ( IOubHack.FileExists( "OubHack/configs/default.conf" ) ) then 



	OH.SafeLoadConfig( "default" );



else 



	IOubHack.RawWrite( "OubHack/configs/default.conf", util.TableToKeyValues( OH.KeySafe( OH.ConfigurationStructure ) ), "w" );



end*/



// Nice way of retrieving values from the configuration structure 

function OH.Get( region, name )



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



	return OH.ConfigurationStructure[ region ][ name ];



end



// Nice way of setting values from the configuration structure 

function OH.Set( region, name, value )



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

	IOubHack.RawWrite( "OubHack/configs/" .. OH.CurrentConfig .. ".conf", util.TableToKeyValues( OH.KeySafe( OH.ConfigurationStructure ) ), "w" );



end



function OH.MatchConfigCase( str )



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



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



	end



	return str;



end



/*

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

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

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

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

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

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

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

*/



OH.VGUI = {};

OH.VGUI.ElementFactory = {};



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



// 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 );



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



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



		if ( panel.Init ) then 



			local st, err = pcall( panel.Init, panel );

			if ( !st ) then OH.LogginThrowError( "Panel " .. name .. " failed to initialize! - " .. err ); return nil; end



		end



		panel:Prepare(); return panel;



	end 



	return vgui.Create( name, parent );



end



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



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 = 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 = 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 = Lerp( 0.70, self.x, self.targetPosX );

		self.y = 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



OH.VGUI.RegisterElement( "OHSlidePanel", panel, "EditablePanel" );



/*

	 #####                                                        #     #                         ###                                                        

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

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

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

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

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

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

*/



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 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

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



	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 );

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



			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[ string.Explode( " ", text )[ 1 ] ] ) then 



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



		local parsed = false;



		for _, data in pairs( OH.ParseCommands( text ) ) do 



			if ( data.name == command ) then 



				parsed = data.args;

				break;



			end



		end



		if ( parsed ) then 



			local sug, sugs =  OH.AutoCompleteCommand( 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 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.LogginPrint( OH.Get( "Logging", "log_errors" ) , 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

		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;



	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( ScrW() * 0.50, 0 );

	OH.GUI.Console:SetSize( ScrW() * 0.50, 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 = Color( 0, 0, 0, 0 ); end 



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



		surface.SetDrawColor( panel.fCol );

		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( 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 = 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 && IsValid( OH.GUI.Console.RichText ) ) then 



		for _, t in 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 



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



	end





end



function OH.GUI.ConsoleOpen()



	if ( !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();



end



function OH.GUI.ConsoleClose()



	if ( !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 );



end



function OH.GUI.ConsoleToggle()



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

	OH.GUI[ "Console" .. ( OH.GUI.Console:IsVisible() and "Close" or "Open" ) ]();

end 



//OH.GUI.ConsoleCreate(); OH.GUI.ConsoleToggle();



concommand.Add( "tits", OH.GUI.ConsoleToggle )



/*



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

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

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

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

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

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

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



*/



OH.Commands = {};

OH.Redirects = {};



OH.Redirects[ "print" ] = print;

OH.Redirects[ "Msg" ] = Msg;

OH.Redirects[ "MsgN" ] = MsgN;

OH.Redirects[ "MsgC" ] = MsgC;



function OH.InitiateRedirects()



	_G.print = function( ... ) OH.Logging.RedirectPrint( OH.Get( "Logging", "log_console" ), ... ); end

	_G.Msg = function( ... ) OH.Logging.RedirectPrint( OH.Get( "Logging", "log_console" ), ... ); end

	_G.MsgN = function( ... ) OH.Logging.RedirectPrint( OH.Get( "Logging", "log_console" ), ... ); end

	_G.MsgC = function( ... ) OH.Logging.RedirectPrint( OH.Get( "Logging", "log_console" ), ... ); end



end



function OH.RemoveRedirects()



	_G.print = OH.Redirects[ "print" ];

	_G.Msg = OH.Redirects[ "Msg" ];

	_G.MsgN = OH.Redirects[ "MsgN" ];

	_G.MsgC = OH.Redirects[ "MsgC" ];



end



function OH.AddHook( name, func )



	OH.Hooks[ name ] = func;

	//_G.hook.Add( name, OH.RandomString( 200 ), 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, ... )



	OH.InitiateRedirects();

	timer.Simple( 0, OH.RemoveRedirects );



	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 _, data in pairs( commands ) do 



		local targs = {};



		local name = data.name;

		local args = data.args;



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



		// Only run this part if it was typed into the console rather than a bind, as binds use this function too.

		if ( OH.GUI.Console && OH.GUI.Console:IsVisible() ) then OH.Logging.Print( OH.Get( "Logging", "log_console" ), "] " .. name ); end



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



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



			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 = OH.FormatWildcards( 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 ( !string.find( com, "\"", i + 1 ) && !isEncap ) then continue; end

			isEncap = !isEncap;



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



			// name wasn't "finished" 

			if ( name == "" ) then commands[ #commands + 1 ] = { name = _name, args = {} }; end



			// Insert current argument 

			if ( arg != "" ) then 



				commands[ #commands ].args[ #commands[ #commands ].args + 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[ #commands + 1 ] = { name = name, args = {} };



			else 



				commands[ #commands ].args[ #commands[ #commands ].args + 1 ] = arg;

				arg = "";



			end





		else 



			if ( name == "" ) then 



				_name = _name .. com[ i ];



			else 



				arg = arg .. com[ i ];



			end 



		end



	end



	return commands;



end

