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