1 // ====================================================
2 // Shared code for server commands, written by Samual
3 // Last updated: December 13th, 2011
4 // ====================================================
6 // find a player which matches the input string, and return their entity number
7 float GetFilteredNumber(string input)
9 entity tmp_player, selection;
10 float output, matches;
12 // check and see if we can get a number from input like "#3" or "3"
13 if(substring(input, 0, 1) == "#")
14 output = stof(substring(input, 1, -1));
18 // if we can't, check and see if we can match the input to the netname of any player in the game
21 FOR_EACH_CLIENT(tmp_player)
22 if (strdecolorize(tmp_player.netname) == strdecolorize(input))
23 selection = tmp_player;
25 if (selection) { output = num_for_edict(selection); }
28 print(strcat("input: ", input, ", output: ", ftos(output), ",\n"));
32 // switch between sprint and print depending on whether the reciever is the server or a player
33 void print_to(entity to, string input)
36 sprint(to, strcat(input, "\n"));
42 // ===================================================
43 // Common commands used in both sv_cmd.qc and cmd.qc
44 // ===================================================
46 void CommonCommand_cvar_changes(float request)
50 case CMD_REQUEST_COMMAND:
52 sprint(self, cvar_changes);
53 return; // never fall through to usage
57 case CMD_REQUEST_USAGE:
59 sprint(self, "\nUsage:^3 sv_cmd cvar_changes\n");
60 sprint(self, " No arguments required.\n");
61 //sprint(self, "See also: ^2cvar_purechanges^7\n");
67 void CommonCommand_cvar_purechanges(float request)
71 case CMD_REQUEST_COMMAND:
73 sprint(self, cvar_purechanges);
74 return; // never fall through to usage
78 case CMD_REQUEST_USAGE:
80 sprint(self, "\nUsage:^3 sv_cmd cvar_purechanges\n");
81 sprint(self, " No arguments required.\n");
82 //sprint(self, "See also: ^2cvar_changes^7\n");
88 void CommonCommand_info(float request, float argc)
92 case CMD_REQUEST_COMMAND:
96 command = builtin_cvar_string(strcat("sv_info_", argv(1)));
98 wordwrap_sprint(command, 1111); // why 1111?
100 sprint(self, "ERROR: unsupported info command\n");
102 return; // never fall through to usage
106 case CMD_REQUEST_USAGE:
108 sprint(self, "\nUsage:^3 cmd info request\n");
109 sprint(self, " Where 'request' is the suffixed string appended onto the request for cvar.\n");
115 void CommonCommand_ladder(float request)
119 case CMD_REQUEST_COMMAND:
121 sprint(self, ladder_reply);
122 return; // never fall through to usage
126 case CMD_REQUEST_USAGE:
128 sprint(self, "\nUsage:^3 cmd ladder\n");
129 sprint(self, " No arguments required.\n");
135 void CommonCommand_lsmaps(float request)
139 case CMD_REQUEST_COMMAND:
141 sprint(self, lsmaps_reply);
142 return; // never fall through to usage
146 case CMD_REQUEST_USAGE:
148 sprint(self, "\nUsage:^3 cmd lsmaps\n");
149 sprint(self, " No arguments required.\n");
155 void CommonCommand_lsnewmaps(float request)
159 case CMD_REQUEST_COMMAND:
161 sprint(self, lsnewmaps_reply);
162 return; // never fall through to usage
166 case CMD_REQUEST_USAGE:
168 sprint(self, "\nUsage:^3 cmd lsnewmaps\n");
169 sprint(self, " No arguments required.\n");
175 void CommonCommand_maplist(float request)
179 case CMD_REQUEST_COMMAND:
181 sprint(self, maplist_reply);
182 return; // never fall through to usage
186 case CMD_REQUEST_USAGE:
188 sprint(self, "\nUsage:^3 cmd maplist\n");
189 sprint(self, " No arguments required.\n");
195 void CommonCommand_rankings(float request)
199 case CMD_REQUEST_COMMAND:
201 sprint(self, rankings_reply);
202 return; // never fall through to usage
206 case CMD_REQUEST_USAGE:
208 sprint(self, "\nUsage:^3 cmd rankings\n");
209 sprint(self, " No arguments required.\n");
215 void CommonCommand_records(float request) // TODO: Isn't this flooding with the sprint messages? Old code, but perhaps bad?
219 case CMD_REQUEST_COMMAND:
223 for(i = 0; i < 10; ++i)
224 sprint(self, records_reply[i]);
226 return; // never fall through to usage
230 case CMD_REQUEST_USAGE:
232 sprint(self, "\nUsage:^3 cmd records\n");
233 sprint(self, " No arguments required.\n");
239 void CommonCommand_teamstatus(float request)
243 case CMD_REQUEST_COMMAND:
245 Score_NicePrint(self);
246 return; // never fall through to usage
250 case CMD_REQUEST_USAGE:
252 sprint(self, "\nUsage:^3 cmd teamstatus\n");
253 sprint(self, " No arguments required.\n");
260 void CommonCommand_timein(float request)
264 case CMD_REQUEST_COMMAND:
266 if(self.flags & FL_CLIENT)
268 if(autocvar_sv_timeout)
271 return sprint(self, "^7Error: There is no active timeout which could be aborted!\n");
272 if (self != timeoutInitiator)
273 return sprint(self, "^7Error: You may not abort the active timeout. Only the player who called it can do that!\n");
275 if (timeoutStatus == 1)
277 remainingTimeoutTime = timeoutStatus = 0;
278 timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately
279 bprint(strcat("^7The timeout was aborted by ", self.netname, " !\n"));
281 else if (timeoutStatus == 2)
283 //only shorten the remainingTimeoutTime if it makes sense
284 if( remainingTimeoutTime > (autocvar_sv_timeout_resumetime + 1) )
286 bprint(strcat("^1Attention: ^7", self.netname, " resumed the game! Prepare for battle!\n"));
287 remainingTimeoutTime = autocvar_sv_timeout_resumetime;
288 timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately
291 sprint(self, "^7Error: Your resumegame call was discarded!\n");
295 return; // never fall through to usage
299 case CMD_REQUEST_USAGE:
301 sprint(self, "\nUsage:^3 cmd timein\n");
302 sprint(self, " No arguments required.\n");
308 void CommonCommand_timeout(float request) // DEAR GOD THIS COMMAND IS TERRIBLE.
312 case CMD_REQUEST_COMMAND:
314 if(self.flags & FL_CLIENT)
316 if(autocvar_sv_timeout)
318 if(self.classname == "player")
321 sprint(self, "^7Error: you can not call a timeout while a vote is active!\n");
324 if (inWarmupStage && !g_warmup_allow_timeout)
325 return sprint(self, "^7Error: You can not call a timeout in warmup-stage!\n");
326 if (time < game_starttime )
327 return sprint(self, "^7Error: You can not call a timeout while the map is being restarted!\n");
329 if (timeoutStatus != 2) {
330 //if the map uses a timelimit make sure that timeout cannot be called right before the map ends
331 if (autocvar_timelimit) {
332 //a timelimit was used
334 myTl = autocvar_timelimit;
336 float lastPossibleTimeout;
337 lastPossibleTimeout = (myTl*60) - autocvar_sv_timeout_leadtime - 1;
339 if (lastPossibleTimeout < time - game_starttime)
340 return sprint(self, "^7Error: It is too late to call a timeout now!\n");
344 //player may not call a timeout if he has no calls left
345 if (self.allowedTimeouts < 1)
346 return sprint(self, "^7Error: You already used all your timeout calls for this map!\n");
349 //now all required checks are passed
350 self.allowedTimeouts -= 1;
351 bprint(self.netname, " ^7called a timeout (", ftos(self.allowedTimeouts), " timeouts left)!\n"); //write a bprint who started the timeout (and how many he has left)
352 remainingTimeoutTime = autocvar_sv_timeout_length;
353 remainingLeadTime = autocvar_sv_timeout_leadtime;
354 timeoutInitiator = self;
355 if (timeoutStatus == 0) { //if another timeout was already active, don't change its status (which was 1 or 2) to 1, only change it to 1 if no timeout was active yet
357 //create the timeout indicator which centerprints the information to all players and takes care of pausing/unpausing
358 timeoutHandler = spawn();
359 timeoutHandler.think = timeoutHandler_Think;
361 timeoutHandler.nextthink = time; //always let the entity think asap
363 //inform all connected clients about the timeout call
364 Announce("timeoutcalled");
368 sprint(self, "^7Error: only players can call a timeout!\n");
371 return; // never fall through to usage
375 case CMD_REQUEST_USAGE:
377 sprint(self, "\nUsage:^3 cmd timeout\n");
378 sprint(self, " No arguments required.\n");
384 void CommonCommand_who(float request)
388 case CMD_REQUEST_COMMAND:
390 float total_listed_players, tmp_hours, tmp_minutes, tmp_seconds;
392 //string tmp_player_name;
394 sprint(self, strcat("List of client information", (autocvar_sv_status_privacy ? " (some data is hidden for privacy)" : string_null), ":\n"));
395 sprint(self, sprintf(" %-4s %-20s %-5s %-3s %-9s %-16s %s\n", "ent", "nickname", "ping", "pl", "time", "ip", "crypto_id"));
397 FOR_EACH_CLIENT(tmp_player)
399 //tmp_player_name = strlimitedlen(tmp_player.netname, "...", TRUE, 20);
401 tmp_hours = tmp_minutes = tmp_seconds = 0;
403 tmp_seconds = (time - tmp_player.jointime);
404 tmp_minutes = (tmp_seconds / 60);
408 tmp_seconds -= (tmp_minutes * 60);
409 tmp_hours = (tmp_minutes / 60);
411 if(tmp_hours) { tmp_minutes -= (tmp_hours * 60); }
414 sprint(self, sprintf(" %-4s %-20s %-5d %-3d %-9s %-16s %s\n",
415 strcat("#", ftos(num_for_edict(tmp_player))),
416 tmp_player.netname, //strcat(tmp_player_name, sprintf("%*s", (20 - strlen(strdecolorize(tmp_player_name))), "")),
417 tmp_player.ping, tmp_player.ping_packetloss,
418 sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds),
419 (autocvar_sv_status_privacy ? "hidden" : tmp_player.netaddress),
420 (autocvar_sv_status_privacy ? "hidden" : tmp_player.crypto_idfp)));
422 ++total_listed_players;
425 sprint(self, strcat("Finished listing ", ftos(total_listed_players), " client(s). \n"));
427 return; // never fall through to usage
431 case CMD_REQUEST_USAGE:
433 sprint(self, "\nUsage:^3 cmd who\n");
434 sprint(self, " No arguments required.\n");
440 /* use this when creating a new command, making sure to place it in alphabetical order.
441 void CommonCommand_(float request)
445 case CMD_REQUEST_COMMAND:
448 return; // never fall through to usage
452 case CMD_REQUEST_USAGE:
454 sprint(self, "\nUsage:^3 cmd \n");
455 sprint(self, " No arguments required.\n");