const char *CHL2MPRules::GetGameDescription( void ) { if ( IsTeamplay() ) return "Team Deathmatch"; return "Deathmatch"; }
bool IGameController::CheckTeamBalance() { if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime) return true; int aT[2] = {0, 0}; for(int i = 0; i < MAX_CLIENTS; i++) { CPlayer *pP = GameServer()->m_apPlayers[i]; if(pP && pP->GetTeam() != TEAM_SPECTATORS) aT[pP->GetTeam()]++; } char aBuf[256]; if(absolute(aT[0]-aT[1]) >= 2) { str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); if(GameServer()->m_pController->m_UnbalancedTick == -1) GameServer()->m_pController->m_UnbalancedTick = Server()->Tick(); return false; } else { str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); GameServer()->m_pController->m_UnbalancedTick = -1; return true; } }
bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) { int aT[2] = {0, 0}; if (!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime) return true; for(int i = 0; i < MAX_CLIENTS; i++) { CPlayer *pP = GameServer()->m_apPlayers[i]; if(pP && pP->GetTeam() != TEAM_SPECTATORS) aT[pP->GetTeam()]++; } // simulate what would happen if changed team aT[JoinTeam]++; if (pPlayer->GetTeam() != TEAM_SPECTATORS) aT[JoinTeam^1]--; // there is a player-difference of at least 2 if(absolute(aT[0]-aT[1]) >= 2) { // player wants to join team with less players if ((aT[0] < aT[1] && JoinTeam == TEAM_RED) || (aT[0] > aT[1] && JoinTeam == TEAM_BLUE)) return true; else return false; } else return true; }
bool IGameController::CanSpawn(CPlayer *pPlayer, vec2 *pOutPos) { CSpawnEval Eval; // spectators can't spawn if(pPlayer->GetTeam() == -1) return false; if(IsTeamplay()) { Eval.m_FriendlyTeam = pPlayer->GetTeam(); // try first try own team spawn, then normal spawn and then enemy EvaluateSpawnType(&Eval, 1+(pPlayer->GetTeam()&1)); if(!Eval.m_Got) { EvaluateSpawnType(&Eval, 0); if(!Eval.m_Got) EvaluateSpawnType(&Eval, 1+((pPlayer->GetTeam()+1)&1)); } } else { EvaluateSpawnType(&Eval, 0); EvaluateSpawnType(&Eval, 1); EvaluateSpawnType(&Eval, 2); } *pOutPos = Eval.m_Pos; return Eval.m_Got; }
bool IGameController::CanSpawn(int Team, vec2 *pOutPos) { CSpawnEval Eval; // spectators can't spawn if(Team == TEAM_SPECTATORS) return false; if(IsTeamplay()) { Eval.m_FriendlyTeam = Team; // first try own team spawn, then normal spawn and then enemy EvaluateSpawnType(&Eval, 1+(Team&1)); if(!Eval.m_Got) { EvaluateSpawnType(&Eval, 0); if(!Eval.m_Got) EvaluateSpawnType(&Eval, 1+((Team+1)&1)); } } else { EvaluateSpawnType(&Eval, 0); EvaluateSpawnType(&Eval, 1); EvaluateSpawnType(&Eval, 2); } *pOutPos = Eval.m_Pos; return Eval.m_Got; }
bool IGameController::CheckTeamBalance() { if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime) return true; int aT[2] = {0, 0}; for(int i = 0; i < MAX_CLIENTS; i++) { CPlayer *pP = GameServer()->m_apPlayers[i]; if(pP && pP->GetTeam() != -1) aT[pP->GetTeam()]++; } if(absolute(aT[0]-aT[1]) >= 2) { dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", aT[0], aT[1]); if(GameServer()->m_pController->m_UnbalancedTick == -1) GameServer()->m_pController->m_UnbalancedTick = Server()->Tick(); return false; } else { dbg_msg("game", "Team is balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->m_pController->m_UnbalancedTick = -1; return true; } }
void IGameController::Snap(int SnappingClient) { CNetObj_Game *pGameObj = (CNetObj_Game *)Server()->SnapNewItem(NETOBJTYPE_GAME, 0, sizeof(CNetObj_Game)); pGameObj->m_Paused = GameServer()->m_World.m_Paused; pGameObj->m_GameOver = m_GameOverTick==-1?0:1; pGameObj->m_SuddenDeath = m_SuddenDeath; pGameObj->m_ScoreLimit = g_Config.m_SvScorelimit; pGameObj->m_TimeLimit = g_Config.m_SvTimelimit; pGameObj->m_RoundStartTick = m_RoundStartTick; pGameObj->m_Flags = m_GameFlags; pGameObj->m_Warmup = m_Warmup; pGameObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0; pGameObj->m_RoundCurrent = m_RoundCount+1; if(SnappingClient == -1) { // we are recording a demo, just set the scores pGameObj->m_TeamscoreRed = m_aTeamscore[0]; pGameObj->m_TeamscoreBlue = m_aTeamscore[1]; } else { // TODO: this little hack should be removed pGameObj->m_TeamscoreRed = IsTeamplay() ? m_aTeamscore[0] : GameServer()->m_apPlayers[SnappingClient]->m_Score; pGameObj->m_TeamscoreBlue = m_aTeamscore[1]; } }
// spawn bool IGameController::CanSpawn(int Team, vec2 *pOutPos) const { // spectators can't spawn if(Team == TEAM_SPECTATORS || GameServer()->m_World.m_Paused || GameServer()->m_World.m_ResetRequested) return false; CSpawnEval Eval; if(IsTeamplay()) { Eval.m_FriendlyTeam = Team; // first try own team spawn, then normal spawn and then enemy EvaluateSpawnType(&Eval, 1+(Team&1)); if(!Eval.m_Got) { EvaluateSpawnType(&Eval, 0); if(!Eval.m_Got) EvaluateSpawnType(&Eval, 1+((Team+1)&1)); } } else { EvaluateSpawnType(&Eval, 0); EvaluateSpawnType(&Eval, 1); EvaluateSpawnType(&Eval, 2); } *pOutPos = Eval.m_Pos; return Eval.m_Got; }
// event int IGameController::OnCharacterDeath(CCharacter *pVictim, CPlayer *pKiller, int Weapon) { // do scoreing if(!pKiller || Weapon == WEAPON_GAME) return 0; if(pKiller == pVictim->GetPlayer()) pVictim->GetPlayer()->m_Score--; // suicide else { if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam()) pKiller->m_Score--; // teamkill else pKiller->m_Score++; // normal kill } if(Weapon == WEAPON_SELF) pVictim->GetPlayer()->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()*3.0f; // update spectator modes for dead players in survival if(m_GameFlags&GAMEFLAG_SURVIVAL) { for(int i = 0; i < MAX_CLIENTS; ++i) if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_DeadSpecMode) GameServer()->m_apPlayers[i]->UpdateDeadSpecMode(); } return 0; }
int IGameController::GetStartTeam() { // this will force the auto balancer to work overtime aswell if(g_Config.m_DbgStress) return TEAM_RED; if(g_Config.m_SvTournamentMode) return TEAM_SPECTATORS; // determine new team int Team = TEAM_RED; if(IsTeamplay()) Team = m_aTeamSize[TEAM_RED] > m_aTeamSize[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED; // check if there're enough player slots left if(m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < Server()->MaxClients()-g_Config.m_SvSpectatorSlots) { ++m_aTeamSize[Team]; m_UnbalancedTick = TBALANCE_CHECK; if(m_GameState == IGS_WARMUP_GAME && HasEnoughPlayers()) SetGameState(IGS_WARMUP_GAME, 0); return Team; } return TEAM_SPECTATORS; }
int IGameController::ClampTeam(int Team) { if(Team < 0) return TEAM_SPECTATORS; if(IsTeamplay()) return Team&1; return 0; }
int IGameController::ClampTeam(int Team) { if(Team < 0) // spectator return -1; if(IsTeamplay()) return Team&1; return 0; }
int IGameController::ClampTeam(int Team) const { if(Team < TEAM_RED) return TEAM_SPECTATORS; if(IsTeamplay()) return Team&1; return TEAM_RED; }
void IGameController::DoTeamBalance() { if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime || absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) < NUM_TEAMS) return; GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); float aTeamScore[NUM_TEAMS] = {0}; float aPlayerScore[MAX_CLIENTS] = {0.0f}; // gather stats for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS) { aPlayerScore[i] = GameServer()->m_apPlayers[i]->m_Score*Server()->TickSpeed()*60.0f/ (Server()->Tick()-GameServer()->m_apPlayers[i]->m_ScoreStartTick); aTeamScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPlayerScore[i]; } } int BiggerTeam = (m_aTeamSize[TEAM_RED] > m_aTeamSize[TEAM_BLUE]) ? TEAM_RED : TEAM_BLUE; int NumBalance = absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) / NUM_TEAMS; // balance teams do { CPlayer *pPlayer = 0; float ScoreDiff = aTeamScore[BiggerTeam]; for(int i = 0; i < MAX_CLIENTS; i++) { if(!GameServer()->m_apPlayers[i] || !CanBeMovedOnBalance(i)) continue; // remember the player whom would cause lowest score-difference if(GameServer()->m_apPlayers[i]->GetTeam() == BiggerTeam && (!pPlayer || absolute((aTeamScore[BiggerTeam^1]+aPlayerScore[i]) - (aTeamScore[BiggerTeam]-aPlayerScore[i])) < ScoreDiff)) { pPlayer = GameServer()->m_apPlayers[i]; ScoreDiff = absolute((aTeamScore[BiggerTeam^1]+aPlayerScore[i]) - (aTeamScore[BiggerTeam]-aPlayerScore[i])); } } // move the player to the other team if(pPlayer) { int Temp = pPlayer->m_LastActionTick; DoTeamChange(pPlayer, BiggerTeam^1); pPlayer->m_LastActionTick = Temp; pPlayer->Respawn(); GameServer()->SendGameMsg(GAMEMSG_TEAM_BALANCE_VICTIM, pPlayer->GetTeam(), pPlayer->GetCID()); } } while(--NumBalance); m_UnbalancedTick = TBALANCE_OK; GameServer()->SendGameMsg(GAMEMSG_TEAM_BALANCE, -1); }
void IGameController::OnPlayerInfoChange(class CPlayer *pP) { const int aTeamColors[2] = {65387, 10223467}; if(IsTeamplay()) { if(pP->GetTeam() >= 0 || pP->GetTeam() <= 1) { pP->m_TeeInfos.m_UseCustomColor = 1; pP->m_TeeInfos.m_ColorBody = aTeamColors[pP->GetTeam()]; pP->m_TeeInfos.m_ColorFeet = aTeamColors[pP->GetTeam()]; } } }
// team bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) const { if(!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime) return true; // simulate what would happen if the player changes team int aPlayerCount[NUM_TEAMS] = { m_aTeamSize[TEAM_RED], m_aTeamSize[TEAM_BLUE] }; aPlayerCount[JoinTeam]++; if(pPlayer->GetTeam() != TEAM_SPECTATORS) aPlayerCount[JoinTeam^1]--; // check if the player-difference decreases or is smaller than 2 return aPlayerCount[JoinTeam]-aPlayerCount[JoinTeam^1] < NUM_TEAMS; }
const char *IGameController::GetTeamName(int Team) const { if(IsTeamplay()) { if(Team == TEAM_RED) return "red team"; else if(Team == TEAM_BLUE) return "blue team"; } else if(Team == 0) return "game"; return "spectators"; }
//----------------------------------------------------------------------------- // Purpose: Find the relationship between players (teamplay vs. deathmatch) //----------------------------------------------------------------------------- int CSDKGameRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) { #ifndef CLIENT_DLL // half life multiplay has a simple concept of Player Relationships. // you are either on another player's team, or you are not. if ( !pPlayer || !pTarget || !pTarget->IsPlayer() || IsTeamplay() == false ) return GR_NOTTEAMMATE; if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) ) return GR_TEAMMATE; #endif return GR_NOTTEAMMATE; }
int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon) { // do scoreing if(!pKiller || Weapon == WEAPON_GAME) return 0; if(pKiller == pVictim->GetPlayer()) pVictim->GetPlayer()->m_Score--; // suicide else { if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam()) pKiller->m_Score--; // teamkill else pKiller->m_Score++; // normal kill } return 0; }
bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) { if(ClientID1 == ClientID2) return false; if(IsTeamplay()) { if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2]) return false; if(GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam()) return true; } return false; }
void IGameController::DoWincheck() { if(m_GameOverTick == -1 && !m_Warmup && !GameServer()->m_World.m_ResetRequested) { if(IsTeamplay()) { // check score win condition if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) || (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) { if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE]) EndRound(); else m_SuddenDeath = 1; } } else { // gather some stats int Topscore = 0; int TopscoreCount = 0; for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i]) { if(GameServer()->m_apPlayers[i]->m_Score > Topscore) { Topscore = GameServer()->m_apPlayers[i]->m_Score; TopscoreCount = 1; } else if(GameServer()->m_apPlayers[i]->m_Score == Topscore) TopscoreCount++; } } // check score win condition if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) || (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) { if(TopscoreCount == 1) EndRound(); else m_SuddenDeath = 1; } } } }
const char *IGameController::GetTeamName(int Team) { if(IsTeamplay()) { if(Team == 0) return "red team"; else if(Team == 1) return "blue team"; } else { if(Team == 0) return "game"; } return "spectators"; }
void IGameController::OnPlayerInfoChange(class CPlayer *pP) { const int aTeamColors[2] = {65387, 10223467}; if(IsTeamplay()) { pP->m_TeeInfos.m_UseCustomColor = 1; if(pP->GetTeam() >= TEAM_RED && pP->GetTeam() <= TEAM_BLUE) { pP->m_TeeInfos.m_ColorBody = aTeamColors[pP->GetTeam()]; pP->m_TeeInfos.m_ColorFeet = aTeamColors[pP->GetTeam()]; } else { pP->m_TeeInfos.m_ColorBody = 12895054; pP->m_TeeInfos.m_ColorFeet = 12895054; } } }
// game void IGameController::DoWincheckMatch() { if(IsTeamplay()) { // check score win condition if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) || (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) { if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE] || m_GameFlags&GAMEFLAG_SURVIVAL) EndMatch(); else m_SuddenDeath = 1; } } else { // gather some stats int Topscore = 0; int TopscoreCount = 0; for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i]) { if(GameServer()->m_apPlayers[i]->m_Score > Topscore) { Topscore = GameServer()->m_apPlayers[i]->m_Score; TopscoreCount = 1; } else if(GameServer()->m_apPlayers[i]->m_Score == Topscore) TopscoreCount++; } } // check score win condition if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) || (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) { if(TopscoreCount == 1) EndMatch(); else m_SuddenDeath = 1; } } }
void IGameController::CheckTeamBalance() { if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime) { m_UnbalancedTick = TBALANCE_OK; return; } // check if teams are unbalanced char aBuf[256]; if(absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) >= NUM_TEAMS) { str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", m_aTeamSize[TEAM_RED], m_aTeamSize[TEAM_BLUE]); if(m_UnbalancedTick <= TBALANCE_OK) m_UnbalancedTick = Server()->Tick(); } else { str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", m_aTeamSize[TEAM_RED], m_aTeamSize[TEAM_BLUE]); m_UnbalancedTick = TBALANCE_OK; } GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); }
int IGameController::GetAutoTeam(int Notthisid) { // this will force the auto balancer to work overtime aswell if(g_Config.m_DbgStress) return 0; int aNumplayers[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i] && i != Notthisid) { if(GameServer()->m_apPlayers[i]->GetTeam() == 0 || GameServer()->m_apPlayers[i]->GetTeam() == 1) aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++; } } int Team = 0; if(IsTeamplay()) Team = aNumplayers[0] > aNumplayers[1] ? 1 : 0; if(CanJoinTeam(Team, Notthisid)) return Team; return -1; }
int IGameController::GetAutoTeam(int NotThisID) { // this will force the auto balancer to work overtime aswell if(g_Config.m_DbgStress) return 0; int aNumplayers[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i] && i != NotThisID) { if(GameServer()->m_apPlayers[i]->GetTeam() >= TEAM_RED && GameServer()->m_apPlayers[i]->GetTeam() <= TEAM_BLUE) aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++; } } int Team = 0; if(IsTeamplay()) Team = aNumplayers[TEAM_RED] > aNumplayers[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED; if(CanJoinTeam(Team, NotThisID)) return Team; return -1; }
void IGameController::Tick() { // do warmup if(m_Warmup) { m_Warmup--; if(!m_Warmup) StartRound(); } if(m_GameOverTick != -1) { // game over.. wait for restart if(Server()->Tick() > m_GameOverTick+Server()->TickSpeed()*10) { CycleMap(); StartRound(); m_RoundCount++; } } // do team-balancing if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) { GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); int aT[2] = {0,0}; float aTScore[2] = {0,0}; float aPScore[MAX_CLIENTS] = {0.0f}; for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS) { aT[GameServer()->m_apPlayers[i]->GetTeam()]++; aPScore[i] = GameServer()->m_apPlayers[i]->m_Score*Server()->TickSpeed()*60.0f/ (Server()->Tick()-GameServer()->m_apPlayers[i]->m_ScoreStartTick); aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPScore[i]; } } // are teams unbalanced? if(absolute(aT[0]-aT[1]) >= 2) { int M = (aT[0] > aT[1]) ? 0 : 1; int NumBalance = absolute(aT[0]-aT[1]) / 2; do { CPlayer *pP = 0; float PD = aTScore[M]; for(int i = 0; i < MAX_CLIENTS; i++) { if(!GameServer()->m_apPlayers[i] || !CanBeMovedOnBalance(i)) continue; // remember the player who would cause lowest score-difference if(GameServer()->m_apPlayers[i]->GetTeam() == M && (!pP || absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])) < PD)) { pP = GameServer()->m_apPlayers[i]; PD = absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])); } } // move the player to the other team int Temp = pP->m_LastActionTick; pP->SetTeam(M^1); pP->m_LastActionTick = Temp; pP->Respawn(); pP->m_ForceBalanced = true; } while (--NumBalance); m_ForceBalanced = true; } m_UnbalancedTick = -1; } // check for inactive players if(g_Config.m_SvInactiveKickTime > 0) { for(int i = 0; i < MAX_CLIENTS; ++i) { if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS && !Server()->IsAuthed(i)) { if(Server()->Tick() > GameServer()->m_apPlayers[i]->m_LastActionTick+g_Config.m_SvInactiveKickTime*Server()->TickSpeed()*60) { switch(g_Config.m_SvInactiveKick) { case 0: { // move player to spectator GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS); } break; case 1: { // move player to spectator if the reserved slots aren't filled yet, kick him otherwise int Spectators = 0; for(int j = 0; j < MAX_CLIENTS; ++j) if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS) ++Spectators; if(Spectators >= g_Config.m_SvSpectatorSlots) Server()->Kick(i, "Kicked for inactivity"); else GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS); } break; case 2: { // kick the player Server()->Kick(i, "Kicked for inactivity"); } } } } } } // first condition is because player score gets reset pretty late. second is to not get two votes, if both sv_endvote_* are set. // third is to only cause the vote in the last round if (m_RoundStartTick != Server()->Tick() && *g_Config.m_SvMaprotation && !m_AutoVoteCaused && m_RoundCount >= g_Config.m_SvRoundsPerMap - 1) { if (g_Config.m_SvEndvoteTime > 0 && g_Config.m_SvTimelimit > 0 && g_Config.m_SvEndvoteTime < g_Config.m_SvTimelimit*60 && Server()->Tick() - m_RoundStartTick >= (g_Config.m_SvTimelimit*60 - g_Config.m_SvEndvoteTime) * Server()->TickSpeed()) { AutoVote(); //time } else if (g_Config.m_SvEndvoteScore > 0 && g_Config.m_SvScorelimit > 0 && g_Config.m_SvEndvoteScore < g_Config.m_SvScorelimit) { int Max = 0; if (m_GameFlags & GAMEFLAG_TEAMS) Max = m_aTeamscore[m_aTeamscore[TEAM_RED] > m_aTeamscore[TEAM_BLUE] ? TEAM_RED : TEAM_BLUE]; else for(int i = 0; i < MAX_CLIENTS; ++i) if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_Score > Max) Max = GameServer()->m_apPlayers[i]->m_Score; if (Max + g_Config.m_SvEndvoteScore >= g_Config.m_SvScorelimit) AutoVote(); //score } } }
void IGameController::Tick() { // do warmup if(m_Warmup) { m_Warmup--; if(!m_Warmup) StartRound(); } if(m_GameOverTick != -1) { // game over.. wait for restart if(Server()->Tick() > m_GameOverTick+Server()->TickSpeed()*10) { CycleMap(); StartRound(); m_RoundCount++; } } // game is Paused if(GameServer()->m_World.m_Paused) ++m_RoundStartTick; // do team-balancing if(IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) { GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); int aT[2] = {0,0}; float aTScore[2] = {0,0}; float aPScore[MAX_CLIENTS] = {0.0f}; for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS) { aT[GameServer()->m_apPlayers[i]->GetTeam()]++; aPScore[i] = GameServer()->m_apPlayers[i]->m_Score*Server()->TickSpeed()*60.0f/ (Server()->Tick()-GameServer()->m_apPlayers[i]->m_ScoreStartTick); aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPScore[i]; } } // are teams unbalanced? if(absolute(aT[0]-aT[1]) >= 2) { int M = (aT[0] > aT[1]) ? 0 : 1; int NumBalance = absolute(aT[0]-aT[1]) / 2; do { CPlayer *pP = 0; float PD = aTScore[M]; for(int i = 0; i < MAX_CLIENTS; i++) { if(!GameServer()->m_apPlayers[i] || !CanBeMovedOnBalance(i)) continue; // remember the player who would cause lowest score-difference if(GameServer()->m_apPlayers[i]->GetTeam() == M && (!pP || absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])) < PD)) { pP = GameServer()->m_apPlayers[i]; PD = absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])); } } // move the player to the other team int Temp = pP->m_LastActionTick; pP->SetTeam(M^1); pP->m_LastActionTick = Temp; pP->Respawn(); pP->m_ForceBalanced = true; } while (--NumBalance); m_ForceBalanced = true; } m_UnbalancedTick = -1; } // check for inactive players if(g_Config.m_SvInactiveKickTime > 0) { // dont kick bots for(int i = 0; i < FIRST_BOT_ID; ++i) { #ifdef CONF_DEBUG if(g_Config.m_DbgDummies) { if(i >= MAX_CLIENTS-g_Config.m_DbgDummies) break; } #endif if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS && !Server()->IsAuthed(i)) { if(Server()->Tick() > GameServer()->m_apPlayers[i]->m_LastActionTick+g_Config.m_SvInactiveKickTime*Server()->TickSpeed()*60) { switch(g_Config.m_SvInactiveKick) { case 0: { // move player to spectator GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS); } break; case 1: { // move player to spectator if the reserved slots aren't filled yet, kick him otherwise int Spectators = 0; for(int j = 0; j < FIRST_BOT_ID; ++j) if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS) ++Spectators; if(Spectators >= g_Config.m_SvSpectatorSlots) Server()->Kick(i, "Kicked for inactivity"); else GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS); } break; case 2: { // kick the player Server()->Kick(i, "Kicked for inactivity"); } } } } } } DoWincheck(); }
void CHL2MPRules::Think( void ) { #ifndef CLIENT_DLL CGameRules::Think(); if ( g_fGameOver ) // someone else quit the game already { // check to see if we should change levels now if ( m_flIntermissionEndTime < gpGlobals->curtime ) { if ( !m_bChangelevelDone ) { ChangeLevel(); // intermission is over m_bChangelevelDone = true; } } return; } // float flTimeLimit = mp_timelimit.GetFloat() * 60; float flFragLimit = fraglimit.GetFloat(); if ( GetMapRemainingTime() < 0 ) { GoToIntermission(); return; } if ( flFragLimit ) { if( IsTeamplay() == true ) { CTeam *pCombine = g_Teams[TEAM_COMBINE]; CTeam *pRebels = g_Teams[TEAM_REBELS]; if ( pCombine->GetScore() >= flFragLimit || pRebels->GetScore() >= flFragLimit ) { GoToIntermission(); return; } } else { // check if any player is over the frag limit for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); if ( pPlayer && pPlayer->FragCount() >= flFragLimit ) { GoToIntermission(); return; } } } } if ( gpGlobals->curtime > m_tmNextPeriodicThink ) { CheckAllPlayersReady(); CheckRestartGame(); m_tmNextPeriodicThink = gpGlobals->curtime + 1.0; } if ( m_flRestartGameTime > 0.0f && m_flRestartGameTime <= gpGlobals->curtime ) { RestartGame(); } if( m_bAwaitingReadyRestart && m_bHeardAllPlayersReady ) { UTIL_ClientPrintAll( HUD_PRINTCENTER, "All players ready. Game will restart in 5 seconds" ); UTIL_ClientPrintAll( HUD_PRINTCONSOLE, "All players ready. Game will restart in 5 seconds" ); m_flRestartGameTime = gpGlobals->curtime + 5; m_bAwaitingReadyRestart = false; } ManageObjectRelocation(); #endif }