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