UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_campaign.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 "../../DateTime.h"
26#include "../../cl_shared.h"
27#include "../../ui/ui_main.h"
28#include "../cgame.h"
29#include "cp_campaign.h"
30#include "cp_capacity.h"
31#include "cp_character.h"
32#include "cp_overlay.h"
33#include "cp_mapfightequip.h"
34#include "cp_hospital.h"
36#include "cp_base_callbacks.h"
38#include "cp_team.h"
39#include "cp_team_callbacks.h"
40#include "cp_popup.h"
41#include "cp_geoscape.h"
42#include "cp_ufo.h"
44#include "cp_alien_interest.h"
45#include "cp_missions.h"
46#include "cp_mission_triggers.h"
47#include "cp_nation.h"
48#include "cp_statistics.h"
49#include "cp_time.h"
50#include "cp_xvi.h"
53#include "cp_transfer.h"
54#include "cp_market_callbacks.h"
56#include "cp_uforecovery.h"
57#include "save/save_campaign.h"
58#include "cp_auto_mission.h"
61
65
66/* fraction of nation that can be below min happiness before the game is lost */
67#define NATIONBELOWLIMITPERCENTAGE 0.5f
68
76
80bool CP_IsRunning (void)
81{
82 return ccs.curCampaign != nullptr;
83}
84
89void CP_EndCampaign (bool won)
90{
91 cgi->Cmd_ExecuteString("game_save slotend \"End of game\"");
92 cgi->Cbuf_AddText("ui_set_endgame %s;", won ? "won" : "lose");
93 cgi->Cbuf_AddText("ui_initstack endgame;");
94
95 cgi->Com_Drop();
96}
97
101void CP_CheckLostCondition (const campaign_t* campaign)
102{
103 bool endCampaign = false;
104
105 if (cp_missiontest->integer)
106 return;
107
108 if (!endCampaign && ccs.credits < -campaign->negativeCreditsUntilLost) {
109 cgi->UI_RegisterText(TEXT_STANDARD, _("You've gone too far into debt."));
110 endCampaign = true;
111 }
112
116 if (ccs.credits < campaign->basecost - campaign->negativeCreditsUntilLost && !B_AtLeastOneExists()) {
117 cgi->UI_RegisterText(TEXT_STANDARD, _("You've lost your bases and don't have enough money to build new ones."));
118 endCampaign = true;
119 }
120
121 if (!endCampaign) {
123 cgi->UI_RegisterText(TEXT_STANDARD, _("You have failed in your charter to protect Earth."
124 " Our home and our people have fallen to the alien infection. Only a handful"
125 " of people on Earth remain human, and the remaining few no longer have a"
126 " chance to stem the tide. Your command is no more; PHALANX is no longer"
127 " able to operate as a functioning unit. Nothing stands between the aliens"
128 " and total victory."));
129 endCampaign = true;
130 } else {
131 /* check for nation happiness */
132 int nationBelowLimit = 0;
133 NAT_Foreach(nation) {
134 const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
135 if (stats->happiness < campaign->minhappiness) {
136 nationBelowLimit++;
137 }
138 }
139 if (nationBelowLimit >= NATIONBELOWLIMITPERCENTAGE * ccs.numNations) {
140 /* lost the game */
141 cgi->UI_RegisterText(TEXT_STANDARD, _("Under your command, PHALANX operations have"
142 " consistently failed to protect nations."
143 " The UN, highly unsatisfied with your performance, has decided to remove"
144 " you from command and subsequently disbands the PHALANX project as an"
145 " effective task force. No further attempts at global cooperation are made."
146 " Earth's nations each try to stand alone against the aliens, and eventually"
147 " fall one by one."));
148 endCampaign = true;
149 }
150 }
151 }
152
153 if (endCampaign)
154 CP_EndCampaign(false);
155}
156
160static void CP_CheckMissionEnd (const campaign_t* campaign)
161{
162 MIS_Foreach(mission) {
163 if (CP_CheckMissionLimitedInTime(mission) && ccs.date > mission->finalDate)
164 CP_MissionStageEnd(campaign, mission);
165 }
166}
167
168/* =========================================================== */
169
177static void CP_CampaignFunctionPeriodicCall (campaign_t* campaign, int dt, bool updateRadarOverlay)
178{
179 UFO_CampaignRunUFOs(campaign, dt);
180 AIR_CampaignRun(campaign, dt, updateRadarOverlay);
181
185
186 /* Update alien interest for bases */
188
189 /* Update how phalanx troop know alien bases */
191
193}
194
199bool CP_OnGeoscape (void)
200{
201 return Q_streq("geoscape", cgi->UI_GetActiveWindowName());
202}
203
209static inline void CP_AdvanceTimeBySeconds (int seconds)
210{
211 ccs.date += DateTime(0, seconds);
212}
213
217static inline bool CP_IsBudgetDue (const dateLong_t* oldDate, const dateLong_t* date)
218{
219 if (oldDate->year < date->year) {
220 return true;
221 }
222 return oldDate->month < date->month;
223}
224
231void CP_CampaignRun (campaign_t* campaign, float secondsSinceLastFrame)
232{
233 /* advance time */
234 ccs.frametime = secondsSinceLastFrame;
235 ccs.timer += secondsSinceLastFrame * ccs.gameTimeScale;
236
238
239 if (ccs.timer < 1.0)
240 return;
241
242 /* calculate new date */
243 int currentsecond = ccs.date.getTimeAsSeconds();
244 int currentday = ccs.date.getDateAsDays();
245 const int currentinterval = currentsecond % DETECTION_INTERVAL;
246 int dt = DETECTION_INTERVAL - currentinterval;
247 dateLong_t date, oldDate;
248 const int timer = (int)floor(ccs.timer);
249 const int checks = (currentinterval + timer) / DETECTION_INTERVAL;
250
251 CP_DateConvertLong(ccs.date, &oldDate);
252
253 int currenthour = currentsecond / DateTime::SECONDS_PER_HOUR;
254 int currentmin = currentsecond / DateTime::SECONDS_PER_MINUTE;
255
256 /* Execute every actions that needs to be independent of time speed : every DETECTION_INTERVAL
257 * - Run UFOs and craft at least every DETECTION_INTERVAL. If detection occurred, break.
258 * - Check if any new mission is detected
259 * - Update stealth value of phalanx bases and installations ; alien bases */
260 for (int i = 0; i < checks; i++) {
261 ccs.timer -= dt;
262 currentsecond += dt;
264 CP_CampaignFunctionPeriodicCall(campaign, dt, false);
265
266 /* if something stopped time, we must stop here the loop */
267 if (CP_IsTimeStopped()) {
268 ccs.timer = 0.0f;
269 break;
270 }
272 }
273
274 dt = timer;
275
277 currentsecond += dt;
278 ccs.timer -= dt;
279
280 /* compute minutely events */
281 /* (this may run multiple times if the time stepping is > 1 minute at a time) */
282 const int newmin = currentsecond / DateTime::SECONDS_PER_MINUTE;
283 while (currentmin < newmin) {
284 currentmin++;
287 }
288
289 /* compute hourly events */
290 /* (this may run multiple times if the time stepping is > 1 hour at a time) */
291 const int newhour = currentsecond / DateTime::SECONDS_PER_HOUR;
292 while (currenthour < newhour) {
293 currenthour++;
300 }
301
302 /* daily events */
303 for (int i = currentday; i < ccs.date.getDateAsDays(); i++) {
304 /* every day */
307 ccs.missionSpawnCallback();
308 CP_SpreadXVI();
311 CP_CampaignRunMarket(campaign);
312 CP_CheckCampaignEvents(campaign);
314 /* should be executed after all daily event that could
315 * change XVI overlay */
318 }
319
320 if (dt > 0) {
321 /* check for campaign events
322 * aircraft and UFO already moved during radar detection (see above),
323 * just make them move the missing part -- if any */
324 CP_CampaignFunctionPeriodicCall(campaign, dt, true);
325 }
326
327 CP_CheckMissionEnd(campaign);
328 CP_CheckLostCondition(campaign);
329 /* Check if there is a base attack mission */
331 /* check if any stores are full */
334
335 CP_DateConvertLong(ccs.date, &date);
336 /* every new month we have to handle the budget */
337 if (CP_IsBudgetDue(&oldDate, &date) && ccs.paid && B_AtLeastOneExists()) {
339 NAT_HandleBudget(campaign);
340 ccs.paid = false;
341 } else if (date.day > 1)
342 ccs.paid = true;
343
345 /* set time cvars */
347}
348
353bool CP_CheckCredits (int costs)
354{
355 if (costs > ccs.credits)
356 return false;
357 return true;
358}
359
365void CP_UpdateCredits (int credits)
366{
367 /* credits */
368 if (credits > MAX_CREDITS)
369 credits = MAX_CREDITS;
370 ccs.credits = credits;
371 cgi->Cvar_Set("mn_credits", _("%i c"), ccs.credits);
372}
373
378static bool CP_LoadMapDefStatXML (xmlNode_t* parent)
379{
380 xmlNode_t* node;
381
382 for (node = cgi->XML_GetNode(parent, SAVE_CAMPAIGN_MAPDEF); node; node = cgi->XML_GetNextNode(node, parent, SAVE_CAMPAIGN_MAPDEF)) {
383 const char* s = cgi->XML_GetString(node, SAVE_CAMPAIGN_MAPDEF_ID);
384 mapDef_t* map;
385
386 if (s[0] == '\0') {
387 cgi->Com_Printf("Warning: MapDef with no id in xml!\n");
388 continue;
389 }
390 map = cgi->Com_GetMapDefinitionByID(s);
391 if (!map) {
392 cgi->Com_Printf("Warning: No MapDef with id '%s'!\n", s);
393 continue;
394 }
395 map->timesAlreadyUsed = cgi->XML_GetInt(node, SAVE_CAMPAIGN_MAPDEF_COUNT, 0);
396 }
397
398 return true;
399}
400
405bool CP_LoadXML (xmlNode_t* parent)
406{
407 xmlNode_t* campaignNode;
408 xmlNode_t* mapNode;
409 const char* name;
410 campaign_t* campaign;
411 xmlNode_t* mapDefStat;
412
413 campaignNode = cgi->XML_GetNode(parent, SAVE_CAMPAIGN_CAMPAIGN);
414 if (!campaignNode) {
415 cgi->Com_Printf("Did not find campaign entry in xml!\n");
416 return false;
417 }
418 if (!(name = cgi->XML_GetString(campaignNode, SAVE_CAMPAIGN_ID))) {
419 cgi->Com_Printf("couldn't locate campaign name in savegame\n");
420 return false;
421 }
422
423 campaign = CP_GetCampaign(name);
424 if (!campaign) {
425 cgi->Com_Printf("......campaign \"%s\" doesn't exist.\n", name);
426 return false;
427 }
428
429 CP_CampaignInit(campaign, true);
430 /* init the map images and reset the map actions */
431 GEO_Reset(campaign->map);
432
433 /* read credits */
434 CP_UpdateCredits(cgi->XML_GetLong(campaignNode, SAVE_CAMPAIGN_CREDITS, 0));
435 ccs.paid = cgi->XML_GetBool(campaignNode, SAVE_CAMPAIGN_PAID, false);
436
437 cgi->SetNextUniqueCharacterNumber(cgi->XML_GetInt(campaignNode, SAVE_CAMPAIGN_NEXTUNIQUECHARACTERNUMBER, 0));
438
439 int date;
440 int time;
441 cgi->XML_GetDate(campaignNode, SAVE_CAMPAIGN_DATE, &date, &time);
442 ccs.date = DateTime(date, time);
443
444 /* read other campaign data */
445 ccs.civiliansKilled = cgi->XML_GetInt(campaignNode, SAVE_CAMPAIGN_CIVILIANSKILLED, 0);
446 ccs.aliensKilled = cgi->XML_GetInt(campaignNode, SAVE_CAMPAIGN_ALIENSKILLED, 0);
447
448 cgi->Com_DPrintf(DEBUG_CLIENT, "CP_LoadXML: Getting position\n");
449
450 /* read map view */
451 mapNode = cgi->XML_GetNode(campaignNode, SAVE_CAMPAIGN_MAP);
452
453 /* Compatibility code for savegames */
454 int oldOverlayStatus = cgi->XML_GetInt(mapNode, SAVE_CAMPAIGN_CL_GEOSCAPE_OVERLAY, -1);
455 if (oldOverlayStatus >= 0) {
456 const int overlayNation = 1 << 0;
457 const int overlayXvi = 1 << 1;
458 const int overlayRadar = 1 << 2;
459
460 cgi->Cvar_SetValue("geo_overlay_radar", oldOverlayStatus & overlayRadar);
461 cgi->Cvar_SetValue("geo_overlay_nation", oldOverlayStatus & overlayNation);
462 cgi->Cvar_SetValue("geo_overlay_xvi", oldOverlayStatus & overlayXvi);
463 } else {
464 cgi->Cvar_SetValue("geo_overlay_radar", cgi->XML_GetInt(mapNode, SAVE_CAMPAIGN_GEO_OVERLAY_RADAR, 0));
465 cgi->Cvar_SetValue("geo_overlay_nation", cgi->XML_GetInt(mapNode, SAVE_CAMPAIGN_GEO_OVERLAY_NATION, 0));
466 cgi->Cvar_SetValue("geo_overlay_xvi", cgi->XML_GetInt(mapNode, SAVE_CAMPAIGN_GEO_OVERLAY_XVI, 0));
467 }
468 radarOverlayWasSet = cgi->XML_GetBool(mapNode, SAVE_CAMPAIGN_RADAROVERLAYWASSET, false);
469 ccs.startXVI = cgi->XML_GetBool(mapNode, SAVE_CAMPAIGN_XVISTARTED, false);
470
471 mapDefStat = cgi->XML_GetNode(campaignNode, SAVE_CAMPAIGN_MAPDEFSTAT);
472 if (mapDefStat && !CP_LoadMapDefStatXML(mapDefStat))
473 return false;
474
475 mxmlDelete(campaignNode);
476 return true;
477}
478
483static bool CP_SaveMapDefStatXML (xmlNode_t* parent)
484{
485 const mapDef_t* md;
486
488 if (md->timesAlreadyUsed > 0) {
489 xmlNode_t* node = cgi->XML_AddNode(parent, SAVE_CAMPAIGN_MAPDEF);
490 cgi->XML_AddString(node, SAVE_CAMPAIGN_MAPDEF_ID, md->id);
491 cgi->XML_AddInt(node, SAVE_CAMPAIGN_MAPDEF_COUNT, md->timesAlreadyUsed);
492 }
493 }
494
495 return true;
496}
497
502bool CP_SaveXML (xmlNode_t* parent)
503{
504 xmlNode_t* campaign;
505 xmlNode_t* map;
506 xmlNode_t* mapDefStat;
507
508 campaign = cgi->XML_AddNode(parent, SAVE_CAMPAIGN_CAMPAIGN);
509
510 cgi->XML_AddString(campaign, SAVE_CAMPAIGN_ID, ccs.curCampaign->id);
511 cgi->XML_AddDate(campaign, SAVE_CAMPAIGN_DATE, ccs.date.getDateAsDays(), ccs.date.getTimeAsSeconds());
512 cgi->XML_AddLong(campaign, SAVE_CAMPAIGN_CREDITS, ccs.credits);
513 cgi->XML_AddShort(campaign, SAVE_CAMPAIGN_PAID, ccs.paid);
514 cgi->XML_AddShortValue(campaign, SAVE_CAMPAIGN_NEXTUNIQUECHARACTERNUMBER, cgi->GetNextUniqueCharacterNumber());
515
516 cgi->XML_AddIntValue(campaign, SAVE_CAMPAIGN_CIVILIANSKILLED, ccs.civiliansKilled);
517 cgi->XML_AddIntValue(campaign, SAVE_CAMPAIGN_ALIENSKILLED, ccs.aliensKilled);
518
519 /* Map and user interface */
520 map = cgi->XML_AddNode(campaign, SAVE_CAMPAIGN_MAP);
521 cgi->XML_AddShort(map, SAVE_CAMPAIGN_GEO_OVERLAY_RADAR, cgi->Cvar_GetInteger("geo_overlay_radar"));
522 cgi->XML_AddShort(map, SAVE_CAMPAIGN_GEO_OVERLAY_NATION, cgi->Cvar_GetInteger("geo_overlay_nation"));
523 cgi->XML_AddShort(map, SAVE_CAMPAIGN_GEO_OVERLAY_XVI, cgi->Cvar_GetInteger("geo_overlay_xvi"));
525 cgi->XML_AddBool(map, SAVE_CAMPAIGN_XVISTARTED, CP_IsXVIStarted());
526
527 mapDefStat = cgi->XML_AddNode(campaign, SAVE_CAMPAIGN_MAPDEFSTAT);
528 if (!CP_SaveMapDefStatXML(mapDefStat))
529 return false;
530
531 return true;
532}
533
541{
542 mission_t* mis;
544 base_t* base;
545 battleParam_t* battleParam = &ccs.battleParameters;
546
547 if (!aircraft) {
548 cgi->Com_Printf("CP_StartSelectedMission: No mission aircraft\n");
549 return;
550 }
551
552 base = aircraft->homebase;
553
554 if (GEO_GetSelectedMission() == nullptr)
556
558 if (!mis) {
559 cgi->Com_Printf("CP_StartSelectedMission: No mission selected\n");
560 return;
561 }
562
563 /* Before we start, we should clear the missionResults array. */
565
566 /* Various sanity checks. */
567 if (!mis->active) {
568 cgi->Com_Printf("CP_StartSelectedMission: Dropship not near landing zone: mis->active: %i\n", mis->active);
569 return;
570 }
571 if (AIR_GetTeamSize(aircraft) == 0) {
572 cgi->Com_Printf("CP_StartSelectedMission: No team in dropship.\n");
573 return;
574 }
575
576 /* if we retry a mission we have to drop from the current game before */
577 cgi->SV_Shutdown("Server quit.", false);
578 cgi->CL_Disconnect();
579
580 CP_CreateBattleParameters(mis, battleParam, aircraft);
581 BATTLE_SetVars(battleParam);
582
583 /* manage inventory */
584 ccs.eMission = base->storage; /* copied, including arrays inside! */
586 CP_CleanupAircraftTeam(aircraft, &ccs.eMission);
587 BATTLE_Start(mis, battleParam);
588}
589#ifdef DEBUG
594static void CP_DebugShowItems_f (void)
595{
596 if (cgi->Cmd_Argc() < 2) {
597 cgi->Com_Printf("Usage: %s <baseID>\n", cgi->Cmd_Argv(0));
598 return;
599 }
600
601 int i = atoi(cgi->Cmd_Argv(1));
602 if (i >= B_GetCount()) {
603 cgi->Com_Printf("invalid baseID (%s)\n", cgi->Cmd_Argv(1));
604 return;
605 }
606 base_t* base = B_GetBaseByIDX(i);
607
608 for (i = 0; i < cgi->csi->numODs; i++) {
609 const objDef_t* obj = INVSH_GetItemByIDX(i);
610 cgi->Com_Printf("%i. %s: %i\n", i, obj->id, B_ItemInBase(obj, base));
611 }
612}
613
620static void CP_DebugAddItem_f (void)
621{
622 if (cgi->Cmd_Argc() < 4) {
623 cgi->Com_Printf("Usage: %s <baseID> <itemid> <count>\n", cgi->Cmd_Argv(0));
624 return;
625 }
626
627 base_t* base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(1)));
628 const objDef_t* obj = INVSH_GetItemByID(cgi->Cmd_Argv(2));
629 const int count = atoi(cgi->Cmd_Argv(3));
630
631 if (!base) {
632 cgi->Com_Printf("Invalid base index given\n");
633 return;
634 }
635 if (!obj) {
636 /* INVSH_GetItemByIDX prints warning already */
637 return;
638 }
639
640 const int amount = B_AddToStorage(base, obj, count);
641 cgi->Com_Printf("%s %s %d\n", base->name, obj->id, amount);
642 if (B_ItemInBase(obj, base) > 0) {
643 technology_t* tech = RS_GetTechForItem(obj);
644 RS_MarkCollected(tech);
645 }
646}
647
654static void CP_DebugAddAntimatter_f (void)
655{
656 if (cgi->Cmd_Argc() < 3) {
657 cgi->Com_Printf("Usage: %s <baseID> <amount>\n", cgi->Cmd_Argv(0));
658 return;
659 }
660
661 base_t* base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(1)));
662 const int amount = atoi(cgi->Cmd_Argv(2));
663
664 if (!base) {
665 cgi->Com_Printf("Invalid base index given\n");
666 return;
667 }
668
669 B_AddAntimatter(base, amount);
670}
671
675static void CP_DebugFullCredits_f (void)
676{
678}
679#endif
680
681/* ===================================================================== */
682
683/* these commands are only available in singleplayer */
684static const cmdList_t game_commands[] = {
685 {"update_base_radar_coverage", RADAR_UpdateBaseRadarCoverage_f, "Update base radar coverage"},
686 {"addeventmail", CL_EventAddMail_f, "Add a new mail (event trigger) - e.g. after a mission"},
687 {"game_go", CP_StartSelectedMission, nullptr},
688 {"game_timestop", CP_GameTimeStop, nullptr},
689 {"game_timeslow", CP_GameTimeSlow, nullptr},
690 {"game_timefast", CP_GameTimeFast, nullptr},
691 {"game_settimeid", CP_SetGameTime_f, nullptr},
692 {"map_center", GEO_CenterOnPoint_f, "Centers the geoscape view on items on the geoscape - and cycle through them"},
693 {"cp_start_xvi_spreading", CP_StartXVISpreading_f, "Start XVI spreading"},
694 {"cp_spawn_ufocarrier", CP_SpawnUFOCarrier_f, "Spawns a UFO-Carrier on the geoscape"},
695 {"cp_attack_ufocarrier", CP_AttackUFOCarrier_f, "Attack the UFO-Carrier"},
696#ifdef DEBUG
697 {"debug_fullcredits", CP_DebugFullCredits_f, "Debug function to give the player full credits"},
698 {"debug_itemadd", CP_DebugAddItem_f, "Debug function to add certain items to base storage"},
699 {"debug_antimatteradd", CP_DebugAddAntimatter_f, "Debug function to add some antimatter to base container"},
700 {"debug_listitem", CP_DebugShowItems_f, "Debug function to show all items in base storage"},
701#endif
702 {nullptr, nullptr, nullptr}
703};
704
724
725static void CP_AddCampaignCommands (void)
726{
727 cgi->Cmd_TableAddList(game_commands);
729}
730
752
754{
755 cgi->Cmd_TableRemoveList(game_commands);
756
758}
759
765void CP_CampaignInit (campaign_t* campaign, bool load)
766{
767 ccs.curCampaign = campaign;
768
769 CP_ReadCampaignData(campaign);
770
772
773 RS_InitTree(campaign, load);
774
776
778
779 /* Init popup and map/geoscape */
780 CL_PopupInit();
781
782 CP_XVIInit();
783
784 if (load) {
785 return;
786 }
787
788 cgi->UI_InitStack("geoscape", "campaign_main");
789
790 CL_EventAddMail("prolog");
791
792 RS_MarkResearchable(nullptr, true);
793 BS_InitMarket(campaign);
794
795 /* create initial employees */
796 E_InitialEmployees(campaign);
797
798 GEO_Reset(campaign->map);
799
800 CP_UpdateCredits(campaign->credits);
801
802 /* Initialize alien interest */
804
805 /* Initialize XVI overlay */
808
809 /* create a base as first step */
810 B_SelectBase(nullptr);
811
812 /* Spawn first missions of the game */
814
815 /* now check the parsed values for errors that are not caught at parsing stage */
817}
818
822void CP_Shutdown (void)
823{
824 if (CP_IsRunning()) {
825 AB_Shutdown();
826 UFO_Shutdown();
827 AIR_Shutdown();
828 INS_Shutdown();
829 INT_Shutdown();
830 NAT_Shutdown();
831 MIS_Shutdown();
832 TR_Shutdown();
834 UR_Shutdown();
835 AM_Shutdown();
836 E_Shutdown();
838
840 for (int i = 0; i < ccs.numAlienCategories; i++) {
841 alienTeamCategory_t* alienCat = &ccs.alienCategories[i];
842 cgi->LIST_Delete(&alienCat->equipment);
843 }
844
845 cgi->Cvar_SetValue("geo_overlay_radar", 0);
846 cgi->Cvar_SetValue("geo_overlay_nations", 0);
847 cgi->Cvar_SetValue("geo_overlay_xvi", 0);
848 /* singleplayer commands are no longer available */
850 }
851
852 GEO_Shutdown();
853}
854
861{
862 campaign_t* campaign;
863 int i;
864
865 for (i = 0, campaign = ccs.campaigns; i < ccs.numCampaigns; i++, campaign++)
866 if (Q_streq(name, campaign->id))
867 break;
868
869 if (i == ccs.numCampaigns) {
870 cgi->Com_Printf("CL_GetCampaign: Campaign \"%s\" doesn't exist.\n", name);
871 return nullptr;
872 }
873 return campaign;
874}
875
882{
883 mapDef_t* md;
884
885 cgi->UI_MessageResetStack();
886
887 /* cleanup dynamic mails */
889
890 AIR_Foreach(aircraft) {
891 AIR_Delete(nullptr, aircraft);
892 }
893
894 base_t* base = nullptr;
895 while((base = B_GetNext(base)) != nullptr) {
896 B_Delete(base);
897 }
898
899 cgi->FreePool(cp_campaignPool);
900
901 /* called to flood the hash list - because the parse tech function
902 * was maybe already called */
904
905 OBJZERO(ccs);
906
907 ccs.missionSpawnCallback = CP_SpawnNewMissions;
908
909 /* Clear mapDef usage statistics */
911 md->timesAlreadyUsed = 0;
912 }
913}
914
915int CP_GetSalaryUpKeepBase (const salary_t* salary, const base_t* base)
916{
917 int cost = salary->baseUpkeep; /* base cost */
918 building_t* building = nullptr;
919 while ((building = B_GetNextBuilding(base, building))) {
920 if (building->buildingStatus == B_STATUS_WORKING
922 cost += building->varCosts;
923 }
924 return cost;
925}
926
928void CP_InitStartup (void)
929{
930 cp_campaignPool = cgi->CreatePool("Client: Local (per game)");
931
932 SAV_Init();
933
934
935 cp_missiontest = cgi->Cvar_Get("cp_missiontest", "0", CVAR_DEVELOPER, "This will never stop the time on geoscape and print information about spawned missions");
936
937 /* init subsystems */
940
962}
DateTime class definition.
Client game mode interface.
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
#define MapDef_ForeachSingleplayerCampaign(var)
Definition cl_shared.h:84
Class describing a point of time.
Definition DateTime.h:31
static const short SECONDS_PER_MINUTE
Definition DateTime.h:34
static const short SECONDS_PER_HOUR
Definition DateTime.h:42
void AIR_CampaignRun(const campaign_t *campaign, int dt, bool updateRadarOverlay)
Handles aircraft movement and actions in geoscape mode.
int AIR_GetTeamSize(const aircraft_t *aircraft)
Counts the number of soldiers in given aircraft.
void AIR_InitStartup(void)
Init actions for aircraft-subsystem.
bool AIR_Delete(base_t *base, aircraft_t *aircraft)
Will remove the given aircraft from the base.
void AIR_Shutdown(void)
Closing actions for aircraft-subsystem.
#define AIR_Foreach(var)
iterates trough all aircraft
void AIRFIGHT_CampaignRunBaseDefence(int dt)
Run base defences.
void AIRFIGHT_CampaignRunProjectiles(const campaign_t *campaign, int dt)
Update values of projectiles.
void AIRFIGHT_InitStartup(void)
void INT_InitStartup(void)
Init actions for alien interests-subsystem.
void INT_Shutdown(void)
Closing actions for alien interests-subsystem.
void INT_IncreaseAlienInterest(const campaign_t *campaign)
Increase alien overall interest.
void INT_ResetAlienInterest(void)
Initialize alien interest values and mission cycle.
Alien interest header.
void AB_InitStartup(void)
Init actions for alienbase-subsystem.
void AB_Shutdown(void)
Closing actions for alienbase-subsystem.
void AB_UpdateStealthForAllBase(void)
Update stealth value of every base for every aircraft.
void AB_BaseSearchedByNations(void)
Nations help in searching alien base.
void AC_InitStartup(void)
Defines commands and cvars for the alien containment menu(s).
void AM_InitStartup(void)
Init actions for automission-subsystem.
void AM_Shutdown(void)
Closing actions for automission-subsystem.
Header file for single player automatic (quick, simulated) missions, without going to the battlescape...
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition cp_base.cpp:326
void B_SelectBase(const base_t *base)
Select and opens a base.
Definition cp_base.cpp:1592
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
Definition cp_base.cpp:286
int B_GetCount(void)
Returns the count of founded bases.
Definition cp_base.cpp:277
int B_AddAntimatter(base_t *base, int amount)
Manages antimatter (adding, removing) through Antimatter Storage Facility.
Definition cp_base.cpp:2635
base_t * B_GetBaseByIDX(int baseIdx)
Array bound check for the base index. Will also return unfounded bases as long as the index is in the...
Definition cp_base.cpp:313
void B_Delete(base_t *base)
Resets a base structure.
Definition cp_base.cpp:898
int B_ItemInBase(const objDef_t *item, const base_t *base)
Check if the item has been collected (i.e it is in the storage) in the given base.
Definition cp_base.cpp:2133
int B_AddToStorage(base_t *base, const objDef_t *obj, int amount)
Add/remove items to/from the storage.
Definition cp_base.cpp:2576
void B_UpdateBuildingConstructions(void)
Updates base data.
Definition cp_base.cpp:2009
void B_InitStartup(void)
Resets console commands.
Definition cp_base.cpp:1970
building_t * B_GetNextBuilding(const base_t *base, building_t *lastBuilding)
Iterates through buildings in a base.
Definition cp_base.cpp:339
#define B_AtLeastOneExists()
Definition cp_base.h:55
void B_InitCallbacks(void)
void B_ShutdownCallbacks(void)
Header file for menu related console command callbacks.
void BDEF_ShutdownCallbacks(void)
void BDEF_InitCallbacks(void)
Header file for menu callback functions used for basedefence menu.
@ B_STATUS_CONSTRUCTION_FINISHED
Definition cp_building.h:34
@ B_STATUS_WORKING
Definition cp_building.h:36
static void CP_CampaignFunctionPeriodicCall(campaign_t *campaign, int dt, bool updateRadarOverlay)
Functions that should be called with a minimum time lapse (will be called at least every DETECTION_IN...
memPool_t * cp_campaignPool
void CP_ResetCampaignData(void)
Will clear most of the parsed singleplayer data.
void CP_Shutdown(void)
Campaign closing actions.
bool CP_OnGeoscape(void)
Returns if we are currently on the Geoscape.
bool CP_IsRunning(void)
Checks whether a campaign mode game is running.
void CP_CampaignRun(campaign_t *campaign, float secondsSinceLastFrame)
Called every frame when we are in geoscape view.
int CP_GetSalaryUpKeepBase(const salary_t *salary, const base_t *base)
const int DETECTION_INTERVAL
delay between actions that must be executed independently of time scale
void CP_InitStartup(void)
static bool CP_SaveMapDefStatXML(xmlNode_t *parent)
Save mapDef statistics.
void CP_CheckLostCondition(const campaign_t *campaign)
Checks whether the player has lost the campaign.
void CP_StartSelectedMission(void)
Starts a selected mission.
static void CP_RemoveCampaignCallbackCommands(void)
registers callback commands that are used by campaign
bool CP_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
static void CP_AdvanceTimeBySeconds(int seconds)
Ensure that the day always matches the seconds. If the seconds per day limit is reached,...
void CP_CampaignInit(campaign_t *campaign, bool load)
Called at new game and load game.
static void CP_CheckMissionEnd(const campaign_t *campaign)
Check for missions that have a timeout defined.
static void CP_AddCampaignCommands(void)
void CP_EndCampaign(bool won)
Function to handle the campaign end.
bool CP_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
campaign_t * CP_GetCampaign(const char *name)
Returns the campaign pointer from global campaign array.
static const cmdList_t game_commands[]
bool CP_CheckCredits(int costs)
Checks whether you have enough credits for something.
void CP_UpdateCredits(int credits)
Sets credits and update mn_credits cvar.
static void CP_RemoveCampaignCommands(void)
static bool CP_LoadMapDefStatXML(xmlNode_t *parent)
Load mapDef statistics.
cvar_t * cp_missiontest
#define NATIONBELOWLIMITPERCENTAGE
static bool CP_IsBudgetDue(const dateLong_t *oldDate, const dateLong_t *date)
ccs_t ccs
static void CP_AddCampaignCallbackCommands(void)
registers callback commands that are used by campaign
Header file for single player campaign control.
const cgame_import_t * cgi
#define MAX_CREDITS
void CP_ReadCampaignData(const campaign_t *campaign)
Definition cp_parse.cpp:692
void CAP_CheckOverflow(void)
Checks capacity overflows on bases.
void CHAR_InitStartup(void)
Campaign initialization actions for the character module.
void CHAR_Shutdown(void)
Campaign closing actions for the character module.
Header file for character (soldier, alien) related campaign functions.
void E_InitialEmployees(const campaign_t *campaign)
Create initial hireable employees.
void E_InitStartup(void)
This is more or less the initial Bind some of the functions in this file to console-commands that you...
void E_Shutdown(void)
Closing actions for employee-subsystem.
void CL_EventAddMail(const char *eventMailId)
Adds the event mail to the message stack. This message is going to be added to the savegame.
Definition cp_event.cpp:507
void CP_CheckCampaignEvents(campaign_t *campaign)
Definition cp_event.cpp:113
void CL_EventAddMail_f(void)
Definition cp_event.cpp:553
void CP_FreeDynamicEventMail(void)
Make sure, that the linked list is freed with every new game.
Definition cp_event.cpp:67
void CP_TriggerEvent(campaignTriggerEventType_t type, const void *userdata)
Triggers a campaign event with a special type.
Definition cp_event.cpp:310
@ NEW_DAY
Definition cp_event.h:79
void AIM_ShutdownCallbacks(void)
void AIM_InitCallbacks(void)
Header file for menu callback functions used for base and aircraft equip menu.
void GEO_Reset(const char *map)
void GEO_InitStartup(void)
Initialise MAP/Geoscape.
void GEO_CenterOnPoint_f(void)
Switch to next model on 2D and 3D geoscape.
void GEO_Shutdown(void)
Header for Geoscape management.
#define GEO_GetMissionAircraft()
Definition cp_geoscape.h:60
#define GEO_GetSelectedMission()
Definition cp_geoscape.h:59
#define GEO_SetSelectedMission(mission)
Definition cp_geoscape.h:65
void HOS_HospitalRun(void)
Checks health status of all employees in all bases.
void HOS_InitStartup(void)
Initial stuff for hospitals Bind some of the functions in this file to console-commands that you can ...
Header file for hospital related stuff.
void HOS_InitCallbacks(void)
void HOS_ShutdownCallbacks(void)
Header file for menu related console command callbacks.
void INS_UpdateInstallationData(void)
Check if some installation are build.
void INS_InitStartup(void)
Resets console commands.
void INS_Shutdown(void)
Closing operations for installations subsystem.
void INS_InitCallbacks(void)
void INS_ShutdownCallbacks(void)
Header file for menu related console command callbacks.
void AII_RepairAircraft(void)
Repair aircraft.
void AII_UpdateInstallationDelay(void)
Update the installation delay of all slots of a given aircraft.
void BDEF_AutoSelectTarget(void)
Chooses target for all base defences and sam sites.
Header for slot management related stuff.
void BS_InitMarket(const campaign_t *campaign)
sets market prices at start of the game
void CP_CampaignRunMarket(campaign_t *campaign)
make number of items change every day.
void BS_ShutdownCallbacks(void)
Function unregisters the callbacks of the maket UI.
void BS_InitCallbacks(void)
Function registers the callbacks of the maket UI and do initializations.
Header file for menu related console command callbacks.
void MSO_Shutdown(void)
void MS_MessageInit(void)
void CP_CheckBaseAttacks(void)
Check and start baseattack missions.
Campaign mission headers.
Campaign mission triggers.
void CP_SpawnUFOCarrier_f(void)
Spawns a UFO-Carrier mission.
void CP_AttackUFOCarrier_f(void)
Decide whether you hit and destroyed the carrier and spawns a new carrier crash site mission.
Campaign mission headers.
void MIS_InitStartup(void)
Init actions for missions-subsystem.
void CP_InitializeSpawningDelay(void)
Initialize spawning delay.
void BATTLE_Start(mission_t *mission, const battleParam_t *battleParameters)
Select the mission type and start the map from mission definition.
void CP_CreateBattleParameters(mission_t *mission, battleParam_t *param, const aircraft_t *aircraft)
Create parameters needed for battle. This is the data that is used for starting the tactical part of ...
void MIS_Shutdown(void)
Closing actions for missions-subsystem.
bool CP_CheckMissionLimitedInTime(const mission_t *mission)
Check if mission should end because of limited time.
void BATTLE_SetVars(const battleParam_t *battleParameters)
Set some needed cvars from a battle definition.
bool CP_CheckNewMissionDetectedOnGeoscape(void)
Check if mission has been detected by radar.
void CP_MissionStageEnd(const campaign_t *campaign, mission_t *mission)
Determine what action should be performed when a mission stage ends.
void CP_SpawnNewMissions(void)
Spawn new missions.
Campaign missions headers.
#define MIS_Foreach(var)
iterates through missions
void NAT_HandleBudget(const campaign_t *campaign)
Update the nation data from all parsed nation each month.
void NAT_BackupMonthlyData(void)
Backs up each nation's relationship values.
void NAT_UpdateHappinessForAllNations(const float minhappiness)
Lower happiness of nations depending on alien activity.
Definition cp_nation.cpp:84
const nationInfo_t * NAT_GetCurrentMonthInfo(const nation_t *const nation)
Get the current month nation stats.
void NAT_InitStartup(void)
Init actions for nation-subsystem.
void NAT_Shutdown(void)
Closing actions for nation-subsystem.
Nation code.
#define NAT_Foreach(var)
iterates trough nations
Definition cp_nation.h:80
void CP_InitializeXVIOverlay(void)
Initialize XVI overlay on geoscape.
Functions to generate and render overlay for geoscape.
void CP_ScriptSanityCheck(void)
Check the parsed script values for errors after parsing every script file.
Definition cp_parse.cpp:623
void CL_PopupInit(void)
Initialise popups.
Definition cp_popup.cpp:458
void PR_ProductionRun(void)
Checks whether an item is finished.
void PR_ShutdownCallbacks(void)
void PR_InitCallbacks(void)
Header file for menu related console command callbacks for production menu.
bool radarOverlayWasSet
Definition cp_radar.cpp:36
void RADAR_UpdateBaseRadarCoverage_f(void)
Update radar coverage when building/destroying new radar.
Definition cp_radar.cpp:277
void RS_MarkCollected(technology_t *tech)
Marks a give technology as collected.
technology_t * RS_GetTechForItem(const objDef_t *item)
Returns technology entry for an item.
void RS_ResetTechs(void)
This is called everytime RS_ParseTechnologies is called - to prevent cyclic hash tables.
void RS_InitStartup(void)
This is more or less the initial Bind some of the functions in this file to console-commands that you...
int RS_ResearchRun(void)
Checks the research status.
void RS_MarkResearchable(const base_t *base, bool init)
Marks all the techs that can be researched. Automatically researches 'free' techs such as ammo for a ...
void RS_InitTree(const campaign_t *campaign, bool load)
Gets all needed names/file-paths/etc... for each technology entry. Should be executed after the parsi...
void RS_ShutdownCallbacks(void)
void RS_InitCallbacks(void)
Header for menu related research stuff.
void SAV_Init(void)
Register all save-subsystems and init some cvars and commands.
Definition cp_save.cpp:410
void STATS_ShutDown(void)
void STATS_InitStartup(void)
Campaign statistic headers.
void CP_CleanupAircraftTeam(aircraft_t *aircraft, equipDef_t *ed)
Reloads weapons, removes not assigned and resets defaults.
Definition cp_team.cpp:240
void CP_CleanTempInventory(base_t *base)
Clears all containers that are temp containers (see script definition).
Definition cp_team.cpp:273
Team management for the campaign gametype headers.
void CP_TEAM_ShutdownCallbacks(void)
Function that unregisters team (UI) callbacks.
void CP_TEAM_InitCallbacks(void)
Function that registers team (UI) callbacks.
Menu related callback functions for the team menu.
void CP_GameTimeFast(void)
Increase game time speed.
Definition cp_time.cpp:174
void CP_GameTimeStop(void)
Stop game time speed.
Definition cp_time.cpp:126
void CP_UpdateTime(void)
Updates date/time and timescale (=timelapse) on the geoscape menu.
Definition cp_time.cpp:104
void CP_DateConvertLong(const DateTime &date, dateLong_t *dateLong)
Converts a date from the engine in a (longer) human-readable format.
Definition cp_time.cpp:73
bool CP_IsTimeStopped(void)
Check if time is stopped.
Definition cp_time.cpp:139
void CP_GameTimeSlow(void)
Decrease game time speed.
Definition cp_time.cpp:160
void CP_SetGameTime_f(void)
Set a new time game from id.
Definition cp_time.cpp:214
Campaign geoscape time header.
void TR_InitStartup(void)
Defines commands and cvars for the Transfer menu(s).
void TR_TransferRun(void)
Checks whether given transfer should be processed.
void TR_Shutdown(void)
Closing actions for transfer-subsystem.
Header file for Transfer stuff.
void UFO_CampaignRunUFOs(const campaign_t *campaign, int deltaTime)
Make the UFOs run.
Definition cp_ufo.cpp:601
bool UFO_CampaignCheckEvents(void)
Check events for UFOs: Appears or disappears on radars.
Definition cp_ufo.cpp:867
void UFO_InitStartup(void)
Init actions for ufo-subsystem.
Definition cp_ufo.cpp:1011
void UFO_UpdateAlienInterestForAllBasesAndInstallations(void)
Update alien interest for all PHALANX bases.
Definition cp_ufo.cpp:437
void UFO_Shutdown(void)
Closing actions for ufo-subsystem.
Definition cp_ufo.cpp:1023
void UP_Shutdown(void)
int UP_GetUnreadMails(void)
Sets the amount of unread/new mails.
void UP_InitStartup(void)
void UR_Shutdown(void)
Closing actions for ufostoring-subsystem.
void UR_InitStartup(void)
Init actions for ufostoring-subsystem.
void UR_ProcessActive(void)
Function to process active recoveries.
UFO recovery and storing.
void CP_UpdateXVIMapButton(void)
This will hide or show the geoscape button for handling the xvi overlay map.
Definition cp_xvi.cpp:298
void CP_ReduceXVIEverywhere(void)
Reduce XVI everywhere.
Definition cp_xvi.cpp:70
int CP_GetAverageXVIRate(void)
Return the average XVI rate.
Definition cp_xvi.cpp:163
void CP_SpreadXVI(void)
Spread XVI for each mission that needs to be daily spread.
Definition cp_xvi.cpp:181
void CP_XVIInit(void)
Definition cp_xvi.cpp:201
void CP_StartXVISpreading_f(void)
Start XVI spreading in campaign.
Definition cp_xvi.cpp:276
void CP_UpdateNationXVIInfection(void)
Update xviInfection value for each nation, using the XVI overlay.
Definition cp_xvi.cpp:88
Campaign XVI header.
#define CP_IsXVIStarted()
Definition cp_xvi.h:37
#define CVAR_DEVELOPER
Definition cvar.h:45
#define DEBUG_CLIENT
Definition defines.h:59
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
const objDef_t * INVSH_GetItemByID(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
QGL_EXTERN GLuint count
Definition r_gl.h:99
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
XML tag constants for savegame.
#define SAVE_CAMPAIGN_PAID
#define SAVE_CAMPAIGN_GEO_OVERLAY_XVI
#define SAVE_CAMPAIGN_MAP
#define SAVE_CAMPAIGN_MAPDEF
#define SAVE_CAMPAIGN_GEO_OVERLAY_NATION
#define SAVE_CAMPAIGN_DATE
#define SAVE_CAMPAIGN_MAPDEF_COUNT
#define SAVE_CAMPAIGN_ID
#define SAVE_CAMPAIGN_CAMPAIGN
#define SAVE_CAMPAIGN_XVISTARTED
#define SAVE_CAMPAIGN_RADAROVERLAYWASSET
#define SAVE_CAMPAIGN_CIVILIANSKILLED
#define SAVE_CAMPAIGN_MAPDEFSTAT
#define SAVE_CAMPAIGN_GEO_OVERLAY_RADAR
#define SAVE_CAMPAIGN_ALIENSKILLED
#define SAVE_CAMPAIGN_NEXTUNIQUECHARACTERNUMBER
#define SAVE_CAMPAIGN_CREDITS
#define SAVE_CAMPAIGN_MAPDEF_ID
#define SAVE_CAMPAIGN_CL_GEOSCAPE_OVERLAY
#define Q_streq(a, b)
Definition shared.h:136
#define OBJZERO(obj)
Definition shared.h:178
An aircraft with all it's data.
struct base_s * homebase
struct mission_s * mission
alien team category definition
linkedList_t * equipment
A base with all it's data.
Definition cp_base.h:84
char name[MAX_VAR]
Definition cp_base.h:86
equipDef_t storage
Definition cp_base.h:112
A building with all it's data.
Definition cp_building.h:73
buildingStatus_t buildingStatus
Definition cp_building.h:94
char map[MAX_VAR]
int maxAllowedXVIRateUntilLost
float minhappiness
int negativeCreditsUntilLost
char id[MAX_VAR]
client campaign structure
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition cvar.h:71
Human readable time information in the game.
Definition cp_time.h:36
byte month
Definition cp_time.h:38
byte day
Definition cp_time.h:39
short year
Definition cp_time.h:37
int timesAlreadyUsed
Definition q_shared.h:490
char * id
Definition q_shared.h:463
mission definition
Definition cp_missions.h:86
missionResults_t missionResults
bool active
Definition cp_missions.h:90
Detailed information about the nation relationship (currently per month, but could be used elsewhere)...
Definition cp_nation.h:35
float happiness
Definition cp_nation.h:39
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
const char * id
Definition inv_shared.h:268
int baseUpkeep
This is the technology parsed from research.ufo.
@ TEXT_STANDARD
Definition ui_dataids.h:30
#define xmlNode_t
Definition xml.h:24