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 += 1;
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;
1001
1002 tmp_entity = new(make_mapinfo);
1003 setthink(tmp_entity, make_mapinfo_Think);
1004 tmp_entity.nextthink = time;
1006 return;
1007 }
1008
1009 default:
1010 case CMD_REQUEST_USAGE:
1011 {
1012 LOG_HELP("Usage:^3 sv_cmd make_mapinfo");
1013 LOG_HELP(" No arguments required.");
1014 LOG_HELP("See also: ^2radarmap^7");
1015 return;
1016 }
1017 }
1018}
1019
1020void GameCommand_moveplayer(int request, int argc)
1021{
1022 switch (request)
1023 {
1025 {
1026 if (!world_initialized)
1027 {
1028 LOG_HELPF("This command works only when the server is running.");
1029 return;
1030 }
1031 float accepted;
1032 entity client;
1033
1034 string targets = strreplace(",", " ", argv(1));
1035 string original_targets = strreplace(" ", ", ", targets);
1036 string destination = argv(2);
1037 if (destination == "spec")
1038 destination = "spectator";
1039
1040 if ((targets) && (destination))
1041 {
1042 string successful = string_null;
1043 string t;
1044 for ( ; targets; )
1045 {
1046 t = car(targets);
1047 targets = cdr(targets);
1048
1049 // Check to see if the player is a valid target
1050 client = GetFilteredEntity(t);
1051 accepted = VerifyClientEntity(client, false, false);
1052 string client_num_str = ftos(etof(client));
1053
1054 if (accepted <= 0)
1055 {
1056 LOG_INFO("moveplayer: ", GetClientErrorString(accepted, t), ".");
1057 }
1058 else if (destination == "spectator")
1059 {
1060 string pl_name = playername(client.netname, client.team, false);
1061 if (!(IS_SPEC(client) || IS_OBSERVER(client)) || INGAME(client))
1062 {
1063 PutObserverInServer(client, true, true);
1064
1065 successful = strcat(successful, (successful ? ", " : ""), pl_name);
1066 }
1067 else
1068 {
1069 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is already spectating.");
1070 }
1071 }
1072 else
1073 {
1074 if (!teamplay)
1075 {
1076 LOG_INFO("Can't change teams when currently not playing a team game.");
1077 return;
1078 }
1079
1080 string pl_name = playername(client.netname, client.team, false);
1081 if (IS_SPEC(client) || IS_OBSERVER(client))
1082 {
1083 // well technically we could, but should we allow that? :P
1084 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is not in the game.");
1085 continue;
1086 }
1087
1088 // set up
1089 int save = Player_GetForcedTeamIndex(client);
1091
1092 // find the team to move the player to
1093 int team_num = Team_ColorToTeam(destination);
1094 entity balance;
1095 if (team_num == client.team) // already on the destination team
1096 {
1097 // keep the forcing undone
1098 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is already on the ",
1099 Team_ColoredFullName(team_num), ".");
1100 continue;
1101 }
1102 else if (team_num == 0) // auto team
1103 {
1104 balance = TeamBalance_CheckAllowedTeams(client);
1105 team_num = Team_IndexToTeam(TeamBalance_FindBestTeam(balance, client, false));
1106 }
1107 else
1108 {
1109 balance = TeamBalance_CheckAllowedTeams(client);
1110 }
1111 Player_SetForcedTeamIndex(client, save);
1112
1113 // Check to see if the destination team is even available
1114 int team_id = Team_TeamToIndex(team_num);
1115 if (team_id == -1)
1116 {
1117 LOG_INFO("Can't move player to ", destination, " team because it doesn't exist.");
1118 TeamBalance_Destroy(balance);
1119 return;
1120 }
1121 if (!IsTeamAvailable(team_num))
1122 {
1123 LOG_INFO("Can't move player to ", destination, " team because it isn't available.");
1124 TeamBalance_Destroy(balance);
1125 return;
1126 }
1127 if (!TeamBalance_IsTeamAllowed(balance, team_id))
1128 {
1129 LOG_INFO("Player #", client_num_str, " (", pl_name, ") is not allowed to join the ",
1130 Team_ColoredFullName(team_num), ".");
1131 TeamBalance_Destroy(balance);
1132 continue;
1133 }
1134 TeamBalance_Destroy(balance);
1135
1136 // If so, lets continue and finally move the player
1138 if (MoveToTeam(client, team_id, 6))
1139 {
1140 successful = strcat(successful, (successful ? ", " : ""), pl_name);
1141 LOG_INFO("Player #", client_num_str, " (", pl_name, ") has been moved to the ",
1142 Team_ColoredFullName(team_num), ".");
1143 }
1144 else
1145 {
1146 LOG_INFO("Unable to move player #", client_num_str, " (", pl_name, ")");
1147 }
1148 }
1149 } // loop end
1150
1151 if (successful) bprint("Successfully moved players ", successful, " to destination ", destination, ".\n");
1152 else LOG_INFO("No players given (", original_targets, ") are able to move.");
1153
1154 return; // still correct parameters so return to avoid usage print
1155 }
1156 }
1157
1158 default:
1159 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1160 case CMD_REQUEST_USAGE:
1161 {
1162 LOG_HELP("Usage:^3 sv_cmd moveplayer <clients> <destination>");
1163 LOG_HELP(" <clients> is a list (separated by commas) of player entity ID's or nicknames");
1164 LOG_HELP(" <destination> is what to send the player to, be it team or spectating");
1165 LOG_HELP(" Full list of destinations here: spec, spectator, red, blue, yellow, pink, auto.");
1166 LOG_HELP("Examples: sv_cmd moveplayer 1,3,5 red");
1167 LOG_HELP(" sv_cmd moveplayer 2 spec");
1168 LOG_HELP("See also: ^2allspec, shuffleteams^7");
1169 return;
1170 }
1171 }
1172}
1173
1174void GameCommand_nextmap(int request, int argc)
1175{
1176 switch (request)
1177 {
1179 {
1180 if (argc >= 2) // nextmap with mapname arg
1181 {
1182 if (argc > 2)
1183 LOG_HELP("Warning: nextmap only takes 1 argument");
1184
1185 string map = ValidateMap(argv(1), NULL);
1186 if (map != "" && map != get_nextmap())
1187 Set_NextMap(map);
1188 }
1189 else // nextmap without args
1190 {
1191 if (get_nextmap() != "")
1193 else
1194 LOG_HELP("none");
1195 }
1196 return; // never fall through to usage
1197 }
1198
1199 default:
1200 case CMD_REQUEST_USAGE:
1201 {
1202 LOG_HELP("Usage:^3 sv_cmd nextmap [<mapname>]");
1203 LOG_HELP(" Without arguments it prints current nextmap if one is set");
1204 LOG_HELP(" With arguments it attempts to set nextmap");
1205 return;
1206 }
1207 }
1208}
1209
1211{
1212 switch (request)
1213 {
1215 {
1216 if (!world_initialized)
1217 {
1218 LOG_HELPF("This command works only when the server is running.");
1219 return;
1220 }
1221 cvar_settemp("sv_spectate", "0");
1222 // if sv_spectate was enabled PlayerFrame() sends SPECTATE_WARNING notifications
1223 return;
1224 }
1225
1226 default:
1227 case CMD_REQUEST_USAGE:
1228 {
1229 LOG_HELP("Usage:^3 sv_cmd nospectators");
1230 LOG_HELP(" No arguments required.");
1231 LOG_HELP("Temporarily disables the ^3sv_spectate ^7cvar.");
1232 return;
1233 }
1234 }
1235}
1236
1237void GameCommand_printstats(int request)
1238{
1239 switch (request)
1240 {
1242 {
1243 if (!world_initialized)
1244 {
1245 LOG_HELPF("This command works only when the server is running.");
1246 return;
1247 }
1248 DumpStats(false);
1249 LOG_INFO("stats dumped.");
1250 return;
1251 }
1252
1253 default:
1254 case CMD_REQUEST_USAGE:
1255 {
1256 LOG_HELP("Usage:^3 sv_cmd printstats");
1257 LOG_HELP(" No arguments required.");
1258 return;
1259 }
1260 }
1261}
1262
1263void GameCommand_radarmap(int request, int argc)
1264{
1265 switch (request)
1266 {
1268 {
1269 if (RadarMap_Make(argc)) return;
1270 }
1271
1272 default:
1273 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1274 case CMD_REQUEST_USAGE:
1275 {
1276 LOG_HELP("Usage:^3 sv_cmd radarmap [--force] [--loop] [--quit] [--block | --trace | --sample | --lineblock] [--sharpen N] [--res W H] [--qual Q]");
1277 LOG_HELP(" The quality factor Q is roughly proportional to the time taken.");
1278 LOG_HELP(" trace supports no quality factor; its result should look like --block with infinite quality factor.");
1279 LOG_HELP("See also: ^2make_mapinfo^7");
1280 return;
1281 }
1282 }
1283}
1284
1286{
1287 switch (request)
1288 {
1290 {
1291 if (!world_initialized)
1292 {
1293 LOG_HELPF("This command works only when the server is running.");
1294 return;
1295 }
1297 return;
1298 }
1299
1300 default:
1301 case CMD_REQUEST_USAGE:
1302 {
1303 LOG_HELP("Usage:^3 sv_cmd reducematchtime");
1304 LOG_HELP(" No arguments required.");
1305 LOG_HELP("See also: ^2extendmatchtime^7");
1306 return;
1307 }
1308 }
1309}
1310
1311void GameCommand_setbots(int request, int argc)
1312{
1313 switch (request)
1314 {
1316 {
1317 if (argc >= 2)
1318 {
1319 cvar_settemp("minplayers", "0");
1320 cvar_settemp("minplayers_per_team", "0");
1321 cvar_settemp("bot_number", argv(1));
1322 bot_fixcount(true);
1323 return;
1324 }
1325 }
1326
1327 default:
1328 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1329 case CMD_REQUEST_USAGE:
1330 {
1331 LOG_HELP("Usage:^3 sv_cmd setbots <botnumber>");
1332 LOG_HELP(" Where <botnumber> is the amount of bots to set bot_number cvar to.");
1333 LOG_HELP("See also: ^2bot_cmd^7");
1334 return;
1335 }
1336 }
1337}
1338
1340{
1341 if (!teamplay)
1342 {
1343 LOG_INFO("Can't shuffle teams when currently not playing a team game.");
1344 return;
1345 }
1346
1347 FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), {
1348 if (Player_HasRealForcedTeam(it)) {
1349 // we could theoretically assign forced players to their teams
1350 // and shuffle the rest to fill the empty spots but in practise
1351 // either all players or none are gonna have forced teams
1352 LOG_INFO("Can't shuffle teams because at least one player has a forced team.");
1353 return;
1354 }
1355 });
1356
1357 int number_of_teams = 0;
1359 for (int i = 1; i <= NUM_TEAMS; ++i)
1360 {
1361 if (TeamBalance_IsTeamAllowed(balance, i))
1362 {
1363 number_of_teams = max(i, number_of_teams);
1364 }
1365 }
1366 TeamBalance_Destroy(balance);
1367
1368 int team_index = 0;
1370 int target_team_index = team_index + 1;
1371 if (Entity_GetTeamIndex(it) != target_team_index)
1372 {
1373 MoveToTeam(it, target_team_index, 6);
1374 }
1375 team_index = (team_index + 1) % number_of_teams;
1376 });
1377
1378 bprint("Successfully shuffled the players around randomly.\n");
1379}
1380
1382{
1383 switch (request)
1384 {
1386 {
1387 if (!world_initialized)
1388 {
1389 LOG_HELPF("This command works only when the server is running.");
1390 return;
1391 }
1393 {
1394 bprint("Players will be shuffled when this round is over.\n");
1396 }
1397 else
1398 shuffleteams();
1399 return;
1400 }
1401
1402 default:
1403 case CMD_REQUEST_USAGE:
1404 {
1405 LOG_HELP("Usage:^3 sv_cmd shuffleteams");
1406 LOG_HELP(" No arguments required.");
1407 LOG_HELP("See also: ^2moveplayer, allspec^7");
1408 return;
1409 }
1410 }
1411}
1412
1413void GameCommand_resetmatch(int request)
1414{
1415 switch (request)
1416 {
1418 {
1419 if (!world_initialized)
1420 {
1421 LOG_HELPF("This command works only when the server is running.");
1422 return;
1423 }
1424 ReadyRestart(false);
1425 return;
1426 }
1427
1428 default:
1429 case CMD_REQUEST_USAGE:
1430 {
1431 LOG_HELP("Usage:^3 sv_cmd resetmatch");
1432 LOG_HELP(" No arguments required.");
1433 return;
1434 }
1435 }
1436}
1437
1438void GameCommand_stuffto(int request, int argc)
1439{
1440 // This... is a fairly dangerous and powerful command... - It allows any arguments to be sent to a client via rcon.
1441 // Because of this, it is disabled by default and must be enabled by the server owner when doing compilation. That way,
1442 // we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument.
1443
1444#ifdef STUFFTO_ENABLED
1445 switch (request)
1446 {
1448 {
1449 if (!world_initialized)
1450 {
1451 LOG_HELPF("This command works only when the server is running.");
1452 return;
1453 }
1454 if (argv(2))
1455 {
1456 entity client = GetIndexedEntity(argc, 1);
1457 float accepted = VerifyClientEntity(client, true, false);
1458
1459 if (accepted > 0)
1460 {
1461 stuffcmd(client, strcat("\n", argv(next_token), "\n"));
1462 LOG_INFO("Command: \"", argv(next_token), "\" sent to ", GetCallerName(client), " (", argv(1), ").");
1463 }
1464 else
1465 {
1466 LOG_INFO("stuffto: ", GetClientErrorString(accepted, argv(1)), ".");
1467 }
1468
1469 return;
1470 }
1471 }
1472
1473 default:
1474 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1475 case CMD_REQUEST_USAGE:
1476 {
1477 LOG_HELP("Usage:^3 sv_cmd stuffto <client> \"<command>\"");
1478 LOG_HELP(" <client> is the entity number or name of the player,");
1479 LOG_HELP(" and <command> is the command to be sent to that player.");
1480 return;
1481 }
1482 }
1483#else
1484 if (request)
1485 {
1486 LOG_HELP("stuffto command is not enabled on this server.");
1487 return;
1488 }
1489#endif
1490}
1491
1492void GameCommand_trace(int request, int argc)
1493{
1494 switch (request)
1495 {
1497 {
1498 entity e;
1499 vector org, delta, start, end, p, q, q0, pos, vv, dv;
1500 float i, f, safe, unsafe, dq, dqf;
1501
1502 switch (argv(1))
1503 {
1504 case "debug":
1505 {
1506 float hitcount = 0;
1507 LOG_INFO("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.");
1508 float worst_endpos_bug = 0;
1509 for ( ; ; )
1510 {
1511 org = world.mins;
1512 delta = world.maxs - world.mins;
1513
1514 start.x = org.x + random() * delta.x;
1515 start.y = org.y + random() * delta.y;
1516 start.z = org.z + random() * delta.z;
1517
1518 end.x = org.x + random() * delta.x;
1519 end.y = org.y + random() * delta.y;
1520 end.z = org.z + random() * delta.z;
1521
1522 start = stov(vtos(start));
1523 end = stov(vtos(end));
1524
1525 tracebox(start, PL_MIN_CONST, PL_MAX_CONST, end, MOVE_NOMONSTERS, NULL);
1526 if (!trace_startsolid && trace_fraction < 1)
1527 {
1528 p = trace_endpos;
1529 tracebox(p, PL_MIN_CONST, PL_MAX_CONST, p, MOVE_NOMONSTERS, NULL);
1530 if (trace_startsolid)
1531 {
1532 rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid
1533 tracebox(start, PL_MIN_CONST, PL_MAX_CONST, end, MOVE_NOMONSTERS, NULL);
1534
1535 // how much do we need to back off?
1536 safe = 1;
1537 unsafe = 0;
1538 for ( ; ; )
1539 {
1540 pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5);
1541 tracebox(pos, PL_MIN_CONST, PL_MAX_CONST, pos, MOVE_NOMONSTERS, NULL);
1542 if (trace_startsolid)
1543 {
1544 if ((safe + unsafe) * 0.5 == unsafe) break;
1545 unsafe = (safe + unsafe) * 0.5;
1546 }
1547 else
1548 {
1549 if ((safe + unsafe) * 0.5 == safe) break;
1550 safe = (safe + unsafe) * 0.5;
1551 }
1552 }
1553
1554 LOG_INFO("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu");
1555 LOG_INFO("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu");
1556
1557 tracebox(p, PL_MIN_CONST + '0.1 0.1 0.1', PL_MAX_CONST - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, NULL);
1558 if (trace_startsolid) LOG_INFO("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p));
1559 else LOG_INFO("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p));
1560 if (++hitcount >= 10) break;
1561 }
1562 else
1563 {
1564 q0 = p;
1565 dq = 0;
1566 dqf = 1;
1567 for ( ; ; )
1568 {
1569 q = p + normalize(end - p) * (dq + dqf);
1570 if (q == q0) break;
1571 tracebox(p, PL_MIN_CONST, PL_MAX_CONST, q, MOVE_NOMONSTERS, NULL);
1572 if (trace_startsolid) error("THIS ONE cannot happen");
1573 if (trace_fraction > 0) dq += dqf * trace_fraction;
1574 dqf *= 0.5;
1575 q0 = q;
1576 }
1577 if (dq > worst_endpos_bug)
1578 {
1579 worst_endpos_bug = dq;
1580 LOG_INFO("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p));
1581 LOG_INFO("could go ", ftos(dq), " units further to ", vtos(q));
1582 if (++hitcount >= 10) break;
1583 }
1584 }
1585 }
1586 }
1587 return;
1588 }
1589
1590 case "debug2":
1591 {
1592 e = nextent(NULL);
1593 tracebox(e.origin + '0 0 32', e.mins, e.maxs, e.origin + '0 0 -1024', MOVE_NORMAL, e);
1594 vv = trace_endpos;
1595 if (trace_fraction == 1)
1596 {
1597 LOG_INFO("not above ground, aborting");
1598 return;
1599 }
1600 f = 0;
1601 for (i = 0; i < 100000; ++i)
1602 {
1603 dv = randomvec();
1604 if (dv.z > 0) dv = -1 * dv;
1605 tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e);
1606 if (trace_startsolid) LOG_INFO("bug 1");
1607 if (trace_fraction == 1)
1608 {
1609 if (dv.z < f)
1610 {
1611 LOG_INFO("bug 2: ", ftos(dv.x), " ", ftos(dv.y), " ", ftos(dv.z));
1612 LOG_INFO(" (", ftos(asin(dv.z / vlen(dv)) * 180 / M_PI), " degrees)");
1613 f = dv.z;
1614 }
1615 }
1616 }
1617 LOG_INFO("highest possible dist: ", ftos(f));
1618 return;
1619 }
1620
1621 case "walk":
1622 {
1623 if (argc == 4 || argc == 5)
1624 {
1625 e = nextent(NULL);
1626 int dphitcontentsmask_save = e.dphitcontentsmask;
1628 if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), stof(argv(4)), MOVE_NORMAL))
1629 LOG_INFO("can walk");
1630 else
1631 LOG_INFO("cannot walk");
1632 e.dphitcontentsmask = dphitcontentsmask_save;
1633 return;
1634 }
1635 }
1636
1637 case "showline":
1638 {
1639 if (argc == 4)
1640 {
1641 vv = stov(argv(2));
1642 dv = stov(argv(3));
1643 traceline(vv, dv, MOVE_NORMAL, NULL);
1644 __trailparticles(NULL, particleeffectnum(EFFECT_TR_NEXUIZPLASMA), vv, trace_endpos);
1645 __trailparticles(NULL, particleeffectnum(EFFECT_TR_CRYLINKPLASMA), trace_endpos, dv);
1646 return;
1647 }
1648 }
1649
1650 // no default case, just go straight to invalid
1651 }
1652 }
1653
1654 default:
1655 LOG_HELPF("Incorrect parameters for ^2%s^7", argv(0));
1656 case CMD_REQUEST_USAGE:
1657 {
1658 LOG_HELP("Usage:^3 sv_cmd trace <command> [<startpos> <endpos>] [<endpos_height>]");
1659 LOG_HELP(" Where <startpos> and <endpos> are parameters for the 'walk' and 'showline' commands,");
1660 LOG_HELP(" <endpos_height> is an optional parameter for the 'walk' command,");
1661 LOG_HELP(" Full list of commands here: debug, debug2, walk, showline.");
1662 LOG_HELP("See also: ^2bbox, gettaginfo^7");
1663 return;
1664 }
1665 }
1666}
1667
1669{
1670 switch (request)
1671 {
1673 {
1674 if (!world_initialized)
1675 {
1676 LOG_HELPF("This command works only when the server is running.");
1677 return;
1678 }
1679 if (teamplay)
1680 {
1681 lockteams = 0;
1682 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_TEAMS_UNLOCKED);
1683 }
1684 else
1685 {
1686 bprint("unlockteams command can only be used in a team-based gametype.\n");
1687 }
1688 return;
1689 }
1690
1691 default:
1692 case CMD_REQUEST_USAGE:
1693 {
1694 LOG_HELP("Usage:^3 sv_cmd unlockteams");
1695 LOG_HELP(" No arguments required.");
1696 LOG_HELP("See also: ^2lockteams^7");
1697 return;
1698 }
1699 }
1700}
1701
1702void GameCommand_warp(int request, int argc)
1703{
1704 switch (request)
1705 {
1707 {
1708 if (!world_initialized)
1709 {
1710 LOG_HELPF("This command works only when the server is running.");
1711 return;
1712 }
1714 {
1715 if (argc >= 2)
1716 {
1718 LOG_INFO("Successfully warped to campaign level ", argv(1), ".");
1719 }
1720 else
1721 {
1723 LOG_INFO("Successfully warped to next campaign level.");
1724 }
1725 }
1726 else
1727 {
1728 LOG_INFO("Not in campaign, can't level warp");
1729 }
1730 return;
1731 }
1732
1733 default:
1734 case CMD_REQUEST_USAGE:
1735 {
1736 LOG_HELP("Usage:^3 sv_cmd warp [<level>]");
1737 LOG_HELP(" <level> is the level to change campaign mode to.");
1738 LOG_HELP(" if <level> is not provided it will change to the next level.");
1739 return;
1740 }
1741 }
1742}
1743
1744/* use this when creating a new command, making sure to place it in alphabetical order... also,
1745** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
1746void GameCommand_(int request)
1747{
1748 switch(request)
1749 {
1750 case CMD_REQUEST_COMMAND:
1751 {
1752 if (!world_initialized)
1753 {
1754 LOG_HELPF("This command works only when the server is running.");
1755 return;
1756 }
1757
1758 return;
1759 }
1760
1761 default:
1762 case CMD_REQUEST_USAGE:
1763 {
1764 LOG_HELP("Usage:^3 sv_cmd ");
1765 LOG_HELP(" No arguments required.");
1766 return;
1767 }
1768 }
1769}
1770*/
1771
1772
1773// ==================================
1774// Macro system for server commands
1775// ==================================
1776
1777// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
1778SERVER_COMMAND(adminmsg, "Send an admin message to a client directly") { GameCommand_adminmsg(request, arguments); }
1779SERVER_COMMAND(allready, "Ends warmup and starts the match") { GameCommand_allready(request); }
1780SERVER_COMMAND(allspec, "Force all players to spectate") { GameCommand_allspec(request, arguments); }
1781SERVER_COMMAND(anticheat, "Create an anticheat report for a client") { GameCommand_anticheat(request, arguments); }
1782SERVER_COMMAND(animbench, "Benchmark model animation (LAGS)") { GameCommand_animbench(request, arguments); }
1783SERVER_COMMAND(bbox, "Print detailed information about world size") { GameCommand_bbox(request); }
1784SERVER_COMMAND(bot_cmd, "Control and send commands to bots") { GameCommand_bot_cmd(request, arguments, command); }
1785SERVER_COMMAND(cointoss, "Flip a virtual coin and give random result") { GameCommand_cointoss(request, arguments); }
1786SERVER_COMMAND(database, "Extra controls of the serverprogs database") { GameCommand_database(request, arguments); }
1787SERVER_COMMAND(defer_clear, "Clear all queued defer commands for a specific client") { GameCommand_defer_clear(request, arguments); }
1788SERVER_COMMAND(defer_clear_all, "Clear all queued defer commands for all clients") { GameCommand_defer_clear_all(request); }
1789SERVER_COMMAND(delrec, "Delete race time record for a map") { GameCommand_delrec(request, arguments); }
1790SERVER_COMMAND(effectindexdump, "Dump list of effects from code and effectinfo.txt") { GameCommand_effectindexdump(request); }
1791SERVER_COMMAND(extendmatchtime, "Increase the timelimit value incrementally") { GameCommand_extendmatchtime(request); }
1792SERVER_COMMAND(gametype, "Simple command to change the active gametype") { GameCommand_gametype(request, arguments); }
1793SERVER_COMMAND(gettaginfo, "Get specific information about a weapon model") { GameCommand_gettaginfo(request, arguments); }
1794SERVER_COMMAND(gotomap, "Simple command to switch to another map") { GameCommand_gotomap(request, arguments); }
1795SERVER_COMMAND(lockteams, "Disable the ability for players to switch or enter teams") { GameCommand_lockteams(request); }
1796SERVER_COMMAND(make_mapinfo, "Automatically rebuild mapinfo files") { GameCommand_make_mapinfo(request); }
1797SERVER_COMMAND(moveplayer, "Change the team/status of a player") { GameCommand_moveplayer(request, arguments); }
1798SERVER_COMMAND(nextmap, "Set/Query the next map") { GameCommand_nextmap(request, arguments); }
1799SERVER_COMMAND(nospectators, "Automatically remove spectators from a match") { GameCommand_nospectators(request); }
1800SERVER_COMMAND(printstats, "Dump eventlog player stats and other score information") { GameCommand_printstats(request); }
1801SERVER_COMMAND(radarmap, "Generate a radar image of the map") { GameCommand_radarmap(request, arguments); }
1802SERVER_COMMAND(reducematchtime, "Decrease the timelimit value incrementally") { GameCommand_reducematchtime(request); }
1803SERVER_COMMAND(resetmatch, "Soft restart the game without changing teams; goes back to warmup if enabled") { GameCommand_resetmatch(request); }
1804SERVER_COMMAND(setbots, "Adjust how many bots are in the match") { GameCommand_setbots(request, arguments); }
1805SERVER_COMMAND(shuffleteams, "Randomly move players to different teams") { GameCommand_shuffleteams(request); }
1806SERVER_COMMAND(stuffto, "Send a command to be executed on a client") { GameCommand_stuffto(request, arguments); }
1807SERVER_COMMAND(trace, "Various debugging tools with tracing") { GameCommand_trace(request, arguments); }
1808SERVER_COMMAND(unlockteams, "Enable the ability for players to switch or enter teams") { GameCommand_unlockteams(request); }
1809SERVER_COMMAND(warp, "Choose different level in campaign") { GameCommand_warp(request, arguments); }
1810
1812{
1813 FOREACH(SERVER_COMMANDS, true, { LOG_HELPF(" ^2%s^7: %s", it.m_name, it.m_description); });
1814}
1815
1816float GameCommand_macro_command(int argc, string command)
1817{
1818 string c = strtolower(argv(0));
1819 FOREACH(SERVER_COMMANDS, it.m_name == c, {
1820 it.m_invokecmd(it, CMD_REQUEST_COMMAND, NULL, argc, command);
1821 return true;
1822 });
1823 return false;
1824}
1825
1827{
1828 string c = strtolower(argv(1));
1829 FOREACH(SERVER_COMMANDS, it.m_name == c, {
1830 it.m_invokecmd(it, CMD_REQUEST_USAGE, NULL, argc, "");
1831 return true;
1832 });
1833 return false;
1834}
1835
1837{
1838 FOREACH(SERVER_COMMANDS, true, { CMD_Write_Alias("qc_cmd_sv", it.m_name, it.m_description); });
1839}
1840
1841
1842// =========================================
1843// Main Function Called By Engine (sv_cmd)
1844// =========================================
1845// If this function exists, game code handles gamecommand instead of the engine code.
1846
1847void GameCommand(string command)
1848{
1849 int argc = tokenize_console(command);
1850
1851 // Guide for working with argc arguments by example:
1852 // argc: 1 - 2 - 3 - 4
1853 // argv: 0 - 1 - 2 - 3
1854 // cmd vote - master - login - password
1855
1856 if (strtolower(argv(0)) == "help")
1857 {
1858 if (argc == 1)
1859 {
1860 LOG_HELP("Server console commands:");
1862
1863 LOG_HELP("\nBanning commands:");
1865
1866 LOG_HELP("\nCommon networked commands:");
1868
1869 LOG_HELP("\nGeneric commands shared by all programs:");
1871
1872 LOG_HELP("\nUsage:^3 sv_cmd <command>^7, where possible commands are listed above.\n"
1873 "For help about a specific command, type sv_cmd help <command>");
1874
1875 return;
1876 }
1877 else if (BanCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
1878 {
1879 return;
1880 }
1881 else if (CommonCommand_macro_usage(argc, NULL)) // same here, but for common commands instead
1882 {
1883 return;
1884 }
1885 else if (GenericCommand_macro_usage(argc)) // same here, but for generic commands instead
1886 {
1887 return;
1888 }
1889 else if (GameCommand_macro_usage(argc)) // finally try for normal commands too
1890 {
1891 return;
1892 }
1893 }
1894 else if (MUTATOR_CALLHOOK(SV_ParseServerCommand, strtolower(argv(0)), argc, command))
1895 {
1896 return; // handled by a mutator
1897 }
1898 else if (BanCommand(command))
1899 {
1900 return; // handled by server/command/ipban.qc
1901 }
1902 else if (CommonCommand_macro_command(argc, NULL, command))
1903 {
1904 return; // handled by server/command/common.qc
1905 }
1906 else if (GenericCommand(command))
1907 {
1908 return; // handled by common/command/generic.qc
1909 }
1910 else if (GameCommand_macro_command(argc, command)) // continue as usual and scan for normal commands
1911 {
1912 return; // handled by one of the above GameCommand_* functions
1913 }
1914
1915 // nothing above caught the command, must be invalid
1916 LOG_INFO(((command != "") ? strcat("Unknown server command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try sv_cmd help.");
1917}
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:243
#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:2082
float cvar_settemp(string tmp_cvar, string tmp_value)
Definition util.qc:811
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:177
int MapInfo_RequiredFlags()
Definition mapinfo.qc:1679
float _MapInfo_FilterGametype(vector pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
Definition mapinfo.qc:181
Gametype MapInfo_CurrentGametype()
Definition mapinfo.qc:1490
int MapInfo_ForbiddenFlags()
Definition mapinfo.qc:1664
int MapInfo_CurrentFeatures()
Definition mapinfo.qc:1480
Gametype MapInfo_Type_FromString(string gtype, bool dowarn, bool is_q3compat)
Definition mapinfo.qc:621
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:747
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:364
f1
Definition all.inc:561
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:261
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:211
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:1438
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:1668
void GameCommand_radarmap(int request, int argc)
Definition sv_cmd.qc:1263
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:1816
void GameCommand_resetmatch(int request)
Definition sv_cmd.qc:1413
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:1339
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:1311
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:1381
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:1210
void GameCommand_warp(int request, int argc)
Definition sv_cmd.qc:1702
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:1174
void GameCommand_anticheat(int request, int argc)
Definition sv_cmd.qc:229
void GameCommand_moveplayer(int request, int argc)
Definition sv_cmd.qc:1020
void GameCommand_reducematchtime(int request)
Definition sv_cmd.qc:1285
void GameCommand(string command)
Definition sv_cmd.qc:1847
void GameCommand_macro_help()
Definition sv_cmd.qc:1811
float GameCommand_macro_usage(int argc)
Definition sv_cmd.qc:1826
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:1836
void GameCommand_printstats(int request)
Definition sv_cmd.qc:1237
void GameCommand_trace(int request, int argc)
Definition sv_cmd.qc:1492
bool shuffleteams_on_reset_map
Definition sv_cmd.qh:7
void race_deleteTime(string map, float pos)
Definition race.qc:462
#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:56
#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:50
#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:1244
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