Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
common.qc
Go to the documentation of this file.
1#include "common.qh"
2
7#include <common/stats.qh>
11#include <server/campaign.qh>
12#include <server/chat.qh>
13#include <server/client.qh>
16#include <server/scores.qh>
17#include <server/world.qh>
18
19
20// ====================================================
21// Shared code for server commands, written by Samual
22// Last updated: December 27th, 2011
23// ====================================================
24
25// select the proper prefix for usage and other messages
27{
28 if (caller) return "cmd";
29 else return "sv_cmd";
30}
31
32// if client return player nickname, or if server return admin nickname
33string GetCallerName(entity caller)
34{
35 if (caller) return playername(caller.netname, caller.team, false);
36 else return ((autocvar_sv_adminnick != "") ? autocvar_sv_adminnick : "SERVER ADMIN"); // autocvar_hostname
37}
38
39// verify that the client provided is acceptable for kicking
41{
42 if (!IS_REAL_CLIENT(client)) return CLIENT_NOT_REAL;
43 return CLIENT_ACCEPTABLE;
44}
45
46// verify that the client provided is acceptable for use
47int VerifyClientEntity(entity client, bool must_be_real, bool must_be_bots)
48{
49 if (!IS_CLIENT(client)) return CLIENT_DOESNT_EXIST;
50 else if (must_be_real && !IS_REAL_CLIENT(client)) return CLIENT_NOT_REAL;
51 else if (must_be_bots && !IS_BOT_CLIENT(client)) return CLIENT_NOT_BOT;
52
53 return CLIENT_ACCEPTABLE;
54}
55
56// if the client is not acceptable, return a string to be used for error messages
57string GetClientErrorString_color(float clienterror, string original_input, string col)
58{
59 switch (clienterror)
60 {
62 { return strcat(col, "Client '", original_input, col, "' doesn't exist");
63 }
64 case CLIENT_NOT_REAL:
65 { return strcat(col, "Client '", original_input, col, "' is not real");
66 }
67 case CLIENT_NOT_BOT:
68 { return strcat(col, "Client '", original_input, col, "' is not a bot");
69 }
70 default:
71 { return "Incorrect usage of GetClientErrorString";
72 }
73 }
74}
75
76// is this entity number even in the possible range of entities?
77bool VerifyClientNumber(int num)
78{
79 return (num >= 1 && num <= maxclients);
80}
81
82entity GetIndexedEntity(int argc, int start_index)
83{
84 entity selection;
85 int tmp_number, index;
86 string tmp_string;
87
88 next_token = -1;
89 index = start_index;
90 selection = NULL;
91
92 if (argc > start_index)
93 {
94 if (substring(argv(index), 0, 1) == "#")
95 {
96 tmp_string = substring(argv(index), 1, -1);
97 ++index;
98
99 if (tmp_string != "") // is it all one token? like #1
100 {
101 tmp_number = stof(tmp_string);
102 }
103 else if (argc > index) // no, it's two tokens? # 1
104 {
105 tmp_number = stof(argv(index));
106 ++index;
107 }
108 else
109 {
110 tmp_number = 0;
111 }
112 }
113 else // maybe it's ONLY a number?
114 {
115 tmp_number = stof(argv(index));
116 ++index;
117 }
118
119 if (VerifyClientNumber(tmp_number))
120 {
121 selection = edict_num(tmp_number); // yes, it was a number
122 }
123 else // no, maybe it's a name?
124 {
125 FOREACH_CLIENT(true, {
126 if(strdecolorize(it.netname) == strdecolorize(argv(start_index)))
127 {
128 selection = it;
129 break; // no reason to keep looking
130 }
131 });
132
133 index = (start_index + 1);
134 }
135 }
136
137 next_token = index;
138 // print(strcat("start_index: ", ftos(start_index), ", next_token: ", ftos(next_token), ", edict: ", ftos(num_for_edict(selection)), ".\n"));
139 return selection;
140}
141
142// find a player which matches the input string, and return their entity
144{
145 entity selection;
146 int tmp_number;
147
148 if (substring(input, 0, 1) == "#") tmp_number = stof(substring(input, 1, -1));
149 else tmp_number = stof(input);
150
151 if (VerifyClientNumber(tmp_number))
152 {
153 selection = edict_num(tmp_number);
154 }
155 else
156 {
157 selection = NULL;
158 FOREACH_CLIENT(true, {
159 if(strdecolorize(it.netname) == strdecolorize(input))
160 {
161 selection = it;
162 break; // no reason to keep looking
163 }
164 });
165 }
166
167 return selection;
168}
169
170// switch between sprint and print depending on whether the receiver is the server or a player
171void print_to(entity to, string input)
172{
173 if (to) sprint(to, strcat(input, "\n"));
174 else print(input, "\n");
175}
176
177// ==========================================
178// Supporting functions for common commands
179// ==========================================
180
181// used by CommonCommand_timeout() and CommonCommand_timein() to handle game pausing and messaging and such.
183{
185 timeout_time = 0;
187
188 delete(this);
189
190 // ReadyCount() does nothing when a timeout is active or pending
191 // so check readiness now to support g_warmup_allow_timeout
193}
194
196{
197 switch (timeout_status)
198 {
199 case TIMEOUT_ACTIVE:
200 {
201 if (timeout_time > 0) // countdown is still going
202 {
203 Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_TIMEOUT_ENDING, timeout_time);
204
205 if (timeout_time == autocvar_sv_timeout_resumetime) // play a warning sound when only <sv_timeout_resumetime> seconds are left
206 Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_PREPARE);
207
208 this.nextthink = time + TIMEOUT_SLOWMO_VALUE; // think again in one second
209 timeout_time -= 1; // decrease the time counter
210 }
211 else // time to end the timeout
212 {
213 Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_TIMEIN);
215
216 // reset the slowmo value back to normal
217 cvar_set("slowmo", ftos(orig_slowmo));
218
219 // unlock the view for players so they can move around again
221 it.fixangle = false;
222 });
223
225 }
226
227 return;
228 }
229
230 case TIMEOUT_LEADTIME:
231 {
232 if (timeout_leadtime > 0) // countdown is still going
233 {
234 Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_TIMEOUT_BEGINNING, timeout_leadtime);
235
236 this.nextthink = time + 1; // think again in one second
237 timeout_leadtime -= 1; // decrease the time counter
238 }
239 else // time to begin the timeout
240 {
242
243 // set the slowmo value to the timeout default slowmo value
245
246 // copy .v_angle to .lastV_angle for every player in order to fix their view during pause (see PlayerPreThink)
248 it.lastV_angle = it.v_angle;
249 });
250
251 this.nextthink = time; // think again next frame to handle it under TIMEOUT_ACTIVE code
252 }
253
254 return;
255 }
256
257
258 case TIMEOUT_INACTIVE:
259 default:
260 {
262 return;
263 }
264 }
265}
266
267
268// ===================================================
269// Common commands used in both sv_cmd.qc and cmd.qc
270// ===================================================
271
272void CommonCommand_cvar_changes(int request, entity caller)
273{
274 switch (request)
275 {
277 {
278 print_to(caller, cvar_changes);
279 return; // never fall through to usage
280 }
281
282 default:
284 {
285 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " cvar_changes"));
286 print_to(caller, " No arguments required.");
287 print_to(caller, "See also: ^2cvar_purechanges^7");
288 return;
289 }
290 }
291}
292
293void CommonCommand_cvar_purechanges(int request, entity caller)
294{
295 switch (request)
296 {
298 {
299 print_to(caller, cvar_purechanges);
300 return; // never fall through to usage
301 }
302
303 default:
305 {
306 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " cvar_purechanges"));
307 print_to(caller, " No arguments required.");
308 print_to(caller, "See also: ^2cvar_changes^7");
309 return;
310 }
311 }
312}
313
314void CommonCommand_editmob(int request, entity caller, int argc)
315{
316 switch (request)
317 {
319 {
320 if (autocvar_g_campaign) { print_to(caller, "Monster editing is disabled in singleplayer"); return; }
321 // no checks for g_monsters here, as it may be toggled mid match which existing monsters
322
323 if (caller)
324 {
325 makevectors(caller.v_angle);
326 WarpZone_TraceLine(caller.origin + caller.view_ofs, caller.origin + caller.view_ofs + v_forward * 100, MOVE_NORMAL, caller);
327 }
328
329 entity mon = trace_ent;
330 bool is_visible = IS_MONSTER(mon);
331 string argument = argv(2);
332
333 switch (argv(1))
334 {
335 case "name":
336 {
337 if (!caller) { print_to(caller, "Only players can edit monsters"); return; }
338 if (!argument) break; // escape to usage
339 if (!autocvar_g_monsters_edit) { print_to(caller, "Monster editing is disabled"); return; }
340 if (mon.realowner != caller && autocvar_g_monsters_edit < 2) { print_to(caller, "This monster does not belong to you"); return; }
341 if (!is_visible) { print_to(caller, "You must look at your monster to edit it"); return; }
342
343 string mon_oldname = mon.m_name;
344
345 mon.m_name = argument;
346 if (mon.sprite) WaypointSprite_UpdateSprites(mon.sprite, WP_Monster, WP_Null, WP_Null); // TODO: the new name is never actually sent to CSQC!
347 print_to(caller, sprintf("Your pet '%s' is now known as '%s'", mon_oldname, mon.m_name));
348 return;
349 }
350 case "spawn":
351 {
352 if (!caller) { print_to(caller, "Only players can spawn monsters"); return; }
353 if (!argv(2)) break; // escape to usage
354
355 int moveflag, tmp_moncount = 0;
356 string arg_lower = strtolower(argument);
357 moveflag = (argv(3)) ? stof(argv(3)) : 1; // follow owner if not defined
358
359 if (arg_lower == "list") { print_to(caller, monsterlist_reply); return; }
360
361 IL_EACH(g_monsters, it.realowner == caller,
362 {
363 ++tmp_moncount;
364 });
365
366 if (!autocvar_g_monsters) { print_to(caller, "Monsters are disabled"); return; }
367 if (autocvar_g_monsters_max <= 0 || autocvar_g_monsters_max_perplayer <= 0) { print_to(caller, "Monster spawning is disabled"); return; }
368 if (!IS_PLAYER(caller)) { print_to(caller, "You must be playing to spawn a monster"); return; }
369 if (MUTATOR_CALLHOOK(AllowMobSpawning, caller)) { print_to(caller, M_ARGV(1, string)); return; }
370 if (caller.vehicle) { print_to(caller, "You can't spawn monsters while driving a vehicle"); return; }
371 if (IS_DEAD(caller)) { print_to(caller, "You can't spawn monsters while dead"); return; }
372 if (tmp_moncount >= autocvar_g_monsters_max) { print_to(caller, "The maximum monster count has been reached"); return; }
373 if (tmp_moncount >= autocvar_g_monsters_max_perplayer) { print_to(caller, "You can't spawn any more monsters"); return; }
374
375 bool found = false;
376 FOREACH(Monsters, it != MON_Null && it.netname == arg_lower,
377 {
378 found = true;
379 break;
380 });
381
382 if (!found && arg_lower != "random" && arg_lower != "anyrandom") { print_to(caller, "Invalid monster"); return; }
383
384 totalspawned += 1;
385 WarpZone_TraceBox(CENTER_OR_VIEWOFS(caller), caller.mins, caller.maxs, CENTER_OR_VIEWOFS(caller) + v_forward * 150, true, caller);
386 mon = spawnmonster(spawn(), arg_lower, MON_Null, caller, caller, trace_endpos, false, false, moveflag);
387 print_to(caller, strcat("Spawned ", mon.m_name));
388 return;
389 }
390 case "kill":
391 {
392 if (!caller) { print_to(caller, "Only players can kill monsters"); return; }
393 if (mon.realowner != caller && autocvar_g_monsters_edit < 2) { print_to(caller, "This monster does not belong to you"); return; }
394 if (!is_visible) { print_to(caller, "You must look at your monster to edit it"); return; }
395
396 Damage(mon, NULL, NULL, GetResource(mon, RES_HEALTH) + mon.max_health + 200, DEATH_KILL.m_id, DMG_NOWEP, mon.origin, '0 0 0');
397 print_to(caller, strcat("Your pet '", mon.m_name, "' has been brutally mutilated"));
398 return;
399 }
400 case "skin":
401 {
402 if (!caller) { print_to(caller, "Only players can edit monsters"); return; }
403 if (!argument) break; // escape to usage
404 if (!autocvar_g_monsters_edit) { print_to(caller, "Monster editing is disabled"); return; }
405 if (!is_visible) { print_to(caller, "You must look at your monster to edit it"); return; }
406 if (mon.realowner != caller && autocvar_g_monsters_edit < 2) { print_to(caller, "This monster does not belong to you"); return; }
407 if (mon.monsterdef == MON_MAGE) { print_to(caller, "Mage skins can't be changed"); return; } // TODO
408
409 mon.skin = stof(argument);
410 print_to(caller, strcat("Monster skin successfully changed to ", ftos(mon.skin)));
411 return;
412 }
413 case "movetarget":
414 {
415 if (!caller) { print_to(caller, "Only players can edit monsters"); return; }
416 if (!argument) break; // escape to usage
417 if (!autocvar_g_monsters_edit) { print_to(caller, "Monster editing is disabled"); return; }
418 if (!is_visible) { print_to(caller, "You must look at your monster to edit it"); return; }
419 if (mon.realowner != caller && autocvar_g_monsters_edit < 2) { print_to(caller, "This monster does not belong to you"); return; }
420
421 mon.monster_moveflags = stof(argument);
422 print_to(caller, strcat("Monster move target successfully changed to ", ftos(mon.monster_moveflags)));
423 return;
424 }
425 case "butcher":
426 {
427 if (caller) { print_to(caller, "This command is not available to players"); return; }
428 if (MUTATOR_CALLHOOK(AllowMobButcher)) { LOG_INFO(M_ARGV(0, string)); return; }
429
430 int tmp_remcount = 0;
431
432 IL_EACH(g_monsters, true,
433 {
434 Monster_Remove(it);
435 ++tmp_remcount;
436 });
438
440
441 print_to(caller, (tmp_remcount) ? sprintf("Killed %d monster%s", tmp_remcount, (tmp_remcount == 1) ? "" : "s") : "No monsters to kill");
442 return;
443 }
444 }
445 }
446
447 default:
449 {
450 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " editmob <command> [<arguments>]"));
451 print_to(caller, " Where <command> can be butcher spawn skin movetarget kill name");
452 print_to(caller, " spawn, skin, movetarget and name require <arguments>");
453 print_to(caller, " spawn also takes arguments list and random");
454 print_to(caller, " Monster will follow owner if third argument of spawn command is not defined");
455 return;
456 }
457 }
458}
459
460void CommonCommand_info(int request, entity caller, int argc)
461{
462 switch (request)
463 {
465 {
466 string command = cvar_string(strcat("sv_info_", argv(1)));
467
468 if (command) wordwrap_sprint(caller, command, 1000);
469 else print_to(caller, "ERROR: unsupported info command");
470
471 return; // never fall through to usage
472 }
473
474 default:
476 {
477 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " info <request>"));
478 print_to(caller, " Where <request> is the suffixed string appended onto the request for cvar.");
479 return;
480 }
481 }
482}
483
484void CommonCommand_ladder(int request, entity caller)
485{
486 switch (request)
487 {
489 {
490 print_to(caller, ladder_reply);
491 return; // never fall through to usage
492 }
493
494 default:
496 {
497 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " ladder"));
498 print_to(caller, " No arguments required.");
499 return;
500 }
501 }
502}
503
504void CommonCommand_lsmaps(int request, entity caller)
505{
506 switch (request)
507 {
509 {
510 print_to(caller, lsmaps_reply);
511 return; // never fall through to usage
512 }
513
514 default:
516 {
517 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " lsmaps"));
518 print_to(caller, " No arguments required.");
519 return;
520 }
521 }
522}
523
524void CommonCommand_printmaplist(int request, entity caller)
525{
526 switch (request)
527 {
529 {
530 print_to(caller, maplist_reply);
531 return; // never fall through to usage
532 }
533
534 default:
536 {
537 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " printmaplist"));
538 print_to(caller, " No arguments required.");
539 return;
540 }
541 }
542}
543
544void CommonCommand_rankings(int request, entity caller)
545{
546 switch (request)
547 {
549 {
550 print_to(caller, rankings_reply);
551 return; // never fall through to usage
552 }
553
554 default:
556 {
557 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " rankings"));
558 print_to(caller, " No arguments required.");
559 return;
560 }
561 }
562}
563
564void CommonCommand_records(int request, entity caller)
565{
566 switch (request)
567 {
569 {
570 int num = stoi(argv(1));
571 if(num > 0 && num <= 10 && records_reply[num - 1] != "")
572 print_to(caller, records_reply[num - 1]);
573 else
574 {
575 for (int i = 0; i < 10; ++i)
576 if (records_reply[i] != "") print_to(caller, records_reply[i]);
577 }
578
579 return; // never fall through to usage
580 }
581
582 default:
584 {
585 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " records [<pagenum>]"));
586 print_to(caller, " Without arguments it prints all records (all pages) for the current gametype,");
587 print_to(caller, " otherwise if there are multiple pages it only prints page <pagenum> (1..10),");
588 return;
589 }
590 }
591}
592
593void CommonCommand_teamstatus(int request, entity caller)
594{
595 switch (request)
596 {
598 {
599 Score_NicePrint(caller);
600 return; // never fall through to usage
601 }
602
603 default:
605 {
606 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " teamstatus"));
607 print_to(caller, " No arguments required.");
608 return;
609 }
610 }
611}
612
613void CommonCommand_time(int request, entity caller)
614{
615 switch (request)
616 {
618 {
619 print_to(caller, strcat("time = ", ftos(time)));
620 print_to(caller, strcat("frame start = ", ftos(gettime(GETTIME_FRAMESTART))));
621 print_to(caller, strcat("realtime = ", ftos(gettime(GETTIME_REALTIME))));
622 print_to(caller, strcat("hires = ", ftos(gettime(GETTIME_HIRES))));
623 print_to(caller, strcat("uptime = ", ftos(gettime(GETTIME_UPTIME))));
624 print_to(caller, strcat("localtime = ", strftime(true, "%a %b %d %H:%M:%S %Z %Y")));
625 print_to(caller, strcat("gmtime = ", strftime(false, "%a %b %d %H:%M:%S %Z %Y")));
626 return;
627 }
628
629 default:
631 {
632 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " time"));
633 print_to(caller, " No arguments required.");
634 return;
635 }
636 }
637}
638
639void CommonCommand_timein(int request, entity caller)
640{
641 switch (request)
642 {
644 {
645 if (!caller || autocvar_sv_timeout)
646 {
647 if (!timeout_status) { print_to(caller, "^7Error: There is no active timeout called."); }
648 else if (caller && (caller != timeout_caller))
649 {
650 print_to(caller, "^7Error: You are not allowed to stop the active timeout.");
651 }
652
653 else // everything should be okay, continue aborting timeout
654 {
655 switch (timeout_status)
656 {
657 case TIMEOUT_LEADTIME:
658 {
660 timeout_time = 0;
661 timeout_handler.nextthink = time; // timeout_handler has to take care of it immediately
662 Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_TIMEOUT);
663 bprint(strcat("^7The timeout was aborted by ", GetCallerName(caller), " !\n"));
664 return;
665 }
666
667 case TIMEOUT_ACTIVE:
668 {
670 timeout_handler.nextthink = time; // timeout_handler has to take care of it immediately
671 bprint(strcat("^1Attention: ^7", GetCallerName(caller), " resumed the game! Prepare for battle!\n"));
672 return;
673 }
674
675 default: LOG_TRACE("timeout status was inactive, but this code was executed anyway?");
676 return;
677 }
678 }
679 }
680 else { print_to(caller, "^1Timeins are not allowed to be called, enable them with sv_timeout 1.\n"); }
681
682 return; // never fall through to usage
683 }
684
685 default:
687 {
688 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " timein"));
689 print_to(caller, " No arguments required.");
690 return;
691 }
692 }
693}
694
695void CommonCommand_timeout(int request, entity caller) // DEAR GOD THIS COMMAND IS TERRIBLE.
696{
697 switch (request)
698 {
700 {
701 if (!caller || autocvar_sv_timeout)
702 {
703 float last_possible_timeout = ((autocvar_timelimit * 60) - autocvar_sv_timeout_leadtime - 1);
704
705 if (timeout_status) { print_to(caller, "^7Error: A timeout is already active."); }
706 else if (vote_called)
707 {
708 print_to(caller, "^7Error: You can not call a timeout while a vote is active.");
709 }
711 {
712 print_to(caller, "^7Error: You can not call a timeout in warmup-stage.");
713 }
714 else if (time < game_starttime)
715 {
716 print_to(caller, "^7Error: You can not call a timeout while the map is being restarted.");
717 }
718 else if (caller && (CS(caller).allowed_timeouts < 1))
719 {
720 print_to(caller, "^7Error: You already used all your timeout calls for this map.");
721 }
722 else if (caller && !IS_PLAYER(caller))
723 {
724 print_to(caller, "^7Error: You must be a player to call a timeout.");
725 }
726 else if ((autocvar_timelimit) && (last_possible_timeout < time - game_starttime))
727 {
728 print_to(caller, "^7Error: It is too late to call a timeout now!");
729 }
730
731 else // everything should be okay, proceed with starting the timeout
732 {
733 if (caller) CS(caller).allowed_timeouts -= 1;
734 // write a bprint who started the timeout (and how many they have left)
735 bprint(GetCallerName(caller), " ^7called a timeout", (caller ? strcat(" (", ftos(CS(caller).allowed_timeouts), " timeout(s) left)") : ""), "!\n");
736
738 timeout_caller = caller;
741
744 timeout_handler.nextthink = time; // always let the entity think asap
745
746 Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_TIMEOUT);
747 }
748 }
749 else { print_to(caller, "^1Timeouts are not allowed to be called, enable them with sv_timeout 1.\n"); }
750
751 return; // never fall through to usage
752 }
753
754 default:
756 {
757 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " timeout"));
758 print_to(caller, " No arguments required.");
759 return;
760 }
761 }
762}
763
764void CommonCommand_who(int request, entity caller, int argc)
765{
766 switch (request)
767 {
769 {
770 float total_listed_players, is_bot;
771
772 float privacy = (caller && autocvar_sv_status_privacy);
773 string separator = strreplace("%", " ", strcat((argv(1) ? argv(1) : " "), "^7"));
774 string tmp_netaddress, tmp_crypto_idfp;
775
776 print_to(caller, strcat("List of client information", (privacy ? " (some data is hidden for privacy)" : ""), ":"));
777 print_to(caller, sprintf(strreplace(" ", separator, " %-4s %-20s %-5s %-3s %-9s %-16s %s "),
778 "ent", "nickname", "ping", "pl", "time", "ip", "crypto_id"));
779
780 total_listed_players = 0;
781 FOREACH_CLIENT(true, {
782 is_bot = (IS_BOT_CLIENT(it));
783
784 if (is_bot)
785 {
786 tmp_netaddress = "null/botclient";
787 tmp_crypto_idfp = "null/botclient";
788 }
789 else if (privacy)
790 {
791 tmp_netaddress = "hidden";
792 tmp_crypto_idfp = "hidden";
793 }
794 else
795 {
796 tmp_netaddress = it.netaddress;
797 tmp_crypto_idfp = it.crypto_idfp;
798 }
799
800 print_to(caller, sprintf(strreplace(" ", separator, " #%-3d %-20.20s %-5d %-3d %-9s %-16s %s "),
801 etof(it),
802 it.netname,
803 CS(it).ping,
805 process_time(1, time - CS(it).jointime),
806 tmp_netaddress,
807 tmp_crypto_idfp));
808
809 ++total_listed_players;
810 });
811
812 print_to(caller, strcat("Finished listing ", ftos(total_listed_players), " client(s) out of ", ftos(maxclients), " slots."));
813
814 return; // never fall through to usage
815 }
816
817 default:
819 {
820 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " who [<separator>]"));
821 print_to(caller, " Where <separator> is the optional string to separate the values with, default is a space.");
822 return;
823 }
824 }
825}
826
827/* use this when creating a new command, making sure to place it in alphabetical order... also,
828** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
829void CommonCommand_(int request, entity caller)
830{
831 switch(request)
832 {
833 case CMD_REQUEST_COMMAND:
834 {
835
836 return; // never fall through to usage
837 }
838
839 default:
840 case CMD_REQUEST_USAGE:
841 {
842 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " "));
843 print_to(caller, " No arguments required.");
844 return;
845 }
846 }
847}
848*/
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
float ping
Definition main.qh:169
float ping_packetloss
Definition main.qh:169
bool warmup_stage
Definition main.qh:120
const int CMD_REQUEST_COMMAND
Definition command.qh:3
const int CMD_REQUEST_USAGE
Definition command.qh:4
#define M_ARGV(x, type)
Definition events.qh:17
#define IS_CLIENT(s)
Definition player.qh:242
#define IS_DEAD(s)
Definition player.qh:245
#define IS_PLAYER(s)
Definition player.qh:243
int timeout_status
Definition stats.qh:87
#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
void wordwrap_sprint(entity to, string s, float l)
Definition util.qc:192
string maplist_reply
Definition util.qh:161
string rankings_reply
Definition util.qh:161
string records_reply[10]
Definition util.qh:162
string strtolower(string s)
string lsmaps_reply
Definition util.qh:161
string ladder_reply
Definition util.qh:161
string monsterlist_reply
Definition util.qh:161
ERASEABLE string process_time(float outputtype, int seconds)
Definition counting.qh:120
float maxclients
entity trace_ent
float GETTIME_UPTIME
float GETTIME_HIRES
const float MOVE_NORMAL
float time
vector trace_endpos
float nextthink
vector v_forward
float GETTIME_FRAMESTART
#define spawn
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition damage.qc:503
#define DMG_NOWEP
Definition damage.qh:104
#define stoi(s)
Definition int.qh:4
#define IL_EACH(this, cond, body)
#define IL_CLEAR(this)
Remove all elements.
#define FOREACH(list, cond, body)
Definition iter.qh:19
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition common.qc:348
void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
Definition common.qc:343
#define LOG_INFO(...)
Definition log.qh:65
#define LOG_TRACE(...)
Definition log.qh:76
bool autocvar_g_campaign
Definition menu.qc:747
void cvar_set(string name, string value)
float stof(string val,...)
string substring(string s, float start, float length)
void sprint(float clientnum, string text,...)
float gettime(void)
void bprint(string text,...)
const string cvar_string(string name)
string ftos(float f)
void print(string text,...)
string argv(float n)
#define etof(e)
Definition misc.qh:25
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
void Kill_Notification(NOTIF broadcast, entity client, MSG net_type, CPID net_cpid)
Definition all.qc:1537
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
void Score_NicePrint(entity to)
Prints the scores to the console of a player.
Definition scores.qc:917
#define setthink(e, f)
float jointime
Definition client.qh:66
void CommonCommand_cvar_purechanges(int request, entity caller)
Definition common.qc:293
void CommonCommand_printmaplist(int request, entity caller)
Definition common.qc:524
void CommonCommand_lsmaps(int request, entity caller)
Definition common.qc:504
void CommonCommand_editmob(int request, entity caller, int argc)
Definition common.qc:314
void print_to(entity to, string input)
Definition common.qc:171
void timeout_handler_reset(entity this)
Definition common.qc:182
string GetCommandPrefix(entity caller)
Definition common.qc:26
void CommonCommand_records(int request, entity caller)
Definition common.qc:564
string GetClientErrorString_color(float clienterror, string original_input, string col)
Definition common.qc:57
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
void CommonCommand_ladder(int request, entity caller)
Definition common.qc:484
void CommonCommand_teamstatus(int request, entity caller)
Definition common.qc:593
void CommonCommand_timeout(int request, entity caller)
Definition common.qc:695
void CommonCommand_who(int request, entity caller, int argc)
Definition common.qc:764
void timeout_handler_think(entity this)
Definition common.qc:195
void CommonCommand_info(int request, entity caller, int argc)
Definition common.qc:460
bool VerifyClientNumber(int num)
Definition common.qc:77
void CommonCommand_timein(int request, entity caller)
Definition common.qc:639
void CommonCommand_rankings(int request, entity caller)
Definition common.qc:544
string GetCallerName(entity caller)
Definition common.qc:33
void CommonCommand_cvar_changes(int request, entity caller)
Definition common.qc:272
void CommonCommand_time(int request, entity caller)
Definition common.qc:613
int VerifyKickableEntity(entity client)
Definition common.qc:40
entity GetFilteredEntity(string input)
Definition common.qc:143
bool autocvar_sv_timeout
Definition common.qh:5
float timeout_leadtime
Definition common.qh:60
const float TIMEOUT_INACTIVE
Definition common.qh:47
int next_token
Definition common.qh:71
const float TIMEOUT_SLOWMO_VALUE
Definition common.qh:52
entity timeout_handler
Definition common.qh:56
float timeout_time
Definition common.qh:59
string autocvar_sv_adminnick
Definition common.qh:3
const float CLIENT_ACCEPTABLE
Definition common.qh:41
const float CLIENT_NOT_BOT
Definition common.qh:44
entity timeout_caller
Definition common.qh:55
const float CLIENT_DOESNT_EXIST
Definition common.qh:42
float orig_slowmo
Definition common.qh:58
bool autocvar_sv_status_privacy
Definition common.qh:4
const float TIMEOUT_ACTIVE
Definition common.qh:49
const float CLIENT_NOT_REAL
Definition common.qh:43
float autocvar_sv_timeout_leadtime
Definition common.qh:6
float allowed_timeouts
Definition common.qh:61
float autocvar_sv_timeout_length
Definition common.qh:7
const float TIMEOUT_LEADTIME
Definition common.qh:48
float autocvar_sv_timeout_resumetime
Definition common.qh:9
void ReadyCount()
Definition vote.qc:553
int vote_called
Definition vote.qh:45
ClientState CS(Client this)
Definition state.qh:47
#define GETTIME_REALTIME
Definition static.qh:3
void Monster_Remove(entity this)
int totalspawned
number of monsters spawned with mobspawn command
int autocvar_g_monsters_max
Definition sv_monsters.qh:8
int monsters_killed
int monsters_total
float autocvar_g_monsters
Definition sv_monsters.qh:5
bool autocvar_g_monsters_edit
Definition sv_monsters.qh:6
IntrusiveList g_monsters
int autocvar_g_monsters_max_perplayer
Definition sv_monsters.qh:9
entity spawnmonster(entity e, string monster, Monster monster_id, entity spawnedby, entity own, vector orig, bool respwn, bool removeifinvalid, int moveflag)
Definition sv_spawn.qc:14
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define IS_MONSTER(v)
Definition utils.qh:21
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50
#define CENTER_OR_VIEWOFS(ent)
Definition utils.qh:29
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition utils.qh:15
void WaypointSprite_UpdateSprites(entity e, entity _m1, entity _m2, entity _m3)
string cvar_changes
Definition world.qh:45
bool autocvar_g_warmup_allow_timeout
Definition world.qh:11
string cvar_purechanges
Definition world.qh:46