core/convar_sm_dota.h
author Kyle Sanderson <kyle.leet@gmail.com>
Mon Aug 12 00:42:56 2013 +0100 (2013-08-12)
changeset 3994 4bc73bac0f4c
parent 3942 7aaa00382627
permissions -rw-r--r--
Added helper stock to check if a command exists. (bug 5510, r=asherkin)
     1 //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
     2 //
     3 // Purpose: 
     4 //
     5 // $Workfile:     $
     6 // $Date:         $
     7 //
     8 //-----------------------------------------------------------------------------
     9 // $NoKeywords: $
    10 //===========================================================================//
    11 
    12 #ifndef CONVAR_H
    13 #define CONVAR_H
    14 
    15 #if _WIN32
    16 #pragma once
    17 #endif
    18 
    19 #include "tier0/dbg.h"
    20 #include "tier1/iconvar.h"
    21 #include "tier1/utlvector.h"
    22 #include "tier1/utlstring.h"
    23 #include "Color.h"
    24 #include "icvar.h"
    25 
    26 #ifdef _WIN32
    27 #define FORCEINLINE_CVAR FORCEINLINE
    28 #elif POSIX
    29 #define FORCEINLINE_CVAR inline
    30 #else
    31 #error "implement me"
    32 #endif
    33 
    34 
    35 //-----------------------------------------------------------------------------
    36 // Uncomment me to test for threading issues for material system convars
    37 // NOTE: You want to disable all threading when you do this
    38 // +host_thread_mode 0 +r_threaded_particles 0 +sv_parallel_packentities 0 +sv_disable_querycache 0
    39 //-----------------------------------------------------------------------------
    40 //#define CONVAR_TEST_MATERIAL_THREAD_CONVARS 1
    41 
    42 
    43 //-----------------------------------------------------------------------------
    44 // Forward declarations
    45 //-----------------------------------------------------------------------------
    46 class ConVar;
    47 class CCommand;
    48 class ConCommand;
    49 class ConCommandBase;
    50 struct characterset_t;
    51 
    52 struct CCommandContext
    53 {
    54 	CCommandContext( int index )
    55 	{
    56 		_index = index;
    57 	}
    58 	
    59 	int Get() const
    60 	{
    61 		return _index;
    62 	}
    63 	
    64 private:
    65 	int _index;
    66 };
    67 
    68 
    69 
    70 //-----------------------------------------------------------------------------
    71 // Any executable that wants to use ConVars need to implement one of
    72 // these to hook up access to console variables.
    73 //-----------------------------------------------------------------------------
    74 class IConCommandBaseAccessor
    75 {
    76 public:
    77 	// Flags is a combination of FCVAR flags in cvar.h.
    78 	// hOut is filled in with a handle to the variable.
    79 	virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
    80 };
    81 
    82 
    83 //-----------------------------------------------------------------------------
    84 // Helper method for console development
    85 //-----------------------------------------------------------------------------
    86 #if defined( _X360 )
    87 void ConVar_PublishToVXConsole();
    88 #endif
    89 
    90 
    91 //-----------------------------------------------------------------------------
    92 // Called when a ConCommand needs to execute
    93 //-----------------------------------------------------------------------------
    94 typedef void ( *FnCommandCallbackV1_t )( void );
    95 typedef void ( *FnCommandCallback_t )( const CCommandContext &context, const CCommand &command );
    96 
    97 #define COMMAND_COMPLETION_MAXITEMS		64
    98 #define COMMAND_COMPLETION_ITEM_LENGTH	64
    99 
   100 //-----------------------------------------------------------------------------
   101 // Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
   102 //-----------------------------------------------------------------------------
   103 typedef int  ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
   104 
   105 
   106 //-----------------------------------------------------------------------------
   107 // Interface version
   108 //-----------------------------------------------------------------------------
   109 class ICommandCallback
   110 {
   111 public:
   112 	virtual void CommandCallback( const CCommand &command ) = 0;
   113 };
   114 
   115 class ICommandCallback2
   116 {
   117 public:
   118 	virtual void CommandCallback( const CCommandContext &context, const CCommand &command ) = 0;
   119 };
   120 
   121 class ICommandCompletionCallback
   122 {
   123 public:
   124 	virtual int  CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
   125 };
   126 
   127 //-----------------------------------------------------------------------------
   128 // Purpose: The base console invoked command/cvar interface
   129 //-----------------------------------------------------------------------------
   130 class ConCommandBase
   131 {
   132 	friend class CCvar;
   133 	friend class ConVar;
   134 	friend class ConCommand;
   135 	friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
   136 	friend void ConVar_PublishToVXConsole();
   137 
   138 	// FIXME: Remove when ConVar changes are done
   139 	friend class CDefaultCvar;
   140 
   141 public:
   142 								ConCommandBase( void );
   143 								ConCommandBase( const char *pName, const char *pHelpString = 0, 
   144 									int flags = 0 );
   145 
   146 	virtual						~ConCommandBase( void );
   147 
   148 	virtual	bool				IsCommand( void ) const;
   149 
   150 	// Check flag
   151 	virtual bool				IsFlagSet( int flag ) const;
   152 	// Set flag
   153 	virtual void				AddFlags( int flags );
   154 	// Clear flag
   155 	virtual void				RemoveFlags( int flags );
   156 
   157 	virtual int					GetFlags() const;
   158 
   159 	// Return name of cvar
   160 	virtual const char			*GetName( void ) const;
   161 
   162 	// Return help text for cvar
   163 	virtual const char			*GetHelpText( void ) const;
   164 
   165 	// Deal with next pointer
   166 	const ConCommandBase		*GetNext( void ) const;
   167 	ConCommandBase				*GetNext( void );
   168 	
   169 	virtual bool				IsRegistered( void ) const;
   170 
   171 	// Returns the DLL identifier
   172 	virtual CVarDLLIdentifier_t	GetDLLIdentifier() const;
   173 
   174 protected:
   175 	virtual void				Create( const char *pName, const char *pHelpString = 0, 
   176 									int flags = 0 );
   177 
   178 	// Used internally by OneTimeInit to initialize/shutdown
   179 	virtual void				Init();
   180 	void						Shutdown();
   181 
   182 	// Internal copy routine ( uses new operator from correct module )
   183 	char						*CopyString( const char *from );
   184 
   185 private:
   186 	// Next ConVar in chain
   187 	// Prior to register, it points to the next convar in the DLL.
   188 	// Once registered, though, m_pNext is reset to point to the next
   189 	// convar in the global list
   190 	ConCommandBase				*m_pNext;
   191 
   192 	// Has the cvar been added to the global list?
   193 	bool						m_bRegistered;
   194 
   195 	// Static data
   196 	const char 					*m_pszName;
   197 	const char 					*m_pszHelpString;
   198 	
   199 	// ConVar flags
   200 	int							m_nFlags;
   201 
   202 protected:
   203 	// ConVars add themselves to this list for the executable. 
   204 	// Then ConVar_Register runs through  all the console variables 
   205 	// and registers them into a global list stored in vstdlib.dll
   206 	static ConCommandBase		*s_pConCommandBases;
   207 
   208 	// ConVars in this executable use this 'global' to access values.
   209 	static IConCommandBaseAccessor	*s_pAccessor;
   210 public:
   211 	inline void SetFlags(int flags)	
   212 	{ 
   213 		m_nFlags = flags; 
   214 	}
   215 };
   216 
   217 
   218 //-----------------------------------------------------------------------------
   219 // Command tokenizer
   220 //-----------------------------------------------------------------------------
   221 class CCommand
   222 {
   223 public:
   224 	CCommand();
   225 	CCommand( int nArgC, const char **ppArgV );
   226 	bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
   227 	void Reset();
   228 
   229 	int ArgC() const;
   230 	const char **ArgV() const;
   231 	const char *ArgS() const;					// All args that occur after the 0th arg, in string form
   232 	const char *GetCommandString() const;		// The entire command in string form, including the 0th arg
   233 	const char *operator[]( int nIndex ) const;	// Gets at arguments
   234 	const char *Arg( int nIndex ) const;		// Gets at arguments
   235 	
   236 	// Helper functions to parse arguments to commands.
   237 	const char* FindArg( const char *pName ) const;
   238 	int FindArgInt( const char *pName, int nDefaultVal ) const;
   239 
   240 	static int MaxCommandLength();
   241 	static characterset_t* DefaultBreakSet();
   242 
   243 private:
   244 	enum
   245 	{
   246 		COMMAND_MAX_ARGC = 64,
   247 		COMMAND_MAX_LENGTH = 512,
   248 	};
   249 
   250 	int		m_nArgc;
   251 	int		m_nArgv0Size;
   252 	char	m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
   253 	char	m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
   254 	const char*	m_ppArgv[ COMMAND_MAX_ARGC ];
   255 };
   256 
   257 inline int CCommand::MaxCommandLength()
   258 {
   259 	return COMMAND_MAX_LENGTH - 1;
   260 }
   261 
   262 inline int CCommand::ArgC() const
   263 {
   264 	return m_nArgc;
   265 }
   266 
   267 inline const char **CCommand::ArgV() const
   268 {
   269 	return m_nArgc ? (const char**)m_ppArgv : NULL;
   270 }
   271 
   272 inline const char *CCommand::ArgS() const
   273 {
   274 	return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
   275 }
   276 
   277 inline const char *CCommand::GetCommandString() const
   278 {
   279 	return m_nArgc ? m_pArgSBuffer : "";
   280 }
   281 
   282 inline const char *CCommand::Arg( int nIndex ) const
   283 {
   284 	// FIXME: Many command handlers appear to not be particularly careful
   285 	// about checking for valid argc range. For now, we're going to
   286 	// do the extra check and return an empty string if it's out of range
   287 	if ( nIndex < 0 || nIndex >= m_nArgc )
   288 		return "";
   289 	return m_ppArgv[nIndex];
   290 }
   291 
   292 inline const char *CCommand::operator[]( int nIndex ) const
   293 {
   294 	return Arg( nIndex );
   295 }
   296 
   297 
   298 //-----------------------------------------------------------------------------
   299 // Purpose: The console invoked command
   300 //-----------------------------------------------------------------------------
   301 class ConCommand : public ConCommandBase
   302 {
   303 friend class CCvar;
   304 
   305 public:
   306 	typedef ConCommandBase BaseClass;
   307 
   308 	ConCommand( const char *pName, FnCommandCallbackV1_t callback, 
   309 		const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
   310 	ConCommand( const char *pName, FnCommandCallback_t callback, 
   311 		const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
   312 	ConCommand( const char *pName, ICommandCallback *pCallback, 
   313 		const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
   314 	ConCommand( const char *pName, ICommandCallback2 *pCallback, 
   315 		const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
   316 
   317 	virtual ~ConCommand( void );
   318 
   319 	virtual	bool IsCommand( void ) const;
   320 
   321 	virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
   322 
   323 	virtual bool CanAutoComplete( void );
   324 
   325 	// Invoke the function
   326 	virtual void Dispatch( const CCommandContext &context, const CCommand &command );
   327 
   328 private:
   329 	// NOTE: To maintain backward compat, we have to be very careful:
   330 	// All public virtual methods must appear in the same order always
   331 	// since engine code will be calling into this code, which *does not match*
   332 	// in the mod code; it's using slightly different, but compatible versions
   333 	// of this class. Also: Be very careful about adding new fields to this class.
   334 	// Those fields will not exist in the version of this class that is instanced
   335 	// in mod code.
   336 
   337 	// Call this function when executing the command
   338 	union
   339 	{
   340 		FnCommandCallbackV1_t m_fnCommandCallbackV1;
   341 		FnCommandCallback_t m_fnCommandCallback;
   342 		ICommandCallback *m_pCommandCallback; 
   343 		ICommandCallback2 *m_pCommandCallback2; 
   344 	};
   345 
   346 	union
   347 	{
   348 		FnCommandCompletionCallback	m_fnCompletionCallback;
   349 		ICommandCompletionCallback *m_pCommandCompletionCallback;
   350 	};
   351 
   352 	bool m_bHasCompletionCallback : 1;
   353 	bool m_bUsingNewCommandCallback : 1;
   354 	bool m_bUsingCommandCallbackInterface : 1;
   355 	bool m_bUsingCommandCallbackInterface2 : 1;
   356 public:
   357 	inline FnCommandCallback_t GetCallback() const
   358 	{ 
   359 		return m_fnCommandCallback; 
   360 	}
   361 };
   362 
   363 
   364 //-----------------------------------------------------------------------------
   365 // Purpose: A console variable
   366 //-----------------------------------------------------------------------------
   367 class ConVar : public ConCommandBase, public IConVar
   368 {
   369 friend class CCvar;
   370 friend class ConVarRef;
   371 friend class SplitScreenConVarRef;
   372 
   373 public:
   374 	typedef ConCommandBase BaseClass;
   375 
   376 								ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
   377 
   378 								ConVar( const char *pName, const char *pDefaultValue, int flags, 
   379 									const char *pHelpString );
   380 								ConVar( const char *pName, const char *pDefaultValue, int flags, 
   381 									const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
   382 								ConVar( const char *pName, const char *pDefaultValue, int flags, 
   383 									const char *pHelpString, FnChangeCallback_t callback );
   384 								ConVar( const char *pName, const char *pDefaultValue, int flags, 
   385 									const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
   386 									FnChangeCallback_t callback );
   387 
   388 	virtual						~ConVar( void );
   389 
   390 	virtual bool				IsFlagSet( int flag ) const;
   391 	virtual const char*			GetHelpText( void ) const;
   392 	virtual bool				IsRegistered( void ) const;
   393 	virtual const char			*GetName( void ) const;
   394 	// Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars
   395 	virtual const char			*GetBaseName( void ) const;
   396 	virtual int					GetSplitScreenPlayerSlot() const;
   397 
   398 	virtual void				AddFlags( int flags );
   399 	virtual int					GetFlags() const;
   400 	virtual	bool				IsCommand( void ) const;
   401 
   402 	// Install a change callback (there shouldn't already be one....)
   403 	void InstallChangeCallback( FnChangeCallback_t callback, bool bInvoke = true );
   404 	void RemoveChangeCallback( FnChangeCallback_t callbackToRemove );
   405 
   406 	int GetChangeCallbackCount() const { return m_pParent->m_fnChangeCallbacks.Count(); }
   407 	FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; }
   408 
   409 	// Retrieve value
   410 	FORCEINLINE_CVAR float			GetFloat( void ) const;
   411 	FORCEINLINE_CVAR int			GetInt( void ) const;
   412 	FORCEINLINE_CVAR Color			GetColor( void ) const;
   413 	FORCEINLINE_CVAR bool			GetBool() const {  return !!GetInt(); }
   414 	FORCEINLINE_CVAR char const	   *GetString( void ) const;
   415 
   416 	// Compiler driven selection for template use
   417 	template <typename T> T Get( void ) const;
   418 	template <typename T> T Get( T * ) const;
   419 
   420 	// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
   421 	//  from alloc/free across dll/exe boundaries.
   422 	
   423 	// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
   424 	virtual void				SetValue( const char *value );
   425 	virtual void				SetValue( float value );
   426 	virtual void				SetValue( int value );
   427 	virtual void				SetValue( Color value );
   428 	
   429 	// Reset to default value
   430 	void						Revert( void );
   431 
   432 	// True if it has a min/max setting
   433 	bool						HasMin() const;
   434 	bool						HasMax() const;
   435 
   436 	bool						GetMin( float& minVal ) const;
   437 	bool						GetMax( float& maxVal ) const;
   438 
   439 	float						GetMinValue() const;
   440 	float						GetMaxValue() const;
   441 
   442 	const char					*GetDefault( void ) const;
   443 
   444 	// Value
   445 	struct CVValue_t
   446 	{
   447 		char						*m_pszString;
   448 		int							m_StringLength;
   449 
   450 		// Values
   451 		float						m_fValue;
   452 		int							m_nValue;
   453 	};
   454 
   455 	FORCEINLINE_CVAR CVValue_t &GetRawValue()
   456 	{
   457 		return m_Value;
   458 	}
   459 	FORCEINLINE_CVAR const CVValue_t &GetRawValue() const
   460 	{
   461 		return m_Value;
   462 	}
   463 
   464 private:
   465 	bool						InternalSetColorFromString( const char *value );
   466 	// Called by CCvar when the value of a var is changing.
   467 	virtual void				InternalSetValue(const char *value);
   468 	// For CVARs marked FCVAR_NEVER_AS_STRING
   469 	virtual void				InternalSetFloatValue( float fNewValue );
   470 	virtual void				InternalSetIntValue( int nValue );
   471 	virtual void				InternalSetColorValue( Color value );
   472 
   473 	virtual bool				ClampValue( float& value );
   474 	virtual void				ChangeStringValue( const char *tempVal, float flOldValue );
   475 
   476 	virtual void				Create( const char *pName, const char *pDefaultValue, int flags = 0,
   477 									const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
   478 									bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
   479 
   480 	// Used internally by OneTimeInit to initialize.
   481 	virtual void				Init();
   482 
   483 
   484 
   485 protected:
   486 
   487 	// This either points to "this" or it points to the original declaration of a ConVar.
   488 	// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
   489 	// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
   490 	ConVar						*m_pParent;
   491 
   492 	// Static data
   493 	const char					*m_pszDefaultValue;
   494 	
   495 	CVValue_t					m_Value;
   496 
   497 	// Min/Max values
   498 	bool						m_bHasMin;
   499 	float						m_fMinVal;
   500 	bool						m_bHasMax;
   501 	float						m_fMaxVal;
   502 	
   503 	// Call this function when ConVar changes
   504 	CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks;
   505 public:
   506 	inline void SetMin(bool set, float min=0.0)
   507 	{ 
   508 		m_bHasMin = set; 
   509 		m_fMinVal = min; 
   510 	}
   511 	inline void SetMax(bool set, float max=0.0)
   512 	{
   513 		m_bHasMax = set;
   514 		m_fMaxVal = max; 
   515 	}
   516 };
   517 
   518 
   519 //-----------------------------------------------------------------------------
   520 // Purpose: Return ConVar value as a float
   521 // Output : float
   522 //-----------------------------------------------------------------------------
   523 FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
   524 {
   525 #ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
   526 	Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
   527 #endif
   528 	return m_pParent->m_Value.m_fValue;
   529 }
   530 
   531 //-----------------------------------------------------------------------------
   532 // Purpose: Return ConVar value as an int
   533 // Output : int
   534 //-----------------------------------------------------------------------------
   535 FORCEINLINE_CVAR int ConVar::GetInt( void ) const 
   536 {
   537 #ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
   538 	Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
   539 #endif
   540 	return m_pParent->m_Value.m_nValue;
   541 }
   542 
   543 //-----------------------------------------------------------------------------
   544 // Purpose: Return ConVar value as a color
   545 // Output : Color
   546 //-----------------------------------------------------------------------------
   547 FORCEINLINE_CVAR Color ConVar::GetColor( void ) const 
   548 {
   549 #ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
   550 	Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
   551 #endif
   552 	unsigned char *pColorElement = ((unsigned char *)&m_pParent->m_Value.m_nValue);
   553 	return Color( pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3] );
   554 }
   555 
   556 
   557 //-----------------------------------------------------------------------------
   558 
   559 template <> FORCEINLINE_CVAR float			ConVar::Get<float>( void ) const		{ return GetFloat(); }
   560 template <> FORCEINLINE_CVAR int			ConVar::Get<int>( void ) const			{ return GetInt(); }
   561 template <> FORCEINLINE_CVAR bool			ConVar::Get<bool>( void ) const			{ return GetBool(); }
   562 template <> FORCEINLINE_CVAR const char *	ConVar::Get<const char *>( void ) const	{ return GetString(); }
   563 template <> FORCEINLINE_CVAR float			ConVar::Get<float>( float *p ) const				{ return ( *p = GetFloat() ); }
   564 template <> FORCEINLINE_CVAR int			ConVar::Get<int>( int *p ) const					{ return ( *p = GetInt() ); }
   565 template <> FORCEINLINE_CVAR bool			ConVar::Get<bool>( bool *p ) const					{ return ( *p = GetBool() ); }
   566 template <> FORCEINLINE_CVAR const char *	ConVar::Get<const char *>( char const **p ) const	{ return ( *p = GetString() ); }
   567 
   568 //-----------------------------------------------------------------------------
   569 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
   570 // Output : const char *
   571 //-----------------------------------------------------------------------------
   572 FORCEINLINE_CVAR const char *ConVar::GetString( void ) const 
   573 {
   574 #ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
   575 	Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
   576 #endif
   577 	if ( m_nFlags & FCVAR_NEVER_AS_STRING )
   578 		return "FCVAR_NEVER_AS_STRING";
   579 	
   580 	char const *str = m_pParent->m_Value.m_pszString;
   581 	return str ? str : "";
   582 }
   583 
   584 class CSplitScreenAddedConVar : public ConVar
   585 {
   586 	typedef ConVar BaseClass;
   587 public:
   588 	CSplitScreenAddedConVar( int nSplitScreenSlot, const char *pName, const ConVar *pBaseVar ) :
   589 		BaseClass
   590 		( 
   591 			pName, 
   592 			pBaseVar->GetDefault(), 
   593 			// Keep basevar flags, except remove _SS and add _SS_ADDED instead
   594 			( pBaseVar->GetFlags() & ~FCVAR_SS ) | FCVAR_SS_ADDED, 
   595 			pBaseVar->GetHelpText(), 
   596 			pBaseVar->HasMin(),
   597 			pBaseVar->GetMinValue(),
   598 			pBaseVar->HasMax(),
   599 			pBaseVar->GetMaxValue()
   600 		),
   601 		m_pBaseVar( pBaseVar ),
   602 		m_nSplitScreenSlot( nSplitScreenSlot )
   603 	{
   604 		for ( int i = 0; i < pBaseVar->GetChangeCallbackCount(); ++i )
   605 		{
   606 			InstallChangeCallback( pBaseVar->GetChangeCallback( i ), false );
   607 		}
   608 		Assert( nSplitScreenSlot >= 1 );
   609 		Assert( nSplitScreenSlot < MAX_SPLITSCREEN_CLIENTS );
   610 		Assert( m_pBaseVar );
   611 		Assert( IsFlagSet( FCVAR_SS_ADDED ) );
   612 		Assert( !IsFlagSet( FCVAR_SS ) );
   613 	}
   614 
   615 	const ConVar *GetBaseVar() const;
   616 	virtual const char *GetBaseName() const;
   617 	void SetSplitScreenPlayerSlot( int nSlot );
   618 	virtual int GetSplitScreenPlayerSlot() const;
   619 
   620 protected:
   621 
   622 	const ConVar	*m_pBaseVar;
   623 	int		m_nSplitScreenSlot;
   624 };
   625 
   626 FORCEINLINE_CVAR const ConVar *CSplitScreenAddedConVar::GetBaseVar() const 
   627 { 
   628 	Assert( m_pBaseVar );
   629 	return m_pBaseVar; 
   630 }
   631 
   632 FORCEINLINE_CVAR const char *CSplitScreenAddedConVar::GetBaseName() const 
   633 { 
   634 	Assert( m_pBaseVar );
   635 	return m_pBaseVar->GetName(); 
   636 }
   637 
   638 FORCEINLINE_CVAR void CSplitScreenAddedConVar::SetSplitScreenPlayerSlot( int nSlot ) 
   639 { 
   640 	m_nSplitScreenSlot = nSlot; 
   641 }
   642 
   643 FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const 
   644 { 
   645 	return m_nSplitScreenSlot; 
   646 }
   647 
   648 //-----------------------------------------------------------------------------
   649 // Used to read/write convars that already exist (replaces the FindVar method)
   650 //-----------------------------------------------------------------------------
   651 class ConVarRef
   652 {
   653 public:
   654 	ConVarRef( const char *pName );
   655 	ConVarRef( const char *pName, bool bIgnoreMissing );
   656 	ConVarRef( IConVar *pConVar );
   657 
   658 	void Init( const char *pName, bool bIgnoreMissing );
   659 	bool IsValid() const;
   660 	bool IsFlagSet( int nFlags ) const;
   661 	IConVar *GetLinkedConVar();
   662 
   663 	// Get/Set value
   664 	float GetFloat( void ) const;
   665 	int GetInt( void ) const;
   666 	Color GetColor( void ) const;
   667 	bool GetBool() const { return !!GetInt(); }
   668 	const char *GetString( void ) const;
   669 
   670 	void SetValue( const char *pValue );
   671 	void SetValue( float flValue );
   672 	void SetValue( int nValue );
   673 	void SetValue( Color value );
   674 	void SetValue( bool bValue );
   675 
   676 	const char *GetName() const;
   677 
   678 	const char *GetDefault() const;
   679 
   680 	const char *GetBaseName() const;
   681 
   682 	int	GetSplitScreenPlayerSlot() const;
   683 
   684 private:
   685 	// High-speed method to read convar data
   686 	IConVar *m_pConVar;
   687 	ConVar *m_pConVarState;
   688 };
   689 
   690 
   691 //-----------------------------------------------------------------------------
   692 // Did we find an existing convar of that name?
   693 //-----------------------------------------------------------------------------
   694 FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
   695 {
   696 	return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
   697 }
   698 
   699 FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
   700 {
   701 	return m_pConVar;
   702 }
   703 
   704 FORCEINLINE_CVAR const char *ConVarRef::GetName() const
   705 {
   706 	return m_pConVar->GetName();
   707 }
   708 
   709 FORCEINLINE_CVAR const char *ConVarRef::GetBaseName() const
   710 {
   711 	return m_pConVar->GetBaseName();
   712 }
   713 
   714 FORCEINLINE_CVAR int ConVarRef::GetSplitScreenPlayerSlot() const
   715 {
   716 	return m_pConVar->GetSplitScreenPlayerSlot();
   717 }
   718 
   719 //-----------------------------------------------------------------------------
   720 // Purpose: Return ConVar value as a float
   721 //-----------------------------------------------------------------------------
   722 FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
   723 {
   724 	return m_pConVarState->m_Value.m_fValue;
   725 }
   726 
   727 //-----------------------------------------------------------------------------
   728 // Purpose: Return ConVar value as an int
   729 //-----------------------------------------------------------------------------
   730 FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const 
   731 {
   732 	return m_pConVarState->m_Value.m_nValue;
   733 }
   734 
   735 //-----------------------------------------------------------------------------
   736 // Purpose: Return ConVar value as a color
   737 //-----------------------------------------------------------------------------
   738 FORCEINLINE_CVAR Color ConVarRef::GetColor( void ) const 
   739 {
   740 	return m_pConVarState->GetColor();
   741 }
   742 
   743 //-----------------------------------------------------------------------------
   744 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
   745 //-----------------------------------------------------------------------------
   746 FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const 
   747 {
   748 	Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
   749 	return m_pConVarState->m_Value.m_pszString;
   750 }
   751 
   752 
   753 FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
   754 {
   755 	m_pConVar->SetValue( pValue );
   756 }
   757 
   758 FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
   759 {
   760 	m_pConVar->SetValue( flValue );
   761 }
   762 
   763 FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
   764 {
   765 	m_pConVar->SetValue( nValue );
   766 }
   767 
   768 FORCEINLINE_CVAR void ConVarRef::SetValue( Color value )
   769 {
   770 	m_pConVar->SetValue( value );
   771 }
   772 
   773 FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
   774 {
   775 	m_pConVar->SetValue( bValue ? 1 : 0 );
   776 }
   777 
   778 FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
   779 {
   780 	return m_pConVarState->m_pszDefaultValue;
   781 }
   782 
   783 //-----------------------------------------------------------------------------
   784 // Helper for referencing splitscreen convars (i.e., "name" and "name2")
   785 //-----------------------------------------------------------------------------
   786 class SplitScreenConVarRef
   787 {
   788 public:
   789 	SplitScreenConVarRef( const char *pName );
   790 	SplitScreenConVarRef( const char *pName, bool bIgnoreMissing );
   791 	SplitScreenConVarRef( IConVar *pConVar );
   792 
   793 	void Init( const char *pName, bool bIgnoreMissing );
   794 	bool IsValid() const;
   795 	bool IsFlagSet( int nFlags ) const;
   796 
   797 	// Get/Set value
   798 	float GetFloat( int nSlot ) const;
   799 	int GetInt( int nSlot ) const;
   800 	Color GetColor( int nSlot ) const;
   801 	bool GetBool( int nSlot ) const { return !!GetInt( nSlot ); }
   802 	const char *GetString( int nSlot  ) const;
   803 
   804 	void SetValue( int nSlot, const char *pValue );
   805 	void SetValue( int nSlot, float flValue );
   806 	void SetValue( int nSlot, int nValue );
   807 	void SetValue( int nSlot, Color value );
   808 	void SetValue( int nSlot, bool bValue );
   809 
   810 	const char *GetName( int nSlot ) const;
   811 
   812 	const char *GetDefault() const;
   813 
   814 	const char *GetBaseName() const;
   815 
   816 private:
   817 	struct cv_t
   818 	{
   819 		IConVar *m_pConVar;
   820 		ConVar *m_pConVarState;
   821 	};
   822 
   823 	cv_t	m_Info[ MAX_SPLITSCREEN_CLIENTS ];
   824 };
   825 
   826 //-----------------------------------------------------------------------------
   827 // Did we find an existing convar of that name?
   828 //-----------------------------------------------------------------------------
   829 FORCEINLINE_CVAR bool SplitScreenConVarRef::IsFlagSet( int nFlags ) const
   830 {
   831 	return ( m_Info[ 0 ].m_pConVar->IsFlagSet( nFlags ) != 0 );
   832 }
   833 
   834 FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetName( int nSlot ) const
   835 {
   836 	return m_Info[ nSlot ].m_pConVar->GetName();
   837 }
   838 
   839 FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetBaseName() const
   840 {
   841 	return m_Info[ 0 ].m_pConVar->GetBaseName();
   842 }
   843 
   844 //-----------------------------------------------------------------------------
   845 // Purpose: Return ConVar value as a float
   846 //-----------------------------------------------------------------------------
   847 FORCEINLINE_CVAR float SplitScreenConVarRef::GetFloat( int nSlot ) const
   848 {
   849 	return m_Info[ nSlot ].m_pConVarState->m_Value.m_fValue;
   850 }
   851 
   852 //-----------------------------------------------------------------------------
   853 // Purpose: Return ConVar value as an int
   854 //-----------------------------------------------------------------------------
   855 FORCEINLINE_CVAR int SplitScreenConVarRef::GetInt( int nSlot ) const 
   856 {
   857 	return m_Info[ nSlot ].m_pConVarState->m_Value.m_nValue;
   858 }
   859 
   860 //-----------------------------------------------------------------------------
   861 // Purpose: Return ConVar value as an int
   862 //-----------------------------------------------------------------------------
   863 FORCEINLINE_CVAR Color SplitScreenConVarRef::GetColor( int nSlot ) const 
   864 {
   865 	return m_Info[ nSlot ].m_pConVarState->GetColor();
   866 }
   867 
   868 //-----------------------------------------------------------------------------
   869 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
   870 //-----------------------------------------------------------------------------
   871 FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetString( int nSlot ) const 
   872 {
   873 	Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
   874 	return m_Info[ nSlot ].m_pConVarState->m_Value.m_pszString;
   875 }
   876 
   877 
   878 FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, const char *pValue )
   879 {
   880 	m_Info[ nSlot ].m_pConVar->SetValue( pValue );
   881 }
   882 
   883 FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, float flValue )
   884 {
   885 	m_Info[ nSlot ].m_pConVar->SetValue( flValue );
   886 }
   887 
   888 FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, int nValue )
   889 {
   890 	m_Info[ nSlot ].m_pConVar->SetValue( nValue );
   891 }
   892 
   893 FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, Color value )
   894 {
   895 	m_Info[ nSlot ].m_pConVar->SetValue( value );
   896 }
   897 
   898 FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, bool bValue )
   899 {
   900 	m_Info[ nSlot ].m_pConVar->SetValue( bValue ? 1 : 0 );
   901 }
   902 
   903 FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetDefault() const
   904 {
   905 	return m_Info[ 0 ].m_pConVarState->m_pszDefaultValue;
   906 }
   907 
   908 //-----------------------------------------------------------------------------
   909 // Called by the framework to register ConCommands with the ICVar
   910 //-----------------------------------------------------------------------------
   911 void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
   912 void ConVar_Unregister( );
   913 
   914 
   915 //-----------------------------------------------------------------------------
   916 // Utility methods 
   917 //-----------------------------------------------------------------------------
   918 void ConVar_PrintDescription( const ConCommandBase *pVar );
   919 
   920 
   921 //-----------------------------------------------------------------------------
   922 // Purpose: Utility class to quickly allow ConCommands to call member methods
   923 //-----------------------------------------------------------------------------
   924 #ifdef _MSC_VER
   925 #pragma warning (disable : 4355 )
   926 #endif
   927 
   928 template< class T >
   929 class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
   930 {
   931 	typedef ConCommand BaseClass;
   932 	typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
   933 	typedef int  ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
   934 
   935 public:
   936 	CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
   937 		int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
   938 		BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
   939 	{
   940 		m_pOwner = pOwner;
   941 		m_Func = callback;
   942 		m_CompletionFunc = completionFunc;
   943 	}
   944 
   945 	~CConCommandMemberAccessor()
   946 	{
   947 		Shutdown();
   948 	}
   949 
   950 	void SetOwner( T* pOwner )
   951 	{
   952 		m_pOwner = pOwner;
   953 	}
   954 
   955 	virtual void CommandCallback( const CCommand &command )
   956 	{
   957 		Assert( m_pOwner && m_Func );
   958 		(m_pOwner->*m_Func)( command );
   959 	}
   960 
   961 	virtual int  CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
   962 	{
   963 		Assert( m_pOwner && m_CompletionFunc );
   964 		return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
   965 	}
   966 
   967 private:
   968 	T* m_pOwner;
   969 	FnMemberCommandCallback_t m_Func;
   970 	FnMemberCommandCompletionCallback_t m_CompletionFunc;
   971 };
   972 
   973 #ifdef _MSC_VER
   974 #pragma warning ( default : 4355 )
   975 #endif
   976 
   977 //-----------------------------------------------------------------------------
   978 // Purpose: Utility macros to quicky generate a simple console command
   979 //-----------------------------------------------------------------------------
   980 #define CON_COMMAND( name, description ) \
   981    static void name( const CCommandContext &context, const CCommand &args ); \
   982    static ConCommand name##_command( #name, name, description ); \
   983    static void name( const CCommandContext &context, const CCommand &args )
   984 
   985 #ifdef CLIENT_DLL
   986 	#define CON_COMMAND_SHARED( name, description ) \
   987 		static void name( const CCommandContext &context, const CCommand &args ); \
   988 		static ConCommand name##_command_client( #name "_client", name, description ); \
   989 		static void name( const CCommandContext &context, const CCommand &args )
   990 #else
   991 	#define CON_COMMAND_SHARED( name, description ) \
   992 		static void name( const CCommandContext &context, const CCommand &args ); \
   993 		static ConCommand name##_command( #name, name, description ); \
   994 		static void name( const CCommandContext &context, const CCommand &args )
   995 #endif
   996 
   997 
   998 #define CON_COMMAND_F( name, description, flags ) \
   999 	static void name( const CCommandContext &context, const CCommand &args ); \
  1000 	static ConCommand name##_command( #name, name, description, flags ); \
  1001 	static void name( const CCommandContext &context, const CCommand &args )
  1002 
  1003 #ifdef CLIENT_DLL
  1004 	#define CON_COMMAND_F_SHARED( name, description, flags ) \
  1005 		static void name( const CCommandContext &context, const CCommand &args ); \
  1006 		static ConCommand name##_command_client( #name "_client", name, description, flags ); \
  1007 		static void name( const CCommandContext &context, const CCommand &args )
  1008 #else
  1009 	#define CON_COMMAND_F_SHARED( name, description, flags ) \
  1010 		static void name( const CCommandContext &context, const CCommand &args ); \
  1011 		static ConCommand name##_command( #name, name, description, flags ); \
  1012 		static void name( const CCommandContext &context, const CCommand &args )
  1013 #endif
  1014 
  1015 
  1016 #define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
  1017 	static void name( const CCommandContext &context, const CCommand &args ); \
  1018 	static ConCommand name##_command( #name, name, description, flags, completion ); \
  1019 	static void name( const CCommandContext &context, const CCommand &args )
  1020 
  1021 #ifdef CLIENT_DLL
  1022 	#define CON_COMMAND_F_COMPLETION_SHARED( name, description, flags, completion ) \
  1023 		static void name( const CCommandContext &context, const CCommand &args ); \
  1024 		static ConCommand name##_command_client( #name "_client", name, description, flags, completion ); \
  1025 		static void name( const CCommandContext &context, const CCommand &args )
  1026 #else
  1027 	#define CON_COMMAND_F_COMPLETION_SHARED( name, description, flags, completion ) \
  1028 		static void name( const CCommandContext &context, const CCommand &args ); \
  1029 		static ConCommand name##_command( #name, name, description, flags, completion ); \
  1030 		static void name( const CCommandContext &context, const CCommand &args )
  1031 #endif
  1032 
  1033 
  1034 #define CON_COMMAND_EXTERN( name, _funcname, description ) \
  1035 	void _funcname( const CCommandContext &context, const CCommand &args ); \
  1036 	static ConCommand name##_command( #name, _funcname, description ); \
  1037 	void _funcname( const CCommandContext &context, const CCommand &args )
  1038 
  1039 #define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
  1040 	void _funcname( const CCommandContext &context, const CCommand &args ); \
  1041 	static ConCommand name##_command( #name, _funcname, description, flags ); \
  1042 	void _funcname( const CCommandContext &context, const CCommand &args )
  1043 
  1044 #define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
  1045 	void _funcname( const CCommandContext &context, const CCommand &args );						\
  1046 	friend class CCommandMemberInitializer_##_funcname;			\
  1047 	class CCommandMemberInitializer_##_funcname					\
  1048 	{															\
  1049 	public:														\
  1050 		CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags )	\
  1051 		{														\
  1052 			m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) );	\
  1053 		}														\
  1054 	private:													\
  1055 		CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor;	\
  1056 	};															\
  1057 																\
  1058 	CCommandMemberInitializer_##_funcname m_##_funcname##_register;		\
  1059 
  1060 
  1061 #endif // CONVAR_H