/** * @brief Gets player for given team. * @param[in] team The team the player data should be searched for * @return The inuse player for the given team or @c NULL when no player found. * @todo What if there are multiple players for a team (multiplayer coop match) */ player_t* G_GetPlayerForTeam (int team) { player_t *p; /* search corresponding player (even ai players) */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) if (p->pers.team == team) /* found player */ return p; p = NULL; while ((p = G_PlayerGetNextActiveAI(p))) if (p->pers.team == team) /* found player */ return p; return NULL; }
/** * @brief Sets the teamnum var for this match * @param[in] player Pointer to connected player * @todo Check whether there are enough free spawnpoints in all cases */ static void G_GetTeam (player_t * player) { player_t *p; int playersInGame = 0; /* player has already a team */ if (player->pers.team > 0) { Com_DPrintf(DEBUG_GAME, "Player %s is already on team %i\n", player->pers.netname, player->pers.team); return; } /* number of currently connected players (no ai players) */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) playersInGame++; /* randomly assign a teamnumber in deathmatch games */ if (playersInGame <= 1 && sv_maxclients->integer > 1 && !sv_teamplay->integer) { int spawnCheck[MAX_TEAMS]; int spawnSpots = 0; int randomSpot; int i; /* skip civilian teams */ for (i = TEAM_PHALANX; i < MAX_TEAMS; i++) { spawnCheck[i] = 0; /* check whether there are spawnpoints for this team */ if (level.num_spawnpoints[i]) spawnCheck[spawnSpots++] = i; } /* we need at least 2 different team spawnpoints for multiplayer in a death match game */ if (spawnSpots < 2) gi.Error("G_GetTeam: Not enough spawn spots in map!"); /* assign random valid team number */ i = spawnSpots; randomSpot = rand() % spawnSpots; for (;;) { const int team = spawnCheck[randomSpot]; if (i == 0) gi.Error("G_GetTeam: Could not assign a team!"); if (G_SetTeamForPlayer(player, team)) { gi.DPrintf("%s has been randomly assigned to team %i\n", player->pers.netname, G_ClientGetTeamNum(player)); break; } i--; randomSpot = (randomSpot + 1) % spawnSpots; } return; } /* find a team */ if (sv_maxclients->integer == 1) G_SetTeamForPlayer(player, TEAM_PHALANX); else if (sv_teamplay->integer) { /* set the team specified in the userinfo */ const int i = G_ClientGetTeamNumPref(player); gi.DPrintf("Get a team for teamplay for %s\n", player->pers.netname); /* civilians are at team zero */ if (i > TEAM_CIVILIAN && sv_maxteams->integer >= i) { G_SetTeamForPlayer(player, i); gi.BroadcastPrintf(PRINT_CONSOLE, "serverconsole: %s has chosen team %i\n", player->pers.netname, i); } else { gi.DPrintf("Team %i is not valid - choose a team between 1 and %i\n", i, sv_maxteams->integer); G_SetTeamForPlayer(player, TEAM_DEFAULT); } } else { int i; /* search team */ gi.DPrintf("Getting a multiplayer team for %s\n", player->pers.netname); for (i = TEAM_CIVILIAN + 1; i < MAX_TEAMS; i++) { if (level.num_spawnpoints[i]) { bool teamAvailable = true; p = NULL; /* check if team is in use (only human controlled players) */ while ((p = G_PlayerGetNextActiveAI(p))) { if (p->pers.team == i) { Com_DPrintf(DEBUG_GAME, "Team %i is already in use\n", i); /* team already in use */ teamAvailable = false; break; } } if (teamAvailable) break; } } /* set the team */ if (i < MAX_TEAMS) { /* remove ai player */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) { if (p->pers.team == i) { gi.BroadcastPrintf(PRINT_CONSOLE, "Removing ai player..."); p->inuse = false; break; } } Com_DPrintf(DEBUG_GAME, "Assigning %s to team %i\n", player->pers.netname, i); G_SetTeamForPlayer(player, i); } else { gi.DPrintf("No free team - disconnecting '%s'\n", player->pers.netname); G_ClientDisconnect(player); } } }
/** * @sa G_PlayerSoldiersCount */ void G_ClientEndRound (Player& player) { Player* p; const int lastTeamIndex = (G_GetActiveTeam() + level.teamOfs) % MAX_TEAMS; if (!G_IsAIPlayer(&player)) { /* inactive players can't end their inactive turn :) */ if (level.activeTeam != player.getTeam()) return; /* check for "team oszillation" */ if (level.framenum < level.nextEndRound) return; level.nextEndRound = level.framenum + 20; } /* only use this for teamplay matches like coopX or fight2on2 and above * also skip this for ai players, this is only called when all ai actors * have finished their 'thinking' */ if (!G_IsAIPlayer(&player) && sv_teamplay->integer) { /* check if all team members are ready */ if (!player.roundDone) { player.roundDone = true; G_EventEndRoundAnnounce(player); G_EventEnd(); } p = nullptr; while ((p = G_PlayerGetNextActiveHuman(p))) if (p->getTeam() == level.activeTeam && !p->roundDone && G_PlayerSoldiersCount(*p) > 0) return; p = nullptr; while ((p = G_PlayerGetNextActiveAI(p))) if (p->getTeam() == level.activeTeam && !p->roundDone && G_PlayerSoldiersCount(*p) > 0) return; } else { player.roundDone = true; } /* clear any remaining reaction fire */ G_ReactionFireOnEndTurn(); if (!G_IsAIPlayer(&player)) { if (g_lastseen->integer > 0) { Edict* ent = nullptr; while ((ent = G_EdictsGetNextActor(ent))) { if (G_IsAI(ent) && G_IsVisibleForTeam(ent, level.activeTeam)) { player.lastSeen = level.actualRound; break; } } if (level.actualRound - player.lastSeen > g_lastseen->integer) { Com_Printf("round end triggered by g_lastseen (player %i (team %i) last seen in round %i of %i rounds)\n", player.getNum(), level.activeTeam, player.lastSeen, level.actualRound); G_MatchEndTrigger(-1, 0); } } } /* let all the invisible players perish now */ G_CheckVisTeamAll(level.activeTeam, VIS_APPEAR, nullptr); G_GetNextActiveTeam(); AI_CheckRespawn(TEAM_ALIEN); /* no other team left? */ if (!G_MatchIsRunning()) return; if (lastTeamIndex > (level.activeTeam + level.teamOfs) % MAX_TEAMS) level.actualRound++; /* communicate next player in row to clients */ G_EventEndRound(); /* store the round start time to be able to abort the round after a give time */ level.roundstartTime = level.time; /* Wounded team members bleed */ G_BleedWounds(level.activeTeam); /* Update the state of stuned team-members. The actual statistics are sent below! */ G_UpdateStunState(level.activeTeam); /* Give the actors of the now active team their TUs. */ G_GiveTimeUnits(level.activeTeam); /* apply morale behaviour, reset reaction fire */ G_ReactionFireReset(level.activeTeam); if (mor_panic->integer) G_MoraleBehaviour(level.activeTeam); G_UpdateCarriedWeight(level.activeTeam); /* start ai - there is only one player for ai teams, and the last pointer must only * be updated for ai players */ p = G_GetPlayerForTeam(level.activeTeam); if (p == nullptr) gi.Error("Could not find player for team %i", level.activeTeam); /* finish off events */ G_EventEnd(); /* reset ready flag for every player on the current team (even ai players) */ p = nullptr; while ((p = G_PlayerGetNextActiveHuman(p))) { if (p->getTeam() == level.activeTeam) { p->roundDone = false; } } p = nullptr; while ((p = G_PlayerGetNextActiveAI(p))) { if (p->getTeam() == level.activeTeam) { p->roundDone = false; } } }