]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/command/cl_cmd.qc
Fix some bugs with settemp and scoreboard_columns_set
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / command / cl_cmd.qc
1 // ==============================================
2 //  CSQC client commands code, written by Samual
3 //  Last updated: December 16th, 2011
4 // ==============================================
5
6 float cvar_clientsettemp(string tmp_cvar, string value)
7 {
8         float created_saved_value;
9         entity e;
10         
11         if not(tmp_cvar || value)
12         {
13                 dprint("Error: Invalid usage of cvar_clientsettemp(string, string); !\n");
14                 return FALSE;
15         }
16         
17         for(e = world; (e = find(e, classname, "saved_cvar_value")); )
18                 if(e.netname == tmp_cvar)
19                         goto saved; // skip creation
20                         
21         // creating a new entity to keep track of this cvar
22         e = spawn();
23         e.classname = "saved_cvar_value";
24         e.netname = strzone(tmp_cvar);
25         e.message = strzone(cvar_string(tmp_cvar));
26         created_saved_value = TRUE;
27         
28         // an entity for this cvar already exists
29         :saved
30         
31         // update the cvar to the value given
32         cvar_set(tmp_cvar, value);
33         
34         return created_saved_value;
35 }
36
37 float cvar_clientsettemp_restore()
38 {
39         float i;
40         entity e;
41         
42         for(e = world; (e = find(e, classname, "saved_cvar_value")); )
43                 { cvar_set(e.netname, e.message); ++i; } 
44                 
45         return i;
46 }
47
48 void DrawDebugModel()
49 {
50         if(time - floor(time) > 0.5)
51         {
52                 PolyDrawModel(self);
53                 self.drawmask = 0;
54         }
55         else
56         {
57                 self.renderflags = 0;
58                 self.drawmask = MASK_NORMAL;
59         }
60 }
61
62
63 // =======================
64 //  Command Sub-Functions
65 // =======================
66
67 void GameCommand_blurtest(float request)
68 {
69         // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now...
70         // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command.
71         
72         #ifdef BLURTEST
73         switch(request)
74         {
75                 case CMD_REQUEST_COMMAND:
76                 {
77                         blurtest_time0 = time;
78                         blurtest_time1 = time + stof(argv(1));
79                         blurtest_radius = stof(argv(2));
80                         blurtest_power = stof(argv(3));
81                         print("Enabled blurtest\n");
82                         return; 
83                 }
84                         
85                 default:
86                 case CMD_REQUEST_USAGE:
87                 {
88                         print("\nUsage:^3 cl_cmd blurtest\n");
89                         print("  No arguments required.\n");
90                         return;
91                 }
92         }
93         #else
94         if(request)
95         {
96                 print("Blurtest is not enabled on this client.\n");
97                 return;
98         }
99         #endif
100 }
101
102 void GameCommand_debugmodel(float request, float argc)
103 {
104         switch(request)
105         {
106                 case CMD_REQUEST_COMMAND:
107                 {
108                         string modelname = argv(1);
109                         entity debugmodel_entity;
110                         
111                         debugmodel_entity = spawn();
112                         precache_model(modelname);
113                         setmodel(debugmodel_entity, modelname);
114                         setorigin(debugmodel_entity, view_origin);
115                         debugmodel_entity.angles = view_angles;
116                         debugmodel_entity.draw = DrawDebugModel;
117                         debugmodel_entity.classname = "debugmodel";
118                         
119                         return; 
120                 }
121                         
122                 default:
123                 case CMD_REQUEST_USAGE:
124                 {
125                         print("\nUsage:^3 cl_cmd debugmodel model\n");
126                         print("  Where 'model' is a string of the model name to use for the debug model.\n");
127                         return;
128                 }
129         }
130 }
131
132 void GameCommand_handlevote(float request, float argc)
133 {
134         switch(request)
135         {
136                 case CMD_REQUEST_COMMAND:
137                 {
138                         float vote_selection;
139                         string vote_string;
140                         
141                         switch(argv(1))
142                         {
143                                 case "yes": vote_selection = 2; vote_string = "yes"; break;
144                                 case "no": vote_selection = 1; vote_string = "no"; break;
145                                 default: break;
146                         }
147                         
148                         if(vote_selection)
149                         {
150                                 if(uid2name_dialog) // handled by "uid2name" option
151                                 {
152                                         vote_active = 0;
153                                         vote_prev = 0;
154                                         vote_change = -9999;
155                                         localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
156                                         uid2name_dialog = 0;
157                                 }
158                                 else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
159                                 
160                                 return;
161                         }
162                 }
163                         
164                 default:
165                         print("Incorrect parameters for ^2handlevote^7\n");
166                 case CMD_REQUEST_USAGE:
167                 {
168                         print("\nUsage:^3 cl_cmd handlevote vote\n");
169                         print("  Where 'vote' is the selection for either the current poll or uid2name.\n");
170                         return;
171                 }
172         }
173 }
174
175 void GameCommand_hud(float request, float argc) // TODO: Add aliases in commands.cfg
176 {
177         switch(request)
178         {
179                 case CMD_REQUEST_COMMAND:
180                 {
181                         switch(argv(1))
182                         {
183                                 case "configure":
184                                 {
185                                         cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
186                                         return;
187                                 }
188                                 
189                                 case "save":
190                                 {
191                                         if(argv(2))
192                                         {
193                                                 HUD_Panel_ExportCfg(argv(2));
194                                                 return;
195                                         }
196                                         else
197                                         {
198                                                 break; // go to usage, we're missing the paramater needed here.
199                                         }
200                                 }
201                                 
202                                 case "radar":
203                                 {
204                                         if(argv(2))
205                                                 hud_panel_radar_maximized = (stof(argv(2)) != 0);
206                                         else
207                                                 hud_panel_radar_maximized = !hud_panel_radar_maximized;
208                                         
209                                         return;
210                                 }
211                                 
212                                 case "scoreboard_columns_set":
213                                 {
214                                         Cmd_HUD_SetFields(argc); // todo update this function
215                                         
216                                         return;
217                                 }
218
219                                 case "scoreboard_columns_help":
220                                 {
221                                         Cmd_HUD_Help(argc); // todo update this function
222                                         
223                                         return;
224                                 }
225                         }
226                         return; 
227                 }
228                         
229                 default:
230                         print("Incorrect parameters for ^2hud^7\n");
231                 case CMD_REQUEST_USAGE:
232                 {
233                         print("\nUsage:^3 cl_cmd hud action [configname | radartoggle]\n");
234                         print("  Where 'action' is the command to complete,\n");
235                         print("  'configname' is the name to save to for \"save\" action,\n");
236                         print("  and 'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action.\n");
237                         print("  Full list of commands here: \"configure, save, radar.\"\n");
238                         return;
239                 }
240         }
241 }
242
243 void GameCommand_mv_download(float request, float argc)
244 {
245         switch(request)
246         {
247                 case CMD_REQUEST_COMMAND:
248                 {
249                         Cmd_MapVote_MapDownload(argc);
250                         
251                         return; 
252                 }
253                         
254                 default:
255                 case CMD_REQUEST_USAGE:
256                 {
257                         print("\nUsage:^3 cl_cmd mapvote_download mapid\n");
258                         print("  Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
259                         return;
260                 }
261         }
262 }
263
264 void GameCommand_sendcvar(float request, float argc)
265 {
266         switch(request)
267         {
268                 case CMD_REQUEST_COMMAND:
269                 {
270                         // W_FixWeaponOrder will trash argv, so save what we need.
271                         string thiscvar = strzone(argv(1));
272                         string s = cvar_string(thiscvar);
273                         
274                         if(thiscvar == "cl_weaponpriority")
275                                 s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
276                         else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
277                                 s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
278                                 
279                         localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
280                         strunzone(thiscvar);
281                         
282                         return; 
283                 }
284                         
285                 default:
286                 case CMD_REQUEST_USAGE:
287                 {
288                         print("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
289                         print("  Where 'cvar' is the cvar plus arguments to send to the server.\n");
290                         return;
291                 }
292         }
293 }
294
295 void GameCommand_settemp(float request, float argc)
296 {
297         switch(request)
298         {
299                 case CMD_REQUEST_COMMAND:
300                 {
301                         if((argv(1) == "restore") && (argc == 2))
302                         {
303                                 float i = cvar_clientsettemp_restore();
304                                 
305                                 if(i)
306                                         dprint("Restored ", ftos(i), " temporary cvar settings to their original values.\n");
307                                 else
308                                         dprint("Nothing to restore.\n");
309                                 
310                                 return;
311                         }
312                         else if(argc >= 3)
313                         {
314                                 if(cvar_clientsettemp(argv(1), argv(2)))
315                                         dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n"); 
316                                 else
317                                         dprint("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n");
318                         
319                                 return;
320                         }
321                 }
322                         
323                 default:
324                         print("Incorrect parameters for ^2settemp^7\n");
325                 case CMD_REQUEST_USAGE:
326                 {
327                         print("\nUsage:^3 cl_cmd settemp <cvar> | [restore]\n");
328                         print("  Where 'cvar' is the cvar plus arguments to send to the server,\n");
329                         print("  or 'restore' allows you to restore all of the original temporary cvar values.\n");
330                         return;
331                 }
332         }
333 }
334
335 /* use this when creating a new command, making sure to place it in alphabetical order.
336 void GameCommand_(float request)
337 {
338         switch(request)
339         {
340                 case CMD_REQUEST_COMMAND:
341                 {
342                         
343                         return; 
344                 }
345                         
346                 default:
347                 case CMD_REQUEST_USAGE:
348                 {
349                         print("\nUsage:^3 cl_cmd \n");
350                         print("  No arguments required.\n");
351                         return;
352                 }
353         }
354 }
355 */
356
357
358 // ==================================
359 //  Macro system for client commands
360 // ==================================
361
362 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
363 #define CLIENT_COMMANDS(request,arguments) \
364         CLIENT_COMMAND("blurtest", GameCommand_blurtest(request), "Feature for testing blur postprocessing") \
365         CLIENT_COMMAND("debugmodel", GameCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
366         CLIENT_COMMAND("handlevote", GameCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
367         CLIENT_COMMAND("hud", GameCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
368         CLIENT_COMMAND("mv_download", GameCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
369         CLIENT_COMMAND("sendcvar", GameCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
370         CLIENT_COMMAND("settemp", GameCommand_settemp(request, arguments), "Temporarily set a value to a cvar which is restored by command or end of each match") \
371         /* nothing */
372         
373 void GameCommand_macro_help()
374 {
375         #define CLIENT_COMMAND(name,function,description) \
376                 { print("  ^2", name, "^7: ", description, "\n"); }
377                 
378         CLIENT_COMMANDS(0, 0)
379         #undef CLIENT_COMMAND
380         
381         return;
382 }
383
384 float GameCommand_macro_command(float argc)
385 {
386         #define CLIENT_COMMAND(name,function,description) \
387                 { if(name == strtolower(argv(0))) { function; return TRUE; } }
388                 
389         CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc)
390         #undef CLIENT_COMMAND
391         
392         return FALSE;
393 }
394
395 float GameCommand_macro_usage(float argc)
396 {
397         #define CLIENT_COMMAND(name,function,description) \
398                 { if(name == strtolower(argv(1))) { function; return TRUE; } }
399                 
400         CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc)
401         #undef CLIENT_COMMAND
402         
403         return FALSE;
404 }
405
406
407 // =========================================
408 //  Main Function Called By Engine (cl_cmd)
409 // =========================================
410 // If this function exists, client code handles gamecommand instead of the engine code.
411
412 void GameCommand(string command)
413 {
414         float argc = tokenize_console(command);
415
416         if(strtolower(argv(0)) == "help") 
417         {
418                 if(argc == 1) 
419                 {
420                         print("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are:\n");
421                         GameCommand_macro_help();
422                         GameCommand_Generic("help");
423                         print("For help about specific commands, type cl_cmd help COMMAND\n");
424                         return;
425                 } 
426                 else if(GameCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
427                 {
428                         return;
429                 }
430         } 
431         else if(GameCommand_Generic(command)) 
432         {
433                 return; // handled by common/gamecommand.qc
434         }
435         else if(GameCommand_macro_command(argc)) // continue as usual and scan for normal commands
436         {
437                 return; // handled by one of the above GameCommand_* functions
438         }
439         
440         // nothing above caught the command, must be invalid
441         print("Unknown client command", ((command != "") ? strcat(" \"", command, "\"") : ""), ". For a list of supported commands, try cl_cmd help.\n");
442         
443         return;
444 }
445
446
447 // ===================================
448 //  Macro system for console commands
449 // ===================================
450
451 // These functions are here specifically to add special + - commands to the game, and are not really normal commands.
452 // Please add client commands to the function above this, as this is only for special reasons.
453 #define CONSOLE_COMMANDS_NORMAL \
454         CONSOLE_COMMAND("+showscores", { scoreboard_showscores = TRUE; }) \
455         CONSOLE_COMMAND("-showscores", { scoreboard_showscores = FALSE; }) \
456         CONSOLE_COMMAND("+showaccuracy", { scoreboard_showaccuracy = TRUE; }) \
457         CONSOLE_COMMAND("-showaccuracy", { scoreboard_showaccuracy = FALSE; }) \
458         /* nothing */
459         
460 #define CONSOLE_COMMANDS_MOVEMENT \
461         CONSOLE_COMMAND("+forward", { ++camera_direction_x; }) \
462         CONSOLE_COMMAND("-forward", { --camera_direction_x; }) \
463         CONSOLE_COMMAND("+back", { --camera_direction_x; }) \
464         CONSOLE_COMMAND("-back", { ++camera_direction_x; }) \
465         CONSOLE_COMMAND("+moveup", { ++camera_direction_z; }) \
466         CONSOLE_COMMAND("-moveup", { --camera_direction_z; }) \
467         CONSOLE_COMMAND("+movedown", { --camera_direction_z; }) \
468         CONSOLE_COMMAND("-movedown", { ++camera_direction_z; }) \
469         CONSOLE_COMMAND("+moveright", { --camera_direction_y; }) \
470         CONSOLE_COMMAND("-moveright", { ++camera_direction_y; }) \
471         CONSOLE_COMMAND("+moveleft", { ++camera_direction_y; }) \
472         CONSOLE_COMMAND("-moveleft", { --camera_direction_y; }) \
473         CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
474         CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
475         CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
476         CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
477         /* nothing */
478
479 void ConsoleCommand_macro_init()
480 {
481         // first init normal commands
482         #define CONSOLE_COMMAND(name,execution) \
483                 { registercommand(name); }
484
485         CONSOLE_COMMANDS_NORMAL
486         #undef CONSOLE_COMMAND
487         
488         // then init movement commands
489         #ifndef CAMERATEST
490         if(isdemo())
491         {
492         #endif
493                 #define CONSOLE_COMMAND(name,execution) \
494                         { registercommand(name); }
495
496                 CONSOLE_COMMANDS_MOVEMENT
497                 #undef CONSOLE_COMMAND
498         #ifndef CAMERATEST
499         }
500         #endif
501         
502         return;
503 }
504
505 float ConsoleCommand_macro_normal(float argc)
506 {
507         #define CONSOLE_COMMAND(name,execution) \
508                 { if(name == strtolower(argv(0))) { { execution } return TRUE; } }
509                 
510         CONSOLE_COMMANDS_NORMAL
511         #undef CONSOLE_COMMAND
512         
513         return FALSE;
514 }
515
516 float ConsoleCommand_macro_movement(float argc)
517 {
518         if(camera_active)
519         {
520                 #define CONSOLE_COMMAND(name,execution) \
521                         { if(name == strtolower(argv(0))) { { execution } return TRUE; } }
522
523                 CONSOLE_COMMANDS_MOVEMENT
524                 #undef CONSOLE_COMMAND
525         }
526         
527         return FALSE;
528 }
529
530
531 // ======================================================
532 //  Main Function Called By Engine (registered commands)
533 // ======================================================
534 // Used to parse commands in the console that have been registered with the "registercommand" function
535
536 float CSQC_ConsoleCommand(string command)
537 {
538         float argc = tokenize_console(command);
539
540         if(ConsoleCommand_macro_normal(argc))
541         {
542                 return TRUE;
543         }
544         else if(ConsoleCommand_macro_movement(argc))
545         {
546                 return TRUE;
547         }
548         
549         // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.
550
551         return FALSE;
552 }