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