void G_ChangeTeam( gentity_t *ent, team_t newTeam ) { team_t oldTeam = (team_t) ent->client->pers.team; if ( oldTeam == newTeam ) { return; } G_LeaveTeam( ent ); ent->client->pers.teamChangeTime = level.time; ent->client->pers.team = newTeam; ent->client->pers.teamInfo = level.startTime - 1; ent->client->pers.classSelection = PCL_NONE; ClientSpawn( ent, nullptr, nullptr, nullptr ); if ( oldTeam == TEAM_HUMANS && newTeam == TEAM_ALIENS ) { // Convert from human to alien credits ent->client->pers.credit = ( int )( ent->client->pers.credit * ALIEN_MAX_CREDITS / HUMAN_MAX_CREDITS + 0.5f ); } else if ( oldTeam == TEAM_ALIENS && newTeam == TEAM_HUMANS ) { // Convert from alien to human credits ent->client->pers.credit = ( int )( ent->client->pers.credit * HUMAN_MAX_CREDITS / ALIEN_MAX_CREDITS + 0.5f ); } if ( !g_cheats.integer ) { if ( ent->client->noclip ) { ent->client->noclip = false; ent->r.contents = ent->client->cliprcontents; } ent->flags &= ~( FL_GODMODE | FL_NOTARGET ); } // Copy credits to ps for the client ent->client->ps.persistant[ PERS_CREDIT ] = ent->client->pers.credit; // Update PERS_UNLOCKABLES in the same frame as PERS_TEAM to prevent bad status change notifications ent->client->ps.persistant[ PERS_UNLOCKABLES ] = BG_UnlockablesMask( newTeam ); ClientUserinfoChanged( ent->client->ps.clientNum, false ); G_UpdateTeamConfigStrings(); Beacon::PropagateAll( ); G_LogPrintf( "ChangeTeam: %d %s: %s^* switched teams", ( int )( ent - g_entities ), BG_TeamName( newTeam ), ent->client->pers.netname ); G_namelog_update_score( ent->client ); TeamplayInfoMessage( ent ); }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect( int clientNum ) { gentity_t *ent; gentity_t *tent; int i; buildHistory_t *ptr; ent = g_entities + clientNum; if( !ent->client ) return; // look through the bhist and readjust it if the referenced ent has left for( ptr = level.buildHistory; ptr; ptr = ptr->next ) { if( ptr->ent == ent ) { ptr->ent = NULL; Q_strncpyz( ptr->name, ent->client->pers.netname, MAX_NETNAME ); } } G_admin_namelog_update( ent->client, qtrue ); G_LeaveTeam( ent ); // stop any following clients for( i = 0; i < level.maxclients; i++ ) { // remove any /ignore settings for this clientNum BG_ClientListRemove( &level.clients[ i ].sess.ignoreList, clientNum ); } // send effect if they were completely connected if( ent->client->pers.connected == CON_CONNECTED && ent->client->sess.sessionTeam != TEAM_SPECTATOR ) { tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT ); tent->s.clientNum = ent->s.clientNum; } if( ent->client->pers.connection ) ent->client->pers.connection->clientNum = -1; G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s\"\n", clientNum, ent->client->pers.ip, ent->client->pers.guid, ent->client->pers.netname ); trap_UnlinkEntity( ent ); ent->s.modelindex = 0; ent->inuse = qfalse; ent->classname = "disconnected"; ent->client->pers.connected = CON_DISCONNECTED; ent->client->ps.persistant[ PERS_TEAM ] = TEAM_FREE; ent->client->sess.sessionTeam = TEAM_FREE; trap_SetConfigstring( CS_PLAYERS + clientNum, ""); CalculateRanks( ); }
/* ================= G_ChangeTeam ================= */ void G_ChangeTeam( gentity_t *ent, team_t newTeam ) { team_t oldTeam = ent->client->pers.teamSelection; if ( oldTeam == newTeam ) { return; } G_LeaveTeam( ent ); ent->client->pers.teamChangeTime = level.time; ent->client->pers.teamSelection = newTeam; ent->client->pers.classSelection = PCL_NONE; ClientSpawn( ent, NULL, NULL, NULL ); if ( oldTeam == TEAM_HUMANS && newTeam == TEAM_ALIENS ) { // Convert from human to alien credits ent->client->pers.credit = ( int )( ent->client->pers.credit * ALIEN_MAX_CREDITS / HUMAN_MAX_CREDITS + 0.5f ); } else if ( oldTeam == TEAM_ALIENS && newTeam == TEAM_HUMANS ) { // Convert from alien to human credits ent->client->pers.credit = ( int )( ent->client->pers.credit * HUMAN_MAX_CREDITS / ALIEN_MAX_CREDITS + 0.5f ); } if ( !g_cheats.integer ) { if ( ent->client->noclip ) { ent->client->noclip = qfalse; ent->r.contents = ent->client->cliprcontents; } ent->flags &= ~( FL_GODMODE | FL_NOTARGET ); } // Copy credits to ps for the client ent->client->ps.persistant[ PERS_CREDIT ] = ent->client->pers.credit; ClientUserinfoChanged( ent->client->ps.clientNum, qfalse ); G_UpdateTeamConfigStrings(); G_LogPrintf( "ChangeTeam: %d %s: %s" S_COLOR_WHITE " switched teams\n", ( int )( ent - g_entities ), BG_TeamName( newTeam ), ent->client->pers.netname ); G_namelog_update_score( ent->client ); TeamplayInfoMessage( ent ); }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect( int clientNum ) { gclient_t *client; gentity_t *ent; gentity_t *tent; int i; ent = g_entities + clientNum; if( !ent->client || ent->client->pers.connected == CON_DISCONNECTED ) return; G_LeaveTeam( ent ); G_namelog_disconnect( ent->client ); G_Vote( ent, TEAM_NONE, qfalse ); // stop any following clients for( i = 0; i < level.maxclients; i++ ) { client = &level.clients[ i ]; // remove any /ignore settings for this clientNum Com_ClientListRemove( &client->sess.ignoreList, clientNum ); // clear impregnatedBy for everyone impregnated by this player if( client->isImpregnated && client->impregnatedBy == clientNum ) client->impregnatedBy = -2; } // send effect if they were completely connected if( ent->client->pers.connected == CON_CONNECTED && ent->client->sess.spectatorState == SPECTATOR_NOT ) { tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT ); tent->s.clientNum = ent->s.clientNum; } G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s^7\"\n", clientNum, ent->client->pers.ip.str, ent->client->pers.guid, ent->client->pers.netname ); trap_UnlinkEntity( ent ); ent->s.modelindex = 0; ent->inuse = qfalse; ent->classname = "disconnected"; ent->client->pers.connected = CON_DISCONNECTED; ent->client->sess.spectatorState = ent->client->ps.persistant[ PERS_SPECSTATE ] = SPECTATOR_NOT; trap_SetConfigstring( CS_PLAYERS + clientNum, ""); CalculateRanks( ); }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect( int clientNum ) { gentity_t *ent; gentity_t *tent; int i; ent = g_entities + clientNum; if ( !ent->client || ent->client->pers.connected == CON_DISCONNECTED ) { return; } G_LeaveTeam( ent ); G_namelog_disconnect( ent->client ); G_Vote( ent, TEAM_NONE, false ); // stop any following clients for ( i = 0; i < level.maxclients; i++ ) { // remove any /ignore settings for this clientNum Com_ClientListRemove( &level.clients[ i ].sess.ignoreList, clientNum ); } // send effect if they were completely connected if ( ent->client->pers.connected == CON_CONNECTED && ent->client->sess.spectatorState == SPECTATOR_NOT ) { tent = G_NewTempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT ); tent->s.clientNum = ent->s.clientNum; } G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s^7\"", clientNum, ent->client->pers.ip.str, ent->client->pers.guid, ent->client->pers.netname ); ent->client->pers.connected = CON_DISCONNECTED; ent->client->sess.spectatorState = SPECTATOR_NOT; ent->client->ps.persistant[ PERS_SPECSTATE ] = SPECTATOR_NOT; G_FreeEntity(ent); ent->classname = "disconnected"; ent->client = level.clients + clientNum; trap_SetConfigstring( CS_PLAYERS + clientNum, "" ); CalculateRanks(); Beacon::PropagateAll(); }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect( int clientNum ) { gentity_t *ent; gentity_t *tent; int i; ent = g_entities + clientNum; if( !ent->client ) return; G_admin_namelog_update( ent->client, qtrue ); G_LeaveTeam( ent ); G_Vote( ent, qfalse ); // stop any following clients for( i = 0; i < level.maxclients; i++ ) { // remove any /ignore settings for this clientNum BG_ClientListRemove( &level.clients[ i ].sess.ignoreList, clientNum ); } // send effect if they were completely connected if( ent->client->pers.connected == CON_CONNECTED && ent->client->sess.spectatorState == SPECTATOR_NOT ) { tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT ); tent->s.clientNum = ent->s.clientNum; } if( ent->client->pers.connection ) ent->client->pers.connection->clientNum = -1; G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s\"\n", clientNum, ent->client->pers.ip, ent->client->pers.guid, ent->client->pers.netname ); trap_UnlinkEntity( ent ); ent->s.modelindex = 0; ent->inuse = qfalse; ent->classname = "disconnected"; ent->client->pers.connected = CON_DISCONNECTED; ent->client->sess.spectatorState = ent->client->ps.persistant[ PERS_SPECSTATE ] = SPECTATOR_NOT; trap_SetConfigstring( CS_PLAYERS + clientNum, ""); CalculateRanks( ); }