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