g_round.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "g_local.h"
00026 
00030 void G_CheckForceEndRound (void)
00031 {
00032     player_t *p;
00033     int i, diff;
00034 
00035     /* check for roundlimits in multiplayer only */
00036     if (!sv_roundtimelimit->integer || sv_maxclients->integer == 1)
00037         return;
00038 
00039     if (level.time != ceil(level.time))
00040         return;
00041 
00042     diff = level.roundstartTime + sv_roundtimelimit->integer - level.time;
00043     switch (diff) {
00044     case 240:
00045         gi.BroadcastPrintf(PRINT_HUD, _("4 minutes left until forced round end\n"));
00046         return;
00047     case 180:
00048         gi.BroadcastPrintf(PRINT_HUD, _("3 minutes left until forced round end\n"));
00049         return;
00050     case 120:
00051         gi.BroadcastPrintf(PRINT_HUD, _("2 minutes left until forced round end\n"));
00052         return;
00053     case 60:
00054         gi.BroadcastPrintf(PRINT_HUD, _("1 minute left until forced round end\n"));
00055         return;
00056     case 30:
00057         gi.BroadcastPrintf(PRINT_HUD, _("30 seconds left until forced round end\n"));
00058         return;
00059     case 15:
00060         gi.BroadcastPrintf(PRINT_HUD, _("15 seconds left until forced round end\n"));
00061         return;
00062     }
00063 
00064     /* active team still has time left */
00065     if (level.time < level.roundstartTime + sv_roundtimelimit->integer)
00066         return;
00067 
00068     gi.BroadcastPrintf(PRINT_HUD, _("Current active team hit the max round time\n"));
00069 
00070     /* set all team members to ready (only human players) */
00071     for (i = 0, p = game.players; i < game.sv_maxplayersperteam; i++, p++)
00072         if (p->inuse && p->pers.team == level.activeTeam) {
00073             G_ClientEndRound(p);
00074             level.nextEndRound = level.framenum;
00075         }
00076 
00077     level.roundstartTime = level.time;
00078 }
00079 
00083 static int G_PlayerSoldiersCount (const player_t* player)
00084 {
00085     int cnt = 0;
00086     edict_t *ent = NULL;
00087 
00088     while ((ent = G_EdictsGetNextLivingActor(ent))) {
00089         if (ent->pnum == player->num)
00090             cnt++;
00091     }
00092 
00093     return cnt;
00094 }
00095 
00104 static void G_UpdateStunState (int team)
00105 {
00106     edict_t *ent = NULL;
00107     const int regen = 1;
00108 
00109     while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team))) {
00110         if (ent->STUN > 0) {
00111             if (regen > ent->STUN)
00112                 ent->STUN = 0;
00113             else
00114                 ent->STUN -= regen;
00115 
00116             G_ActorCheckRevitalise(ent);
00117         }
00118     }
00119 }
00120 
00124 static void G_GetNextActiveTeam (void)
00125 {
00126     int i;
00127     const int lastTeam = G_GetActiveTeam();
00128 
00129     level.activeTeam = TEAM_NO_ACTIVE;
00130 
00131     /* search next team */
00132     for (i = 1; i < MAX_TEAMS; i++) {
00133         const int team = (lastTeam + i) % MAX_TEAMS;
00134         if (level.num_alive[team]) {
00135             /* found next player */
00136             level.activeTeam = team;
00137             break;
00138         }
00139     }
00140 }
00141 
00145 void G_ClientEndRound (player_t * player)
00146 {
00147     player_t *p;
00148     int i;
00149 
00150     if (!G_IsAIPlayer(player)) {
00151         /* inactive players can't end their inactive round :) */
00152         if (level.activeTeam != player->pers.team)
00153             return;
00154 
00155         /* check for "team oszillation" */
00156         if (level.framenum < level.nextEndRound)
00157             return;
00158 
00159         level.nextEndRound = level.framenum + 20;
00160     }
00161 
00162     /* only use this for teamplay matches like coopX or 2on2 and above
00163      * also skip this for ai players, this is only called when all ai actors
00164      * have finished their 'thinking' */
00165     if (!G_IsAIPlayer(player) && sv_teamplay->integer) {
00166         /* check if all team members are ready */
00167         if (!player->roundDone) {
00168             player->roundDone = qtrue;
00169             gi.AddEvent(PM_ALL, EV_ENDROUNDANNOUNCE | EVENT_INSTANTLY);
00170             gi.WriteByte(player->num);
00171             gi.WriteByte(player->pers.team);
00172             gi.EndEvents();
00173         }
00174         for (i = 0, p = game.players; i < game.sv_maxplayersperteam * 2; i++, p++)
00175             if (p->inuse && p->pers.team == level.activeTeam && !p->roundDone && G_PlayerSoldiersCount(p) > 0)
00176                 return;
00177     } else {
00178         player->roundDone = qtrue;
00179     }
00180 
00181     /* clear any remaining reaction fire */
00182     G_ReactionFireEndTurn();
00183 
00184     /* let all the invisible players perish now */
00185     G_CheckVisTeamAll(level.activeTeam, qtrue, NULL);
00186 
00187     G_GetNextActiveTeam();
00188 
00189     /* no other team left? */
00190     if (!G_MatchIsRunning())
00191         return;
00192 
00193     level.actualRound++;
00194 
00195     /* communicate next player in row to clients */
00196     G_EventEndRound();
00197 
00198     /* store the round start time to be able to abort the round after a give time */
00199     level.roundstartTime = level.time;
00200 
00201     /* Update the state of stuned team-members. The actual statistics are sent below! */
00202     G_UpdateStunState(level.activeTeam);
00203 
00204     /* Give the actors of the now active team their TUs. */
00205     G_GiveTimeUnits(level.activeTeam);
00206 
00207     /* apply morale behaviour, reset reaction fire */
00208     G_ReactionFireReset(level.activeTeam);
00209     if (mor_panic->integer)
00210         G_MoraleBehaviour(level.activeTeam);
00211 
00212     /* start ai - there is only one player for ai teams, and the last pointer must only
00213      * be updated for ai players */
00214     p = G_GetPlayerForTeam(level.activeTeam);
00215     if (p == NULL)
00216         gi.Error("Could not find player for team %i", level.activeTeam);
00217 
00218     /* finish off events */
00219     gi.EndEvents();
00220 
00221     /* reset ready flag for every player on the current team (even ai players) */
00222     for (i = 0, p = game.players; i < game.sv_maxplayersperteam * 2; i++, p++)
00223         if (p->inuse && p->pers.team == level.activeTeam)
00224             p->roundDone = qfalse;
00225 }

Generated by  doxygen 1.6.2