]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/command/cl_cmd.qc
Merge remote branch 'origin/master' into samual/updatecommands
[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 LocalCommand_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 LocalCommand_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 LocalCommand_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                         if(InterpretBoolean(argv(1)))
142                         {
143                                 vote_selection = 2; 
144                                 vote_string = "yes";
145                         }
146                         else
147                         {
148                                 vote_selection = 1; 
149                                 vote_string = "no"; 
150                         }
151                         
152                         if(vote_selection)
153                         {
154                                 if(uid2name_dialog) // handled by "uid2name" option
155                                 {
156                                         vote_active = 0;
157                                         vote_prev = 0;
158                                         vote_change = -9999;
159                                         localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
160                                         uid2name_dialog = 0;
161                                 }
162                                 else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
163                                 
164                                 return;
165                         }
166                 }
167                         
168                 default:
169                         print("Incorrect parameters for ^2handlevote^7\n");
170                 case CMD_REQUEST_USAGE:
171                 {
172                         print("\nUsage:^3 cl_cmd handlevote vote\n");
173                         print("  Where 'vote' is the selection for either the current poll or uid2name.\n");
174                         return;
175                 }
176         }
177 }
178
179 void LocalCommand_hud(float request, float argc)
180 {
181         switch(request)
182         {
183                 case CMD_REQUEST_COMMAND:
184                 {
185                         switch(argv(1))
186                         {
187                                 case "configure":
188                                 {
189                                         cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
190                                         return;
191                                 }
192                                 
193                                 case "save":
194                                 {
195                                         if(argv(2))
196                                         {
197                                                 HUD_Panel_ExportCfg(argv(2));
198                                                 return;
199                                         }
200                                         else
201                                         {
202                                                 break; // go to usage, we're missing the paramater needed here.
203                                         }
204                                 }
205                                 
206                                 case "scoreboard_columns_set":
207                                 {
208                                         Cmd_HUD_SetFields(argc); 
209                                         return;
210                                 }
211
212                                 case "scoreboard_columns_help":
213                                 {
214                                         Cmd_HUD_Help();
215                                         return;
216                                 }
217                                 
218                                 case "radar":
219                                 {
220                                         hud_panel_radar_maximized = (argv(2) ? InterpretBoolean(argv(2)) : !hud_panel_radar_maximized);
221                                         return;
222                                 }
223                         }
224                 }
225                         
226                 default:
227                         print("Incorrect parameters for ^2hud^7\n");
228                 case CMD_REQUEST_USAGE:
229                 {
230                         print("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n");
231                         print("  Where 'action' is the command to complete,\n");
232                         print("  'configname' is the name to save to for \"save\" action,\n");
233                         print("  'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
234                         print("  and 'layout' is how to organize the scoreboard columns for the set action.\n");
235                         print("  Full list of commands here: \"configure, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
236                         return;
237                 }
238         }
239 }
240
241 void LocalCommand_localprint(float request, float argc)
242 {
243         switch(request)
244         {
245                 case CMD_REQUEST_COMMAND:
246                 {
247                         if(argv(1))
248                         {
249                                 centerprint_hud(argv(1));
250                                 return; 
251                         }
252                 }
253                         
254                 default:
255                         print("Incorrect parameters for ^2localprint^7\n");
256                 case CMD_REQUEST_USAGE:
257                 {
258                         print("\nUsage:^3 cl_cmd localprint \"message\"\n");
259                         print("  'message' is the centerprint message to send to yourself.\n");
260                         return;
261                 }
262         }
263 }
264
265 void LocalCommand_mv_download(float request, float argc)
266 {
267         switch(request)
268         {
269                 case CMD_REQUEST_COMMAND:
270                 {
271                         Cmd_MapVote_MapDownload(argc);
272                         return; 
273                 }
274                         
275                 default:
276                 case CMD_REQUEST_USAGE:
277                 {
278                         print("\nUsage:^3 cl_cmd mv_download mapid\n");
279                         print("  Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
280                         return;
281                 }
282         }
283 }
284
285 void LocalCommand_sendcvar(float request, float argc)
286 {
287         switch(request)
288         {
289                 case CMD_REQUEST_COMMAND:
290                 {
291                         // W_FixWeaponOrder will trash argv, so save what we need.
292                         string thiscvar = strzone(argv(1));
293                         string s = cvar_string(thiscvar);
294                         
295                         if(thiscvar == "cl_weaponpriority")
296                                 s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
297                         else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
298                                 s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
299                                 
300                         localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
301                         strunzone(thiscvar);
302                         return; 
303                 }
304                         
305                 default:
306                 case CMD_REQUEST_USAGE:
307                 {
308                         print("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
309                         print("  Where 'cvar' is the cvar plus arguments to send to the server.\n");
310                         return;
311                 }
312         }
313 }
314
315 void LocalCommand_settemp(float request, float argc)
316 {
317         switch(request)
318         {
319                 case CMD_REQUEST_COMMAND:
320                 {
321                         if((argv(1) == "restore") && argv(2))
322                         {
323                                 float i = cvar_clientsettemp_restore();
324                                 
325                                 if(i)
326                                         dprint("Restored ", ftos(i), " temporary cvar settings to their original values.\n");
327                                 else
328                                         dprint("Nothing to restore.\n");
329                                 
330                                 return;
331                         }
332                         else if(argc >= 3)
333                         {
334                                 if(cvar_clientsettemp(argv(1), argv(2)))
335                                         dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n"); 
336                                 else
337                                         dprint("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n");
338                         
339                                 return;
340                         }
341                 }
342                         
343                 default:
344                         print("Incorrect parameters for ^2settemp^7\n");
345                 case CMD_REQUEST_USAGE:
346                 {
347                         print("\nUsage:^3 cl_cmd settemp \"cvar\" | [restore]\n");
348                         print("  Where 'cvar' is the cvar plus arguments to send to the server,\n");
349                         print("  or 'restore' allows you to restore all of the original temporary cvar values.\n");
350                         return;
351                 }
352         }
353 }
354
355 /* use this when creating a new command, making sure to place it in alphabetical order.
356 void LocalCommand_(float request)
357 {
358         switch(request)
359         {
360                 case CMD_REQUEST_COMMAND:
361                 {
362                         
363                         return; 
364                 }
365                         
366                 default:
367                 case CMD_REQUEST_USAGE:
368                 {
369                         print("\nUsage:^3 cl_cmd \n");
370                         print("  No arguments required.\n");
371                         return;
372                 }
373         }
374 }
375 */
376
377
378 // ==================================
379 //  Macro system for client commands
380 // ==================================
381
382 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
383 #define CLIENT_COMMANDS(request,arguments) \
384         CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \
385         CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
386         CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
387         CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
388         CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
389         CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
390         CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
391         CLIENT_COMMAND("settemp", LocalCommand_settemp(request, arguments), "Temporarily set a value to a cvar which is restored by command or end of each match") \
392         /* nothing */
393         
394 void LocalCommand_macro_help()
395 {
396         #define CLIENT_COMMAND(name,function,description) \
397                 { print("  ^2", name, "^7: ", description, "\n"); }
398                 
399         CLIENT_COMMANDS(0, 0)
400         #undef CLIENT_COMMAND
401         
402         return;
403 }
404
405 float LocalCommand_macro_command(float argc)
406 {
407         #define CLIENT_COMMAND(name,function,description) \
408                 { if(name == strtolower(argv(0))) { function; return TRUE; } }
409                 
410         CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc)
411         #undef CLIENT_COMMAND
412         
413         return FALSE;
414 }
415
416 float LocalCommand_macro_usage(float argc)
417 {
418         #define CLIENT_COMMAND(name,function,description) \
419                 { if(name == strtolower(argv(1))) { function; return TRUE; } }
420                 
421         CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc)
422         #undef CLIENT_COMMAND
423         
424         return FALSE;
425 }
426
427
428 // =========================================
429 //  Main Function Called By Engine (cl_cmd)
430 // =========================================
431 // If this function exists, client code handles gamecommand instead of the engine code.
432
433 void GameCommand(string command)
434 {
435         float argc = tokenize_console(command);
436
437         if(strtolower(argv(0)) == "help") 
438         {
439                 if(argc == 1) 
440                 {
441                         print("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are:\n");
442                         LocalCommand_macro_help();
443                         GameCommand_Generic("help");
444                         print("For help about specific commands, type cl_cmd help COMMAND\n");
445                         return;
446                 } 
447                 else if(LocalCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
448                 {
449                         return;
450                 }
451         } 
452         else if(GameCommand_Generic(command)) 
453         {
454                 return; // handled by common/command/generic.qc
455         }
456         else if(LocalCommand_macro_command(argc)) // continue as usual and scan for normal commands
457         {
458                 return; // handled by one of the above LocalCommand_* functions
459         }
460         
461         // nothing above caught the command, must be invalid
462         print(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n");
463         
464         return;
465 }
466
467
468 // ===================================
469 //  Macro system for console commands
470 // ===================================
471
472 // These functions are here specifically to add special + - commands to the game, and are not really normal commands.
473 // Please add client commands to the function above this, as this is only for special reasons.
474 #define CONSOLE_COMMANDS_NORMAL \
475         CONSOLE_COMMAND("+showscores", { scoreboard_showscores = TRUE; }) \
476         CONSOLE_COMMAND("-showscores", { scoreboard_showscores = FALSE; }) \
477         CONSOLE_COMMAND("+showaccuracy", { scoreboard_showaccuracy = TRUE; }) \
478         CONSOLE_COMMAND("-showaccuracy", { scoreboard_showaccuracy = FALSE; }) \
479         /* nothing */
480         
481 #define CONSOLE_COMMANDS_MOVEMENT \
482         CONSOLE_COMMAND("+forward", { ++camera_direction_x; }) \
483         CONSOLE_COMMAND("-forward", { --camera_direction_x; }) \
484         CONSOLE_COMMAND("+back", { --camera_direction_x; }) \
485         CONSOLE_COMMAND("-back", { ++camera_direction_x; }) \
486         CONSOLE_COMMAND("+moveup", { ++camera_direction_z; }) \
487         CONSOLE_COMMAND("-moveup", { --camera_direction_z; }) \
488         CONSOLE_COMMAND("+movedown", { --camera_direction_z; }) \
489         CONSOLE_COMMAND("-movedown", { ++camera_direction_z; }) \
490         CONSOLE_COMMAND("+moveright", { --camera_direction_y; }) \
491         CONSOLE_COMMAND("-moveright", { ++camera_direction_y; }) \
492         CONSOLE_COMMAND("+moveleft", { ++camera_direction_y; }) \
493         CONSOLE_COMMAND("-moveleft", { --camera_direction_y; }) \
494         CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
495         CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
496         CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
497         CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
498         /* nothing */
499
500 void ConsoleCommand_macro_init()
501 {
502         // first init normal commands
503         #define CONSOLE_COMMAND(name,execution) \
504                 { registercommand(name); }
505
506         CONSOLE_COMMANDS_NORMAL
507         #undef CONSOLE_COMMAND
508         
509         // then init movement commands
510         #ifndef CAMERATEST
511         if(isdemo())
512         {
513         #endif
514                 #define CONSOLE_COMMAND(name,execution) \
515                         { registercommand(name); }
516
517                 CONSOLE_COMMANDS_MOVEMENT
518                 #undef CONSOLE_COMMAND
519         #ifndef CAMERATEST
520         }
521         #endif
522         
523         return;
524 }
525
526 float ConsoleCommand_macro_normal(float argc)
527 {
528         #define CONSOLE_COMMAND(name,execution) \
529                 { if(name == strtolower(argv(0))) { { execution } return TRUE; } }
530                 
531         CONSOLE_COMMANDS_NORMAL
532         #undef CONSOLE_COMMAND
533         
534         return FALSE;
535 }
536
537 float ConsoleCommand_macro_movement(float argc)
538 {
539         if(camera_active)
540         {
541                 #define CONSOLE_COMMAND(name,execution) \
542                         { if(name == strtolower(argv(0))) { { execution } return TRUE; } }
543
544                 CONSOLE_COMMANDS_MOVEMENT
545                 #undef CONSOLE_COMMAND
546         }
547         
548         return FALSE;
549 }
550
551
552 // ======================================================
553 //  Main Function Called By Engine (registered commands)
554 // ======================================================
555 // Used to parse commands in the console that have been registered with the "registercommand" function
556
557 float CSQC_ConsoleCommand(string command)
558 {
559         float argc = tokenize_console(command);
560
561         if(ConsoleCommand_macro_normal(argc))
562         {
563                 return TRUE;
564         }
565         else if(ConsoleCommand_macro_movement(argc))
566         {
567                 return TRUE;
568         }
569         
570         // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.
571
572         return FALSE;
573 }