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