UFO: Alien Invasion
Doxygen documentation generating
g_round.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2023 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
byte num_alive[MAX_TEAMS]
Definition: g_local.h:115
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
#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:44
Misc utility functions for game module.
static void G_GetNextActiveTeam(void)
Get the next active team.
Definition: g_round.cpp:162
void G_CheckForceEndRound(void)
Check whether a forced turn end should be executed.
Definition: g_round.cpp:39
int integer
Definition: cvar.h:81
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 getPlayerNum() const
Definition: g_edict.h:234
void G_MoraleBehaviour(int team)
Applies morale behaviour on actors.
Definition: g_morale.cpp:156
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.
float roundstartTime
Definition: g_local.h:97
Player * G_PlayerGetNextActiveAI(Player *lastPlayer)
Iterate through the list of players.
Definition: g_client.cpp:126
int actualRound
Definition: g_local.h:104
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.
character_t chr
Definition: g_edict.h:116
cvar_t * mor_panic
Definition: g_main.cpp:103
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
int framenum
Definition: g_local.h:81
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
void setStun(int stu)
Definition: g_edict.h:302
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
int nextEndRound
Definition: g_local.h:103
#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
Actor * G_EdictsGetNextActor(Actor *lastEnt)
Iterate through the actor entities (even the dead!)
Definition: g_edicts.cpp:231
Local definitions for game module.
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.
An Edict of type Actor.
Definition: g_edict.h:348
int getStun() const
Definition: g_edict.h:308
int activeTeam
Definition: g_local.h:101
static void G_UpdateCarriedWeight(int team)
Updates the weight carried for each team member.
Definition: g_round.cpp:139
int getWeight() const
Get the weight of the items in the given inventory (excluding those in temp containers).
Definition: inv_shared.cpp:937
float time
Definition: g_local.h:82
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
void addStun(int stu)
Definition: g_edict.h:305
cvar_t * sv_teamplay
Definition: g_main.cpp:61
#define G_IsAIPlayer(player)
Definition: g_local.h:142
Interface for g_client.cpp.
chrScoreMission_t * scoreMission
Definition: chr_shared.h:407
#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
Inventory inv
Definition: chr_shared.h:411