UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
g_round.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2020 UFO: Alien Invasion.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "g_local.h"
26 #include "g_actor.h"
27 #include "g_ai.h"
28 #include "g_client.h"
29 #include "g_edicts.h"
30 #include "g_health.h"
31 #include "g_match.h"
32 #include "g_reaction.h"
33 #include "g_utils.h"
34 #include "g_vis.h"
35 
40 {
41  /* check for roundlimits in multiplayer only */
43  return;
44 
45  if (!G_MatchIsRunning())
46  return;
47 
48  if (level.time != ceil(level.time))
49  return;
50 
52  switch (diff) {
53  case 240:
54  gi.BroadcastPrintf(PRINT_HUD, _("4 minutes left until forced turn end."));
55  return;
56  case 180:
57  gi.BroadcastPrintf(PRINT_HUD, _("3 minutes left until forced turn end."));
58  return;
59  case 120:
60  gi.BroadcastPrintf(PRINT_HUD, _("2 minutes left until forced turn end."));
61  return;
62  case 60:
63  gi.BroadcastPrintf(PRINT_HUD, _("1 minute left until forced turn end."));
64  return;
65  case 30:
66  gi.BroadcastPrintf(PRINT_HUD, _("30 seconds left until forced turn end."));
67  return;
68  case 15:
69  gi.BroadcastPrintf(PRINT_HUD, _("15 seconds left until forced turn end."));
70  return;
71  }
72 
73  /* active team still has time left */
75  return;
76 
77  gi.BroadcastPrintf(PRINT_HUD, _("Current active team hit the max round time."));
78 
79  /* store this in a local variable, as the global variable is changed in G_ClientEndRound */
80  const int activeTeam = level.activeTeam;
81  /* set all team members to ready (only human players) */
82  Player* p = nullptr;
83  while ((p = G_PlayerGetNextActiveHuman(p))) {
84  if (p->getTeam() == activeTeam) {
85  G_ClientEndRound(*p);
87  }
88  }
89 
91 }
92 
96 static int G_PlayerSoldiersCount (const Player& player)
97 {
98  int cnt = 0;
99  Actor* actor = nullptr;
100 
101  while ((actor = G_EdictsGetNextLivingActor(actor))) {
102  if (actor->getPlayerNum() == player.getNum())
103  cnt++;
104  }
105 
106  return cnt;
107 }
108 
117 static void G_UpdateStunState (int team)
118 {
119  const int regen = 1;
120 
121  Actor* actor = nullptr;
122  while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
123  const int stun = actor->getStun();
124  if (stun > 0) {
125  if (regen > stun)
126  actor->setStun(0);
127  else
128  actor->addStun(-regen);
129 
130  G_ActorCheckRevitalise(actor);
131  }
132  }
133 }
134 
139 static void G_UpdateCarriedWeight (int team)
140 {
141  Actor* actor = nullptr;
142 
143  while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
144  if (actor->chr.scoreMission) {
145  actor->chr.scoreMission->carriedWeight += actor->chr.inv.getWeight();
146  }
147  }
148 }
149 
150 static void G_RoundTouchTriggers (int team)
151 {
152  Actor* actor = nullptr;
153 
154  while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
155  G_TouchTriggers(actor);
156  }
157 }
158 
162 static void G_GetNextActiveTeam (void)
163 {
164  const int lastTeam = G_GetActiveTeam();
165 
166  Com_DPrintf(DEBUG_GAME, "round end from team %i\n", lastTeam);
168 
169  /* search next team */
170  for (int i = 1; i < MAX_TEAMS; i++) {
171  const int team = (lastTeam + i) % MAX_TEAMS;
172  if (level.num_alive[team]) {
173  /* found next player */
174  level.activeTeam = team;
175  Com_DPrintf(DEBUG_GAME, "round start for team %i\n", team);
176  break;
177  }
178  }
179 }
180 
184 void G_ClientEndRound (Player& player)
185 {
186  const int lastTeamIndex = (G_GetActiveTeam() + level.teamOfs) % MAX_TEAMS;
187 
188  if (!G_IsAIPlayer(&player)) {
189  /* inactive players can't end their inactive turn :) */
190  if (level.activeTeam != player.getTeam())
191  return;
192 
193  /* check for "team oszillation" */
195  return;
196 
198  }
199 
200  /* only use this for teamplay matches like coopX or fight2on2 and above
201  * also skip this for ai players, this is only called when all ai actors
202  * have finished their 'thinking' */
203  if (!G_IsAIPlayer(&player) && sv_teamplay->integer) {
204  /* check if all team members are ready */
205  if (!player.roundDone) {
206  player.roundDone = true;
207  G_EventEndRoundAnnounce(player);
208  G_EventEnd();
209  }
210  Player* p = nullptr;
211  while ((p = G_PlayerGetNextActiveHuman(p)))
212  if (p->getTeam() == level.activeTeam && !p->roundDone && G_PlayerSoldiersCount(*p) > 0)
213  return;
214  p = nullptr;
215  while ((p = G_PlayerGetNextActiveAI(p)))
216  if (p->getTeam() == level.activeTeam && !p->roundDone && G_PlayerSoldiersCount(*p) > 0)
217  return;
218  } else {
219  player.roundDone = true;
220  }
221 
222  /* clear any remaining reaction fire */
224 
225  if (!G_IsAIPlayer(&player)) {
226  if (g_lastseen->integer > 0) {
227  Actor* actor = nullptr;
228  while ((actor = G_EdictsGetNextActor(actor))) {
229  if (G_IsAI(actor) && G_IsVisibleForTeam(actor, level.activeTeam)) {
230  player.lastSeen = level.actualRound;
231  break;
232  }
233  }
234  if (level.actualRound - player.lastSeen > g_lastseen->integer) {
235  Com_Printf("round end triggered by g_lastseen (player %i (team %i) last seen in round %i of %i rounds)\n",
236  player.getNum(), level.activeTeam, player.lastSeen, level.actualRound);
237  G_MatchEndTrigger(-1, 0);
238  }
239  }
240  }
241 
242  /* Wounded team members bleed now */
244 
245  /* let all the invisible players perish now */
247 
249 
251 
252  /* no other team left? */
253  if (!G_MatchIsRunning())
254  return;
255 
256  if (lastTeamIndex > (level.activeTeam + level.teamOfs) % MAX_TEAMS)
257  level.actualRound++;
258 
259  /* communicate next player in row to clients */
260  G_EventEndRound();
261 
262  /* store the round start time to be able to abort the round after a give time */
264 
266 
267  /* Update the state of stuned team-members. The actual statistics are sent below! */
269 
270  /* Give the actors of the now active team their TUs. */
272 
274 
275  /* apply morale behaviour, reset reaction fire */
277  if (mor_panic->integer)
279 
280  /* start ai - there is only one player for ai teams, and the last pointer must only
281  * be updated for ai players */
282  Player* p = G_GetPlayerForTeam(level.activeTeam);
283  if (p == nullptr)
284  gi.Error("Could not find player for team %i", level.activeTeam);
285 
286  /* finish off events */
287  G_EventEnd();
288 
289  /* reset ready flag for every player on the current team (even ai players) */
290  p = nullptr;
291  while ((p = G_PlayerGetNextActiveHuman(p))) {
292  if (p->getTeam() == level.activeTeam) {
293  p->roundDone = false;
294  }
295  }
296 
297  p = nullptr;
298  while ((p = G_PlayerGetNextActiveAI(p))) {
299  if (p->getTeam() == level.activeTeam) {
300  p->roundDone = false;
301  }
302  }
303 }
void G_EventEnd(void)
Definition: g_events.cpp:711
int G_TouchTriggers(Edict *ent, const entity_type_t type)
Check the world against triggers for the current entity.
Definition: g_utils.cpp:547
Reaction fire system.
cvar_t * g_lastseen
Definition: g_main.cpp:120
Player * G_PlayerGetNextActiveHuman(Player *lastPlayer)
Iterate through the list of players.
Definition: g_client.cpp:110
void G_MatchEndTrigger(int team, int timeGap)
Triggers the end of the game. Will be executed in the next server (or game) frame.
Definition: g_match.cpp:125
Actor * G_EdictsGetNextLivingActor(Actor *lastEnt)
Iterate through the living actor entities.
Definition: g_edicts.cpp:196
void G_ClientEndRound(Player &player)
Definition: g_round.cpp:184
#define MAX_TEAMS
Definition: defines.h:98
int getStun() const
Definition: g_edict.h:308
#define TEAM_ALIEN
Definition: q_shared.h:63
Artificial Intelligence functions.
#define VIS_APPEAR
Definition: g_vis.h:36
#define _(String)
Definition: cl_shared.h:43
Misc utility functions for game module.
int activeTeam
Definition: g_local.h:101
static void G_GetNextActiveTeam(void)
Get the next active team.
Definition: g_round.cpp:162
character_t chr
Definition: g_edict.h:116
void G_CheckForceEndRound(void)
Check whether a forced turn end should be executed.
Definition: g_round.cpp:39
void G_EventEndRound(void)
End of turn event for the current active team.
Definition: g_events.cpp:414
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
int nextEndRound
Definition: g_local.h:103
int integer
Definition: cvar.h:81
chrScoreMission_t * scoreMission
Definition: chr_shared.h:388
void G_MoraleBehaviour(int team)
Applies morale behaviour on actors.
Definition: g_morale.cpp:156
int actualRound
Definition: g_local.h:104
static int G_PlayerSoldiersCount(const Player &player)
Counts the still living actors for a player.
Definition: g_round.cpp:96
bool G_MatchIsRunning(void)
Checks whether the game is running (active team and no intermission time)
Definition: g_match.cpp:320
Match related functions.
int framenum
Definition: g_local.h:81
Player * G_PlayerGetNextActiveAI(Player *lastPlayer)
Iterate through the list of players.
Definition: g_client.cpp:126
void G_EventEndRoundAnnounce(const Player &player)
Definition: g_events.cpp:654
Player * G_GetPlayerForTeam(int team)
Gets player for given team.
Definition: g_utils.cpp:188
game_import_t gi
Definition: g_main.cpp:39
void G_ReactionFireOnEndTurn(void)
Called at the end of turn, all outstanding reaction fire is resolved.
int getWeight() const
Get the weight of the items in the given inventory (excluding those in temp containers).
Definition: inv_shared.cpp:937
cvar_t * mor_panic
Definition: g_main.cpp:103
An Edict of type Actor.
Definition: g_edict.h:348
byte num_alive[MAX_TEAMS]
Definition: g_local.h:115
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
void G_BleedWounds(const int team)
Deal damage to each wounded team member.
Definition: g_health.cpp:130
static void G_UpdateStunState(int team)
Regenerate the "STUN" value of each (partly) stunned team member.
Definition: g_round.cpp:117
int G_CheckVisTeamAll(const int team, const vischeckflags_t visFlags, const Edict *ent)
Do G_CheckVisTeam for all entities ent is the one that is looking at the others.
Definition: g_vis.cpp:376
void setStun(int stu)
Definition: g_edict.h:302
#define G_IsSinglePlayer()
Definition: g_local.h:146
void G_GiveTimeUnits(int team)
Network function to update the time units (TUs) for each team-member.
Definition: g_client.cpp:224
#define G_IsAI(ent)
Definition: g_local.h:141
Actor * G_EdictsGetNextLivingActorOfTeam(Actor *lastEnt, const int team)
Iterate through the living actor entities of the given team.
Definition: g_edicts.cpp:216
QGL_EXTERN GLint i
Definition: r_gl.h:113
cvar_t * sv_roundtimelimit
Definition: g_main.cpp:56
int getPlayerNum() const
Definition: g_edict.h:234
Actor * G_EdictsGetNextActor(Actor *lastEnt)
Iterate through the actor entities (even the dead!)
Definition: g_edicts.cpp:231
Local definitions for game module.
void addStun(int stu)
Definition: g_edict.h:305
void AI_CheckRespawn(int team)
If the cvar g_endlessaliens is set we will endlessly respawn aliens.
Definition: g_ai.cpp:1908
void G_ActorCheckRevitalise(Actor *actor)
Definition: g_actor.cpp:386
functions to handle the storage and lifecycle of all edicts in the game module.
static void G_UpdateCarriedWeight(int team)
Updates the weight carried for each team member.
Definition: g_round.cpp:139
Inventory inv
Definition: chr_shared.h:392
int G_GetActiveTeam(void)
Returns the current active team to the server.
Definition: g_client.cpp:327
#define G_IsVisibleForTeam(ent, team)
Definition: g_local.h:144
#define TEAM_NO_ACTIVE
Definition: q_shared.h:60
static void G_RoundTouchTriggers(int team)
Definition: g_round.cpp:150
float roundstartTime
Definition: g_local.h:97
cvar_t * sv_teamplay
Definition: g_main.cpp:61
#define G_IsAIPlayer(player)
Definition: g_local.h:142
Interface for g_client.cpp.
#define DEBUG_GAME
Definition: defines.h:61
void G_ReactionFireReset(int team)
Guess! Reset all "shaken" states on end of turn?
level_locals_t level
Definition: g_main.cpp:38
#define PRINT_HUD
Definition: defines.h:107
float time
Definition: g_local.h:82