/* * G_Match_NotReady */ void G_Match_NotReady( edict_t *ent ) { if( ent->s.team == TEAM_SPECTATOR ) { G_PrintMsg( ent, "Join the game first\n" ); return; } if( GS_MatchState() != MATCH_STATE_WARMUP && GS_MatchState() != MATCH_STATE_COUNTDOWN ) { G_PrintMsg( ent, "A match is not being setup.\n" ); return; } if( !level.ready[PLAYERNUM( ent )] ) { G_PrintMsg( ent, "You weren't ready.\n" ); return; } level.ready[PLAYERNUM( ent )] = false; G_PrintMsg( NULL, "%s%s is no longer ready.\n", ent->r.client->netname, S_COLOR_WHITE ); G_UpdatePlayerMatchMsg( ent ); G_Match_CheckReadys(); }
/* * 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 ); }
/* * G_Match_Ready */ void G_Match_Ready( edict_t *ent ) { if( ent->r.svflags & SVF_FAKECLIENT && level.ready[PLAYERNUM( ent )] == true ) return; if( ent->s.team == TEAM_SPECTATOR ) { G_PrintMsg( ent, "Join the game first\n" ); return; } if( GS_MatchState() != MATCH_STATE_WARMUP ) { if( !( ent->r.svflags & SVF_FAKECLIENT ) ) G_PrintMsg( ent, "We're not in warmup.\n" ); return; } if( level.ready[PLAYERNUM( ent )] ) { G_PrintMsg( ent, "You are already ready.\n" ); return; } level.ready[PLAYERNUM( ent )] = true; G_PrintMsg( NULL, "%s%s is ready!\n", ent->r.client->netname, S_COLOR_WHITE ); G_UpdatePlayerMatchMsg( ent ); G_Match_CheckReadys(); }
/* * 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(); }