//-----------------------------------------------------------------------------
//
//  $Logfile:: /game/console.cpp                                              $
// $Revision:: 3                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 8/8/01 4:44 PM                                                 $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
// Consoles are script controlled decals that can change dynamically.  Eventually,
// their behaviour will be expanded to include interaction with the player as well.
//

#include "console.h"
#include "scriptmaster.h"
#include "camera.h"
#include "player.h"

ConsoleManager consoleManager;

Event EV_Console_Activate( "conactivate" );

CLASS_DECLARATION( TriggerUse, Console, "console" );

ResponseDef Console::Responses[] =
{
	{ &EV_Console_Activate, ( Response )& Console::Activate },
	{ &EV_Trigger_Effect, ( Response )& Console::Activate },
	{ &EV_Use, ( Response )& Console::Use },
	{ NULL, NULL }
};

/*****************************************************************************/
/*SINED console (0 .5 .8) ? NOUSE SCROLL MENU NOPVS
   consolename (required)
   virtualwidth
   virtualheight
   fraction
   rows
   cols
   menufile
   scroll
   menu
 *****************************************************************************/

Console::Console()
{
	netconsole_t*   con;
	str mfile;

	if( LoadingSavegame )
	{
		// Increment the global number of consoles and return
		globals.num_consoles++;
		return;
	}

	showModel();
	setMoveType( MOVETYPE_PUSH );
	setSolidType( SOLID_BSP );

	console_name = G_GetSpawnArg( "consolename", "" );
	if( !LoadingSavegame && !console_name.length() )
	{
		error( "Console", "consolename is undefined\n" );
	}

	if( console_name == MAIN_CONSOLE )
	{
		error( "Console", "console name \"maincon\" is reserved\n" );
	}
	if( console_name == MISSION_CONSOLE )
	{
		error( "Console", "console name \"missioncon\" is reserved\n" );
	}


	wait            = G_GetFloatArg( "wait", 1.0f );
	virtual_width   = G_GetFloatArg( "virtualwidth", 640.0f );
	virtual_height  = G_GetFloatArg( "virtualheight", 480.0f );
	fraction        = G_GetFloatArg( "fraction", 1.0f );
	rows            = G_GetIntArg( "rows", 32 );
	cols            = G_GetIntArg( "cols", 80 );
	mfile           = G_GetSpawnArg( "menufile", "" );
	scroll          = G_GetIntArg( "scroll", 0 );
	menu            = G_GetIntArg( "menu", 0 );
	respondto       = TRIGGER_PLAYERS;

	menufile = G_FixSlashes( mfile.c_str() );

	if( scroll )
		spawnflags |= 2;
	if( menu )
		spawnflags |= 4;

	// A console of this name already exists, so just assign it's number to the number of the
	// one that already exists
	if( !LoadingSavegame )
	{
		console_number = consoleManager.ConsoleExists( console_name );
		if( console_number )
		{
			return;
		}
	}

	// Check for a free console on the server
	if( globals.num_consoles >= globals.max_consoles )
		error( "Console::Create", "No free consoles\n" );

	// Increment the global number of consoles.
	globals.num_consoles++;

	console_number          = globals.num_consoles;
	con                     = &g_consoles[globals.num_consoles];
	con->inuse              = true;
	con->s.spawnflags       = spawnflags;
	con->s.consoleactive    = true;
	con->s.create_time      = -1;
	con->s.number           = globals.num_consoles;
	con->s.virtual_width    = virtual_width;
	con->s.virtual_height   = virtual_height;
	con->s.fraction         = fraction;
	con->s.rows             = rows;
	con->s.cols             = cols;
	con->s.menu_file[0]     = 0;
	con->s.linepos          = 1;

	con->s.console_owner    = entnum;

	created = true;
	if( menufile.length() )
	{
		strcpy( con->s.menu_file, menufile.c_str() );
		con->s.menufile_update_time = -1;
	}
	else
	{
		con->s.menufile_update_time = 0;
	}

	strcpy( con->s.console_name, console_name.c_str() );
	con->s.name_update_time = -1;
	con->s.console_return_time = 0;

	if( !LoadingSavegame )
	{
		// Add it to the manager
		consoleManager.AddConsole( this );
	}
}

Console::~Console()
{
	consoleManager.RemoveConsole( this );
}

void Console::Use( Event* ev )
{
	// Don't respond to users using me!
	if( spawnflags & 1 )
		return;

	TriggerStuff( ev );
}

void Console::Activate( Event* ev )
{
	char string[1024];
	Entity*   other;
	Event*    ev2;
	Camera*   cam;
	int num;

	if( !created )
	{
		Event* ev1;
		ev1 = new Event( ev );
		PostEvent( ev1, 0.1 );
		return;
	}

	assert( created );

	other = ev->GetEntity( 1 );

	num = G_FindTarget( 0, Target() );

	if( num && other->isClient() )
	{
		Player* client;

		client = ( Player* )other;
		cam = ( Camera* ) G_GetEntity( num );
		assert( cam );
		client->SetCamera( cam );
		ev2 = new Event( EV_Player_HideStats );
		client->ProcessEvent( ev2 );
	}

	Com_sprintf( string, sizeof( string ), "use %s", console_name.c_str() );

	gi.WriteByte( svc_console_command );
	gi.WriteString( string );
	gi.unicast( other->edict, true );

	ev2 = new Event( EV_EnterConsole );
	ev2->AddString( console_name );
	other->PostEvent( ev2, 0 );
}

CLASS_DECLARATION( Listener, ConsoleManager, "consolemgr" );

Event EV_ConsoleManager_ProcessCommand( "consolecmd", EV_CONSOLE );
Event EV_ConsoleManager_ProcessVariable( "consolevar", EV_CONSOLE );
Event EV_ConsoleManager_ConPositionPositive( "consolepos", EV_CONSOLE );
Event EV_ConsoleManager_ConPositionNegative( "consoleneg", EV_CONSOLE );
Event EV_ConsoleManager_ConPositionReturn( "consoleret", EV_CONSOLE );
Event EV_ConsoleManager_ConMenuInfo( "consolemenu", EV_CONSOLE );
Event EV_ConsoleManager_ConPrint( "conprint" );
Event EV_ConsoleManager_ConNewline( "connewline" );
Event EV_ConsoleManager_ConLayout( "conlayout" );
Event EV_ConsoleManager_ConAppLayout( "conapplayout" );
Event EV_ConsoleManager_ConClearLayout( "conclearlayout" );
Event EV_ConsoleManager_ConVirtualWidth( "convirtualwidth" );
Event EV_ConsoleManager_ConVirtualHeight( "convirtualheight" );
Event EV_ConsoleManager_ConFraction( "confraction" );
Event EV_ConsoleManager_ConDeactivate( "condeactivate" );
Event EV_ConsoleManager_ConActivate( "conactivate" );
Event EV_ConsoleManager_ConRows( "rows" );
Event EV_ConsoleManager_ConColumns( "cols" );
Event EV_ConsoleManager_ConClear( "conclear" );
Event EV_ConsoleManager_ConLayoutFile( "conlayoutfile" );
Event EV_ConsoleManager_ConLoadMenuFile( "conmenufile" );
Event EV_ConsoleManager_ConFocus( "focus" );
Event EV_ConsoleManager_ConForeground( "foreground" );
Event EV_ConsoleManager_MenuActive( "menuactive" );
Event EV_ConsoleManager_MenuInactive( "menuinactive" );
Event EV_ConsoleManager_ConStatusBar( "sbar" );
Event EV_ConsoleManager_ConStatusBarValue( "sbarvalue" );
Event EV_ConsoleManager_ConKickUsers( "kick" );

Event EV_KickFromConsole( "kickcon" );
Event EV_EnterConsole( "entercon" );
Event EV_ExitConsole( "exitcon", EV_CONSOLE );

ResponseDef ConsoleManager::Responses[] =
{
	{ &EV_ConsoleManager_ProcessCommand, ( Response )& ConsoleManager::ProcessCmd },
	{ &EV_ConsoleManager_ProcessVariable, ( Response )& ConsoleManager::ProcessVar },
	{ &EV_ConsoleManager_ConPositionPositive, ( Response )& ConsoleManager::ConsolePositionPositive },
	{ &EV_ConsoleManager_ConPositionNegative, ( Response )& ConsoleManager::ConsolePositionNegative },
	{ &EV_ConsoleManager_ConPositionReturn, ( Response )& ConsoleManager::ConsolePositionReturn },
	{ &EV_ConsoleManager_ConMenuInfo, ( Response )& ConsoleManager::ConsoleMenuInfo },
	{ &EV_ConsoleManager_ConPrint, ( Response )& ConsoleManager::ConsolePrint },
	{ &EV_ConsoleManager_ConPrint, ( Response )& ConsoleManager::ConsolePrint },
	{ &EV_ConsoleManager_ConNewline, ( Response )& ConsoleManager::ConsoleNewline },
	{ &EV_ConsoleManager_ConLayout, ( Response )& ConsoleManager::ConsoleLayout },
	{ &EV_ConsoleManager_ConLayoutFile, ( Response )& ConsoleManager::ConsoleLayoutFile },
	{ &EV_ConsoleManager_ConAppLayout, ( Response )& ConsoleManager::ConsoleAppLayout },
	{ &EV_ConsoleManager_ConClearLayout, ( Response )& ConsoleManager::ConsoleClearLayout },
	{ &EV_ConsoleManager_ConVirtualWidth, ( Response )& ConsoleManager::ConsoleVirtualWidth },
	{ &EV_ConsoleManager_ConVirtualHeight, ( Response )& ConsoleManager::ConsoleVirtualHeight },
	{ &EV_ConsoleManager_ConFraction, ( Response )& ConsoleManager::ConsoleFraction },
	{ &EV_ConsoleManager_ConDeactivate, ( Response )& ConsoleManager::ConsoleDeactivate },
	{ &EV_ConsoleManager_ConActivate, ( Response )& ConsoleManager::ConsoleActivate },
	{ &EV_ConsoleManager_ConRows, ( Response )& ConsoleManager::ConsoleRows },
	{ &EV_ConsoleManager_ConColumns, ( Response )& ConsoleManager::ConsoleColumns },
	{ &EV_ConsoleManager_ConClear, ( Response )& ConsoleManager::ConsoleClear },
	{ &EV_ConsoleManager_ConLoadMenuFile, ( Response )& ConsoleManager::ConsoleLoadMenuFile },
	{ &EV_ConsoleManager_ConFocus, ( Response )& ConsoleManager::ConsoleFocus },
	{ &EV_ConsoleManager_ConForeground, ( Response )& ConsoleManager::ConsoleForeground },
	{ &EV_ConsoleManager_MenuActive, ( Response )& ConsoleManager::ConsoleMenuActive },
	{ &EV_ConsoleManager_MenuInactive, ( Response )& ConsoleManager::ConsoleMenuInactive },
	{ &EV_ConsoleManager_ConStatusBar, ( Response )& ConsoleManager::ConsoleStatusBar },
	{ &EV_ConsoleManager_ConStatusBarValue, ( Response )& ConsoleManager::ConsoleStatusBarValue },
	{ &EV_ConsoleManager_ConKickUsers, ( Response )& ConsoleManager::ConsoleKickUsers },
	{ NULL, NULL }
};

//=============
//ConsoleExists - returns the number of the console, 0 if not found.
//=============
int ConsoleManager::ConsoleExists( str con_name )
{
	int num, i;
	Console* p;

	// Check for mission computer
	if( !strcmp( con_name.c_str(), "missioncon" ) )
		return mission_console_number;

	num = consoleList.NumObjects();
	for( i = 1; i <= num; i++ )
	{
		p = ( Console* )consoleList.ObjectAt( i );
		if( con_name == p->ConsoleName() )
		{
			return p->ConsoleNumber();
		}
	}

	gi.dprintf( "Console %s does not exist\n", con_name.c_str() );

	return 0;
}

//=============
//ConsoleExists
//=============
qboolean ConsoleManager::ConsoleExists( int con_number )
{
	int num, i;
	Console* p;

	// Check for mission computer
	if( con_number == mission_console_number )
		return true;

	num = consoleList.NumObjects();
	for( i = 1; i <= num; i++ )
	{
		p = ( Console* )consoleList.ObjectAt( i );
		if( p->ConsoleNumber() == con_number )
			return true;
	}
	return false;
}

//==========
//ProcessCmd - Send this command to the script director.
//==========
void ConsoleManager::ProcessCmd( Event* ev )
{
	Director.ConsoleInput( ev->GetToken( 1 ), ev->GetToken( 2 ) );
}

//==========
//ProcessVar - Send this variable to the script director.
//==========
void ConsoleManager::ProcessVar( Event* ev )
{
	Director.ConsoleVariable( ev->GetToken( 1 ), ev->GetToken( 2 ) );
}

//=====================
//ConsolePositionReturn
//=====================
void ConsoleManager::ConsolePositionReturn( Event* ev )
{
	netconsole_t* svcon;
	int num = ev->GetInteger( 1 );

	if( !ConsoleExists( num ) )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.linepos = 1;
	svcon->s.cmdline[svcon->s.linepos] = 0;
	svcon->s.console_return_time = level.time;
}

//=======================
//ConsolePositionPositive
//=======================
void ConsoleManager::ConsolePositionPositive( Event* ev )
{
	netconsole_t* svcon;
	int num = ev->GetInteger( 1 );

	if( !ConsoleExists( num ) )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];

	if( svcon->s.linepos < MAXCMDLINE - 1 )
	{
		svcon->s.cmdline[svcon->s.linepos] = ev->GetInteger( 2 );
		svcon->s.linepos++;
		svcon->s.cmdline[svcon->s.linepos] = 0;
	}
}


//=======================
//ConsolePositionNegative
//=======================
void ConsoleManager::ConsolePositionNegative( Event* ev )
{
	netconsole_t* svcon;
	int num = ev->GetInteger( 1 );

	if( !ConsoleExists( num ) )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];

	if( svcon->s.linepos > 1 )
	{
		svcon->s.linepos--;
		svcon->s.cmdline[svcon->s.linepos] = 0;
	}
}


//===============
//ConsoleMenuInfo
//===============
void ConsoleManager::ConsoleMenuInfo( Event* ev )
{
	netconsole_t* svcon;
	int num = ev->GetInteger( 1 );

	if( !ConsoleExists( num ) )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.menu_level = ev->GetInteger( 2 );
	svcon->s.sel_menu_item = ev->GetInteger( 3 );
}

void ConsoleManager::CreateMissionComputer( void )
{
	netconsole_t*   con;

	// Check for a free console on the server
	if( globals.num_consoles >= globals.max_consoles )
		gi.error( "Console::CreateMissionComputer: No free consoles\n" );

	// Increment the global number of consoles.
	globals.num_consoles++;
	mission_console_number  = globals.num_consoles;
	con                     = &g_consoles[globals.num_consoles];
	con->inuse              = true;
	con->s.spawnflags       = 2 | 8;
	con->s.consoleactive    = true;
	con->s.create_time      = -1;
	con->s.number           = globals.num_consoles;
	con->s.virtual_width    = 320;
	con->s.virtual_height   = 240;
	con->s.fraction         = 1.0f;
	con->s.rows             = 30;
	con->s.cols             = 40;
	con->s.menu_file[0]     = 0;
	con->s.linepos          = 1;
	con->s.menufile_update_time = 0;
	strcpy( con->s.console_name, MISSION_CONSOLE );
	con->s.name_update_time = -1;
	con->s.console_return_time = 0;
}

void ConsoleManager::Reset( void )
{
	globals.num_consoles = 0;
	mission_console_number = 0;
	consoleList.ClearObjectList();
}

//==========
//AddConsole - Add a console to the manager
//==========
int ConsoleManager::AddConsole( Console* console )
{
	int num;
	num = consoleList.AddObject( console );
	return num;
}

//=============
//RemoveConsole - Remove a console from the manager
//=============
void ConsoleManager::RemoveConsole( Console* console )
{
	// Make sure that this exists in the manager
	if( consoleList.IndexOfObject( console ) )
		consoleList.RemoveObject( console );
}

//============
//ConsolePrint - Print a string to the buffer of the console
//============
void ConsoleManager::ConsolePrint( Event* ev )
{
	char*              bufptr;
	const char*        str;
	netconbuffer_t*    svbuff;
	//netconsole_t*      svcon;
	int*               start;
	int*               end;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );
	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	//svcon  = &g_consoles[num];
	svbuff = &g_conbuffers[num];
	bufptr = &svbuff->s.buffer[0];
	start  = &svbuff->s.start;
	end    = &svbuff->s.end;
	str = ev->GetString( 2 );
	svbuff->s.end_index += (int)strlen( str );

	while( *str )
	{
		if( ( *end + 1 ) % MAX_BUFFER_LENGTH == ( *start ) )
		{
			svbuff->s.start_index += 1;
			*start = ( *start + 1 ) % MAX_BUFFER_LENGTH;
		}

		bufptr[*end] = *str;
		*end = ( *end + 1 ) % MAX_BUFFER_LENGTH;
		str++;
	}
}

//==============
//ConsoleNewline - Prints a newline to the buffer of the console
//==============
void ConsoleManager::ConsoleNewline( Event* ev )
{
	ev->AddString( "\n" );
	ConsolePrint( ev );
}

//=================
//ConsoleLayoutFile - Orders the console to load a client side layout file
//=================
void ConsoleManager::ConsoleLayoutFile( Event* ev )
{
	netconsole_t*   svcon;
	int num;
	const char*     layout_filename;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon = &g_consoles[num];
	layout_filename = ev->GetString( 2 );
	strcpy( svcon->s.layout_file, layout_filename );
	svcon->s.layoutfile_update_time = level.time;
}

//=============
//ConsoleLayout - Set the layout string
//=============
void ConsoleManager::ConsoleLayout( Event* ev )
{
	str console_name;
	netconsole_t*         svcon;
	int num;
	char*                   layout;
	char*                 token, *sav;
	char newlayout[MAX_LAYOUT_LENGTH];
	static const char*    seps = " ";

	console_name = ev->GetString( 1 );
	num = ConsoleExists( console_name );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon = &g_consoles[ num ];
	layout = strdup( ev->GetString( 2 ) );

	if( strlen( layout ) > MAX_LAYOUT_LENGTH )
		error( "ConsoleManager::ConsoleLayout", "Max layout length exceeded for %s\n", ev->GetString( 1 ) );

	strcpy( newlayout, layout );

	if( coop->value && ( !strcmp( console_name.c_str(), "missioncon" ) ) )
	{
		newlayout[ 0 ] = 0;

		token = strtok_r( layout, seps, &sav );
		while( token )
		{
			// Skip over "fc" console commands in coop
			if( !strcmp( token, "fc" ) )
			{
				strtok_r( NULL, seps, &sav );
				strtok_r( NULL, seps, &sav );
				strtok_r( NULL, seps, &sav );
				strtok_r( NULL, seps, &sav );
			}
			else if( strstr( token, "---" ) )
			{
				strcat( newlayout, " " );
				strcat( newlayout, "\"\"" );
				// Skip over extraneous lines of characters
			}
			else
			{
				strcat( newlayout, " " );
				strcat( newlayout, token );
			}
			token = strtok_r( NULL, seps, &sav );
		}
	}

	free( layout );
	strcpy( svcon->s.layout, newlayout );
	svcon->s.layout_update_time = level.time;
}

//================
//ConsoleAppLayout - Append to the layout string
//================
void ConsoleManager::ConsoleAppLayout( Event* ev )
{
	netconsole_t*         svcon;
	int layout_length, num;
	char*                   layout;
	char*                 token, *sav;
	char newlayout[MAX_LAYOUT_LENGTH];
	static const char*    seps = " ";
	str consolename;

	consolename = ev->GetString( 1 );
	num = ConsoleExists( consolename );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];

	layout    = strdup( ev->GetString( 2 ) );
	layout_length = (int)strlen( layout ) + (int)strlen( svcon->s.layout ) + 1;

	if( layout_length > MAX_LAYOUT_LENGTH )
		error( "ConsoleManager::ConsoleAppLayout", "Max layout length exceeded for %s\n", ev->GetString( 1 ) );

	strcpy( newlayout, layout );

	if( coop->value && ( !strcmp( consolename.c_str(), "missioncon" ) ) )
	{
		newlayout[ 0 ] = 0;

		token = strtok_r( layout, seps, &sav );
		while( token )
		{
			// Skip over "fc" console commands in coop
			if( !strcmp( token, "fc" ) )
			{
				strtok_r( NULL, seps, &sav );
				strtok_r( NULL, seps, &sav );
				strtok_r( NULL, seps, &sav );
				strtok_r( NULL, seps, &sav );
			}
			else if( strstr( token, "---" ) )
			{
				strcat( newlayout, "\"\"" );
				// Skip over extraneous lines of characters
			}
			else
			{
				strcat( newlayout, " " );
				strcat( newlayout, token );
			}
			token = strtok_r( NULL, seps, &sav );
		}
	}

	free( layout );
	strcat( svcon->s.layout, " " );
	strcat( svcon->s.layout, newlayout );
	svcon->s.layout_update_time = level.time;
}

//==================
//ConsoleClearLayout - Clear the layout string
//==================
void ConsoleManager::ConsoleClearLayout( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.layout[0] = 0;
	svcon->s.layout_update_time = level.time;
}

//===========
//ConsoleRows - Set the number of rows in the console
//===========
void ConsoleManager::ConsoleRows( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.rows = ev->GetInteger( 2 );
}

//==============
//ConsoleColumns - Set the number of columns in the console
//==============
void ConsoleManager::ConsoleColumns( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.cols = ev->GetInteger( 2 );
}

//===================
//ConsoleVirtualWidth - Set the virtual width of the console
//===================
void ConsoleManager::ConsoleVirtualWidth( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.virtual_width = ev->GetFloat( 2 );
}

//====================
//ConsoleVirtualHeight - Set the virtual height of the console
//====================
void ConsoleManager::ConsoleVirtualHeight( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.virtual_height = ev->GetFloat( 2 );
}

//===============
//ConsoleFraction - Set the fraction of the console that the scrolling
//part of the console covers.
//===============
void ConsoleManager::ConsoleFraction( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.fraction = ev->GetFloat( 2 );
}

//=================
//ConsoleDeactivate - Deactivate the console.
//=================
void ConsoleManager::ConsoleDeactivate( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.consoleactive = false;
}

//=================
//ConsoleActivate - Activate the console
//=================
void ConsoleManager::ConsoleActivate( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.consoleactive = true;
}

//============
//ConsoleClear - Clears the buffer of the scrolling part of the console
//============
void ConsoleManager::ConsoleClear( Event* ev )
{
	//const char*      bufptr;
	netconbuffer_t*    svbuff;
	netconsole_t*      svcon;

	int num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svbuff = &g_conbuffers[num];
	//bufptr = &svbuff->s.buffer[0];
	svbuff->s.start = 0;
	svbuff->s.end = 0;
	svbuff->s.end_index = 0;
	svbuff->s.start_index = 0;
	svcon->s.cleared_console_time = level.time;
}

//==============
//ConsoleManager - Load a client side menu file
//==============
void ConsoleManager::ConsoleLoadMenuFile( Event* ev )
{
	netconsole_t*   svcon;
	int num;
	const char*     path;
	str mfile;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	path = ev->GetString( 2 );
	mfile = G_FixSlashes( path );
	strcpy( svcon->s.menu_file, mfile.c_str() );
	svcon->s.menufile_update_time = level.time;
}

//============
//ConsoleFocus - Change the focus of console to the scrolling part or
//the menu part.
//============
void ConsoleManager::ConsoleFocus( Event* ev )
{
	const char*     focus;
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	focus  = ev->GetString( 2 );

	if( !Q_stricmp( focus, "menu" ) )
	{
		svcon->s.focus = MENU3D;
	}
	else if( !strcmp( focus, "console" ) )
	{
		svcon->s.focus = CONSOLE3D;
	}
	else
	{
		error( "ConsoleManager::ConsoleFocus", "invalid focus type\n" );
	}
}

//=================
//ConsoleForeground - Set the foreground color of the console
//=================
void ConsoleManager::ConsoleForeground( Event* ev )
{
	netconsole_t*   svcon;
	int num;
	num = ConsoleExists( ev->GetString( 1 ) );
	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}
	svcon          = &g_consoles[num];
	svcon->s.red   = ev->GetFloat( 2 );
	svcon->s.green = ev->GetFloat( 3 );
	svcon->s.blue  = ev->GetFloat( 4 );
	svcon->s.alpha = ev->GetFloat( 5 );
}

//===================
//ConsoleMenuActivate - Activates the menu (i.e. draw it)
//===================
void ConsoleManager::ConsoleMenuActive( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.menuactive = true;
}

//===================
//ConsoleMenuInactive - Deactivates the menu (i.e. don't draw it)
//===================
void ConsoleManager::ConsoleMenuInactive( Event* ev )
{
	netconsole_t*   svcon;
	int num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	svcon  = &g_consoles[num];
	svcon->s.menuactive = false;
}

//================
//ConsoleStatusBar - Create a status bar on the console.
//================
void ConsoleManager::ConsoleStatusBar( Event* ev )
{
	netconsole_t*   svcon;
	int num;
	int sbar_num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	sbar_num = ev->GetInteger( 2 );
	svcon  = &g_consoles[num];

	svcon->s.sbar[sbar_num].width       = ev->GetFloat( 3 );
	svcon->s.sbar[sbar_num].height      = ev->GetFloat( 4 );
	svcon->s.sbar[sbar_num].min         = ev->GetFloat( 5 );
	svcon->s.sbar[sbar_num].max         = ev->GetFloat( 6 );
	svcon->s.sbar[sbar_num].value       = ev->GetFloat( 7 );
	svcon->s.sbar[sbar_num].red         = ev->GetFloat( 8 );
	svcon->s.sbar[sbar_num].green       = ev->GetFloat( 9 );
	svcon->s.sbar[sbar_num].blue        = ev->GetFloat( 10 );
	svcon->s.sbar[sbar_num].alpha       = ev->GetFloat( 11 );
	svcon->s.sbar[sbar_num].update_time = level.time;
}

//=====================
//ConsoleStatusBarValue
//=====================
void ConsoleManager::ConsoleStatusBarValue( Event* ev )
{
	netconsole_t*   svcon;
	int num;
	int sbar_num;

	num = ConsoleExists( ev->GetString( 1 ) );

	if( !num )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}

	sbar_num = ev->GetInteger( 2 );
	svcon  = &g_consoles[num];
	svcon->s.sbar[sbar_num].value = ev->GetFloat( 3 );
}

//================
//ConsoleKickUsers
//================
void ConsoleManager::ConsoleKickUsers( Event* ev )
{
	char msg[ MAX_MSGLEN ];

	if( !ConsoleExists( ev->GetString( 1 ) ) )
	{
		// ConsoleExists will give a warning about this console not existing
		return;
	}
	sprintf( msg, "sku %s", ev->GetString( 1 ) );
	gi.WriteByte( svc_console_command );
	gi.WriteString( msg );
	gi.multicast( NULL, MULTICAST_ALL );
}
