team_t PickTeam(int ignoreClientNum) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount(ignoreClientNum, TEAM_BLUE); counts[TEAM_RED] = TeamCount(ignoreClientNum, TEAM_RED); if (!g_redLocked.integer && counts[TEAM_BLUE] > counts[TEAM_RED]) { return TEAM_RED; } if (!g_blueLocked.integer && counts[TEAM_RED] > counts[TEAM_BLUE]) { return TEAM_BLUE; } // equal team count, so join the team with the lowest score if (!g_redLocked.integer && level.teamScores[TEAM_RED] < level.teamScores[TEAM_BLUE]) { return TEAM_RED; } if (!g_blueLocked.integer && level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE]) { return TEAM_BLUE; } // equal score, join random team if (!g_redLocked.integer && !g_blueLocked.integer) { return (rand() % 2 ? TEAM_RED : TEAM_BLUE); } return TEAM_SPECTATOR; }
// Changes team spectator lock status void G_refSpeclockTeams_cmd(gentity_t *ent, qboolean fLock) { char *status; // Ensure proper locking G_updateSpecLock(TEAM_AXIS, (TeamCount(-1, TEAM_AXIS)) ? fLock : qfalse); G_updateSpecLock(TEAM_ALLIES, (TeamCount(-1, TEAM_ALLIES)) ? fLock : qfalse); status = va("Referee has ^3SPECTATOR %sLOCKED^7 teams", ((fLock) ? "" : "UN")); G_printFull(status, ent); // Update viewers as necessary // G_pollMultiPlayers(); if (fLock) { level.server_settings |= CV_SVS_LOCKSPECS; } else { level.server_settings &= ~CV_SVS_LOCKSPECS; } trap_SetConfigstring(CS_SERVERTOGGLES, va("%d", level.server_settings)); }
/** * @brief Figure out if we are allowed/want to follow a given player * @param[in] ent * @param[in] nTeam * @return */ qboolean G_allowFollow(gentity_t *ent, int nTeam) { if (g_gametype.integer == GT_WOLF_LMS && g_lms_followTeamOnly.integer) { if ((ent->client->sess.spec_invite & nTeam) == nTeam) { return qtrue; } if (ent->client->sess.sessionTeam != TEAM_SPECTATOR && ent->client->sess.sessionTeam != nTeam) { return qfalse; } } if (level.time - level.startTime > 2500) { if (TeamCount(-1, TEAM_AXIS) == 0) { teamInfo[TEAM_AXIS].spec_lock = qfalse; } if (TeamCount(-1, TEAM_ALLIES) == 0) { teamInfo[TEAM_ALLIES].spec_lock = qfalse; } } return((!teamInfo[nTeam].spec_lock || ent->client->sess.sessionTeam != TEAM_SPECTATOR || (ent->client->sess.spec_invite & nTeam) == nTeam)); }
/* ================ PickTeam ================ */ team_t PickTeam(int ignoreClientNum) { int counts[TEAM_NUM_TEAMS] = { 0, 0, 0 }; counts[TEAM_ALLIES] = TeamCount(ignoreClientNum, TEAM_ALLIES); counts[TEAM_AXIS] = TeamCount(ignoreClientNum, TEAM_AXIS); if (counts[TEAM_ALLIES] > counts[TEAM_AXIS]) { return TEAM_AXIS; } if (counts[TEAM_AXIS] > counts[TEAM_ALLIES]) { return TEAM_ALLIES; } // Nico, let's pick axis team, why not ? :) return TEAM_AXIS; }
// Checks to see if a specified team is allowing players to join. qboolean G_teamJoinCheck(int team_num, gentity_t *ent) { int cnt = TeamCount(-1, team_num); // Sanity check if (cnt == 0) { G_teamReset(team_num); teamInfo[team_num].team_lock = qfalse; } // Check for locked teams if (team_num == TEAM_AXIS || team_num == TEAM_ALLIES) { if ((int)ent->client->sess.sessionTeam == team_num) { return qtrue; } // Check for full teams if (team_maxplayers.integer > 0 && team_maxplayers.integer <= cnt) { G_printFull(va("The %s team is full!", aTeams[team_num]), ent); return qfalse; // Check for locked teams } else if (teamInfo[team_num].team_lock && (!(ent->client->pers.invite & team_num))) { G_printFull(va("The %s team is LOCKED!", aTeams[team_num]), ent); return qfalse; } } return qtrue; }
/** * @brief Check if we need to reset the game state due to an empty team * @param[in] nTeam */ void G_verifyMatchState(team_t nTeam) { if ((level.lastRestartTime + 1000) < level.time && (nTeam == TEAM_ALLIES || nTeam == TEAM_AXIS) && (g_gamestate.integer == GS_PLAYING || g_gamestate.integer == GS_WARMUP_COUNTDOWN || g_gamestate.integer == GS_INTERMISSION)) { if (TeamCount(-1, nTeam) == 0) { if (g_doWarmup.integer > 0) { level.lastRestartTime = level.time; if (g_gametype.integer == GT_WOLF_STOPWATCH) { trap_Cvar_Set("g_currentRound", "0"); trap_Cvar_Set("g_nextTimeLimit", "0"); } trap_SendConsoleCommand(EXEC_APPEND, va("map_restart 0 %i\n", GS_WARMUP)); } else { teamInfo[nTeam].team_lock = qfalse; } G_teamReset(nTeam, qtrue); } } // Cleanup of ready count G_checkReady(); }
/* ================ PickTeam ================ */ team_t PickTeam( int ignoreClientNum ) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( ignoreClientNum, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( ignoreClientNum, TEAM_RED ); if ( counts[TEAM_BLUE] > counts[TEAM_RED] ) { return TEAM_RED; } if ( counts[TEAM_RED] > counts[TEAM_BLUE] ) { return TEAM_BLUE; } // equal team count, so join the team with the lowest score if ( level.teamScores[TEAM_BLUE] > level.teamScores[TEAM_RED] ) { return TEAM_RED; } return TEAM_BLUE; }
// Changes team lock status void G_refLockTeams_cmd(gentity_t *ent, qboolean fLock) { char *status; teamInfo[TEAM_AXIS].team_lock = (TeamCount(-1, TEAM_AXIS)) ? fLock : qfalse; teamInfo[TEAM_ALLIES].team_lock = (TeamCount(-1, TEAM_ALLIES)) ? fLock : qfalse; status = va("Referee has ^3%sLOCKED^7 teams", ((fLock) ? "" : "UN")); G_printFull(status, ent); G_refPrintf(ent, "You have %sLOCKED teams\n", ((fLock) ? "" : "UN")); if( fLock ) { level.server_settings |= CV_SVS_LOCKTEAMS; } else { level.server_settings &= ~CV_SVS_LOCKTEAMS; } trap_SetConfigstring(CS_SERVERTOGGLES, va("%d", level.server_settings)); }
// Puts a player on a team. void G_refPlayerPut_cmd( gentity_t *ent, int team_id ) { int pid; char arg[ MAX_TOKEN_CHARS ]; gentity_t *player; // Works for teamplayish matches if ( g_gametype.integer < GT_WOLF ) { G_refPrintf( ent, "\"put[allies|axis]\" only for team-based games!" ); return; } // Find the player to place. trap_Argv( 2, arg, sizeof( arg ) ); if ( ( pid = ClientNumberFromString( ent, arg ) ) == -1 ) { return; } player = g_entities + pid; // Can only move to other teams. if ( player->client->sess.sessionTeam == team_id ) { G_refPrintf( ent, "\"%s\" is already on team %s!", player->client->pers.netname, aTeams[ team_id ] ); // CHRUKER: b047 - Removed unneeded linebreak return; } if ( team_maxplayers.integer && TeamCount( -1, team_id ) >= team_maxplayers.integer ) { G_refPrintf( ent, "Sorry, the %s team is already full!", aTeams[ team_id ] ); // CHRUKER: b047 - Removed unneeded linebreak return; } player->client->pers.invite = team_id; player->client->pers.ready = qfalse; if ( team_id == TEAM_AXIS ) { SetTeam( player, "red", qtrue, -1, -1, qfalse ); } else { SetTeam( player, "blue", qtrue, -1, -1, qfalse ); } if ( g_gamestate.integer == GS_WARMUP || g_gamestate.integer == GS_WARMUP_COUNTDOWN ) { G_readyMatchState(); } }
/** * @brief Checks to see if a specified team is allowing players to join. * @param[in] team_num * @param[in] ent * @return */ qboolean G_teamJoinCheck(team_t team_num, gentity_t *ent) { int cnt = TeamCount(-1, team_num); // Sanity check if (cnt == 0) { G_teamReset(team_num, qtrue); teamInfo[team_num].team_lock = qfalse; } // Check for locked teams if ((team_num == TEAM_AXIS || team_num == TEAM_ALLIES)) { if (ent->client->sess.sessionTeam == team_num) { return qtrue; } if (g_gametype.integer != GT_WOLF_LMS) { // Check for full teams if (team_maxplayers.integer > 0 && team_maxplayers.integer <= cnt) { G_printFull(va("The %s team is full!", aTeams[team_num]), ent); return qfalse; // Check for locked teams } else if (teamInfo[team_num].team_lock && (!(ent->client->pers.invite & team_num))) { G_printFull(va("The %s team is LOCKED!", aTeams[team_num]), ent); return qfalse; } } else { if (team_maxplayers.integer > 0 && team_maxplayers.integer <= cnt) { G_printFull(va("The %s team is full!", aTeams[team_num]), ent); return qfalse; } else if (g_gamestate.integer == GS_PLAYING && g_lms_lockTeams.integer && (!(ent->client->pers.invite & team_num))) { G_printFull(va("The %s team is LOCKED!", aTeams[team_num]), ent); return qfalse; } } } return qtrue; }
// Puts a player on a team. void G_refPlayerPut_cmd(gentity_t *ent, int team_id) { int pid; char arg[MAX_TOKEN_CHARS]; gentity_t *player; // Works for teamplayish matches if(g_gametype.integer < GT_WOLF) { G_refPrintf(ent, "\"put[allies|axis]\" only for team-based games!"); return; } // yada - yeah right not giving an arg will end up as slot 0... // fixme: could maybe also be handled in ClientNumberFromString // if(ent&&!*s) return ent-g_entities; if(trap_Argc()!=3){ G_refPrintf(ent,"Usage: \\ref put[allies|axis] <pid>"); return; } // Find the player to place. trap_Argv(2, arg, sizeof(arg)); if((pid = ClientNumberFromString(ent, arg)) == -1) return; player = g_entities + pid; // Can only move to other teams. if(player->client->sess.sessionTeam == team_id) { // CHRUKER: b047 - Remove unneeded linebreak G_refPrintf(ent, "\"%s\" is already on team %s!", player->client->pers.netname, aTeams[team_id]); return; } if(team_maxplayers.integer && TeamCount(-1, team_id) >= team_maxplayers.integer) { // CHRUKER: b047 - Remove unneeded linebreak G_refPrintf(ent, "Sorry, the %s team is already full!", aTeams[team_id]); return; } player->client->pers.invite = team_id; player->client->pers.ready = qfalse; if( team_id == TEAM_AXIS ) { SetTeam( player, "red", qtrue, -1, -1, qfalse ); } else { SetTeam( player, "blue", qtrue, -1, -1, qfalse ); } if(g_gamestate.integer == GS_WARMUP || g_gamestate.integer == GS_WARMUP_COUNTDOWN) G_readyMatchState(); }
// Changes team lock status void G_refLockTeams_cmd(gentity_t * ent, qboolean fLock) { char *status; teamInfo[TEAM_AXIS].team_lock = (TeamCount(-1, TEAM_AXIS)) ? fLock : qfalse; teamInfo[TEAM_ALLIES].team_lock = (TeamCount(-1, TEAM_ALLIES)) ? fLock : qfalse; status = va("Referee has ^3%sLOCKED^7 teams", ((fLock) ? "" : "UN")); // CHRUKER: b041 - Was only sending this to ent, but it should be broadcasted G_printFull(status, NULL); G_refPrintf(ent, "You have %sLOCKED teams", ((fLock) ? "" : "UN")); // CHRUKER: b047 - Removed unneeded linebreak if(fLock) { level.server_settings |= CV_SVS_LOCKTEAMS; } else { level.server_settings &= ~CV_SVS_LOCKTEAMS; } trap_SetConfigstring(CS_SERVERTOGGLES, va("%d", level.server_settings)); }
/* ============= CheckTournament Once a frame, check for changes in tournement player state ============= */ void CheckTournament() { // check because we run 3 game frames before calling Connect and/or ClientBegin // for clients on a map_restart if( theLevel.numPlayingClients_ == 0 ) return; if( g_gametype.integer == GT_TOURNAMENT ) { // pull in a spectator if needed if( theLevel.numPlayingClients_ < 2 ) AddTournamentPlayer(); // if we don't have two players, go back to "waiting for players" if( theLevel.numPlayingClients_ != 2 ) { if( theLevel.warmupTime_ != -1 ) { theLevel.warmupTime_ = -1; SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) ); G_LogPrintf( "Warmup:\n" ); } return; } if( theLevel.warmupTime_ == 0 ) return; // if the warmup is changed at the console, restart it if( g_warmup.modificationCount != theLevel.warmupModificationCount_ ) { theLevel.warmupModificationCount_ = g_warmup.modificationCount; theLevel.warmupTime_ = -1; } // if all players have arrived, start the countdown if( theLevel.warmupTime_ < 0 ) { if( theLevel.numPlayingClients_ == 2 ) { // fudge by -1 to account for extra delays theLevel.warmupTime_ = theLevel.time_ + ( g_warmup.integer - 1 ) * 1000; SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) ); } return; } // if the warmup time has counted down, restart if( theLevel.time_ > theLevel.warmupTime_ ) { theLevel.warmupTime_ += 10000; Cvar_Set( "g_restarted", "1" ); Cbuf_ExecuteText( EXEC_APPEND, "map_restart 0\n" ); theLevel.restarted_ = true; return; } } else if( g_gametype.integer != GT_SINGLE_PLAYER && g_gametype.integer != GT_MISSION_EDITOR && theLevel.warmupTime_ != 0 ) { int counts[ClientBase::TEAM_NUM_TEAMS]; bool notEnough = false; if( g_gametype.integer > GT_TEAM ) { counts[ClientBase::TEAM_BLUE] = TeamCount( -1, ClientBase::TEAM_BLUE ); counts[ClientBase::TEAM_RED] = TeamCount( -1, ClientBase::TEAM_RED ); if (counts[ClientBase::TEAM_RED] < 1 || counts[ClientBase::TEAM_BLUE] < 1) notEnough = true; } else if( theLevel.numPlayingClients_ < 2 ) notEnough = true; if( notEnough ) { if( theLevel.warmupTime_ != -1 ) { theLevel.warmupTime_ = -1; SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) ); G_LogPrintf( "Warmup:\n" ); } return; // still waiting for team members } if( theLevel.warmupTime_ == 0 ) return; // if the warmup is changed at the console, restart it if( g_warmup.modificationCount != theLevel.warmupModificationCount_ ) { theLevel.warmupModificationCount_ = g_warmup.modificationCount; theLevel.warmupTime_ = -1; } // if all players have arrived, start the countdown if( theLevel.warmupTime_ < 0 ) { // fudge by -1 to account for extra delays theLevel.warmupTime_ = theLevel.time_ + ( g_warmup.integer - 1 ) * 1000; SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) ); return; } // if the warmup time has counted down, restart if( theLevel.time_ > theLevel.warmupTime_ ) { theLevel.warmupTime_ += 10000; Cvar_Set( "g_restarted", "1" ); Cbuf_ExecuteText( EXEC_APPEND, "map_restart 0\n" ); theLevel.restarted_ = true; return; } } }
/* LQ3A: Added bBroadcast parameter to allow the calling function to suppress the change. */ void SetTeam( gentity_t *ent, char *s, qboolean bBroadcast) { /* LQ3A */ team_t team, oldTeam; gclient_t *client; int clientNum; spectatorState_t specState; int specClient; int teamLeader; // // see what change is requested // client = ent->client; clientNum = client - level.clients; specClient = 0; specState = SPECTATOR_NOT; if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_SCOREBOARD; } else if ( !Q_stricmp( s, "follow1" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -1; } else if ( !Q_stricmp( s, "follow2" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -2; } else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FREE; } else if ( g_gametype.integer >= GT_TEAM ) { // if running a team game, assign player to one of the teams specState = SPECTATOR_NOT; if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) { team = TEAM_RED; } else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) { team = TEAM_BLUE; } else { // pick the team with the least number of players team = PickTeam( clientNum ); } if ( g_teamForceBalance.integer ) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( ent->client->ps.clientNum, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( ent->client->ps.clientNum, TEAM_RED ); // We allow a spread of two if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) { trap_SendServerCommand( ent->client->ps.clientNum, "cp \"Red team has too many players.\n\"" ); return; // ignore the request } if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) { trap_SendServerCommand( ent->client->ps.clientNum, "cp \"Blue team has too many players.\n\"" ); return; // ignore the request } // It's ok, the team we are switching to has less or same number of players } } else { // force them to spectators if there aren't any spots free /* LQ3A */ team = ((client->sess.sessionTeam == TEAM_FREE) || ((client->sess.sessionTeam != TEAM_FREE) && LQ3A_GetVacantPlayerSlots())) ? TEAM_FREE : TEAM_SPECTATOR; } // override decision if limiting the players if ( (g_gametype.integer == GT_TOURNAMENT) && level.numNonSpectatorClients >= 2 ) { team = TEAM_SPECTATOR; } else if ( g_maxGameClients.integer > 0 && level.numNonSpectatorClients > g_maxGameClients.integer ) { team = TEAM_SPECTATOR; } // // decide if we will allow the change // oldTeam = client->sess.sessionTeam; /* LQ3A */ if ( team == oldTeam /*&& team != TEAM_SPECTATOR*/ ) { return; } /* LQ3A: Ensure we're allowed to spectate. */ if ((team == TEAM_SPECTATOR) && !LQ3A_CanClientSpectate(ent)) { return; } // // execute the team change // // if the player was dead leave the body if ( client->ps.stats[STAT_HEALTH] <= 0 ) { CopyToBodyQue(ent); } // he starts at 'base' client->pers.teamState.state = TEAM_BEGIN; /* LQ3A*/ if (oldTeam == TEAM_SPECTATOR) { ent->r.svFlags &= ~SVF_NOCLIENT; client->pers.enterTime += (level.time - client->sess.spectatorTime); /* Restore the players score. */ client->ps.persistant[PERS_SCORE] = client->pers.iScore; } else if (ent->client->ps.stats[STAT_HEALTH] > 0) { // Kill him (makes sure he loses flags, etc) ent->flags &= ~FL_GODMODE; /* LQ3A: Kill the player if they have too little health. */ if ((g_spectatorFreePass.integer > 0) && (ent->client->ps.stats[STAT_HEALTH] < g_spectatorFreePass.integer)) { ent->client->ps.stats[STAT_HEALTH] = ent->health = 0; player_die (ent, ent, ent, 100000, MOD_SUICIDE); } else { /* LQ3A: Drop items and return flags when we're allowed to become a spectator without commiting suicide. */ // if client is in a nodrop area, don't drop anything (but return CTF flags!) if (!(trap_PointContents(ent->r.currentOrigin, -1) & CONTENTS_NODROP)) { TossClientItems(ent); } else { if (ent->client->ps.powerups[PW_NEUTRALFLAG]) { Team_ReturnFlag(TEAM_FREE); } else if (ent->client->ps.powerups[PW_REDFLAG]) { Team_ReturnFlag(TEAM_RED); } else if (ent->client->ps.powerups[PW_BLUEFLAG]) { Team_ReturnFlag(TEAM_BLUE); } } #ifdef MISSIONPACK TossClientPersistantPowerups(ent); if(g_gametype.integer == GT_HARVESTER) { TossClientCubes(ent); } #endif } } // they go to the end of the line for tournements if ( team == TEAM_SPECTATOR ) { /* LQ3A */ LQ3A_CompleteClientMoveToSpectatorTeam(ent); } client->sess.sessionTeam = team; client->sess.spectatorState = specState; client->sess.spectatorClient = specClient; client->sess.teamLeader = qfalse; if ( team == TEAM_RED || team == TEAM_BLUE ) { teamLeader = TeamLeader( team ); // if there is no team leader or the team leader is a bot and this client is not a bot if ( teamLeader == -1 || ( !(g_entities[clientNum].r.svFlags & SVF_BOT) && (g_entities[teamLeader].r.svFlags & SVF_BOT) ) ) { SetLeader( team, clientNum ); } } // make sure there is a team leader on the team the player came from if ( oldTeam == TEAM_RED || oldTeam == TEAM_BLUE ) { CheckTeamLeader( oldTeam ); } /* LQ3A: Broadcast the change when instructed to do so. */ if (bBroadcast) { BroadcastTeamChange(client, oldTeam); } // get and distribute relevent paramters ClientUserinfoChanged( clientNum ); /* LQ3A */ if (team != TEAM_SPECTATOR) { /* Spawn the client into the game. */ ClientBegin(clientNum); } else { /* Update the cached scores. */ CalculateRanks(); } }
//[/BotTweaks] //RACC - Adds/removes bots to maintain the minimum player limit. void G_CheckMinimumPlayers( void ) { int minplayers; int humanplayers, botplayers; //[BotTweaks] int humanplayers2, botplayers2; //[/BotTweaks] static int checkminimumplayers_time; //[TABBot] //We want the minimum players system to work in siege. /* if (g_gametype.integer == GT_SIEGE) { return; } */ //[/TABBot] //[NewGameTypes][EnhancedImpliment] /* if (g_gametype.integer == GT_RPG)// MJN - Not implementing this for RPG { return; } */ //[/NewGameTypes] //[TABBots] if(level.time - level.startTime < 10000) {//don't spawn in new bots for 10 seconds. Otherwise we're going to be adding/removing //bots before the original ones spawn in. return; } //[/TABBots] if (level.intermissiontime) return; //only check once each 10 seconds if (checkminimumplayers_time > level.time - 10000) { return; } checkminimumplayers_time = level.time; trap_Cvar_Update(&bot_minplayers); minplayers = bot_minplayers.integer; //[BotTweaks] //MJN - All that new fancy bot auto limiting code. :) if(g_allowBotLimit.integer == 0) { if (minplayers <= 0) return; } if(g_allowBotLimit.integer == 1) { if ( g_minHumans.integer < 0 ) {//clamp g_minHumans to positive values. g_minHumans.integer = 0; } if(g_maxBots.integer <= 0) {//just don't do anything if g_maxBots is zero or negative. return; } } if(g_allowBotLimit.integer == 1) {//use the new bot code that Chosen One did for us. // Teams each get Max Bots specified if (g_gametype.integer >= GT_TEAM) {//team gametypes // MJN - Make sure numbers don't exceed maxclients if (minplayers >= g_maxclients.integer / 2) { minplayers = (g_maxclients.integer / 2) -1; } if (g_maxBots.integer >= g_maxclients.integer / 2) { g_maxBots.integer = (g_maxclients.integer / 2) -1; } if (g_minHumans.integer >= g_maxclients.integer / 2) { g_minHumans.integer = (g_maxclients.integer / 2) -1; } //Handle Red Team Count //[AdminSys] humanplayers = G_CountHumanPlayers( -1, TEAM_RED ); //humanplayers = G_CountHumanPlayers( TEAM_RED ); //[/AdminSys] botplayers = G_CountBotPlayers( TEAM_RED ); if(botplayers < g_maxBots.integer && humanplayers < g_minHumans.integer ) { G_AddRandomBot( TEAM_RED ); } else if (humanplayers + botplayers > g_maxBots.integer && humanplayers >= g_minHumans.integer ) { G_RemoveRandomBot( TEAM_RED ); } //Handle Blue Team Count //[AdminSys] humanplayers2 = G_CountHumanPlayers( -1, TEAM_BLUE ); //humanplayers2 = G_CountHumanPlayers( TEAM_BLUE ); //[/AdminSys] botplayers2 = G_CountBotPlayers( TEAM_BLUE ); // MJN - Max Bots/Min Humans added here if(botplayers2 < g_maxBots.integer && humanplayers2 < g_minHumans.integer) { G_AddRandomBot( TEAM_BLUE ); } else if (humanplayers2 + botplayers2 > g_maxBots.integer && humanplayers2 >= g_minHumans.integer) { G_RemoveRandomBot( TEAM_BLUE ); } } else if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) {//duel gametypes // MJN - Make sure numbers don't exceed maxclients if (minplayers >= g_maxclients.integer) { minplayers = g_maxclients.integer-1; } if (g_maxBots.integer >= g_maxclients.integer) { g_maxBots.integer = g_maxclients.integer-1; } if (g_minHumans.integer >= g_maxclients.integer) { g_minHumans.integer = g_maxclients.integer-1; } //[AdminSys] humanplayers = G_CountHumanPlayers( -1, -1 ); //humanplayers = G_CountHumanPlayers( -1 ); //[/AdminSys] botplayers = G_CountBotPlayers( -1 ); if(botplayers < g_maxBots.integer && humanplayers < g_minHumans.integer) { G_AddRandomBot( TEAM_FREE ); } else if (humanplayers + botplayers > g_maxBots.integer && humanplayers >= g_minHumans.integer) { // try to remove spectators first if (!G_RemoveRandomBot( TEAM_SPECTATOR )) { // just remove the bot that is playing G_RemoveRandomBot( -1 ); } } } else if (g_gametype.integer == GT_FFA) {//ffa gametype // MJN - Make sure numbers don't exceed maxclients if (minplayers >= g_maxclients.integer) { minplayers = g_maxclients.integer-1; } if (g_maxBots.integer >= g_maxclients.integer) { g_maxBots.integer = g_maxclients.integer-1; } if (g_minHumans.integer >= g_maxclients.integer) { g_minHumans.integer = g_maxclients.integer-1; } //[AdminSys] humanplayers = G_CountHumanPlayers( -1, TEAM_FREE ); //humanplayers = G_CountHumanPlayers( TEAM_FREE ); //[/AdminSys] botplayers = G_CountBotPlayers( TEAM_FREE ); if(botplayers < g_maxBots.integer && humanplayers < g_minHumans.integer) { G_AddRandomBot( TEAM_FREE ); } else if (humanplayers + botplayers > g_maxBots.integer && humanplayers >= g_minHumans.integer) { G_RemoveRandomBot( TEAM_FREE ); } } else if (g_gametype.integer == GT_HOLOCRON || g_gametype.integer == GT_JEDIMASTER) {//special ffa gametypes // MJN - Make sure numbers don't exceed maxclients if (minplayers >= g_maxclients.integer) { minplayers = g_maxclients.integer-1; } if (g_maxBots.integer >= g_maxclients.integer) { g_maxBots.integer = g_maxclients.integer-1; } if (g_minHumans.integer >= g_maxclients.integer) { g_minHumans.integer = g_maxclients.integer-1; } //[AdminSys] humanplayers = G_CountHumanPlayers( -1, TEAM_FREE ); //humanplayers = G_CountHumanPlayers( TEAM_FREE ); //[/AdminSys] botplayers = G_CountBotPlayers( TEAM_FREE ); if(botplayers < g_maxBots.integer && humanplayers < g_minHumans.integer) { G_AddRandomBot( TEAM_FREE ); }else if (humanplayers + botplayers > g_maxBots.integer && humanplayers >= g_minHumans.integer) { G_RemoveRandomBot( TEAM_FREE ); } } } else {//use the basejka system for redundency's sake. if (minplayers <= 0) return; if (minplayers > g_maxclients.integer) { minplayers = g_maxclients.integer; } //[AdminSys] humanplayers = G_CountHumanPlayers( -1, -1 ); //humanplayers = G_CountHumanPlayers( -1 ); //[/AdminSys] botplayers = G_CountBotPlayers( -1 ); if ((humanplayers+botplayers) < minplayers) { G_AddRandomBot(-1); } else if ((humanplayers+botplayers) > minplayers && botplayers) { // try to remove spectators first if (!G_RemoveRandomBot(TEAM_SPECTATOR)) { //[AdminSys] if(g_gametype.integer < GT_TEAM) {//no teams, just remove a bot. G_RemoveRandomBot(-1); } else if( g_teamForceBalance.integer > 1 ) {//team game, determine which team to pull from. int botRemoveTeam = -1; int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( -1, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( -1, TEAM_RED ); //always remove bot from the team with the most players on it. //that should always balance the teams properly, except for human/bot //balancing. if(counts[TEAM_RED] > counts[TEAM_BLUE]) {//red team has too many players botRemoveTeam = TEAM_RED; } else if(counts[TEAM_BLUE] > counts[TEAM_RED]) {//blue team has too many players botRemoveTeam = TEAM_BLUE; } if(botRemoveTeam == -1 || !G_RemoveRandomBot(botRemoveTeam)) {//didn't have a specific team to remove from or we couldn't remove from the team //we wanted. G_RemoveRandomBot(-1); } } // just remove the bot that is playing //G_RemoveRandomBot(-1); //[/AdminSys] } } } /* basejka code if (minplayers <= 0) return; if (minplayers > g_maxclients.integer) { minplayers = g_maxclients.integer; } humanplayers = G_CountHumanPlayers( -1 ); botplayers = G_CountBotPlayers( -1 ); if ((humanplayers+botplayers) < minplayers) { G_AddRandomBot(-1); } else if ((humanplayers+botplayers) > minplayers && botplayers) { // try to remove spectators first if (!G_RemoveRandomBot(TEAM_SPECTATOR)) { // just remove the bot that is playing G_RemoveRandomBot(-1); } } */ //[/BotTweaks] /* if (g_gametype.integer >= GT_TEAM) { int humanplayers2, botplayers2; if (minplayers >= g_maxclients.integer / 2) { minplayers = (g_maxclients.integer / 2) -1; } humanplayers = G_CountHumanPlayers( TEAM_RED ); botplayers = G_CountBotPlayers( TEAM_RED ); humanplayers2 = G_CountHumanPlayers( TEAM_BLUE ); botplayers2 = G_CountBotPlayers( TEAM_BLUE ); // if ((humanplayers+botplayers+humanplayers2+botplayers) < minplayers) { if ((humanplayers+botplayers) < (humanplayers2+botplayers2)) { G_AddRandomBot( TEAM_RED ); } else { G_AddRandomBot( TEAM_BLUE ); } } else if ((humanplayers+botplayers+humanplayers2+botplayers) > minplayers && botplayers) { if ((humanplayers+botplayers) < (humanplayers2+botplayers2)) { G_RemoveRandomBot( TEAM_BLUE ); } else { G_RemoveRandomBot( TEAM_RED ); } } } else if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) { if (minplayers >= g_maxclients.integer) { minplayers = g_maxclients.integer-1; } humanplayers = G_CountHumanPlayers( -1 ); botplayers = G_CountBotPlayers( -1 ); // if (humanplayers + botplayers < minplayers) { G_AddRandomBot( TEAM_FREE ); } else if (humanplayers + botplayers > minplayers && botplayers) { // try to remove spectators first if (!G_RemoveRandomBot( TEAM_SPECTATOR )) { // just remove the bot that is playing G_RemoveRandomBot( -1 ); } } } else if (g_gametype.integer == GT_FFA) { if (minplayers >= g_maxclients.integer) { minplayers = g_maxclients.integer-1; } humanplayers = G_CountHumanPlayers( TEAM_FREE ); botplayers = G_CountBotPlayers( TEAM_FREE ); // if (humanplayers + botplayers < minplayers) { G_AddRandomBot( TEAM_FREE ); } else if (humanplayers + botplayers > minplayers && botplayers) { G_RemoveRandomBot( TEAM_FREE ); } } else if (g_gametype.integer == GT_HOLOCRON || g_gametype.integer == GT_JEDIMASTER) { if (minplayers >= g_maxclients.integer) { minplayers = g_maxclients.integer-1; } humanplayers = G_CountHumanPlayers( TEAM_FREE ); botplayers = G_CountBotPlayers( TEAM_FREE ); // if (humanplayers + botplayers < minplayers) { G_AddRandomBot( TEAM_FREE ); } else if (humanplayers + botplayers > minplayers && botplayers) { G_RemoveRandomBot( TEAM_FREE ); } } */ }
// Prints current player match info. // --> FIXME: put the pretty print on the client void G_printMatchInfo(gentity_t *ent) { int i, j, cnt = 0, eff, time_eff; int tot_timex, tot_timel, tot_timep, tot_kills, tot_deaths, tot_gibs, tot_sk, tot_tk, tot_tg, tot_dg, tot_dr, tot_tdg, tot_tdr, tot_xp; #ifdef FEATURE_RATING float tot_rating, tot_delta; #endif gclient_t *cl; char *ref; char n2[MAX_STRING_CHARS]; for (i = TEAM_AXIS; i <= TEAM_SPECTATOR; i++) { if (!TeamCount(-1, i)) { continue; } tot_timex = 0; tot_timel = 0; tot_timep = 0; tot_kills = 0; tot_deaths = 0; tot_gibs = 0; tot_sk = 0; tot_tk = 0; tot_tg = 0; tot_dg = 0; tot_dr = 0; tot_tdg = 0; tot_tdr = 0; tot_xp = 0; #ifdef FEATURE_RATING tot_rating = 0.f; tot_delta = 0.f; #endif CP("sc \"\n\""); #ifdef FEATURE_RATING CP("sc \"^7TEAM Player ^1 TmX^4 TmL^7 TmP^7 Kll Dth Gib SK TK TG^7 Eff^2 DG^1 DR^6 TDG^4 TDR^3 Score^8 Rating^5 Delta\n\""); CP("sc \"^7--------------------------------------------------------------------------------------------------------------\n\""); #else CP("sc \"^7TEAM Player ^1 TmX^4 TmL^7 TmP^7 Kll Dth Gib SK TK TG^7 Eff^2 DG^1 DR^6 TDG^4 TDR^3 Score\n\""); CP("sc \"^7-----------------------------------------------------------------------------------------------\n\""); #endif for (j = 0; j < level.numConnectedClients; j++) { cl = level.clients + level.sortedClients[j]; if (cl->pers.connected != CON_CONNECTED || cl->sess.sessionTeam != i) { continue; } SanitizeString(cl->pers.netname, n2, qfalse); n2[15] = 0; ref = "^7"; tot_timex += cl->sess.time_axis; tot_timel += cl->sess.time_allies; tot_timep += cl->sess.time_played; tot_kills += cl->sess.kills; tot_deaths += cl->sess.deaths; tot_gibs += cl->sess.gibs; tot_sk += cl->sess.self_kills; tot_tk += cl->sess.team_kills; tot_tg += cl->sess.team_gibs; tot_dg += cl->sess.damage_given; tot_dr += cl->sess.damage_received; tot_tdg += cl->sess.team_damage_given; tot_tdr += cl->sess.team_damage_received; tot_xp += cl->ps.persistant[PERS_SCORE]; #ifdef FEATURE_RATING tot_rating += cl->sess.mu - 3 * cl->sess.sigma; tot_delta += (cl->sess.mu - 3 * cl->sess.sigma) - (cl->sess.oldmu - 3 * cl->sess.oldsigma); #endif eff = (cl->sess.deaths + cl->sess.kills == 0) ? 0 : 100 * cl->sess.kills / (cl->sess.deaths + cl->sess.kills); if (eff < 0) { eff = 0; } time_eff = (cl->sess.time_axis + cl->sess.time_allies == 0) ? 0 : 100 * cl->sess.time_played / (cl->sess.time_axis + cl->sess.time_allies); if (ent->client == cl || (ent->client->sess.sessionTeam == TEAM_SPECTATOR && ent->client->sess.spectatorState == SPECTATOR_FOLLOW && ent->client->sess.spectatorClient == level.sortedClients[j])) { ref = "^3"; } cnt++; #ifdef FEATURE_RATING trap_SendServerCommand(ent - g_entities, va("sc \"%-14s %s%-15s^1%4d^4%4d^7%s%4d^3%4d%4d%4d%4d%4d%4d%s%4d^2%6d^1%6d^6%5d^4%5d^3%7d^8%8.2f^5%+7.2f\n\"", #else trap_SendServerCommand(ent - g_entities, va("sc \"%-14s %s%-15s^1%4d^4%4d^7%s%4d^3%4d%4d%4d%4d%4d%4d%s%4d^2%6d^1%6d^6%5d^4%5d^3%7d\n\"", #endif aTeams[i], ref, n2, cl->sess.time_axis / 60000, cl->sess.time_allies / 60000, ref, time_eff, cl->sess.kills, cl->sess.deaths, cl->sess.gibs, cl->sess.self_kills, cl->sess.team_kills, cl->sess.team_gibs, ref, eff, cl->sess.damage_given, cl->sess.damage_received, cl->sess.team_damage_given, cl->sess.team_damage_received, cl->ps.persistant[PERS_SCORE] #ifdef FEATURE_RATING , (cl->sess.mu - 3 * cl->sess.sigma < 0.f) ? 0.f : cl->sess.mu - 3 * cl->sess.sigma, (cl->sess.mu - 3 * cl->sess.sigma) - (cl->sess.oldmu - 3 * cl->sess.oldsigma) #endif )); } eff = (tot_kills + tot_deaths == 0) ? 0 : 100 * tot_kills / (tot_kills + tot_deaths); if (eff < 0) { eff = 0; } time_eff = (tot_timex + tot_timel == 0) ? 0 : 100 * tot_timep / (tot_timex + tot_timel); #ifdef FEATURE_RATING CP("sc \"^7--------------------------------------------------------------------------------------------------------------\n\""); trap_SendServerCommand(ent - g_entities, va("sc \"%-14s ^5%-15s^1%4d^4%4d^5%4d%4d%4d%4d%4d%4d%4d^5%4d^2%6d^1%6d^6%5d^4%5d^3%7d^8%8.2f^5%+7.2f\n\"", #else CP("sc \"^7-----------------------------------------------------------------------------------------------\n\""); trap_SendServerCommand(ent - g_entities, va("sc \"%-14s ^5%-15s^1%4d^4%4d^5%4d%4d%4d%4d%4d%4d%4d^5%4d^2%6d^1%6d^6%5d^4%5d^3%7d\n\"", #endif aTeams[i], "Totals", tot_timex / 60000, tot_timel / 60000, time_eff, tot_kills, tot_deaths, tot_gibs, tot_sk, tot_tk, tot_tg, eff, tot_dg, tot_dr, tot_tdg, tot_tdr, tot_xp #ifdef FEATURE_RATING , (tot_rating < 0.f) ? 0.f : tot_rating / TeamCount(-1, i), tot_delta / TeamCount(-1, i) #endif )); } CP(va("sc \"%s\n\n\" 0", ((!cnt) ? "^3\nNo scores to report." : ""))); }
// Prints current player match info. // --> FIXME: put the pretty print on the client void G_printMatchInfo(gentity_t *ent) { int i, j, cnt = 0, eff; int tot_timex, tot_timel, tot_kills, tot_deaths, tot_gp, tot_sk, tot_tk, tot_dg, tot_dr, tot_tdg, tot_tdr, tot_xp; gclient_t *cl; char *ref; char n2[MAX_STRING_CHARS]; for (i = TEAM_AXIS; i <= TEAM_ALLIES; i++) { if (!TeamCount(-1, i)) { continue; } tot_timex = 0; tot_timel = 0; tot_kills = 0; tot_deaths = 0; tot_sk = 0; tot_tk = 0; tot_dg = 0; tot_dr = 0; tot_tdg = 0; tot_tdr = 0; tot_gp = 0; tot_xp = 0; CP("sc \"\n\""); CP("sc \"^7TEAM Player ^1TmX ^4TmL ^7Kll Dth SK TK Eff ^3GP^7 ^2DG ^1DR ^6TDG ^4TDR ^3Score\n\""); CP("sc \"^7-----------------------------------------------------------------------------------\n\""); for (j = 0; j < level.numPlayingClients; j++) { cl = level.clients + level.sortedClients[j]; if (cl->pers.connected != CON_CONNECTED || cl->sess.sessionTeam != i) { continue; } SanitizeString(cl->pers.netname, n2, qfalse); n2[15] = 0; ref = "^7"; tot_timex += cl->sess.time_axis; tot_timel += cl->sess.time_allies; tot_kills += cl->sess.kills; tot_deaths += cl->sess.deaths; tot_sk += cl->sess.selfkills; tot_tk += cl->sess.team_kills; tot_dg += cl->sess.damage_given; tot_dr += cl->sess.damage_received; tot_tdg += cl->sess.team_damage_given; tot_tdr += cl->sess.team_damage_received; tot_gp += cl->sess.game_points; tot_xp += cl->ps.persistant[PERS_SCORE]; eff = (cl->sess.deaths + cl->sess.kills == 0) ? 0 : 100 * cl->sess.kills / (cl->sess.deaths + cl->sess.kills); if (eff < 0) { eff = 0; } if (ent->client == cl || (ent->client->sess.sessionTeam == TEAM_SPECTATOR && ent->client->sess.spectatorState == SPECTATOR_FOLLOW && ent->client->sess.spectatorClient == level.sortedClients[j])) { ref = "^3"; } cnt++; CP(va("sc \"%-10s %s%-15s^1%4d^4%4d^3%4d%4d%4d%4d%s%4d^3%4d^2%6d^1%6d^6%5d^4%5d^3%7d\n\"", aTeams[i], ref, n2, cl->sess.time_axis / 60000, cl->sess.time_allies / 60000, cl->sess.kills, cl->sess.deaths, cl->sess.selfkills, cl->sess.team_kills, ref, eff, cl->sess.game_points - (cl->sess.kills * WOLF_FRAG_BONUS), cl->sess.damage_given, cl->sess.damage_received, cl->sess.team_damage_given, cl->sess.team_damage_received, cl->ps.persistant[PERS_SCORE])); } eff = (tot_kills + tot_deaths == 0) ? 0 : 100 * tot_kills / (tot_kills + tot_deaths); if (eff < 0) { eff = 0; } CP("sc \"^7------------------------------------------- ---------------------------------------\n\""); CP(va("sc \"%-10s ^5%-15s^1%4d^4%4d^5%4d%4d%4d%4d^5%4d^3%4d^2%6d^1%6d^6%5d^4%5d^3%7d\n\"", aTeams[i], "Totals", tot_timex / 60000, tot_timel / 60000, tot_kills, tot_deaths, tot_sk, tot_tk, eff, tot_gp - (tot_kills * WOLF_FRAG_BONUS), tot_dg, tot_dr, tot_tdg, tot_tdr, tot_xp)); } CP(va("sc \"%s\n\n\" 0", ((!cnt) ? "^3\nNo scores to report." : ""))); }
void SetTeam( gentity_t *ent, char *s ) { int clientNum, specClient=0; team_t team, oldTeam; gclient_t *client = ent->client; spectatorState_t specState = SPECTATOR_NOT; // see what change is requested clientNum = ARRAY_INDEX( level.clients, client ); if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_SCOREBOARD; } else if ( !Q_stricmp( s, "follow1" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -1; } else if ( !Q_stricmp( s, "follow2" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -2; } else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FREE; } // if running a team game, assign player to one of the teams else if ( level.gametype >= GT_TEAMBLOOD ) { specState = SPECTATOR_NOT; if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) team = TEAM_RED; else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) team = TEAM_BLUE; else team = PickTeam( clientNum ); // pick the team with the least number of players if ( g_teamForceBalance->integer ) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( clientNum, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( clientNum, TEAM_RED ); // We allow a spread of two if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) { trap->SV_GameSendServerCommand( clientNum, "cp \"Red team has too many players.\n\"" ); return; // ignore the request } if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) { trap->SV_GameSendServerCommand( clientNum, "cp \"Blue team has too many players.\n\"" ); return; // ignore the request } // It's ok, the team we are switching to has less or same number of players } } else team = TEAM_FREE; // force them to spectators if there aren't any spots free // override decision if limiting the players if ( (level.gametype == GT_DUEL) && level.numNonSpectatorClients >= 2 ) team = TEAM_SPECTATOR; else if ( g_maxGameClients->integer > 0 && level.numNonSpectatorClients >= g_maxGameClients->integer ) team = TEAM_SPECTATOR; // decide if we will allow the change oldTeam = client->sess.sessionTeam; if ( team == oldTeam && team != TEAM_SPECTATOR ) return; // if the player was dead leave the body if ( client->ps.stats[STAT_HEALTH] <= 0 ) { CopyToBodyQue( ent ); } // he starts at 'base' client->pers.teamState.state = TEAM_BEGIN; if ( oldTeam != TEAM_SPECTATOR ) { // Kill him (makes sure he loses flags, etc) ent->flags &= ~FL_GODMODE; ent->client->ps.stats[STAT_HEALTH] = ent->health = 0; player_die( ent, ent, ent, 100000, MOD_SUICIDE ); } // they go to the end of the line for tournaments if ( team == TEAM_SPECTATOR && oldTeam != team ) AddTournamentQueue( client ); // exploit fix: with 3 (any odd amount?) players connected, one could /callvote map x followed by /team s to force the vote G_ClearVote( ent ); client->sess.sessionTeam = team; client->sess.spectatorState = specState; client->sess.spectatorClient = specClient; BroadcastTeamChange( client, oldTeam ); ClientUserinfoChanged( clientNum ); ClientBegin( clientNum ); }
// forty - #607 - Merge in Density's damage received display code // Prints current player match info. // --> FIXME: put the pretty print on the client void G_printMatchInfo(gentity_t *ent) { int i, j, cnt, eff; int tot_kills, tot_deaths, tot_gp, tot_sui, tot_tk, tot_dg, tot_dr, tot_tdg, tot_tdr; gclient_t *cl; char *ref; char n2[MAX_STRING_CHARS]; cnt = 0; for(i=TEAM_AXIS; i<=TEAM_ALLIES; i++) { if(!TeamCount(-1, i)) continue; tot_kills = 0; tot_deaths = 0; tot_sui = 0; tot_tk = 0; tot_dg = 0; tot_dr = 0; tot_tdg = 0; tot_tdr = 0; tot_gp = 0; // Dens: Added TDR CP("sc \"\n^7TEAM Player Kll Dth Sui TK Eff ^3GP^7 ^2DG ^1DR ^6TDG ^4TDR ^3Score\n" "^7--------------------------------------------------------------------------\n\""); for(j=0; j<level.numPlayingClients; j++) { cl = level.clients + level.sortedClients[j]; if(cl->pers.connected != CON_CONNECTED || cl->sess.sessionTeam != i) continue; SanitizeString(cl->pers.netname, n2, qfalse); n2[15] = 0; ref = "^7"; tot_kills += cl->sess.kills; tot_deaths += cl->sess.deaths; tot_sui += cl->sess.suicides; tot_tk += cl->sess.team_kills; tot_dg += cl->sess.damage_given; tot_dr += cl->sess.damage_received; tot_tdg += cl->sess.team_damage_given; tot_tdr += cl->sess.team_damage_received; tot_gp += cl->sess.game_points; eff = (cl->sess.deaths + cl->sess.kills == 0) ? 0 : 100 * cl->sess.kills / (cl->sess.deaths + cl->sess.kills); if(eff < 0) eff = 0; if(ent->client == cl || (ent->client->sess.sessionTeam == TEAM_SPECTATOR && ent->client->sess.spectatorState == SPECTATOR_FOLLOW && ent->client->sess.spectatorClient == level.sortedClients[j])) { ref = "^3"; } cnt++; CP(va("sc \"%-10s %s%-15s^3%4d%4d%4d%3d%s%4d^3%4d^2%6d^1%6d^6%5d^4%5d^3%7d\n\"", aTeams[i], ref, n2, cl->sess.kills, cl->sess.deaths, cl->sess.suicides, cl->sess.team_kills, ref, eff, cl->sess.game_points - (cl->sess.kills * WOLF_FRAG_BONUS), cl->sess.damage_given, cl->sess.damage_received, cl->sess.team_damage_given, cl->sess.team_damage_received, cl->ps.persistant[PERS_SCORE])); } eff = (tot_kills + tot_deaths == 0) ? 0 : 100 * tot_kills / (tot_kills + tot_deaths); if(eff < 0) eff = 0; CP(va("sc \"^7--------------------------------------------------------------------------\n" "%-10s ^5%-15s%4d%4d%4d%3d^5%4d^3%4d^2%6d^1%6d^6%5d^4%5d^3%7d\n\"", aTeams[i], "Totals", tot_kills, tot_deaths, tot_sui, tot_tk, eff, tot_gp - (tot_kills * WOLF_FRAG_BONUS), tot_dg, tot_dr, tot_tdg, tot_tdr, tot_gp)); } CP(va("sc \"%s\n\n\" 0", ((!cnt) ? "^3\nNo scores to report." : ""))); if (g_killRating.integer & KILL_RATING_VISIBLE) { //josh: reward messages for match and overall top killers G_TopKillersMessage(ent); } if (g_playerRating.integer & PLAYER_RATING_VISIBLE) { //josh: reward message for top player rating G_TopPlayerMessage(ent); } }
/* ============= CheckTournament Once a frame, check for changes in tournement player state ============= */ void CheckTournament( void ) { // check because we run 3 game frames before calling Connect and/or ClientBegin // for clients on a map_restart if ( level.numPlayingClients == 0 ) { return; } if ( g_gametype.integer == GT_TOURNAMENT ) { // pull in a spectator if needed if ( level.numPlayingClients < 2 ) { AddTournamentPlayer(); } // if we don't have two players, go back to "waiting for players" if ( level.numPlayingClients != 2 ) { if ( level.warmupTime != -1 ) { level.warmupTime = -1; trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) ); G_LogPrintf( "Warmup:\n" ); } return; } if ( level.warmupTime == 0 ) { return; } // if the warmup is changed at the console, restart it if ( g_warmup.modificationCount != level.warmupModificationCount ) { level.warmupModificationCount = g_warmup.modificationCount; level.warmupTime = -1; } // if all players have arrived, start the countdown if ( level.warmupTime < 0 ) { if ( level.numPlayingClients == 2 ) { // fudge by -1 to account for extra delays if ( g_warmup.integer > 1 ) { level.warmupTime = level.time + ( g_warmup.integer - 1 ) * 1000; } else { level.warmupTime = 0; } trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) ); } return; } // if the warmup time has counted down, restart if ( level.time > level.warmupTime ) { level.warmupTime += 10000; trap_Cvar_Set( "g_restarted", "1" ); trap_SendConsoleCommand( EXEC_APPEND, "map_restart 0\n" ); level.restarted = qtrue; return; } } else if ( g_gametype.integer != GT_SINGLE_PLAYER && level.warmupTime != 0 ) { int counts[TEAM_NUM_TEAMS]; qboolean notEnough = qfalse; if ( g_gametype.integer > GT_TEAM ) { counts[TEAM_BLUE] = TeamCount( -1, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( -1, TEAM_RED ); if (counts[TEAM_RED] < 1 || counts[TEAM_BLUE] < 1) { notEnough = qtrue; } } else if ( level.numPlayingClients < 2 ) { notEnough = qtrue; } if ( notEnough ) { if ( level.warmupTime != -1 ) { level.warmupTime = -1; trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) ); G_LogPrintf( "Warmup:\n" ); } return; // still waiting for team members } if ( level.warmupTime == 0 ) { return; } // if the warmup is changed at the console, restart it if ( g_warmup.modificationCount != level.warmupModificationCount ) { level.warmupModificationCount = g_warmup.modificationCount; level.warmupTime = -1; } // if all players have arrived, start the countdown if ( level.warmupTime < 0 ) { // fudge by -1 to account for extra delays if ( g_warmup.integer > 1 ) { level.warmupTime = level.time + ( g_warmup.integer - 1 ) * 1000; } else { level.warmupTime = 0; } trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) ); return; } // if the warmup time has counted down, restart if ( level.time > level.warmupTime ) { level.warmupTime += 10000; trap_Cvar_Set( "g_restarted", "1" ); trap_SendConsoleCommand( EXEC_APPEND, "map_restart 0\n" ); level.restarted = qtrue; return; } } }
/* ================= SetTeam ================= */ void SetTeam( gentity_t *ent, char *s ) { int team, oldTeam; gclient_t *client; int clientNum; spectatorState_t specState; int specClient; int teamLeader; // // see what change is requested // client = ent->client; clientNum = client - level.clients; specClient = 0; specState = SPECTATOR_NOT; if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_SCOREBOARD; } else if ( !Q_stricmp( s, "follow1" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -1; } else if ( !Q_stricmp( s, "follow2" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -2; } else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FREE; } else if ( g_gametype.integer >= GT_TEAM ) { // if running a team game, assign player to one of the teams specState = SPECTATOR_NOT; if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) { team = TEAM_RED; } else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) { team = TEAM_BLUE; } else { // pick the team with the least number of players team = PickTeam( clientNum ); } if ( g_teamForceBalance.integer ) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( clientNum, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( clientNum, TEAM_RED ); // We allow a spread of two if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) { trap_SendServerCommand( clientNum, "cp \"Red team has too many players.\n\"" ); return; // ignore the request } if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) { trap_SendServerCommand( clientNum, "cp \"Blue team has too many players.\n\"" ); return; // ignore the request } // It's ok, the team we are switching to has less or same number of players } } else { // force them to spectators if there aren't any spots free team = TEAM_FREE; } // override decision if limiting the players if ( (g_gametype.integer == GT_TOURNAMENT) && level.numNonSpectatorClients >= 2 ) { team = TEAM_SPECTATOR; } else if ( g_maxGameClients.integer > 0 && level.numNonSpectatorClients >= g_maxGameClients.integer ) { team = TEAM_SPECTATOR; } // // decide if we will allow the change // oldTeam = client->sess.sessionTeam; if ( team == oldTeam && team != TEAM_SPECTATOR ) { return; } // // execute the team change // // if the player was dead leave the body if ( client->ps.stats[STAT_HEALTH] <= 0 ) { CopyToBodyQue(ent); } // he starts at 'base' client->pers.teamState.state = TEAM_BEGIN; if ( oldTeam != TEAM_SPECTATOR ) { // Kill him (makes sure he loses flags, etc) ent->flags &= ~FL_GODMODE; ent->client->ps.stats[STAT_HEALTH] = ent->health = 0; player_die (ent, ent, ent, 100000, MOD_SUICIDE); } // they go to the end of the line for tournements if(team == TEAM_SPECTATOR && oldTeam != team) AddTournamentQueue(client); client->sess.sessionTeam = team; client->sess.spectatorState = specState; client->sess.spectatorClient = specClient; client->sess.teamLeader = qfalse; if ( team == TEAM_RED || team == TEAM_BLUE ) { teamLeader = TeamLeader( team ); // if there is no team leader or the team leader is a bot and this client is not a bot if ( teamLeader == -1 || ( !(g_entities[clientNum].r.svFlags & SVF_BOT) && (g_entities[teamLeader].r.svFlags & SVF_BOT) ) ) { SetLeader( team, clientNum ); } } // make sure there is a team leader on the team the player came from if ( oldTeam == TEAM_RED || oldTeam == TEAM_BLUE ) { CheckTeamLeader( oldTeam ); } BroadcastTeamChange( client, oldTeam ); // get and distribute relevent paramters ClientUserinfoChanged( clientNum ); ClientBegin( clientNum ); }