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