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