This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/common/cvar.c

890 lines
19 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
cvar.c - dynamic variable tracking
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
2011-03-09 22:00:00 +01:00
#include "common.h"
2017-02-15 22:00:00 +01:00
#include "math.h" // fabs...
2011-03-09 22:00:00 +01:00
2018-03-03 22:00:00 +01:00
convar_t *cvar_vars = NULL; // head of list
2016-11-17 22:00:00 +01:00
convar_t *cmd_scripting;
2011-03-09 22:00:00 +01:00
/*
============
Cvar_FindVar
2017-02-12 22:00:00 +01:00
find the specified variable by name
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
2011-03-09 22:00:00 +01:00
{
convar_t *var;
2017-02-12 22:00:00 +01:00
if( !var_name )
return NULL;
2011-03-09 22:00:00 +01:00
for( var = cvar_vars; var; var = var->next )
{
2017-02-12 22:00:00 +01:00
if( ignore_group && FBitSet( ignore_group, var->flags ))
continue;
2011-03-11 22:00:00 +01:00
if( !Q_stricmp( var_name, var->name ))
2011-03-09 22:00:00 +01:00
return var;
}
2017-02-12 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
return NULL;
}
2018-03-05 22:00:00 +01:00
/*
============
Cvar_BuildAutoDescription
build cvar auto description that based on the setup flags
============
*/
const char *Cvar_BuildAutoDescription( int flags )
{
static char desc[128];
desc[0] = '\0';
if( FBitSet( flags, FCVAR_EXTDLL ))
Q_strncpy( desc, "game ", sizeof( desc ));
else if( FBitSet( flags, FCVAR_CLIENTDLL ))
Q_strncpy( desc, "client ", sizeof( desc ));
else if( FBitSet( flags, FCVAR_GAMEUIDLL ))
Q_strncpy( desc, "GameUI ", sizeof( desc ));
if( FBitSet( flags, FCVAR_SERVER ))
Q_strncat( desc, "server ", sizeof( desc ));
if( FBitSet( flags, FCVAR_USERINFO ))
Q_strncat( desc, "user ", sizeof( desc ));
if( FBitSet( flags, FCVAR_ARCHIVE ))
Q_strncat( desc, "archived ", sizeof( desc ));
Q_strncat( desc, "cvar", sizeof( desc ));
return desc;
}
2011-03-09 22:00:00 +01:00
/*
============
2017-02-12 22:00:00 +01:00
Cvar_UpdateInfo
deal with userinfo etc
2011-03-09 22:00:00 +01:00
============
*/
2017-04-01 23:00:00 +02:00
static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean notify )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_USERINFO ))
{
if ( host.type == HOST_DEDICATED )
{
// g-cont. this is a very strange behavior...
Info_SetValueForKey( SV_Serverinfo(), var->name, value, MAX_SERVERINFO_STRING ),
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", SV_Serverinfo( ));
}
else
{
if( !Info_SetValueForKey( CL_Userinfo(), var->name, value, MAX_INFO_STRING ))
return false; // failed to change value
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// time to update server copy of userinfo
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", var->name, value );
}
}
2017-04-01 23:00:00 +02:00
if( FBitSet( var->flags, FCVAR_SERVER ) && notify )
2017-02-12 22:00:00 +01:00
{
if( !FBitSet( var->flags, FCVAR_UNLOGGED ))
{
if( FBitSet( var->flags, FCVAR_PROTECTED ))
{
Log_Printf( "Server cvar \"%s\" = \"%s\"\n", var->name, "***PROTECTED***" );
2018-02-27 22:00:00 +01:00
SV_BroadcastPrintf( NULL, "\"%s\" changed to \"%s\"\n", var->name, "***PROTECTED***" );
2017-02-12 22:00:00 +01:00
}
else
{
Log_Printf( "Server cvar \"%s\" = \"%s\"\n", var->name, value );
2018-02-27 22:00:00 +01:00
SV_BroadcastPrintf( NULL, "\"%s\" changed to \"%s\"\n", var->name, value );
2017-02-12 22:00:00 +01:00
}
}
}
2017-01-14 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
return true;
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_ValidateString
deal with userinfo etc
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
const char *Cvar_ValidateString( convar_t *var, const char *value )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
const char *pszValue;
static char szNew[MAX_STRING];
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
pszValue = value;
szNew[0] = 0;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// this cvar's string must only contain printable characters.
// strip out any other crap. we'll fill in "empty" if nothing is left
if( FBitSet( var->flags, FCVAR_PRINTABLEONLY ))
{
char *szVal = szNew;
int len = 0;
// step through the string, only copying back in characters that are printable
while( *pszValue && len < MAX_STRING )
{
if( ((byte)*pszValue) < 32 )
{
pszValue++;
continue;
}
*szVal++ = *pszValue++;
len++;
}
*szVal = '\0';
pszValue = szNew;
// g-cont. is this even need?
if( !Q_strlen( szNew )) Q_strncpy( szNew, "empty", sizeof( szNew ));
}
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITEPACE ))
{
char *szVal = szNew;
int len = 0;
// step through the string, only copying back in characters that are printable
while( *pszValue && len < MAX_STRING )
{
if( *pszValue == ' ' )
{
pszValue++;
continue;
}
*szVal++ = *pszValue++;
len++;
}
*szVal = '\0';
pszValue = szNew;
}
return pszValue;
2011-03-09 22:00:00 +01:00
}
2018-02-12 22:00:00 +01:00
/*
============
Cvar_UnlinkVar
unlink the variable
============
*/
int Cvar_UnlinkVar( const char *var_name, int group )
{
int count = 0;
convar_t **prev;
convar_t *var;
prev = &cvar_vars;
while( 1 )
{
var = *prev;
if( !var ) break;
// do filter by name
if( var_name && Q_strcmp( var->name, var_name ))
{
prev = &var->next;
continue;
}
// do filter by specified group
if( group && !FBitSet( var->flags, group ))
{
prev = &var->next;
continue;
}
// unlink variable from list
freestring( var->string );
*prev = var->next;
// only allocated cvars can throw these fields
if( FBitSet( var->flags, FCVAR_ALLOCATED ))
{
freestring( var->name );
freestring( var->def_string );
freestring( var->desc );
Mem_Free( var );
}
count++;
}
return count;
}
2011-03-09 22:00:00 +01:00
/*
============
2017-02-12 22:00:00 +01:00
Cvar_Changed
Tell the engine parts about cvar changing
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
static void Cvar_Changed( convar_t *var )
2011-03-09 22:00:00 +01:00
{
2018-02-12 22:00:00 +01:00
Assert( var != NULL );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// tell about changes
SetBits( var->flags, FCVAR_CHANGED );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// tell the engine parts with global state
if( FBitSet( var->flags, FCVAR_USERINFO ))
host.userinfo_changed = true;
if( FBitSet( var->flags, FCVAR_MOVEVARS ))
host.movevars_changed = true;
2017-03-21 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_VIDRESTART ))
2017-02-12 22:00:00 +01:00
host.renderinfo_changed = true;
if( !Q_strcmp( var->name, "sv_cheats" ))
host.allow_cheats = Q_atoi( var->string );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_LookupVars
============
*/
void Cvar_LookupVars( int checkbit, void *buffer, void *ptr, setpair_t callback )
{
2017-02-12 22:00:00 +01:00
convar_t *var;
2011-03-09 22:00:00 +01:00
// nothing to process ?
if( !callback ) return;
// force checkbit to 0 for lookup all cvars
2017-02-12 22:00:00 +01:00
for( var = cvar_vars; var; var = var->next )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
if( checkbit && !FBitSet( var->flags, checkbit ))
2012-12-21 21:00:00 +01:00
continue;
2011-04-08 22:00:00 +02:00
if( buffer )
{
2017-02-12 22:00:00 +01:00
callback( var->name, var->string, buffer, ptr );
2011-04-08 22:00:00 +02:00
}
2011-03-09 22:00:00 +01:00
else
{
// NOTE: dlls cvars doesn't have description
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_ALLOCATED|FCVAR_EXTENDED ))
callback( var->name, var->string, var->desc, ptr );
else callback( var->name, var->string, "", ptr );
2011-03-09 22:00:00 +01:00
}
}
}
/*
============
Cvar_Get
If the variable already exists, the value will not be set
The flags will be or'ed in if the variable exists.
============
*/
2017-02-12 22:00:00 +01:00
convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *var_desc )
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
convar_t *cur, *find, *var;
2011-03-09 22:00:00 +01:00
2018-02-12 22:00:00 +01:00
ASSERT( name && *name );
2016-11-17 22:00:00 +01:00
// check for command coexisting
2017-02-12 22:00:00 +01:00
if( Cmd_Exists( name ))
2016-11-17 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
MsgDev( D_ERROR, "can't register variable '%s', is already defined as command\n", name );
2011-03-09 22:00:00 +01:00
return NULL;
}
2017-02-12 22:00:00 +01:00
var = Cvar_FindVar( name );
2011-03-09 22:00:00 +01:00
if( var )
{
2017-02-12 22:00:00 +01:00
// already existed?
if( FBitSet( flags, FCVAR_GLCONFIG ))
2011-03-09 22:00:00 +01:00
{
2017-05-04 23:00:00 +02:00
// NOTE: cvars without description produced by Cvar_FullSet
// which executed from the config file. So we don't need to
// change value here: we *already* have actual value from config.
// in other cases we need to rewrite them
if( Q_strcmp( var->desc, "" ))
{
// directly set value
freestring( var->string );
var->string = copystring( value );
var->value = Q_atof( var->string );
SetBits( var->flags, flags );
// tell engine about changes
Cvar_Changed( var );
}
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
else
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
SetBits( var->flags, flags );
Cvar_DirectSet( var, value );
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_ALLOCATED ) && Q_strcmp( var_desc, var->desc ))
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
if( !FBitSet( flags, FCVAR_GLCONFIG ))
2017-08-18 23:00:00 +02:00
MsgDev( D_REPORT, "%s change description from %s to %s\n", var->name, var->desc, var_desc );
2011-03-09 22:00:00 +01:00
// update description if needs
2017-02-12 22:00:00 +01:00
freestring( var->desc );
var->desc = copystring( var_desc );
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
return var;
}
// allocate a new cvar
var = Z_Malloc( sizeof( *var ));
2017-02-12 22:00:00 +01:00
var->name = copystring( name );
var->string = copystring( value );
var->def_string = copystring( value );
var->desc = copystring( var_desc );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2017-02-12 22:00:00 +01:00
var->flags = flags|FCVAR_ALLOCATED;
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
// link the variable in alphanumerical order
for( cur = NULL, find = cvar_vars; find && Q_strcmp( find->name, var->name ) < 0; cur = find, find = find->next );
if( cur ) cur->next = var;
else cvar_vars = var;
var->next = find;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// fill it cls.userinfo, svs.serverinfo
2017-04-01 23:00:00 +02:00
Cvar_UpdateInfo( var, var->string, false );
2016-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// tell engine about changes
Cvar_Changed( var );
2016-11-23 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
return var;
}
/*
============
Cvar_RegisterVariable
Adds a freestanding variable to the variable list.
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_RegisterVariable( convar_t *var )
2011-03-09 22:00:00 +01:00
{
2018-02-12 22:00:00 +01:00
convar_t *cur, *find, *dup;
2011-03-09 22:00:00 +01:00
ASSERT( var != NULL );
2017-02-12 22:00:00 +01:00
// first check to see if it has allready been defined
2018-02-12 22:00:00 +01:00
dup = Cvar_FindVar( var->name );
if( dup )
2017-02-12 22:00:00 +01:00
{
2018-02-12 22:00:00 +01:00
if( !FBitSet( dup->flags, FCVAR_TEMPORARY ))
{
MsgDev( D_ERROR, "can't register variable '%s', is already defined\n", var->name );
return;
}
// time to replace temp variable with real
Cvar_UnlinkVar( var->name, FCVAR_TEMPORARY );
2017-02-12 22:00:00 +01:00
}
2011-03-09 22:00:00 +01:00
// check for overlap with a command
if( Cmd_Exists( var->name ))
{
2017-02-12 22:00:00 +01:00
MsgDev( D_ERROR, "can't register variable '%s', is already defined as command\n", var->name );
2011-03-09 22:00:00 +01:00
return;
}
2016-11-17 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// NOTE: all the 'long' engine cvars have an special setntinel on static declaration
// (all the engine cvars should be declared through CVAR_DEFINE macros or they shouldn't working properly anyway)
// so we can determine long version 'convar_t' and short version 'cvar_t' more reliable than by FCVAR_EXTDLL flag
if( CVAR_CHECK_SENTINEL( var )) SetBits( var->flags, FCVAR_EXTENDED );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// copy the value off, because future sets will free it
if( FBitSet( var->flags, FCVAR_EXTENDED ))
var->def_string = var->string; // just swap pointers
2016-11-17 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
var->string = copystring( var->string );
var->value = Q_atof( var->string );
2016-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// find the supposed position in chain (alphanumerical order)
for( cur = NULL, find = cvar_vars; find && Q_strcmp( find->name, var->name ) < 0; cur = find, find = find->next );
2016-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// now link variable
if( cur ) cur->next = var;
else cvar_vars = var;
var->next = find;
2016-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// fill it cls.userinfo, svs.serverinfo
2017-04-01 23:00:00 +02:00
Cvar_UpdateInfo( var, var->string, false );
2016-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// tell engine about changes
Cvar_Changed( var );
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
/*
============
2017-02-12 22:00:00 +01:00
Cvar_DirectSet
way to change value for many cvars
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_DirectSet( convar_t *var, const char *value )
2011-03-09 22:00:00 +01:00
{
const char *pszValue;
2017-02-12 22:00:00 +01:00
if( !var ) return; // ???
2016-11-17 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// lookup for registration
2017-03-14 22:00:00 +01:00
if( CVAR_CHECK_SENTINEL( var ) || ( var->next == NULL && !FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED )))
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
// need to registering cvar fisrt
MsgDev( D_WARN, "Cvar_DirectSet: called for unregistered cvar '%s'\n", var->name );
Cvar_RegisterVariable( var ); // ok, register it
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
// lookup for registration again
if( var != Cvar_FindVar( var->name ))
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
MsgDev( D_ERROR, "Cvar_DirectSet: couldn't find cvar '%s' in linked list\n", var->name );
return;
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_READ_ONLY|FCVAR_GLCONFIG ))
2011-03-09 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "%s is read-only.\n", var->name );
2017-02-12 22:00:00 +01:00
return;
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_CHEAT ) && !host.allow_cheats )
2011-03-09 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "%s is cheat protected.\n", var->name );
2017-02-12 22:00:00 +01:00
return;
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
// just tell user about deferred changes
if( FBitSet( var->flags, FCVAR_LATCH ) && ( SV_Active() || CL_Active( )))
2018-03-03 22:00:00 +01:00
Con_Printf( "%s will be changed upon restarting.\n", var->name );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// check value
if( !value )
2011-03-09 22:00:00 +01:00
{
2017-02-21 22:00:00 +01:00
if( !FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED ))
2011-03-09 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "%s has no default value and can't be reset.\n", var->name );
2017-02-12 22:00:00 +01:00
return;
2011-03-09 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
value = var->def_string; // reset to default value
2016-11-24 22:00:00 +01:00
}
2017-02-12 22:00:00 +01:00
pszValue = Cvar_ValidateString( var, value );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// nothing to change
if( !Q_strcmp( pszValue, var->string ))
return;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// fill it cls.userinfo, svs.serverinfo
2017-04-01 23:00:00 +02:00
if( !Cvar_UpdateInfo( var, pszValue, true ))
2017-02-12 22:00:00 +01:00
return;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// and finally changed the cvar itself
freestring( var->string );
2011-03-09 22:00:00 +01:00
var->string = copystring( pszValue );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// tell engine about changes
Cvar_Changed( var );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_FullSet
2017-02-12 22:00:00 +01:00
can set any protected cvars
2011-03-09 22:00:00 +01:00
============
*/
void Cvar_FullSet( const char *var_name, const char *value, int flags )
{
2017-02-12 22:00:00 +01:00
convar_t *var = Cvar_FindVar( var_name );
if( !var )
2011-03-09 22:00:00 +01:00
{
Cvar_Get( var_name, value, flags, "" );
return;
}
2017-02-12 22:00:00 +01:00
freestring( var->string );
2011-03-09 22:00:00 +01:00
var->string = copystring( value );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2017-02-12 22:00:00 +01:00
SetBits( var->flags, flags );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// tell engine about changes
Cvar_Changed( var );
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_Set
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_Set( const char *var_name, const char *value )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
convar_t *var = Cvar_FindVar( var_name );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
if( !var )
2017-03-14 22:00:00 +01:00
{
// there is an error in C code if this happens
if( host.type != HOST_DEDICATED )
MsgDev( D_ERROR, "Cvar_Set: variable '%s' not found\n", var_name );
2011-03-09 22:00:00 +01:00
return;
}
2017-02-12 22:00:00 +01:00
Cvar_DirectSet( var, value );
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_SetValue
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_SetValue( const char *var_name, float value )
2011-03-09 22:00:00 +01:00
{
char val[32];
2017-02-12 22:00:00 +01:00
if( fabs( value - (int)value ) < 0.000001 )
Q_snprintf( val, sizeof( val ), "%d", (int)value );
else Q_snprintf( val, sizeof( val ), "%f", value );
2011-03-09 22:00:00 +01:00
Cvar_Set( var_name, val );
}
/*
============
Cvar_Reset
============
*/
void Cvar_Reset( const char *var_name )
{
2017-02-12 22:00:00 +01:00
Cvar_Set( var_name, NULL );
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_VariableValue
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
float Cvar_VariableValue( const char *var_name )
2011-03-09 22:00:00 +01:00
{
convar_t *var;
2017-02-12 22:00:00 +01:00
var = Cvar_FindVar( var_name );
if( !var ) return 0.0f;
2012-12-21 21:00:00 +01:00
2017-02-12 22:00:00 +01:00
return Q_atof( var->string );
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_VariableInteger
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
int Cvar_VariableInteger( const char *var_name )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
convar_t *var;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
var = Cvar_FindVar( var_name );
if( !var ) return 0;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
return Q_atoi( var->string );
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_VariableString
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
char *Cvar_VariableString( const char *var_name )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
convar_t *var;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
var = Cvar_FindVar( var_name );
if( !var ) return "";
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
return var->string;
2011-03-09 22:00:00 +01:00
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_SetCheatState
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
Any testing variables will be reset to the safe values
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_SetCheatState( void )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
convar_t *var;
2016-11-17 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// set all default vars to the safe value
for( var = cvar_vars; var; var = var->next )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
// can't process dll cvars - missed def_string
if( !FBitSet( var->flags, FCVAR_ALLOCATED|FCVAR_EXTENDED ))
continue;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_CHEAT ))
{
if( Q_strcmp( var->def_string, var->string ))
Cvar_DirectSet( var, var->def_string );
}
2011-03-09 22:00:00 +01:00
}
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_Command
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
Handles variable inspection and changing from the console
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
qboolean Cvar_Command( void )
2011-03-09 22:00:00 +01:00
{
convar_t *v;
2017-02-12 22:00:00 +01:00
// check variables
v = Cvar_FindVar( Cmd_Argv( 0 ));
if( !v ) return false;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
// perform a variable print or set
if( Cmd_Argc() == 1 )
{
if( FBitSet( v->flags, FCVAR_ALLOCATED|FCVAR_EXTENDED ))
2018-03-03 22:00:00 +01:00
Con_Printf( "\"%s\" is \"%s\" ( ^3\"%s\"^7 )\n", v->name, v->string, v->def_string );
else Con_Printf( "\"%s\" is \"%s\"\n", v->name, v->string );
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
return true;
}
2011-03-09 22:00:00 +01:00
2017-03-14 22:00:00 +01:00
if( host.apply_game_config )
{
if( !FBitSet( v->flags, FCVAR_EXTDLL ))
return true; // only game.dll cvars passed
}
2017-02-12 22:00:00 +01:00
if( FBitSet( v->flags, FCVAR_SPONLY ) && CL_GetMaxClients() > 1 )
2011-03-09 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "can't set \"%s\" in multiplayer\n", v->name );
2017-02-12 22:00:00 +01:00
return false;
}
else
{
Cvar_DirectSet( v, Cmd_Argv( 1 ));
2017-03-23 22:00:00 +01:00
if( host.apply_game_config )
host.sv_cvars_restored++;
2017-02-12 22:00:00 +01:00
return true;
2011-03-09 22:00:00 +01:00
}
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_WriteVariables
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
Writes lines containing "variable value" for all variables
with the specified flag set to true.
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_WriteVariables( file_t *f, int group )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
convar_t *var;
for( var = cvar_vars; var; var = var->next )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, group ))
FS_Printf( f, "%s \"%s\"\n", var->name, var->string );
2011-03-09 22:00:00 +01:00
}
}
/*
============
2017-02-12 22:00:00 +01:00
Cvar_Toggle_f
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
Toggles a cvar for easy single key binding
2011-03-09 22:00:00 +01:00
============
*/
2017-02-12 22:00:00 +01:00
void Cvar_Toggle_f( void )
2011-03-09 22:00:00 +01:00
{
2017-02-12 22:00:00 +01:00
int v;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
if( Cmd_Argc() != 2 )
2011-03-09 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( S_USAGE "toggle <variable>\n" );
2011-03-09 22:00:00 +01:00
return;
}
2017-02-12 22:00:00 +01:00
v = !Cvar_VariableInteger( Cmd_Argv( 1 ));
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
Cvar_Set( Cmd_Argv( 1 ), va( "%i", v ));
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetR_f
2017-08-18 23:00:00 +02:00
keep for legacy configs
2011-03-09 22:00:00 +01:00
============
*/
void Cvar_SetR_f( void )
{
if( Cmd_Argc() != 3 )
{
2018-03-03 22:00:00 +01:00
Con_Printf( S_USAGE "setr <variable> <value>\n" );
2011-03-09 22:00:00 +01:00
return;
}
2017-02-12 22:00:00 +01:00
Cvar_Set( Cmd_Argv( 1 ), Cmd_Argv( 2 ));
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetGL_f
As Cvar_Set, but also flags it as glconfig
============
*/
void Cvar_SetGL_f( void )
{
if( Cmd_Argc() != 3 )
{
2018-03-03 22:00:00 +01:00
Con_Printf( S_USAGE "setgl <variable> <value>\n" );
2011-03-09 22:00:00 +01:00
return;
}
2017-05-04 23:00:00 +02:00
Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), FCVAR_GLCONFIG );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_Reset_f
============
*/
void Cvar_Reset_f( void )
{
if( Cmd_Argc() != 2 )
{
2018-03-03 22:00:00 +01:00
Con_Printf( S_USAGE "reset <variable>\n" );
2011-03-09 22:00:00 +01:00
return;
}
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
Cvar_Reset( Cmd_Argv( 1 ));
}
/*
============
Cvar_List_f
============
*/
void Cvar_List_f( void )
{
convar_t *var;
2012-12-21 21:00:00 +01:00
char *match = NULL;
2016-11-19 22:00:00 +01:00
char *value;
2017-02-12 22:00:00 +01:00
int count = 0;
2011-03-09 22:00:00 +01:00
2012-12-21 21:00:00 +01:00
if( Cmd_Argc() > 1 )
match = Cmd_Argv( 1 );
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
for( var = cvar_vars; var; var = var->next )
2011-03-09 22:00:00 +01:00
{
2012-12-21 21:00:00 +01:00
if( var->name[0] == '@' )
continue; // never shows system cvars
2011-03-11 22:00:00 +01:00
if( match && !Q_stricmpext( match, var->name ))
2011-03-09 22:00:00 +01:00
continue;
2016-11-19 22:00:00 +01:00
if( Q_colorstr( var->string ))
value = va( "\"%s\"", var->string );
else value = va( "\"^2%s^7\"", var->string );
2017-02-12 22:00:00 +01:00
if( FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED ))
2018-03-03 22:00:00 +01:00
Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, var->desc );
2018-03-05 22:00:00 +01:00
else Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, Cvar_BuildAutoDescription( var->flags ));
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
count++;
2011-03-09 22:00:00 +01:00
}
2018-03-03 22:00:00 +01:00
Con_Printf( "\n%i cvars\n", count );
2011-03-09 22:00:00 +01:00
}
/*
============
2016-11-17 22:00:00 +01:00
Cvar_Unlink
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
unlink all cvars with specified flag
2011-03-09 22:00:00 +01:00
============
*/
2016-11-17 22:00:00 +01:00
void Cvar_Unlink( int group )
2011-03-09 22:00:00 +01:00
{
2018-02-12 22:00:00 +01:00
int count;
2011-03-09 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
if( Cvar_VariableInteger( "host_gameloaded" ) && FBitSet( group, FCVAR_EXTDLL ))
2011-03-09 22:00:00 +01:00
return;
2017-02-12 22:00:00 +01:00
if( Cvar_VariableInteger( "host_clientloaded" ) && FBitSet( group, FCVAR_CLIENTDLL ))
2016-11-17 22:00:00 +01:00
return;
2011-03-15 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
if( Cvar_VariableInteger( "host_gameuiloaded" ) && FBitSet( group, FCVAR_GAMEUIDLL ))
2011-07-22 22:00:00 +02:00
return;
2018-02-12 22:00:00 +01:00
count = Cvar_UnlinkVar( NULL, group );
2018-03-23 22:00:00 +01:00
Con_Reportf( "unlink %i cvars\n", count );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_Init
Reads in all archived cvars
============
*/
void Cvar_Init( void )
{
cvar_vars = NULL;
2017-02-12 22:00:00 +01:00
cmd_scripting = Cvar_Get( "cmd_scripting", "0", FCVAR_ARCHIVE, "enable simple condition checking and variable operations" );
2018-03-03 22:00:00 +01:00
Cvar_RegisterVariable (&host_developer); // early registering for dev
2016-11-17 22:00:00 +01:00
Cmd_AddCommand( "setr", Cvar_SetR_f, "create or change the value of a renderinfo variable" );
Cmd_AddCommand( "setgl", Cvar_SetGL_f, "create or change the value of a opengl variable" );
2017-02-12 22:00:00 +01:00
Cmd_AddCommand( "toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" );
2016-11-17 22:00:00 +01:00
Cmd_AddCommand( "reset", Cvar_Reset_f, "reset any type variable to initial value" );
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
}