UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cvar.cpp
Go to the documentation of this file.
1 
11 /*
12 Copyright (C) 1997-2001 Id Software, Inc.
13 
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License
16 as published by the Free Software Foundation; either version 2
17 of the License, or (at your option) any later version.
18 
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 
23 See the GNU General Public License for more details.
24 
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 
29 */
30 
31 #include "common.h"
32 #include "../shared/infostring.h"
33 #include <vector>
34 
35 #define CVAR_HASH_SIZE 64
36 
38 
39 // @todo This uses the STL, however, in a recent discussion on the forum it was stated that there
40 // should be no use of STL due to memory issues, so this needs to change
41 typedef std::vector<CvarListenerPtr> CvarListeners;
43 
48 static bool renderModified;
49 
54 static bool userinfoModified;
55 
56 void Com_SetUserinfoModified (bool modified)
57 {
58  userinfoModified = modified;
59 }
60 
62 {
63  return userinfoModified;
64 }
65 
66 void Com_SetRenderModified (bool modified)
67 {
68  renderModified = modified;
69 }
70 
72 {
73  return renderModified;
74 }
75 
79 static cvar_t* cvarVars;
80 
82 {
83  return cvarVars;
84 }
85 
86 
94 static bool Cvar_InfoValidate (const char* s)
95 {
96  return s[strcspn(s, "\\\";")] == '\0';
97 }
98 
106 cvar_t* Cvar_FindVar (const char* varName)
107 {
108  const unsigned hash = Com_HashKey(varName, CVAR_HASH_SIZE);
109 
110  for (cvar_t* var = cvarVarsHash[hash]; var; var = var->hash_next) {
111  if (Q_streq(varName, var->name))
112  return var;
113  }
114 
115  return nullptr;
116 }
117 
125 float Cvar_GetValue (const char* varName)
126 {
127  const cvar_t* var = Cvar_FindVar(varName);
128  if (!var)
129  return 0.0f;
130  return atof(var->string);
131 }
132 
133 
139 bool Cvar_SetCheckFunction (const char* varName, bool (*check) (cvar_t* cvar))
140 {
141  cvar_t* var = Cvar_FindVar(varName);
142  if (!var) {
143  Com_Printf("Could not set check function for cvar '%s'\n", varName);
144  return false;
145  }
146  var->check = check;
147  /* execute the check */
148  var->check(var);
149  return true;
150 }
151 
161 bool Cvar_AssertValue (cvar_t* cvar, float minVal, float maxVal, bool shouldBeIntegral)
162 {
163  assert(cvar);
164 
165  if (shouldBeIntegral) {
166  if ((int)cvar->value != cvar->integer) {
167  Com_Printf("WARNING: cvar '%s' must be integral (%f)\n", cvar->name, cvar->value);
168  Cvar_Set(cvar->name, "%d", cvar->integer);
169  return true;
170  }
171  }
172 
173  if (cvar->value < minVal) {
174  Com_Printf("WARNING: cvar '%s' out of range (%f < %f)\n", cvar->name, cvar->value, minVal);
175  Cvar_SetValue(cvar->name, minVal);
176  return true;
177  } else if (cvar->value > maxVal) {
178  Com_Printf("WARNING: cvar '%s' out of range (%f > %f)\n", cvar->name, cvar->value, maxVal);
179  Cvar_SetValue(cvar->name, maxVal);
180  return true;
181  }
182 
183  /* no changes */
184  return false;
185 }
186 
194 int Cvar_GetInteger (const char* varName)
195 {
196  const cvar_t* var = Cvar_FindVar(varName);
197  if (!var)
198  return 0;
199  return var->integer;
200 }
201 
210 const char* Cvar_GetString (const char* varName)
211 {
212  const cvar_t* var = Cvar_FindVar(varName);
213  if (!var)
214  return "";
215  return var->string;
216 }
217 
226 const char* Cvar_VariableStringOld (const char* varName)
227 {
228  const cvar_t* var = Cvar_FindVar(varName);
229  if (!var)
230  return "";
231  if (var->oldString)
232  return var->oldString;
233  else
234  return "";
235 }
236 
241 void Cvar_Reset (cvar_t* cvar)
242 {
243  if (cvar->oldString == nullptr)
244  return;
245 
246  char* str = Mem_StrDup(cvar->oldString);
247  Cvar_Set(cvar->name, "%s", str);
248  Mem_Free(str);
249 }
250 
258 int Cvar_CompleteVariable (const char* partial, const char** match)
259 {
260  int n = 0;
261  for (cvar_t const* cvar = cvarVars; cvar; cvar = cvar->next) {
262 #ifndef DEBUG
263  if (cvar->flags & CVAR_DEVELOPER)
264  continue;
265 #endif
266  if (Cmd_GenericCompleteFunction(cvar->name, partial, match)) {
267  Com_Printf("[var] %-20s = \"%s\"\n", cvar->name, cvar->string);
268  if (cvar->description)
269  Com_Printf(S_COLOR_GREEN " %s\n", cvar->description);
270  ++n;
271  }
272  }
273  return n;
274 }
275 
279 bool Cvar_Delete (const char* varName)
280 {
281  const unsigned hash = Com_HashKey(varName, CVAR_HASH_SIZE);
282  for (cvar_t** anchor = &cvarVarsHash[hash]; *anchor; anchor = &(*anchor)->hash_next) {
283  cvar_t* const var = *anchor;
284  if (!Q_strcasecmp(varName, var->name)) {
285  if (var->flags != 0) {
286  Com_Printf("Can't delete the cvar '%s' - it's a special cvar\n", varName);
287  return false;
288  }
289  HASH_Delete(anchor);
290  if (var->prev) {
291  assert(var->prev->next == var);
292  var->prev->next = var->next;
293  } else
294  cvarVars = var->next;
295  if (var->next) {
296  assert(var->next->prev == var);
297  var->next->prev = var->prev;
298  }
299 
300  for (CvarListeners::iterator i = cvarListeners.begin(); i != cvarListeners.end(); ++i) {
301  (*i)->onDelete(var);
302  }
303 
304  Mem_Free(var->name);
305  Mem_Free(var->string);
306  Mem_Free(var->description);
307  Mem_Free(var->oldString);
308  Mem_Free(var->defaultString);
309  /* latched cvars should not be removable */
310  assert(var->latchedString == nullptr);
311  cvarChangeListener_t* changeListener = var->changeListener;
312  while (changeListener) {
313  cvarChangeListener_t* changeListener2 = changeListener->next;
314  Mem_Free(changeListener);
315  changeListener = changeListener2;
316  }
317  Mem_Free(var);
318 
319  return true;
320  }
321  }
322  Com_Printf("Cvar '%s' wasn't found\n", varName);
323  return false;
324 }
325 
342 cvar_t* Cvar_Get (const char* var_name, const char* var_value, int flags, const char* desc)
343 {
344  const unsigned hash = Com_HashKey(var_name, CVAR_HASH_SIZE);
345 
346  if (flags & (CVAR_USERINFO | CVAR_SERVERINFO)) {
347  if (!Cvar_InfoValidate(var_name)) {
348  Com_Printf("invalid info cvar name\n");
349  return nullptr;
350  }
351  }
352 
353  if (cvar_t* const var = Cvar_FindVar(var_name)) {
354  if (!var->defaultString && (flags & CVAR_CHEAT))
355  var->defaultString = Mem_PoolStrDup(var_value, com_cvarSysPool, 0);
356  var->flags |= flags;
357  if (desc) {
358  Mem_Free(var->description);
359  var->description = Mem_PoolStrDup(desc, com_cvarSysPool, 0);
360  }
361  return var;
362  }
363 
364  if (!var_value)
365  return nullptr;
366 
367  if (flags & (CVAR_USERINFO | CVAR_SERVERINFO)) {
368  if (!Cvar_InfoValidate(var_value)) {
369  Com_Printf("invalid info cvar value '%s' of cvar '%s'\n", var_value, var_name);
370  return nullptr;
371  }
372  }
373 
375  var->name = Mem_PoolStrDup(var_name, com_cvarSysPool, 0);
376  var->string = Mem_PoolStrDup(var_value, com_cvarSysPool, 0);
377  var->oldString = nullptr;
378  var->modified = true;
379  var->value = atof(var->string);
380  var->integer = atoi(var->string);
381  if (desc)
382  var->description = Mem_PoolStrDup(desc, com_cvarSysPool, 0);
383 
384  HASH_Add(cvarVarsHash, var, hash);
385  /* link the variable in */
386  var->next = cvarVars;
387  cvarVars = var;
388  if (var->next)
389  var->next->prev = var;
390 
391  var->flags = flags;
392  if (var->flags & CVAR_CHEAT)
393  var->defaultString = Mem_PoolStrDup(var_value, com_cvarSysPool, 0);
394 
395  for (CvarListeners::iterator i = cvarListeners.begin(); i != cvarListeners.end(); ++i) {
396  (*i)->onCreate(var);
397  }
398 
399  return var;
400 }
401 
407 {
408  cvarListeners.push_back(listener);
409 }
410 
416 {
417  cvarListeners.erase(std::remove(cvarListeners.begin(), cvarListeners.end(), listener), cvarListeners.end());
418 }
419 
424 static void Cvar_ExecuteChangeListener (const cvar_t* cvar)
425 {
426  const cvarChangeListener_t* listener = cvar->changeListener;
427  while (listener) {
428  listener->exec(cvar->name, cvar->oldString, cvar->string, listener->data);
429  listener = listener->next;
430  }
431 }
432 
434 {
436  listener->exec = listenerFunc;
437  return listener;
438 }
439 
447 {
448  cvar_t* var = Cvar_FindVar(varName);
449  if (!var) {
450  Com_Printf("Could not register change listener, cvar '%s' wasn't found\n", varName);
451  return nullptr;
452  }
453 
454  if (!var->changeListener) {
455  cvarChangeListener_t* l = Cvar_GetChangeListener(listenerFunc);
456  var->changeListener = l;
457  return l;
458  } else {
460  while (l) {
461  if (l->exec == listenerFunc) {
462  return l;
463  }
464  l = l->next;
465  }
466 
467  l = var->changeListener;
468  while (l) {
469  if (!l->next) {
470  cvarChangeListener_t* listener = Cvar_GetChangeListener(listenerFunc);
471  l->next = listener;
472  l->next->next = nullptr;
473  return listener;
474  }
475  l = l->next;
476  }
477  }
478 
479  return nullptr;
480 }
481 
487 void Cvar_UnRegisterChangeListener (const char* varName, cvarChangeListenerFunc_t listenerFunc)
488 {
489  cvar_t* var = Cvar_FindVar(varName);
490  if (!var) {
491  Com_Printf("Could not unregister change listener, cvar '%s' wasn't found\n", varName);
492  return;
493  }
494 
495  for (cvarChangeListener_t** anchor = &var->changeListener; *anchor; anchor = &(*anchor)->next) {
496  cvarChangeListener_t* const l = *anchor;
497  if (l->exec == listenerFunc) {
498  *anchor = l->next;
499  Mem_Free(l);
500  return;
501  }
502  }
503 }
504 
512 static cvar_t* Cvar_Set2 (const char* varName, const char* value, bool force)
513 {
514  if (!value)
515  return nullptr;
516 
517  cvar_t* var = Cvar_FindVar(varName);
518  /* create it */
519  if (!var)
520  return Cvar_Get(varName, value);
521 
522  if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO)) {
523  if (!Cvar_InfoValidate(value)) {
524  Com_Printf("invalid info cvar value '%s' of cvar '%s'\n", value, varName);
525  return var;
526  }
527  }
528 
529  if (!force) {
530  if (var->flags & CVAR_NOSET) {
531  Com_Printf("%s is write protected.\n", varName);
532  return var;
533  }
534 #ifndef DEBUG
535  if (var->flags & CVAR_DEVELOPER) {
536  Com_Printf("%s is a developer cvar.\n", varName);
537  return var;
538  }
539 #endif
540 
541  if (var->flags & CVAR_LATCH) {
542  if (var->latchedString) {
543  if (Q_streq(value, var->latchedString))
544  return var;
545  Mem_Free(var->latchedString);
546  var->latchedString = nullptr;
547  } else {
548  if (Q_streq(value, var->string))
549  return var;
550  }
551 
552  /* if we are running a server */
553  if (Com_ServerState()) {
554  Com_Printf("%s will be changed for next game.\n", varName);
555  var->latchedString = Mem_PoolStrDup(value, com_cvarSysPool, 0);
556  } else {
557  Mem_Free(var->oldString);
558  var->oldString = var->string;
559  var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0);
560  var->value = atof(var->string);
561  var->integer = atoi(var->string);
562  }
563 
564  if (var->check && var->check(var))
565  Com_Printf("Invalid value for cvar %s\n", varName);
566 
567  return var;
568  }
569  } else {
570  Mem_Free(var->latchedString);
571  var->latchedString = nullptr;
572  }
573 
574  if (Q_streq(value, var->string))
575  return var; /* not changed */
576 
577  if (var->flags & CVAR_R_MASK)
578  Com_SetRenderModified(true);
579 
580  Mem_Free(var->oldString); /* free the old value string */
581  var->oldString = var->string;
582  var->modified = true;
583 
584  if (var->flags & CVAR_USERINFO)
585  Com_SetUserinfoModified(true); /* transmit at next opportunity */
586 
587  var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0);
588  var->value = atof(var->string);
589  var->integer = atoi(var->string);
590 
591  if (var->check && var->check(var)) {
592  Com_Printf("Invalid value for cvar %s\n", varName);
593  return var;
594  }
595 
597 
598  return var;
599 }
600 
604 cvar_t* Cvar_ForceSet (const char* varName, const char* value)
605 {
606  return Cvar_Set2(varName, value, true);
607 }
608 
615 cvar_t* Cvar_Set (const char* varName, const char* value, ...)
616 {
617  va_list argptr;
618  char text[512];
619  va_start(argptr, value);
620  Q_vsnprintf(text, sizeof(text), value, argptr);
621  va_end(argptr);
622 
623  return Cvar_Set2(varName, text, false);
624 }
625 
640 cvar_t* Cvar_FullSet (const char* varName, const char* value, int flags)
641 {
642  if (!value)
643  return nullptr;
644 
645  cvar_t* var = Cvar_FindVar(varName);
646  /* create it */
647  if (!var)
648  return Cvar_Get(varName, value, flags);
649 
650  var->modified = true;
651 
652  /* transmit at next opportunity */
653  if (var->flags & CVAR_USERINFO)
655 
656  Mem_Free(var->oldString); /* free the old value string */
657  var->oldString = var->string;
658 
659  var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0);
660  var->value = atof(var->string);
661  var->integer = atoi(var->string);
662  var->flags = flags;
663 
664  return var;
665 }
666 
671 void Cvar_SetValue (const char* varName, float value)
672 {
673  if (value == (int) value)
674  Cvar_Set(varName, "%i", (int)value);
675  else
676  Cvar_Set(varName, "%1.2f", value);
677 }
678 
684 {
685  for (cvar_t* var = cvarVars; var; var = var->next) {
686  if (!var->latchedString)
687  continue;
688  var->oldString = var->string;
689  var->string = var->latchedString;
690  var->latchedString = nullptr;
691  var->value = atof(var->string);
692  var->integer = atoi(var->string);
693  }
694 }
695 
708 bool Cvar_Command (void)
709 {
710  /* check variables */
711  cvar_t* v = Cvar_FindVar(Cmd_Argv(0));
712  if (!v)
713  return false;
714 
715  /* perform a variable print or set */
716  if (Cmd_Argc() == 1) {
717  Com_Printf("\"%s\" is \"%s\"\n", v->name, v->string);
718  return true;
719  }
720 
721  Cvar_Set(v->name, "%s", Cmd_Argv(1));
722  return true;
723 }
724 
728 static void Cvar_SetOld_f (void)
729 {
730  if (Cmd_Argc() != 2) {
731  Com_Printf("Usage: %s <variable>\n", Cmd_Argv(0));
732  return;
733  }
734 
735  /* check variables */
736  cvar_t* v = Cvar_FindVar(Cmd_Argv(1));
737  if (!v) {
738  Com_Printf("cvar '%s' not found\n", Cmd_Argv(1));
739  return;
740  }
741  if (v->oldString)
742  Cvar_Set(Cmd_Argv(1), "%s", v->oldString);
743 }
744 
745 static void Cvar_Define_f (void)
746 {
747  if (Cmd_Argc() < 2) {
748  Com_Printf("Usage: %s <cvarname> <value>\n", Cmd_Argv(0));
749  return;
750  }
751 
752  const char* name = Cmd_Argv(1);
753 
754  if (Cvar_FindVar(name) == nullptr)
755  Cvar_Set(name, "%s", Cmd_Argc() == 3 ? Cmd_Argv(2) : "");
756 }
757 
761 static void Cvar_Set_f (void)
762 {
763  const int c = Cmd_Argc();
764  if (c != 3 && c != 4) {
765  Com_Printf("Usage: %s <variable> <value> [u / s / a]\n", Cmd_Argv(0));
766  return;
767  }
768 
769  if (c == 4) {
770  const cvar_t* const var = Cvar_FindVar(Cmd_Argv(1));
771  if (var && (var->flags & (CVAR_NOSET | CVAR_LATCH))) {
772  Com_Printf("Can't set %s: is a special cvar\n", Cmd_Argv(1));
773  return;
774  }
775 
776  const char* arg = Cmd_Argv(3);
777  int flags = 0;
778 
779  while (arg[0] != '\0') {
780  switch (arg[0]) {
781  case 'u':
782  flags |= CVAR_USERINFO;
783  break;
784  case 's':
785  flags |= CVAR_SERVERINFO;
786  break;
787  case 'a':
788  flags |= CVAR_ARCHIVE;
789  break;
790  default:
791  Com_Printf("Invalid flags %c given\n", arg[0]);
792  break;
793  }
794  arg++;
795  }
796  Cvar_FullSet(Cmd_Argv(1), Cmd_Argv(2), flags);
797  } else {
798  Cvar_Set(Cmd_Argv(1), "%s", Cmd_Argv(2));
799  }
800 }
801 
805 static void Cvar_Switch_f (void)
806 {
807  const int c = Cmd_Argc();
808  if (c != 2 && c != 3) {
809  Com_Printf("Usage: %s <variable> [u / s / a]\n", Cmd_Argv(0));
810  return;
811  }
812 
813  if (c == 3) {
814  const cvar_t* const var = Cvar_FindVar(Cmd_Argv(1));
815  if (var && (var->flags & (CVAR_NOSET | CVAR_LATCH))) {
816  Com_Printf("Can't switch %s: is a special cvar\n", Cmd_Argv(1));
817  return;
818  }
819 
820  const char* arg = Cmd_Argv(2);
821  int flags = 0;
822 
823  while (arg[0] != '\0') {
824  switch (arg[0]) {
825  case 'u':
826  flags |= CVAR_USERINFO;
827  break;
828  case 's':
829  flags |= CVAR_SERVERINFO;
830  break;
831  case 'a':
832  flags |= CVAR_ARCHIVE;
833  break;
834  default:
835  Com_Printf("Invalid flags %c given\n", arg[0]);
836  break;
837  }
838  arg++;
839  }
840  Cvar_FullSet(Cmd_Argv(1), va("%i", !Cvar_GetInteger(Cmd_Argv(1))), flags);
841  } else {
842  Com_Printf("val: %i\n", Cvar_GetInteger(Cmd_Argv(1)));
843  Cvar_Set(Cmd_Argv(1), "%i", !Cvar_GetInteger(Cmd_Argv(1)));
844  }
845 }
846 
851 static void Cvar_Copy_f (void)
852 {
853  const int c = Cmd_Argc();
854  if (c < 3) {
855  Com_Printf("Usage: %s <target> <source>\n", Cmd_Argv(0));
856  return;
857  }
858 
859  Cvar_Set(Cmd_Argv(1), "%s", Cvar_GetString(Cmd_Argv(2)));
860 }
861 
862 
869 {
870  for (const cvar_t* var = cvarVars; var; var = var->next) {
871  if (var->flags & CVAR_ARCHIVE)
872  FS_Printf(f, "set %s \"%s\" a\n", var->name, var->string);
873  }
874 }
875 
881 bool Cvar_PendingCvars (int flags)
882 {
883  for (const cvar_t* var = cvarVars; var; var = var->next) {
884  if ((var->flags & flags) && var->modified)
885  return true;
886  }
887 
888  return false;
889 }
890 
891 void Cvar_ClearVars (int flags)
892 {
893  for (cvar_t* var = cvarVars; var; var = var->next) {
894  if (var->flags & flags)
895  var->modified = false;
896  }
897 }
898 
902 static void Cvar_List_f (void)
903 {
904  int l = 0;
905  const char* token = nullptr;
906  const int c = Cmd_Argc();
907 
908  if (c == 2) {
909  token = Cmd_Argv(1);
910  l = strlen(token);
911  }
912 
913  int i = 0;
914  for (cvar_t* var = cvarVars; var; var = var->next, i++) {
915  if (token && strncmp(var->name, token, l)) {
916  i--;
917  continue;
918  }
919 #ifndef DEBUG
920  /* don't show developer cvars in release mode */
921  if (var->flags & CVAR_DEVELOPER)
922  continue;
923 #endif
924 
925  Com_Printf(var->flags & CVAR_ARCHIVE ? "A" : " ");
926  Com_Printf(var->flags & CVAR_USERINFO ? "U" : " ");
927  Com_Printf(var->flags & CVAR_SERVERINFO ? "S" : " ");
928  Com_Printf(var->modified ? "M" : " ");
929  Com_Printf(var->flags & CVAR_DEVELOPER ? "D" : " ");
930  Com_Printf(var->flags & CVAR_R_IMAGES ? "I" : " ");
931  Com_Printf(var->flags & CVAR_NOSET ? "-" :
932  var->flags & CVAR_LATCH ? "L" : " ");
933  Com_Printf(" %-20s \"%s\"\n", var->name, var->string);
934  if (var->description)
935  Com_Printf(S_COLOR_GREEN " %s\n", var->description);
936  }
937  Com_Printf("%i cvars\n", i);
938  Com_Printf("legend:\n"
939  "S: Serverinfo\n"
940  "L: Latched\n"
941  "D: Developer\n"
942  "U: Userinfo\n"
943  "I: Image\n"
944  "*: Archive\n"
945  "-: Not changeable\n"
946  );
947 }
948 
955 static char* Cvar_BitInfo (int bit, char* info, size_t infoSize)
956 {
957  for (cvar_t* var = cvarVars; var; var = var->next) {
958  if (var->flags & bit)
959  Info_SetValueForKey(info, infoSize, var->name, var->string);
960  }
961  return info;
962 }
963 
967 const char* Cvar_Userinfo (char* info, size_t infoSize)
968 {
969  info[0] = '\0';
970  return Cvar_BitInfo(CVAR_USERINFO, info, infoSize);
971 }
972 
977 const char* Cvar_Serverinfo (char* info, size_t infoSize)
978 {
979  info[0] = '\0';
980  return Cvar_BitInfo(CVAR_SERVERINFO, info, infoSize);
981 }
982 
987 static void Cvar_Del_f (void)
988 {
989  const int c = Cmd_Argc();
990  if (c != 2) {
991  Com_Printf("Usage: %s <variable>\n", Cmd_Argv(0));
992  return;
993  }
994 
995  Cvar_Delete(Cmd_Argv(1));
996 }
997 
1001 static void Cvar_Add_f (void)
1002 {
1003  if (Cmd_Argc() != 3) {
1004  Com_Printf("Usage: %s <variable> <value>\n", Cmd_Argv(0));
1005  return;
1006  }
1007 
1008  const cvar_t* cvar = Cvar_FindVar(Cmd_Argv(1));
1009  if (!cvar) {
1010  Com_Printf("Cvar_Add_f: %s does not exist\n", Cmd_Argv(1));
1011  return;
1012  }
1013 
1014  const float value = cvar->value + atof(Cmd_Argv(2));
1015  Cvar_SetValue(Cmd_Argv(1), value);
1016 }
1017 
1021 static void Cvar_Mod_f (void)
1022 {
1023  if (Cmd_Argc() != 3) {
1024  Com_Printf("Usage: %s <variable> <value>\n", Cmd_Argv(0));
1025  return;
1026  }
1027 
1028  const cvar_t* cvar = Cvar_FindVar(Cmd_Argv(1));
1029  if (!cvar) {
1030  Com_Printf("Cvar_Mod_f: %s does not exist\n", Cmd_Argv(1));
1031  return;
1032  }
1033 
1034  const int value = cvar->integer % atoi(Cmd_Argv(2));
1035  Cvar_SetValue(Cmd_Argv(1), value);
1036 }
1037 
1043 {
1044  if (!(Com_ServerState() && !Cvar_GetInteger("sv_cheats")))
1045  return;
1046 
1047  for (cvar_t* var = cvarVars; var; var = var->next) {
1048  if (!(var->flags & CVAR_CHEAT))
1049  continue;
1050 
1051  if (!var->defaultString) {
1052  Com_Printf("Cheat cvars: Cvar %s has no default value\n", var->name);
1053  continue;
1054  }
1055 
1056  if (Q_streq(var->string, var->defaultString))
1057  continue;
1058 
1059  /* also remove the oldString value here */
1060  Mem_Free(var->oldString);
1061  var->oldString = nullptr;
1062  Mem_Free(var->string);
1063  var->string = Mem_PoolStrDup(var->defaultString, com_cvarSysPool, 0);
1064  var->value = atof(var->string);
1065  var->integer = atoi(var->string);
1066 
1067  Com_Printf("'%s' is a cheat cvar - activate sv_cheats to use it.\n", var->name);
1068  }
1069 }
1070 
1071 #ifdef DEBUG
1072 void Cvar_PrintDebugCvars (void)
1073 {
1074  Com_Printf("Debug cvars:\n");
1075  for (const cvar_t* var = cvarVars; var; var = var->next) {
1076  if ((var->flags & CVAR_DEVELOPER) || !strncmp(var->name, "debug_", 6))
1077  Com_Printf(" * %s (%s)\n %s\n", var->name, var->string, var->description ? var->description : "");
1078  }
1079  Com_Printf("\n");
1080 }
1081 #endif
1082 
1087 void Cvar_Init (void)
1088 {
1089  Cmd_AddCommand("setold", Cvar_SetOld_f, "Restore the cvar old value");
1090  Cmd_AddCommand("del", Cvar_Del_f, "Delete a cvar");
1091  Cmd_AddCommand("set", Cvar_Set_f, "Set a cvar value");
1092  Cmd_AddCommand("switch", Cvar_Switch_f, "Switch a boolean cvar value");
1093  Cmd_AddCommand("add", Cvar_Add_f, "Add a value to a cvar");
1094  Cmd_AddCommand("define", Cvar_Define_f, "Defines a cvar if it does not exist");
1095  Cmd_AddCommand("mod", Cvar_Mod_f, "Apply a modulo on a cvar");
1096  Cmd_AddCommand("copy", Cvar_Copy_f, "Copy cvar target to source");
1097  Cmd_AddCommand("cvarlist", Cvar_List_f, "Show all cvars");
1098 }
1099 
1100 void Cvar_Shutdown (void)
1101 {
1102  cvarVars = nullptr;
1103  OBJZERO(cvarVarsHash);
1104 }
void Com_SetRenderModified(bool modified)
Definition: cvar.cpp:66
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition: cmd.cpp:516
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition: cmd.cpp:744
#define CVAR_USERINFO
Definition: cvar.h:41
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
Definition: shared.cpp:535
cvarChangeListener_t * Cvar_RegisterChangeListener(const char *varName, cvarChangeListenerFunc_t listenerFunc)
Registers a listener that is executed each time a cvar changed its value.
Definition: cvar.cpp:446
static bool userinfoModified
This is set each time a CVAR_USERINFO variable is changed so that the client knows to send it to the ...
Definition: cvar.cpp:54
#define CVAR_R_MASK
Definition: cvar.h:51
void Cvar_UnRegisterChangeListener(const char *varName, cvarChangeListenerFunc_t listenerFunc)
Unregisters a cvar change listener.
Definition: cvar.cpp:487
struct cvar_s * hash_next
Definition: cvar.h:86
#define HASH_Delete(anchor)
Definition: common.h:439
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
bool Cvar_AssertValue(cvar_t *cvar, float minVal, float maxVal, bool shouldBeIntegral)
Checks cvar values.
Definition: cvar.cpp:161
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition: cvar.h:71
static cvarChangeListener_t * Cvar_GetChangeListener(cvarChangeListenerFunc_t listenerFunc)
Definition: cvar.cpp:433
const char * Cvar_Serverinfo(char *info, size_t infoSize)
Returns an info string containing all the CVAR_SERVERINFO cvars.
Definition: cvar.cpp:977
static void Cvar_Switch_f(void)
Allows switching boolean cvars between zero and not-zero from console.
Definition: cvar.cpp:805
void(* cvarChangeListenerFunc_t)(const char *cvarName, const char *oldValue, const char *newValue, void *data)
Callback for the change listener.
Definition: cvar.h:59
static void Cvar_Copy_f(void)
Allows copying variables Available via console command copy.
Definition: cvar.cpp:851
float value
Definition: cvar.h:80
void Cvar_UnRegisterCvarListener(CvarListenerPtr listener)
Unregisters a cvar listener.
Definition: cvar.cpp:415
void Cvar_UpdateLatchedVars(void)
Any variables with latched values will now be updated.
Definition: cvar.cpp:683
void Cvar_Shutdown(void)
Definition: cvar.cpp:1100
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
bool Cmd_GenericCompleteFunction(char const *candidate, char const *partial, char const **match)
Definition: cmd.cpp:648
char * defaultString
Definition: cvar.h:75
#define Mem_StrDup(in)
Definition: mem.h:48
static void Cvar_Mod_f(void)
Apply a modulo to a cvar.
Definition: cvar.cpp:1021
int integer
Definition: cvar.h:81
bool Cvar_PendingCvars(int flags)
Checks whether there are pending cvars for the given flags.
Definition: cvar.cpp:881
#define CVAR_ARCHIVE
Definition: cvar.h:40
int Cvar_GetInteger(const char *varName)
Returns the int value of a cvar.
Definition: cvar.cpp:194
struct cvar_s * next
Definition: cvar.h:84
int flags
Definition: cvar.h:78
char * latchedString
Definition: cvar.h:74
static void Cvar_Define_f(void)
Definition: cvar.cpp:745
static char * Cvar_BitInfo(int bit, char *info, size_t infoSize)
Return a string with all cvars with bitflag given by parameter set.
Definition: cvar.cpp:955
cvar_t * Cvar_GetFirst(void)
Return the first cvar of the cvar list.
Definition: cvar.cpp:81
bool Cvar_Command(void)
Handles variable inspection and changing from the console.
Definition: cvar.cpp:708
cvarChangeListenerFunc_t exec
Definition: cvar.h:62
char * oldString
Definition: cvar.h:76
static void Cvar_ExecuteChangeListener(const cvar_t *cvar)
Executes the change listeners for a cvar.
Definition: cvar.cpp:424
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition: cvar.cpp:342
void Cvar_Init(void)
Reads in all archived cvars.
Definition: cvar.cpp:1087
#define OBJZERO(obj)
Definition: shared.h:178
float Cvar_GetValue(const char *varName)
Returns the float value of a cvar.
Definition: cvar.cpp:125
void Cvar_RegisterCvarListener(CvarListenerPtr listener)
Registers a cvar listener.
Definition: cvar.cpp:406
static wrapCache_t * hash[MAX_WRAP_HASH]
Definition: r_font.cpp:86
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition: cmd.cpp:505
const char * Cvar_VariableStringOld(const char *varName)
Returns the old value of cvar as string before we changed it.
Definition: cvar.cpp:226
#define CVAR_NOSET
Definition: cvar.h:43
char * description
Definition: cvar.h:77
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
Definition: files.cpp:1495
bool Com_IsUserinfoModified(void)
Definition: cvar.cpp:61
#define S_COLOR_GREEN
Definition: common.h:219
#define Q_strcasecmp(a, b)
Definition: shared.h:131
struct cvar_s * prev
Definition: cvar.h:85
memPool_t * com_cvarSysPool
Definition: common.cpp:71
#define HASH_Add(hash, elem, index)
Definition: common.h:430
void Cvar_FixCheatVars(void)
Reset cheat cvar values to default.
Definition: cvar.cpp:1042
bool Cvar_Delete(const char *varName)
Function to remove the cvar and free the space.
Definition: cvar.cpp:279
static void Cvar_Add_f(void)
Add a value to a cvar.
Definition: cvar.cpp:1001
static void Cvar_Set_f(void)
Allows setting and defining of arbitrary cvars from console.
Definition: cvar.cpp:761
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
cvar_t * Cvar_FullSet(const char *varName, const char *value, int flags)
Sets a cvar from console with the given flags.
Definition: cvar.cpp:640
void Info_SetValueForKey(char *s, const size_t size, const char *key, const char *value)
Adds a new entry into string with given value.
Definition: infostring.cpp:169
#define CVAR_LATCH
Definition: cvar.h:44
void Cvar_Reset(cvar_t *cvar)
Sets the cvar value back to the old value.
Definition: cvar.cpp:241
cvarChangeListener_t * changeListener
Definition: cvar.h:83
QGL_EXTERN GLint i
Definition: r_gl.h:113
std::vector< CvarListenerPtr > CvarListeners
Definition: cvar.cpp:41
char * string
Definition: cvar.h:73
bool Com_IsRenderModified(void)
Definition: cvar.cpp:71
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
#define CVAR_DEVELOPER
Definition: cvar.h:45
static void Cvar_List_f(void)
List all cvars via console command 'cvarlist'.
Definition: cvar.cpp:902
#define Mem_Free(ptr)
Definition: mem.h:35
#define CVAR_HASH_SIZE
Definition: cvar.cpp:35
unsigned int Com_HashKey(const char *name, int hashsize)
returns hash key for a string
Definition: shared.cpp:336
const char * Cvar_Userinfo(char *info, size_t infoSize)
Returns an info string containing all the CVAR_USERINFO cvars.
Definition: cvar.cpp:967
bool(* check)(struct cvar_s *cvar)
Definition: cvar.h:82
definitions common between client and server, but not game lib
static CvarListeners cvarListeners
Definition: cvar.cpp:42
#define CVAR_R_IMAGES
Definition: cvar.h:47
static cvar_t * Cvar_Set2(const char *varName, const char *value, bool force)
Sets a cvar values Handles write protection and latched cvars as expected.
Definition: cvar.cpp:512
cvar_t * Cvar_ForceSet(const char *varName, const char *value)
Will set the variable even if NOSET or LATCH.
Definition: cvar.cpp:604
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition: cvar.cpp:615
struct cvarChangeListener_s * next
Definition: cvar.h:63
const char * Cvar_GetString(const char *varName)
Returns the value of cvar as string.
Definition: cvar.cpp:210
#define Q_streq(a, b)
Definition: shared.h:136
#define Mem_PoolStrDup(in, pool, tagNum)
Definition: mem.h:50
static void Cvar_Del_f(void)
Delete a cvar - set [cvar] "" isn't working from within the scripts.
Definition: cvar.cpp:987
static cvar_t * cvarVarsHash[CVAR_HASH_SIZE]
Definition: cvar.cpp:37
static void Cvar_SetOld_f(void)
Allows resetting cvars to old value from console.
Definition: cvar.cpp:728
bool modified
Definition: cvar.h:79
#define Mem_PoolAllocType(type, pool)
Definition: mem.h:43
#define CVAR_CHEAT
Definition: cvar.h:46
void Cvar_ClearVars(int flags)
Definition: cvar.cpp:891
char name[MAX_OSPATH]
Definition: filesys.h:57
void Cvar_SetValue(const char *varName, float value)
Expands value to a string and calls Cvar_Set.
Definition: cvar.cpp:671
int Cvar_CompleteVariable(const char *partial, const char **match)
Unix like tab completion for console variables.
Definition: cvar.cpp:258
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
cvar_t * Cvar_FindVar(const char *varName)
Searches for a cvar given by parameter.
Definition: cvar.cpp:106
int Com_ServerState(void)
Check whether we are the server or have a singleplayer tactical mission.
Definition: common.cpp:538
void Cvar_WriteVariables(qFILE *f)
appends lines containing "set variable value" for all variables with the archive flag set to true...
Definition: cvar.cpp:868
bool Cvar_SetCheckFunction(const char *varName, bool(*check)(cvar_t *cvar))
Set a checker function for cvar values.
Definition: cvar.cpp:139
#define CVAR_SERVERINFO
Definition: cvar.h:42
char * name
Definition: cvar.h:72
void Com_SetUserinfoModified(bool modified)
Definition: cvar.cpp:56
static bool renderModified
This is set each time a CVAR_USERINFO variable is changed so that the renderer knows to update stuff ...
Definition: cvar.cpp:48
static bool Cvar_InfoValidate(const char *s)
Check that the Cvar identifier name doesn't contain a backslash, a double quote or a semi-colon...
Definition: cvar.cpp:94
static cvar_t * cvarVars
Cvar list.
Definition: cvar.cpp:79