UFO: Alien Invasion
cp_mission_baseattack.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2022 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24 
25 #include "../../../cl_shared.h"
26 #include "../../../ui/ui_dataids.h"
27 #include "../cp_campaign.h"
28 #include "../cp_capacity.h"
29 #include "../cp_geoscape.h"
30 #include "../cp_ufo.h"
31 #include "../cp_missions.h"
32 #include "../cp_time.h"
33 #include "../cp_popup.h"
34 #include "../cp_alien_interest.h"
35 #include "cp_mission_baseattack.h"
36 
43 
50 {
55 
56  CP_MissionRemove(mission);
57 }
58 
63 {
64  base_t* base = mission->data.base;
65 
66  if (base) {
67  base->baseStatus = BASE_WORKING;
68 
69  /* clean up the fakeAircraft */
70  cgi->LIST_Delete(&baseAttackFakeAircraft.acTeam);
71 
74  }
75 
76  GEO_SetMissionAircraft(nullptr);
77 
80 
81  /* reset current selected mission */
82  GEO_NotifyMissionRemoved(mission);
83 
84  CP_MissionRemove(mission);
85 }
86 
91 {
92  /* Prevent multiple bases from being attacked. by resetting interest. */
94 }
95 
101 {
102  mission->stage = STAGE_RETURN_TO_ORBIT;
103 
104  if (mission->ufo) {
106  UFO_SetRandomDest(mission->ufo);
107  /* Display UFO on geoscape if it is detected */
108  mission->ufo->landed = false;
109  } else {
110  /* Go to next stage on next frame */
111  mission->finalDate = ccs.date;
112  }
113 }
114 
121 {
122  base_t* base = mission->data.base;
123  assert(base);
124  /* Base attack is over, alien won */
125  Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Your base: %s has been destroyed! All employees killed and all equipment destroyed."), base->name);
126  MS_AddNewMessage(_("Notice"), cp_messageBuffer);
127 
128  cgi->LIST_Delete(&baseAttackFakeAircraft.acTeam);
129  B_Destroy(base);
130  CP_GameTimeStop();
131 
132  /* we really don't want to use the fake aircraft anywhere */
133  GEO_SetMissionAircraft(nullptr);
135 
136  /* HACK This hack is only needed until base will be really destroyed
137  * we must recalculate items in storage because of the items we collected on battlefield */
138  CAP_UpdateStorageCap(base);
139  base->aircraftCurrent = nullptr;
140  base->baseStatus = BASE_WORKING;
141 }
142 
147 static void CP_BaseAttackPrepareBattle (mission_t* mission)
148 {
149  if (!mission)
150  return;
151 
152  base_t* base = mission->data.base;
153 
154  GEO_SelectMission(mission);
155  mission->active = true;
156  cgi->Com_DPrintf(DEBUG_CLIENT, "Base attack: %s at %.0f:%.0f\n", mission->id, mission->pos[0], mission->pos[1]);
157 
158  /* Fill the fake aircraft */
161  /* needed for transfer of alien corpses */
163 
164  /* needed to spawn soldiers on map */
167 
172  GEO_SetInterceptorAircraft(&baseAttackFakeAircraft); /* needed for updating soldier stats sa CHAR_UpdateStats */
173  B_SetCurrentSelectedBase(base); /* needed for equipment menu */
174 
175  static char popupText[1024];
176  Com_sprintf(popupText, sizeof(popupText), _("Base '%s' is under attack! What to do?"), base->name);
177  cgi->UI_RegisterText(TEXT_POPUP, popupText);
178 
179  CP_GameTimeStop();
180  cgi->UI_PushWindow("popup_baseattack");
181 }
182 
188 {
189  base_t* base = mission->data.base;
190  int soldiers;
191 
192  assert(base);
193  mission->stage = STAGE_BASE_ATTACK;
195  if (mission->ufo) {
196  /* ufo becomes invisible on geoscape, but don't remove it from ufo global array (may reappear)*/
197  CP_UFORemoveFromGeoscape(mission, false);
198  }
199 
200  /* we always need at least one command centre in the base - because the
201  * phalanx soldiers have their starting positions here.
202  * There should also always be an entrance - the aliens start there
203  * but we don't need to check that as entrance can't be destroyed */
206  cgi->Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no Command Center: it can't defend itself. Destroy base.\n", base->name);
208  return;
209  }
210 
211  MSO_CheckAddNewMessage(NT_BASE_ATTACK, _("Base attack"), va(_("Base '%s' is under attack!"), base->name), MSG_BASEATTACK);
212 
215 
216  soldiers = 0;
217  E_Foreach(EMPL_SOLDIER, employee) {
218  if (!employee->isHiredInBase(base))
219  continue;
220  if (employee->isAwayFromBase())
221  continue;
222  soldiers++;
223  }
224  if (soldiers == 0) {
225  cgi->Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers at home: it can't defend itself. Destroy base.\n", base->name);
227  return;
228  }
230 }
231 
232 
238 {
239  MIS_Foreach(mission) {
240  if (mission->category == INTERESTCATEGORY_BASE_ATTACK && mission->stage == STAGE_BASE_ATTACK)
242  }
243 }
244 
251 {
252  float randomNumber;
253  float sum = 0.0f;
254  base_t* base = nullptr;
255 
256  /* Choose randomly a base depending on alienInterest values for those bases */
257  while ((base = B_GetNext(base)) != nullptr)
258  sum += base->alienInterest;
259  randomNumber = frand() * sum;
260  while ((base = B_GetNext(base)) != nullptr) {
261  randomNumber -= base->alienInterest;
262  if (randomNumber < 0)
263  break;
264  }
265 
266  /* Make sure we have a base */
267  assert(base && (randomNumber < 0));
268 
269  /* base is already under attack */
270  if (B_IsUnderAttack(base))
271  return nullptr;
272  /* base not (yet) working */
273  if (!B_GetBuildingStatus(base, B_COMMAND))
274  return nullptr;
275 
276  return base;
277 }
278 
283 static void CP_BaseAttackGoToBase (mission_t* mission)
284 {
285  base_t* base;
286 
287  mission->stage = STAGE_MISSION_GOTO;
288 
289  base = CP_BaseAttackChooseBase();
290  if (!base) {
291  cgi->Com_Printf("CP_BaseAttackGoToBase: no base found\n");
292  CP_MissionRemove(mission);
293  return;
294  }
295  mission->data.base = base;
296 
297  mission->mapDef = cgi->Com_GetMapDefinitionByID("baseattack");
298  if (!mission->mapDef) {
299  CP_MissionRemove(mission);
300  cgi->Com_Error(ERR_DROP, "Could not find mapdef baseattack");
301  return;
302  }
303 
304  Vector2Copy(base->pos, mission->pos);
305  mission->posAssigned = true;
306 
307  if (mission->ufo) {
309  UFO_SendToDestination(mission->ufo, mission->pos);
310  } else {
311  /* Go to next stage on next frame */
312  mission->finalDate = ccs.date;
313  }
314 }
315 
321 {
322  switch (mission->stage) {
323  case STAGE_NOT_ACTIVE:
324  /* Create mission */
325  CP_MissionBegin(mission);
326  break;
328  /* Choose a base to attack and go to this base */
329  CP_BaseAttackGoToBase(mission);
330  break;
331  case STAGE_MISSION_GOTO:
332  /* just arrived on base location: attack it */
333  CP_BaseAttackStartMission(mission);
334  break;
335  case STAGE_BASE_ATTACK:
336  /* Leave earth */
338  break;
340  /* mission is over, remove mission */
342  break;
343  default:
344  cgi->Com_Printf("CP_BaseAttackMissionNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
345  CP_MissionRemove(mission);
346  break;
347  }
348 }
static base_t * CP_BaseAttackChooseBase(void)
Choose Base that will be attacked.
struct base_s * homebase
Definition: cp_aircraft.h:150
#define VectorCopy(src, dest)
Definition: vector.h:51
#define GEO_SetInterceptorAircraft(interceptor)
Definition: cp_geoscape.h:63
uiMessageListNodeMessage_t * MSO_CheckAddNewMessage(const notify_t messagecategory, const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup)
Adds a new message to message stack. It uses message settings to verify whether sound should be playe...
void UFO_SetRandomDest(aircraft_t *ufocraft)
Give a random destination to the given UFO, and make him to move there.
Definition: cp_ufo.cpp:259
char popupText[UI_MAX_SMALLTEXTLEN]
strings to be used for popup when text is not static
Definition: ui_popup.cpp:37
missionStage_t stage
Definition: cp_missions.h:99
mission definition
Definition: cp_missions.h:86
bool B_GetBuildingStatus(const base_t *const base, const buildingType_t buildingType)
Get the status associated to a building.
Definition: cp_base.cpp:478
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don&#39;t need to have varargs versions of all text functi...
Definition: shared.cpp:410
A base with all it&#39;s data.
Definition: cp_base.h:84
#define E_Foreach(employeeType, var)
Definition: cp_employee.h:122
#define MIS_Foreach(var)
iterates through missions
Definition: cp_missions.h:119
#define _(String)
Definition: cl_shared.h:44
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
#define B_IsUnderAttack(base)
Definition: cp_base.h:53
void CP_BaseAttackMissionLeave(mission_t *mission)
Base attack mission ends: UFO leave earth.
char id[MAX_VAR]
Definition: cp_missions.h:88
void INT_ChangeIndividualInterest(float interestFactor, interestCategory_t category)
Change individual interest value.
void GEO_NotifyMissionRemoved(const mission_t *mission)
Notify that a mission has been removed.
char name[MAX_VAR]
Definition: cp_base.h:86
uiMessageListNodeMessage_t * MS_AddNewMessage(const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup, bool playSound)
Adds a new message to message stack.
Definition: cp_messages.cpp:63
void CP_GameTimeStop(void)
Stop game time speed.
Definition: cp_time.cpp:126
union mission_t::missionData_t data
#define ERR_DROP
Definition: common.h:211
#define DEBUG_CLIENT
Definition: defines.h:59
aircraft_t * aircraftCurrent
Definition: cp_base.h:100
void CP_CheckBaseAttacks(void)
Check and start baseattack missions.
#define OBJZERO(obj)
Definition: shared.h:178
aircraft_t * AIR_GetFirstFromBase(const base_t *b)
Iterates through the aircraft of a base.
Definition: cp_aircraft.cpp:51
int E_CountByType(employeeType_t type)
Returns number of employees of a type.
Definition: cp_employee.cpp:39
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
Definition: cp_base.cpp:286
void CP_BaseAttackMissionIsFailure(mission_t *mission)
Base attack mission is over and is a failure (from an alien point of view): change interest values...
const cgame_import_t * cgi
bool CP_MissionBegin(mission_t *mission)
mission begins: UFO arrive on earth.
void CP_MissionRemove(mission_t *mission)
Removes a mission from mission global array.
ccs_t ccs
Definition: cp_campaign.cpp:63
vec3_t pos
Definition: cp_aircraft.h:132
int basesAttacked
Definition: cp_statistics.h:33
class DateTime finalDate
Definition: cp_missions.h:103
vec2_t pos
Definition: cp_missions.h:105
linkedList_t * acTeam
Definition: cp_aircraft.h:140
bool active
Definition: cp_missions.h:90
void B_Destroy(base_t *base)
Destroy a base.
Definition: cp_base.cpp:914
void B_SetCurrentSelectedBase(const base_t *base)
Sets the selected base.
Definition: cp_base.cpp:1553
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Definition: cp_messages.cpp:33
int B_GetNumberOfBuildingsInBaseByBuildingType(const base_t *base, const buildingType_t buildingType)
Counts the number of buildings of a particular building type in a base.
Definition: cp_base.cpp:1386
void CP_BaseAttackMissionDestroyBase(mission_t *mission)
Base attack mission ends: UFO leave earth.
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
An aircraft with all it&#39;s data.
Definition: cp_aircraft.h:115
void CAP_UpdateStorageCap(base_t *base)
Update Storage Capacity.
Definition: cp_capacity.cpp:52
struct mission_s * mission
Definition: cp_aircraft.h:153
stats_t campaignStats
Definition: cp_campaign.h:379
float frand(void)
Return random values between 0 and 1.
Definition: mathlib.cpp:506
void CP_BaseAttackMissionNextStage(mission_t *mission)
Determine what action should be performed when a Base Attack mission stage ends.
void CP_BaseAttackStartMission(mission_t *mission)
Start Base Attack.
int maxTeamSize
Definition: cp_aircraft.h:139
class DateTime date
Definition: cp_campaign.h:246
#define MAX_ACTIVETEAM
Definition: defines.h:41
void CP_UFORemoveFromGeoscape(mission_t *mission, bool destroyed)
Removes (temporarily or permanently) a UFO from geoscape: make it land and call notify functions...
static aircraft_t baseAttackFakeAircraft
This fake aircraft is used to assign soldiers for a base attack mission.
#define Vector2Copy(src, dest)
Definition: vector.h:52
void UFO_SendToDestination(aircraft_t *ufo, const vec2_t dest)
Make the specified UFO go to destination.
Definition: cp_ufo.cpp:562
static void CP_BaseAttackPrepareBattle(mission_t *mission)
Prepare things for baseattack battle.
Campaign mission headers.
bool posAssigned
Definition: cp_missions.h:112
mapDef_t *IMPORT * Com_GetMapDefinitionByID(const char *mapDefID)
float alienInterest
Definition: cp_base.h:104
aircraft_t * ufo
Definition: cp_missions.h:106
vec3_t pos
Definition: cp_base.h:91
void CP_BaseAttackMissionIsSuccess(mission_t *mission)
Base attack mission is over and is a success (from an alien point of view): change interest values...
baseStatus_t baseStatus
Definition: cp_base.h:102
#define GEO_SetMissionAircraft(aircraft)
Definition: cp_geoscape.h:66
void CP_MissionDisableTimeLimit(mission_t *mission)
Disable time limit for given mission.
mission_t * GEO_SelectMission(mission_t *mission)
Select the specified mission.
mapDef_t * mapDef
Definition: cp_missions.h:89
void CP_BaseAttackMissionOnSpawn(void)
Run when the mission is spawned.
static void CP_BaseAttackGoToBase(mission_t *mission)
Set base attack mission, and go to base position.