| 2057 | } |
| 2058 | |
| 2059 | bool updateclientteam(int cln, int newteam, int ftr) |
| 2060 | { |
| 2061 | if(!valid_client(cln)) return false; |
| 2062 | if(!team_isvalid(newteam) && newteam != TEAM_ANYACTIVE) newteam = TEAM_SPECT; |
| 2063 | client &cl = *clients[cln]; |
| 2064 | if(cl.team == newteam && ftr != FTR_AUTOTEAM) return true; // no change |
| 2065 | int *teamsizes = numteamclients(cln); |
| 2066 | if( sg->mastermode == MM_OPEN && cl.state.forced && ftr == FTR_PLAYERWISH && newteam < TEAM_SPECT && team_base(cl.team) != team_base(newteam) ) return false; // player forced to team => deny wish to change |
| 2067 | if(newteam == TEAM_ANYACTIVE) // when spawning from spect – 20210601: or just after dying in a deathmatch .. apparently. |
| 2068 | { |
| 2069 | if(sg->mastermode == MM_MATCH && cl.team < TEAM_SPECT) |
| 2070 | { |
| 2071 | newteam = team_base(cl.team); |
| 2072 | } |
| 2073 | else |
| 2074 | { |
| 2075 | // join (autoteam => smaller || balanced => weaker(*)) team. (*): if theres enough data to establish strength, otherwise fallback to random |
| 2076 | if(sg->autoteam && teamsizes[TEAM_CLA] != teamsizes[TEAM_RVSF]) newteam = teamsizes[TEAM_CLA] < teamsizes[TEAM_RVSF] ? TEAM_CLA : TEAM_RVSF; |
| 2077 | else |
| 2078 | { |
| 2079 | int teamscore[2] = {0, 0}, sum = calcscores(); // sum != 0 is either <0 if match data based or >0 vita based and exceeded shuffleteamthreshold |
| 2080 | loopv(clients) if(clients[i]->type!=ST_EMPTY && i != cln && clients[i]->isauthed && clients[i]->team != TEAM_SPECT) |
| 2081 | { |
| 2082 | teamscore[team_base(clients[i]->team)] += clients[i]->at3_score; |
| 2083 | } |
| 2084 | newteam = sum==0 ? rnd(2) : (teamscore[TEAM_CLA] < teamscore[TEAM_RVSF] ? TEAM_CLA : TEAM_RVSF); |
| 2085 | } |
| 2086 | } |
| 2087 | } |
| 2088 | if(ftr == FTR_PLAYERWISH) |
| 2089 | { |
| 2090 | if(sg->mastermode == MM_MATCH && sg->matchteamsize && m_teammode) |
| 2091 | { |
| 2092 | if(newteam != TEAM_SPECT && (team_base(newteam) != team_base(cl.team) || !m_teammode)) return false; // no switching sides in match mode when teamsize is set |
| 2093 | } |
| 2094 | if(team_isactive(newteam)) |
| 2095 | { |
| 2096 | if(!m_teammode && cl.state.state == CS_ALIVE) return false; // no comments |
| 2097 | if(sg->mastermode == MM_MATCH) |
| 2098 | { |
| 2099 | if(m_teammode && sg->matchteamsize && teamsizes[newteam] >= sg->matchteamsize) return false; // ensure maximum team size |
| 2100 | } |
| 2101 | else |
| 2102 | { |
| 2103 | if(m_teammode && sg->autoteam && teamsizes[newteam] > teamsizes[team_opposite(newteam)]) return false; // don't switch to an already bigger team |
| 2104 | } |
| 2105 | } |
| 2106 | else if(sg->mastermode != MM_MATCH || !m_teammode) newteam = TEAM_SPECT; // only match mode (team) has more than one spect team |
| 2107 | } |
| 2108 | if(cl.team == newteam && ftr != FTR_AUTOTEAM) return true; // no change |
| 2109 | if(cl.team != newteam) sdropflag(cl.clientnum); |
| 2110 | if(ftr != FTR_INFO && (team_isspect(newteam) || (team_isactive(newteam) && team_isactive(cl.team)))) forcedeath(&cl); |
| 2111 | sendf(-1, 1, "riii", SV_SETTEAM, cln, newteam | ((ftr == FTR_SILENTFORCE ? FTR_INFO : ftr) << 4)); |
| 2112 | if(ftr != FTR_INFO && !team_isspect(newteam) && team_isspect(cl.team)) sendspawn(&cl); |
| 2113 | if (team_isspect(newteam)) { |
| 2114 | cl.state.state = CS_SPECTATE; |
| 2115 | cl.state.lastdeath = sg->gamemillis; |
| 2116 | if(m_flags_ && clienthasflag(cl.clientnum) >= 0) // switching to spectate while holding the flag punishment |
no test coverage detected