void LeaveSpectatorMode()
{
- if(isJoinAllowed()) {
+ if(nJoinAllowed(1)) {
if(!teams_matter || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) {
self.classname = "player";
* Determines whether the player is allowed to join. This depends on cvar
* g_maxplayers, if it isn't used this function always return TRUE, otherwise
* it checks whether the number of currently playing players exceeds g_maxplayers.
- * @return bool TRUE if the player is allowed to join, false otherwise
+ * @return int number of free slots for players, 0 if none
*/
-float isJoinAllowed() {
+float nJoinAllowed(float includeMe) {
if(self.team_forced < 0)
return FALSE; // forced spectators can never join
+ // TODO simplify this
+ local entity e;
+
+ local float totalClients;
+ FOR_EACH_CLIENT(e)
+ totalClients += 1;
+
if (!autocvar_g_maxplayers)
- return TRUE;
+ return maxclients - totalClients + includeMe;
- local entity e;
local float currentlyPlaying;
- FOR_EACH_REALPLAYER(e) {
- if(e.classname == "player")
- currentlyPlaying += 1;
- }
+ FOR_EACH_REALPLAYER(e)
+ currentlyPlaying += 1;
+
if(currentlyPlaying < autocvar_g_maxplayers)
- return TRUE;
+ return min(maxclients - totalClients + includeMe, autocvar_g_maxplayers - currentlyPlaying);
- return FALSE;
+ return 0;
}
/**
if(!g_arena)
if (self.classname != "player" && !lockteams)
{
- if(isJoinAllowed()) {
+ if(nJoinAllowed(1)) {
self.classname = "player";
if(g_ca)
self.caplayer = 1;
.float jointime; // time of joining
.float alivetime; // time of being alive
-float isJoinAllowed();
+float nJoinAllowed(float includeMe);
#define PREVENT_JOIN_TEXT "^1You may not join the game at this time.\n\nThe player limit reached maximum capacity."
//sv_timeout: pauses the game by setting the gamespeed to a really low value (see TIMEOUT_SLOWMO_VALUE)
entity winnerscorekeeper;
entity secondscorekeeper;
entity sk;
+ float slots;
+
+ // format:
+ // gametype:P<pure>:S<slots>::plabel,plabel:tlabel,tlabel:teamid:tscore,tscore:teamid:tscore,tscore
+ // score labels always start with a symbol or with lower case
+ // so to match pure, match for :P0:
+ // to match full, match for :S0:
s = GetGametype();
s = strcat(s, ":", autocvar_g_xonoticversion);
s = strcat(s, ":P", ftos(cvar_purechanges_count));
+ s = strcat(s, ":S", ftos(nJoinAllowed(0)));
s = strcat(s, "::", GetPlayerScoreString(world, 1)); // make this 1 once we can, note: this doesn't contain any :<letter>
fullstatus = autocvar_g_full_getstatus_responses;