Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
sv_cmd.qc
Go to the documentation of this file.
1#include "sv_cmd.qh"
2
3#include <common/constants.qh>
6#include <common/mapinfo.qh>
10#include <common/teams.qh>
11#include <common/util.qh>
12#include <server/anticheat.qh>
13#include <server/bot/api.qh>
14#include <server/campaign.qh>
15#include <server/client.qh>
18#include <server/command/cmd.qh>
23#include <server/ipban.qh>
24#include <server/mapvoting.qh>
26#include <server/player.qh>
28#include <server/teamplay.qh>
29#include <server/world.qh>
30
31// used by GameCommand_make_mapinfo()
33{
35 {
36 LOG_INFO("Done rebuiling mapinfos.");
38 delete(this);
39 }
40 else
41 {
43 this.nextthink = time;
44 }
45}
46
47// used by GameCommand_extendmatchtime() and GameCommand_reducematchtime()
48void changematchtime(float delta, float mi, float ma)
49{
50 float cur;
51 float update;
52 float lim;
53
54 if (delta == 0) return;
55 if (autocvar_timelimit < 0) return;
56
57 if (mi <= 10) mi = 10; // at least ten sec in the future
58 cur = time - game_starttime;
59 if (cur > 0) mi += cur; // from current time!
60
61 lim = autocvar_timelimit * 60;
62
63 if (delta > 0)
64 {
65 if (lim == 0) return; // cannot increase any further
66 else if (lim < ma) update = min(ma, lim + delta);
67 else // already above maximum: FAIL
68 return;
69 }
70 else
71 {
72 if (lim == 0) // infinite: try reducing to max, if we are allowed to
73 update = max(mi, ma);
74 else if (lim > mi) // above minimum: decrease
75 update = max(mi, lim + delta);
76 else // already below minimum: FAIL
77 return;
78 }
79
80 cvar_set("timelimit", ftos(update / 60));
81}
82
83
84// =======================
85// Command Sub-Functions
86// =======================
87
88void GameCommand_adminmsg(int request, int argc)
89{
90 switch (request)
91 {
93 {
95 {
96 LOG_HELPF("This command works only when the server is running.");
97 return;
98 }
99 entity client;
100 float accepted;
101
102 string targets = strreplace(",", " ", argv(1));
103 string original_targets = strreplace(" ", ", ", targets);
104 string admin_message = argv(2);
105 float infobartime = stof(argv(3));
106
107 string successful, t;
108 successful = string_null;
109
110 if ((targets) && (admin_message))
111 {
112 for ( ; targets; )
113 {
114 t = car(targets);
115 targets = cdr(targets);
116
117 // Check to see if the player is a valid target
118 client = GetFilteredEntity(t);
119 accepted = VerifyClientEntity(client, true, false);
120
121 if (accepted <= 0)
122 {
123 LOG_INFO("adminmsg: ", GetClientErrorString(accepted, t), (targets ? ", skipping to next player.\n" : "."));
124 continue;
125 }
126
127 // send the centerprint/console print or infomessage
128 if (infobartime)
129 {
130 stuffcmd(client, sprintf("\ninfobar %f \"%s\"\n", infobartime, MakeConsoleSafe(admin_message)));
131 }
132 else
133 {
134 centerprint(client, strcat("^3", GetCallerName(NULL), ":\n^7", admin_message));
135 sprint(client, strcat("\{1}\{13}^3", GetCallerName(NULL), "^7: ", admin_message, "\n"));
136 }
137
138 successful = strcat(successful, (successful ? ", " : ""), playername(client.netname, client.team, false));
139 LOG_TRACE("Message sent to ", playername(client.netname, client.team, false));
140 continue;
141 }
142
143 if (successful) bprint("Successfully sent message '", admin_message, "' to ", successful, ".\n");
144 else LOG_INFO("No players given (", original_targets, ") could receive the message.");
145
146 return;
147 }
148 }
149
150 default:
151 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
153 {
154 LOG_HELP("Usage:^3 sv_cmd adminmsg <clients> \"<message>\" [<infobartime>]");
155 LOG_HELP(" <clients> is a list (separated by commas) of player entity ID's or nicknames");
156 LOG_HELP(" If <infobartime> is provided, the message will be sent to infobar.");
157 LOG_HELP(" Otherwise, it will just be sent as a centerprint message.");
158 LOG_HELP("Examples: adminmsg 2,4 \"this infomessage will last for ten seconds\" 10");
159 LOG_HELP(" adminmsg 2,5 \"this message will be a centerprint\"");
160 return;
161 }
162 }
163}
164
165void GameCommand_allready(int request)
166{
167 switch (request)
168 {
170 {
172 {
173 LOG_HELPF("This command works only when the server is running.");
174 return;
175 }
176 if(warmup_stage)
177 {
178 ReadyRestart(true);
179 }
180 else
181 LOG_INFO("Not in warmup.");
182
183 return;
184 }
185
186 default:
188 {
189 LOG_HELP("Usage:^3 sv_cmd allready");
190 LOG_HELP(" No arguments required.");
191 return;
192 }
193 }
194}
195
196void GameCommand_allspec(int request, int argc)
197{
198 switch (request)
199 {
201 {
203 {
204 LOG_HELPF("This command works only when the server is running.");
205 return;
206 }
207 string reason = argv(1);
208 int n = 0;
210 PutObserverInServer(it, true, true);
211 ++n;
212 });
213 if (n) bprint(strcat("Successfully forced all (", ftos(n), ") players to spectate", (reason ? strcat(" for reason: '", reason, "'") : ""), ".\n"));
214 else LOG_INFO("No players found to spectate.");
215 return;
216 }
217
218 default:
220 {
221 LOG_HELP("Usage:^3 sv_cmd allspec [<reason>]");
222 LOG_HELP(" Where <reason> is an optional argument for explanation of allspec command.");
223 LOG_HELP("See also: ^2moveplayer, shuffleteams^7");
224 return;
225 }
226 }
227}
228
229void GameCommand_anticheat(int request, int argc)
230{
231 switch (request)
232 {
234 {
236 {
237 LOG_HELPF("This command works only when the server is running.");
238 return;
239 }
240 entity client = GetIndexedEntity(argc, 1);
241 float accepted = VerifyClientEntity(client, false, false);
242
243 if (accepted > 0)
244 {
246 return;
247 }
248 else
249 {
250 LOG_INFO("anticheat: ", GetClientErrorString(accepted, argv(1)), ".");
251 }
252 }
253
254 default:
255 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
257 {
258 LOG_HELP("Usage:^3 sv_cmd anticheat <client>");
259 LOG_HELP(" <client> is the entity number or name of the player.");
260 return;
261 }
262 }
263}
264
265void GameCommand_bbox(int request)
266{
267 switch (request)
268 {
270 {
271 vector size_min = '0 0 0';
272 vector size_max = '0 0 0';
273 tracebox('1 0 0' * world.absmin.x,
274 '0 1 0' * world.absmin.y + '0 0 1' * world.absmin.z,
275 '0 1 0' * world.absmax.y + '0 0 1' * world.absmax.z,
276 '1 0 0' * world.absmax.x,
278 NULL);
279 size_min.x = (trace_startsolid) ? world.absmin.x : trace_endpos.x;
280
281 tracebox('0 1 0' * world.absmin.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.absmax.y,
286 NULL);
287 size_min.y = (trace_startsolid) ? world.absmin.y : trace_endpos.y;
288
289 tracebox('0 0 1' * world.absmin.z,
290 '1 0 0' * world.absmin.x + '0 1 0' * world.absmin.y,
291 '1 0 0' * world.absmax.x + '0 1 0' * world.absmax.y,
292 '0 0 1' * world.absmax.z,
294 NULL);
295 size_min.z = (trace_startsolid) ? world.absmin.z : trace_endpos.z;
296
297 tracebox('1 0 0' * world.absmax.x,
298 '0 1 0' * world.absmin.y + '0 0 1' * world.absmin.z,
299 '0 1 0' * world.absmax.y + '0 0 1' * world.absmax.z,
300 '1 0 0' * world.absmin.x,
302 NULL);
303 size_max.x = (trace_startsolid) ? world.absmax.x : trace_endpos.x;
304
305 tracebox('0 1 0' * world.absmax.y,
306 '1 0 0' * world.absmin.x + '0 0 1' * world.absmin.z,
307 '1 0 0' * world.absmax.x + '0 0 1' * world.absmax.z,
308 '0 1 0' * world.absmin.y,
310 NULL);
311 size_max.y = (trace_startsolid) ? world.absmax.y : trace_endpos.y;
312
313 tracebox('0 0 1' * world.absmax.z,
314 '1 0 0' * world.absmin.x + '0 1 0' * world.absmin.y,
315 '1 0 0' * world.absmax.x + '0 1 0' * world.absmax.y,
316 '0 0 1' * world.absmin.z,
318 NULL);
319 size_max.z = (trace_startsolid) ? world.absmax.z : trace_endpos.z;
320
321 LOG_INFOF("Original size: %v %v", world.absmin, world.absmax);
322 LOG_INFOF("Currently set size: %v %v", world.mins, world.maxs);
323 LOG_INFOF("Solid bounding box size: %v %v", size_min, size_max);
324 return;
325 }
326
327 default:
329 {
330 LOG_HELP("Usage:^3 sv_cmd bbox");
331 LOG_HELP(" No arguments required.");
332 LOG_HELP("See also: ^2gettaginfo, trace^7");
333 return;
334 }
335 }
336}
337
338void GameCommand_bot_cmd(int request, int argc, string command)
339{
340 switch (request)
341 {
343 {
345 {
346 LOG_HELPF("This command works only when the server is running.");
347 return;
348 }
349 entity bot;
350
351 if (argv(1) == "reset")
352 {
354 return;
355 }
356 else if (argv(1) == "setbots")
357 {
358 cvar_settemp("bot_vs_human", "0");
359 cvar_settemp("minplayers", "0");
360 cvar_settemp("minplayers_per_team", "0");
361 cvar_settemp("bot_number", "0");
362 bot_fixcount(false); // Kill all bots.
363 cvar_settemp("bot_number", argv(2));
364 if (!bot_fixcount(true)) LOG_INFO("Sorry, could not set requested bot count");
365 return;
366 }
367 else if (argv(1) == "load" && argc == 3)
368 {
369 float fh, i;
370 string s;
371 fh = fopen(argv(2), FILE_READ);
372 if (fh < 0)
373 {
374 LOG_INFO("cannot open the file");
375 return;
376 }
377
378 i = 0;
379 while ((s = fgets(fh)))
380 {
381 argc = tokenize_console(s);
382
383 if (argc >= 3 && argv(0) == "sv_cmd" && argv(1) == "bot_cmd")
384 {
385 if (argv(2) == "reset")
386 {
388 }
389 else if (argv(2) == "setbots")
390 {
391 cvar_settemp("bot_vs_human", "0");
392 cvar_settemp("minplayers", "0");
393 cvar_settemp("minplayers_per_team", "0");
394 cvar_settemp("bot_number", "0");
395 bot_fixcount(false); // Kill all bots.
396 cvar_settemp("bot_number", argv(3));
397 if (!bot_fixcount(true)) LOG_INFO("Sorry, could not set requested bot count");
398 }
399 else
400 {
401 if(argv(2) == "*" || argv(2) == "all")
404 });
405 else
406 {
407 bot = find_bot_by_number(stof(argv(2)));
408 if (bot == NULL) bot = find_bot_by_name(argv(2));
409 if (bot) bot_queuecommand(bot, substring(s, argv_start_index(3), -1));
410 }
411 }
412 }
413 else
414 {
415 localcmd(strcat(s, "\n"));
416 }
417
418 ++i;
419 }
420 LOG_INFO(ftos(i), " commands read");
421 fclose(fh);
422 return;
423 }
424 else if (argv(1) == "help")
425 {
426 if (argv(2)) bot_cmdhelp(argv(2));
427 else bot_list_commands();
428 return;
429 }
430 else if (argc >= 3) // this comes last
431 {
432 if(argv(1) == "*" || argv(1) == "all")
433 {
434 int bot_num = 0;
436 bot_queuecommand(it, substring(command, argv_start_index(2), -1));
437 ++bot_num;
438 });
439 if(bot_num)
440 LOG_INFO("Command '", substring(command, argv_start_index(2), -1), "' sent to all bots (", ftos(bot_num), ")");
441 return;
442 }
443 else
444 {
445 bot = find_bot_by_number(stof(argv(1)));
446 if (bot == NULL) bot = find_bot_by_name(argv(1));
447 if (bot)
448 {
449 LOG_INFO("Command '", substring(command, argv_start_index(2), -1), "' sent to bot ", bot.netname);
450 bot_queuecommand(bot, substring(command, argv_start_index(2), -1));
451 return;
452 }
453 else
454 {
455 LOG_INFO("Error: Can't find bot with the name or id '", argv(1), "' - Did you mistype the command?"); // don't return so that usage is shown
456 }
457 }
458 }
459 }
460
461 default:
462 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
464 {
465 LOG_HELP("Usage:^3 sv_cmd bot_cmd <client> <command> [<arguments>]");
466 LOG_HELP(" <client> can be either the name of the bot or a progressive number (not the entity number!)");
467 LOG_HELP(" can also be '*' or 'all' to allow sending the command to all the bots");
468 LOG_HELP(" For full list of commands, see bot_cmd help [<command>].");
469 LOG_HELP("Examples: sv_cmd bot_cmd 1 cc say something");
470 LOG_HELP(" sv_cmd bot_cmd 1 presskey jump");
471 LOG_HELP(" sv_cmd bot_cmd * pause");
472 return;
473 }
474 }
475}
476
477void GameCommand_cointoss(int request, int argc)
478{
479 switch (request)
480 {
482 {
484 {
485 LOG_HELPF("This command works only when the server is running.");
486 return;
487 }
488 string result1 = (argv(2) ? strcat("^7", argv(1)) : "^1HEADS");
489 string result2 = (argv(2) ? strcat("^7", argv(2)) : "^4TAILS");
490 string choice = ((random() > 0.5) ? result1 : result2);
491
492 Send_Notification(NOTIF_ALL, NULL, MSG_MULTI, MULTI_COINTOSS, choice);
493 return;
494 }
495
496 default:
498 {
499 LOG_HELP("Usage:^3 sv_cmd cointoss [<result1> <result2>]");
500 LOG_HELP(" Where <result1> and <result2> are user created options.");
501 return;
502 }
503 }
504}
505
506void GameCommand_database(int request, int argc)
507{
508 switch (request)
509 {
511 {
512 if (argc == 3)
513 {
514 if (argv(1) == "save")
515 {
517 LOG_INFO("Copied serverprogs database to '", argv(2), "' in the data directory.");
518 return;
519 }
520 else if (argv(1) == "dump")
521 {
523 LOG_INFO("DB dumped."); // wtf does this do?
524 return;
525 }
526 else if (argv(1) == "load")
527 {
530 LOG_INFO("Loaded '", argv(2), "' as new serverprogs database.");
531 return;
532 }
533 }
534 }
535
536 default:
537 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
539 {
540 LOG_HELP("Usage:^3 sv_cmd database <action> <filename>");
541 LOG_HELP(" Where <action> is the command to complete,");
542 LOG_HELP(" and <filename> is what it acts upon.");
543 LOG_HELP(" Full list of commands here: save, dump, load.");
544 return;
545 }
546 }
547}
548
549void GameCommand_defer_clear(int request, int argc)
550{
551 switch (request)
552 {
554 {
556 {
557 LOG_HELPF("This command works only when the server is running.");
558 return;
559 }
560 entity client;
561 float accepted;
562
563 if (argc >= 2)
564 {
565 client = GetIndexedEntity(argc, 1);
566 accepted = VerifyClientEntity(client, true, false);
567
568 if (accepted > 0)
569 {
570 stuffcmd(client, "defer clear\n");
571 LOG_INFO("defer clear stuffed to ", playername(client.netname, client.team, false));
572 }
573 else { LOG_INFO("defer_clear: ", GetClientErrorString(accepted, argv(1)), "."); }
574
575 return;
576 }
577 }
578
579 default:
580 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
582 {
583 LOG_HELP("Usage:^3 sv_cmd defer_clear <client>");
584 LOG_HELP(" <client> is the entity number or name of the player.");
585 LOG_HELP("See also: ^2defer_clear_all^7");
586 return;
587 }
588 }
589}
590
592{
593 switch (request)
594 {
596 {
598 {
599 LOG_HELPF("This command works only when the server is running.");
600 return;
601 }
602 int n = 0;
603 int argc;
604
605 FOREACH_CLIENT(true, {
606 argc = tokenize_console(strcat("defer_clear ", ftos(etof(it))));
608 ++n;
609 });
610 if (n) LOG_INFO("Successfully stuffed defer clear to all clients (", ftos(n), ")"); // should a message be added if no players were found?
611 return;
612 }
613
614 default:
616 {
617 LOG_HELP("Usage:^3 sv_cmd defer_clear_all");
618 LOG_HELP(" No arguments required.");
619 LOG_HELP("See also: ^2defer_clear^7");
620 return;
621 }
622 }
623}
624
625void GameCommand_delrec(int request, int argc) // perhaps merge later with records and printstats and such?
626{
627 switch (request)
628 {
630 {
631 if (argv(1))
632 {
633 if (argv(2)) race_deleteTime(argv(2), stof(argv(1)));
634 else race_deleteTime(GetMapname(), stof(argv(1)));
635 return;
636 }
637 }
638
639 default:
640 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
642 {
643 LOG_HELP("Usage:^3 sv_cmd delrec <ranking> [<map>]");
644 LOG_HELP(" <ranking> is which ranking level to clear up to, ");
645 LOG_HELP(" it will clear all records up to nth place.");
646 LOG_HELP(" if <map> is not provided it will use current map.");
647 return;
648 }
649 }
650}
651
652void print_Effect_Index(int d, string effect_name)
653{
654 // this is inside a function to avoid expanding it on compilation everytime
655 LOG_INFO("effect ", effect_name, " is ", ftos(_particleeffectnum(effect_name)), "\n");
656 db_put(d, effect_name, "1");
657}
658
660{
661 switch (request)
662 {
664 {
665 float fh, d;
666 string s;
667
668 d = db_create();
669 LOG_INFO("begin of effects list");
670
671 print_Effect_Index(d, "TE_GUNSHOT");
672 print_Effect_Index(d, "TE_GUNSHOTQUAD");
673 print_Effect_Index(d, "TE_SPIKE");
674 print_Effect_Index(d, "TE_SPIKEQUAD");
675 print_Effect_Index(d, "TE_SUPERSPIKE");
676 print_Effect_Index(d, "TE_SUPERSPIKEQUAD");
677 print_Effect_Index(d, "TE_WIZSPIKE");
678 print_Effect_Index(d, "TE_KNIGHTSPIKE");
679 print_Effect_Index(d, "TE_EXPLOSION");
680 print_Effect_Index(d, "TE_EXPLOSIONQUAD");
681 print_Effect_Index(d, "TE_TAREXPLOSION");
682 print_Effect_Index(d, "TE_TELEPORT");
683 print_Effect_Index(d, "TE_LAVASPLASH");
684 print_Effect_Index(d, "TE_SMALLFLASH");
685 print_Effect_Index(d, "TE_FLAMEJET");
686 print_Effect_Index(d, "EF_FLAME");
687 print_Effect_Index(d, "TE_BLOOD");
688 print_Effect_Index(d, "TE_SPARK");
689 print_Effect_Index(d, "TE_PLASMABURN");
690 print_Effect_Index(d, "TE_TEI_G3");
691 print_Effect_Index(d, "TE_TEI_SMOKE");
692 print_Effect_Index(d, "TE_TEI_BIGEXPLOSION");
693 print_Effect_Index(d, "TE_TEI_PLASMAHIT");
694 print_Effect_Index(d, "EF_STARDUST");
695 print_Effect_Index(d, "TR_ROCKET");
696 print_Effect_Index(d, "TR_GRENADE");
697 print_Effect_Index(d, "TR_BLOOD");
698 print_Effect_Index(d, "TR_WIZSPIKE");
699 print_Effect_Index(d, "TR_SLIGHTBLOOD");
700 print_Effect_Index(d, "TR_KNIGHTSPIKE");
701 print_Effect_Index(d, "TR_VORESPIKE");
702 print_Effect_Index(d, "TR_NEHAHRASMOKE");
703 print_Effect_Index(d, "TR_NEXUIZPLASMA");
704 print_Effect_Index(d, "TR_GLOWTRAIL");
705 print_Effect_Index(d, "TR_SEEKER");
706 print_Effect_Index(d, "SVC_PARTICLE");
707
708 fh = fopen("effectinfo.txt", FILE_READ);
709 while ((s = fgets(fh)))
710 {
712 if (argv(0) == "effect")
713 {
714 if (db_get(d, argv(1)) != "1")
715 {
716 int i = _particleeffectnum(argv(1));
717 if (i >= 0) LOG_INFO("effect ", argv(1), " is ", ftos(i));
718 db_put(d, argv(1), "1");
719 }
720 }
721 }
722 LOG_INFO("end of effects list");
723
724 db_close(d);
725 return;
726 }
727
728 default:
730 {
731 LOG_HELP("Usage:^3 sv_cmd effectindexdump");
732 LOG_HELP(" No arguments required.");
733 return;
734 }
735 }
736}
737
739{
740 switch (request)
741 {
743 {
745 {
746 LOG_HELPF("This command works only when the server is running.");
747 return;
748 }
750 return;
751 }
752
753 default:
755 {
756 LOG_HELP("Usage:^3 sv_cmd extendmatchtime");
757 LOG_HELP(" No arguments required.");
758 LOG_HELP("See also: ^2reducematchtime^7");
759 return;
760 }
761 }
762}
763
764void GameCommand_gametype(int request, int argc)
765{
766 switch (request)
767 {
769 {
771 {
772 LOG_HELPF("This command works only when the server is running.");
773 return;
774 }
775 if (argv(1) != "")
776 {
777 string s = argv(1);
778 Gametype t = MapInfo_Type_FromString(s, false, false);
779
780 if (t)
781 {
782 // don't execute gametype hooks because they can change active
783 // gametype rules if executed during the game
784 GameTypeVote_SetGametype(t, "", false);
785 }
786 else
787 bprint("Failed to switch to ", s, ": this gametype does not exist!\n");
788
789 return;
790 }
791 }
792
793 default:
794 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
796 {
797 LOG_HELP("Usage:^3 sv_cmd gametype <mode>");
798 LOG_HELP(" Where <mode> is the gametype mode to switch to.");
799 LOG_HELP("See also: ^2gotomap^7");
800 return;
801 }
802 }
803}
804
805void GameCommand_gettaginfo(int request, int argc)
806{
807 switch (request)
808 {
810 {
811 entity tmp_entity;
812 float i;
813 vector v;
814
815 if (argc >= 4)
816 {
817 tmp_entity = spawn();
818 if (argv(1) == "w")
819 {
820 .entity weaponentity = weaponentities[0];
821 _setmodel(tmp_entity, (nextent(NULL)).(weaponentity).model);
822 }
823 else
824 {
825 precache_model(argv(1));
826 _setmodel(tmp_entity, argv(1));
827 }
828 tmp_entity.frame = stof(argv(2));
829 if (substring(argv(3), 0, 1) == "#") i = stof(substring(argv(3), 1, -1));
830 else i = gettagindex(tmp_entity, argv(3));
831 if (i)
832 {
833 v = gettaginfo(tmp_entity, i);
834 LOG_HELPF("model %s frame %s tag %s index %s parent %s",
835 tmp_entity.model, ftos(tmp_entity.frame), gettaginfo_name, ftos(i), ftos(gettaginfo_parent)
836 );
837 LOG_HELPF(" vector = %s %s %s", ftos(v.x), ftos(v.y), ftos(v.z));
841 LOG_HELPF(" up = %s %s %s", ftos(gettaginfo_up.x), ftos(gettaginfo_up.y), ftos(gettaginfo_up.z));
842 if (argc >= 6)
843 {
844 v.y = -v.y;
845 localcmd(strcat(argv(4), vtos(v), argv(5), "\n"));
846 }
847 }
848 else
849 {
850 LOG_INFO("bone not found");
851 }
852
853 delete(tmp_entity);
854 return;
855 }
856 }
857
858 default:
859 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
861 {
862 LOG_HELP("Usage:^3 sv_cmd gettaginfo <model> <frame> <index> [<command1>] [<command2>]");
863 LOG_HELP("See also: ^2bbox, trace^7");
864 return;
865 }
866 }
867}
868
869void GameCommand_animbench(int request, int argc)
870{
871 switch (request)
872 {
874 {
875 entity tmp_entity;
876
877 if (argc >= 4)
878 {
879 tmp_entity = spawn();
880 if (argv(1) == "w")
881 {
882 .entity weaponentity = weaponentities[0];
883 _setmodel(tmp_entity, (nextent(NULL)).(weaponentity).model);
884 }
885 else
886 {
887 precache_model(argv(1));
888 _setmodel(tmp_entity, argv(1));
889 }
890 float f1 = stof(argv(2));
891 float f2 = stof(argv(3));
892 float t0;
893 float t1 = 0;
894 float t2 = 0;
895 float n = 0;
896
897 while (t1 + t2 < 1)
898 {
899 tmp_entity.frame = f1;
901 getsurfacepoint(tmp_entity, 0, 0);
902 t1 += gettime(GETTIME_HIRES) - t0;
903 tmp_entity.frame = f2;
905 getsurfacepoint(tmp_entity, 0, 0);
906 t2 += gettime(GETTIME_HIRES) - t0;
907 ++n;
908 }
909 LOG_INFO("model ", tmp_entity.model, " frame ", ftos(f1), " animtime ", ftos(n / t1), "/s");
910 LOG_INFO("model ", tmp_entity.model, " frame ", ftos(f2), " animtime ", ftos(n / t2), "/s");
911
912 delete(tmp_entity);
913 return;
914 }
915 }
916
917 default:
918 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
920 {
921 LOG_HELP("Usage:^3 sv_cmd animbench <model> <frame1> <frame2>");
922 LOG_HELP("See also: ^2bbox, trace^7");
923 return;
924 }
925 }
926}
927
928void GameCommand_gotomap(int request, int argc)
929{
930 switch (request)
931 {
933 {
935 {
936 LOG_HELPF("This command works only when the server is running.");
937 return;
938 }
939 if (argv(1))
940 {
941 LOG_INFO(GotoMap(argv(1)));
942 return;
943 }
944 }
945
946 default:
947 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
949 {
950 LOG_HELP("Usage:^3 sv_cmd gotomap <map>");
951 LOG_HELP(" Where <map> is the *.bsp file to change to.");
952 LOG_HELP("See also: ^2gametype^7");
953 return;
954 }
955 }
956}
957
958void GameCommand_lockteams(int request)
959{
960 switch (request)
961 {
963 {
965 {
966 LOG_HELPF("This command works only when the server is running.");
967 return;
968 }
969 if (teamplay)
970 {
971 lockteams = 1;
972 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_TEAMS_LOCKED);
973 // nobody can join or change teams now so remove everyone from the queue
974 FOREACH_CLIENT(it.wants_join, it.wants_join = it.team_selected = 0);
975 }
976 else
977 {
978 bprint("lockteams command can only be used in a team-based gametype.\n");
979 }
980 return;
981 }
982
983 default:
985 {
986 LOG_HELP("Usage:^3 sv_cmd lockteams");
987 LOG_HELP(" No arguments required.");
988 LOG_HELP("See also: ^2unlockteams^7");
989 return;
990 }
991 }
992}
993
995{
996 switch (request)
997 {
999 {
1000 entity tmp_entity = new(make_mapinfo);
1001 setthink(tmp_entity, make_mapinfo_Think);
1002 tmp_entity.nextthink = time;
1004 return;
1005 }
1006
1007 default:
1008 case CMD_REQUEST_USAGE:
1009 {
1010 LOG_HELP("Usage:^3 sv_cmd make_mapinfo");
1011 LOG_HELP(" No arguments required.");
1012 LOG_HELP("See also: ^2radarmap^7");
1013 return;
1014 }
1015 }
1016}
1017
1018void GameCommand_moveplayer(int request, int argc)
1019{
1020 switch (request)
1021 {
1023 {
1024 if (!world_initialized)
1025 {
1026 LOG_HELPF("This command works only when the server is running.");
1027 return;
1028 }
1029 float accepted;
1030 entity client;
1031
1032 string targets = strreplace(",", " ", argv(1));
1033 string original_targets = strreplace(" ", ", ", targets);
1034 string destination = argv(2);
1035 if (destination == "spec")
1036 destination = "spectator";
1037
1038 if ((targets) && (destination))
1039 {
1040 string successful = string_null;
1041 string t;
1042 for ( ; targets; )
1043 {
1044 t = car(targets);
1045 targets = cdr(targets);
1046
1047 // Check to see if the player is a valid target
1048 client = GetFilteredEntity(t);
1049 accepted = VerifyClientEntity(client, false, false);
1050 string client_num_str = ftos(etof(client));
1051
1052 if (accepted <= 0)
1053 {
1054 LOG_INFO("moveplayer: ", GetClientErrorString(accepted, t), ".");
1055 }
1056 else if (destination == "spectator")
1057 {
1058 string pl_name = playername(client.netname, client.team, false);
1059 if (!(IS_SPEC(client) || IS_OBSERVER(client)) || INGAME(client))
1060 {
1061 PutObserverInServer(client, true, true);
1062
1063 successful = strcat(successful, (successful ? ", " : ""), pl_name);
1064 }
1065 else
1066 {
1067 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is already spectating.");
1068 }
1069 }
1070 else
1071 {
1072 if (!teamplay)
1073 {
1074 LOG_INFO("Can't change teams when currently not playing a team game.");
1075 return;
1076 }
1077
1078 string pl_name = playername(client.netname, client.team, false);
1079 if (IS_SPEC(client) || IS_OBSERVER(client))
1080 {
1081 // well technically we could, but should we allow that? :P
1082 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is not in the game.");
1083 continue;
1084 }
1085
1086 // set up
1087 int save = Player_GetForcedTeamIndex(client);
1089
1090 // find the team to move the player to
1091 int team_num = Team_ColorToTeam(destination);
1092 entity balance;
1093 if (team_num == client.team) // already on the destination team
1094 {
1095 // keep the forcing undone
1096 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is already on the ",
1097 Team_ColoredFullName(team_num), ".");
1098 continue;
1099 }
1100 else if (team_num == 0) // auto team
1101 {
1102 balance = TeamBalance_CheckAllowedTeams(client);
1103 team_num = Team_IndexToTeam(TeamBalance_FindBestTeam(balance, client, false));
1104 }
1105 else
1106 {
1107 balance = TeamBalance_CheckAllowedTeams(client);
1108 }
1109 Player_SetForcedTeamIndex(client, save);
1110
1111 // Check to see if the destination team is even available
1112 int team_id = Team_TeamToIndex(team_num);
1113 if (team_id == -1)
1114 {
1115 LOG_INFO("Can't move player to ", destination, " team because it doesn't exist.");
1116 TeamBalance_Destroy(balance);
1117 return;
1118 }
1119 if (!IsTeamAvailable(team_num))
1120 {
1121 LOG_INFO("Can't move player to ", destination, " team because it isn't available.");
1122 TeamBalance_Destroy(balance);
1123 return;
1124 }
1125 if (!TeamBalance_IsTeamAllowed(balance, team_id))
1126 {
1127 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is not allowed to join the ",
1128 Team_ColoredFullName(team_num), ".");
1129 TeamBalance_Destroy(balance);
1130 continue;
1131 }
1132 TeamBalance_Destroy(balance);
1133
1134 // If so, lets continue and finally move the player
1136 if (MoveToTeam(client, team_id, 6))
1137 {
1138 successful = strcat(successful, (successful ? ", " : ""), pl_name);
1139 LOG_INFO("Player #", client_num_str, " (", pl_name, ") has been moved to the ",
1140 Team_ColoredFullName(team_num), ".");
1141 }
1142 else
1143 {
1144 LOG_INFO("Unable to move player #", client_num_str, " (", pl_name, ")");
1145 }
1146 }
1147 } // loop end
1148
1149 if (successful) bprint("Successfully moved players ", successful, " to destination ", destination, ".\n");
1150 else LOG_INFO("No players given (", original_targets, ") are able to move.");
1151
1152 return; // still correct parameters so return to avoid usage print
1153 }
1154 }
1155
1156 default:
1157 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1158 case CMD_REQUEST_USAGE:
1159 {
1160 LOG_HELP("Usage:^3 sv_cmd moveplayer <clients> <destination>");
1161 LOG_HELP(" <clients> is a list (separated by commas) of player entity ID's or nicknames");
1162 LOG_HELP(" <destination> is what to send the player to, be it team or spectating");
1163 LOG_HELP(" Full list of destinations here: spec, spectator, red, blue, yellow, pink, auto.");
1164 LOG_HELP("Examples: sv_cmd moveplayer 1,3,5 red");
1165 LOG_HELP(" sv_cmd moveplayer 2 spec");
1166 LOG_HELP("See also: ^2allspec, shuffleteams^7");
1167 return;
1168 }
1169 }
1170}
1171
1172void GameCommand_nextmap(int request, int argc)
1173{
1174 switch (request)
1175 {
1177 {
1178 if (argc >= 2) // nextmap with mapname arg
1179 {
1180 if (argc > 2)
1181 LOG_HELP("Warning: nextmap only takes 1 argument");
1182
1183 string map = ValidateMap(argv(1), NULL);
1184 if (map != "" && map != get_nextmap())
1185 Set_NextMap(map);
1186 }
1187 else // nextmap without args
1188 {
1189 if (get_nextmap() != "")
1191 else
1192 LOG_HELP("none");
1193 }
1194 return; // never fall through to usage
1195 }
1196
1197 default:
1198 case CMD_REQUEST_USAGE:
1199 {
1200 LOG_HELP("Usage:^3 sv_cmd nextmap [<mapname>]");
1201 LOG_HELP(" Without arguments it prints current nextmap if one is set");
1202 LOG_HELP(" With arguments it attempts to set nextmap");
1203 return;
1204 }
1205 }
1206}
1207
1209{
1210 switch (request)
1211 {
1213 {
1214 if (!world_initialized)
1215 {
1216 LOG_HELPF("This command works only when the server is running.");
1217 return;
1218 }
1219 cvar_settemp("sv_spectate", "0");
1220 // if sv_spectate was enabled PlayerFrame() sends SPECTATE_WARNING notifications
1221 return;
1222 }
1223
1224 default:
1225 case CMD_REQUEST_USAGE:
1226 {
1227 LOG_HELP("Usage:^3 sv_cmd nospectators");
1228 LOG_HELP(" No arguments required.");
1229 LOG_HELP("Temporarily disables the ^3sv_spectate ^7cvar.");
1230 return;
1231 }
1232 }
1233}
1234
1235void GameCommand_printstats(int request)
1236{
1237 switch (request)
1238 {
1240 {
1241 if (!world_initialized)
1242 {
1243 LOG_HELPF("This command works only when the server is running.");
1244 return;
1245 }
1246 DumpStats(false);
1247 LOG_INFO("stats dumped.");
1248 return;
1249 }
1250
1251 default:
1252 case CMD_REQUEST_USAGE:
1253 {
1254 LOG_HELP("Usage:^3 sv_cmd printstats");
1255 LOG_HELP(" No arguments required.");
1256 return;
1257 }
1258 }
1259}
1260
1261void GameCommand_radarmap(int request, int argc)
1262{
1263 switch (request)
1264 {
1266 {
1267 if (RadarMap_Make(argc)) return;
1268 }
1269
1270 default:
1271 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1272 case CMD_REQUEST_USAGE:
1273 {
1274 LOG_HELP("Usage:^3 sv_cmd radarmap [--force] [--loop] [--quit] [--block | --trace | --sample | --lineblock] [--sharpen N] [--res W H] [--qual Q]");
1275 LOG_HELP(" The quality factor Q is roughly proportional to the time taken.");
1276 LOG_HELP(" trace supports no quality factor; its result should look like --block with infinite quality factor.");
1277 LOG_HELP("See also: ^2make_mapinfo^7");
1278 return;
1279 }
1280 }
1281}
1282
1284{
1285 switch (request)
1286 {
1288 {
1289 if (!world_initialized)
1290 {
1291 LOG_HELPF("This command works only when the server is running.");
1292 return;
1293 }
1295 return;
1296 }
1297
1298 default:
1299 case CMD_REQUEST_USAGE:
1300 {
1301 LOG_HELP("Usage:^3 sv_cmd reducematchtime");
1302 LOG_HELP(" No arguments required.");
1303 LOG_HELP("See also: ^2extendmatchtime^7");
1304 return;
1305 }
1306 }
1307}
1308
1309void GameCommand_setbots(int request, int argc)
1310{
1311 switch (request)
1312 {
1314 {
1315 if (argc >= 2)
1316 {
1317 cvar_settemp("minplayers", "0");
1318 cvar_settemp("minplayers_per_team", "0");
1319 cvar_settemp("bot_number", argv(1));
1320 bot_fixcount(true);
1321 return;
1322 }
1323 }
1324
1325 default:
1326 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1327 case CMD_REQUEST_USAGE:
1328 {
1329 LOG_HELP("Usage:^3 sv_cmd setbots <botnumber>");
1330 LOG_HELP(" Where <botnumber> is the amount of bots to set bot_number cvar to.");
1331 LOG_HELP("See also: ^2bot_cmd^7");
1332 return;
1333 }
1334 }
1335}
1336
1338{
1339 if (!teamplay)
1340 {
1341 LOG_INFO("Can't shuffle teams when currently not playing a team game.");
1342 return;
1343 }
1344
1345 FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), {
1346 if (Player_HasRealForcedTeam(it)) {
1347 // we could theoretically assign forced players to their teams
1348 // and shuffle the rest to fill the empty spots but in practise
1349 // either all players or none are gonna have forced teams
1350 LOG_INFO("Can't shuffle teams because at least one player has a forced team.");
1351 return;
1352 }
1353 });
1354
1355 int number_of_teams = 0;
1357 for (int i = 1; i <= NUM_TEAMS; ++i)
1358 {
1359 if (TeamBalance_IsTeamAllowed(balance, i))
1360 {
1361 number_of_teams = max(i, number_of_teams);
1362 }
1363 }
1364 TeamBalance_Destroy(balance);
1365
1366 int team_index = 0;
1368 int target_team_index = team_index + 1;
1369 if (Entity_GetTeamIndex(it) != target_team_index)
1370 {
1371 MoveToTeam(it, target_team_index, 6);
1372 }
1373 team_index = (team_index + 1) % number_of_teams;
1374 });
1375
1376 bprint("Successfully shuffled the players around randomly.\n");
1377}
1378
1380{
1381 switch (request)
1382 {
1384 {
1385 if (!world_initialized)
1386 {
1387 LOG_HELPF("This command works only when the server is running.");
1388 return;
1389 }
1391 {
1392 bprint("Players will be shuffled when this round is over.\n");
1394 }
1395 else
1396 shuffleteams();
1397 return;
1398 }
1399
1400 default:
1401 case CMD_REQUEST_USAGE:
1402 {
1403 LOG_HELP("Usage:^3 sv_cmd shuffleteams");
1404 LOG_HELP(" No arguments required.");
1405 LOG_HELP("See also: ^2moveplayer, allspec^7");
1406 return;
1407 }
1408 }
1409}
1410
1411void GameCommand_resetmatch(int request)
1412{
1413 switch (request)
1414 {
1416 {
1417 if (!world_initialized)
1418 {
1419 LOG_HELPF("This command works only when the server is running.");
1420 return;
1421 }
1422 ReadyRestart(false);
1423 return;
1424 }
1425
1426 default:
1427 case CMD_REQUEST_USAGE:
1428 {
1429 LOG_HELP("Usage:^3 sv_cmd resetmatch");
1430 LOG_HELP(" No arguments required.");
1431 return;
1432 }
1433 }
1434}
1435
1436void GameCommand_stuffto(int request, int argc)
1437{
1438 // This... is a fairly dangerous and powerful command... - It allows any arguments to be sent to a client via rcon.
1439 // Because of this, it is disabled by default and must be enabled by the server owner when doing compilation. That way,
1440 // we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument.
1441
1442#ifdef STUFFTO_ENABLED
1443 switch (request)
1444 {
1446 {
1447 if (!world_initialized)
1448 {
1449 LOG_HELPF("This command works only when the server is running.");
1450 return;
1451 }
1452 if (argv(2))
1453 {
1454 entity client = GetIndexedEntity(argc, 1);
1455 float accepted = VerifyClientEntity(client, true, false);
1456
1457 if (accepted > 0)
1458 {
1459 stuffcmd(client, strcat("\n", argv(next_token), "\n"));
1460 LOG_INFO("Command: \"", argv(next_token), "\" sent to ", GetCallerName(client), " (", argv(1), ").");
1461 }
1462 else
1463 {
1464 LOG_INFO("stuffto: ", GetClientErrorString(accepted, argv(1)), ".");
1465 }
1466
1467 return;
1468 }
1469 }
1470
1471 default:
1472 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1473 case CMD_REQUEST_USAGE:
1474 {
1475 LOG_HELP("Usage:^3 sv_cmd stuffto <client> \"<command>\"");
1476 LOG_HELP(" <client> is the entity number or name of the player,");
1477 LOG_HELP(" and <command> is the command to be sent to that player.");
1478 return;
1479 }
1480 }
1481#else
1482 if (request)
1483 {
1484 LOG_HELP("stuffto command is not enabled on this server.");
1485 return;
1486 }
1487#endif
1488}
1489
1490void GameCommand_trace(int request, int argc)
1491{
1492 switch (request)
1493 {
1495 {
1496 entity e;
1497 vector org, delta, start, end, p, q, q0, pos, vv, dv;
1498 float i, f, safe, unsafe, dq, dqf;
1499
1500 switch (argv(1))
1501 {
1502 case "debug":
1503 {
1504 float hitcount = 0;
1505 LOG_INFO("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.");
1506 float worst_endpos_bug = 0;
1507 for ( ; ; )
1508 {
1509 org = world.mins;
1510 delta = world.maxs - world.mins;
1511
1512 start.x = org.x + random() * delta.x;
1513 start.y = org.y + random() * delta.y;
1514 start.z = org.z + random() * delta.z;
1515
1516 end.x = org.x + random() * delta.x;
1517 end.y = org.y + random() * delta.y;
1518 end.z = org.z + random() * delta.z;
1519
1520 start = stov(vtos(start));
1521 end = stov(vtos(end));
1522
1523 tracebox(start, PL_MIN_CONST, PL_MAX_CONST, end, MOVE_NOMONSTERS, NULL);
1524 if (!trace_startsolid && trace_fraction < 1)
1525 {
1526 p = trace_endpos;
1527 tracebox(p, PL_MIN_CONST, PL_MAX_CONST, p, MOVE_NOMONSTERS, NULL);
1528 if (trace_startsolid)
1529 {
1530 rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid
1531 tracebox(start, PL_MIN_CONST, PL_MAX_CONST, end, MOVE_NOMONSTERS, NULL);
1532
1533 // how much do we need to back off?
1534 safe = 1;
1535 unsafe = 0;
1536 for ( ; ; )
1537 {
1538 pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5);
1539 tracebox(pos, PL_MIN_CONST, PL_MAX_CONST, pos, MOVE_NOMONSTERS, NULL);
1540 if (trace_startsolid)
1541 {
1542 if ((safe + unsafe) * 0.5 == unsafe) break;
1543 unsafe = (safe + unsafe) * 0.5;
1544 }
1545 else
1546 {
1547 if ((safe + unsafe) * 0.5 == safe) break;
1548 safe = (safe + unsafe) * 0.5;
1549 }
1550 }
1551
1552 LOG_INFO("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu");
1553 LOG_INFO("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu");
1554
1555 tracebox(p, PL_MIN_CONST + '0.1 0.1 0.1', PL_MAX_CONST - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, NULL);
1556 if (trace_startsolid) LOG_INFO("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p));
1557 else LOG_INFO("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p));
1558 if (++hitcount >= 10) break;
1559 }
1560 else
1561 {
1562 q0 = p;
1563 dq = 0;
1564 dqf = 1;
1565 for ( ; ; )
1566 {
1567 q = p + normalize(end - p) * (dq + dqf);
1568 if (q == q0) break;
1569 tracebox(p, PL_MIN_CONST, PL_MAX_CONST, q, MOVE_NOMONSTERS, NULL);
1570 if (trace_startsolid) error("THIS ONE cannot happen");
1571 if (trace_fraction > 0) dq += dqf * trace_fraction;
1572 dqf *= 0.5;
1573 q0 = q;
1574 }
1575 if (dq > worst_endpos_bug)
1576 {
1577 worst_endpos_bug = dq;
1578 LOG_INFO("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p));
1579 LOG_INFO("could go ", ftos(dq), " units further to ", vtos(q));
1580 if (++hitcount >= 10) break;
1581 }
1582 }
1583 }
1584 }
1585 return;
1586 }
1587
1588 case "debug2":
1589 {
1590 e = nextent(NULL);
1591 tracebox(e.origin + '0 0 32', e.mins, e.maxs, e.origin + '0 0 -1024', MOVE_NORMAL, e);
1592 vv = trace_endpos;
1593 if (trace_fraction == 1)
1594 {
1595 LOG_INFO("not above ground, aborting");
1596 return;
1597 }
1598 f = 0;
1599 for (i = 0; i < 100000; ++i)
1600 {
1601 dv = randomvec();
1602 if (dv.z > 0) dv = -1 * dv;
1603 tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e);
1604 if (trace_startsolid) LOG_INFO("bug 1");
1605 if (trace_fraction == 1)
1606 {
1607 if (dv.z < f)
1608 {
1609 LOG_INFO("bug 2: ", ftos(dv.x), " ", ftos(dv.y), " ", ftos(dv.z));
1610 LOG_INFO(" (", ftos(asin(dv.z / vlen(dv)) * 180 / M_PI), " degrees)");
1611 f = dv.z;
1612 }
1613 }
1614 }
1615 LOG_INFO("highest possible dist: ", ftos(f));
1616 return;
1617 }
1618
1619 case "walk":
1620 {
1621 if (argc == 4 || argc == 5)
1622 {
1623 e = nextent(NULL);
1624 int dphitcontentsmask_save = e.dphitcontentsmask;
1626 if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), stof(argv(4)), MOVE_NORMAL))
1627 LOG_INFO("can walk");
1628 else
1629 LOG_INFO("cannot walk");
1630 e.dphitcontentsmask = dphitcontentsmask_save;
1631 return;
1632 }
1633 }
1634
1635 case "showline":
1636 {
1637 if (argc == 4)
1638 {
1639 vv = stov(argv(2));
1640 dv = stov(argv(3));
1641 traceline(vv, dv, MOVE_NORMAL, NULL);
1642 __trailparticles(NULL, particleeffectnum(EFFECT_TR_NEXUIZPLASMA), vv, trace_endpos);
1643 __trailparticles(NULL, particleeffectnum(EFFECT_TR_CRYLINKPLASMA), trace_endpos, dv);
1644 return;
1645 }
1646 }
1647
1648 // no default case, just go straight to invalid
1649 }
1650 }
1651
1652 default:
1653 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1654 case CMD_REQUEST_USAGE:
1655 {
1656 LOG_HELP("Usage:^3 sv_cmd trace <command> [<startpos> <endpos>] [<endpos_height>]");
1657 LOG_HELP(" Where <startpos> and <endpos> are parameters for the 'walk' and 'showline' commands,");
1658 LOG_HELP(" <endpos_height> is an optional parameter for the 'walk' command,");
1659 LOG_HELP(" Full list of commands here: debug, debug2, walk, showline.");
1660 LOG_HELP("See also: ^2bbox, gettaginfo^7");
1661 return;
1662 }
1663 }
1664}
1665
1667{
1668 switch (request)
1669 {
1671 {
1672 if (!world_initialized)
1673 {
1674 LOG_HELPF("This command works only when the server is running.");
1675 return;
1676 }
1677 if (teamplay)
1678 {
1679 lockteams = 0;
1680 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_TEAMS_UNLOCKED);
1681 }
1682 else
1683 {
1684 bprint("unlockteams command can only be used in a team-based gametype.\n");
1685 }
1686 return;
1687 }
1688
1689 default:
1690 case CMD_REQUEST_USAGE:
1691 {
1692 LOG_HELP("Usage:^3 sv_cmd unlockteams");
1693 LOG_HELP(" No arguments required.");
1694 LOG_HELP("See also: ^2lockteams^7");
1695 return;
1696 }
1697 }
1698}
1699
1700void GameCommand_warp(int request, int argc)
1701{
1702 switch (request)
1703 {
1705 {
1706 if (!world_initialized)
1707 {
1708 LOG_HELPF("This command works only when the server is running.");
1709 return;
1710 }
1712 {
1713 if (argc >= 2)
1714 {
1716 LOG_INFO("Successfully warped to campaign level ", argv(1), ".");
1717 }
1718 else
1719 {
1721 LOG_INFO("Successfully warped to next campaign level.");
1722 }
1723 }
1724 else
1725 {
1726 LOG_INFO("Not in campaign, can't level warp");
1727 }
1728 return;
1729 }
1730
1731 default:
1732 case CMD_REQUEST_USAGE:
1733 {
1734 LOG_HELP("Usage:^3 sv_cmd warp [<level>]");
1735 LOG_HELP(" <level> is the level to change campaign mode to.");
1736 LOG_HELP(" if <level> is not provided it will change to the next level.");
1737 return;
1738 }
1739 }
1740}
1741
1742/* use this when creating a new command, making sure to place it in alphabetical order... also,
1743** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
1744void GameCommand_(int request)
1745{
1746 switch(request)
1747 {
1748 case CMD_REQUEST_COMMAND:
1749 {
1750 if (!world_initialized)
1751 {
1752 LOG_HELPF("This command works only when the server is running.");
1753 return;
1754 }
1755
1756 return;
1757 }
1758
1759 default:
1760 case CMD_REQUEST_USAGE:
1761 {
1762 LOG_HELP("Usage:^3 sv_cmd ");
1763 LOG_HELP(" No arguments required.");
1764 return;
1765 }
1766 }
1767}
1768*/
1769
1770
1771// ==================================
1772// Macro system for server commands
1773// ==================================
1774
1775// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
1776SERVER_COMMAND(adminmsg, "Send an admin message to a client directly") { GameCommand_adminmsg(request, arguments); }
1777SERVER_COMMAND(allready, "Ends warmup and starts the match") { GameCommand_allready(request); }
1778SERVER_COMMAND(allspec, "Force all players to spectate") { GameCommand_allspec(request, arguments); }
1779SERVER_COMMAND(anticheat, "Create an anticheat report for a client") { GameCommand_anticheat(request, arguments); }
1780SERVER_COMMAND(animbench, "Benchmark model animation (LAGS)") { GameCommand_animbench(request, arguments); }
1781SERVER_COMMAND(bbox, "Print detailed information about world size") { GameCommand_bbox(request); }
1782SERVER_COMMAND(bot_cmd, "Control and send commands to bots") { GameCommand_bot_cmd(request, arguments, command); }
1783SERVER_COMMAND(cointoss, "Flip a virtual coin and give random result") { GameCommand_cointoss(request, arguments); }
1784SERVER_COMMAND(database, "Extra controls of the serverprogs database") { GameCommand_database(request, arguments); }
1785SERVER_COMMAND(defer_clear, "Clear all queued defer commands for a specific client") { GameCommand_defer_clear(request, arguments); }
1786SERVER_COMMAND(defer_clear_all, "Clear all queued defer commands for all clients") { GameCommand_defer_clear_all(request); }
1787SERVER_COMMAND(delrec, "Delete race time record for a map") { GameCommand_delrec(request, arguments); }
1788SERVER_COMMAND(effectindexdump, "Dump list of effects from code and effectinfo.txt") { GameCommand_effectindexdump(request); }
1789SERVER_COMMAND(extendmatchtime, "Increase the timelimit value incrementally") { GameCommand_extendmatchtime(request); }
1790SERVER_COMMAND(gametype, "Simple command to change the active gametype") { GameCommand_gametype(request, arguments); }
1791SERVER_COMMAND(gettaginfo, "Get specific information about a weapon model") { GameCommand_gettaginfo(request, arguments); }
1792SERVER_COMMAND(gotomap, "Simple command to switch to another map") { GameCommand_gotomap(request, arguments); }
1793SERVER_COMMAND(lockteams, "Disable the ability for players to switch or enter teams") { GameCommand_lockteams(request); }
1794SERVER_COMMAND(make_mapinfo, "Automatically rebuild mapinfo files") { GameCommand_make_mapinfo(request); }
1795SERVER_COMMAND(moveplayer, "Change the team/status of a player") { GameCommand_moveplayer(request, arguments); }
1796SERVER_COMMAND(nextmap, "Set/Query the next map") { GameCommand_nextmap(request, arguments); }
1797SERVER_COMMAND(nospectators, "Automatically remove spectators from a match") { GameCommand_nospectators(request); }
1798SERVER_COMMAND(printstats, "Dump eventlog player stats and other score information") { GameCommand_printstats(request); }
1799SERVER_COMMAND(radarmap, "Generate a radar image of the map") { GameCommand_radarmap(request, arguments); }
1800SERVER_COMMAND(reducematchtime, "Decrease the timelimit value incrementally") { GameCommand_reducematchtime(request); }
1801SERVER_COMMAND(resetmatch, "Soft restart the game without changing teams; goes back to warmup if enabled") { GameCommand_resetmatch(request); }
1802SERVER_COMMAND(setbots, "Adjust how many bots are in the match") { GameCommand_setbots(request, arguments); }
1803SERVER_COMMAND(shuffleteams, "Randomly move players to different teams") { GameCommand_shuffleteams(request); }
1804SERVER_COMMAND(stuffto, "Send a command to be executed on a client") { GameCommand_stuffto(request, arguments); }
1805SERVER_COMMAND(trace, "Various debugging tools with tracing") { GameCommand_trace(request, arguments); }
1806SERVER_COMMAND(unlockteams, "Enable the ability for players to switch or enter teams") { GameCommand_unlockteams(request); }
1807SERVER_COMMAND(warp, "Choose different level in campaign") { GameCommand_warp(request, arguments); }
1808
1810{
1811 FOREACH(SERVER_COMMANDS, true, { LOG_HELPF(" ^2%s^7: %s", it.m_name, it.m_description); });
1812}
1813
1814float GameCommand_macro_command(int argc, string command)
1815{
1816 string c = strtolower(argv(0));
1817 FOREACH(SERVER_COMMANDS, it.m_name == c, {
1818 it.m_invokecmd(it, CMD_REQUEST_COMMAND, NULL, argc, command);
1819 return true;
1820 });
1821 return false;
1822}
1823
1825{
1826 string c = strtolower(argv(1));
1827 FOREACH(SERVER_COMMANDS, it.m_name == c, {
1828 it.m_invokecmd(it, CMD_REQUEST_USAGE, NULL, argc, "");
1829 return true;
1830 });
1831 return false;
1832}
1833
1835{
1836 FOREACH(SERVER_COMMANDS, true, { CMD_Write_Alias("qc_cmd_sv", it.m_name, it.m_description); });
1837}
1838
1839
1840// =========================================
1841// Main Function Called By Engine (sv_cmd)
1842// =========================================
1843// If this function exists, game code handles gamecommand instead of the engine code.
1844
1845void GameCommand(string command)
1846{
1847 int argc = tokenize_console(command);
1848
1849 // Guide for working with argc arguments by example:
1850 // argc: 1 - 2 - 3 - 4
1851 // argv: 0 - 1 - 2 - 3
1852 // cmd vote - master - login - password
1853
1854 if (strtolower(argv(0)) == "help")
1855 {
1856 if (argc == 1)
1857 {
1858 LOG_HELP("Server console commands:");
1860
1861 LOG_HELP("\nBanning commands:");
1863
1864 LOG_HELP("\nCommon networked commands:");
1866
1867 LOG_HELP("\nGeneric commands shared by all programs:");
1869
1870 LOG_HELP("\nUsage:^3 sv_cmd <command>^7, where possible commands are listed above.\n"
1871 "For help about a specific command, type sv_cmd help <command>");
1872
1873 return;
1874 }
1875 else if (BanCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
1876 {
1877 return;
1878 }
1879 else if (CommonCommand_macro_usage(argc, NULL)) // same here, but for common commands instead
1880 {
1881 return;
1882 }
1883 else if (GenericCommand_macro_usage(argc)) // same here, but for generic commands instead
1884 {
1885 return;
1886 }
1887 else if (GameCommand_macro_usage(argc)) // finally try for normal commands too
1888 {
1889 return;
1890 }
1891 }
1892 else if (MUTATOR_CALLHOOK(SV_ParseServerCommand, strtolower(argv(0)), argc, command))
1893 {
1894 return; // handled by a mutator
1895 }
1896 else if (BanCommand(command))
1897 {
1898 return; // handled by server/command/ipban.qc
1899 }
1900 else if (CommonCommand_macro_command(argc, NULL, command))
1901 {
1902 return; // handled by server/command/common.qc
1903 }
1904 else if (GenericCommand(command))
1905 {
1906 return; // handled by common/command/generic.qc
1907 }
1908 else if (GameCommand_macro_command(argc, command)) // continue as usual and scan for normal commands
1909 {
1910 return; // handled by one of the above GameCommand_* functions
1911 }
1912
1913 // nothing above caught the command, must be invalid
1914 LOG_INFO(((command != "") ? strcat("Unknown server command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try sv_cmd help.");
1915}
void bot_resetqueues()
entity find_bot_by_number(float number)
Definition scripting.qc:246
bool bot_fixcount(bool multiple_per_frame)
Definition bot.qc:623
entity find_bot_by_name(string name)
Definition scripting.qc:235
void bot_queuecommand(entity bot, string cmdstring)
Definition scripting.qc:30
void bot_cmdhelp(string scmd)
Definition scripting.qc:331
bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode)
void bot_list_commands()
Definition scripting.qc:444
void BanCommand_macro_help()
Definition banning.qc:480
float BanCommand_macro_usage(int argc)
Definition banning.qc:500
float BanCommand(string command)
Definition banning.qc:520
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
bool warmup_stage
Definition main.qh:120
entity gametype
Definition main.qh:43
const int CMD_REQUEST_COMMAND
Definition command.qh:3
const int CMD_REQUEST_USAGE
Definition command.qh:4
#define IS_PLAYER(s)
Definition player.qh:242
#define autocvar_timelimit
Definition stats.qh:92
float game_starttime
Definition stats.qh:82
string playername(string thename, int teamid, bool team_colorize)
Definition util.qc:2178
float cvar_settemp(string tmp_cvar, string tmp_value)
Definition util.qc:807
string strtolower(string s)
const vector PL_MIN_CONST
Definition constants.qh:56
const vector PL_MAX_CONST
Definition constants.qh:55
const float MOVE_NOMONSTERS
float DPCONTENTS_BOTCLIP
float GETTIME_HIRES
float gettaginfo_parent
float DPCONTENTS_SOLID
const float MOVE_NORMAL
float DPCONTENTS_BODY
vector gettaginfo_forward
string gettaginfo_name
const float FILE_READ
float DPCONTENTS_PLAYERCLIP
float time
vector trace_endpos
float trace_startsolid
float nextthink
float MOVE_WORLDONLY
vector gettaginfo_right
vector gettaginfo_up
float trace_fraction
vector gettaginfo_offset
#define spawn
ERASEABLE string MakeConsoleSafe(string input)
escape the string to make it safe for consoles
Definition cvar.qh:24
#define gettagindex
#define tokenize_console
#define argv_start_index
#define particleeffectnum(e)
Definition effect.qh:3
model
Definition ent_cs.qc:139
float GenericCommand_macro_usage(int argc)
Definition generic.qc:582
void GenericCommand_macro_help()
Definition generic.qc:567
float GenericCommand(string command)
Definition generic.qc:603
#define CMD_Write_Alias(execute, command, description)
Definition generic.qh:34
void Set_NextMap(string mapname)
string GetMapname()
string GotoMap(string m)
#define get_nextmap()
#define FOREACH(list, cond, body)
Definition iter.qh:19
#define LOG_HELP(...)
Definition log.qh:85
#define LOG_INFO(...)
Definition log.qh:65
#define LOG_TRACE(...)
Definition log.qh:76
#define LOG_HELPF(...)
Definition log.qh:86
#define LOG_INFOF(...)
Definition log.qh:66
ERASEABLE void db_close(int db)
Definition map.qh:84
ERASEABLE int db_load(string filename)
Definition map.qh:35
ERASEABLE int db_create()
Definition map.qh:25
ERASEABLE void db_save(int db, string filename)
Definition map.qh:8
ERASEABLE string db_get(int db, string key)
Definition map.qh:91
ERASEABLE void db_put(int db, string key, string value)
Definition map.qh:101
ERASEABLE void db_dump(int db, string filename)
Definition map.qh:69
float MapInfo_FilterGametype(Gametype pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
Definition mapinfo.qc:176
int MapInfo_RequiredFlags()
Definition mapinfo.qc:1670
float _MapInfo_FilterGametype(vector pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
Definition mapinfo.qc:180
Gametype MapInfo_CurrentGametype()
Definition mapinfo.qc:1482
int MapInfo_ForbiddenFlags()
Definition mapinfo.qc:1655
int MapInfo_CurrentFeatures()
Definition mapinfo.qc:1472
Gametype MapInfo_Type_FromString(string gtype, bool dowarn, bool is_q3compat)
Definition mapinfo.qc:620
void MapInfo_Enumerate()
Definition mapinfo.qc:134
vector MAPINFO_TYPE_ALL
Definition mapinfo.qh:27
#define M_PI
Definition mathlib.qh:108
bool autocvar_g_campaign
Definition menu.qc:752
void localcmd(string command,...)
void cvar_set(string name, string value)
string fgets(float fhandle)
void fclose(float fhandle)
float stof(string val,...)
entity nextent(entity e)
string substring(string s, float start, float length)
void sprint(float clientnum, string text,...)
float fopen(string filename, float mode)
float gettime(void)
vector stov(string s)
float random(void)
void bprint(string text,...)
float vlen(vector v)
vector randomvec(void)
void centerprint(string text,...)
string vtos(vector v)
float min(float f,...)
float rint(float f)
vector normalize(vector v)
string ftos(float f)
string argv(float n)
float max(float f,...)
#define etof(e)
Definition misc.qh:25
string string_null
Definition nil.qh:9
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1points f2
Definition all.inc:366
f1
Definition all.inc:563
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
#define NULL
Definition post.qh:14
#define world
Definition post.qh:15
#define gettaginfo
Definition post.qh:32
#define error
Definition pre.qh:6
#define stuffcmd(cl,...)
Definition progsdefs.qh:23
bool RadarMap_Make(int argc)
Definition radarmap.qh:3
bool IsTeamAvailable(int team_num)
entity bot_cmd
Definition scripting.qh:59
#define setthink(e, f)
vector
Definition self.qh:92
vector org
Definition self.qh:92
void CampaignLevelWarp(float n)
Definition campaign.qc:262
void PutObserverInServer(entity this, bool is_forced, bool use_spawnpoint)
putting a client as observer in the server
Definition client.qc:261
entity GetIndexedEntity(int argc, int start_index)
Definition common.qc:82
int VerifyClientEntity(entity client, bool must_be_real, bool must_be_bots)
Definition common.qc:47
string GetCallerName(entity caller)
Definition common.qc:33
entity GetFilteredEntity(string input)
Definition common.qc:143
float CommonCommand_macro_usage(int argc, entity caller)
Definition common.qh:178
void CommonCommand_macro_help(entity caller)
Definition common.qh:163
#define GetClientErrorString(clienterror, original_input)
Definition common.qh:87
int next_token
Definition common.qh:71
float CommonCommand_macro_command(int argc, entity caller, string command)
Definition common.qh:168
#define SERVER_COMMAND(id, description)
Definition reg.qh:9
string ValidateMap(string validated_map, entity caller)
Definition vote.qc:672
void ReadyRestart(bool forceWarmupEnd)
Definition vote.qc:526
bool GameTypeVote_SetGametype(Gametype type, string gametype_string, bool call_hooks)
Definition mapvoting.qc:835
void anticheat_report_to_eventlog(entity this)
Definition anticheat.qc:210
ERASEABLE string car(string s)
returns first word
Definition string.qh:259
ERASEABLE string cdr(string s)
returns all but first word
Definition string.qh:268
void GameCommand_stuffto(int request, int argc)
Definition sv_cmd.qc:1436
void GameCommand_effectindexdump(int request)
Definition sv_cmd.qc:659
void GameCommand_cointoss(int request, int argc)
Definition sv_cmd.qc:477
void GameCommand_unlockteams(int request)
Definition sv_cmd.qc:1666
void GameCommand_radarmap(int request, int argc)
Definition sv_cmd.qc:1261
void GameCommand_delrec(int request, int argc)
Definition sv_cmd.qc:625
void GameCommand_gotomap(int request, int argc)
Definition sv_cmd.qc:928
void GameCommand_allready(int request)
Definition sv_cmd.qc:165
float GameCommand_macro_command(int argc, string command)
Definition sv_cmd.qc:1814
void GameCommand_resetmatch(int request)
Definition sv_cmd.qc:1411
void print_Effect_Index(int d, string effect_name)
Definition sv_cmd.qc:652
void GameCommand_animbench(int request, int argc)
Definition sv_cmd.qc:869
void changematchtime(float delta, float mi, float ma)
Definition sv_cmd.qc:48
void shuffleteams()
Definition sv_cmd.qc:1337
void GameCommand_database(int request, int argc)
Definition sv_cmd.qc:506
void GameCommand_bbox(int request)
Definition sv_cmd.qc:265
void GameCommand_defer_clear_all(int request)
Definition sv_cmd.qc:591
void GameCommand_extendmatchtime(int request)
Definition sv_cmd.qc:738
void GameCommand_setbots(int request, int argc)
Definition sv_cmd.qc:1309
void make_mapinfo_Think(entity this)
Definition sv_cmd.qc:32
void GameCommand_make_mapinfo(int request)
Definition sv_cmd.qc:994
void GameCommand_shuffleteams(int request)
Definition sv_cmd.qc:1379
void GameCommand_gettaginfo(int request, int argc)
Definition sv_cmd.qc:805
void GameCommand_lockteams(int request)
Definition sv_cmd.qc:958
void GameCommand_nospectators(int request)
Definition sv_cmd.qc:1208
void GameCommand_warp(int request, int argc)
Definition sv_cmd.qc:1700
void GameCommand_allspec(int request, int argc)
Definition sv_cmd.qc:196
void GameCommand_bot_cmd(int request, int argc, string command)
Definition sv_cmd.qc:338
void GameCommand_adminmsg(int request, int argc)
Definition sv_cmd.qc:88
void GameCommand_nextmap(int request, int argc)
Definition sv_cmd.qc:1172
void GameCommand_anticheat(int request, int argc)
Definition sv_cmd.qc:229
void GameCommand_moveplayer(int request, int argc)
Definition sv_cmd.qc:1018
void GameCommand_reducematchtime(int request)
Definition sv_cmd.qc:1283
void GameCommand(string command)
Definition sv_cmd.qc:1845
void GameCommand_macro_help()
Definition sv_cmd.qc:1809
float GameCommand_macro_usage(int argc)
Definition sv_cmd.qc:1824
void GameCommand_defer_clear(int request, int argc)
Definition sv_cmd.qc:549
void GameCommand_gametype(int request, int argc)
Definition sv_cmd.qc:764
void GameCommand_macro_write_aliases(float fh)
Definition sv_cmd.qc:1834
void GameCommand_printstats(int request)
Definition sv_cmd.qc:1235
void GameCommand_trace(int request, int argc)
Definition sv_cmd.qc:1490
bool shuffleteams_on_reset_map
Definition sv_cmd.qh:7
void race_deleteTime(string map, float pos)
Definition race.qc:461
#define INGAME(it)
Definition sv_rules.qh:24
int Entity_GetTeamIndex(entity this)
Returns the team index of the given entity.
Definition teamplay.qc:181
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition teamplay.qc:599
bool Player_HasRealForcedTeam(entity player)
Returns whether player has real forced team.
Definition teamplay.qc:313
int Player_GetForcedTeamIndex(entity player)
Returns the index of the forced team of the given player.
Definition teamplay.qc:318
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings.
Definition teamplay.qc:459
bool TeamBalance_IsTeamAllowed(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition teamplay.qc:826
void Player_SetForcedTeamIndex(entity player, int team_index)
Sets the index of the forced team of the given player.
Definition teamplay.qc:323
int TeamBalance_FindBestTeam(entity balance, entity player, bool ignore_player)
Finds the team that will make the game most balanced if the player joins it.
Definition teamplay.qc:944
bool MoveToTeam(entity client, int team_index, int type)
Moves player to the specified team.
Definition teamplay.qc:299
@ TEAM_FORCE_DEFAULT
Don't force any team.
Definition teamplay.qh:138
bool lockteams
Definition teamplay.qh:15
int Team_TeamToIndex(int team_num)
Converts team value into team index.
Definition teams.qh:184
#define Team_ColoredFullName(teamid)
Definition teams.qh:232
int Team_IndexToTeam(int index)
Converts team index into team value.
Definition teams.qh:169
const int NUM_TEAMS
Number of teams in the game.
Definition teams.qh:3
bool teamplay
Definition teams.qh:59
float Team_ColorToTeam(string team_color)
Definition teams.qh:116
#define IS_OBSERVER(v)
Definition utils.qh:11
#define FOREACH_CLIENT_RANDOM(cond, body)
Definition utils.qh:58
#define IS_SPEC(v)
Definition utils.qh:10
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition utils.qh:15
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
void DumpStats(float final)
Definition world.qc:1265
float autocvar_timelimit_max
Definition world.qh:27
int world_initialized
Definition world.qh:43
float autocvar_timelimit_min
Definition world.qh:26
float autocvar_timelimit_decrement
Definition world.qh:25
float autocvar_timelimit_increment
Definition world.qh:24
float ServerProgsDB
Definition world.qh:128