UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_mission_baseattack.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23*/
24
25#include "../../../cl_shared.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"
36
43
58
63{
64 base_t* base = mission->data.base;
65
66 if (base) {
68
69 /* clean up the fakeAircraft */
70 cgi->LIST_Delete(&baseAttackFakeAircraft.acTeam);
71
73 baseAttackFakeAircraft.mission = nullptr;
74 }
75
77
80
81 /* reset current selected 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);
127
128 cgi->LIST_Delete(&baseAttackFakeAircraft.acTeam);
129 B_Destroy(base);
131
132 /* we really don't want to use the fake aircraft anywhere */
133 GEO_SetMissionAircraft(nullptr);
134 baseAttackFakeAircraft.mission = 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 */
139 base->aircraftCurrent = nullptr;
140 base->baseStatus = BASE_WORKING;
141}
142
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 */
160 baseAttackFakeAircraft.homebase = base;
161 /* needed for transfer of alien corpses */
163
164 /* needed to spawn soldiers on map */
166 baseAttackFakeAircraft.mission = mission;
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
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
214 ccs.campaignStats.basesAttacked++;
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
283static void CP_BaseAttackGoToBase (mission_t* mission)
284{
285 base_t* base;
286
287 mission->stage = STAGE_MISSION_GOTO;
288
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;
332 /* just arrived on base location: attack it */
334 break;
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}
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
#define ERR_DROP
Definition common.h:211
aircraft_t * AIR_GetFirstFromBase(const base_t *b)
Iterates through the aircraft of a base.
void INT_ChangeIndividualInterest(float interestFactor, interestCategory_t category)
Change individual interest value.
Alien interest header.
@ INTERESTCATEGORY_BASE_ATTACK
@ INTERESTCATEGORY_BUILDING
@ INTERESTCATEGORY_RECON
@ INTERESTCATEGORY_TERROR_ATTACK
@ INTERESTCATEGORY_INTERCEPT
@ INTERESTCATEGORY_HARVEST
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
Definition cp_base.cpp:286
void B_SetCurrentSelectedBase(const base_t *base)
Sets the selected base.
Definition cp_base.cpp:1553
void B_Destroy(base_t *base)
Destroy a base.
Definition cp_base.cpp:914
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
bool B_GetBuildingStatus(const base_t *const base, const buildingType_t buildingType)
Get the status associated to a building.
Definition cp_base.cpp:478
@ BASE_UNDER_ATTACK
Definition cp_base.h:63
@ BASE_WORKING
Definition cp_base.h:64
#define B_IsUnderAttack(base)
Definition cp_base.h:53
@ B_COMMAND
Definition cp_building.h:62
ccs_t ccs
Header file for single player campaign control.
const cgame_import_t * cgi
void CAP_UpdateStorageCap(base_t *base)
Update Storage Capacity.
int E_CountByType(employeeType_t type)
Returns number of employees of a type.
@ EMPL_SOLDIER
Definition cp_employee.h:31
@ EMPL_ROBOT
Definition cp_employee.h:35
#define E_Foreach(employeeType, var)
mission_t * GEO_SelectMission(mission_t *mission)
Select the specified mission.
void GEO_NotifyMissionRemoved(const mission_t *mission)
Notify that a mission has been removed.
Header for Geoscape management.
#define GEO_SetInterceptorAircraft(interceptor)
Definition cp_geoscape.h:63
#define GEO_SetMissionAircraft(aircraft)
Definition cp_geoscape.h:66
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...
@ NT_BASE_ATTACK
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.
char cp_messageBuffer[MAX_MESSAGE_TEXT]
@ MSG_BASEATTACK
Definition cp_messages.h:43
static aircraft_t baseAttackFakeAircraft
This fake aircraft is used to assign soldiers for a base attack mission.
void CP_CheckBaseAttacks(void)
Check and start baseattack missions.
static void CP_BaseAttackPrepareBattle(mission_t *mission)
Prepare things for baseattack battle.
void CP_BaseAttackMissionIsSuccess(mission_t *mission)
Base attack mission is over and is a success (from an alien point of view): change interest values.
void CP_BaseAttackMissionOnSpawn(void)
Run when the mission is spawned.
void CP_BaseAttackMissionLeave(mission_t *mission)
Base attack mission ends: UFO leave earth.
static base_t * CP_BaseAttackChooseBase(void)
Choose Base that will be attacked.
void CP_BaseAttackMissionDestroyBase(mission_t *mission)
Base attack mission ends: UFO leave earth.
void CP_BaseAttackMissionNextStage(mission_t *mission)
Determine what action should be performed when a Base Attack mission stage ends.
static void CP_BaseAttackGoToBase(mission_t *mission)
Set base attack mission, and go to base position.
void CP_BaseAttackStartMission(mission_t *mission)
Start Base Attack.
void CP_BaseAttackMissionIsFailure(mission_t *mission)
Base attack mission is over and is a failure (from an alien point of view): change interest values.
Campaign mission headers.
bool CP_MissionBegin(mission_t *mission)
mission begins: UFO arrive on earth.
void CP_UFORemoveFromGeoscape(mission_t *mission, bool destroyed)
Removes (temporarily or permanently) a UFO from geoscape: make it land and call notify functions.
void CP_MissionRemove(mission_t *mission)
Removes a mission from mission global array.
void CP_MissionDisableTimeLimit(mission_t *mission)
Disable time limit for given mission.
Campaign missions headers.
#define MIS_Foreach(var)
iterates through missions
@ STAGE_RETURN_TO_ORBIT
Definition cp_missions.h:51
@ STAGE_MISSION_GOTO
Definition cp_missions.h:39
@ STAGE_NOT_ACTIVE
Definition cp_missions.h:35
@ STAGE_COME_FROM_ORBIT
Definition cp_missions.h:36
@ STAGE_BASE_ATTACK
Definition cp_missions.h:43
void CP_GameTimeStop(void)
Stop game time speed.
Definition cp_time.cpp:126
Campaign geoscape time header.
void UFO_SendToDestination(aircraft_t *ufo, const vec2_t dest)
Make the specified UFO go to destination.
Definition cp_ufo.cpp:562
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
#define DEBUG_CLIENT
Definition defines.h:59
#define MAX_ACTIVETEAM
Definition defines.h:41
float frand(void)
Return random values between 0 and 1.
Definition mathlib.cpp:506
#define OBJZERO(obj)
Definition shared.h:178
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
An aircraft with all it's data.
A base with all it's data.
Definition cp_base.h:84
aircraft_t * aircraftCurrent
Definition cp_base.h:100
float alienInterest
Definition cp_base.h:104
baseStatus_t baseStatus
Definition cp_base.h:102
char name[MAX_VAR]
Definition cp_base.h:86
vec3_t pos
Definition cp_base.h:91
mission definition
Definition cp_missions.h:86
aircraft_t * ufo
mapDef_t * mapDef
Definition cp_missions.h:89
bool active
Definition cp_missions.h:90
missionStage_t stage
Definition cp_missions.h:99
vec2_t pos
union mission_t::missionData_t data
bool posAssigned
class DateTime finalDate
char id[MAX_VAR]
Definition cp_missions.h:88
@ TEXT_POPUP
Definition ui_dataids.h:38
char popupText[UI_MAX_SMALLTEXTLEN]
strings to be used for popup when text is not static
Definition ui_popup.cpp:37
#define VectorCopy(src, dest)
Definition vector.h:51
#define Vector2Copy(src, dest)
Definition vector.h:52