/* * G_Teams_SetTeam - sets clients team without any checking */ void G_Teams_SetTeam( edict_t *ent, int team ) { assert( ent && ent->r.inuse && ent->r.client ); assert( team >= TEAM_SPECTATOR && team < GS_MAX_TEAMS ); // if player was on a team, send partial report to matchmaker if( ent->r.client->team != TEAM_SPECTATOR && ent->r.client->team != team && GS_MatchState() == MATCH_STATE_PLAYTIME ) { G_Printf("Sending teamchange to MM, team %d to team %d\n", ent->r.client->team, team ); G_AddPlayerReport( ent, false ); // trap_MR_SendPartialReport(); } // clear scores at changing team memset( &ent->r.client->level.stats, 0, sizeof( ent->r.client->level.stats ) ); memset( &ent->r.client->teamstate, 0, sizeof( ent->r.client->teamstate ) ); ent->r.client->team = team; ent->r.client->teamstate.timeStamp = level.time; G_Teams_UnInvitePlayer( team, ent ); G_ClientRespawn( ent, true ); // make ghost using G_ClientRespawn so team is updated at ghosting G_SpawnQueue_AddClient( ent ); level.ready[PLAYERNUM( ent )] = false; G_Match_CheckReadys(); G_UpdatePlayerMatchMsg( ent ); }
/* * ClientDisconnect * Called when a player drops from the server. * Will not be called between levels. */ void ClientDisconnect( edict_t *ent, const char *reason ) { int team; if( !ent->r.client || !ent->r.inuse ) return; // always report in RACE mode if( GS_RaceGametype() || ( ent->r.client->team != TEAM_SPECTATOR && ( GS_MatchState() == MATCH_STATE_PLAYTIME || GS_MatchState() == MATCH_STATE_POSTMATCH ) ) ) G_AddPlayerReport( ent, GS_MatchState() == MATCH_STATE_POSTMATCH ); for( team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ ) G_Teams_UnInvitePlayer( team, ent ); if( !level.gametype.disableObituaries || !(ent->r.svflags & SVF_FAKECLIENT ) ) { if( !reason ) G_PrintMsg( NULL, "%s" S_COLOR_WHITE " disconnected\n", ent->r.client->netname ); else G_PrintMsg( NULL, "%s" S_COLOR_WHITE " disconnected (%s" S_COLOR_WHITE ")\n", ent->r.client->netname, reason ); } // send effect if( ent->s.team > TEAM_SPECTATOR ) G_TeleportEffect( ent, false ); ent->r.client->team = TEAM_SPECTATOR; G_ClientRespawn( ent, true ); // respawn as ghost ent->movetype = MOVETYPE_NOCLIP; // allow freefly // let the gametype scripts know this client just disconnected G_Gametype_ScoreEvent( ent->r.client, "disconnect", NULL ); G_FreeAI( ent ); AI_EnemyRemoved( ent ); ent->r.inuse = false; ent->r.svflags = SVF_NOCLIENT; memset( ent->r.client, 0, sizeof( *ent->r.client ) ); ent->r.client->ps.playerNum = PLAYERNUM( ent ); trap_ConfigString( CS_PLAYERINFOS+PLAYERNUM( ent ), "" ); GClip_UnlinkEntity( ent ); G_Match_CheckReadys(); }