mirror of
https://github.com/Q3Rally-Team/q3rally.git
synced 2024-11-30 07:31:04 +00:00
96a9e2a9aa
This updates from SDL 2.0.4 to SDL 2.0.8. Fix nullptr dereference in front of nullptr check in FS_CheckPak0 Fix undefined behaviour due to shifting signed in snd_mem.c Fix shifting bits out of byte in tr_font.c Fix shift into sign in cl_cin.c Fix signed bit operations in MSG_ReadBits Add missing address operator in cm_polylib.c OpenGL1: Decay float[8] to float * in tr_marks.c Avoid srcList[-1] in snd_openal.c Fix the behaviour of CVAR_LATCH|CVAR_CHEAT cvars Maximize cURL buffer size Fix mouse grab after toggling fullscreen Fix q3history buffer not cleared between mods and OOB-access Revert "Removed "Color Depth" from q3_ui system settings, it didn't control anything." Fix displayed color/depth/stencil bits values Restore setting r_colorbits in q3_ui Make setting r_stencilbits more consistent in Team Arena UI Fix map list in Team Arena start server menu after entering SP menu Support SDL audio devices that require float32 samples. sdl_snd.c should just initialize SDL audio without checking SDL_WasInit(). There's no need to SDL_PauseAudio(1) before calling SDL_CloseAudio(). Added audio capture support to SDL backend. Use the SDL2 audio device interface instead of the legacy 1.2 API. Disable SDL audio capture until prebuilt SDL libraries are updated to 2.0.8. Update SDL2 to 2.0.8 Add SDL 2.0.1 headers for macOS PPC Make macOS Universal Bundle target 10.6 for x86 and x86_64 Fix possible bot goal state NULL pointer dereference Fix uninitialized bot_goal_t fields Remove unnecessary NULL pointer check in Cmd_RemoveCommand Make UI_DrawProportionalString handle NULL string Fix compiling against macOS system OpenAL and SDL2 frameworks Fix array index in CanDamage() function - discovered by MARTY Fix compiling Makefile (broke in macOS frameworks commit) Fix clearing keys for control in Team Arena UI Make s_useOpenAL be CVAR_LATCH Improvements for dedicated camera followers (team follow1/2) Fix not closing description.txt and fix path seperator Fix duplicate bots displayed in Team Arena ingame add bot menu OpenGL2: Fix parsing specularScale in shaders Don't allow SDL audio capture using pulseaudio Isolate the Altivec code so non-Altivec PPC targets can use the same binary. Limit -maltivec to specific source files on OpenBSD too (untested) Use SDL 2.0.1 headers for macOS ppc64 Fix console offset while Team Arena voiceMenu is open OpenGL2: Readd r_deluxeSpecular. Fix client kicked as unpure when missing the latest cgame/ui pk3s Don't create multiple windows when GL context creation fails Require OpenGL 1.2 for GL_CLAMP_TO_EDGE Fix Linux uninstaller requiring Bash Fix Linux uninstaller redirecting stderr to stdout in preuninstall.sh Reported by @illwieckz. Fix in_restart causing fatal error while video is shutdown Allow pkg-config binary to be overridden with PKG_CONFIG Make testgun command without argument disable test gun model Remove unused renderer_buffer variable Don't upload 8 bit grayscale images as 16 bit luminance OpenGL1: Use RE_UploadCinematic() instead of duplicate code Don't load non-core GL functions for OpenGL 3.2 core context Load OpenGL ES 2.0 function procs Don't check fixed function GL extensions when using shader pipeline OpenGL2: Fix world VAO cache drawing when glIndex_t is unsigned short OpenGL2: Misc fixes and cleanup Fix IQM root joint backlerp when joint number is more than 0 Improve IQM loading Improve IQM CPU vertex skinning performance OpenGL2: Add GPU vertex skinning for IQM models
1464 lines
29 KiB
C
1464 lines
29 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1999-2005 Id Software, Inc.
|
|
|
|
This file is part of Quake III Arena source code.
|
|
|
|
Quake III Arena source code 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 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
Quake III Arena source code 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.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Quake III Arena source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
// cvar.c -- dynamic variable tracking
|
|
|
|
#include "q_shared.h"
|
|
#include "qcommon.h"
|
|
|
|
cvar_t *cvar_vars = NULL;
|
|
cvar_t *cvar_cheats;
|
|
int cvar_modifiedFlags;
|
|
|
|
#define MAX_CVARS 2048
|
|
cvar_t cvar_indexes[MAX_CVARS];
|
|
int cvar_numIndexes;
|
|
|
|
#define FILE_HASH_SIZE 256
|
|
static cvar_t *hashTable[FILE_HASH_SIZE];
|
|
|
|
/*
|
|
================
|
|
return a hash value for the filename
|
|
================
|
|
*/
|
|
static long generateHashValue( const char *fname ) {
|
|
int i;
|
|
long hash;
|
|
char letter;
|
|
|
|
hash = 0;
|
|
i = 0;
|
|
while (fname[i] != '\0') {
|
|
letter = tolower(fname[i]);
|
|
hash+=(long)(letter)*(i+119);
|
|
i++;
|
|
}
|
|
hash &= (FILE_HASH_SIZE-1);
|
|
return hash;
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_ValidateString
|
|
============
|
|
*/
|
|
static qboolean Cvar_ValidateString( const char *s ) {
|
|
if ( !s ) {
|
|
return qfalse;
|
|
}
|
|
if ( strchr( s, '\\' ) ) {
|
|
return qfalse;
|
|
}
|
|
if ( strchr( s, '\"' ) ) {
|
|
return qfalse;
|
|
}
|
|
if ( strchr( s, ';' ) ) {
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_FindVar
|
|
============
|
|
*/
|
|
static cvar_t *Cvar_FindVar( const char *var_name ) {
|
|
cvar_t *var;
|
|
long hash;
|
|
|
|
hash = generateHashValue(var_name);
|
|
|
|
for (var=hashTable[hash] ; var ; var=var->hashNext) {
|
|
if (!Q_stricmp(var_name, var->name)) {
|
|
return var;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_VariableValue
|
|
============
|
|
*/
|
|
float Cvar_VariableValue( const char *var_name ) {
|
|
cvar_t *var;
|
|
|
|
var = Cvar_FindVar (var_name);
|
|
if (!var)
|
|
return 0;
|
|
return var->value;
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_VariableIntegerValue
|
|
============
|
|
*/
|
|
int Cvar_VariableIntegerValue( const char *var_name ) {
|
|
cvar_t *var;
|
|
|
|
var = Cvar_FindVar (var_name);
|
|
if (!var)
|
|
return 0;
|
|
return var->integer;
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_VariableString
|
|
============
|
|
*/
|
|
char *Cvar_VariableString( const char *var_name ) {
|
|
cvar_t *var;
|
|
|
|
var = Cvar_FindVar (var_name);
|
|
if (!var)
|
|
return "";
|
|
return var->string;
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_VariableStringBuffer
|
|
============
|
|
*/
|
|
void Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ) {
|
|
cvar_t *var;
|
|
|
|
var = Cvar_FindVar (var_name);
|
|
if (!var) {
|
|
*buffer = 0;
|
|
}
|
|
else {
|
|
Q_strncpyz( buffer, var->string, bufsize );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Flags
|
|
============
|
|
*/
|
|
int Cvar_Flags(const char *var_name)
|
|
{
|
|
cvar_t *var;
|
|
|
|
if(!(var = Cvar_FindVar(var_name)))
|
|
return CVAR_NONEXISTENT;
|
|
else
|
|
{
|
|
if(var->modified)
|
|
return var->flags | CVAR_MODIFIED;
|
|
else
|
|
return var->flags;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_CommandCompletion
|
|
============
|
|
*/
|
|
void Cvar_CommandCompletion(void (*callback)(const char *s))
|
|
{
|
|
cvar_t *cvar;
|
|
|
|
for(cvar = cvar_vars; cvar; cvar = cvar->next)
|
|
{
|
|
if(cvar->name)
|
|
callback(cvar->name);
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Validate
|
|
============
|
|
*/
|
|
static const char *Cvar_Validate( cvar_t *var,
|
|
const char *value, qboolean warn )
|
|
{
|
|
static char s[ MAX_CVAR_VALUE_STRING ];
|
|
float valuef;
|
|
qboolean changed = qfalse;
|
|
|
|
if( !var->validate )
|
|
return value;
|
|
|
|
if( !value )
|
|
return value;
|
|
|
|
if( Q_isanumber( value ) )
|
|
{
|
|
valuef = atof( value );
|
|
|
|
if( var->integral )
|
|
{
|
|
if( !Q_isintegral( valuef ) )
|
|
{
|
|
if( warn )
|
|
Com_Printf( "WARNING: cvar '%s' must be integral", var->name );
|
|
|
|
valuef = (int)valuef;
|
|
changed = qtrue;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( warn )
|
|
Com_Printf( "WARNING: cvar '%s' must be numeric", var->name );
|
|
|
|
valuef = atof( var->resetString );
|
|
changed = qtrue;
|
|
}
|
|
|
|
if( valuef < var->min )
|
|
{
|
|
if( warn )
|
|
{
|
|
if( changed )
|
|
Com_Printf( " and is" );
|
|
else
|
|
Com_Printf( "WARNING: cvar '%s'", var->name );
|
|
|
|
if( Q_isintegral( var->min ) )
|
|
Com_Printf( " out of range (min %d)", (int)var->min );
|
|
else
|
|
Com_Printf( " out of range (min %f)", var->min );
|
|
}
|
|
|
|
valuef = var->min;
|
|
changed = qtrue;
|
|
}
|
|
else if( valuef > var->max )
|
|
{
|
|
if( warn )
|
|
{
|
|
if( changed )
|
|
Com_Printf( " and is" );
|
|
else
|
|
Com_Printf( "WARNING: cvar '%s'", var->name );
|
|
|
|
if( Q_isintegral( var->max ) )
|
|
Com_Printf( " out of range (max %d)", (int)var->max );
|
|
else
|
|
Com_Printf( " out of range (max %f)", var->max );
|
|
}
|
|
|
|
valuef = var->max;
|
|
changed = qtrue;
|
|
}
|
|
|
|
if( changed )
|
|
{
|
|
if( Q_isintegral( valuef ) )
|
|
{
|
|
Com_sprintf( s, sizeof( s ), "%d", (int)valuef );
|
|
|
|
if( warn )
|
|
Com_Printf( ", setting to %d\n", (int)valuef );
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf( s, sizeof( s ), "%f", valuef );
|
|
|
|
if( warn )
|
|
Com_Printf( ", setting to %f\n", valuef );
|
|
}
|
|
|
|
return s;
|
|
}
|
|
else
|
|
return value;
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_Get
|
|
|
|
If the variable already exists, the value will not be set unless CVAR_ROM
|
|
The flags will be or'ed in if the variable exists.
|
|
============
|
|
*/
|
|
cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
|
|
cvar_t *var;
|
|
long hash;
|
|
int index;
|
|
|
|
if ( !var_name || ! var_value ) {
|
|
Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" );
|
|
}
|
|
|
|
if ( !Cvar_ValidateString( var_name ) ) {
|
|
Com_Printf("invalid cvar name string: %s\n", var_name );
|
|
var_name = "BADNAME";
|
|
}
|
|
|
|
#if 0 // FIXME: values with backslash happen
|
|
if ( !Cvar_ValidateString( var_value ) ) {
|
|
Com_Printf("invalid cvar value string: %s\n", var_value );
|
|
var_value = "BADVALUE";
|
|
}
|
|
#endif
|
|
|
|
var = Cvar_FindVar (var_name);
|
|
|
|
if(var)
|
|
{
|
|
var_value = Cvar_Validate(var, var_value, qfalse);
|
|
|
|
// Make sure the game code cannot mark engine-added variables as gamecode vars
|
|
if(var->flags & CVAR_VM_CREATED)
|
|
{
|
|
if(!(flags & CVAR_VM_CREATED))
|
|
var->flags &= ~CVAR_VM_CREATED;
|
|
}
|
|
else if (!(var->flags & CVAR_USER_CREATED))
|
|
{
|
|
if(flags & CVAR_VM_CREATED)
|
|
flags &= ~CVAR_VM_CREATED;
|
|
}
|
|
|
|
// if the C code is now specifying a variable that the user already
|
|
// set a value for, take the new value as the reset value
|
|
if(var->flags & CVAR_USER_CREATED)
|
|
{
|
|
var->flags &= ~CVAR_USER_CREATED;
|
|
Z_Free( var->resetString );
|
|
var->resetString = CopyString( var_value );
|
|
|
|
if(flags & CVAR_ROM)
|
|
{
|
|
// this variable was set by the user,
|
|
// so force it to value given by the engine.
|
|
|
|
if(var->latchedString)
|
|
Z_Free(var->latchedString);
|
|
|
|
var->latchedString = CopyString(var_value);
|
|
}
|
|
}
|
|
|
|
// Make sure servers cannot mark engine-added variables as SERVER_CREATED
|
|
if(var->flags & CVAR_SERVER_CREATED)
|
|
{
|
|
if(!(flags & CVAR_SERVER_CREATED))
|
|
var->flags &= ~CVAR_SERVER_CREATED;
|
|
}
|
|
else
|
|
{
|
|
if(flags & CVAR_SERVER_CREATED)
|
|
flags &= ~CVAR_SERVER_CREATED;
|
|
}
|
|
|
|
var->flags |= flags;
|
|
|
|
// only allow one non-empty reset string without a warning
|
|
if ( !var->resetString[0] ) {
|
|
// we don't have a reset string yet
|
|
Z_Free( var->resetString );
|
|
var->resetString = CopyString( var_value );
|
|
} else if ( var_value[0] && strcmp( var->resetString, var_value ) ) {
|
|
Com_DPrintf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n",
|
|
var_name, var->resetString, var_value );
|
|
}
|
|
// if we have a latched string, take that value now
|
|
if ( var->latchedString ) {
|
|
char *s;
|
|
|
|
s = var->latchedString;
|
|
var->latchedString = NULL; // otherwise cvar_set2 would free it
|
|
Cvar_Set2( var_name, s, qtrue );
|
|
Z_Free( s );
|
|
}
|
|
|
|
// ZOID--needs to be set so that cvars the game sets as
|
|
// SERVERINFO get sent to clients
|
|
cvar_modifiedFlags |= flags;
|
|
|
|
return var;
|
|
}
|
|
|
|
//
|
|
// allocate a new cvar
|
|
//
|
|
|
|
// find a free cvar
|
|
for(index = 0; index < MAX_CVARS; index++)
|
|
{
|
|
if(!cvar_indexes[index].name)
|
|
break;
|
|
}
|
|
|
|
if(index >= MAX_CVARS)
|
|
{
|
|
if(!com_errorEntered)
|
|
Com_Error(ERR_FATAL, "Error: Too many cvars, cannot create a new one!");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
var = &cvar_indexes[index];
|
|
|
|
if(index >= cvar_numIndexes)
|
|
cvar_numIndexes = index + 1;
|
|
|
|
var->name = CopyString (var_name);
|
|
var->string = CopyString (var_value);
|
|
var->modified = qtrue;
|
|
var->modificationCount = 1;
|
|
var->value = atof (var->string);
|
|
var->integer = atoi(var->string);
|
|
var->resetString = CopyString( var_value );
|
|
var->validate = qfalse;
|
|
var->description = NULL;
|
|
|
|
// link the variable in
|
|
var->next = cvar_vars;
|
|
if(cvar_vars)
|
|
cvar_vars->prev = var;
|
|
|
|
var->prev = NULL;
|
|
cvar_vars = var;
|
|
|
|
var->flags = flags;
|
|
// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
|
|
cvar_modifiedFlags |= var->flags;
|
|
|
|
hash = generateHashValue(var_name);
|
|
var->hashIndex = hash;
|
|
|
|
var->hashNext = hashTable[hash];
|
|
if(hashTable[hash])
|
|
hashTable[hash]->hashPrev = var;
|
|
|
|
var->hashPrev = NULL;
|
|
hashTable[hash] = var;
|
|
|
|
return var;
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Print
|
|
|
|
Prints the value, default, and latched string of the given variable
|
|
============
|
|
*/
|
|
void Cvar_Print( cvar_t *v ) {
|
|
Com_Printf ("\"%s\" is:\"%s" S_COLOR_WHITE "\"",
|
|
v->name, v->string );
|
|
|
|
if ( !( v->flags & CVAR_ROM ) ) {
|
|
if ( !Q_stricmp( v->string, v->resetString ) ) {
|
|
Com_Printf (", the default" );
|
|
} else {
|
|
Com_Printf (" default:\"%s" S_COLOR_WHITE "\"",
|
|
v->resetString );
|
|
}
|
|
}
|
|
|
|
Com_Printf ("\n");
|
|
|
|
if ( v->latchedString ) {
|
|
Com_Printf( "latched: \"%s\"\n", v->latchedString );
|
|
}
|
|
|
|
if ( v->description ) {
|
|
Com_Printf( "%s\n", v->description );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Set2
|
|
============
|
|
*/
|
|
cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {
|
|
cvar_t *var;
|
|
|
|
// Com_DPrintf( "Cvar_Set2: %s %s\n", var_name, value );
|
|
|
|
if ( !Cvar_ValidateString( var_name ) ) {
|
|
Com_Printf("invalid cvar name string: %s\n", var_name );
|
|
var_name = "BADNAME";
|
|
}
|
|
|
|
#if 0 // FIXME
|
|
if ( value && !Cvar_ValidateString( value ) ) {
|
|
Com_Printf("invalid cvar value string: %s\n", value );
|
|
var_value = "BADVALUE";
|
|
}
|
|
#endif
|
|
|
|
var = Cvar_FindVar (var_name);
|
|
if (!var) {
|
|
if ( !value ) {
|
|
return NULL;
|
|
}
|
|
// create it
|
|
if ( !force ) {
|
|
return Cvar_Get( var_name, value, CVAR_USER_CREATED );
|
|
} else {
|
|
return Cvar_Get (var_name, value, 0);
|
|
}
|
|
}
|
|
|
|
if (!value ) {
|
|
value = var->resetString;
|
|
}
|
|
|
|
value = Cvar_Validate(var, value, qtrue);
|
|
|
|
if((var->flags & CVAR_LATCH) && var->latchedString)
|
|
{
|
|
if(!strcmp(value, var->string))
|
|
{
|
|
Z_Free(var->latchedString);
|
|
var->latchedString = NULL;
|
|
return var;
|
|
}
|
|
|
|
if(!strcmp(value, var->latchedString))
|
|
return var;
|
|
}
|
|
else if(!strcmp(value, var->string))
|
|
return var;
|
|
|
|
// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
|
|
cvar_modifiedFlags |= var->flags;
|
|
|
|
if (!force)
|
|
{
|
|
if (var->flags & CVAR_ROM)
|
|
{
|
|
Com_Printf ("%s is read only.\n", var_name);
|
|
return var;
|
|
}
|
|
|
|
if (var->flags & CVAR_INIT)
|
|
{
|
|
Com_Printf ("%s is write protected.\n", var_name);
|
|
return var;
|
|
}
|
|
|
|
if ((var->flags & CVAR_CHEAT) && !cvar_cheats->integer)
|
|
{
|
|
Com_Printf ("%s is cheat protected.\n", var_name);
|
|
return var;
|
|
}
|
|
|
|
if (var->flags & CVAR_LATCH)
|
|
{
|
|
if (var->latchedString)
|
|
{
|
|
if (strcmp(value, var->latchedString) == 0)
|
|
return var;
|
|
Z_Free (var->latchedString);
|
|
}
|
|
else
|
|
{
|
|
if (strcmp(value, var->string) == 0)
|
|
return var;
|
|
}
|
|
|
|
Com_Printf ("%s will be changed upon restarting.\n", var_name);
|
|
var->latchedString = CopyString(value);
|
|
var->modified = qtrue;
|
|
var->modificationCount++;
|
|
return var;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (var->latchedString)
|
|
{
|
|
Z_Free (var->latchedString);
|
|
var->latchedString = NULL;
|
|
}
|
|
}
|
|
|
|
if (!strcmp(value, var->string))
|
|
return var; // not changed
|
|
|
|
var->modified = qtrue;
|
|
var->modificationCount++;
|
|
|
|
Z_Free (var->string); // free the old value string
|
|
|
|
var->string = CopyString(value);
|
|
var->value = atof (var->string);
|
|
var->integer = atoi (var->string);
|
|
|
|
return var;
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Set
|
|
============
|
|
*/
|
|
void Cvar_Set( const char *var_name, const char *value) {
|
|
Cvar_Set2 (var_name, value, qtrue);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_SetSafe
|
|
============
|
|
*/
|
|
void Cvar_SetSafe( const char *var_name, const char *value )
|
|
{
|
|
int flags = Cvar_Flags( var_name );
|
|
|
|
if((flags != CVAR_NONEXISTENT) && (flags & CVAR_PROTECTED))
|
|
{
|
|
if( value )
|
|
Com_Error( ERR_DROP, "Restricted source tried to set "
|
|
"\"%s\" to \"%s\"", var_name, value );
|
|
else
|
|
Com_Error( ERR_DROP, "Restricted source tried to "
|
|
"modify \"%s\"", var_name );
|
|
return;
|
|
}
|
|
Cvar_Set( var_name, value );
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_SetLatched
|
|
============
|
|
*/
|
|
void Cvar_SetLatched( const char *var_name, const char *value) {
|
|
Cvar_Set2 (var_name, value, qfalse);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_SetValue
|
|
============
|
|
*/
|
|
void Cvar_SetValue( const char *var_name, float value) {
|
|
char val[32];
|
|
|
|
if ( value == (int)value ) {
|
|
Com_sprintf (val, sizeof(val), "%i",(int)value);
|
|
} else {
|
|
Com_sprintf (val, sizeof(val), "%f",value);
|
|
}
|
|
Cvar_Set (var_name, val);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_SetValueSafe
|
|
============
|
|
*/
|
|
void Cvar_SetValueSafe( const char *var_name, float value )
|
|
{
|
|
char val[32];
|
|
|
|
if( Q_isintegral( value ) )
|
|
Com_sprintf( val, sizeof(val), "%i", (int)value );
|
|
else
|
|
Com_sprintf( val, sizeof(val), "%f", value );
|
|
Cvar_SetSafe( var_name, val );
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Reset
|
|
============
|
|
*/
|
|
void Cvar_Reset( const char *var_name ) {
|
|
Cvar_Set2( var_name, NULL, qfalse );
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_ForceReset
|
|
============
|
|
*/
|
|
void Cvar_ForceReset(const char *var_name)
|
|
{
|
|
Cvar_Set2(var_name, NULL, qtrue);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_SetCheatState
|
|
|
|
Any testing variables will be reset to the safe values
|
|
============
|
|
*/
|
|
void Cvar_SetCheatState(void)
|
|
{
|
|
cvar_t *var;
|
|
|
|
// set all default vars to the safe value
|
|
for(var = cvar_vars; var ; var = var->next)
|
|
{
|
|
if(var->flags & CVAR_CHEAT)
|
|
{
|
|
// the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here
|
|
// because of a different var->latchedString
|
|
if (var->latchedString)
|
|
{
|
|
Z_Free(var->latchedString);
|
|
var->latchedString = NULL;
|
|
}
|
|
if (strcmp(var->resetString,var->string))
|
|
Cvar_Set(var->name, var->resetString);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Command
|
|
|
|
Handles variable inspection and changing from the console
|
|
============
|
|
*/
|
|
qboolean Cvar_Command( void ) {
|
|
cvar_t *v;
|
|
|
|
// check variables
|
|
v = Cvar_FindVar (Cmd_Argv(0));
|
|
if (!v) {
|
|
return qfalse;
|
|
}
|
|
|
|
// perform a variable print or set
|
|
if ( Cmd_Argc() == 1 ) {
|
|
Cvar_Print( v );
|
|
return qtrue;
|
|
}
|
|
|
|
// set the value if forcing isn't required
|
|
Cvar_Set2 (v->name, Cmd_Args(), qfalse);
|
|
return qtrue;
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_Print_f
|
|
|
|
Prints the contents of a cvar
|
|
(preferred over Cvar_Command where cvar names and commands conflict)
|
|
============
|
|
*/
|
|
void Cvar_Print_f(void)
|
|
{
|
|
char *name;
|
|
cvar_t *cv;
|
|
|
|
if(Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf ("usage: print <variable>\n");
|
|
return;
|
|
}
|
|
|
|
name = Cmd_Argv(1);
|
|
|
|
cv = Cvar_FindVar(name);
|
|
|
|
if(cv)
|
|
Cvar_Print(cv);
|
|
else
|
|
Com_Printf ("Cvar %s does not exist.\n", name);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Toggle_f
|
|
|
|
Toggles a cvar for easy single key binding, optionally through a list of
|
|
given values
|
|
============
|
|
*/
|
|
void Cvar_Toggle_f( void ) {
|
|
int i, c = Cmd_Argc();
|
|
char *curval;
|
|
|
|
if(c < 2) {
|
|
Com_Printf("usage: toggle <variable> [value1, value2, ...]\n");
|
|
return;
|
|
}
|
|
|
|
if(c == 2) {
|
|
Cvar_Set2(Cmd_Argv(1), va("%d",
|
|
!Cvar_VariableValue(Cmd_Argv(1))),
|
|
qfalse);
|
|
return;
|
|
}
|
|
|
|
if(c == 3) {
|
|
Com_Printf("toggle: nothing to toggle to\n");
|
|
return;
|
|
}
|
|
|
|
curval = Cvar_VariableString(Cmd_Argv(1));
|
|
|
|
// don't bother checking the last arg for a match since the desired
|
|
// behaviour is the same as no match (set to the first argument)
|
|
for(i = 2; i + 1 < c; i++) {
|
|
if(strcmp(curval, Cmd_Argv(i)) == 0) {
|
|
Cvar_Set2(Cmd_Argv(1), Cmd_Argv(i + 1), qfalse);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// fallback
|
|
Cvar_Set2(Cmd_Argv(1), Cmd_Argv(2), qfalse);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Set_f
|
|
|
|
Allows setting and defining of arbitrary cvars from console, even if they
|
|
weren't declared in C code.
|
|
============
|
|
*/
|
|
void Cvar_Set_f( void ) {
|
|
int c;
|
|
char *cmd;
|
|
cvar_t *v;
|
|
|
|
c = Cmd_Argc();
|
|
cmd = Cmd_Argv(0);
|
|
|
|
if ( c < 2 ) {
|
|
Com_Printf ("usage: %s <variable> <value>\n", cmd);
|
|
return;
|
|
}
|
|
if ( c == 2 ) {
|
|
Cvar_Print_f();
|
|
return;
|
|
}
|
|
|
|
v = Cvar_Set2 (Cmd_Argv(1), Cmd_ArgsFrom(2), qfalse);
|
|
if( !v ) {
|
|
return;
|
|
}
|
|
switch( cmd[3] ) {
|
|
case 'a':
|
|
if( !( v->flags & CVAR_ARCHIVE ) ) {
|
|
v->flags |= CVAR_ARCHIVE;
|
|
cvar_modifiedFlags |= CVAR_ARCHIVE;
|
|
}
|
|
break;
|
|
case 'u':
|
|
if( !( v->flags & CVAR_USERINFO ) ) {
|
|
v->flags |= CVAR_USERINFO;
|
|
cvar_modifiedFlags |= CVAR_USERINFO;
|
|
}
|
|
break;
|
|
case 's':
|
|
if( !( v->flags & CVAR_SERVERINFO ) ) {
|
|
v->flags |= CVAR_SERVERINFO;
|
|
cvar_modifiedFlags |= CVAR_SERVERINFO;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Reset_f
|
|
============
|
|
*/
|
|
void Cvar_Reset_f( void ) {
|
|
if ( Cmd_Argc() != 2 ) {
|
|
Com_Printf ("usage: reset <variable>\n");
|
|
return;
|
|
}
|
|
Cvar_Reset( Cmd_Argv( 1 ) );
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_WriteVariables
|
|
|
|
Appends lines containing "set variable value" for all variables
|
|
with the archive flag set to qtrue.
|
|
============
|
|
*/
|
|
void Cvar_WriteVariables(fileHandle_t f)
|
|
{
|
|
cvar_t *var;
|
|
char buffer[1024];
|
|
|
|
for (var = cvar_vars; var; var = var->next)
|
|
{
|
|
if(!var->name || Q_stricmp( var->name, "cl_cdkey" ) == 0)
|
|
continue;
|
|
|
|
if( var->flags & CVAR_ARCHIVE ) {
|
|
// write the latched value, even if it hasn't taken effect yet
|
|
if ( var->latchedString ) {
|
|
if( strlen( var->name ) + strlen( var->latchedString ) + 10 > sizeof( buffer ) ) {
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: value of variable "
|
|
"\"%s\" too long to write to file\n", var->name );
|
|
continue;
|
|
}
|
|
Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->latchedString);
|
|
} else {
|
|
if( strlen( var->name ) + strlen( var->string ) + 10 > sizeof( buffer ) ) {
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: value of variable "
|
|
"\"%s\" too long to write to file\n", var->name );
|
|
continue;
|
|
}
|
|
Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->string);
|
|
}
|
|
FS_Write( buffer, strlen( buffer ), f );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_List_f
|
|
============
|
|
*/
|
|
void Cvar_List_f( void ) {
|
|
cvar_t *var;
|
|
int i;
|
|
char *match;
|
|
|
|
if ( Cmd_Argc() > 1 ) {
|
|
match = Cmd_Argv( 1 );
|
|
} else {
|
|
match = NULL;
|
|
}
|
|
|
|
i = 0;
|
|
for (var = cvar_vars ; var ; var = var->next, i++)
|
|
{
|
|
if(!var->name || (match && !Com_Filter(match, var->name, qfalse)))
|
|
continue;
|
|
|
|
if (var->flags & CVAR_SERVERINFO) {
|
|
Com_Printf("S");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_SYSTEMINFO) {
|
|
Com_Printf("s");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_USERINFO) {
|
|
Com_Printf("U");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_ROM) {
|
|
Com_Printf("R");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_INIT) {
|
|
Com_Printf("I");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_ARCHIVE) {
|
|
Com_Printf("A");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_LATCH) {
|
|
Com_Printf("L");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_CHEAT) {
|
|
Com_Printf("C");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_USER_CREATED) {
|
|
Com_Printf("?");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
|
|
Com_Printf (" %s \"%s\"\n", var->name, var->string);
|
|
}
|
|
|
|
Com_Printf ("\n%i total cvars\n", i);
|
|
Com_Printf ("%i cvar indexes\n", cvar_numIndexes);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_ListModified_f
|
|
============
|
|
*/
|
|
void Cvar_ListModified_f( void ) {
|
|
cvar_t *var;
|
|
int totalModified;
|
|
char *value;
|
|
char *match;
|
|
|
|
if ( Cmd_Argc() > 1 ) {
|
|
match = Cmd_Argv( 1 );
|
|
} else {
|
|
match = NULL;
|
|
}
|
|
|
|
totalModified = 0;
|
|
for (var = cvar_vars ; var ; var = var->next)
|
|
{
|
|
if ( !var->name || !var->modificationCount )
|
|
continue;
|
|
|
|
value = var->latchedString ? var->latchedString : var->string;
|
|
if ( !strcmp( value, var->resetString ) )
|
|
continue;
|
|
|
|
totalModified++;
|
|
|
|
if (match && !Com_Filter(match, var->name, qfalse))
|
|
continue;
|
|
|
|
if (var->flags & CVAR_SERVERINFO) {
|
|
Com_Printf("S");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_SYSTEMINFO) {
|
|
Com_Printf("s");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_USERINFO) {
|
|
Com_Printf("U");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_ROM) {
|
|
Com_Printf("R");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_INIT) {
|
|
Com_Printf("I");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_ARCHIVE) {
|
|
Com_Printf("A");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_LATCH) {
|
|
Com_Printf("L");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_CHEAT) {
|
|
Com_Printf("C");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
if (var->flags & CVAR_USER_CREATED) {
|
|
Com_Printf("?");
|
|
} else {
|
|
Com_Printf(" ");
|
|
}
|
|
|
|
Com_Printf (" %s \"%s\", default \"%s\"\n", var->name, value, var->resetString);
|
|
}
|
|
|
|
Com_Printf ("\n%i total modified cvars\n", totalModified);
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Unset
|
|
|
|
Unsets a cvar
|
|
============
|
|
*/
|
|
|
|
cvar_t *Cvar_Unset(cvar_t *cv)
|
|
{
|
|
cvar_t *next = cv->next;
|
|
|
|
// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
|
|
cvar_modifiedFlags |= cv->flags;
|
|
|
|
if(cv->name)
|
|
Z_Free(cv->name);
|
|
if(cv->string)
|
|
Z_Free(cv->string);
|
|
if(cv->latchedString)
|
|
Z_Free(cv->latchedString);
|
|
if(cv->resetString)
|
|
Z_Free(cv->resetString);
|
|
if(cv->description)
|
|
Z_Free(cv->description);
|
|
|
|
if(cv->prev)
|
|
cv->prev->next = cv->next;
|
|
else
|
|
cvar_vars = cv->next;
|
|
if(cv->next)
|
|
cv->next->prev = cv->prev;
|
|
|
|
if(cv->hashPrev)
|
|
cv->hashPrev->hashNext = cv->hashNext;
|
|
else
|
|
hashTable[cv->hashIndex] = cv->hashNext;
|
|
if(cv->hashNext)
|
|
cv->hashNext->hashPrev = cv->hashPrev;
|
|
|
|
Com_Memset(cv, '\0', sizeof(*cv));
|
|
|
|
return next;
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Unset_f
|
|
|
|
Unsets a userdefined cvar
|
|
============
|
|
*/
|
|
|
|
void Cvar_Unset_f(void)
|
|
{
|
|
cvar_t *cv;
|
|
|
|
if(Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: %s <varname>\n", Cmd_Argv(0));
|
|
return;
|
|
}
|
|
|
|
cv = Cvar_FindVar(Cmd_Argv(1));
|
|
|
|
if(!cv)
|
|
return;
|
|
|
|
if(cv->flags & CVAR_USER_CREATED)
|
|
Cvar_Unset(cv);
|
|
else
|
|
Com_Printf("Error: %s: Variable %s is not user created.\n", Cmd_Argv(0), cv->name);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_Restart
|
|
|
|
Resets all cvars to their hardcoded values and removes userdefined variables
|
|
and variables added via the VMs if requested.
|
|
============
|
|
*/
|
|
|
|
void Cvar_Restart(qboolean unsetVM)
|
|
{
|
|
cvar_t *curvar;
|
|
|
|
curvar = cvar_vars;
|
|
|
|
while(curvar)
|
|
{
|
|
if((curvar->flags & CVAR_USER_CREATED) ||
|
|
(unsetVM && (curvar->flags & CVAR_VM_CREATED)))
|
|
{
|
|
// throw out any variables the user/vm created
|
|
curvar = Cvar_Unset(curvar);
|
|
continue;
|
|
}
|
|
|
|
if(!(curvar->flags & (CVAR_ROM | CVAR_INIT | CVAR_NORESTART)))
|
|
{
|
|
// Just reset the rest to their default values.
|
|
Cvar_Set2(curvar->name, curvar->resetString, qfalse);
|
|
}
|
|
|
|
curvar = curvar->next;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
Cvar_Restart_f
|
|
|
|
Resets all cvars to their hardcoded values
|
|
============
|
|
*/
|
|
void Cvar_Restart_f(void)
|
|
{
|
|
Cvar_Restart(qfalse);
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
Cvar_InfoString
|
|
=====================
|
|
*/
|
|
char *Cvar_InfoString(int bit)
|
|
{
|
|
static char info[MAX_INFO_STRING];
|
|
cvar_t *var;
|
|
|
|
info[0] = 0;
|
|
|
|
for(var = cvar_vars; var; var = var->next)
|
|
{
|
|
if(var->name && (var->flags & bit))
|
|
Info_SetValueForKey (info, var->name, var->string);
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
Cvar_InfoString_Big
|
|
|
|
handles large info strings ( CS_SYSTEMINFO )
|
|
=====================
|
|
*/
|
|
char *Cvar_InfoString_Big(int bit)
|
|
{
|
|
static char info[BIG_INFO_STRING];
|
|
cvar_t *var;
|
|
|
|
info[0] = 0;
|
|
|
|
for (var = cvar_vars; var; var = var->next)
|
|
{
|
|
if(var->name && (var->flags & bit))
|
|
Info_SetValueForKey_Big (info, var->name, var->string);
|
|
}
|
|
return info;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=====================
|
|
Cvar_InfoStringBuffer
|
|
=====================
|
|
*/
|
|
void Cvar_InfoStringBuffer( int bit, char* buff, int buffsize ) {
|
|
Q_strncpyz(buff,Cvar_InfoString(bit),buffsize);
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
Cvar_CheckRange
|
|
=====================
|
|
*/
|
|
void Cvar_CheckRange( cvar_t *var, float min, float max, qboolean integral )
|
|
{
|
|
var->validate = qtrue;
|
|
var->min = min;
|
|
var->max = max;
|
|
var->integral = integral;
|
|
|
|
// Force an initial range check
|
|
Cvar_Set( var->name, var->string );
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
Cvar_SetDescription
|
|
=====================
|
|
*/
|
|
void Cvar_SetDescription( cvar_t *var, const char *var_description )
|
|
{
|
|
if( var_description && var_description[0] != '\0' )
|
|
{
|
|
if( var->description != NULL )
|
|
{
|
|
Z_Free( var->description );
|
|
}
|
|
var->description = CopyString( var_description );
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
Cvar_Register
|
|
|
|
basically a slightly modified Cvar_Get for the interpreted modules
|
|
=====================
|
|
*/
|
|
void Cvar_Register(vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags)
|
|
{
|
|
cvar_t *cv;
|
|
|
|
// There is code in Cvar_Get to prevent CVAR_ROM cvars being changed by the
|
|
// user. In other words CVAR_ARCHIVE and CVAR_ROM are mutually exclusive
|
|
// flags. Unfortunately some historical game code (including single player
|
|
// baseq3) sets both flags. We unset CVAR_ROM for such cvars.
|
|
if ((flags & (CVAR_ARCHIVE | CVAR_ROM)) == (CVAR_ARCHIVE | CVAR_ROM)) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: Unsetting CVAR_ROM from cvar '%s', "
|
|
"since it is also CVAR_ARCHIVE\n", varName );
|
|
flags &= ~CVAR_ROM;
|
|
}
|
|
|
|
// Don't allow VM to specific a different creator or other internal flags.
|
|
if ( flags & CVAR_USER_CREATED ) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: VM tried to set CVAR_USER_CREATED on cvar '%s'\n", varName );
|
|
flags &= ~CVAR_USER_CREATED;
|
|
}
|
|
if ( flags & CVAR_SERVER_CREATED ) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: VM tried to set CVAR_SERVER_CREATED on cvar '%s'\n", varName );
|
|
flags &= ~CVAR_SERVER_CREATED;
|
|
}
|
|
if ( flags & CVAR_PROTECTED ) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: VM tried to set CVAR_PROTECTED on cvar '%s'\n", varName );
|
|
flags &= ~CVAR_PROTECTED;
|
|
}
|
|
if ( flags & CVAR_MODIFIED ) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: VM tried to set CVAR_MODIFIED on cvar '%s'\n", varName );
|
|
flags &= ~CVAR_MODIFIED;
|
|
}
|
|
if ( flags & CVAR_NONEXISTENT ) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: VM tried to set CVAR_NONEXISTENT on cvar '%s'\n", varName );
|
|
flags &= ~CVAR_NONEXISTENT;
|
|
}
|
|
|
|
cv = Cvar_FindVar(varName);
|
|
|
|
// Don't modify cvar if it's protected.
|
|
if ( cv && ( cv->flags & CVAR_PROTECTED ) ) {
|
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: VM tried to register protected cvar '%s' with value '%s'%s\n",
|
|
varName, defaultValue, ( flags & ~cv->flags ) != 0 ? " and new flags" : "" );
|
|
} else {
|
|
cv = Cvar_Get(varName, defaultValue, flags | CVAR_VM_CREATED);
|
|
}
|
|
|
|
if (!vmCvar)
|
|
return;
|
|
|
|
vmCvar->handle = cv - cvar_indexes;
|
|
vmCvar->modificationCount = -1;
|
|
Cvar_Update( vmCvar );
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
Cvar_Update
|
|
|
|
updates an interpreted modules' version of a cvar
|
|
=====================
|
|
*/
|
|
void Cvar_Update( vmCvar_t *vmCvar ) {
|
|
cvar_t *cv = NULL;
|
|
assert(vmCvar);
|
|
|
|
if ( (unsigned)vmCvar->handle >= cvar_numIndexes ) {
|
|
Com_Error( ERR_DROP, "Cvar_Update: handle out of range" );
|
|
}
|
|
|
|
cv = cvar_indexes + vmCvar->handle;
|
|
|
|
if ( cv->modificationCount == vmCvar->modificationCount ) {
|
|
return;
|
|
}
|
|
if ( !cv->string ) {
|
|
return; // variable might have been cleared by a cvar_restart
|
|
}
|
|
vmCvar->modificationCount = cv->modificationCount;
|
|
if ( strlen(cv->string)+1 > MAX_CVAR_VALUE_STRING )
|
|
Com_Error( ERR_DROP, "Cvar_Update: src %s length %u exceeds MAX_CVAR_VALUE_STRING",
|
|
cv->string,
|
|
(unsigned int) strlen(cv->string));
|
|
Q_strncpyz( vmCvar->string, cv->string, MAX_CVAR_VALUE_STRING );
|
|
|
|
vmCvar->value = cv->value;
|
|
vmCvar->integer = cv->integer;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cvar_CompleteCvarName
|
|
==================
|
|
*/
|
|
void Cvar_CompleteCvarName( char *args, int argNum )
|
|
{
|
|
if( argNum == 2 )
|
|
{
|
|
// Skip "<cmd> "
|
|
char *p = Com_SkipTokens( args, 1, " " );
|
|
|
|
if( p > args )
|
|
Field_CompleteCommand( p, qfalse, qtrue );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
Cvar_Init
|
|
|
|
Reads in all archived cvars
|
|
============
|
|
*/
|
|
void Cvar_Init (void)
|
|
{
|
|
Com_Memset(cvar_indexes, '\0', sizeof(cvar_indexes));
|
|
Com_Memset(hashTable, '\0', sizeof(hashTable));
|
|
|
|
cvar_cheats = Cvar_Get("sv_cheats", "1", CVAR_ROM | CVAR_SYSTEMINFO );
|
|
|
|
Cmd_AddCommand ("print", Cvar_Print_f);
|
|
Cmd_AddCommand ("toggle", Cvar_Toggle_f);
|
|
Cmd_SetCommandCompletionFunc( "toggle", Cvar_CompleteCvarName );
|
|
Cmd_AddCommand ("set", Cvar_Set_f);
|
|
Cmd_SetCommandCompletionFunc( "set", Cvar_CompleteCvarName );
|
|
Cmd_AddCommand ("sets", Cvar_Set_f);
|
|
Cmd_SetCommandCompletionFunc( "sets", Cvar_CompleteCvarName );
|
|
Cmd_AddCommand ("setu", Cvar_Set_f);
|
|
Cmd_SetCommandCompletionFunc( "setu", Cvar_CompleteCvarName );
|
|
Cmd_AddCommand ("seta", Cvar_Set_f);
|
|
Cmd_SetCommandCompletionFunc( "seta", Cvar_CompleteCvarName );
|
|
Cmd_AddCommand ("reset", Cvar_Reset_f);
|
|
Cmd_SetCommandCompletionFunc( "reset", Cvar_CompleteCvarName );
|
|
Cmd_AddCommand ("unset", Cvar_Unset_f);
|
|
Cmd_SetCommandCompletionFunc("unset", Cvar_CompleteCvarName);
|
|
|
|
Cmd_AddCommand ("cvarlist", Cvar_List_f);
|
|
Cmd_AddCommand ("cvar_modified", Cvar_ListModified_f);
|
|
Cmd_AddCommand ("cvar_restart", Cvar_Restart_f);
|
|
}
|