]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/gamecommand.qc
ecad7948ee66d1ee0ddce47dc03c43d1a4fd1d99
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / gamecommand.qc
1 // =====================================================
2 //  Server side game commands code, reworked by Samual
3 //  Last updated: November 4th, 2011
4 // =====================================================
5
6 #define GC_REQUEST_HELP 1
7 #define GC_REQUEST_COMMAND 2
8 #define GC_REQUEST_USAGE 3
9
10 float RadarMap_Make(float argc);
11
12 string GotoMap(string m);
13
14 void race_deleteTime(string map, float pos);
15
16
17 // ============================
18 //  Misc. Supporting Functions
19 // ============================
20
21 //  used by GameCommand_make_mapinfo()
22 void make_mapinfo_Think()
23 {
24         if(MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
25         {
26                 print("Done rebuiling mapinfos.\n");
27                 MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
28                 remove(self);
29         }
30         else
31         {
32                 self.think = make_mapinfo_Think;
33                 self.nextthink = time;
34         }
35 }
36
37 //  used by GameCommand_extendmatchtime() and GameCommand_reducematchtime()
38 void changematchtime(float delta, float mi, float ma)
39 {
40         float cur;
41         float new;
42         float lim;
43
44         if(delta == 0)
45                 return;
46         if(autocvar_timelimit < 0)
47                 return;
48
49         if(mi <= 10)
50                 mi = 10; // at least ten sec in the future
51         cur = time - game_starttime;
52         if(cur > 0)
53                 mi += cur; // from current time!
54
55         lim = autocvar_timelimit * 60;
56
57         if(delta > 0)
58         {
59                 if(lim == 0)
60                         return; // cannot increase any further
61                 else if(lim < ma)
62                         new = min(ma, lim + delta);
63                 else // already above maximum: FAIL
64                         return;
65         }
66         else
67         {
68                 if(lim == 0) // infinite: try reducing to max, if we are allowed to
69                         new = max(mi, ma);
70                 else if(lim > mi) // above minimum: decrease
71                         new = max(mi, lim + delta);
72                 else // already below minimum: FAIL
73                         return;
74         }
75
76         cvar_set("timelimit", ftos(new / 60));
77 }
78
79 //  used by GameCommand_modelbug() // TODO: is this even needed?
80 float g_clientmodel_genericsendentity (entity to, float sf);
81 void modelbug_make_svqc();
82 void modelbug_make_csqc()
83 {
84         Net_LinkEntity(self, TRUE, 0, g_clientmodel_genericsendentity);
85         self.think = modelbug_make_svqc;
86         self.nextthink = time + 1;
87         setorigin(self, self.origin - '0 0 8');
88 }
89 void modelbug_make_svqc()
90 {
91         self.SendEntity = func_null;
92         self.think = modelbug_make_csqc;
93         self.nextthink = time + 1;
94         setorigin(self, self.origin + '0 0 8');
95 }
96 void modelbug()
97 {
98         entity e;
99         e = spawn();
100         setorigin(e, nextent(world).origin);
101         precache_model("models_portal.md3");
102         setmodel(e, "models/portal.md3");
103         e.think = modelbug_make_svqc;
104         e.nextthink = time + 1;
105 }
106
107
108 // =======================
109 //  Command Sub-Functions
110 // =======================
111
112 void GameCommand_adminmsg(float request, float argc)
113 {
114         entity client;
115         float entno = stof(argv(1)); 
116         float n, i;
117         string s;
118         
119         switch(request)
120         {
121                 case GC_REQUEST_HELP:
122                         print("  ^2adminmsg^7: Send an admin message to a client directly\n");
123                         return;
124                         
125                 case GC_REQUEST_COMMAND:
126                         if(argc >= 3 && argc <= 4) {
127                                 if((entno < 0) | (entno > maxclients)) {
128                                         print("Player ", argv(1), " doesn't exist\n");
129                                         return;
130                                 }
131                                 n = 0;
132                                 for(i = (entno ? entno : 1); i <= (entno ? entno : maxclients); ++i)
133                                 {
134                                         client = edict_num(i);
135                                         if(client.flags & FL_CLIENT)
136                                         {
137                                                 if(argc == 4)
138                                                 {
139                                                         // make the string console safe
140                                                         s = argv(2);
141                                                         s = strreplace("\n", "", s);
142                                                         s = strreplace("\\", "\\\\", s);
143                                                         s = strreplace("$", "$$", s);
144                                                         s = strreplace("\"", "\\\"", s);
145                                                         stuffcmd(client, sprintf("\ninfobar %f \"%s\"\n", stof(argv(3)), s));
146                                                 }
147                                                 else
148                                                 {
149                                                         centerprint(client, strcat("^3", admin_name(), ":\n\n^7", argv(2)));
150                                                         sprint(client, strcat("\{1}\{13}^3", admin_name(), "^7: ", argv(2), "\n"));
151                                                 }
152                                                 dprint("Message sent to ", client.netname, "\n");
153                                                 ++n;
154                                         }
155                                 }
156                                 if(!n) { print(strcat("Client (", argv(1) ,") not found.\n")); } 
157                                 return;
158                         } 
159                         
160                 default:
161                         print("Incorrect parameters for ^2adminmsg^7\n");
162                 case GC_REQUEST_USAGE:
163                         print("\nUsage:^3 sv_cmd adminmsg clientnumber \"message\" [infobartime]\n");
164                         print("  If infobartime is provided, the message will be sent to infobar.\n");
165                         print("  Otherwise, it will just be sent as a centerprint message.\n");
166                         print("Examples: adminmsg 4 \"this infomessage will last for ten seconds\" 10\n");
167                         print("          adminmsg 2 \"this message will be a centerprint\"\n");
168                         return;
169         }
170 }
171
172 void GameCommand_allready(float request)
173 {
174         switch(request)
175         {
176                 case GC_REQUEST_HELP:
177                         print("  ^2allready^7: Restart the server and reset the players\n");
178                         return;
179                         
180                 case GC_REQUEST_COMMAND:
181                         ReadyRestart();
182                         return;
183                         
184                 default:
185                 case GC_REQUEST_USAGE:
186                         print("\nUsage:^3 sv_cmd allready\n");
187                         print("  No arguments required.\n");
188                         return;
189         }
190 }
191
192 void GameCommand_allspec(float request, float argc)
193 {
194         entity client;
195         float i;
196         
197         switch(request)
198         {
199                 case GC_REQUEST_HELP:
200                         print("  ^2allspec^7: Force all players to spectate\n");
201                         return;
202                         
203                 case GC_REQUEST_COMMAND:
204                         FOR_EACH_PLAYER(client)
205                         {
206                                 self = client;
207                                 PutObserverInServer();
208                                 ++i;
209                         }
210                         if(i) { bprint(strcat("Successfully forced all (", ftos(i), ") players to spectate", (argv(1) ? strcat(" for reason: '", argv(1), "'") : ""), ".\n")); }
211                         else { print("No players found to spectate.\n"); }
212                         return;
213                         
214                 default:
215                 case GC_REQUEST_USAGE:
216                         print("\nUsage:^3 sv_cmd allspec [reason]\n");
217                         print("  Where 'reason' is an optional argument for explanation of allspec command.\n");
218                         print("See also: ^2moveplayer^7\n");
219                         return;
220         }
221 }
222
223 void GameCommand_anticheat(float request, float argc) // FIXME: player entity is never found
224 {
225         entity client;
226         float entno = stof(argv(1)); 
227         
228         switch(request)
229         {
230                 case GC_REQUEST_HELP:
231                         print("  ^2anticheat^7: Create an anticheat report for a client\n");
232                         return;
233                         
234                 case GC_REQUEST_COMMAND:
235                         if((entno < 1) | (entno > maxclients)) {
236                                 print("Player ", argv(1), " doesn't exist\n");
237                                 return;
238                         }
239                         client = edict_num(entno);
240                         if(clienttype(client) != CLIENTTYPE_REAL && clienttype(client) != CLIENTTYPE_BOT) {
241                                 print("Player ", client.netname, " is not active\n");
242                                 return;
243                         }
244                         self = client;
245                         anticheat_report();
246                         return;
247                         
248                 default:
249                         print("Incorrect parameters for ^2anticheat^7\n");
250                 case GC_REQUEST_USAGE:
251                         print("\nUsage:^3 sv_cmd anticheat clientnumber\n");
252                         print("  where 'clientnumber' is player entity number.\n");
253                         return;
254         }
255 }
256
257 void GameCommand_bbox(float request)
258 {
259         switch(request)
260         {
261                 case GC_REQUEST_HELP:
262                         print("  ^2bbox^7: Print detailed information about world size\n");
263                         return;
264                         
265                 case GC_REQUEST_COMMAND:
266                         print("Original size: ", ftos(world.absmin_x), " ", ftos(world.absmin_y), " ", ftos(world.absmin_z));
267                         print(" ", ftos(world.absmax_x), " ", ftos(world.absmax_y), " ", ftos(world.absmax_z), "\n");
268                         print("Currently set size: ", ftos(world.mins_x), " ", ftos(world.mins_y), " ", ftos(world.mins_z));
269                         print(" ", ftos(world.maxs_x), " ", ftos(world.maxs_y), " ", ftos(world.maxs_z), "\n");
270                         print("Solid bounding box size:");
271
272                         tracebox('1 0 0' * world.absmin_x,
273                                                         '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z,
274                                                         '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z,
275                                                         '1 0 0' * world.absmax_x,
276                                         MOVE_WORLDONLY,
277                                         world);
278                         if(trace_startsolid)
279                                 print(" ", ftos(world.absmin_x));
280                         else
281                                 print(" ", ftos(trace_endpos_x));
282
283                         tracebox('0 1 0' * world.absmin_y,
284                                                         '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z,
285                                                         '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z,
286                                                         '0 1 0' * world.absmax_y,
287                                         MOVE_WORLDONLY,
288                                         world);
289                         if(trace_startsolid)
290                                 print(" ", ftos(world.absmin_y));
291                         else
292                                 print(" ", ftos(trace_endpos_y));
293
294                         tracebox('0 0 1' * world.absmin_z,
295                                                         '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y,
296                                                         '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y,
297                                                         '0 0 1' * world.absmax_z,
298                                         MOVE_WORLDONLY,
299                                         world);
300                         if(trace_startsolid)
301                                 print(" ", ftos(world.absmin_z));
302                         else
303                                 print(" ", ftos(trace_endpos_z));
304
305                         tracebox('1 0 0' * world.absmax_x,
306                                                         '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z,
307                                                         '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z,
308                                                         '1 0 0' * world.absmin_x,
309                                         MOVE_WORLDONLY,
310                                         world);
311                         if(trace_startsolid)
312                                 print(" ", ftos(world.absmax_x));
313                         else
314                                 print(" ", ftos(trace_endpos_x));
315
316                         tracebox('0 1 0' * world.absmax_y,
317                                                         '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z,
318                                                         '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z,
319                                                         '0 1 0' * world.absmin_y,
320                                         MOVE_WORLDONLY,
321                                         world);
322                         if(trace_startsolid)
323                                 print(" ", ftos(world.absmax_y));
324                         else
325                                 print(" ", ftos(trace_endpos_y));
326
327                         tracebox('0 0 1' * world.absmax_z,
328                                                         '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y,
329                                                         '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y,
330                                                         '0 0 1' * world.absmin_z,
331                                         MOVE_WORLDONLY,
332                                         world);
333                         if(trace_startsolid)
334                                 print(" ", ftos(world.absmax_z));
335                         else
336                                 print(" ", ftos(trace_endpos_z));
337                                 
338                         print("\n");
339                         return;
340                         
341                 default:
342                 case GC_REQUEST_USAGE:
343                         print("\nUsage:^3 sv_cmd bbox\n");
344                         print("  No arguments required.\n");
345                         print("See also: ^2gettaginfo^7\n");
346                         return;
347         }
348 }
349
350 void GameCommand_bot_cmd(float request, float argc) // what a mess... old old code.
351 {
352         entity bot;
353         
354         switch(request)
355         {
356                 case GC_REQUEST_HELP:
357                         print("  ^2bot_cmd^7: Control and send commands to bots\n");
358                         return;
359                         
360                 case GC_REQUEST_COMMAND:
361                         if(argv(1) == "reset")
362                         {
363                                 bot_resetqueues();
364                                 return;
365                         }
366                         else if(argv(1) == "load" && argc == 3)
367                         {
368                                 float fh, i;
369                                 string s;
370                                 fh = fopen(argv(2), FILE_READ);
371                                 if(fh < 0)
372                                 {
373                                         print("cannot open the file\n");
374                                         return;
375                                 }
376
377                                 i = 0;
378                                 while((s = fgets(fh)))
379                                 {
380                                         argc = tokenize_console(s);
381
382                                         if(argc >= 3 && argv(0) == "sv_cmd" && argv(1) == "bot_cmd")
383                                         {
384                                                 if(argv(2) == "reset")
385                                                 {
386                                                         bot_resetqueues();
387                                                 }
388                                                 else if(argv(2) == "setbots")
389                                                 {
390                                                         cvar_settemp("minplayers", "0");
391                                                         cvar_settemp("bot_number", argv(3));
392                                                         if(!bot_fixcount())
393                                                                 print("Sorry, could not set requested bot count\n");
394                                                 }
395                                                 else
396                                                 {
397                                                         // let's start at token 2 so we can skip sv_cmd bot_cmd
398                                                         bot = find_bot_by_number(stof(argv(2)));
399                                                         if(bot == world)
400                                                                 bot = find_bot_by_name(argv(2));
401                                                         if(bot)
402                                                                 bot_queuecommand(bot, strcat(argv(3), " ", argv(4)));
403                                                 }
404                                         }
405                                         else
406                                                 localcmd(strcat(s, "\n"));
407
408                                         ++i;
409                                 }
410                                 print(ftos(i), " commands read\n");
411                                 fclose(fh);
412                                 return;
413                         }
414                         else if(argv(1) == "help")
415                         {
416                                 if(argv(2))
417                                         bot_cmdhelp(argv(2));
418                                 else
419                                         bot_list_commands();
420                                 return;
421                         }
422                         else if(argc >= 3) // this comes last
423                         {
424                                 bot = find_bot_by_number(stof(argv(1)));
425                                 if(bot == world)
426                                         bot = find_bot_by_name(argv(1));
427                                 if(bot)
428                                 {
429                                         print(strcat("Command '", strcat(argv(2), " ", argv(3)), "' sent to bot ", bot.netname, "\n"));
430                                         bot_queuecommand(bot, strcat(argv(2), " ", argv(3)));
431                                         return;
432                                 }
433                                 else
434                                         print(strcat("Error: Can't find bot with the name or id '", argv(1),"' - Did you mistype the command?\n")); // don't return so that usage is shown
435                         }
436                         
437                 default:
438                         print("Incorrect parameters for ^2bot_cmd^7\n");
439                 case GC_REQUEST_USAGE:
440                         print("\nUsage:^3 sv_cmd bot_cmd client command [argument]\n");
441                         print("  'client' can be either the name or entity id of the bot\n");
442                         print("  For full list of commands, see bot_cmd help [command].\n");
443                         print("Examples: bot_cmd <id> cc \"say something\"\n");
444                         print("          bot_cmd <id> presskey jump\n");
445                         return;
446         }
447 }
448
449 void GameCommand_cointoss(float request, float argc)
450 {
451         entity client;
452         string result1 = (argv(2) ? strcat("^7", argv(1), "^3!\n") : "^1HEADS^3!\n");
453         string result2 = (argv(2) ? strcat("^7", argv(2), "^3!\n") : "^4TAILS^3!\n");
454         string choice = ((random() > 0.5) ? result1 : result2);
455         
456         switch(request)
457         {
458                 case GC_REQUEST_HELP:
459                         print("  ^2cointoss^7: Flip a virtual coin and give random result\n");
460                         return;
461                         
462                 case GC_REQUEST_COMMAND:
463                         FOR_EACH_CLIENT(client)
464                                 centerprint(client, strcat("^3Throwing coin... Result: ", choice));
465                         bprint(strcat("^3Throwing coin... Result: ", choice));
466                         return;
467                         
468                 default:
469                 case GC_REQUEST_USAGE:
470                         print("\nUsage:^3 sv_cmd cointoss [result1 result2]\n");
471                         print("  Where 'result1' and 'result2' are user created options.\n");
472                         return;
473         }
474 }
475
476 void GameCommand_cvar_changes(float request)
477 {
478         switch(request)
479         {
480                 case GC_REQUEST_HELP:
481                         print("  ^2cvar_changes^7: Prints a list of all changed server cvars\n");
482                         return;
483                         
484                 case GC_REQUEST_COMMAND:
485                         print(cvar_changes);
486                         return;
487                         
488                 default:
489                 case GC_REQUEST_USAGE:
490                         print("\nUsage:^3 sv_cmd cvar_changes\n");
491                         print("  No arguments required.\n");
492                         print("See also: ^2cvar_purechanges^7\n");
493                         return;
494         }
495 }
496
497 void GameCommand_cvar_purechanges(float request)
498 {
499         switch(request)
500         {
501                 case GC_REQUEST_HELP:
502                         print("  ^2cvar_purechanges^7: Prints a list of all changed gameplay cvars\n");
503                         return;
504                         
505                 case GC_REQUEST_COMMAND:
506                         print(cvar_purechanges);
507                         return;
508                         
509                 default:
510                 case GC_REQUEST_USAGE:
511                         print("\nUsage:^3 sv_cmd cvar_purechanges\n");
512                         print("  No arguments required.\n");
513                         print("See also: ^2cvar_changes^7\n");
514                         return;
515         }
516 }
517
518 void GameCommand_database(float request, float argc)
519 {
520         switch(request)
521         {
522                 case GC_REQUEST_HELP:
523                         print("  ^2database^7: Extra controls of the serverprogs database\n");
524                         return;
525                         
526                 case GC_REQUEST_COMMAND:
527                         if(argc == 3)
528                         {
529                                 if(argv(1) == "save")
530                                 {
531                                         db_save(ServerProgsDB, argv(2));
532                                         print(strcat("Copied serverprogs database to '", argv(2), "' in the data directory.\n"));
533                                         return;
534                                 }
535                                 else if(argv(1) == "dump")
536                                 {
537                                         db_dump(ServerProgsDB, argv(2));
538                                         print("DB dumped.\n"); // wtf does this do?
539                                         return;
540                                 }
541                                 else if(argv(1) == "load")
542                                 {
543                                         db_close(ServerProgsDB);
544                                         ServerProgsDB = db_load(argv(2));
545                                         print(strcat("Loaded '", argv(2), "' as new serverprogs database.\n"));
546                                         return;
547                                 }
548                         }
549                         
550                 default:
551                         print("Incorrect parameters for ^2database^7\n");
552                 case GC_REQUEST_USAGE:
553                         print("\nUsage:^3 sv_cmd database action filename\n");
554                         print("  Where 'action' is the command to complete,\n");
555                         print("  and 'filename' is what it acts upon.\n");
556                         print("  Full list of commands here: \"save, dump, load.\"\n");
557                         return;
558         }
559 }
560
561 void GameCommand_defer_clear(float request, float argc)
562 {
563         entity client;
564         float entno = stof(argv(1));
565         
566         switch(request)
567         {
568                 case GC_REQUEST_HELP:
569                         print("  ^2defer_clear^7: Clear all queued defer commands for client\n");
570                         return;
571                         
572                 case GC_REQUEST_COMMAND:
573                         if(argc == 2)
574                         {
575                                 // player_id is out of range
576                                 if((entno < 1) | (entno > maxclients)) {
577                                         print("Player ", argv(1), " doesn't exist\n");
578                                         return;
579                                 }
580                                 client = edict_num(entno);
581                                 if not(client.flags & FL_CLIENT) {
582                                         print("Player ", argv(1), " doesn't exist\n");
583                                         return;
584                                 }
585                                 if(clienttype(client) == CLIENTTYPE_BOT) {
586                                         print("Player ", argv(1), " (", client.netname, ") is a bot\n");
587                                         return;
588                                 }
589                                 stuffcmd(client, "defer clear\n");
590                                 print("defer clear stuffed to ", argv(1), " (", client.netname, ")\n");
591                                 return;
592                         }
593                 
594                 default:
595                         print("Incorrect parameters for ^2defer_clear^7\n");
596                 case GC_REQUEST_USAGE:
597                         print("\nUsage:^3 sv_cmd defer_clear clientnumber\n");
598                         print("  where 'clientnumber' is player entity number.\n");
599                         print("See also: ^2defer_clear_all^7\n");
600                         return;
601         }
602 }
603
604 void GameCommand_defer_clear_all(float request)
605 {
606         entity client;
607         float i;
608         float argc;
609         
610         switch(request)
611         {
612                 case GC_REQUEST_HELP:
613                         print("  ^2defer_clear_all^7: Clear all queued defer commands for all clients\n");
614                         return;
615                         
616                 case GC_REQUEST_COMMAND:
617                         FOR_EACH_CLIENT(client)
618                         {
619                                 argc = tokenize_console(strcat("defer_clear ", ftos(num_for_edict(client))));
620                                 GameCommand_defer_clear(GC_REQUEST_COMMAND, argc);      
621                                 ++i;
622                         }
623                         if(i) { bprint(strcat("Successfully stuffed defer clear to all clients (", ftos(i), ")\n")); } // should a message be added if no players were found? 
624                         return;
625                 
626                 default:
627                 case GC_REQUEST_USAGE:
628                         print("\nUsage:^3 sv_cmd defer_clear_all\n");
629                         print("  No arguments required.\n");
630                         print("See also: ^2defer_clear^7\n");
631                         return;
632         }
633 }
634
635 void GameCommand_delrec(float request, float argc) // UNTESTED // perhaps merge later with records and printstats and such?
636 {
637         switch(request)
638         {
639                 case GC_REQUEST_HELP:
640                         print("  ^2delrec^7: Delete race time record for a map\n");
641                         return;
642                         
643                 case GC_REQUEST_COMMAND:
644                         if(argv(1))
645                         {
646                                 if(argv(2))
647                                         race_deleteTime(argv(2), stof(argv(1)));
648                                 else
649                                         race_deleteTime(GetMapname(), stof(argv(1)));
650                                 return;
651                         }
652                         
653                 default:
654                         print("Incorrect parameters for ^2delrec^7\n");
655                 case GC_REQUEST_USAGE:
656                         print("\nUsage:^3 sv_cmd delrec ranking [map]\n");
657                         print("  'ranking' is which ranking level to clear up to, \n");
658                         print("  it will clear all records up to nth place.\n");
659                         print("  if 'map' is not provided it will use current map.\n");
660                         return;
661         }
662 }
663
664 void GameCommand_effectindexdump(float request)
665 {
666         float fh, d;
667         string s;
668         
669         switch(request)
670         {
671                 case GC_REQUEST_HELP:
672                         print("  ^2effectindexdump^7: Dump list of effects from code and effectinfo.txt\n");
673                         return;
674                         
675                 case GC_REQUEST_COMMAND:
676                         d = db_create();
677                         print("begin of effects list\n");
678                         db_put(d, "TE_GUNSHOT", "1"); print("effect TE_GUNSHOT is ", ftos(particleeffectnum("TE_GUNSHOT")), "\n");
679                         db_put(d, "TE_GUNSHOTQUAD", "1"); print("effect TE_GUNSHOTQUAD is ", ftos(particleeffectnum("TE_GUNSHOTQUAD")), "\n");
680                         db_put(d, "TE_SPIKE", "1"); print("effect TE_SPIKE is ", ftos(particleeffectnum("TE_SPIKE")), "\n");
681                         db_put(d, "TE_SPIKEQUAD", "1"); print("effect TE_SPIKEQUAD is ", ftos(particleeffectnum("TE_SPIKEQUAD")), "\n");
682                         db_put(d, "TE_SUPERSPIKE", "1"); print("effect TE_SUPERSPIKE is ", ftos(particleeffectnum("TE_SUPERSPIKE")), "\n");
683                         db_put(d, "TE_SUPERSPIKEQUAD", "1"); print("effect TE_SUPERSPIKEQUAD is ", ftos(particleeffectnum("TE_SUPERSPIKEQUAD")), "\n");
684                         db_put(d, "TE_WIZSPIKE", "1"); print("effect TE_WIZSPIKE is ", ftos(particleeffectnum("TE_WIZSPIKE")), "\n");
685                         db_put(d, "TE_KNIGHTSPIKE", "1"); print("effect TE_KNIGHTSPIKE is ", ftos(particleeffectnum("TE_KNIGHTSPIKE")), "\n");
686                         db_put(d, "TE_EXPLOSION", "1"); print("effect TE_EXPLOSION is ", ftos(particleeffectnum("TE_EXPLOSION")), "\n");
687                         db_put(d, "TE_EXPLOSIONQUAD", "1"); print("effect TE_EXPLOSIONQUAD is ", ftos(particleeffectnum("TE_EXPLOSIONQUAD")), "\n");
688                         db_put(d, "TE_TAREXPLOSION", "1"); print("effect TE_TAREXPLOSION is ", ftos(particleeffectnum("TE_TAREXPLOSION")), "\n");
689                         db_put(d, "TE_TELEPORT", "1"); print("effect TE_TELEPORT is ", ftos(particleeffectnum("TE_TELEPORT")), "\n");
690                         db_put(d, "TE_LAVASPLASH", "1"); print("effect TE_LAVASPLASH is ", ftos(particleeffectnum("TE_LAVASPLASH")), "\n");
691                         db_put(d, "TE_SMALLFLASH", "1"); print("effect TE_SMALLFLASH is ", ftos(particleeffectnum("TE_SMALLFLASH")), "\n");
692                         db_put(d, "TE_FLAMEJET", "1"); print("effect TE_FLAMEJET is ", ftos(particleeffectnum("TE_FLAMEJET")), "\n");
693                         db_put(d, "EF_FLAME", "1"); print("effect EF_FLAME is ", ftos(particleeffectnum("EF_FLAME")), "\n");
694                         db_put(d, "TE_BLOOD", "1"); print("effect TE_BLOOD is ", ftos(particleeffectnum("TE_BLOOD")), "\n");
695                         db_put(d, "TE_SPARK", "1"); print("effect TE_SPARK is ", ftos(particleeffectnum("TE_SPARK")), "\n");
696                         db_put(d, "TE_PLASMABURN", "1"); print("effect TE_PLASMABURN is ", ftos(particleeffectnum("TE_PLASMABURN")), "\n");
697                         db_put(d, "TE_TEI_G3", "1"); print("effect TE_TEI_G3 is ", ftos(particleeffectnum("TE_TEI_G3")), "\n");
698                         db_put(d, "TE_TEI_SMOKE", "1"); print("effect TE_TEI_SMOKE is ", ftos(particleeffectnum("TE_TEI_SMOKE")), "\n");
699                         db_put(d, "TE_TEI_BIGEXPLOSION", "1"); print("effect TE_TEI_BIGEXPLOSION is ", ftos(particleeffectnum("TE_TEI_BIGEXPLOSION")), "\n");
700                         db_put(d, "TE_TEI_PLASMAHIT", "1"); print("effect TE_TEI_PLASMAHIT is ", ftos(particleeffectnum("TE_TEI_PLASMAHIT")), "\n");
701                         db_put(d, "EF_STARDUST", "1"); print("effect EF_STARDUST is ", ftos(particleeffectnum("EF_STARDUST")), "\n");
702                         db_put(d, "TR_ROCKET", "1"); print("effect TR_ROCKET is ", ftos(particleeffectnum("TR_ROCKET")), "\n");
703                         db_put(d, "TR_GRENADE", "1"); print("effect TR_GRENADE is ", ftos(particleeffectnum("TR_GRENADE")), "\n");
704                         db_put(d, "TR_BLOOD", "1"); print("effect TR_BLOOD is ", ftos(particleeffectnum("TR_BLOOD")), "\n");
705                         db_put(d, "TR_WIZSPIKE", "1"); print("effect TR_WIZSPIKE is ", ftos(particleeffectnum("TR_WIZSPIKE")), "\n");
706                         db_put(d, "TR_SLIGHTBLOOD", "1"); print("effect TR_SLIGHTBLOOD is ", ftos(particleeffectnum("TR_SLIGHTBLOOD")), "\n");
707                         db_put(d, "TR_KNIGHTSPIKE", "1"); print("effect TR_KNIGHTSPIKE is ", ftos(particleeffectnum("TR_KNIGHTSPIKE")), "\n");
708                         db_put(d, "TR_VORESPIKE", "1"); print("effect TR_VORESPIKE is ", ftos(particleeffectnum("TR_VORESPIKE")), "\n");
709                         db_put(d, "TR_NEHAHRASMOKE", "1"); print("effect TR_NEHAHRASMOKE is ", ftos(particleeffectnum("TR_NEHAHRASMOKE")), "\n");
710                         db_put(d, "TR_NEXUIZPLASMA", "1"); print("effect TR_NEXUIZPLASMA is ", ftos(particleeffectnum("TR_NEXUIZPLASMA")), "\n");
711                         db_put(d, "TR_GLOWTRAIL", "1"); print("effect TR_GLOWTRAIL is ", ftos(particleeffectnum("TR_GLOWTRAIL")), "\n");
712                         db_put(d, "TR_SEEKER", "1"); print("effect TR_SEEKER is ", ftos(particleeffectnum("TR_SEEKER")), "\n");
713                         db_put(d, "SVC_PARTICLE", "1"); print("effect SVC_PARTICLE is ", ftos(particleeffectnum("SVC_PARTICLE")), "\n");
714
715                         fh = fopen("effectinfo.txt", FILE_READ);
716                         while((s = fgets(fh)))
717                         {
718                                 tokenize_console(s);
719                                 if(argv(0) == "effect")
720                                 {
721                                         if(db_get(d, argv(1)) != "1")
722                                         {
723                                                 if(particleeffectnum(argv(1)) >= 0)
724                                                         print("effect ", argv(1), " is ", ftos(particleeffectnum(argv(1))), "\n");
725                                                 db_put(d, argv(1), "1");
726                                         }
727                                 }
728                         }
729                         print("end of effects list\n");
730
731                         db_close(d);
732                         return;
733                         
734                 default:
735                 case GC_REQUEST_USAGE:
736                         print("\nUsage:^3 sv_cmd effectindexdump\n");
737                         print("  No arguments required.\n");
738                         return;
739         }
740 }
741
742 void GameCommand_extendmatchtime(float request)
743 {
744         switch(request)
745         {
746                 case GC_REQUEST_HELP:
747                         print("  ^2extendmatchtime^7: Increase the timelimit value incrementally\n");
748                         return;
749                         
750                 case GC_REQUEST_COMMAND:
751                         changematchtime(autocvar_timelimit_increment* 60, autocvar_timelimit_min*60, autocvar_timelimit_max*60);
752                         return;
753                         
754                 default:
755                 case GC_REQUEST_USAGE:
756                         print("\nUsage:^3 sv_cmd extendmatchtime\n");
757                         print("  No arguments required.\n");
758                         print("See also: ^2reducematchtime^7\n");
759                         return;
760         }
761 }
762
763 void GameCommand_find(float request, float argc)
764 {
765         entity client;
766         
767         switch(request)
768         {
769                 case GC_REQUEST_HELP:
770                         print("  ^2find^7: Search through entities for matching classname\n");
771                         return;
772                         
773                 case GC_REQUEST_COMMAND:
774                         for(client = world; (client = find(client, classname, argv(1))); )
775                                 print(etos(client), "\n");
776                         return;
777                         
778                 default:
779                         print("Incorrect parameters for ^2find^7\n");
780                 case GC_REQUEST_USAGE:
781                         print("\nUsage:^3 sv_cmd find classname\n");
782                         print("  Where 'classname' is the classname to search for.\n");
783                         return;
784         }
785 }
786
787 void GameCommand_gametype(float request, float argc)
788 {
789         string s = argv(1);
790         float t = MapInfo_Type_FromString(s), tsave = MapInfo_CurrentGametype();
791         
792         switch(request)
793         {
794                 case GC_REQUEST_HELP:
795                         print("  ^2gametype^7: Simple command to change the active gametype\n");
796                         return;
797                         
798                 case GC_REQUEST_COMMAND:
799                         if(t)
800                         {
801                                 MapInfo_SwitchGameType(t);
802                                 MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
803                                 if(MapInfo_count > 0)
804                                         bprint("Game type successfully switched to ", s, "\n");
805                                 else
806                                 {
807                                         bprint("Cannot use this game type: no map for it found\n");
808                                         MapInfo_SwitchGameType(tsave);
809                                         MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
810                                 }
811                         }
812                         else
813                                 bprint("Game type switch to ", s, " failed: this type does not exist!\n");
814                         return;
815                         
816                 default:
817                         print("Incorrect parameters for ^2gametype^7\n");
818                 case GC_REQUEST_USAGE:
819                         print("\nUsage:^3 sv_cmd gametype mode\n");
820                         print("  Where 'mode' is the gametype mode to switch to.\n");
821                         print("See also: ^2gotomap^7\n");
822                         return;
823         }
824 }
825
826 void GameCommand_gettaginfo(float request, float argc) // UNTESTED // todo: finish usage description for it (but, must first learn this shit)
827 {
828         entity tmp_entity;
829         float i;
830         vector v;
831         
832         switch(request)
833         {
834                 case GC_REQUEST_HELP:
835                         print("  ^2gettaginfo^7: Get specific information about a weapon model\n");
836                         return;
837                         
838                 case GC_REQUEST_COMMAND:
839                         if(argc >= 4)
840                         {
841                                 tmp_entity = spawn();
842                                 if(argv(1) == "w")
843                                         setmodel(tmp_entity, (nextent(world)).weaponentity.model);
844                                 else
845                                 {
846                                         precache_model(argv(1));
847                                         setmodel(tmp_entity, argv(1));
848                                 }
849                                 tmp_entity.frame = stof(argv(2));
850                                 if(substring(argv(3), 0, 1) == "#")
851                                         i = stof(substring(argv(3), 1, -1));
852                                 else
853                                         i = gettagindex(tmp_entity, argv(3));
854                                 if(i)
855                                 {
856                                         v = gettaginfo(tmp_entity, i);
857                                         print("model ", tmp_entity.model, " frame ", ftos(tmp_entity.frame), " tag ", gettaginfo_name);
858                                         print(" index ", ftos(i), " parent ", ftos(gettaginfo_parent), "\n");
859                                         print(" vector = ", ftos(v_x), " ", ftos(v_y), " ", ftos(v_z), "\n");
860                                         print(" offset = ", ftos(gettaginfo_offset_x), " ", ftos(gettaginfo_offset_y), " ", ftos(gettaginfo_offset_z), "\n");
861                                         print(" forward = ", ftos(gettaginfo_forward_x), " ", ftos(gettaginfo_forward_y), " ", ftos(gettaginfo_forward_z), "\n");
862                                         print(" right = ", ftos(gettaginfo_right_x), " ", ftos(gettaginfo_right_y), " ", ftos(gettaginfo_right_z), "\n");
863                                         print(" up = ", ftos(gettaginfo_up_x), " ", ftos(gettaginfo_up_y), " ", ftos(gettaginfo_up_z), "\n");
864                                         if(argc >= 6)
865                                         {
866                                                 v_y = -v_y;
867                                                 localcmd(strcat(argv(4), vtos(v), argv(5), "\n"));
868                                         }
869                                 }
870                                 else
871                                         print("bone not found\n");
872                                         
873                                 remove(tmp_entity);
874                                 return;
875                         }
876                         
877                 default:
878                         print("Incorrect parameters for ^2gettaginfo^7\n");
879                 case GC_REQUEST_USAGE:
880                         print("\nUsage:^3 sv_cmd gettaginfo\n");
881                         print("  FIXME: Arguments currently unknown\n");
882                         print("See also: ^2bbox^7\n");
883                         return;
884         }
885 }
886
887 void GameCommand_gotomap(float request, float argc)
888 {
889         switch(request)
890         {
891                 case GC_REQUEST_HELP:
892                         print("  ^2gotomap^7: Simple command to switch to another map\n");
893                         return;
894                         
895                 case GC_REQUEST_COMMAND:
896                         if(argc == 2)
897                         {
898                                 print(GotoMap(argv(1)), "\n");
899                                 return;
900                         }
901                         
902                 default:
903                         print("Incorrect parameters for ^2gotomap^7\n");
904                 case GC_REQUEST_USAGE:
905                         print("\nUsage:^3 sv_cmd gotomap map\n");
906                         print("  Where 'map' is the *.bsp file to change to.\n");
907                         print("See also: ^2gametype^7\n");
908                         return;
909         }
910 }
911
912 void GameCommand_ladder(float request)
913 {
914         switch(request)
915         {
916                 case GC_REQUEST_HELP:
917                         print("  ^2ladder^7: Get information about top players if supported\n");
918                         return;
919                         
920                 case GC_REQUEST_COMMAND:
921                         print(ladder_reply);
922                         return;
923                         
924                 default:
925                 case GC_REQUEST_USAGE:
926                         print("\nUsage:^3 sv_cmd ladder\n");
927                         print("  No arguments required.\n");
928                         return;
929         }
930 }
931
932 void GameCommand_lockteams(float request)
933 {
934         switch(request)
935         {
936                 case GC_REQUEST_HELP:
937                         print("  ^2lockteams^7: Disable the ability for players to switch or enter teams\n");
938                         return;
939                         
940                 case GC_REQUEST_COMMAND:
941                         if(teamplay)
942                         {
943                                 lockteams = 1;
944                                 bprint("^1The teams are now locked.\n");
945                         }
946                         else
947                                 bprint("That command can only be used in a team-based gamemode.\n");
948                         return;
949                         
950                 default:
951                 case GC_REQUEST_USAGE:
952                         print("\nUsage:^3 sv_cmd lockteams\n");
953                         print("  No arguments required.\n");
954                         print("See also: ^2unlockteams^7\n");
955                         return;
956         }
957 }
958
959 void GameCommand_make_mapinfo(float request) // UNTESTED
960 {
961         entity tmp_entity;
962         
963         switch(request)
964         {
965                 case GC_REQUEST_HELP:
966                         print("  ^2make_mapinfo^7: Automatically rebuild mapinfo files\n");
967                         return;
968                         
969                 case GC_REQUEST_COMMAND: 
970                         tmp_entity = spawn();
971                         tmp_entity.classname = "make_mapinfo";
972                         tmp_entity.think = make_mapinfo_Think;
973                         tmp_entity.nextthink = time; // this sucks... todo: re-write this -- Use initializeentity later
974                         MapInfo_Enumerate();
975                         return;
976                         
977                 default:
978                 case GC_REQUEST_USAGE:
979                         print("\nUsage:^3 sv_cmd make_mapinfo\n");
980                         print("  No arguments required.\n");
981                         return;
982         }
983 }
984
985 void GameCommand_modelbug(float request) // UNTESTED // is this even needed anymore? 
986 {
987         switch(request)
988         {
989                 case GC_REQUEST_HELP:
990                         print("  ^2modelbug^7: foobar\n");
991                         return;
992                         
993                 case GC_REQUEST_COMMAND:
994                         modelbug();
995                         return;
996                         
997                 default:
998                 case GC_REQUEST_USAGE:
999                         print("\nUsage:^3 sv_cmd modelbug\n");
1000                         print("  No arguments required.\n");
1001                         return;
1002         }
1003 }
1004
1005 void GameCommand_moveplayer(float request, float argc)
1006 {
1007         entity client;
1008         
1009         string targets = strreplace(",", " ", argv(1));
1010         string original_targets = strreplace(" ", ", ", targets);
1011         string destination = argv(2);
1012         string notify = argv(3);
1013         
1014         string successful, t;
1015         
1016         switch(request)
1017         {
1018                 case GC_REQUEST_HELP:
1019                         print("  ^2moveplayer^7: Change the team/status of a player\n");
1020                         return;
1021                         
1022                 case GC_REQUEST_COMMAND:
1023                         // lets see if the target(s) even actually exist.
1024                         if((targets) && (destination))
1025                         { 
1026                                 for(;targets;)
1027                                 {
1028                                         t = car(targets); targets = cdr(targets);
1029
1030                                         // Check to see if the player is a valid target
1031                                         if((GetFilteredNumber(t) < 1) || (GetFilteredNumber(t) > maxclients)) // player_id is out of range
1032                                         {
1033                                                 print("Player ", ftos(GetFilteredNumber(t)), " doesn't exist (out of range)", (targets ? ", skipping to next player.\n" : ".\n"));
1034                                                 continue; 
1035                                         }
1036                                         client = edict_num(GetFilteredNumber(t));
1037                                         if not(client.flags & FL_CLIENT) // player entity is not a client
1038                                         {
1039                                                 print("Player ", ftos(GetFilteredNumber(t)), " doesn't exist (not a client)", (targets ? ", skipping to next player.\n" : ".\n"));
1040                                                 continue;
1041                                         }
1042                                         
1043                                         // Where are we putting this player?
1044                                         if(destination == "spec" || destination == "spectator") 
1045                                         {
1046                                                 if(client.classname != "spectator" && client.classname != "observer")
1047                                                 {
1048                                                         self = client;
1049                                                         PutObserverInServer();
1050                                                         
1051                                                         successful = strcat(successful, (successful ? ", " : ""), client.netname);
1052                                                 }
1053                                                 else
1054                                                 {
1055                                                         print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already spectating.\n");
1056                                                 }
1057                                                 continue;
1058                                         }
1059                                         else
1060                                         {
1061                                                 if(client.classname != "spectator" && client.classname != "observer")
1062                                                 {
1063                                                         if(teamplay)
1064                                                         {
1065                                                                 // set up
1066                                                                 float team_color;
1067                                                                 float save = client.team_forced;
1068                                                                 client.team_forced = 0;
1069
1070                                                                 // find the team to move the player to
1071                                                                 team_color = ColourToNumber(destination);
1072                                                                 if(team_color == client.team) // already on the destination team
1073                                                                 {
1074                                                                         // keep the forcing undone
1075                                                                         print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already on the ", ColoredTeamName(client.team), (targets ? ", skipping to next player.\n" : ".\n"));
1076                                                                         continue;
1077                                                                 } 
1078                                                                 else if(team_color == 0)  // auto team
1079                                                                 {
1080                                                                         team_color = NumberToTeamNumber(FindSmallestTeam(client, FALSE));
1081                                                                 }
1082                                                                 else
1083                                                                 {
1084                                                                         CheckAllowedTeams(client);
1085                                                                 }
1086                                                                 client.team_forced = save;
1087                                                                 
1088                                                                 // Check to see if the destination team is even available
1089                                                                 switch(team_color) 
1090                                                                 {
1091                                                                         case COLOR_TEAM1: if(c1 == -1) { print("Sorry, can't move player to red team if it doesn't exist.\n"); return; } break;
1092                                                                         case COLOR_TEAM2: if(c2 == -1) { print("Sorry, can't move player to blue team if it doesn't exist.\n"); return; } break;
1093                                                                         case COLOR_TEAM3: if(c3 == -1) { print("Sorry, can't move player to yellow team if it doesn't exist.\n"); return; } break;
1094                                                                         case COLOR_TEAM4: if(c4 == -1) { print("Sorry, can't move player to pink team if it doesn't exist.\n"); return; } break;
1095                                                                         
1096                                                                         default: print("Sorry, can't move player here if team ", destination, " doesn't exist.\n"); return;
1097                                                                 }
1098                                                                 
1099                                                                 // If so, lets continue and finally move the player
1100                                                                 client.team_forced = 0;
1101                                                                 MoveToTeam(client, team_color, 6, stof(notify));
1102                                                                 successful = strcat(successful, (successful ? ", " : ""), client.netname);
1103                                                                 print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") has been moved to the ", ColoredTeamName(team_color), ".\n");
1104                                                                 continue;
1105                                                         }
1106                                                         else
1107                                                         {
1108                                                                 print("Can't change teams when currently not playing a team game.\n");
1109                                                                 return;
1110                                                         }
1111                                                 }
1112                                                 else
1113                                                 {
1114                                                         print("Can't change teams if the player isn't in the game.\n"); // well technically we could, but should we allow that? :P 
1115                                                         return;
1116                                                 }
1117                                         }
1118                                 }
1119                                 
1120                                 if(successful)
1121                                         print("Successfully moved players ", successful, " to destination ", destination, ".\n");
1122                                 else
1123                                         print("No players given (", original_targets, ") are able to move.\n");
1124                                         
1125                                 return; // still correct parameters so return to avoid usage print
1126                         }
1127                         
1128                 default:
1129                         print("Incorrect parameters for ^2moveplayer^7\n");
1130                 case GC_REQUEST_USAGE:
1131                         print("\nUsage:^3 sv_cmd moveplayer clientnumbers destination [notify]\n");
1132                         print("  'clientnumbers' is a list (separated by commas) of player entity ID's\n");
1133                         print("  'destination' is what to send the player to, be it team or spectating\n");
1134                         print("  Full list of destinations here: \"spec, spectator, red, blue, yellow, pink, auto.\"\n");
1135                         print("  'notify' is whether or not to send messages notifying of the move. Detail below.\n");
1136                         print("    0 (00) automove centerprint, admin message; 1 (01) automove centerprint, no admin message\n");
1137                         print("    2 (10) no centerprint, admin message; 3 (11) no centerprint, no admin message\n");
1138                         print("Examples: moveplayer 1,3,5 red 3\n");
1139                         print("          moveplayer 2 spec \n");
1140                         print("See also: ^2allspec^7\n");
1141                         return;
1142         }
1143 }
1144
1145 void GameCommand_nospectators(float request)
1146 {
1147         switch(request)
1148         {
1149                 case GC_REQUEST_HELP:
1150                         print("  ^2nospectators^7: Automatically remove spectators from a match\n");
1151                         return;
1152                         
1153                 case GC_REQUEST_COMMAND:
1154                         blockSpectators = 1;
1155                         entity plr;
1156                         FOR_EACH_CLIENT(plr) //give every spectator <g_maxplayers_spectator_blocktime> seconds time to become a player
1157                         {
1158                                 if(plr.classname == "spectator" || plr.classname == "observer")
1159                                 {
1160                                         plr.spectatortime = time;
1161                                         sprint(plr, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
1162                                 }
1163                         }
1164                         bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds!\n"));
1165                         return;
1166                         
1167                 default:
1168                 case GC_REQUEST_USAGE:
1169                         print("\nUsage:^3 sv_cmd nospectators\n");
1170                         print("  No arguments required.\n");
1171                         return;
1172         }
1173 }
1174
1175 void GameCommand_onslaught_updatelinks(float request) // UNTESTED // should this be here? Perhaps some mutatorhook call instead....
1176 {
1177         switch(request)
1178         {
1179                 case GC_REQUEST_HELP:
1180                         print("  ^2onslaught_updatelinks^7: Refresh link status for onslaught\n");
1181                         return;
1182                         
1183                 case GC_REQUEST_COMMAND:
1184                         onslaught_updatelinks();
1185                         print("ONS links updated\n");
1186                         return;
1187                         
1188                 default:
1189                 case GC_REQUEST_USAGE:
1190                         print("\nUsage:^3 sv_cmd onslaught_updatelinks\n");
1191                         print("  No arguments required.\n");
1192                         return;
1193         }
1194 }
1195
1196 void GameCommand_playerdemo(float request, float argc) // UNTESTED // TODO: change the if statements for sub arguments to switches
1197 {
1198         entity client;
1199         float i, n, entno;
1200         string s;
1201         
1202         switch(request)
1203         {
1204                 case GC_REQUEST_HELP:
1205                         print("  ^2playerdemo^7: Control the ability to save demos of players\n");
1206                         return;
1207                         
1208                 case GC_REQUEST_COMMAND:
1209                         if(argv(1) == "read")
1210                         {
1211                                 // TODO: Create a general command for looking this up, save a lot of space everywhere in this file
1212                                 entno = stof(argv(2));
1213                                 if((entno < 1) | (entno > maxclients)) {
1214                                         print("Player ", argv(2), " doesn't exist\n");
1215                                         return;
1216                                 }
1217                                 client = edict_num(entno);
1218                                 if(clienttype(client) != CLIENTTYPE_BOT) {
1219                                         print("Player ", client.netname, " is not a bot\n");
1220                                         return;
1221                                 }
1222                                 self = client;
1223                                 playerdemo_open_read(argv(3));
1224                                 return;
1225                         }
1226                         else if(argv(1) == "write")
1227                         {
1228                                 entno = stof(argv(2));
1229                                 if((entno < 1) | (entno > maxclients)) {
1230                                         print("Player ", argv(2), " doesn't exist\n");
1231                                         return;
1232                                 }
1233                                 client = edict_num(entno);
1234                                 self = client;
1235                                 playerdemo_open_write(argv(3));
1236                                 return;
1237                         }
1238                         else if(argv(1) == "auto_read_and_write")
1239                         {
1240                                 s = argv(2);
1241                                 n = stof(argv(3));
1242                                 cvar_set("bot_number", ftos(n));
1243                                 localcmd("wait; wait; wait\n");
1244                                 for(i = 0; i < n; ++i)
1245                                         localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", s, ftos(i+1), "\n");
1246                                 localcmd("sv_cmd playerdemo write 1 ", ftos(n+1), "\n");
1247                                 return;
1248                         }
1249                         else if(argv(1) == "auto_read")
1250                         {
1251                                 s = argv(2);
1252                                 n = stof(argv(3));
1253                                 cvar_set("bot_number", ftos(n));
1254                                 localcmd("wait; wait; wait\n");
1255                                 for(i = 0; i < n; ++i)
1256                                         localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", s, ftos(i+1), "\n");
1257                                 return;
1258                         }
1259                         return;
1260                         
1261                 default:
1262                         print("Incorrect parameters for ^2radarmap^7\n");
1263                 case GC_REQUEST_USAGE:
1264                         print("\nUsage:^3 sv_cmd \n");
1265                         print("  FIXME: Arguments currently unknown\n");
1266                         return;
1267         }
1268 }
1269
1270 void GameCommand_printstats(float request)
1271 {
1272         switch(request)
1273         {
1274                 case GC_REQUEST_HELP:
1275                         print("  ^2printstats^7: foobar\n");
1276                         return;
1277                         
1278                 case GC_REQUEST_COMMAND:
1279                         DumpStats(FALSE);
1280                         print("stats dumped.\n");
1281                         return;
1282                         
1283                 default:
1284                 case GC_REQUEST_USAGE:
1285                         print("\nUsage:^3 sv_cmd printstats\n");
1286                         print("  No arguments required.\n");
1287                         return;
1288         }
1289 }
1290
1291 void GameCommand_radarmap(float request, float argc)
1292 {
1293         switch(request)
1294         {
1295                 case GC_REQUEST_HELP:
1296                         print("  ^2radarmap^7: Generate a radar image of the map\n");
1297                         return;
1298                         
1299                 case GC_REQUEST_COMMAND:
1300                         if(RadarMap_Make(argc))
1301                                 return;
1302                         
1303                 default:
1304                         print("Incorrect parameters for ^2radarmap^7\n");
1305                 case GC_REQUEST_USAGE:
1306                         print("\nUsage:^3 sv_cmd radarmap [--force] [--loop] [--quit] [--block | --trace | --sample | --lineblock] [--sharpen N] [--res W H] [--qual Q]\n");
1307                         print("  The quality factor Q is roughly proportional to the time taken.\n");
1308                         print("  trace supports no quality factor; its result should look like --block with infinite quality factor.\n");
1309                         return;
1310         }
1311 }
1312
1313 void GameCommand_rankings(float request) // this is OLD.... jeez.
1314 {
1315         switch(request)
1316         {
1317                 case GC_REQUEST_HELP:
1318                         print("  ^2rankings^7: Print information about rankings\n");
1319                         return;
1320                         
1321                 case GC_REQUEST_COMMAND:
1322                         strunzone(rankings_reply);
1323                         rankings_reply = strzone(getrankings());
1324                         print(rankings_reply);
1325                         return;
1326                         
1327                 default:
1328                 case GC_REQUEST_USAGE:
1329                         print("\nUsage:^3 sv_cmd rankings\n");
1330                         print("  No arguments required.\n");
1331                         return;
1332         }
1333 }
1334
1335 void GameCommand_records(float request)
1336 {
1337         float i;
1338         
1339         switch(request)
1340         {
1341                 case GC_REQUEST_HELP:
1342                         print("  ^2records^7: List top 10 records for the current map\n");
1343                         return;
1344                         
1345                 case GC_REQUEST_COMMAND:
1346                         for (i = 0; i < 10; ++i)
1347                                 print(records_reply[i]);
1348                         return;
1349                         
1350                 default:
1351                 case GC_REQUEST_USAGE:
1352                         print("\nUsage:^3 sv_cmd records\n");
1353                         print("  No arguments required.\n");
1354                         return;
1355         }
1356 }
1357
1358 void GameCommand_reducematchtime(float request)
1359 {
1360         switch(request)
1361         {
1362                 case GC_REQUEST_HELP:
1363                         print("  ^2reducematchtime^7: Decrease the timelimit value incrementally\n");
1364                         return;
1365                         
1366                 case GC_REQUEST_COMMAND:
1367                         changematchtime(autocvar_timelimit_decrement*-60, autocvar_timelimit_min*60, autocvar_timelimit_max*60);
1368                         return;
1369                         
1370                 default:
1371                 case GC_REQUEST_USAGE:
1372                         print("\nUsage:^3 sv_cmd reducematchtime\n");
1373                         print("  No arguments required.\n");
1374                         print("See also: ^2extendmatchtime^7\n");
1375                         return;
1376         }
1377 }
1378
1379 void GameCommand_setbots(float request, float argc)
1380 {
1381         switch(request)
1382         {
1383                 case GC_REQUEST_HELP:
1384                         print("  ^2setbots^7: Change the values of bot_number and minplayers immediately to change the bot count\n");
1385                         return;
1386                         
1387                 case GC_REQUEST_COMMAND:
1388                         if(argc >= 3 && argv(1) == "setbots")
1389                         {
1390                                 cvar_settemp("minplayers", "0");
1391                                 cvar_settemp("bot_number", argv(2));
1392                                 bot_fixcount();
1393                                 return;
1394                         }
1395                         
1396                 default:
1397                 case GC_REQUEST_USAGE:
1398                         print("\nUsage:^3 sv_cmd setbots botnumber\n");
1399                         print("  Where 'botnumber' is the amount of bots to set bot_number cvar to.\n");
1400                         print("See also: ^2bot_cmd^7\n");
1401                         return;
1402         }
1403 }
1404
1405 void GameCommand_stuffto(float request, float argc)
1406 {
1407         // This... is a fairly dangerous and powerful command... - It allows any arguments to be sent to a client via rcon.
1408         // Because of this, it is disabled by default and must be enabled by the server owner when doing compilation. That way,
1409         // we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument.
1410         
1411         entity client;
1412         float entno;
1413         
1414         #ifdef STUFFTO_ENABLED
1415         switch(request)
1416         {
1417                 case GC_REQUEST_HELP:
1418                         print("  ^2stuffto^7: Send a command to be executed on a client\n");
1419                         return;
1420                         
1421                 case GC_REQUEST_COMMAND:
1422                         if(argc == 3)
1423                         {
1424                                 entno = stof(argv(1));
1425                                 client = world;
1426                                 if(entno <= maxclients)
1427                                         client = edict_num(entno);
1428                                 if(client.flags & FL_CLIENT)
1429                                 {
1430                                         stuffcmd(client, strcat("\n", argv(2), "\n"));
1431                                         print(strcat("Command: \"", argv(2), "\" sent to ", client.netname, " (", argv(1) ,").\n"));
1432                                 }
1433                                 else
1434                                         print(strcat("Client (", argv(1) ,") not found.\n"));
1435                                 
1436                                 return;
1437                         }
1438                         
1439                 default:
1440                         print("Incorrect parameters for ^2stuffto^7\n");
1441                 case GC_REQUEST_USAGE:
1442                         print("\nUsage:^3 sv_cmd stuffto clientnumber command\n");
1443                         print("  FIXME: Arguments currently unknown\n");
1444                         return;
1445         }
1446         #else // give the response for missing command to fake them out ;3
1447         if(request == GC_REQUEST_COMMAND)
1448         {
1449                 print("Invalid command. For a list of supported commands, try sv_cmd help.\n");
1450                 return;
1451         }
1452         #endif
1453 }
1454
1455 void GameCommand_teamstatus(float request)
1456 {
1457         switch(request)
1458         {
1459                 case GC_REQUEST_HELP:
1460                         print("  ^2teamstatus^7: Show information about player and team scores\n");
1461                         return;
1462                         
1463                 case GC_REQUEST_COMMAND:
1464                         Score_NicePrint(world);
1465                         return;
1466                         
1467                 default:
1468                 case GC_REQUEST_USAGE:
1469                         print("\nUsage:^3 sv_cmd teamstatus\n");
1470                         print("  No arguments required.\n");
1471                         return;
1472         }
1473 }
1474
1475 void GameCommand_time(float request)
1476 {
1477         switch(request)
1478         {
1479                 case GC_REQUEST_HELP:
1480                         print("  ^2time^7: Print different formats/readouts of time\n");
1481                         return;
1482                         
1483                 case GC_REQUEST_COMMAND:
1484                         print("time = ", ftos(time), "\n");
1485                         print("frame start = ", ftos(gettime(GETTIME_FRAMESTART)), "\n");
1486                         print("realtime = ", ftos(gettime(GETTIME_REALTIME)), "\n");
1487                         print("hires = ", ftos(gettime(GETTIME_HIRES)), "\n");
1488                         print("uptime = ", ftos(gettime(GETTIME_UPTIME)), "\n");
1489                         print("localtime = ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"); // FIXME: Why is strftime broken? is engine problem, I think.
1490                         print("gmtime = ", strftime(FALSE, "%a %b %e %H:%M:%S %Z %Y"), "\n");
1491                         return;
1492                         
1493                 default:
1494                 case GC_REQUEST_USAGE:
1495                         print("\nUsage:^3 sv_cmd time\n");
1496                         print("  No arguments required.\n");
1497                         return;
1498         }
1499 }
1500
1501 void GameCommand_trace(float request, float argc)
1502 {
1503         entity e;
1504         vector org, delta, start, end, p, q, q0, pos, vv, dv;
1505         float i, f, safe, unsafe, dq, dqf;
1506         
1507         // TODO: Clean up all of these variables and merge the code below to use only a few
1508                                                 
1509         switch(request)
1510         {
1511                 case GC_REQUEST_HELP:
1512                         print("  ^2trace^7: Various debugging tools with tracing\n");
1513                         return;
1514                         
1515                 case GC_REQUEST_COMMAND:
1516                         switch(argv(1))
1517                         {
1518                                 case "debug":
1519                                         print("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.\n");
1520                                         for(;;)
1521                                         {
1522                                                 org = world.mins;
1523                                                 delta = world.maxs - world.mins;
1524
1525                                                 start_x = org_x + random() * delta_x;
1526                                                 start_y = org_y + random() * delta_y;
1527                                                 start_z = org_z + random() * delta_z;
1528
1529                                                 end_x = org_x + random() * delta_x;
1530                                                 end_y = org_y + random() * delta_y;
1531                                                 end_z = org_z + random() * delta_z;
1532
1533                                                 start = stov(vtos(start));
1534                                                 end = stov(vtos(end));
1535
1536                                                 tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world);
1537                                                 if(!trace_startsolid)
1538                                                 {
1539                                                         p = trace_endpos;
1540                                                         tracebox(p, PL_MIN, PL_MAX, p, MOVE_NOMONSTERS, world);
1541                                                         if(trace_startsolid || trace_fraction == 1)
1542                                                         {
1543                                                                 rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid
1544                                                                 tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world);
1545                                                                 tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world);
1546
1547                                                                 if(trace_startsolid)
1548                                                                 {
1549                                                                         // how much do we need to back off?
1550                                                                         safe = 1;
1551                                                                         unsafe = 0;
1552                                                                         for(;;)
1553                                                                         {
1554                                                                                 pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5);
1555                                                                                 tracebox(pos, PL_MIN, PL_MAX, pos, MOVE_NOMONSTERS, world);
1556                                                                                 if(trace_startsolid)
1557                                                                                 {
1558                                                                                         if((safe + unsafe) * 0.5 == unsafe)
1559                                                                                                 break;
1560                                                                                         unsafe = (safe + unsafe) * 0.5;
1561                                                                                 }
1562                                                                                 else
1563                                                                                 {
1564                                                                                         if((safe + unsafe) * 0.5 == safe)
1565                                                                                                 break;
1566                                                                                         safe = (safe + unsafe) * 0.5;
1567                                                                                 }
1568                                                                         }
1569
1570                                                                         print("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu\n");
1571                                                                         print("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu\n");
1572
1573                                                                         tracebox(p, PL_MIN + '0.1 0.1 0.1', PL_MAX - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, world);
1574                                                                         if(trace_startsolid)
1575                                                                                 print("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n");
1576                                                                         else
1577                                                                                 print("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n");
1578                                                                         break;
1579                                                                 }
1580
1581                                                                 q0 = p;
1582                                                                 dq = 0;
1583                                                                 dqf = 1;
1584                                                                 for(;;)
1585                                                                 {
1586                                                                         q = p + normalize(end - p) * (dq + dqf);
1587                                                                         if(q == q0)
1588                                                                                 break;
1589                                                                         tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world);
1590                                                                         if(trace_startsolid)
1591                                                                                 error("THIS ONE cannot happen");
1592                                                                         if(trace_fraction > 0)
1593                                                                                 dq += dqf * trace_fraction;
1594                                                                         dqf *= 0.5;
1595                                                                         q0 = q;
1596                                                                 }
1597                                                                 if(dq > 0)
1598                                                                 {
1599                                                                         print("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n");
1600                                                                         print("could go ", ftos(dq), " units further to ", vtos(q), "\n");
1601                                                                         break;
1602                                                                 }
1603                                                         }
1604                                                 }
1605                                         }
1606                                         return;
1607                                         
1608                                 case "debug2":
1609                                         e = nextent(world);
1610                                         tracebox(e.origin + '0 0 32', e.mins, e.maxs, e.origin + '0 0 -1024', MOVE_NORMAL, e);
1611                                         vv = trace_endpos;
1612                                         if(trace_fraction == 1)
1613                                         {
1614                                                 print("not above ground, aborting\n");
1615                                                 return;
1616                                         }
1617                                         f = 0;
1618                                         for(i = 0; i < 100000; ++i)
1619                                         {
1620                                                 dv = randomvec();
1621                                                 if(dv_z > 0)
1622                                                         dv = -1 * dv;
1623                                                 tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e);
1624                                                 if(trace_startsolid)
1625                                                         print("bug 1\n");
1626                                                 if(trace_fraction == 1)
1627                                                 if(dv_z < f)
1628                                                 {
1629                                                         print("bug 2: ", ftos(dv_x), " ", ftos(dv_y), " ", ftos(dv_z));
1630                                                         print(" (", ftos(asin(dv_z / vlen(dv)) * 180 / M_PI), " degrees)\n");
1631                                                         f = dv_z;
1632                                                 }
1633                                         }
1634                                         print("highest possible dist: ", ftos(f), "\n");
1635                                         return;
1636                                 
1637                                 case "walk":
1638                                         if(argc == 3)
1639                                         {
1640                                                 e = nextent(world);
1641                                                 if(tracewalk(e, stov(argv(1)), e.mins, e.maxs, stov(argv(2)), MOVE_NORMAL))
1642                                                         print("can walk\n");
1643                                                 else
1644                                                         print("cannot walk\n");
1645                                                 return;
1646                                         }
1647                                                 
1648                                 case "showline":
1649                                         if(argc == 3)
1650                                         {
1651                                                 vv = stov(argv(1));
1652                                                 dv = stov(argv(2));
1653                                                 traceline(vv, dv, MOVE_NORMAL, world);
1654                                                 trailparticles(world, particleeffectnum("TR_NEXUIZPLASMA"), vv, trace_endpos);
1655                                                 trailparticles(world, particleeffectnum("TR_CRYLINKPLASMA"), trace_endpos, dv);
1656                                                 return;
1657                                         }
1658                                         
1659                                 // no default case, just go straight to "invalid arguments"
1660                         }
1661                         
1662                 default:
1663                 case GC_REQUEST_USAGE:
1664                         print("\nUsage:^3 sv_cmd trace command [arguments]\n");
1665                         print("  FIXME: Arguments currently unknown\n");
1666                         return;
1667         }
1668 }
1669
1670 void GameCommand_unlockteams(float request)
1671 {
1672         switch(request)
1673         {
1674                 case GC_REQUEST_HELP:
1675                         print("  ^2unlockteams^7: Enable the ability for players to switch or enter teams\n");
1676                         return;
1677                         
1678                 case GC_REQUEST_COMMAND:
1679                         if(teamplay)
1680                         {
1681                                 lockteams = 0;
1682                                 bprint("^1The teams are now unlocked.\n");
1683                         }
1684                         else
1685                                 bprint("That command can only be used in a team-based gamemode.\n");
1686                         return;
1687                         
1688                 default:
1689                 case GC_REQUEST_USAGE:
1690                         print("\nUsage:^3 sv_cmd unlockteams\n");
1691                         print("  No arguments required.\n");
1692                         print("See also: ^2lockteams^7\n");
1693                         return;
1694         }
1695 }
1696
1697 void GameCommand_warp(float request, float argc)
1698 {
1699         switch (request)
1700         {
1701                 case GC_REQUEST_HELP:
1702                         print("  ^2warp^7: Choose different level in campaign\n");
1703                         return;
1704                 
1705                 case GC_REQUEST_COMMAND:
1706                         if(autocvar_g_campaign)
1707                         {
1708                                 
1709                                 if(argc >= 2)
1710                                 {
1711                                         CampaignLevelWarp(stof(argv(1)));
1712                                         print("Successfully warped to campaign level ", stof(argv(1)), ".\n");
1713                                 }       
1714                                 else
1715                                 {
1716                                         CampaignLevelWarp(-1);
1717                                         print("Successfully warped to next campaign level.\n");
1718                                 }
1719                         }
1720                         else
1721                                 print("Not in campaign, can't level warp\n");
1722                         return;
1723                 
1724                 default:
1725                 case GC_REQUEST_USAGE:
1726                         print("\nUsage:^3 sv_cmd level\n");
1727                         print("  'level' is the level to change campaign mode to.\n");
1728                         return;
1729         }
1730 }
1731
1732
1733 // =========================================
1734 //  Main Function Called By Engine (sv_cmd)
1735 // =========================================
1736 // If this function exists, game code handles gamecommand instead of the engine code.
1737
1738 void GameCommand(string command)
1739 {
1740         // ===== TODO list =====
1741         // find all FIXME's and TODO'S and UNTESTED'S and finish them :P
1742
1743         float search_request_type;
1744         float argc = tokenize_console(command);
1745
1746         if(strtolower(argv(0)) == "help") 
1747         {
1748                 if(argc == 1) 
1749                 {
1750                         print("\nUsage:^3 sv_cmd COMMAND...^7, where possible commands are:\n");
1751                         GameCommand_adminmsg(GC_REQUEST_HELP, 0);
1752                         GameCommand_allready(GC_REQUEST_HELP);
1753                         GameCommand_allspec(GC_REQUEST_HELP, 0);
1754                         GameCommand_anticheat(GC_REQUEST_HELP, 0);
1755                         GameCommand_bbox(GC_REQUEST_HELP);
1756                         GameCommand_bot_cmd(GC_REQUEST_HELP, 0);
1757                         GameCommand_cointoss(GC_REQUEST_HELP, 0);
1758                         GameCommand_cvar_changes(GC_REQUEST_HELP);
1759                         GameCommand_cvar_purechanges(GC_REQUEST_HELP);
1760                         GameCommand_database(GC_REQUEST_HELP, 0);
1761                         GameCommand_defer_clear(GC_REQUEST_HELP, 0);
1762                         GameCommand_defer_clear_all(GC_REQUEST_HELP);
1763                         GameCommand_delrec(GC_REQUEST_HELP, 0);
1764                         GameCommand_effectindexdump(GC_REQUEST_HELP);
1765                         GameCommand_extendmatchtime(GC_REQUEST_HELP);
1766                         GameCommand_find(GC_REQUEST_HELP, 0);
1767                         GameCommand_gametype(GC_REQUEST_HELP, 0);
1768                         GameCommand_gettaginfo(GC_REQUEST_HELP, 0);
1769                         GameCommand_gotomap(GC_REQUEST_HELP, 0);
1770                         GameCommand_ladder(GC_REQUEST_HELP);
1771                         GameCommand_lockteams(GC_REQUEST_HELP);
1772                         GameCommand_make_mapinfo(GC_REQUEST_HELP);
1773                         GameCommand_modelbug(GC_REQUEST_HELP);
1774                         GameCommand_moveplayer(GC_REQUEST_HELP, 0);
1775                         GameCommand_nospectators(GC_REQUEST_HELP);
1776                         GameCommand_onslaught_updatelinks(GC_REQUEST_HELP);
1777                         GameCommand_playerdemo(GC_REQUEST_HELP, 0);
1778                         GameCommand_printstats(GC_REQUEST_HELP);
1779                         GameCommand_radarmap(GC_REQUEST_HELP, 0);
1780                         GameCommand_rankings(GC_REQUEST_HELP);
1781                         GameCommand_records(GC_REQUEST_HELP);
1782                         GameCommand_reducematchtime(GC_REQUEST_HELP);
1783                         GameCommand_setbots(GC_REQUEST_HELP, 0);
1784                         GameCommand_stuffto(GC_REQUEST_HELP, 0);
1785                         GameCommand_teamstatus(GC_REQUEST_HELP);
1786                         GameCommand_time(GC_REQUEST_HELP);
1787                         GameCommand_trace(GC_REQUEST_HELP, 0);
1788                         GameCommand_unlockteams(GC_REQUEST_HELP);
1789                         GameCommand_warp(GC_REQUEST_HELP, 0);
1790                         GameCommand_Vote("help", world);
1791                         GameCommand_Ban("help");
1792                         GameCommand_Generic("help");
1793                         print("For help about specific commands, type sv_cmd help COMMAND\n");
1794                         return;
1795                 } 
1796                 else
1797                         search_request_type = GC_REQUEST_USAGE; // Instead of trying to call a command, we're going to see detailed information about it
1798         } 
1799         else if(GameCommand_Vote(command, world)) 
1800         {
1801                 return; // handled by server/vote.qc 
1802         }
1803         else if(GameCommand_Ban(command)) 
1804         {
1805                 return; // handled by server/ipban.qc
1806         }
1807         else if(GameCommand_Generic(command)) 
1808         {
1809                 return; // handled by common/gamecommand.qc
1810         }
1811         else
1812                 search_request_type = GC_REQUEST_COMMAND; // continue as usual and scan for normal commands
1813                 
1814         switch(strtolower((search_request_type == GC_REQUEST_USAGE) ? argv(1) : argv(0))) // if first argument is help, then search for the second argument. Else, search for first. 
1815         {
1816                 // Do not hard code aliases for these, instead create them in defaultXonotic.cfg
1817                 // also: keep in alphabetical order, please ;)
1818                 
1819                 case "adminmsg": GameCommand_adminmsg(search_request_type, argc); break;
1820                 case "allready": GameCommand_allready(search_request_type); break;
1821                 case "allspec": GameCommand_allspec(search_request_type, argc); break;
1822                 case "anticheat": GameCommand_anticheat(search_request_type, argc); break;
1823                 case "bbox": GameCommand_bbox(search_request_type); break;
1824                 case "bot_cmd": GameCommand_bot_cmd(search_request_type, argc); break;
1825                 case "cointoss": GameCommand_cointoss(search_request_type, argc); break; 
1826                 case "cvar_changes": GameCommand_cvar_changes(search_request_type); break; 
1827                 case "cvar_purechanges": GameCommand_cvar_purechanges(search_request_type); break; 
1828                 case "database": GameCommand_database(search_request_type, argc); break;
1829                 case "defer_clear": GameCommand_defer_clear(search_request_type, argc); break;
1830                 case "defer_clear_all": GameCommand_defer_clear_all(search_request_type); break;
1831                 case "delrec": GameCommand_delrec(search_request_type, argc); break;
1832                 case "effectindexdump": GameCommand_effectindexdump(search_request_type); break;
1833                 case "extendmatchtime": GameCommand_extendmatchtime(search_request_type); break;
1834                 case "find": GameCommand_find(search_request_type, argc); break; 
1835                 case "gametype": GameCommand_gametype(search_request_type, argc); break;
1836                 case "gettaginfo": GameCommand_gettaginfo(search_request_type, argc); break;
1837                 case "gotomap": GameCommand_gotomap(search_request_type, argc); break;
1838                 case "ladder": GameCommand_ladder(search_request_type); break;
1839                 case "lockteams": GameCommand_lockteams(search_request_type); break;
1840                 case "make_mapinfo": GameCommand_make_mapinfo(search_request_type); break;
1841                 case "modelbug": GameCommand_modelbug(search_request_type); break;
1842                 case "moveplayer": GameCommand_moveplayer(search_request_type, argc); break;
1843                 case "nospectators": GameCommand_nospectators(search_request_type); break;
1844                 case "onslaught_updatelinks": GameCommand_onslaught_updatelinks(search_request_type); break;
1845                 case "playerdemo": GameCommand_playerdemo(search_request_type, argc); break;
1846                 case "printstats": GameCommand_printstats(search_request_type); break;
1847                 case "radarmap": GameCommand_radarmap(search_request_type, argc); break;
1848                 case "rankings": GameCommand_rankings(search_request_type); break;
1849                 case "records": GameCommand_records(search_request_type); break;
1850                 case "reducematchtime": GameCommand_reducematchtime(search_request_type); break;
1851                 case "setbots": GameCommand_setbots(search_request_type, argc); break;
1852                 case "stuffto": GameCommand_stuffto(search_request_type, argc); break;
1853                 case "teamstatus": GameCommand_teamstatus(search_request_type); break;
1854                 case "time": GameCommand_time(search_request_type); break;
1855                 case "trace": GameCommand_trace(search_request_type, argc); break;
1856                 case "unlockteams": GameCommand_unlockteams(search_request_type); break;
1857                 case "warp": GameCommand_warp(search_request_type, argc); break;
1858                 
1859                 default:
1860                         print("Invalid command. For a list of supported commands, try sv_cmd help.\n");
1861         }
1862 }