00001
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "common.h"
00032 #include "../shared/infostring.h"
00033
00034 #define CVAR_HASH_SIZE 64
00035
00036 static cvar_t *cvarVarsHash[CVAR_HASH_SIZE];
00037
00042 static qboolean renderModified;
00043
00048 static qboolean userinfoModified;
00049
00050 void Com_SetUserinfoModified (qboolean modified)
00051 {
00052 userinfoModified = modified;
00053 }
00054
00055 qboolean Com_IsUserinfoModified (void)
00056 {
00057 return userinfoModified;
00058 }
00059
00060 void Com_SetRenderModified (qboolean modified)
00061 {
00062 renderModified = modified;
00063 }
00064
00065 qboolean Com_IsRenderModified (void)
00066 {
00067 return renderModified;
00068 }
00069
00073 static cvar_t *cvarVars;
00074
00075 static qboolean Cvar_InfoValidate (const char *s)
00076 {
00077 if (strstr(s, "\\"))
00078 return qfalse;
00079 if (strstr(s, "\""))
00080 return qfalse;
00081 if (strstr(s, ";"))
00082 return qfalse;
00083 return qtrue;
00084 }
00085
00093 cvar_t *Cvar_FindVar (const char *varName)
00094 {
00095 cvar_t *var;
00096 const unsigned hash = Com_HashKey(varName, CVAR_HASH_SIZE);
00097
00098 for (var = cvarVarsHash[hash]; var; var = var->hash_next)
00099 if (!strcmp(varName, var->name))
00100 return var;
00101
00102 return NULL;
00103 }
00104
00112 float Cvar_GetValue (const char *varName)
00113 {
00114 cvar_t *var;
00115
00116 var = Cvar_FindVar(varName);
00117 if (!var)
00118 return 0.0;
00119 return atof(var->string);
00120 }
00121
00122
00128 qboolean Cvar_SetCheckFunction (const char *varName, qboolean (*check) (cvar_t* cvar))
00129 {
00130 cvar_t *var;
00131
00132 var = Cvar_FindVar(varName);
00133 if (!var) {
00134 Com_Printf("Could not set check function for cvar '%s'\n", varName);
00135 return qfalse;
00136 }
00137 var->check = check;
00138
00139 var->check(var);
00140 return qtrue;
00141 }
00142
00152 qboolean Cvar_AssertValue (cvar_t * cvar, float minVal, float maxVal, qboolean shouldBeIntegral)
00153 {
00154 assert(cvar);
00155
00156 if (shouldBeIntegral) {
00157 if ((int)cvar->value != cvar->integer) {
00158 Com_Printf("WARNING: cvar '%s' must be integral (%f)\n", cvar->name, cvar->value);
00159 Cvar_Set(cvar->name, va("%d", cvar->integer));
00160 return qtrue;
00161 }
00162 }
00163
00164 if (cvar->value < minVal) {
00165 Com_Printf("WARNING: cvar '%s' out of range (%f < %f)\n", cvar->name, cvar->value, minVal);
00166 Cvar_SetValue(cvar->name, minVal);
00167 return qtrue;
00168 } else if (cvar->value > maxVal) {
00169 Com_Printf("WARNING: cvar '%s' out of range (%f > %f)\n", cvar->name, cvar->value, maxVal);
00170 Cvar_SetValue(cvar->name, maxVal);
00171 return qtrue;
00172 }
00173
00174
00175 return qfalse;
00176 }
00177
00186 qboolean Cvar_AssertString (cvar_t * cvar, char **array, int arraySize)
00187 {
00188 int i;
00189 char *string;
00190
00191 assert(cvar);
00192
00193 for (i = 0; i < arraySize; i++) {
00194 string = array[i];
00195 if (strncmp(cvar->string, string, sizeof(cvar->string))) {
00196
00197 return qfalse;
00198 }
00199 }
00200
00201 Com_Printf("Cvar '%s' has not a valid value\n", cvar->name);
00202
00203 if (cvar->oldString)
00204 Cvar_Set(cvar->name, cvar->oldString);
00205
00206
00207 return qtrue;
00208 }
00209
00217 int Cvar_GetInteger (const char *varName)
00218 {
00219 const cvar_t *var;
00220
00221 var = Cvar_FindVar(varName);
00222 if (!var)
00223 return 0;
00224 return var->integer;
00225 }
00226
00235 const char *Cvar_GetString (const char *varName)
00236 {
00237 const cvar_t *var;
00238
00239 var = Cvar_FindVar(varName);
00240 if (!var)
00241 return "";
00242 return var->string;
00243 }
00244
00253 const char *Cvar_VariableStringOld (const char *varName)
00254 {
00255 cvar_t *var;
00256
00257 var = Cvar_FindVar(varName);
00258 if (!var)
00259 return "";
00260 if (var->oldString)
00261 return var->oldString;
00262 else
00263 return "";
00264 }
00265
00273 int Cvar_CompleteVariable (const char *partial, const char **match)
00274 {
00275 int matches = 0;
00276 const char *localMatch[MAX_COMPLETE];
00277 cvar_t* cvar;
00278 size_t len;
00279
00280 len = strlen(partial);
00281 if (!len)
00282 return 0;
00283
00284 localMatch[matches] = NULL;
00285
00286
00287 for (cvar = cvarVars; cvar; cvar = cvar->next)
00288 if (!strncmp(partial, cvar->name, len)) {
00289 #ifndef DEBUG
00290 if (cvar->flags & CVAR_DEVELOPER)
00291 continue;
00292 #endif
00293 Com_Printf("[var] %-20s = \"%s\"\n", cvar->name, cvar->string);
00294 if (cvar->description)
00295 Com_Printf(COLORED_GREEN " %s\n", cvar->description);
00296 localMatch[matches++] = cvar->name;
00297 if (matches >= MAX_COMPLETE)
00298 break;
00299 }
00300
00301 return Cmd_GenericCompleteFunction(len, match, matches, localMatch);
00302 }
00303
00307 qboolean Cvar_Delete (const char *varName)
00308 {
00309 unsigned hash;
00310 cvar_t *var, *previousVar = NULL;
00311
00312 hash = Com_HashKey(varName, CVAR_HASH_SIZE);
00313 for (var = cvarVarsHash[hash]; var; var = var->hash_next) {
00314 if (!Q_strcasecmp(varName, var->name)) {
00315 cvarChangeListener_t *changeListener;
00316 if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO | CVAR_NOSET | CVAR_LATCH)) {
00317 Com_Printf("Can't delete the cvar '%s' - it's a special cvar\n", varName);
00318 return qfalse;
00319 }
00320 if (var->prev) {
00321 assert(var->prev->next == var);
00322 var->prev->next = var->next;
00323 } else
00324 cvarVars = var->next;
00325 if (var->next) {
00326 assert(var->next->prev == var);
00327 var->next->prev = var->prev;
00328 }
00329 if (previousVar) {
00330 assert(previousVar->hash_next == var);
00331 previousVar->hash_next = var->hash_next;
00332 } else {
00333 cvarVarsHash[hash] = var->hash_next;
00334 }
00335 Mem_Free(var->name);
00336 Mem_Free(var->string);
00337 if (var->description)
00338 Mem_Free(var->description);
00339 if (var->oldString)
00340 Mem_Free(var->oldString);
00341 if (var->defaultString)
00342 Mem_Free(var->defaultString);
00343
00344 assert(var->latchedString == NULL);
00345 changeListener = var->changeListener;
00346 while (changeListener) {
00347 cvarChangeListener_t *changeListener2 = changeListener->next;
00348 Mem_Free(changeListener);
00349 changeListener = changeListener2;
00350 }
00351 Mem_Free(var);
00352
00353 return qtrue;
00354 }
00355 previousVar = var;
00356 }
00357 Com_Printf("Cvar '%s' wasn't found\n", varName);
00358 return qfalse;
00359 }
00360
00377 cvar_t *Cvar_Get (const char *var_name, const char *var_value, int flags, const char* desc)
00378 {
00379 cvar_t *var;
00380 const unsigned hash = Com_HashKey(var_name, CVAR_HASH_SIZE);
00381
00382 if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
00383 if (!Cvar_InfoValidate(var_name)) {
00384 Com_Printf("invalid info cvar name\n");
00385 return NULL;
00386 }
00387
00388 var = Cvar_FindVar(var_name);
00389 if (var) {
00390 if (!var->defaultString && flags & CVAR_CHEAT)
00391 var->defaultString = Mem_PoolStrDup(var_value, com_cvarSysPool, 0);
00392 var->flags |= flags;
00393 if (desc) {
00394 if (var->description)
00395 Mem_Free(var->description);
00396 var->description = Mem_PoolStrDup(desc, com_cvarSysPool, 0);
00397 }
00398 return var;
00399 }
00400
00401 if (!var_value)
00402 return NULL;
00403
00404 if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
00405 if (!Cvar_InfoValidate(var_value)) {
00406 Com_Printf("invalid info cvar value '%s' of cvar '%s'\n", var_value, var_name);
00407 return NULL;
00408 }
00409
00410 var = Mem_PoolAlloc(sizeof(*var), com_cvarSysPool, 0);
00411 var->name = Mem_PoolStrDup(var_name, com_cvarSysPool, 0);
00412 var->string = Mem_PoolStrDup(var_value, com_cvarSysPool, 0);
00413 var->oldString = NULL;
00414 var->modified = qtrue;
00415 var->value = atof(var->string);
00416 var->integer = atoi(var->string);
00417 if (desc)
00418 var->description = Mem_PoolStrDup(desc, com_cvarSysPool, 0);
00419
00420 HASH_Add(cvarVarsHash, var, hash);
00421
00422 var->next = cvarVars;
00423 cvarVars = var;
00424 if (var->next)
00425 var->next->prev = var;
00426
00427 var->flags = flags;
00428 if (var->flags & CVAR_CHEAT)
00429 var->defaultString = Mem_PoolStrDup(var_value, com_cvarSysPool, 0);
00430
00431 return var;
00432 }
00433
00438 static void Cvar_ExecuteChangeListener (const cvar_t* cvar)
00439 {
00440 const cvarChangeListener_t *listener = cvar->changeListener;
00441 while (listener) {
00442 listener->exec(cvar->name, cvar->oldString, cvar->string);
00443 listener = listener->next;
00444 }
00445 }
00446
00447 static cvarChangeListener_t *Cvar_GetChangeListener (cvarChangeListenerFunc_t listenerFunc)
00448 {
00449 cvarChangeListener_t *listener = Mem_PoolAlloc(sizeof(*listener), com_cvarSysPool, 0);
00450 listener->exec = listenerFunc;
00451 return listener;
00452 }
00453
00460 void Cvar_RegisterChangeListener (const char *varName, cvarChangeListenerFunc_t listenerFunc)
00461 {
00462 cvarChangeListener_t *listener;
00463 cvar_t *var = Cvar_FindVar(varName);
00464 if (!var) {
00465 Com_Printf("Could not register change listener, cvar '%s' wasn't found\n", varName);
00466 return;
00467 }
00468
00469 listener = Cvar_GetChangeListener(listenerFunc);
00470 if (!var->changeListener) {
00471 var->changeListener = listener;
00472 } else {
00473 cvarChangeListener_t *l = var->changeListener;
00474 while (l) {
00475 if (l->exec == listenerFunc) {
00476 Com_Printf("Cvar change listener already registered\n");
00477 return;
00478 }
00479 l = l->next;
00480 }
00481
00482 l = var->changeListener;
00483 while (l) {
00484 if (!l->next) {
00485 l->next = listener;
00486 l->next->next = NULL;
00487 break;
00488 }
00489 l = l->next;
00490 }
00491 }
00492 }
00493
00499 void Cvar_UnRegisterChangeListener (const char *varName, cvarChangeListenerFunc_t listenerFunc)
00500 {
00501 cvar_t *var = Cvar_FindVar(varName);
00502 cvarChangeListener_t *l, *prev;
00503
00504 if (!var) {
00505 Com_Printf("Could not unregister change listener, cvar '%s' wasn't found\n", varName);
00506 return;
00507 }
00508
00509 l = var->changeListener;
00510 prev = NULL;
00511 while (l) {
00512 if (l->exec == listenerFunc) {
00513 if (prev) {
00514 prev->next = l->next;
00515 } else {
00516 var->changeListener = l->next;
00517 }
00518 Mem_Free(l);
00519 return;
00520 }
00521 prev = l;
00522 l = l->next;
00523 }
00524 }
00525
00533 static cvar_t *Cvar_Set2 (const char *varName, const char *value, qboolean force)
00534 {
00535 cvar_t *var;
00536
00537 if (!value)
00538 return NULL;
00539
00540 var = Cvar_FindVar(varName);
00541
00542 if (!var)
00543 return Cvar_Get(varName, value, 0, NULL);
00544
00545 if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO))
00546 if (!Cvar_InfoValidate(value)) {
00547 Com_Printf("invalid info cvar value '%s' of cvar '%s'\n", value, varName);
00548 return var;
00549 }
00550
00551 if (!force) {
00552 if (var->flags & CVAR_NOSET) {
00553 Com_Printf("%s is write protected.\n", varName);
00554 return var;
00555 }
00556 #ifndef DEBUG
00557 if (var->flags & CVAR_DEVELOPER) {
00558 Com_Printf("%s is a developer cvar.\n", varName);
00559 return var;
00560 }
00561 #endif
00562
00563 if (var->flags & CVAR_LATCH) {
00564 if (var->latchedString) {
00565 if (!strcmp(value, var->latchedString))
00566 return var;
00567 Mem_Free(var->latchedString);
00568 var->latchedString = NULL;
00569 } else {
00570 if (!strcmp(value, var->string))
00571 return var;
00572 }
00573
00574
00575 if (Com_ServerState()) {
00576 Com_Printf("%s will be changed for next game.\n", varName);
00577 var->latchedString = Mem_PoolStrDup(value, com_cvarSysPool, 0);
00578 } else {
00579 if (var->oldString)
00580 Mem_Free(var->oldString);
00581 var->oldString = var->string;
00582 var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0);
00583 var->value = atof(var->string);
00584 var->integer = atoi(var->string);
00585 }
00586
00587 if (var->check)
00588 if (var->check(var))
00589 Com_Printf("Invalid value for cvar %s\n", varName);
00590
00591 return var;
00592 }
00593 } else {
00594 if (var->latchedString) {
00595 Mem_Free(var->latchedString);
00596 var->latchedString = NULL;
00597 }
00598 }
00599
00600 if (!strcmp(value, var->string))
00601 return var;
00602
00603 if (var->flags & CVAR_R_MASK)
00604 Com_SetRenderModified(qtrue);
00605
00606 if (var->oldString)
00607 Mem_Free(var->oldString);
00608 var->oldString = var->string;
00609 var->modified = qtrue;
00610
00611 if (var->flags & CVAR_USERINFO)
00612 Com_SetUserinfoModified(qtrue);
00613
00614 var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0);
00615 var->value = atof(var->string);
00616 var->integer = atoi(var->string);
00617
00618 if (var->check)
00619 if (var->check(var)) {
00620 Com_Printf("Invalid value for cvar %s\n", varName);
00621 return var;
00622 }
00623
00624 Cvar_ExecuteChangeListener(var);
00625
00626 return var;
00627 }
00628
00632 cvar_t *Cvar_ForceSet (const char *varName, const char *value)
00633 {
00634 return Cvar_Set2(varName, value, qtrue);
00635 }
00636
00643 cvar_t *Cvar_Set (const char *varName, const char *value)
00644 {
00645 return Cvar_Set2(varName, value, qfalse);
00646 }
00647
00662 cvar_t *Cvar_FullSet (const char *varName, const char *value, int flags)
00663 {
00664 cvar_t *var;
00665
00666 if (!value)
00667 return NULL;
00668
00669 var = Cvar_FindVar(varName);
00670
00671 if (!var)
00672 return Cvar_Get(varName, value, flags, NULL);
00673
00674 var->modified = qtrue;
00675
00676
00677 if (var->flags & CVAR_USERINFO)
00678 Com_SetUserinfoModified(qtrue);
00679
00680 if (var->oldString)
00681 Mem_Free(var->oldString);
00682 var->oldString = var->string;
00683
00684 var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0);
00685 var->value = atof(var->string);
00686 var->integer = atoi(var->string);
00687 var->flags = flags;
00688
00689 return var;
00690 }
00691
00696 void Cvar_SetValue (const char *varName, float value)
00697 {
00698 char val[32];
00699
00700 if (value == (int) value)
00701 Com_sprintf(val, sizeof(val), "%i", (int) value);
00702 else
00703 Com_sprintf(val, sizeof(val), "%1.2f", value);
00704 Cvar_Set(varName, val);
00705 }
00706
00707
00712 void Cvar_UpdateLatchedVars (void)
00713 {
00714 cvar_t *var;
00715
00716 for (var = cvarVars; var; var = var->next) {
00717 if (!var->latchedString)
00718 continue;
00719 var->oldString = var->string;
00720 var->string = var->latchedString;
00721 var->latchedString = NULL;
00722 var->value = atof(var->string);
00723 var->integer = atoi(var->string);
00724 }
00725 }
00726
00739 qboolean Cvar_Command (void)
00740 {
00741 cvar_t *v;
00742
00743
00744 v = Cvar_FindVar(Cmd_Argv(0));
00745 if (!v)
00746 return qfalse;
00747
00748
00749 if (Cmd_Argc() == 1) {
00750 Com_Printf("\"%s\" is \"%s\"\n", v->name, v->string);
00751 return qtrue;
00752 }
00753
00754 Cvar_Set(v->name, Cmd_Argv(1));
00755 return qtrue;
00756 }
00757
00761 static void Cvar_SetOld_f (void)
00762 {
00763 cvar_t *v;
00764
00765 if (Cmd_Argc() != 2) {
00766 Com_Printf("Usage: %s <variable>\n", Cmd_Argv(0));
00767 return;
00768 }
00769
00770
00771 v = Cvar_FindVar(Cmd_Argv(1));
00772 if (!v) {
00773 Com_Printf("cvar '%s' not found\n", Cmd_Argv(1));
00774 return;
00775 }
00776 if (v->oldString)
00777 Cvar_Set(Cmd_Argv(1), v->oldString);
00778 }
00779
00780 static void Cvar_Define_f (void)
00781 {
00782 const char *name;
00783
00784 if (Cmd_Argc() < 2) {
00785 Com_Printf("Usage: %s <cvarname> <value>\n", Cmd_Argv(0));
00786 return;
00787 }
00788
00789 name = Cmd_Argv(1);
00790
00791 if (Cvar_FindVar(name) == NULL)
00792 Cvar_Set(name, Cmd_Argc() == 3 ? Cmd_Argv(2) : "");
00793 }
00794
00798 static void Cvar_Set_f (void)
00799 {
00800 const int c = Cmd_Argc();
00801 if (c != 3 && c != 4) {
00802 Com_Printf("Usage: %s <variable> <value> [u / s]\n", Cmd_Argv(0));
00803 return;
00804 }
00805
00806 if (c == 4) {
00807 const char *arg = Cmd_Argv(3);
00808 int flags = 0;
00809
00810 while (arg[0] != '\0') {
00811 switch (arg[0]) {
00812 case 'u':
00813 flags |= CVAR_USERINFO;
00814 break;
00815 case 's':
00816 flags |= CVAR_SERVERINFO;
00817 break;
00818 case 'a':
00819 flags |= CVAR_ARCHIVE;
00820 break;
00821 default:
00822 Com_Printf("invalid flags %c given\n", arg[0]);
00823 }
00824 arg++;
00825 }
00826 Cvar_FullSet(Cmd_Argv(1), Cmd_Argv(2), flags);
00827 } else
00828 Cvar_Set(Cmd_Argv(1), Cmd_Argv(2));
00829 }
00830
00831
00836 static void Cvar_Copy_f (void)
00837 {
00838 int c;
00839
00840 c = Cmd_Argc();
00841 if (c < 3) {
00842 Com_Printf("Usage: %s <target> <source>\n", Cmd_Argv(0));
00843 return;
00844 }
00845
00846 Cvar_Set(Cmd_Argv(1), Cvar_GetString(Cmd_Argv(2)));
00847 }
00848
00849
00855 void Cvar_WriteVariables (qFILE *f)
00856 {
00857 const cvar_t *var;
00858
00859 for (var = cvarVars; var; var = var->next)
00860 if (var->flags & CVAR_ARCHIVE)
00861 FS_Printf(f, "set %s \"%s\" a\n", var->name, var->string);
00862 }
00863
00869 qboolean Cvar_PendingCvars (int flags)
00870 {
00871 const cvar_t *var;
00872
00873 for (var = cvarVars; var; var = var->next)
00874 if ((var->flags & flags) && var->modified)
00875 return qtrue;
00876
00877 return qfalse;
00878 }
00879
00880 void Cvar_ClearVars (int flags)
00881 {
00882 cvar_t *var;
00883
00884 for (var = cvarVars; var; var = var->next)
00885 if ((var->flags & flags) && var->modified)
00886 var->modified = qfalse;
00887 }
00888
00892 static void Cvar_List_f (void)
00893 {
00894 cvar_t *var;
00895 int i, c, l = 0;
00896 const char *token = NULL;
00897
00898 c = Cmd_Argc();
00899
00900 if (c == 2) {
00901 token = Cmd_Argv(1);
00902 l = strlen(token);
00903 }
00904
00905 i = 0;
00906 for (var = cvarVars; var; var = var->next, i++) {
00907 if (c == 2 && strncmp(var->name, token, l)) {
00908 i--;
00909 continue;
00910 }
00911 #ifndef DEBUG
00912
00913 if (var->flags & CVAR_DEVELOPER)
00914 continue;
00915 #endif
00916
00917 if (var->flags & CVAR_ARCHIVE)
00918 Com_Printf("A");
00919 else
00920 Com_Printf(" ");
00921 if (var->flags & CVAR_USERINFO)
00922 Com_Printf("U");
00923 else
00924 Com_Printf(" ");
00925 if (var->flags & CVAR_SERVERINFO)
00926 Com_Printf("S");
00927 else
00928 Com_Printf(" ");
00929 if (var->modified)
00930 Com_Printf("M");
00931 else
00932 Com_Printf(" ");
00933 if (var->flags & CVAR_DEVELOPER)
00934 Com_Printf("D");
00935 else
00936 Com_Printf(" ");
00937 if (var->flags & CVAR_R_IMAGES)
00938 Com_Printf("I");
00939 else
00940 Com_Printf(" ");
00941 if (var->flags & CVAR_NOSET)
00942 Com_Printf("-");
00943 else if (var->flags & CVAR_LATCH)
00944 Com_Printf("L");
00945 else
00946 Com_Printf(" ");
00947 Com_Printf(" %-20s \"%s\"\n", var->name, var->string);
00948 if (var->description)
00949 Com_Printf(COLORED_GREEN " %s\n", var->description);
00950 }
00951 Com_Printf("%i cvars\n", i);
00952 Com_Printf("legend:\n"
00953 "S: Serverinfo\n"
00954 "L: Latched\n"
00955 "D: Developer\n"
00956 "U: Userinfo\n"
00957 "I: Image\n"
00958 "*: Archive\n"
00959 "-: Not changeable\n"
00960 );
00961 }
00962
00967 static char *Cvar_BitInfo (int bit)
00968 {
00969 static char info[MAX_INFO_STRING];
00970 cvar_t *var;
00971
00972 info[0] = 0;
00973
00974 for (var = cvarVars; var; var = var->next)
00975 if (var->flags & bit)
00976 Info_SetValueForKey(info, sizeof(info), var->name, var->string);
00977 return info;
00978 }
00979
00983 const char *Cvar_Userinfo (void)
00984 {
00985 return Cvar_BitInfo(CVAR_USERINFO);
00986 }
00987
00992 const char *Cvar_Serverinfo (void)
00993 {
00994 return Cvar_BitInfo(CVAR_SERVERINFO);
00995 }
00996
01001 static void Cvar_Del_f (void)
01002 {
01003 int c;
01004
01005 c = Cmd_Argc();
01006 if (c != 2) {
01007 Com_Printf("Usage: %s <variable>\n", Cmd_Argv(0));
01008 return;
01009 }
01010
01011 Cvar_Delete(Cmd_Argv(1));
01012 }
01013
01017 static void Cvar_Add_f (void)
01018 {
01019 cvar_t *cvar;
01020 float value;
01021 if (Cmd_Argc() != 3) {
01022 Com_Printf("Usage: %s <variable> <value>\n", Cmd_Argv(0));
01023 return;
01024 }
01025
01026 cvar = Cvar_FindVar(Cmd_Argv(1));
01027 if (!cvar) {
01028 Com_Printf("Cvar_Add_f: %s not exists\n", Cmd_Argv(1));
01029 return;
01030 }
01031
01032 value = cvar->value + atof(Cmd_Argv(2));
01033 Cvar_SetValue(Cmd_Argv(1), value);
01034 }
01035
01039 static void Cvar_Mod_f (void)
01040 {
01041 cvar_t *cvar;
01042 int value;
01043 if (Cmd_Argc() != 3) {
01044 Com_Printf("Usage: %s <variable> <value>\n", Cmd_Argv(0));
01045 return;
01046 }
01047
01048 cvar = Cvar_FindVar(Cmd_Argv(1));
01049 if (!cvar) {
01050 Com_Printf("Cvar_Mod_f: %s not exists\n", Cmd_Argv(1));
01051 return;
01052 }
01053
01054 value = cvar->integer % atoi(Cmd_Argv(2));
01055 Cvar_SetValue(Cmd_Argv(1), value);
01056 }
01057
01062 void Cvar_FixCheatVars (void)
01063 {
01064 cvar_t *var;
01065
01066 if (!(Com_ServerState() && !Cvar_GetInteger("sv_cheats")))
01067 return;
01068
01069 for (var = cvarVars; var; var = var->next) {
01070 if (!(var->flags & CVAR_CHEAT))
01071 continue;
01072
01073 if (!var->defaultString) {
01074 Com_Printf("Cheat cvars: Cvar %s has no default value\n", var->name);
01075 continue;
01076 }
01077
01078 if (!strcmp(var->string, var->defaultString))
01079 continue;
01080
01081
01082 if (var->oldString) {
01083 Mem_Free(var->oldString);
01084 var->oldString = NULL;
01085 }
01086 Mem_Free(var->string);
01087 var->string = Mem_PoolStrDup(var->defaultString, com_cvarSysPool, 0);
01088 var->value = atof(var->string);
01089 var->integer = atoi(var->string);
01090
01091 Com_Printf("'%s' is a cheat cvar - activate sv_cheats to use it.\n", var->name);
01092 }
01093 }
01094
01095 #ifdef DEBUG
01096 void Cvar_PrintDebugCvars (void)
01097 {
01098 const cvar_t *var;
01099
01100 Com_Printf("Debug cvars:\n");
01101 for (var = cvarVars; var; var = var->next) {
01102 if ((var->flags & CVAR_DEVELOPER) || !strncmp(var->name, "debug_", 6))
01103 Com_Printf(" * %s (%s)\n %s\n", var->name, var->string, var->description ? var->description : "");
01104 }
01105 Com_Printf("\n");
01106 }
01107 #endif
01108
01113 void Cvar_Init (void)
01114 {
01115 Cmd_AddCommand("setold", Cvar_SetOld_f, "Restore the cvar old value");
01116 Cmd_AddCommand("del", Cvar_Del_f, "Delete a cvar");
01117 Cmd_AddCommand("set", Cvar_Set_f, "Set a cvar value");
01118 Cmd_AddCommand("add", Cvar_Add_f, "Add a value to a cvar");
01119 Cmd_AddCommand("define", Cvar_Define_f, "Defines a cvar if it does not exist");
01120 Cmd_AddCommand("mod", Cvar_Mod_f, "Apply a modulo on a cvar");
01121 Cmd_AddCommand("copy", Cvar_Copy_f, "Copy cvar target to source");
01122 Cmd_AddCommand("cvarlist", Cvar_List_f, "Show all cvars");
01123 }
01124
01125 void Cvar_Shutdown (void)
01126 {
01127 cvarVars = NULL;
01128 memset(cvarVarsHash, 0, sizeof(cvarVarsHash));
01129 }