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