/** * @brief Purges all the AI from the entities. */ void AIL_Cleanup (void) { Edict *ent = nullptr; while ((ent = G_EdictsGetNextActor(ent))) AIL_CleanupActor(ent); }
/** * @brief Purges all the AI from the entities. */ void AIL_Cleanup (void) { edict_t *ent = NULL; while ((ent = G_EdictsGetNextActor(ent))) AIL_CleanupActor(ent); }
/** * @brief Write player stats to network buffer * @sa G_SendStats */ void G_SendPlayerStats (const Player& player) { Edict* ent = nullptr; while ((ent = G_EdictsGetNextActor(ent))) if (ent->team == player.getTeam()) { G_EventActorStats(*ent, G_PlayerToPM(player)); G_SendWoundStats(ent); } }
/** * @brief Searches an actor by a unique character number * @param[in] ucn The unique character number * @param[in] team The team to get the actor with the ucn from * @return The actor edict if found, otherwise @c nullptr */ Edict* G_EdictsGetActorByUCN (const int ucn, const int team) { Edict* ent = nullptr; while ((ent = G_EdictsGetNextActor(ent))) if (team == ent->team && ent->chr.ucn == ucn) return ent; return nullptr; }
/** * @brief Searches an actor by a unique character number * @param[in] ucn The unique character number * @param[in] team The team to get the actor with the ucn from * @return The actor edict if found, otherwise @c nullptr */ Actor* G_EdictsGetActorByUCN (const int ucn, const int team) { Actor* actor = nullptr; while ((actor = G_EdictsGetNextActor(actor))) if (team == actor->getTeam() && actor->chr.ucn == ucn) return actor; return nullptr; }
/** * @brief This function sends all the actors to the client that are not visible * initially - this is needed because an actor can e.g. produce sounds that are * send over the net. And the client can only handle them if he knows the * @c le_t (local entity) already * @note Call this for the first @c G_CheckVis call for every new * actor or player * @sa G_CheckVis * @sa CL_ActorAdd */ void G_SendInvisible (const player_t* player) { const int team = player->pers.team; assert(team != TEAM_NO_ACTIVE); if (level.num_alive[team]) { edict_t* ent = NULL; /* check visibility */ while ((ent = G_EdictsGetNextActor(ent))) { if (ent->team != team) { /* not visible for this team - so add the le only */ if (!G_IsVisibleForTeam(ent, team)) { G_EventActorAdd(G_PlayerToPM(player), ent); } } } } }
/** * @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; } } }
/** * @brief Handles the end of a match * @param[in] team The winning team number * @param[in] nextmap Is there a follow-up map within the same match ? * @sa G_RunFrame * @sa CL_ParseResults */ static void G_MatchSendResults (int team, bool nextmap) { edict_t *ent, *attacker; int i, j = 0; attacker = NULL; ent = NULL; /* Calculate new scores/skills for the soldiers. */ while ((ent = G_EdictsGetNextLivingActor(ent))) { if (!G_IsAI(ent)) G_UpdateCharacterExperience(ent); else if (ent->team == team) attacker = ent; } /* if aliens won, make sure every soldier that is not in the rescue zone dies */ if (team == TEAM_ALIEN) { ent = NULL; while ((ent = G_EdictsGetNextLivingActor(ent))) if (ent->team != team && !G_ActorIsInRescueZone(ent)) { ent->HP = 0; G_ActorDieOrStun(ent, attacker); } } G_VisMakeEverythingVisible(); /* send results */ G_EventAdd(PM_ALL, EV_RESULTS, -1); gi.WriteByte(MAX_TEAMS); gi.WriteByte(team); gi.WriteByte(nextmap); for (i = 0; i < MAX_TEAMS; i++) { gi.WriteByte(level.num_spawned[i]); gi.WriteByte(level.num_alive[i]); } for (i = 0; i <= MAX_TEAMS; i++) for (j = 0; j < MAX_TEAMS; j++) gi.WriteByte(level.num_kills[i][j]); for (i = 0; i <= MAX_TEAMS; i++) for (j = 0; j < MAX_TEAMS; j++) gi.WriteByte(level.num_stuns[i][j]); /* how many actors */ j = 0; ent = NULL; while ((ent = G_EdictsGetNextActor(ent))) if (!G_IsAI(ent)) j++; /* number of soldiers */ gi.WriteByte(j); if (j) { ent = NULL; while ((ent = G_EdictsGetNextActor(ent))) { if (!G_IsAI(ent)) { G_SendCharacterData(ent); } } } G_EventEnd(); }
/** * @brief Handles the end of a match * @param[in] team The winning team number * @param[in] nextmap Is there a follow-up map within the same match ? * @sa G_RunFrame * @sa CL_ParseResults */ static void G_MatchSendResults (int team, bool nextmap) { Edict* attacker = nullptr; Actor* actor = nullptr; /* Calculate new scores/skills for the soldiers. */ while ((actor = G_EdictsGetNextLivingActor(actor))) { if (!G_IsAI(actor)) G_UpdateCharacterExperience(actor); else if (actor->getTeam() == team) attacker = actor; } /* if aliens won, make sure every soldier that is not in the rescue zone dies */ if (team == TEAM_ALIEN) { actor = nullptr; while ((actor = G_EdictsGetNextLivingActor(actor))) if (actor->getTeam() != team && !actor->isInRescueZone()) { actor->HP = 0; G_ActorDieOrStun(actor, attacker); } } G_VisMakeEverythingVisible(); /* send results */ G_EventAdd(PM_ALL, EV_RESULTS, -1); gi.WriteByte(MAX_TEAMS); gi.WriteByte(team); gi.WriteByte(nextmap); for (int i = 0; i < MAX_TEAMS; i++) { gi.WriteByte(level.num_spawned[i]); gi.WriteByte(level.num_alive[i]); } for (int i = 0; i <= MAX_TEAMS; i++) for (int j = 0; j < MAX_TEAMS; j++) gi.WriteByte(level.num_kills[i][j]); for (int i = 0; i <= MAX_TEAMS; i++) for (int j = 0; j < MAX_TEAMS; j++) gi.WriteByte(level.num_stuns[i][j]); /* how many actors */ int n = 0; actor = nullptr; while ((actor = G_EdictsGetNextActor(actor))) if (!G_IsAI(actor)) n++; /* number of soldiers */ gi.WriteByte(n); if (n) { actor = nullptr; while ((actor = G_EdictsGetNextActor(actor))) { if (!G_IsAI(actor)) { G_SendCharacterData(actor); } } } G_EventEnd(); }