UFO: Alien Invasion
test_campaign.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 "test_shared.h"
26 #include "../client/DateTime.h"
27 #include "../client/client.h"
28 #include "../client/cl_lua.h"
29 #include "../client/cgame/cl_game.h"
30 #include "../client/renderer/r_state.h" /* r_state */
31 #include "../client/ui/ui_main.h"
32 #include "../client/cgame/campaign/cp_campaign.h"
33 #include "../client/cgame/campaign/cp_geoscape.h"
34 #include "../client/cgame/campaign/cp_hospital.h"
35 #include "../client/cgame/campaign/cp_missions.h"
36 #include "../client/cgame/campaign/cp_nation.h"
37 #include "../client/cgame/campaign/cp_overlay.h"
38 #include "../client/cgame/campaign/cp_ufo.h"
39 #include "../client/cgame/campaign/cp_time.h"
40 #include "../client/cgame/campaign/cp_alien_interest.h"
41 #include "../client/cgame/campaign/cp_auto_mission.h"
42 #include "../client/cgame/campaign/itemcargo.h"
43 #include "../client/cgame/campaign/missions/cp_mission_intercept.h"
44 #include "../shared/parse.h"
45 #include "../shared/images.h"
46 
47 static const int TAG_INVENTORY = 1538;
48 
49 static void FreeInventory (void* data)
50 {
51  Mem_Free(data);
52 }
53 
54 static void* AllocInventoryMemory (size_t size)
55 {
57 }
58 
59 static void FreeAllInventory (void)
60 {
62 }
63 
65 
66 static inline void ResetInventoryList (void)
67 {
69  cls.i.initInventory("testCampaign", &csi, &inventoryImport);
70 }
71 
72 static campaign_t* GetCampaign (void)
73 {
74  return CP_GetCampaign("main");
75 }
76 
77 class CampaignTest: public ::testing::Test {
78 protected:
79  static void SetUpTestCase()
80  {
81  TEST_Init();
82 
83  cl_genericPool = Mem_CreatePool("Client: Generic");
84  cp_campaignPool = Mem_CreatePool("Client: Local (per game)");
85  cp_missiontest = Cvar_Get("cp_missiontest", "0");
86  vid_imagePool = Mem_CreatePool("Vid: Image system");
87 
89  R_FontInit();
90  CL_InitLua();
91  UI_Init();
93 
94  OBJZERO(cls);
95  Com_ParseScripts(false);
96 
97  Cmd_ExecuteString("game_setmode campaign");
98 
99  Cmd_AddCommand("msgoptions_set", Cmd_Dummy_f);
100 
103  }
104 
105  static void TearDownTestCase()
106  {
108  TEST_Shutdown();
109  }
110 
111  void SetUp()
112  {
113  campaign_t* campaign;
114 
117  campaign = GetCampaign();
118  CP_ReadCampaignData(campaign);
119 
121 
123 
124  GEO_Shutdown();
125  GEO_Init(campaign->map);
126 
127  ccs.curCampaign = campaign;
128  }
129 };
130 
131 static installation_t* CreateInstallation (const char* name, const vec2_t pos)
132 {
134  installation_t* installation = INS_Build(installationTemplate, pos, name);
135 
136  /* fake the build time */
137  installation->buildStart = ccs.date.getDateAsDays() - installation->installationTemplate->buildTime;
139 
140  return installation;
141 }
142 
143 static base_t* CreateBase (const char* name, const vec2_t pos, bool fillBase = false)
144 {
145  const campaign_t* campaign = GetCampaign();
146 
147  RS_InitTree(campaign, false);
148  E_InitialEmployees(campaign);
149  base_t* base = B_Build(campaign, pos, name, fillBase);
150 
151  /* First base */
152  if (ccs.campaignStats.basesBuilt == 1)
153  B_SetUpFirstBase(campaign, base);
154 
155  return base;
156 }
157 
158 TEST_F(CampaignTest, testAircraftHandling)
159 {
160  const vec2_t destination = { 10, 10 };
161  base_t* base;
162  aircraft_t* aircraft;
163  aircraft_t* newAircraft;
164  aircraft_t* aircraftTemplate;
165  int firstIdx;
166  int initialCount;
167  int count;
168  int newFound;
169 
170  base = CreateBase("unittestaircraft", destination);
171  ASSERT_TRUE(nullptr != base);
172 
174  aircraft = AIR_GetFirstFromBase(base);
175  ASSERT_TRUE(nullptr != aircraft);
176 
177  /* aircraft should have a template */
178  aircraftTemplate = aircraft->tpl;
179  ASSERT_TRUE(nullptr != aircraftTemplate);
180 
181  firstIdx = aircraft->idx;
182  initialCount = AIR_BaseCountAircraft(base);
183 
184  /* test deletion (part 1) */
185  AIR_DeleteAircraft(aircraft);
187  ASSERT_EQ(count, initialCount - 1);
188 
189  /* test addition (part 1) */
190  newAircraft = AIR_NewAircraft(base, aircraftTemplate);
191  ASSERT_TRUE(nullptr != newAircraft);
193  ASSERT_EQ(count, initialCount);
194 
195  /* new aircraft assigned to the right base */
196  ASSERT_EQ(newAircraft->homebase, base);
197 
198  newFound = 0;
199  AIR_Foreach(a) {
200  /* test deletion (part 2) */
201  ASSERT_NE(firstIdx, a->idx);
202  /* for test addition (part 2) */
203  if (a->idx == newAircraft->idx)
204  newFound++;
205  }
206  /* test addition (part 2) */
207  ASSERT_EQ(newFound, 1);
208 
209  /* check if AIR_Foreach iterates through all aircraft */
210  AIR_Foreach(a) {
212  }
213  aircraft = AIR_GetFirstFromBase(base);
214  ASSERT_TRUE(nullptr == aircraft);
216  ASSERT_EQ(count, 0);
217 
218  /* cleanup for the following tests */
219  E_DeleteAllEmployees(nullptr);
220 
221  base->founded = false;
222 }
223 
224 TEST_F(CampaignTest, testEmployeeHandling)
225 {
226  int i;
227 
228  for (i = 0; i < MAX_EMPL; i++) {
230  if (type != EMPL_ROBOT) {
231  int cnt;
232  Employee* e = E_CreateEmployee(type, nullptr, nullptr);
233  ASSERT_TRUE(nullptr != e);
234 
235  cnt = E_CountUnhired(type);
236  ASSERT_EQ(cnt, 1);
237 
238  E_DeleteEmployee(e);
239 
240  cnt = E_CountUnhired(type);
241  ASSERT_EQ(cnt, 0);
242  }
243  }
244 
245  {
246  const int amount = 3;
247  for (i = 0; i < amount; i++) {
248  Employee* e = E_CreateEmployee(EMPL_SOLDIER, nullptr, nullptr);
249  ASSERT_TRUE(nullptr != e);
250  }
251  {
252  int cnt = 0;
253  E_Foreach(EMPL_SOLDIER, e) {
254  (void)e;
255  cnt++;
256  }
257 
258  ASSERT_EQ(cnt, amount);
259 
260  E_Foreach(EMPL_SOLDIER, e) {
261  ASSERT_TRUE(E_DeleteEmployee(e));
262  }
263 
265  ASSERT_EQ(cnt, 0);
266  }
267  }
268 
269  {
270  const ugv_t* ugvType = Com_GetUGVByID("ugv_ares_w");
271  Employee* e = E_CreateEmployee(EMPL_ROBOT, nullptr, ugvType);
272  ASSERT_TRUE(nullptr != e);
273  ASSERT_TRUE(E_DeleteEmployee(e));
274  }
275 
276  {
277  int i, cnt;
278  for (i = 0; i < 512; i++) {
279  Employee* e = E_CreateEmployee(EMPL_SOLDIER, nullptr, nullptr);
280  ASSERT_TRUE(nullptr != e);
281 
283  ASSERT_EQ(cnt, i + 1);
284  }
285  E_DeleteAllEmployees(nullptr);
286 
288  ASSERT_EQ(cnt, 0);
289  }
290 }
291 
292 TEST_F(CampaignTest, testBaseBuilding)
293 {
294  ccs.credits = 10000000;
295 
296  vec2_t pos = {0, 0};
297  base_t* base = CreateBase("unittestcreatebase", pos);
298 
300 
301  B_Destroy(base);
302 
303  for (int i = 0; i < MAX_EMPL; i++) {
305  ASSERT_EQ(E_CountHired(base, type), 0);
306  }
307 
308  /* cleanup for the following tests */
309  E_DeleteAllEmployees(nullptr);
310 
311  base->founded = false;
312 }
313 
314 TEST_F(CampaignTest, testAutoMissions)
315 {
316  const vec2_t pos = {-73.2, 18.5};
317  base_t* base;
318  missionResults_t result;
319  battleParam_t battleParameters;
320  aircraft_t* aircraft;
321  mission_t* mission;
322  campaign_t* campaign;
323 
324  campaign = GetCampaign();
325  ASSERT_TRUE(campaign != nullptr);
326 
327  OBJZERO(result);
328  OBJZERO(battleParameters);
329 
330  ccs.overallInterest = 36;
332 
333  base = CreateBase("unittestautomission", pos);
334  ASSERT_TRUE(nullptr != base);
335 
336  aircraft = nullptr;
337  AIR_ForeachFromBase(a, base) {
338  if (AIR_GetTeamSize(a) > 0) {
339  aircraft = a;
340  break;
341  }
342  }
343  ASSERT_TRUE(nullptr != aircraft);
344  ASSERT_TRUE(AIR_GetTeamSize(aircraft) > 0);
345 
347  Vector2Copy(pos, mission->pos);
348  mission->posAssigned = true;
349  mission->mapDef = Com_GetMapDefinitionByID("farm2");
350  ASSERT_TRUE(nullptr != mission);
351 
352  CP_CreateBattleParameters(mission, &battleParameters, aircraft);
353  AM_Go(mission, aircraft, campaign, &battleParameters, &result);
354 
355  ASSERT_TRUE(result.state == WON);
356 }
357 
358 TEST_F(CampaignTest, testTransferItem)
359 {
360  const campaign_t* campaign = GetCampaign();
361  const vec2_t pos = {0, 0};
362  const vec2_t posTarget = {51, 0};
363  transfer_t tr;
364 
365  base_t* base = CreateBase("unittesttransferitem", pos);
366  ASSERT_TRUE(nullptr != base);
367  base_t* targetBase = CreateBase("unittesttransferitemtargetbase", posTarget, true);
368  ASSERT_TRUE(nullptr != targetBase);
369  B_SetUpFirstBase(campaign, targetBase);
370 
371  const objDef_t* od = INVSH_GetItemByID("assault");
372  ASSERT_TRUE(nullptr != od);
373 
374  OBJZERO(tr);
375  tr.itemCargo = new ItemCargo();
376  tr.itemCargo->add(od, 1, 0);
377  tr.destBase = targetBase;
378  tr.itemCargo->add(od, 1, 0);
379 
380  transfer_t* transfer = TR_TransferStart(base, tr);
381  ASSERT_TRUE(nullptr != transfer);
382 
383  ASSERT_EQ(LIST_Count(ccs.transfers), 1);
384 
385  transfer->event = ccs.date + DateTime(1, 0);
386 
387  /* check if it's arrived immediately */
388  TR_TransferRun();
389  ASSERT_FALSE(LIST_IsEmpty(ccs.transfers));
390 
391  /* check if it arrives (even a second) before it should */
392  ccs.date += DateTime(1, -1);
393  TR_TransferRun();
394  ASSERT_FALSE(LIST_IsEmpty(ccs.transfers));
395 
396  /* check if it arrived right when it should */
397  ccs.date += DateTime(0, 1);
398  TR_TransferRun();
399  ASSERT_TRUE(LIST_IsEmpty(ccs.transfers));
400 
401  /* Start another transfer to check higher time lapse */
402  transfer = TR_TransferStart(base, tr);
403  ASSERT_TRUE(nullptr != transfer);
404  ASSERT_EQ(LIST_Count(ccs.transfers), 1);
405 
406  transfer->event = ccs.date + DateTime(1, 0);
407 
408  /* check if it arrived when time passed the deadline by days already */
409  ccs.date += DateTime(2, 0);
410  TR_TransferRun();
411  ASSERT_TRUE(LIST_IsEmpty(ccs.transfers));
412 
413  /* Start another transfer to check higher time lapse */
414  transfer = TR_TransferStart(base, tr);
415  ASSERT_TRUE(nullptr != transfer);
416  ASSERT_EQ(LIST_Count(ccs.transfers), 1);
417 
418  transfer->event = ccs.date + DateTime(1, 0);
419 
420  /* check if it arrived when time passed the deadline by days already */
421  ccs.date += DateTime(1, 1);
422  TR_TransferRun();
423  ASSERT_TRUE(LIST_IsEmpty(ccs.transfers));
424 
425 
426  /* cleanup for the following tests */
427  E_DeleteAllEmployees(nullptr);
428  delete tr.itemCargo;
429  tr.itemCargo = nullptr;
430 
431  base->founded = false;
432 }
433 
434 TEST_F(CampaignTest, testUFORecovery)
435 {
436  const vec2_t pos = {0, 0};
437  const aircraft_t* ufo;
438  storedUFO_t* storedUFO;
439  installation_t* installation;
440  DateTime date(ccs.date);
441 
442  ufo = AIR_GetAircraft("craft_ufo_fighter");
443  ASSERT_TRUE(nullptr != ufo);
444 
445  CreateBase("unittestproduction", pos);
446 
447  installation = CreateInstallation("unittestuforecovery", pos);
448 
449  date += DateTime(1, 0);
450  storedUFO = US_StoreUFO(ufo, installation, date, 1.0);
451  ASSERT_TRUE(nullptr != storedUFO);
452  ASSERT_EQ(storedUFO->status, SUFO_RECOVERED);
453 
455 
456  ASSERT_EQ(storedUFO->status, SUFO_RECOVERED);
457 
458  ccs.date += DateTime(1, 0);
459 
461 
462  ASSERT_EQ(storedUFO->status, SUFO_STORED);
463 
464  /* cleanup for the following tests */
465  E_DeleteAllEmployees(nullptr);
466 }
467 
468 TEST_F(CampaignTest, testAlienPSIDevice)
469 {
470  RS_MarkResearchable(nullptr, true);
471 
472  technology_t* alienPsiDevice = RS_GetTechByID("rs_alien_psi_device");
473  RS_MarkOneResearchable(alienPsiDevice);
474  ASSERT_TRUE(alienPsiDevice->statusResearchable);
475 }
476 
477 TEST_F(CampaignTest, testResearch)
478 {
479  RS_MarkResearchable(nullptr, true);
480 
481  technology_t* laserTech = RS_GetTechByID("rs_laser");
482  ASSERT_TRUE(nullptr != laserTech);
483  technology_t* otherLaserTech = RS_GetTechByID("rs_baselaser");
484  ASSERT_TRUE(nullptr != otherLaserTech);
485 
486  const vec2_t pos = {0, 0};
487  base_t* base = CreateBase("unittestbase", pos);
488 
489  ASSERT_TRUE(laserTech->statusResearchable);
490 
491  RS_AssignScientist(laserTech, base);
492 
493  ASSERT_EQ(laserTech->base, base);
494  ASSERT_EQ(laserTech->scientists, 1);
495  ASSERT_EQ(laserTech->statusResearch, RS_RUNNING);
496 
497  ASSERT_FALSE(otherLaserTech->statusResearchable);
498 
499  const int n = laserTech->time * (1.0f / ccs.curCampaign->researchRate);
500  for (int i = 0; i < n; i++) {
501  const int finished = RS_ResearchRun();
502  ASSERT_EQ(finished, 0) << "Did not expect to finish a research (#" << finished << ", i:" << i << ")";
503  }
504 
505  ASSERT_EQ(laserTech->statusResearch, RS_RUNNING);
506  ASSERT_EQ(RS_ResearchRun(), 1);
507  ASSERT_EQ(laserTech->statusResearch, RS_FINISH);
508 
509  ASSERT_TRUE(otherLaserTech->statusResearchable);
510 
511  /* cleanup for the following tests */
512  E_DeleteAllEmployees(nullptr);
513 
514  base->founded = false;
515 }
516 
517 TEST_F(CampaignTest, testProductionItem)
518 {
519  const vec2_t pos = {0, 0};
520  base_t* base;
521  const objDef_t* od;
522  const technology_t* tech;
523  int old;
524  int i, n;
526  production_t* prod;
527 
528  base = CreateBase("unittestproduction", pos);
529 
530  ASSERT_TRUE(B_AtLeastOneExists());
531  ASSERT_TRUE(B_GetBuildingStatus(base, B_WORKSHOP));
532  ASSERT_TRUE(E_CountHired(base, EMPL_WORKER) > 0);
533  ASSERT_TRUE(PR_ProductionAllowed(base));
534 
535  od = INVSH_GetItemByID("assault");
536  ASSERT_TRUE(nullptr != od);
537 
539  old = base->storage.numItems[od->idx];
540  prod = PR_QueueNew(base, &data, 1);
541  ASSERT_TRUE(nullptr != prod);
542  tech = RS_GetTechForItem(od);
543  n = PR_GetRemainingMinutes(prod);
544  i = tech->produceTime / PR_WorkersAvailable(base);
545  ASSERT_EQ(i, PR_GetRemainingHours(prod));
546  for (i = 0; i < n; i++) {
548  }
549 
550  ASSERT_EQ(old, base->storage.numItems[od->idx]);
552  ASSERT_EQ(old + 1, base->storage.numItems[od->idx]);
553 
554  /* cleanup for the following tests */
555  E_DeleteAllEmployees(nullptr);
556 
557  base->founded = false;
558 }
559 
560 TEST_F(CampaignTest, testProductionAircraft)
561 {
562  const vec2_t pos = {0, 0};
563  base_t* base;
564  const aircraft_t* aircraft;
565  int old;
566  int i, n;
568  production_t* prod;
569 
570  base = CreateBase("unittestproduction", pos);
571 
572  ASSERT_TRUE(B_AtLeastOneExists());
573  ASSERT_TRUE(B_GetBuildingStatus(base, B_WORKSHOP));
574  ASSERT_TRUE(E_CountHired(base, EMPL_WORKER) > 0);
575  ASSERT_TRUE(PR_ProductionAllowed(base));
576 
577  /* Check for production requirements */
578  aircraft = AIR_GetAircraft("craft_inter_stingray");
579  ASSERT_TRUE(nullptr != aircraft);
581  /* no antimatter */
582  ASSERT_TRUE(nullptr == PR_QueueNew(base, &data, 1));
583 
584  old = CAP_GetCurrent(base, CAP_AIRCRAFT_SMALL);
585  aircraft = AIR_GetAircraft("craft_inter_stiletto");
586  ASSERT_TRUE(nullptr != aircraft);
588  prod = PR_QueueNew(base, &data, 1);
589  ASSERT_TRUE(nullptr != prod);
590 
591  n = PR_GetRemainingMinutes(prod);
592  i = aircraft->tech->produceTime / PR_WorkersAvailable(base);
593  ASSERT_EQ(i, PR_GetRemainingHours(prod));
594  for (i = 0; i < n; i++) {
596  }
597 
598  ASSERT_EQ(old, CAP_GetCurrent(base, CAP_AIRCRAFT_SMALL));
600  ASSERT_EQ(old + 1, CAP_GetCurrent(base, CAP_AIRCRAFT_SMALL));
601 
602  /* cleanup for the following tests */
603  E_DeleteAllEmployees(nullptr);
604 
605  base->founded = false;
606 }
607 
608 TEST_F(CampaignTest, testDisassembly)
609 {
610  const vec2_t pos = {0, 0};
611  base_t* base;
612  const aircraft_t* ufo;
613  int old;
614  int i, n;
615  storedUFO_t* storedUFO;
617  installation_t* installation;
618  production_t* prod;
619 
620  base = CreateBase("unittestproduction", pos);
621 
622  ASSERT_TRUE(B_AtLeastOneExists());
623  ASSERT_TRUE(B_GetBuildingStatus(base, B_WORKSHOP));
624  ASSERT_TRUE(E_CountHired(base, EMPL_WORKER) > 0);
625  ASSERT_TRUE(PR_ProductionAllowed(base));
626 
627  ufo = AIR_GetAircraft("craft_ufo_fighter");
628  ASSERT_TRUE(nullptr != ufo);
629 
630  installation = CreateInstallation("unittestproduction", pos);
631 
632  storedUFO = US_StoreUFO(ufo, installation, ccs.date, 1.0);
633  ASSERT_TRUE(nullptr != storedUFO);
634  ASSERT_EQ(storedUFO->status, SUFO_RECOVERED);
636  prod = PR_QueueNew(base, &data, 1);
637  ASSERT_TRUE(nullptr != prod);
638 
639  old = CAP_GetCurrent(base, CAP_ITEMS);
640  n = PR_GetRemainingMinutes(prod);
641  i = storedUFO->comp->time / PR_WorkersAvailable(base);
642  ASSERT_EQ(i, PR_GetRemainingHours(prod));
643  for (i = 0; i < n; i++) {
645  }
646 
647  ASSERT_EQ(old, CAP_GetCurrent(base, CAP_ITEMS));
649  ASSERT_NE(old, CAP_GetCurrent(base, CAP_ITEMS));
650 
651  /* cleanup for the following tests */
652  E_DeleteAllEmployees(nullptr);
653 
654  base->founded = false;
655 }
656 
658 {
659  vec2_t pos;
660  bool coast = false;
661 
662  Vector2Set(pos, -51, 0);
663  ASSERT_TRUE(MapIsWater(GEO_GetColor(pos, MAPTYPE_TERRAIN, nullptr)));
664 
665  Vector2Set(pos, 51, 0);
666  ASSERT_TRUE(!MapIsWater(GEO_GetColor(pos, MAPTYPE_TERRAIN, nullptr)));
667 
668  Vector2Set(pos, 20, 20);
669  ASSERT_TRUE(MapIsWater(GEO_GetColor(pos, MAPTYPE_TERRAIN, nullptr)));
670 
671  Vector2Set(pos, -45, 2.5);
672  ASSERT_TRUE(!MapIsWater(GEO_GetColor(pos, MAPTYPE_TERRAIN, &coast)));
673  ASSERT_TRUE(coast);
674 }
675 
676 TEST_F(CampaignTest, testAirFight)
677 {
678  const vec2_t destination = { 10, 10 };
679  /* just some random delta time value that is high enough
680  * to ensure that all the weapons are reloaded */
681  const int deltaTime = 1000;
682 
683  campaign_t* campaign = GetCampaign();
684 
685  base_t* base = CreateBase("unittestairfight", destination);
686  ASSERT_TRUE(nullptr != base);
687 
688  int cnt = AIR_BaseCountAircraft(base);
689  int i = 0;
690  AIR_ForeachFromBase(a, base)
691  i++;
692  ASSERT_EQ(i, cnt);
693 
694  aircraft_t* aircraft = AIR_GetFirstFromBase(base);
695  ASSERT_TRUE(nullptr != aircraft);
696  aircraft->status = AIR_IDLE;
697  ASSERT_TRUE(AIR_IsAircraftOnGeoscape(aircraft));
698 
699  /* ensure that a FIGHTER can spawn */
700  ufoType_t ufoTypes[UFO_MAX];
701  ASSERT_NE(0, UFO_GetAvailableUFOsForMission(INTERESTCATEGORY_INTERCEPT, ufoTypes, false));
702  const aircraft_t* ufoTemplate = UFO_GetByType(ufoTypes[0]); /* the first interceptor will do */
703  ASSERT_TRUE(nullptr != ufoTemplate);
704  ccs.overallInterest = ufoTemplate->ufoInterestOnGeoscape + 1;
705 
706  /* prepare the mission */
708  ASSERT_TRUE(nullptr != mission);
709  ASSERT_EQ(mission->stage, STAGE_NOT_ACTIVE);
710  CP_InterceptNextStage(mission);
711  ASSERT_EQ(mission->stage, STAGE_COME_FROM_ORBIT);
712  CP_InterceptNextStage(mission);
713  ASSERT_EQ(mission->stage, STAGE_INTERCEPT);
714  aircraft_t* ufo = mission->ufo;
715  ASSERT_TRUE(nullptr != ufo);
716  ufo->ufotype = ufoTypes[0];
717  /* we have to update the routing data here to be sure that the ufo is
718  * not spawned on the other side of the globe */
719  Vector2Copy(destination, ufo->pos);
720  UFO_SendToDestination(ufo, destination);
721  ASSERT_TRUE(VectorEqual(ufo->pos, base->pos));
722  ASSERT_TRUE(VectorEqual(ufo->pos, aircraft->pos));
723 
724  ASSERT_TRUE(aircraft->maxWeapons > 0);
725  for (i = 0; i < aircraft->maxWeapons; i++)
726  ASSERT_TRUE(aircraft->weapons[i].delayNextShot == 0);
727 
728  /* search a target */
729  UFO_CampaignRunUFOs(campaign, deltaTime);
730  ASSERT_TRUE(nullptr != ufo->aircraftTarget);
731 
732  /* ensure that one hit will destroy the craft */
733  ufo->aircraftTarget->damage = 1;
734  srand(1);
735  /* don't take any pilot skill into account here */
736  OBJZERO(ufo->aircraftTarget->pilot->chr.score.skills);
737  UFO_CheckShootBack(campaign, ufo, ufo->aircraftTarget);
738 
739  /* one projectile should be spawned */
740  ASSERT_EQ(ccs.numProjectiles, 1);
741  AIRFIGHT_CampaignRunProjectiles(campaign, deltaTime);
742  /* don't use mission pointer from here it might been removed */
743 
744  /* target is destroyed */
745  ASSERT_TRUE(nullptr == ufo->aircraftTarget);
746 
747  /* one aircraft less */
748  ASSERT_EQ(cnt - 1, AIR_BaseCountAircraft(base));
749 
750  /* cleanup for the following tests */
751  E_DeleteAllEmployees(nullptr);
752 
753  base->founded = false;
754 }
755 
756 TEST_F(CampaignTest, testRadar)
757 {
758  const vec2_t destination = { 10, 10 };
759  ufoType_t ufoTypes[UFO_MAX];
760  ASSERT_NE(0, UFO_GetAvailableUFOsForMission(INTERESTCATEGORY_INTERCEPT, ufoTypes, false));
761 
762  base_t* base = CreateBase("unittestradar", destination);
764  aircraft_t* ufo = UFO_AddToGeoscape(ufoTypes[0], destination, mission);
765  Vector2Copy(destination, ufo->pos);
766  UFO_SendToDestination(ufo, destination);
767  ASSERT_TRUE(VectorEqual(ufo->pos, base->pos));
768  ASSERT_TRUE(VectorEqual(ufo->pos, ufo->pos));
769  /* to ensure that the UFOs are really detected when they are in range */
770  base->radar.ufoDetectionProbability = 1.0;
771  ASSERT_TRUE(RADAR_CheckUFOSensored(&base->radar, base->pos, ufo, false));
772 
773  /* cleanup for the following tests */
774  E_DeleteAllEmployees(nullptr);
775 
776  base->founded = false;
777 }
778 
779 TEST_F(CampaignTest, testNation)
780 {
781  const nation_t* nation;
782  campaign_t* campaign;
783 
784  nation = NAT_GetNationByID("europe");
785  ASSERT_TRUE(nullptr != nation);
786 
787  campaign = GetCampaign();
788 
789  NAT_HandleBudget(campaign);
791 }
792 
793 TEST_F(CampaignTest, testMarket)
794 {
795  campaign_t* campaign;
796 
797  campaign = GetCampaign();
798 
799  RS_InitTree(campaign, false);
800 
801  BS_InitMarket(campaign);
802 
803  CP_CampaignRunMarket(campaign);
805 }
806 
807 TEST_F(CampaignTest, testSaveLoad)
808 {
809  const vec2_t pos = {0, 0};
810  base_t* base;
811  campaign_t* campaign;
812 
813  campaign = GetCampaign();
814 
815  SAV_Init();
816 
817  ccs.curCampaign = campaign;
818 
819  Cvar_Set("save_compressed", "0");
820 
821  base = CreateBase("unittestbase", pos);
822 
823  {
824  ASSERT_TRUE(base->founded);
825  ASSERT_EQ(base->baseStatus, BASE_WORKING);
826 
827  Cmd_ExecuteString("game_quicksave");
828  }
829  {
830  B_Destroy(base);
831 
832  ASSERT_EQ(base->baseStatus, BASE_DESTROYED);
833 
834  E_DeleteAllEmployees(nullptr);
835 
836  B_SetName(base, "unittestbase2");
837  }
838 #if 0
839  {
840  ResetCampaignData();
841 
842  Cmd_ExecuteString("game_quickload");
843 
846  ASSERT_EQ(base->baseStatus, BASE_WORKING);
847  ASSERT_STREQ(base->name, "unittestbase");
848 
849  B_Destroy(base);
850 
851  E_DeleteAllEmployees(nullptr);
852  }
853 #endif
854  base->founded = false;
855 }
856 
857 TEST_F(CampaignTest, testSaveMassEmployees)
858 {
859  campaign_t* campaign = GetCampaign();
860 
861  SAV_Init();
862 
863  ccs.curCampaign = campaign;
864 
865  Cvar_Set("save_compressed", "0");
866 
867  const vec2_t pos = {0, 0};
868  base_t* base = CreateBase("unittestmassemployees", pos);
869 
870  nation_t* nation = NAT_GetNationByID("europe");
871  ASSERT_TRUE(nullptr != nation);
872 
873  const int employees = 10000;
874  for (int i = 0; i < employees; i++) {
875  Employee* e = E_CreateEmployee(EMPL_SOLDIER, nation);
876  if (CAP_GetFreeCapacity(base, CAP_EMPLOYEES) > 0) {
877  ASSERT_TRUE(E_HireEmployee(base, e));
878  }
879  }
880 
881  Cmd_ExecuteString("game_quicksave");
882 
883  /* cleanup for the following tests */
884  E_DeleteAllEmployees(nullptr);
885 
886  base->founded = false;
887 }
888 
889 TEST_F(CampaignTest, testLoadMassEmployees)
890 {
891  Cmd_ExecuteString("game_quickload");
892 
893  /* cleanup for the following tests */
894  E_DeleteAllEmployees(nullptr);
895 }
896 
897 TEST_F(CampaignTest, testCampaignRun)
898 {
899  const vec2_t destination = { 10, 10 };
900  const int days = 10;
901  const int seconds = days * DateTime::SECONDS_PER_DAY;
902 
903  base_t* base = CreateBase("unittestcampaignrun", destination);
904 
905  campaign_t* campaign = GetCampaign();
906 
907  RS_InitTree(campaign, false);
908 
909  BS_InitMarket(campaign);
910 
911  int startDay = ccs.date.getDateAsDays();
912  for (int i = 0; i < seconds; i++) {
913  ccs.gameTimeScale = 1;
914  CP_CampaignRun(campaign, 1);
915  }
916  ASSERT_EQ(ccs.date.getDateAsDays() - startDay, days);
917 
918  /* cleanup for the following tests */
919  E_DeleteAllEmployees(nullptr);
920 
921  base->founded = false;
922 }
923 
925 {
926  int i;
927  aircraft_t* ufo;
928  const char* error;
929 
930  ccs.curCampaign = nullptr;
931  ASSERT_TRUE(SAV_GameLoad("unittest1", &error));
932  ASSERT_TRUE(nullptr != ccs.curCampaign);
933 
934  i = 0;
935  ufo = nullptr;
936  while ((ufo = UFO_GetNextOnGeoscape(ufo)) != nullptr)
937  i++;
938 
939  /* there should be one ufo on the geoscape */
940  ASSERT_EQ(i, 1);
941 }
942 
943 TEST_F(CampaignTest, testDateHandling)
944 {
945  DateTime date = DateTime(300, 300);
946 
947  ccs.date = date;
948 
949  ASSERT_TRUE(date <= ccs.date);
950  ASSERT_FALSE(ccs.date > date);
951 
952  date = DateTime(299, 310);
953 
954  ASSERT_TRUE(date <= ccs.date);
955  ASSERT_TRUE(ccs.date > date);
956 
957  date = DateTime(301, 0);
958 
959  ASSERT_FALSE(date <= ccs.date);
960  ASSERT_FALSE(ccs.date > date);
961 
962  date = DateTime(300, 299);
963 
964  ASSERT_TRUE(date <= ccs.date);
965  ASSERT_TRUE(ccs.date > date);
966 
967  date = DateTime(300, 301);
968 
969  ASSERT_FALSE(date <= ccs.date);
970  ASSERT_FALSE(ccs.date > date);
971 }
972 
976 TEST_F(CampaignTest, testCampaignDateHandling)
977 {
978  campaign_t* campaign;
979  base_t* base;
980  const vec2_t destination = { 10, 10 };
981 
982  base = CreateBase("unittestcampaigntime", destination);
983 
984  campaign = GetCampaign();
985 
986  RS_InitTree(campaign, false);
987 
988  BS_InitMarket(campaign);
989 
990  /* one hour till month change */
991  ccs.date = DateTime(30, 23 * 60 * 60);
993  ccs.gameLapse = 7;
994  ccs.paid = true;
995  CP_UpdateTime();
996  CP_CampaignRun(campaign, 1);
997  ASSERT_FALSE(ccs.paid);
998  ASSERT_TRUE(CP_IsTimeStopped());
999 
1000  /* cleanup for the following tests */
1001  E_DeleteAllEmployees(nullptr);
1002 
1003  base->founded = false;
1004 }
1005 
1006 TEST_F(CampaignTest, testHospital)
1007 {
1008  base_t* base;
1009  const vec2_t destination = { 10, 10 };
1010  int i, n;
1011 
1012  base = CreateBase("unittesthospital", destination);
1013 
1014  n = 0;
1015  /* hurt all employees */
1016  for (i = 0; i < MAX_EMPL; i++) {
1018  E_Foreach(type, employee) {
1019  if (!employee->isHired())
1020  continue;
1021  employee->chr.HP = employee->chr.maxHP - 10;
1022  n++;
1023  }
1024  }
1025  ASSERT_NE(n, 0);
1026 
1027  HOS_HospitalRun();
1028 
1029  for (i = 0; i < MAX_EMPL; i++) {
1031  E_Foreach(type, employee) {
1032  if (!employee->isHired())
1033  continue;
1034  ASSERT_NE(employee->chr.HP, employee->chr.maxHP - 10) << employee->chr.HP << "/" << employee->chr.maxHP;
1035  }
1036  }
1037 
1038  /* cleanup for the following tests */
1039  E_DeleteAllEmployees(nullptr);
1040 
1041  base->founded = false;
1042 }
1043 
1044 TEST_F(CampaignTest, testBuildingConstruction)
1045 {
1046  const vec2_t pos = {0, 0};
1047  int x, y;
1048  base_t* base;
1049  const building_t* buildingTemplate;
1050  building_t* entrance, *building1, *building2;
1051 
1052  /* day 0 has special meaning! */
1053  /* if building->startTime is 0 no buildTime checks done! */
1054  ccs.date += DateTime(1, 0);
1055  base = CreateBase("unittestbuildingconstruction1", pos);
1056  ASSERT_TRUE(nullptr != base);
1057  base = CreateBase("unittestbuildingconstruction2", pos);
1058  ASSERT_TRUE(nullptr != base);
1059 
1060  /* base should have exactly one building: entrance */
1061  ASSERT_EQ(ccs.numBuildings[base->idx], 1);
1062  entrance = &ccs.buildings[base->idx][0];
1063 
1064  /* try to build powerplant that is not connected */
1065  buildingTemplate = B_GetBuildingTemplate("building_powerplant");
1066  ASSERT_TRUE(nullptr != buildingTemplate);
1067 
1068  /* select position */
1069  x = entrance->pos[0];
1070  y = entrance->pos[1];
1071  ASSERT_EQ(entrance, base->map[y][x].building);
1072  if (x >= 2)
1073  x -= 2;
1074  else
1075  x += 2;
1076  /* reset blocked status if set */
1077  base->map[y][x].blocked = false;
1078  /* try to build (should fail) */
1079  building1 = B_BuildBuilding(base, buildingTemplate, x, y);
1080  ASSERT_TRUE(nullptr == building1);
1081 
1082  /* next to the entrance it should succeed */
1083  x = (x + entrance->pos[0]) /2;
1084  base->map[y][x].blocked = false;
1085  building1 = B_BuildBuilding(base, buildingTemplate, x, y);
1086  ASSERT_TRUE(nullptr != building1);
1087 
1088  /* try to build to first pos again (still fail, conecting building not ready) */
1089  if (x < entrance->pos[0])
1090  x--;
1091  else
1092  x++;
1093  building2 = B_BuildBuilding(base, buildingTemplate, x, y);
1094  ASSERT_TRUE(nullptr == building2);
1095  /* roll time one day before building finishes */
1096  ccs.date += DateTime(building1->buildTime - 1, 0);
1098  /* building should be under construction */
1099  ASSERT_EQ(building1->buildingStatus, B_STATUS_UNDER_CONSTRUCTION);
1100  /* step a day */
1101  ccs.date += DateTime(1, 0);
1103  /* building should be ready */
1104  ASSERT_EQ(building1->buildingStatus, B_STATUS_WORKING);
1105 
1106  /* try build other building (now it should succeed) */
1107  building2 = B_BuildBuilding(base, buildingTemplate, x, y);
1108  ASSERT_TRUE(nullptr != building2);
1109 
1110  /* try to destroy the second (should success) */
1111  ASSERT_TRUE(B_BuildingDestroy(building2));
1112  /* rebuild */
1113  building2 = B_BuildBuilding(base, buildingTemplate, x, y);
1114  ASSERT_TRUE(nullptr != building2);
1115 
1116  /* try to destroy the first (should fail) */
1117  ASSERT_FALSE(B_BuildingDestroy(building1));
1118  /* build up the second */
1119  ccs.date += DateTime(building2->buildTime, 0);
1121  /* try to destroy the first (should fail) */
1122  ASSERT_FALSE(B_BuildingDestroy(building1));
1123  /* try to destroy the second (should succeess) */
1124  ASSERT_TRUE(B_BuildingDestroy(building2));
1125  /* try to destroy the first (should succeed) */
1126  ASSERT_TRUE(B_BuildingDestroy(building1));
1127 
1128  /* cleanup for the following tests */
1129  E_DeleteAllEmployees(nullptr);
1130 
1131  base->founded = false;
1132 }
1133 
1134 /* https://sourceforge.net/tracker/index.php?func=detail&aid=3090011&group_id=157793&atid=805242 */
1135 TEST_F(CampaignTest, test3090011)
1136 {
1137  const char* error = nullptr;
1138  bool success;
1139 
1140  success = SAV_GameLoad("3090011", &error);
1141  ASSERT_TRUE(success) << error;
1142 }
1143 
1144 static bool skipTest (const mapDef_t* md)
1145 {
1146  const char* map = md->id;
1147  return Q_streq(map, "baseattack") || Q_streq(map, "rescue") || Q_streq(map, "alienbase");
1148 }
1149 
1150 TEST_F(CampaignTest, testTerrorMissions)
1151 {
1152  int numUfoTypes;
1153  ufoType_t ufoTypes[UFO_MAX];
1154  mapDef_t* md;
1155  int i;
1156 
1157  /* Set overall interest level so every UFO can be used for missions */
1158  const short ufoIdsNum = Com_GetUfoIdsNum();
1159  for (i = 0; i < ufoIdsNum; i++) {
1160  ufoType_t ufoType = i;
1161  const aircraft_t* ufo = UFO_GetByType(ufoType);
1162 
1163  if (!ufo)
1164  continue;
1165 
1167  }
1168 
1169  /* Search without UFO */
1170  LIST_Foreach(ccs.cities, city_t, city) {
1171  mission_t mission;
1172  OBJZERO(mission);
1173  ASSERT_TRUE(CP_ChooseMap(&mission, city->pos)) << "could not find a map for city " << city->id;
1174  }
1175 
1176  /* Search with UFOs available for Terror missions */
1177  numUfoTypes = UFO_GetAvailableUFOsForMission(INTERESTCATEGORY_TERROR_ATTACK, ufoTypes, false);
1178  ASSERT_NE(0, numUfoTypes);
1179  for (i = 0; i < numUfoTypes; i++) {
1180  ufoType_t ufoType = i;
1181  mission_t mission;
1182  aircraft_t* ufo = UFO_AddToGeoscape(ufoTypes[ufoType], nullptr, &mission);
1183 
1184  OBJZERO(mission);
1185  mission.ufo = ufo;
1186  ASSERT_TRUE(nullptr != ufo);
1187  ufo->mission = &mission;
1188 
1189  LIST_Foreach(ccs.cities, city_t, city) {
1190  mission.mapDef = nullptr;
1191 #ifdef TEST_BIGUFOS
1192  ASSERT_TRUE(CP_ChooseMap(&mission, city->pos)) << "could not find map for city " << city->id << " with ufo: " << ufo->id;
1193 #else
1194  CP_ChooseMap(&mission, city->pos);
1195 #endif
1196  }
1197 
1199  }
1200 
1202  /* skip mapDefs that were used */
1203  if (md->timesAlreadyUsed > 0)
1204  continue;
1205  /* skip special mapDefs */
1206  if (skipTest(md))
1207  continue;
1208  /* skip mapDefs which don't support UFO types that do terror missions */
1209  if (!LIST_IsEmpty(md->ufos)) {
1210  bool found = false;
1211  for (i = 0; i < numUfoTypes; i++) {
1212  ufoType_t ufoType = i;
1213  const aircraft_t* ufo = UFO_GetByType(ufoTypes[ufoType]);
1214 
1215  if (!ufo)
1216  continue;
1217 
1218  if (LIST_ContainsString(md->ufos, ufo->id)) {
1219  found = true;
1220  break;
1221  }
1222  }
1223  if (!found)
1224  continue;
1225  }
1226  ASSERT_TRUE(va("%s wasn't used", md->id));
1227  }
1228 }
1229 
1230 TEST_F(CampaignTest, testRandomPosMissions)
1231 {
1232  const mapDef_t* md;
1233 
1235  if (!skipTest(md)) {
1236  mission_t mission;
1237  bool result;
1238  OBJZERO(mission);
1239  result = CP_GetRandomPosOnGeoscapeWithParameters(mission.pos, md->terrains, md->cultures, md->populations, nullptr);
1240  ASSERT_TRUE(result) << "could not find a mission for mapdef " << md->id;
1241  }
1242  }
1243 }
1244 
1246 static void testEventTrigger_f (void)
1247 {
1248  testEventTriggerCalled = true;
1249 }
1250 
1251 TEST_F(CampaignTest, testEventTrigger)
1252 {
1253  testEventTriggerCalled = false;
1254  for (int i = 0; i < 60; i++) {
1256  ccs.date += DateTime(1, 0);
1257  }
1258  Cmd_AddCommand("test_eventtrigger", testEventTrigger_f);
1260  OBJZERO(*event);
1261  event->active = true;
1262  event->type = UFO_DETECTION;
1263  event->id = Mem_StrDup("test_eventtrigger");
1264  event->command = Mem_StrDup("test_eventtrigger");
1265  event->require = Mem_StrDup("ufo[craft_ufo_harvester]");
1266  CP_TriggerEvent(UFO_DETECTION, "craft_ufo_harvester");
1267  ASSERT_TRUE(testEventTriggerCalled);
1268  testEventTriggerCalled = false;
1270  ASSERT_FALSE(testEventTriggerCalled);
1271  event->once = true;
1272  CP_TriggerEvent(UFO_DETECTION, "craft_ufo_harvester");
1273  ASSERT_TRUE(testEventTriggerCalled);
1274  testEventTriggerCalled = false;
1275  CP_TriggerEvent(UFO_DETECTION, "craft_ufo_harvester");
1276  ASSERT_FALSE(testEventTriggerCalled);
1278  Cmd_RemoveCommand("test_eventtrigger");
1279 }
1280 
1281 TEST_F(CampaignTest, testAssembleMap)
1282 {
1283  const int expected = 22;
1284  const int maxSize = BASE_SIZE * BASE_SIZE;
1285  ASSERT_TRUE(maxSize >= expected);
1286 
1287  const vec2_t destination = { 10, 10 };
1288  base_t* base = CreateBase("unittestassemble", destination);
1289  ASSERT_TRUE(nullptr != base);
1290  char maps[2048];
1291  char coords[2048];
1292 
1293  ASSERT_TRUE(B_AssembleMap(maps, sizeof(maps), coords, sizeof(coords), base));
1294  const char* str = coords;
1295  int coordsAmount = 0;
1296  do {
1297  Com_Parse(&str);
1298  if (str != nullptr)
1299  ++coordsAmount;
1300  } while (str != nullptr);
1301 
1302  str = maps;
1303  int mapsAmount = 0;
1304  do {
1305  Com_Parse(&str);
1306  if (str != nullptr)
1307  ++mapsAmount;
1308  } while (str != nullptr);
1309 
1310  /* we have three components, x, y and z for the coordinates */
1311  ASSERT_EQ(coordsAmount / 3, expected) << "coords have " << coordsAmount << " entries: '" << coords << "'";
1312  ASSERT_EQ(mapsAmount, expected) << "maps have " << mapsAmount << " entries: '"<< maps << "'";
1313 }
1314 
1315 TEST_F(CampaignTest, testGeoscapeMaps)
1316 {
1317  const char* types[] = {"terrain", "culture", "population", "nations", nullptr};
1318  for (int i = 0; i < ccs.numCampaigns; i++) {
1319  const campaign_t& c = ccs.campaigns[i];
1320  int refW = -1;
1321  int refH = -1;
1322 
1323  for (const char **t = types; *t; ++t) {
1324  const char *image = va("pics/geoscape/%s_%s", c.map, *t);
1325  SDL_Surface *surf = Img_LoadImage(image);
1326  ASSERT_TRUE(surf != nullptr);
1327  const int w = surf->w;
1328  const int h = surf->h;
1329  if (refH == -1) {
1330  refH = h;
1331  refW = w;
1332  }
1333  SDL_FreeSurface(surf);
1334  ASSERT_EQ(refH, h);
1335  ASSERT_EQ(refW, w);
1336  }
1337  }
1338 }
Transfer information (they are being stored in ccs.transfers).
Definition: cp_transfer.h:33
bool CP_IsTimeStopped(void)
Check if time is stopped.
Definition: cp_time.cpp:139
void SAV_Init(void)
Register all save-subsystems and init some cvars and commands.
Definition: cp_save.cpp:413
struct base_s * homebase
Definition: cp_aircraft.h:150
int overallInterest
Definition: cp_campaign.h:239
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition: cmd.cpp:744
production_t * PR_QueueNew(base_t *base, const productionData_t *data, signed int amount)
Add a new item to the bottom of the production queue.
Definition: cp_produce.cpp:234
int numProjectiles
Definition: cp_campaign.h:305
aircraftStatus_t status
Definition: cp_aircraft.h:126
nation_t * NAT_GetNationByID(const char *nationID)
Return a nation-pointer by the nations id.
Definition: cp_nation.cpp:64
virtual bool add(const objDef_t *od, int amount, int looseAmount)
Add items to the cargo.
Definition: itemcargo.cpp:39
missionStage_t stage
Definition: cp_missions.h:99
class ItemCargo * itemCargo
Definition: cp_transfer.h:39
const installationTemplate_t * INS_GetInstallationTemplateByType(installationType_t type)
Returns the installation Template for a given installation type.
void Cmd_RemoveCommand(const char *cmdName)
Removes a command from script interface.
Definition: cmd.cpp:786
void B_UpdateBuildingConstructions(void)
Updates base data.
Definition: cp_base.cpp:2009
const objDef_t * INVSH_GetItemByID(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn&#39;t found.
Definition: inv_shared.cpp:282
mission definition
Definition: cp_missions.h:86
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
bool B_GetBuildingStatus(const base_t *const base, const buildingType_t buildingType)
Get the status associated to a building.
Definition: cp_base.cpp:478
bool CP_ChooseMap(mission_t *mission, const vec2_t pos)
Choose a map for given mission.
aircraft_t * AIR_NewAircraft(base_t *base, const aircraft_t *aircraftTemplate)
Places a new aircraft in the given base.
static base_t * CreateBase(const char *name, const vec2_t pos, bool fillBase=false)
void UI_Init(void)
Definition: ui_main.cpp:278
void GEO_Init(const char *map)
void CP_InterceptNextStage(mission_t *mission)
Determine what action should be performed when a Intercept mission stage ends.
void RS_MarkOneResearchable(technology_t *tech)
Marks one tech as researchable.
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
void INT_ResetAlienInterest(void)
Initialize alien interest values and mission cycle.
#define E_Foreach(employeeType, var)
Definition: cp_employee.h:122
Holds all information for the production of one item-type.
Definition: cp_produce.h:59
int maxWeapons
Definition: cp_aircraft.h:145
static void FreeAllInventory(void)
char * id
Definition: cp_aircraft.h:120
char map[MAX_VAR]
Definition: cp_campaign.h:178
void INS_UpdateInstallationData(void)
Check if some installation are build.
bool paid
Definition: cp_campaign.h:269
int gameTimeScale
Definition: cp_campaign.h:265
void UFO_CampaignRunUFOs(const campaign_t *campaign, int deltaTime)
Make the UFOs run.
Definition: cp_ufo.cpp:601
csi_t csi
Definition: common.cpp:39
#define Mem_PoolAlloc(size, pool, tagNum)
Definition: mem.h:41
static const inventoryImport_t inventoryImport
struct base_s * base
Definition: cp_research.h:169
void GEO_Shutdown(void)
short ufoType_t
Definition: scripts.h:145
void RS_MarkResearchable(const base_t *base, bool init)
Marks all the techs that can be researched. Automatically researches &#39;free&#39; techs such as ammo for a ...
base_t * destBase
Definition: cp_transfer.h:34
Class describing a point of time.
Definition: DateTime.h:30
#define BASE_SIZE
Definition: cp_base.h:38
storedUFO_t * US_StoreUFO(const aircraft_t *ufoTemplate, installation_t *installation, DateTime &date, float condition)
Adds an UFO to the storage.
voidpf void uLong size
Definition: ioapi.h:42
#define B_AtLeastOneExists()
Definition: cp_base.h:55
void Com_ParseScripts(bool onlyServer)
Definition: scripts.cpp:3619
char name[MAX_VAR]
Definition: cp_base.h:86
buildingStatus_t buildingStatus
Definition: cp_building.h:94
linkedList_t * ufos
Definition: q_shared.h:491
aircraft_t * UFO_AddToGeoscape(ufoType_t ufoType, const vec2_t destination, mission_t *mission)
Add a UFO to geoscape.
Definition: cp_ufo.cpp:773
QGL_EXTERN GLsizei const GLvoid * data
Definition: r_gl.h:89
void CP_ResetCampaignData(void)
Will clear most of the parsed singleplayer data.
const aircraft_t * AIR_GetAircraft(const char *name)
Searches the global array of aircraft types for a given aircraft.
const byte * GEO_GetColor(const vec2_t pos, mapType_t type, bool *coast)
Returns the color value from geoscape of a certain mask (terrain, culture or population) at a given p...
InventoryInterface i
Definition: client.h:101
void BS_InitMarket(const campaign_t *campaign)
sets market prices at start of the game
Definition: cp_market.cpp:526
ufoType_t ufotype
Definition: cp_aircraft.h:125
aircraft_t * UFO_GetNextOnGeoscape(aircraft_t *lastUFO)
Definition: cp_ufo.cpp:66
#define PR_SetData(dataPtr, typeVal, ptr)
Definition: cp_produce.h:80
int basesBuilt
Definition: cp_statistics.h:32
#define Mem_StrDup(in)
Definition: mem.h:48
Nation definition.
Definition: cp_nation.h:46
Structure for stored UFOs.
A installation with all it&#39;s data.
class DateTime event
Definition: cp_transfer.h:36
static const int SECONDS_PER_DAY
Definition: DateTime.h:43
building_t * B_GetBuildingTemplate(const char *buildingName)
Returns the building in the global building-types list that has the unique name buildingID.
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:62
#define CAP_GetCurrent(base, capacity)
Definition: cp_capacity.h:52
int E_CountHired(const base_t *const base, employeeType_t type)
Counts hired employees of a given type in a given base.
linkedList_t * populations
Definition: q_shared.h:487
building_t * B_BuildBuilding(base_t *base, const building_t *buildingTemplate, int col, int row)
Build a new building to the base.
Definition: cp_base.cpp:1279
int LIST_Count(const linkedList_t *list)
Definition: list.cpp:344
memPool_t * cl_genericPool
Definition: cl_main.cpp:86
void CP_ReadCampaignData(const campaign_t *campaign)
Definition: cp_parse.cpp:692
int CAP_GetFreeCapacity(const base_t *base, baseCapacities_t capacityType)
Returns the free capacity of a type.
bool E_HireEmployee(base_t *base, Employee *employee)
Hires the employee in a base.
static void SetUpTestCase()
int idx
Definition: cp_base.h:85
City definition.
Definition: cp_nation.h:70
void Cmd_ExecuteString(const char *text,...)
A complete command line has been parsed, so try to execute it.
Definition: cmd.cpp:1007
missionState_t state
Definition: cp_missions.h:63
client_static_t cls
Definition: cl_main.cpp:83
bool E_DeleteEmployee(Employee *employee)
Removes the employee completely from the game (buildings + global list).
int ufoInterestOnGeoscape
Definition: cp_aircraft.h:172
struct radar_s radar
Definition: cp_base.h:106
int realtime
Definition: client.h:58
int PR_WorkersAvailable(const base_t *base)
Returns the numer of workers available to produce an item.
Definition: cp_produce.cpp:64
int buildTime
Definition: cp_building.h:92
#define MAX_CREDITS
Definition: cp_campaign.h:401
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition: cvar.cpp:342
aircraftSlot_t weapons[MAX_AIRCRAFTSLOT]
Definition: cp_aircraft.h:144
#define OBJZERO(obj)
Definition: shared.h:178
int UFO_GetAvailableUFOsForMission(const interestCategory_t missionType, ufoType_t *ufoTypes, bool checkInterest)
Fill an array with available UFOs for the mission type.
Definition: cp_ufo.cpp:153
void CP_UpdateTime(void)
Updates date/time and timescale (=timelapse) on the geoscape menu.
Definition: cp_time.cpp:104
int PR_GetRemainingHours(const production_t *prod)
Calculates the remaining hours for a technology.
Definition: cp_produce.cpp:90
int timesAlreadyUsed
Definition: q_shared.h:490
const aircraft_t * UFO_GetByType(const ufoType_t type)
Get the aircraft template for a given UFO type.
Definition: cp_ufo.cpp:109
aircraft_t * AIR_GetFirstFromBase(const base_t *b)
Iterates through the aircraft of a base.
Definition: cp_aircraft.cpp:51
campaign_t campaigns[MAX_CAMPAIGNS]
Definition: cp_campaign.h:381
Item cargo class.
Definition: itemcargo.h:41
void TEST_Shutdown(void)
Definition: test_shared.cpp:34
#define Vector2Set(v, x, y)
Definition: vector.h:61
TEST_F(CampaignTest, testAircraftHandling)
void CL_InitLua(void)
Initializes the ui-lua interfacing environment.
Definition: cl_lua.cpp:126
void CP_CampaignRun(campaign_t *campaign, float secondsSinceLastFrame)
Called every frame when we are in geoscape view.
int numCampaignTriggerEvents
Definition: cp_campaign.h:335
void UR_ProcessActive(void)
Function to process active recoveries.
int numItems[MAX_OBJDEFS]
Definition: inv_shared.h:608
gltexunit_t * active_texunit
Definition: r_state.h:117
campaignTriggerEvent_t campaignTriggerEvents[MAX_CAMPAIGN_TRIGGER_EVENTS]
Definition: cp_campaign.h:334
void initInventory(const char *name, const csi_t *csi, const inventoryImport_t *import)
Initializes the inventory definition by linking the ->next pointers properly.
Definition: inventory.cpp:986
int getDateAsDays() const
Return the date part of the DateTime as days.
Definition: DateTime.cpp:46
short Com_GetUfoIdsNum(void)
Definition: scripts.cpp:571
Employee * E_CreateEmployee(employeeType_t type, const nation_t *nation, const ugv_t *ugvType)
Creates an entry of a new employee in the global list and assignes it to no building/base.
void CP_ParseCampaignData(void)
Read the data for campaigns.
Definition: cp_parse.cpp:641
memPool_t * com_genericPool
Definition: common.cpp:73
static bool skipTest(const mapDef_t *md)
void B_SetUpFirstBase(const campaign_t *campaign, base_t *base)
Setup aircraft and equipment for first base. Uses the campaign scriptable equipmentlist.
Definition: cp_base.cpp:1107
#define UFO_MAX
Definition: scripts.h:146
static void testEventTrigger_f(void)
employeeType_t
The types of employees.
Definition: cp_employee.h:30
static void FreeInventory(void *data)
void CP_UpdateCredits(int credits)
Sets credits and update mn_credits cvar.
campaign_t * CP_GetCampaign(const char *name)
Returns the campaign pointer from global campaign array.
SDL_Surface * Img_LoadImage(char const *name)
Loads the specified image from the game filesystem and populates the provided SDL_Surface.
Definition: images.cpp:435
#define Mem_CreatePool(name)
Definition: mem.h:32
struct aircraft_s * tpl
Definition: cp_aircraft.h:119
ccs_t ccs
Definition: cp_campaign.cpp:63
vec3_t pos
Definition: cp_aircraft.h:132
gltexunit_t texunits[MAX_GL_TEXUNITS]
Definition: r_state.h:114
static transfer_t tr
int numBuildings[MAX_BASES]
Definition: cp_campaign.h:344
void CP_TriggerEvent(campaignTriggerEventType_t type, const void *userdata)
Triggers a campaign event with a special type.
Definition: cp_event.cpp:310
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 ...
vec2_t pos
Definition: cp_missions.h:105
const linkedList_t * LIST_ContainsString(const linkedList_t *list, const char *string)
Searches for the first occurrence of a given string.
Definition: list.cpp:73
int AIR_BaseCountAircraft(const base_t *base)
Returns the number of aircraft on the given base.
Definition: cp_aircraft.cpp:75
#define MapDef_ForeachSingleplayerCampaign(var)
Definition: cl_shared.h:84
char * id
Definition: q_shared.h:463
linkedList_t * transfers
Definition: cp_campaign.h:308
vec2_t pos
Definition: cp_building.h:104
#define MAX_INSTALLATIONS_PER_BASE
mapDef_t * Com_GetMapDefinitionByID(const char *mapDefID)
Definition: scripts.cpp:3598
void AM_Go(mission_t *mission, aircraft_t *aircraft, const campaign_t *campaign, const battleParam_t *battleParameters, missionResults_t *results)
Handles the auto mission.
bool CP_GetRandomPosOnGeoscapeWithParameters(vec2_t pos, const linkedList_t *terrainTypes, const linkedList_t *cultureTypes, const linkedList_t *populationTypes, const linkedList_t *nations)
Determines a random position on geoscape that fulfills certain criteria given via parameters...
technology_t * RS_GetTechByID(const char *id)
return a pointer to the technology identified by given id string
void B_Destroy(base_t *base)
Destroy a base.
Definition: cp_base.cpp:914
installation_t * INS_Build(const installationTemplate_t *installationTemplate, const vec2_t pos, const char *name)
Build a new installation.
bool AIR_IsAircraftOnGeoscape(const aircraft_t *aircraft)
Checks whether given aircraft is on geoscape.
QGL_EXTERN void(APIENTRY *qglActiveTexture)(GLenum texture)
static const int TAG_INVENTORY
QGL_EXTERN GLuint count
Definition: r_gl.h:99
#define AIR_ForeachFromBase(var, base)
iterates trough all aircraft from a specific homebase
Definition: cp_aircraft.h:202
building_t buildings[MAX_BASES][MAX_BUILDINGS]
Definition: cp_campaign.h:342
bool PR_ProductionAllowed(const base_t *base)
Returns true if the current base is able to produce items.
Definition: cp_produce.cpp:596
static bool testEventTriggerCalled
int E_CountUnhired(employeeType_t type)
Counts unhired employees of a given type in a given base.
An aircraft with all it&#39;s data.
Definition: cp_aircraft.h:115
static void ResetInventoryList(void)
struct technology_s * tech
Definition: cp_aircraft.h:163
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
equipDef_t storage
Definition: cp_base.h:112
transfer_t * TR_TransferStart(base_t *srcBase, transfer_t &transData)
Starts a transfer.
struct mission_s * mission
Definition: cp_aircraft.h:153
int PR_GetRemainingMinutes(const production_t *prod)
Calculates the remaining time for a technology in minutes.
Definition: cp_produce.cpp:79
int B_GetInstallationLimit(void)
Counts the actual installation count limit.
Definition: cp_base.cpp:1153
campaign_t * curCampaign
Definition: cp_campaign.h:378
stats_t campaignStats
Definition: cp_campaign.h:379
#define Mem_FreeTag(pool, tagNum)
Definition: mem.h:36
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...
QGL_EXTERN GLint i
Definition: r_gl.h:113
Structure with mission info needed to create results summary at menu won.
Definition: cp_missions.h:61
void CL_SetClientState(connstate_t state)
Sets the client state.
Definition: cl_main.cpp:1015
void TEST_Init(void)
Definition: test_shared.cpp:72
int AIR_GetTeamSize(const aircraft_t *aircraft)
Counts the number of soldiers in given aircraft.
This is the technology parsed from research.ufo.
Definition: cp_research.h:139
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
class DateTime date
Definition: cp_campaign.h:246
#define Mem_Free(ptr)
Definition: mem.h:35
bool RADAR_CheckUFOSensored(radar_t *radar, const vec2_t posRadar, const aircraft_t *ufo, bool detected)
Check if the specified UFO is inside the sensor range of the given radar.
Definition: cp_radar.cpp:408
storedUFOStatus_t status
linkedList_t * cities
Definition: cp_campaign.h:300
#define MapIsWater(color)
Definition: cp_geoscape.h:32
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it&#39;s safe to delete the returned entry from the list while looping over ...
Definition: list.h:41
void E_InitialEmployees(const campaign_t *campaign)
Create initial hireable employees.
#define Vector2Copy(src, dest)
Definition: vector.h:52
vec_t vec2_t[2]
Definition: ufotypes.h:38
int numCampaigns
Definition: cp_campaign.h:382
memPool_t * vid_imagePool
Definition: cl_main.cpp:88
void UFO_SendToDestination(aircraft_t *ufo, const vec2_t dest)
Make the specified UFO go to destination.
Definition: cp_ufo.cpp:562
void E_DeleteAllEmployees(base_t *base)
Removes all employees completely from the game (buildings + global list) from a given base...
rstate_t r_state
Definition: r_main.cpp:48
bool B_AssembleMap(char *maps, size_t mapsLength, char *coords, size_t coordsLength, const base_t *base)
Perform the base assembling in case of an alien attack.
Definition: cp_base.cpp:563
static campaign_t * GetCampaign(void)
bool founded
Definition: cp_base.h:90
void GAME_InitStartup(void)
Definition: cl_game.cpp:1693
void HOS_HospitalRun(void)
Checks health status of all employees in all bases.
Definition: cp_hospital.cpp:82
A building with all it&#39;s data.
Definition: cp_building.h:73
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition: cvar.cpp:615
bool posAssigned
Definition: cp_missions.h:112
#define Q_streq(a, b)
Definition: shared.h:136
bool statusResearchable
Definition: cp_research.h:177
#define AIR_Foreach(var)
iterates trough all aircraft
Definition: cp_aircraft.h:193
building_t * building
Definition: cp_base.h:69
static installation_t * CreateInstallation(const char *name, const vec2_t pos)
bool LIST_IsEmpty(const linkedList_t *list)
Checks whether the given list is empty.
Definition: list.cpp:335
void Cmd_Dummy_f(void)
Dummy binding if you don&#39;t want unknown commands forwarded to the server.
Definition: cmd.cpp:1083
int RS_ResearchRun(void)
Checks the research status.
bool B_BuildingDestroy(building_t *building)
Removes a building from the given base.
Definition: cp_base.cpp:771
int gameLapse
Definition: cp_campaign.h:266
technology_t * RS_GetTechForItem(const objDef_t *item)
Returns technology entry for an item.
aircraft_t * ufo
Definition: cp_missions.h:106
vec3_t pos
Definition: cp_base.h:91
void RS_AssignScientist(technology_t *tech, base_t *base, Employee *employee)
Assigns scientist to the selected research-project.
static void * AllocInventoryMemory(size_t size)
int credits
Definition: cp_campaign.h:243
void destroyInventoryInterface(void)
Definition: inventory.cpp:997
void UFO_RemoveFromGeoscape(aircraft_t *ufo)
Remove the specified ufo from geoscape.
Definition: cp_ufo.cpp:817
void TR_TransferRun(void)
Checks whether given transfer should be processed.
struct aircraft_s * aircraftTarget
Definition: cp_aircraft.h:157
linkedList_t * terrains
Definition: q_shared.h:486
researchStatus_t statusResearch
Definition: cp_research.h:165
linkedList_t * cultures
Definition: q_shared.h:488
#define VectorEqual(a, b)
Definition: vector.h:65
const installationTemplate_t * installationTemplate
void CP_CampaignRunMarket(campaign_t *campaign)
make number of items change every day.
Definition: cp_market.cpp:579
baseStatus_t baseStatus
Definition: cp_base.h:102
base_t * B_Build(const campaign_t *campaign, const vec2_t pos, const char *name, bool fillBase)
Build new base, uses template for the first base.
Definition: cp_base.cpp:1185
cvar_t * cp_missiontest
Definition: cp_campaign.cpp:64
float researchRate
Definition: cp_campaign.h:198
void AIRFIGHT_CampaignRunProjectiles(const campaign_t *campaign, int dt)
Update values of projectiles.
baseBuildingTile_t map[BASE_SIZE][BASE_SIZE]
Definition: cp_base.h:87
void PR_ProductionRun(void)
Checks whether an item is finished.
Definition: cp_produce.cpp:556
mapDef_t * mapDef
Definition: cp_missions.h:89
void NAT_HandleBudget(const campaign_t *campaign)
Update the nation data from all parsed nation each month.
Definition: cp_nation.cpp:714
Defines a type of UGV/Robot.
Definition: chr_shared.h:245
struct components_s * comp
void R_FontInit(void)
Definition: r_font.cpp:722
void B_SetName(base_t *base, const char *name)
Set the base name.
Definition: cp_base.cpp:1173
bool SAV_GameLoad(const char *file, const char **error)
Loads the given savegame from an xml File.
Definition: cp_save.cpp:152
mission_t * CP_CreateNewMission(interestCategory_t category, bool beginNow)
Create a new mission of given category.
const ugv_t * Com_GetUGVByID(const char *ugvID)
Searches an UGV definition by a given script id and returns the pointer to the global data...
Definition: scripts.cpp:3381
void UFO_CheckShootBack(const campaign_t *campaign, aircraft_t *ufo, aircraft_t *phalanxAircraft)
Check if the ufo can shoot back at phalanx aircraft.
Definition: cp_ufo.cpp:578
int Sys_Milliseconds(void)
Definition: unix_shared.cpp:41
void AIR_DeleteAircraft(aircraft_t *aircraft)
Removes an aircraft from its base and the game.
static void TearDownTestCase()