]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/command/sv_cmd.qc
Merge remote branch 'origin/master' into samual/updatecommands
[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() // Samual: 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)
98 {
99         switch(request)
100         {
101                 case CMD_REQUEST_COMMAND:
102                 {
103                         entity client;
104                         float accepted;
105                         
106                         string targets = strreplace(",", " ", argv(1));
107                         string original_targets = strreplace(" ", ", ", targets);
108                         string admin_message = argv(2);
109                         float infobartime = stof(argv(3));
110                         
111                         string successful, t;
112                         
113                         if((targets) && (admin_message))
114                         {
115                                 for(;targets;)
116                                 {
117                                         t = car(targets); targets = cdr(targets);
118                                         
119                                         // Check to see if the player is a valid target
120                                         client = GetFilteredEntity(t);
121                                         accepted = VerifyClientEntity(client, TRUE, FALSE);
122                                         
123                                         if not(accepted) 
124                                         {
125                                                 print("adminmsg: ", GetClientErrorString(accepted, t), (targets ? ", skipping to next player.\n" : ".\n")); 
126                                                 continue;
127                                         }
128                                         
129                                         // send the centerprint/console print or infomessage
130                                         if(infobartime)
131                                         {
132                                                 stuffcmd(client, sprintf("\ninfobar %f \"%s\"\n", infobartime, MakeConsoleSafe(admin_message)));
133                                         }
134                                         else
135                                         {
136                                                 centerprint(client, strcat("^3", admin_name(), ":\n^7", admin_message));
137                                                 sprint(client, strcat("\{1}\{13}^3", admin_name(), "^7: ", admin_message, "\n"));
138                                         }
139                                         
140                                         successful = strcat(successful, (successful ? ", " : ""), client.netname);
141                                         dprint("Message sent to ", client.netname, "\n");
142                                         continue;
143                                 }
144                                 
145                                 if(successful)
146                                         bprint("Successfully sent message '", admin_message, "' to ", successful, ".\n");
147                                 else
148                                         print("No players given (", original_targets, ") could recieve the message.\n");
149                                         
150                                 return;
151                         }
152                 }
153                 
154                 default:
155                         print("Incorrect parameters for ^2adminmsg^7\n");
156                 case CMD_REQUEST_USAGE:
157                 {
158                         print("\nUsage:^3 sv_cmd adminmsg clients \"message\" [infobartime]\n");
159                         print("  'clients' is a list (separated by commas) of player entity ID's or nicknames\n");
160                         print("  If infobartime is provided, the message will be sent to infobar.\n");
161                         print("  Otherwise, it will just be sent as a centerprint message.\n");
162                         print("Examples: adminmsg 2,4 \"this infomessage will last for ten seconds\" 10\n");
163                         print("          adminmsg 2,5 \"this message will be a centerprint\"\n");
164                         return;
165                 }
166         }
167 }
168
169 void GameCommand_allready(float request)
170 {
171         switch(request)
172         {
173                 case CMD_REQUEST_COMMAND:
174                 {
175                         ReadyRestart();
176                         return;
177                 }
178                         
179                 default:
180                 case CMD_REQUEST_USAGE:
181                 {
182                         print("\nUsage:^3 sv_cmd allready\n");
183                         print("  No arguments required.\n");
184                         return;
185                 }
186         }
187 }
188
189 void GameCommand_allspec(float request, float argc)
190 {       
191         switch(request)
192         {
193                 case CMD_REQUEST_COMMAND:
194                 {
195                         entity client;
196                         string reason = argv(1);
197                         float i;
198                         
199                         FOR_EACH_REALPLAYER(client)
200                         {
201                                 self = client;
202                                 PutObserverInServer();
203                                 ++i;
204                         }
205                         if(i) { bprint(strcat("Successfully forced all (", ftos(i), ") players to spectate", (reason ? strcat(" for reason: '", reason, "'") : ""), ".\n")); }
206                         else { print("No players found to spectate.\n"); }
207                         return;
208                 }
209                         
210                 default:
211                 case CMD_REQUEST_USAGE:
212                 {
213                         print("\nUsage:^3 sv_cmd allspec [reason]\n");
214                         print("  Where 'reason' is an optional argument for explanation of allspec command.\n");
215                         print("See also: ^2moveplayer, shuffleteams^7\n");
216                         return;
217                 }
218         }
219 }
220
221 void GameCommand_anticheat(float request, float argc) 
222 {
223         switch(request)
224         {
225                 case CMD_REQUEST_COMMAND:
226                 {
227                         entity client = GetFilteredEntity(argv(1));
228                         float accepted = VerifyClientEntity(client, FALSE, FALSE);
229                         
230                         if(accepted) 
231                         {
232                                 self = client;
233                                 anticheat_report();
234                                 return;
235                         }
236                         else
237                         {
238                                 print("anticheat: ", GetClientErrorString(accepted, argv(1)), ".\n"); 
239                         }
240                 }
241                         
242                 default:
243                         print("Incorrect parameters for ^2anticheat^7\n");
244                 case CMD_REQUEST_USAGE:
245                 {
246                         print("\nUsage:^3 sv_cmd anticheat client\n");
247                         print("  'client' is the entity number or name of the player.\n");
248                         return;
249                 }
250         }
251 }
252
253 void GameCommand_bbox(float request)
254 {
255         switch(request)
256         {
257                 case CMD_REQUEST_COMMAND:
258                 {
259                         print("Original size: ", ftos(world.absmin_x), " ", ftos(world.absmin_y), " ", ftos(world.absmin_z));
260                         print(" ", ftos(world.absmax_x), " ", ftos(world.absmax_y), " ", ftos(world.absmax_z), "\n");
261                         print("Currently set size: ", ftos(world.mins_x), " ", ftos(world.mins_y), " ", ftos(world.mins_z));
262                         print(" ", ftos(world.maxs_x), " ", ftos(world.maxs_y), " ", ftos(world.maxs_z), "\n");
263                         print("Solid bounding box size:");
264
265                         tracebox('1 0 0' * world.absmin_x,
266                                                         '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z,
267                                                         '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z,
268                                                         '1 0 0' * world.absmax_x,
269                                         MOVE_WORLDONLY,
270                                         world);
271                         if(trace_startsolid)
272                                 print(" ", ftos(world.absmin_x));
273                         else
274                                 print(" ", ftos(trace_endpos_x));
275
276                         tracebox('0 1 0' * world.absmin_y,
277                                                         '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z,
278                                                         '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z,
279                                                         '0 1 0' * world.absmax_y,
280                                         MOVE_WORLDONLY,
281                                         world);
282                         if(trace_startsolid)
283                                 print(" ", ftos(world.absmin_y));
284                         else
285                                 print(" ", ftos(trace_endpos_y));
286
287                         tracebox('0 0 1' * world.absmin_z,
288                                                         '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y,
289                                                         '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y,
290                                                         '0 0 1' * world.absmax_z,
291                                         MOVE_WORLDONLY,
292                                         world);
293                         if(trace_startsolid)
294                                 print(" ", ftos(world.absmin_z));
295                         else
296                                 print(" ", ftos(trace_endpos_z));
297
298                         tracebox('1 0 0' * world.absmax_x,
299                                                         '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z,
300                                                         '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z,
301                                                         '1 0 0' * world.absmin_x,
302                                         MOVE_WORLDONLY,
303                                         world);
304                         if(trace_startsolid)
305                                 print(" ", ftos(world.absmax_x));
306                         else
307                                 print(" ", ftos(trace_endpos_x));
308
309                         tracebox('0 1 0' * world.absmax_y,
310                                                         '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z,
311                                                         '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z,
312                                                         '0 1 0' * world.absmin_y,
313                                         MOVE_WORLDONLY,
314                                         world);
315                         if(trace_startsolid)
316                                 print(" ", ftos(world.absmax_y));
317                         else
318                                 print(" ", ftos(trace_endpos_y));
319
320                         tracebox('0 0 1' * world.absmax_z,
321                                                         '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y,
322                                                         '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y,
323                                                         '0 0 1' * world.absmin_z,
324                                         MOVE_WORLDONLY,
325                                         world);
326                         if(trace_startsolid)
327                                 print(" ", ftos(world.absmax_z));
328                         else
329                                 print(" ", ftos(trace_endpos_z));
330                                 
331                         print("\n");
332                         return;
333                 }
334                         
335                 default:
336                 case CMD_REQUEST_USAGE:
337                 {
338                         print("\nUsage:^3 sv_cmd bbox\n");
339                         print("  No arguments required.\n");
340                         print("See also: ^2gettaginfo^7\n");
341                         return;
342                 }
343         }
344 }
345
346 void GameCommand_bot_cmd(float request, float argc) // legacy
347 {
348         switch(request)
349         {
350                 case CMD_REQUEST_COMMAND:
351                 {
352                         entity bot;
353                         
354                         if(argv(1) == "reset")
355                         {
356                                 bot_resetqueues();
357                                 return;
358                         }
359                         else if(argv(1) == "load" && argc == 3)
360                         {
361                                 float fh, i;
362                                 string s;
363                                 fh = fopen(argv(2), FILE_READ);
364                                 if(fh < 0)
365                                 {
366                                         print("cannot open the file\n");
367                                         return;
368                                 }
369
370                                 i = 0;
371                                 while((s = fgets(fh)))
372                                 {
373                                         argc = tokenize_console(s);
374
375                                         if(argc >= 3 && argv(0) == "sv_cmd" && argv(1) == "bot_cmd")
376                                         {
377                                                 if(argv(2) == "reset")
378                                                 {
379                                                         bot_resetqueues();
380                                                 }
381                                                 else if(argv(2) == "setbots")
382                                                 {
383                                                         cvar_settemp("minplayers", "0");
384                                                         cvar_settemp("bot_number", argv(3));
385                                                         if(!bot_fixcount())
386                                                                 print("Sorry, could not set requested bot count\n");
387                                                 }
388                                                 else
389                                                 {
390                                                         // let's start at token 2 so we can skip sv_cmd bot_cmd
391                                                         bot = find_bot_by_number(stof(argv(2)));
392                                                         if(bot == world)
393                                                                 bot = find_bot_by_name(argv(2));
394                                                         if(bot)
395                                                                 bot_queuecommand(bot, strcat(argv(3), " ", argv(4)));
396                                                 }
397                                         }
398                                         else
399                                                 localcmd(strcat(s, "\n"));
400
401                                         ++i;
402                                 }
403                                 print(ftos(i), " commands read\n");
404                                 fclose(fh);
405                                 return;
406                         }
407                         else if(argv(1) == "help")
408                         {
409                                 if(argv(2))
410                                         bot_cmdhelp(argv(2));
411                                 else
412                                         bot_list_commands();
413                                 return;
414                         }
415                         else if(argc >= 3) // this comes last
416                         {
417                                 bot = find_bot_by_number(stof(argv(1)));
418                                 if(bot == world)
419                                         bot = find_bot_by_name(argv(1));
420                                 if(bot)
421                                 {
422                                         print(strcat("Command '", strcat(argv(2), " ", argv(3)), "' sent to bot ", bot.netname, "\n"));
423                                         bot_queuecommand(bot, strcat(argv(2), " ", argv(3)));
424                                         return;
425                                 }
426                                 else
427                                         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
428                         }
429                 }
430                         
431                 default:
432                         print("Incorrect parameters for ^2bot_cmd^7\n");
433                 case CMD_REQUEST_USAGE:
434                 {
435                         print("\nUsage:^3 sv_cmd bot_cmd client command [argument]\n");
436                         print("  'client' can be either the name or entity id of the bot\n");
437                         print("  For full list of commands, see bot_cmd help [command].\n");
438                         print("Examples: bot_cmd <id> cc \"say something\"\n");
439                         print("          bot_cmd <id> presskey jump\n");
440                         return;
441                 }
442         }
443 }
444
445 void GameCommand_cointoss(float request, float argc)
446 {
447         switch(request)
448         {
449                 case CMD_REQUEST_COMMAND:
450                 {
451                         entity client;
452                         string result1 = (argv(2) ? strcat("^7", argv(1), "^3!\n") : "^1HEADS^3!\n");
453                         string result2 = (argv(2) ? strcat("^7", argv(2), "^3!\n") : "^4TAILS^3!\n");
454                         string choice = ((random() > 0.5) ? result1 : result2);
455                         
456                         FOR_EACH_CLIENT(client)
457                                 centerprint(client, strcat("^3Throwing coin... Result: ", choice));
458                         bprint(strcat("^3Throwing coin... Result: ", choice));
459                         return;
460                 }
461                 
462                 default:
463                 case CMD_REQUEST_USAGE:
464                 {
465                         print("\nUsage:^3 sv_cmd cointoss [result1 result2]\n");
466                         print("  Where 'result1' and 'result2' are user created options.\n");
467                         return;
468                 }
469         }
470 }
471
472 void GameCommand_database(float request, float argc) // legacy
473 {
474         switch(request)
475         {
476                 case CMD_REQUEST_COMMAND:
477                 {
478                         if(argc == 3)
479                         {
480                                 if(argv(1) == "save")
481                                 {
482                                         db_save(ServerProgsDB, argv(2));
483                                         print(strcat("Copied serverprogs database to '", argv(2), "' in the data directory.\n"));
484                                         return;
485                                 }
486                                 else if(argv(1) == "dump")
487                                 {
488                                         db_dump(ServerProgsDB, argv(2));
489                                         print("DB dumped.\n"); // wtf does this do?
490                                         return;
491                                 }
492                                 else if(argv(1) == "load")
493                                 {
494                                         db_close(ServerProgsDB);
495                                         ServerProgsDB = db_load(argv(2));
496                                         print(strcat("Loaded '", argv(2), "' as new serverprogs database.\n"));
497                                         return;
498                                 }
499                         }
500                 }
501                         
502                 default:
503                         print("Incorrect parameters for ^2database^7\n");
504                 case CMD_REQUEST_USAGE:
505                 {
506                         print("\nUsage:^3 sv_cmd database action filename\n");
507                         print("  Where 'action' is the command to complete,\n");
508                         print("  and 'filename' is what it acts upon.\n");
509                         print("  Full list of commands here: \"save, dump, load.\"\n");
510                         return;
511                 }
512         }
513 }
514
515 void GameCommand_defer_clear(float request, float argc)
516 {       
517         switch(request)
518         {
519                 case CMD_REQUEST_COMMAND:
520                 {
521                         entity client;
522                         float accepted;
523                         
524                         if(argc == 2)
525                         {
526                                 client = GetFilteredEntity(argv(1));
527                                 accepted = VerifyClientEntity(client, TRUE, FALSE);
528                                 
529                                 if(accepted)
530                                 {
531                                         stuffcmd(client, "defer clear\n");
532                                         print("defer clear stuffed to ", argv(1), " (", client.netname, ")\n");
533                                 }
534                                 else { print("defer_clear: ", GetClientErrorString(accepted, argv(1)), ".\n"); }
535                                 
536                                 return;
537                         }
538                 }
539                 
540                 default:
541                         print("Incorrect parameters for ^2defer_clear^7\n");
542                 case CMD_REQUEST_USAGE:
543                 {
544                         print("\nUsage:^3 sv_cmd defer_clear client\n");
545                         print("  'client' is the entity number or name of the player.\n");
546                         print("See also: ^2defer_clear_all^7\n");
547                         return;
548                 }
549         }
550 }
551
552 void GameCommand_defer_clear_all(float request)
553 {       
554         switch(request)
555         {
556                 case CMD_REQUEST_COMMAND:
557                 {
558                         entity client;
559                         float i;
560                         float argc;
561                         
562                         FOR_EACH_CLIENT(client)
563                         {
564                                 argc = tokenize_console(strcat("defer_clear ", ftos(num_for_edict(client))));
565                                 GameCommand_defer_clear(CMD_REQUEST_COMMAND, argc);     
566                                 ++i;
567                         }
568                         if(i) { print(strcat("Successfully stuffed defer clear to all clients (", ftos(i), ")\n")); } // should a message be added if no players were found? 
569                         return;
570                 }
571                 
572                 default:
573                 case CMD_REQUEST_USAGE:
574                 {
575                         print("\nUsage:^3 sv_cmd defer_clear_all\n");
576                         print("  No arguments required.\n");
577                         print("See also: ^2defer_clear^7\n");
578                         return;
579                 }
580         }
581 }
582
583 void GameCommand_delrec(float request, float argc) // legacy // perhaps merge later with records and printstats and such?
584 {
585         switch(request)
586         {
587                 case CMD_REQUEST_COMMAND:
588                 {
589                         if(argv(1))
590                         {
591                                 if(argv(2))
592                                         race_deleteTime(argv(2), stof(argv(1)));
593                                 else
594                                         race_deleteTime(GetMapname(), stof(argv(1)));
595                                 return;
596                         }
597                 }       
598                 
599                 default:
600                         print("Incorrect parameters for ^2delrec^7\n");
601                 case CMD_REQUEST_USAGE:
602                 {
603                         print("\nUsage:^3 sv_cmd delrec ranking [map]\n");
604                         print("  'ranking' is which ranking level to clear up to, \n");
605                         print("  it will clear all records up to nth place.\n");
606                         print("  if 'map' is not provided it will use current map.\n");
607                         return;
608                 }
609         }
610 }
611
612 void GameCommand_effectindexdump(float request) // legacy
613 {
614         switch(request)
615         {
616                 case CMD_REQUEST_COMMAND:
617                 {
618                         float fh, d;
619                         string s;
620                         
621                         d = db_create();
622                         print("begin of effects list\n");
623                         db_put(d, "TE_GUNSHOT", "1"); print("effect TE_GUNSHOT is ", ftos(particleeffectnum("TE_GUNSHOT")), "\n");
624                         db_put(d, "TE_GUNSHOTQUAD", "1"); print("effect TE_GUNSHOTQUAD is ", ftos(particleeffectnum("TE_GUNSHOTQUAD")), "\n");
625                         db_put(d, "TE_SPIKE", "1"); print("effect TE_SPIKE is ", ftos(particleeffectnum("TE_SPIKE")), "\n");
626                         db_put(d, "TE_SPIKEQUAD", "1"); print("effect TE_SPIKEQUAD is ", ftos(particleeffectnum("TE_SPIKEQUAD")), "\n");
627                         db_put(d, "TE_SUPERSPIKE", "1"); print("effect TE_SUPERSPIKE is ", ftos(particleeffectnum("TE_SUPERSPIKE")), "\n");
628                         db_put(d, "TE_SUPERSPIKEQUAD", "1"); print("effect TE_SUPERSPIKEQUAD is ", ftos(particleeffectnum("TE_SUPERSPIKEQUAD")), "\n");
629                         db_put(d, "TE_WIZSPIKE", "1"); print("effect TE_WIZSPIKE is ", ftos(particleeffectnum("TE_WIZSPIKE")), "\n");
630                         db_put(d, "TE_KNIGHTSPIKE", "1"); print("effect TE_KNIGHTSPIKE is ", ftos(particleeffectnum("TE_KNIGHTSPIKE")), "\n");
631                         db_put(d, "TE_EXPLOSION", "1"); print("effect TE_EXPLOSION is ", ftos(particleeffectnum("TE_EXPLOSION")), "\n");
632                         db_put(d, "TE_EXPLOSIONQUAD", "1"); print("effect TE_EXPLOSIONQUAD is ", ftos(particleeffectnum("TE_EXPLOSIONQUAD")), "\n");
633                         db_put(d, "TE_TAREXPLOSION", "1"); print("effect TE_TAREXPLOSION is ", ftos(particleeffectnum("TE_TAREXPLOSION")), "\n");
634                         db_put(d, "TE_TELEPORT", "1"); print("effect TE_TELEPORT is ", ftos(particleeffectnum("TE_TELEPORT")), "\n");
635                         db_put(d, "TE_LAVASPLASH", "1"); print("effect TE_LAVASPLASH is ", ftos(particleeffectnum("TE_LAVASPLASH")), "\n");
636                         db_put(d, "TE_SMALLFLASH", "1"); print("effect TE_SMALLFLASH is ", ftos(particleeffectnum("TE_SMALLFLASH")), "\n");
637                         db_put(d, "TE_FLAMEJET", "1"); print("effect TE_FLAMEJET is ", ftos(particleeffectnum("TE_FLAMEJET")), "\n");
638                         db_put(d, "EF_FLAME", "1"); print("effect EF_FLAME is ", ftos(particleeffectnum("EF_FLAME")), "\n");
639                         db_put(d, "TE_BLOOD", "1"); print("effect TE_BLOOD is ", ftos(particleeffectnum("TE_BLOOD")), "\n");
640                         db_put(d, "TE_SPARK", "1"); print("effect TE_SPARK is ", ftos(particleeffectnum("TE_SPARK")), "\n");
641                         db_put(d, "TE_PLASMABURN", "1"); print("effect TE_PLASMABURN is ", ftos(particleeffectnum("TE_PLASMABURN")), "\n");
642                         db_put(d, "TE_TEI_G3", "1"); print("effect TE_TEI_G3 is ", ftos(particleeffectnum("TE_TEI_G3")), "\n");
643                         db_put(d, "TE_TEI_SMOKE", "1"); print("effect TE_TEI_SMOKE is ", ftos(particleeffectnum("TE_TEI_SMOKE")), "\n");
644                         db_put(d, "TE_TEI_BIGEXPLOSION", "1"); print("effect TE_TEI_BIGEXPLOSION is ", ftos(particleeffectnum("TE_TEI_BIGEXPLOSION")), "\n");
645                         db_put(d, "TE_TEI_PLASMAHIT", "1"); print("effect TE_TEI_PLASMAHIT is ", ftos(particleeffectnum("TE_TEI_PLASMAHIT")), "\n");
646                         db_put(d, "EF_STARDUST", "1"); print("effect EF_STARDUST is ", ftos(particleeffectnum("EF_STARDUST")), "\n");
647                         db_put(d, "TR_ROCKET", "1"); print("effect TR_ROCKET is ", ftos(particleeffectnum("TR_ROCKET")), "\n");
648                         db_put(d, "TR_GRENADE", "1"); print("effect TR_GRENADE is ", ftos(particleeffectnum("TR_GRENADE")), "\n");
649                         db_put(d, "TR_BLOOD", "1"); print("effect TR_BLOOD is ", ftos(particleeffectnum("TR_BLOOD")), "\n");
650                         db_put(d, "TR_WIZSPIKE", "1"); print("effect TR_WIZSPIKE is ", ftos(particleeffectnum("TR_WIZSPIKE")), "\n");
651                         db_put(d, "TR_SLIGHTBLOOD", "1"); print("effect TR_SLIGHTBLOOD is ", ftos(particleeffectnum("TR_SLIGHTBLOOD")), "\n");
652                         db_put(d, "TR_KNIGHTSPIKE", "1"); print("effect TR_KNIGHTSPIKE is ", ftos(particleeffectnum("TR_KNIGHTSPIKE")), "\n");
653                         db_put(d, "TR_VORESPIKE", "1"); print("effect TR_VORESPIKE is ", ftos(particleeffectnum("TR_VORESPIKE")), "\n");
654                         db_put(d, "TR_NEHAHRASMOKE", "1"); print("effect TR_NEHAHRASMOKE is ", ftos(particleeffectnum("TR_NEHAHRASMOKE")), "\n");
655                         db_put(d, "TR_NEXUIZPLASMA", "1"); print("effect TR_NEXUIZPLASMA is ", ftos(particleeffectnum("TR_NEXUIZPLASMA")), "\n");
656                         db_put(d, "TR_GLOWTRAIL", "1"); print("effect TR_GLOWTRAIL is ", ftos(particleeffectnum("TR_GLOWTRAIL")), "\n");
657                         db_put(d, "TR_SEEKER", "1"); print("effect TR_SEEKER is ", ftos(particleeffectnum("TR_SEEKER")), "\n");
658                         db_put(d, "SVC_PARTICLE", "1"); print("effect SVC_PARTICLE is ", ftos(particleeffectnum("SVC_PARTICLE")), "\n");
659
660                         fh = fopen("effectinfo.txt", FILE_READ);
661                         while((s = fgets(fh)))
662                         {
663                                 tokenize_console(s);
664                                 if(argv(0) == "effect")
665                                 {
666                                         if(db_get(d, argv(1)) != "1")
667                                         {
668                                                 if(particleeffectnum(argv(1)) >= 0)
669                                                         print("effect ", argv(1), " is ", ftos(particleeffectnum(argv(1))), "\n");
670                                                 db_put(d, argv(1), "1");
671                                         }
672                                 }
673                         }
674                         print("end of effects list\n");
675
676                         db_close(d);
677                         return;
678                 }
679                         
680                 default:
681                 case CMD_REQUEST_USAGE:
682                 {
683                         print("\nUsage:^3 sv_cmd effectindexdump\n");
684                         print("  No arguments required.\n");
685                         return;
686                 }
687         }
688 }
689
690 void GameCommand_extendmatchtime(float request)
691 {
692         switch(request)
693         {
694                 case CMD_REQUEST_COMMAND:
695                 {
696                         changematchtime(autocvar_timelimit_increment* 60, autocvar_timelimit_min*60, autocvar_timelimit_max*60);
697                         return;
698                 }
699                         
700                 default:
701                 case CMD_REQUEST_USAGE:
702                 {
703                         print("\nUsage:^3 sv_cmd extendmatchtime\n");
704                         print("  No arguments required.\n");
705                         print("See also: ^2reducematchtime^7\n");
706                         return;
707                 }
708         }
709 }
710
711 void GameCommand_find(float request, float argc)
712 {       
713         switch(request)
714         {
715                 case CMD_REQUEST_COMMAND:
716                 {
717                         entity client;
718                         
719                         for(client = world; (client = find(client, classname, argv(1))); )
720                                 print(etos(client), "\n");
721                                 
722                         return;
723                 }
724                         
725                 default:
726                         print("Incorrect parameters for ^2find^7\n");
727                 case CMD_REQUEST_USAGE:
728                 {
729                         print("\nUsage:^3 sv_cmd find classname\n");
730                         print("  Where 'classname' is the classname to search for.\n");
731                         return;
732                 }
733         }
734 }
735
736 void GameCommand_gametype(float request, float argc)
737 {       
738         switch(request)
739         {
740                 case CMD_REQUEST_COMMAND:
741                 {
742                         string s = argv(1);
743                         float t = MapInfo_Type_FromString(s), tsave = MapInfo_CurrentGametype();
744                         
745                         if(t)
746                         {
747                                 MapInfo_SwitchGameType(t);
748                                 MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
749                                 if(MapInfo_count > 0)
750                                         bprint("Game type successfully switched to ", s, "\n");
751                                 else
752                                 {
753                                         bprint("Cannot use this game type: no map for it found\n");
754                                         MapInfo_SwitchGameType(tsave);
755                                         MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
756                                 }
757                         }
758                         else
759                                 bprint("Game type switch to ", s, " failed: this type does not exist!\n");
760                         return;
761                 }
762                         
763                 default:
764                         print("Incorrect parameters for ^2gametype^7\n");
765                 case CMD_REQUEST_USAGE:
766                 {
767                         print("\nUsage:^3 sv_cmd gametype mode\n");
768                         print("  Where 'mode' is the gametype mode to switch to.\n");
769                         print("See also: ^2gotomap^7\n");
770                         return;
771                 }
772         }
773 }
774
775 void GameCommand_gettaginfo(float request, float argc) // UNTESTED
776 {       
777         switch(request)
778         {
779                 case CMD_REQUEST_COMMAND:
780                 {
781                         entity tmp_entity;
782                         float i;
783                         vector v;
784                         
785                         if(argc >= 4)
786                         {
787                                 tmp_entity = spawn();
788                                 if(argv(1) == "w")
789                                         setmodel(tmp_entity, (nextent(world)).weaponentity.model);
790                                 else
791                                 {
792                                         precache_model(argv(1));
793                                         setmodel(tmp_entity, argv(1));
794                                 }
795                                 tmp_entity.frame = stof(argv(2));
796                                 if(substring(argv(3), 0, 1) == "#")
797                                         i = stof(substring(argv(3), 1, -1));
798                                 else
799                                         i = gettagindex(tmp_entity, argv(3));
800                                 if(i)
801                                 {
802                                         v = gettaginfo(tmp_entity, i);
803                                         print("model ", tmp_entity.model, " frame ", ftos(tmp_entity.frame), " tag ", gettaginfo_name);
804                                         print(" index ", ftos(i), " parent ", ftos(gettaginfo_parent), "\n");
805                                         print(" vector = ", ftos(v_x), " ", ftos(v_y), " ", ftos(v_z), "\n");
806                                         print(" offset = ", ftos(gettaginfo_offset_x), " ", ftos(gettaginfo_offset_y), " ", ftos(gettaginfo_offset_z), "\n");
807                                         print(" forward = ", ftos(gettaginfo_forward_x), " ", ftos(gettaginfo_forward_y), " ", ftos(gettaginfo_forward_z), "\n");
808                                         print(" right = ", ftos(gettaginfo_right_x), " ", ftos(gettaginfo_right_y), " ", ftos(gettaginfo_right_z), "\n");
809                                         print(" up = ", ftos(gettaginfo_up_x), " ", ftos(gettaginfo_up_y), " ", ftos(gettaginfo_up_z), "\n");
810                                         if(argc >= 6)
811                                         {
812                                                 v_y = -v_y;
813                                                 localcmd(strcat(argv(4), vtos(v), argv(5), "\n"));
814                                         }
815                                 }
816                                 else
817                                         print("bone not found\n");
818                                         
819                                 remove(tmp_entity);
820                                 return;
821                         }
822                 }
823                         
824                 default:
825                         print("Incorrect parameters for ^2gettaginfo^7\n");
826                 case CMD_REQUEST_USAGE:
827                 {
828                         print("\nUsage:^3 sv_cmd gettaginfo model frame index [command one] [command two]\n");
829                         print("See also: ^2bbox^7\n");
830                         return;
831                 }
832         }
833 }
834
835 void GameCommand_gotomap(float request, float argc)
836 {
837         switch(request)
838         {
839                 case CMD_REQUEST_COMMAND:
840                 {
841                         if(argc == 2)
842                         {
843                                 print(GotoMap(argv(1)), "\n");
844                                 return;
845                         }
846                 }
847                         
848                 default:
849                         print("Incorrect parameters for ^2gotomap^7\n");
850                 case CMD_REQUEST_USAGE:
851                 {
852                         print("\nUsage:^3 sv_cmd gotomap map\n");
853                         print("  Where 'map' is the *.bsp file to change to.\n");
854                         print("See also: ^2gametype^7\n");
855                         return;
856                 }
857         }
858 }
859
860 void GameCommand_lockteams(float request)
861 {
862         switch(request)
863         {
864                 case CMD_REQUEST_COMMAND:
865                 {
866                         if(teamplay)
867                         {
868                                 lockteams = 1;
869                                 bprint("^1The teams are now locked.\n");
870                         }
871                         else
872                         {
873                                 bprint("lockteams command can only be used in a team-based gamemode.\n");
874                         }
875                         return;
876                 }
877                         
878                 default:
879                 case CMD_REQUEST_USAGE:
880                 {
881                         print("\nUsage:^3 sv_cmd lockteams\n");
882                         print("  No arguments required.\n");
883                         print("See also: ^2unlockteams^7\n");
884                         return;
885                 }
886         }
887 }
888
889 void GameCommand_make_mapinfo(float request) // UNTESTED
890 {
891         switch(request)
892         {
893                 case CMD_REQUEST_COMMAND:
894                 { 
895                         entity tmp_entity;
896                         
897                         tmp_entity = spawn();
898                         tmp_entity.classname = "make_mapinfo";
899                         tmp_entity.think = make_mapinfo_Think;
900                         tmp_entity.nextthink = time;
901                         MapInfo_Enumerate();
902                         return;
903                 }
904                         
905                 default:
906                 case CMD_REQUEST_USAGE:
907                 {
908                         print("\nUsage:^3 sv_cmd make_mapinfo\n");
909                         print("  No arguments required.\n");
910                         return;
911                 }
912         }
913 }
914
915 void GameCommand_modelbug(float request) // UNTESTED // is this even needed anymore? 
916 {
917         switch(request)
918         {
919                 case CMD_REQUEST_COMMAND:
920                 {
921                         modelbug();
922                         return;
923                 }
924                         
925                 default:
926                 case CMD_REQUEST_USAGE:
927                 {
928                         print("\nUsage:^3 sv_cmd modelbug\n");
929                         print("  No arguments required.\n");
930                         return;
931                 }
932         }
933 }
934
935 void GameCommand_moveplayer(float request, float argc)
936 {
937         switch(request)
938         {
939                 case CMD_REQUEST_COMMAND:
940                 {
941                         float accepted;
942                         entity client;
943         
944                         string targets = strreplace(",", " ", argv(1));
945                         string original_targets = strreplace(" ", ", ", targets);
946                         string destination = argv(2);
947                         string notify = argv(3);
948                         
949                         string successful, t;
950                         
951                         // lets see if the target(s) even actually exist.
952                         if((targets) && (destination))
953                         { 
954                                 for(;targets;)
955                                 {
956                                         t = car(targets); targets = cdr(targets);
957
958                                         // Check to see if the player is a valid target
959                                         client = GetFilteredEntity(t);
960                                         accepted = VerifyClientEntity(client, FALSE, FALSE);
961                                         
962                                         if not(accepted) 
963                                         {
964                                                 print("moveplayer: ", GetClientErrorString(accepted, t), (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                         if(argv(2) && argv(3))
1131                         {
1132                                 entity client;
1133                                 float i, n, accepted;
1134                                 
1135                                 switch(argv(1))
1136                                 {
1137                                         case "read":
1138                                         {
1139                                                 client = GetFilteredEntity(argv(2));
1140                                                 accepted = VerifyClientEntity(client, FALSE, TRUE);
1141                                                 
1142                                                 if not(accepted) 
1143                                                 {
1144                                                         print("playerdemo: read: ", GetClientErrorString(accepted, argv(2)), ".\n"); 
1145                                                         return;
1146                                                 }
1147                                                 
1148                                                 self = client;
1149                                                 playerdemo_open_read(argv(3));
1150                                                 return;
1151                                         }
1152                                         
1153                                         case "write":
1154                                         {
1155                                                 client = GetFilteredEntity(argv(2));
1156                                                 accepted = VerifyClientEntity(client, FALSE, FALSE);
1157                                                 
1158                                                 if not(accepted) 
1159                                                 {
1160                                                         print("playerdemo: write: ", GetClientErrorString(accepted, argv(2)), ".\n"); 
1161                                                         return;
1162                                                 }
1163                                                 
1164                                                 self = client;
1165                                                 playerdemo_open_write(argv(3));
1166                                                 return;
1167                                         }
1168                                         
1169                                         case "auto_read_and_write":
1170                                         {
1171                                                 n = GetFilteredNumber(argv(3));
1172                                                 cvar_set("bot_number", ftos(n));
1173                                                 
1174                                                 localcmd("wait; wait; wait\n");
1175                                                 for(i = 0; i < n; ++i) { localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", argv(2), ftos(i+1), "\n"); }
1176                                                 
1177                                                 localcmd("sv_cmd playerdemo write 1 ", ftos(n+1), "\n");
1178                                                 return;
1179                                         }
1180                                         
1181                                         case "auto_read":
1182                                         {
1183                                                 n = GetFilteredNumber(argv(3));
1184                                                 cvar_set("bot_number", ftos(n));
1185                                                 
1186                                                 localcmd("wait; wait; wait\n");
1187                                                 for(i = 0; i < n; ++i) { localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", argv(2), ftos(i+1), "\n"); }
1188                                                 return;
1189                                         }
1190                                 }
1191                         }
1192                 }
1193                         
1194                 default:
1195                         print("Incorrect parameters for ^2playerdemo^7\n");
1196                 case CMD_REQUEST_USAGE:
1197                 {
1198                         print("\nUsage:^3 sv_cmd playerdemo command (entitynumber filename | entitynumber botnumber)\n");
1199                         print("  Full list of commands here: \"read, write, auto_read_and_write, auto_read.\"\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, client;
1305                                 float i, x, z, t_teams, t_players, team_color, accepted;
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                                                         if(VerifyClientNumber(shuffleteams_players[z]))
1357                                                                 self = edict_num(shuffleteams_players[z]);
1358
1359                                                         if(self.team != team_color) 
1360                                                                 MoveToTeam(self, team_color, 6, 0);
1361
1362                                                         shuffleteams_players[z] = 0;
1363                                                         shuffleteams_teams[i] = shuffleteams_teams[i] + 1;
1364                                                 }
1365                                                 else
1366                                                 {
1367                                                         break; // move on to next team
1368                                                 }
1369                                         }
1370                                 }
1371                                 
1372                                 bprint("Successfully shuffled the players around randomly.\n");
1373                                 
1374                                 // clear the buffers now
1375                                 for (i=0; i<SHUFFLETEAMS_MAX_PLAYERS; ++i)
1376                                         shuffleteams_players[i] = 0;
1377                                 
1378                                 for (i=0; i<SHUFFLETEAMS_MAX_TEAMS; ++i)
1379                                         shuffleteams_teams[i] = 0;
1380                         }
1381                         else
1382                         {
1383                                 print("Can't shuffle teams when currently not playing a team game.\n");
1384                         }
1385                         
1386                         return;
1387                 }
1388                         
1389                 default:
1390                 case CMD_REQUEST_USAGE:
1391                 {
1392                         print("\nUsage:^3 sv_cmd shuffleteams\n");
1393                         print("  No arguments required.\n");
1394                         print("See also: ^2moveplayer, allspec^7\n");
1395                         return;
1396                 }
1397         }
1398 }
1399
1400 void GameCommand_stuffto(float request, float argc)
1401 {
1402         // This... is a fairly dangerous and powerful command... - It allows any arguments to be sent to a client via rcon.
1403         // Because of this, it is disabled by default and must be enabled by the server owner when doing compilation. That way,
1404         // we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument.
1405         
1406         #ifdef STUFFTO_ENABLED
1407         switch(request)
1408         {
1409                 case CMD_REQUEST_COMMAND:
1410                 {
1411                         entity client;
1412                         float entno;
1413                         
1414                         if(argc == 3)
1415                         {
1416                                 entno = GetFilteredNumber(argv(1));
1417                                 client = world;
1418                                 if(entno <= maxclients)
1419                                         client = edict_num(entno);
1420                                 if(client.flags & FL_CLIENT)
1421                                 {
1422                                         stuffcmd(client, strcat("\n", argv(2), "\n"));
1423                                         print(strcat("Command: \"", argv(2), "\" sent to ", client.netname, " (", argv(1) ,").\n"));
1424                                 }
1425                                 else
1426                                         print(strcat("Client (", argv(1) ,") not found.\n"));
1427                                 
1428                                 return;
1429                         }
1430                 }
1431                         
1432                 default:
1433                         print("Incorrect parameters for ^2stuffto^7\n");
1434                 case CMD_REQUEST_USAGE:
1435                 {
1436                         print("\nUsage:^3 sv_cmd stuffto client \"command\"\n");
1437                         print("  'client' is the entity number or name of the player,\n");
1438                         print("  and 'command' is the command to be sent to that player.\n");
1439                         return;
1440                 }
1441         }
1442         #else
1443         if(request)
1444         {
1445                 print("stuffto command is not enabled on this server.\n");
1446                 return;
1447         }
1448         #endif
1449 }
1450
1451 void GameCommand_trace(float request, float argc)
1452 {                                               
1453         switch(request)
1454         {
1455                 case CMD_REQUEST_COMMAND:
1456                 {
1457                         // TODO: Clean up all of these variables and merge the code below to use only a few
1458                         entity e;
1459                         vector org, delta, start, end, p, q, q0, pos, vv, dv;
1460                         float i, f, safe, unsafe, dq, dqf;
1461         
1462                         switch(argv(1))
1463                         {
1464                                 case "debug":
1465                                 {
1466                                         print("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.\n");
1467                                         for(;;)
1468                                         {
1469                                                 org = world.mins;
1470                                                 delta = world.maxs - world.mins;
1471
1472                                                 start_x = org_x + random() * delta_x;
1473                                                 start_y = org_y + random() * delta_y;
1474                                                 start_z = org_z + random() * delta_z;
1475
1476                                                 end_x = org_x + random() * delta_x;
1477                                                 end_y = org_y + random() * delta_y;
1478                                                 end_z = org_z + random() * delta_z;
1479
1480                                                 start = stov(vtos(start));
1481                                                 end = stov(vtos(end));
1482
1483                                                 tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world);
1484                                                 if(!trace_startsolid)
1485                                                 {
1486                                                         p = trace_endpos;
1487                                                         tracebox(p, PL_MIN, PL_MAX, p, MOVE_NOMONSTERS, world);
1488                                                         if(trace_startsolid || trace_fraction == 1)
1489                                                         {
1490                                                                 rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid
1491                                                                 tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world);
1492                                                                 tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world);
1493
1494                                                                 if(trace_startsolid)
1495                                                                 {
1496                                                                         // how much do we need to back off?
1497                                                                         safe = 1;
1498                                                                         unsafe = 0;
1499                                                                         for(;;)
1500                                                                         {
1501                                                                                 pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5);
1502                                                                                 tracebox(pos, PL_MIN, PL_MAX, pos, MOVE_NOMONSTERS, world);
1503                                                                                 if(trace_startsolid)
1504                                                                                 {
1505                                                                                         if((safe + unsafe) * 0.5 == unsafe)
1506                                                                                                 break;
1507                                                                                         unsafe = (safe + unsafe) * 0.5;
1508                                                                                 }
1509                                                                                 else
1510                                                                                 {
1511                                                                                         if((safe + unsafe) * 0.5 == safe)
1512                                                                                                 break;
1513                                                                                         safe = (safe + unsafe) * 0.5;
1514                                                                                 }
1515                                                                         }
1516
1517                                                                         print("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu\n");
1518                                                                         print("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu\n");
1519
1520                                                                         tracebox(p, PL_MIN + '0.1 0.1 0.1', PL_MAX - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, world);
1521                                                                         if(trace_startsolid)
1522                                                                                 print("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n");
1523                                                                         else
1524                                                                                 print("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n");
1525                                                                         break;
1526                                                                 }
1527
1528                                                                 q0 = p;
1529                                                                 dq = 0;
1530                                                                 dqf = 1;
1531                                                                 for(;;)
1532                                                                 {
1533                                                                         q = p + normalize(end - p) * (dq + dqf);
1534                                                                         if(q == q0)
1535                                                                                 break;
1536                                                                         tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world);
1537                                                                         if(trace_startsolid)
1538                                                                                 error("THIS ONE cannot happen");
1539                                                                         if(trace_fraction > 0)
1540                                                                                 dq += dqf * trace_fraction;
1541                                                                         dqf *= 0.5;
1542                                                                         q0 = q;
1543                                                                 }
1544                                                                 if(dq > 0)
1545                                                                 {
1546                                                                         print("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n");
1547                                                                         print("could go ", ftos(dq), " units further to ", vtos(q), "\n");
1548                                                                         break;
1549                                                                 }
1550                                                         }
1551                                                 }
1552                                         }
1553                                         return;
1554                                 }
1555                                         
1556                                 case "debug2":
1557                                 {
1558                                         e = nextent(world);
1559                                         tracebox(e.origin + '0 0 32', e.mins, e.maxs, e.origin + '0 0 -1024', MOVE_NORMAL, e);
1560                                         vv = trace_endpos;
1561                                         if(trace_fraction == 1)
1562                                         {
1563                                                 print("not above ground, aborting\n");
1564                                                 return;
1565                                         }
1566                                         f = 0;
1567                                         for(i = 0; i < 100000; ++i)
1568                                         {
1569                                                 dv = randomvec();
1570                                                 if(dv_z > 0)
1571                                                         dv = -1 * dv;
1572                                                 tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e);
1573                                                 if(trace_startsolid)
1574                                                         print("bug 1\n");
1575                                                 if(trace_fraction == 1)
1576                                                 if(dv_z < f)
1577                                                 {
1578                                                         print("bug 2: ", ftos(dv_x), " ", ftos(dv_y), " ", ftos(dv_z));
1579                                                         print(" (", ftos(asin(dv_z / vlen(dv)) * 180 / M_PI), " degrees)\n");
1580                                                         f = dv_z;
1581                                                 }
1582                                         }
1583                                         print("highest possible dist: ", ftos(f), "\n");
1584                                         return;
1585                                 }
1586                                 
1587                                 case "walk":
1588                                 {
1589                                         if(argc == 3)
1590                                         {
1591                                                 e = nextent(world);
1592                                                 if(tracewalk(e, stov(argv(1)), e.mins, e.maxs, stov(argv(2)), MOVE_NORMAL))
1593                                                         print("can walk\n");
1594                                                 else
1595                                                         print("cannot walk\n");
1596                                                 return;
1597                                         }
1598                                 }
1599                                 
1600                                 case "showline":
1601                                 {
1602                                         if(argc == 3)
1603                                         {
1604                                                 vv = stov(argv(1));
1605                                                 dv = stov(argv(2));
1606                                                 traceline(vv, dv, MOVE_NORMAL, world);
1607                                                 trailparticles(world, particleeffectnum("TR_NEXUIZPLASMA"), vv, trace_endpos);
1608                                                 trailparticles(world, particleeffectnum("TR_CRYLINKPLASMA"), trace_endpos, dv);
1609                                                 return;
1610                                         }
1611                                 }
1612                                 
1613                                 // no default case, just go straight to invalid
1614                         }
1615                 }
1616                         
1617                 default:
1618                         print("Incorrect parameters for ^2trace^7\n");
1619                 case CMD_REQUEST_USAGE:
1620                 {
1621                         print("\nUsage:^3 sv_cmd trace command [arguments]\n");
1622                         print("  TODO: Arguments currently unknown\n");
1623                         return;
1624                 }
1625         }
1626 }
1627
1628 void GameCommand_unlockteams(float request)
1629 {
1630         switch(request)
1631         {
1632                 case CMD_REQUEST_COMMAND:
1633                 {
1634                         if(teamplay)
1635                         {
1636                                 lockteams = 0;
1637                                 bprint("^1The teams are now unlocked.\n");
1638                         }
1639                         else
1640                         {
1641                                 bprint("unlockteams command can only be used in a team-based gamemode.\n");
1642                         }
1643                         return;
1644                 }
1645                         
1646                 default:
1647                 case CMD_REQUEST_USAGE:
1648                 {
1649                         print("\nUsage:^3 sv_cmd unlockteams\n");
1650                         print("  No arguments required.\n");
1651                         print("See also: ^2lockteams^7\n");
1652                         return;
1653                 }
1654         }
1655 }
1656
1657 void GameCommand_warp(float request, float argc)
1658 {
1659         switch (request)
1660         {
1661                 case CMD_REQUEST_COMMAND:
1662                 {
1663                         if(autocvar_g_campaign)
1664                         {
1665                                 if(argc >= 2)
1666                                 {
1667                                         CampaignLevelWarp(stof(argv(1)));
1668                                         print("Successfully warped to campaign level ", stof(argv(1)), ".\n");
1669                                 }       
1670                                 else
1671                                 {
1672                                         CampaignLevelWarp(-1);
1673                                         print("Successfully warped to next campaign level.\n");
1674                                 }
1675                         }
1676                         else
1677                                 print("Not in campaign, can't level warp\n");
1678                         return;
1679                 }
1680                 
1681                 default:
1682                 case CMD_REQUEST_USAGE:
1683                 {
1684                         print("\nUsage:^3 sv_cmd level\n");
1685                         print("  'level' is the level to change campaign mode to.\n");
1686                         return;
1687                 }
1688         }
1689 }
1690
1691 /* use this when creating a new command, making sure to place it in alphabetical order.
1692 void GameCommand_(float request)
1693 {
1694         switch(request)
1695         {
1696                 case CMD_REQUEST_COMMAND:
1697                 {
1698                         
1699                         return;
1700                 }
1701                         
1702                 default:
1703                 case CMD_REQUEST_USAGE:
1704                 {
1705                         print("\nUsage:^3 sv_cmd \n");
1706                         print("  No arguments required.\n");
1707                         return;
1708                 }
1709         }
1710 }
1711 */
1712
1713
1714 // ==================================
1715 //  Macro system for server commands
1716 // ==================================
1717
1718 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
1719 #define SERVER_COMMANDS(request,arguments,command) \
1720         SERVER_COMMAND("adminmsg", GameCommand_adminmsg(request, arguments), "Send an admin message to a client directly") \
1721         SERVER_COMMAND("allready", GameCommand_allready(request), "Restart the server and reset the players") \
1722         SERVER_COMMAND("allspec", GameCommand_allspec(request, arguments), "Force all players to spectate") \
1723         SERVER_COMMAND("anticheat", GameCommand_anticheat(request, arguments), "Create an anticheat report for a client") \
1724         SERVER_COMMAND("bbox", GameCommand_bbox(request), "Print detailed information about world size") \
1725         SERVER_COMMAND("bot_cmd", GameCommand_bot_cmd(request, arguments), "Control and send commands to bots") \
1726         SERVER_COMMAND("cointoss", GameCommand_cointoss(request, arguments), "Flip a virtual coin and give random result") \
1727         SERVER_COMMAND("cvar_changes", CommonCommand_cvar_changes(request, world), "Prints a list of all changed server cvars") \
1728         SERVER_COMMAND("cvar_purechanges", CommonCommand_cvar_purechanges(request, world), "Prints a list of all changed gameplay cvars") \
1729         SERVER_COMMAND("database", GameCommand_database(request, arguments), "Extra controls of the serverprogs database") \
1730         SERVER_COMMAND("defer_clear", GameCommand_defer_clear(request, arguments), "Clear all queued defer commands for a specific client") \
1731         SERVER_COMMAND("defer_clear_all", GameCommand_defer_clear_all(request), "Clear all queued defer commands for all clients") \
1732         SERVER_COMMAND("delrec", GameCommand_delrec(request, arguments), "Delete race time record for a map") \
1733         SERVER_COMMAND("effectindexdump", GameCommand_effectindexdump(request), "Dump list of effects from code and effectinfo.txt") \
1734         SERVER_COMMAND("extendmatchtime", GameCommand_extendmatchtime(request), "Increase the timelimit value incrementally") \
1735         SERVER_COMMAND("find", GameCommand_find(request, arguments), "Search through entities for matching classname") \
1736         SERVER_COMMAND("gametype", GameCommand_gametype(request, arguments), "Simple command to change the active gametype") \
1737         SERVER_COMMAND("gettaginfo", GameCommand_gettaginfo(request, arguments), "Get specific information about a weapon model") \
1738         SERVER_COMMAND("gotomap", GameCommand_gotomap(request, arguments), "Simple command to switch to another map") \
1739         SERVER_COMMAND("info", CommonCommand_info(request, world, arguments), "todo") \
1740         SERVER_COMMAND("ladder", CommonCommand_ladder(request, world), "Get information about top players if supported") \
1741         SERVER_COMMAND("lockteams", GameCommand_lockteams(request), "Disable the ability for players to switch or enter teams") \
1742         SERVER_COMMAND("lsmaps", CommonCommand_lsmaps(request, world), "List maps which can be used with the current game mode") \
1743         SERVER_COMMAND("lsnewmaps", CommonCommand_lsnewmaps(request, world), "todo") \
1744         SERVER_COMMAND("make_mapinfo", GameCommand_make_mapinfo(request), "Automatically rebuild mapinfo files") \
1745         SERVER_COMMAND("maplist", CommonCommand_maplist(request, world), "Display full server maplist reply") \
1746         SERVER_COMMAND("modelbug", GameCommand_modelbug(request), "TODO foobar") \
1747         SERVER_COMMAND("moveplayer", GameCommand_moveplayer(request, arguments), "Change the team/status of a player") \
1748         SERVER_COMMAND("nospectators", GameCommand_nospectators(request), "Automatically remove spectators from a match") \
1749         SERVER_COMMAND("onslaught_updatelinks", GameCommand_onslaught_updatelinks(request), "Refresh link status for onslaught") \
1750         SERVER_COMMAND("playerdemo", GameCommand_playerdemo(request, arguments), "Control the ability to save demos of players") \
1751         SERVER_COMMAND("printstats", GameCommand_printstats(request), "TODO foobar") \
1752         SERVER_COMMAND("radarmap", GameCommand_radarmap(request, arguments), "Generate a radar image of the map") \
1753         SERVER_COMMAND("rankings", CommonCommand_rankings(request, world), "Print information about rankings") \
1754         SERVER_COMMAND("records", CommonCommand_records(request, world), "List top 10 records for the current map") \
1755         SERVER_COMMAND("reducematchtime", GameCommand_reducematchtime(request), "Decrease the timelimit value incrementally") \
1756         SERVER_COMMAND("setbots", GameCommand_setbots(request, arguments), "Adjust how many bots are in the match") \
1757         SERVER_COMMAND("shuffleteams", GameCommand_shuffleteams(request), "Randomly move players to different teams") \
1758         SERVER_COMMAND("stuffto", GameCommand_stuffto(request, arguments), "Send a command to be executed on a client") \
1759         SERVER_COMMAND("teamstatus", CommonCommand_teamstatus(request, world), "Show information about player and team scores") \
1760         SERVER_COMMAND("time", CommonCommand_time(request, world), "Print different formats/readouts of time") \
1761         SERVER_COMMAND("timein", CommonCommand_timein(request, world), "Resume the game from being paused with a timeout") \
1762         SERVER_COMMAND("timeout", CommonCommand_timeout(request, world), "Call a timeout which pauses the game for certain amount of time unless unpaused") \
1763         SERVER_COMMAND("trace", GameCommand_trace(request, arguments), "Various debugging tools with tracing") \
1764         SERVER_COMMAND("unlockteams", GameCommand_unlockteams(request), "Enable the ability for players to switch or enter teams") \
1765         SERVER_COMMAND("warp", GameCommand_warp(request, arguments), "Choose different level in campaign") \
1766         SERVER_COMMAND("who", CommonCommand_who(request, world, arguments), "Display detailed client information about all players") \
1767         SERVER_COMMAND("vote", VoteCommand(request, world, arguments, command), "Server side control of voting") \
1768         /* nothing */
1769
1770 void GameCommand_macro_help()
1771 {
1772         #define SERVER_COMMAND(name,function,description) \
1773                 { print("  ^2", name, "^7: ", description, "\n"); }
1774                 
1775         SERVER_COMMANDS(0, 0, "")
1776         #undef SERVER_COMMAND
1777         
1778         return;
1779 }
1780
1781 float GameCommand_macro_command(float argc, string command)
1782 {
1783         #define SERVER_COMMAND(name,function,description) \
1784                 { if(name == strtolower(argv(0))) { function; return TRUE; } }
1785                 
1786         SERVER_COMMANDS(CMD_REQUEST_COMMAND, argc, command)
1787         #undef SERVER_COMMAND
1788         
1789         return FALSE;
1790 }
1791
1792 float GameCommand_macro_usage(float argc)
1793 {
1794         #define SERVER_COMMAND(name,function,description) \
1795                 { if(name == strtolower(argv(1))) { function; return TRUE; } }
1796                 
1797         SERVER_COMMANDS(CMD_REQUEST_USAGE, argc, "")
1798         #undef SERVER_COMMAND
1799         
1800         return FALSE;
1801 }
1802         
1803
1804 // =========================================
1805 //  Main Function Called By Engine (sv_cmd)
1806 // =========================================
1807 // If this function exists, game code handles gamecommand instead of the engine code.
1808
1809 void GameCommand(string command)
1810 {
1811         float argc = tokenize_console(command);
1812         
1813         // Guide for working with argc arguments by example:
1814         // argc:   1    - 2      - 3     - 4
1815         // argv:   0    - 1      - 2     - 3 
1816         // cmd     vote - master - login - password
1817
1818         if(strtolower(argv(0)) == "help") 
1819         {
1820                 if(argc == 1) 
1821                 {
1822                         print("\nUsage:^3 sv_cmd COMMAND...^7, where possible commands are:\n");
1823                         GameCommand_macro_help();
1824                         
1825                         GameCommand_Ban("help");
1826                         GameCommand_Generic("help");
1827                         print("For help about specific commands, type sv_cmd help COMMAND\n");
1828                         return;
1829                 } 
1830                 else if(GameCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
1831                 {
1832                         return;
1833                 }
1834         } 
1835         else if(GameCommand_Ban(command)) 
1836         {
1837                 return; // handled by server/ipban.qc
1838         }
1839         else if(GameCommand_Generic(command)) 
1840         {
1841                 return; // handled by common/gamecommand.qc
1842         }
1843         else if(GameCommand_macro_command(argc, command)) // continue as usual and scan for normal commands
1844         {
1845                 return; // handled by one of the above GameCommand_* functions
1846         }
1847         
1848         // nothing above caught the command, must be invalid
1849         print(((command != "") ? strcat("Unknown server command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try sv_cmd help.\n");
1850         
1851         return;
1852 }