From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_campaign_8cpp_source.html | 2463 +++++++++++++++++++++++++++ 1 file changed, 2463 insertions(+) create mode 100644 Doc/doxygen/html/_campaign_8cpp_source.html (limited to 'Doc/doxygen/html/_campaign_8cpp_source.html') diff --git a/Doc/doxygen/html/_campaign_8cpp_source.html b/Doc/doxygen/html/_campaign_8cpp_source.html new file mode 100644 index 0000000..436768d --- /dev/null +++ b/Doc/doxygen/html/_campaign_8cpp_source.html @@ -0,0 +1,2463 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/Campaign.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
Campaign.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 4.5
+
2  Destroyer Studios LLC
+
3  Copyright (C) 1997-2006. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: Campaign.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Campaign defines a strategic military scenario.
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "Campaign.h"
+
17 #include "CampaignPlanStrategic.h"
+
18 #include "CampaignPlanAssignment.h"
+
19 #include "CampaignPlanEvent.h"
+
20 #include "CampaignPlanMission.h"
+
21 #include "CampaignPlanMovement.h"
+ +
23 #include "CampaignSaveGame.h"
+
24 #include "Combatant.h"
+
25 #include "CombatAction.h"
+
26 #include "CombatEvent.h"
+
27 #include "CombatGroup.h"
+
28 #include "CombatRoster.h"
+
29 #include "CombatUnit.h"
+
30 #include "CombatZone.h"
+
31 #include "Galaxy.h"
+
32 #include "Mission.h"
+
33 #include "StarSystem.h"
+
34 #include "Starshatter.h"
+
35 #include "Player.h"
+
36 
+
37 #include "Game.h"
+
38 #include "Bitmap.h"
+
39 #include "DataLoader.h"
+
40 #include "ParseUtil.h"
+
41 #include "Random.h"
+
42 #include "FormatUtil.h"
+
43 
+
44 
+
45 const int TIME_NEVER = (int) 1e9;
+
46 const int ONE_DAY = (int) 24 * 3600;
+
47 
+
48 // +====================================================================+
+
49 
+ +
51 : mission(0), start(0), type(0), id(0), min_rank(0), max_rank(0),
+
52 action_id(0), action_status(0), exec_once(0),
+
53 start_before(TIME_NEVER), start_after(0)
+
54 { }
+
55 
+ +
57 {
+
58  delete mission;
+
59 }
+
60 
+
61 bool
+ +
63 {
+
64  Campaign* campaign = Campaign::GetCampaign();
+
65  Player* player = Player::GetCurrentPlayer();
+
66  CombatGroup* player_group = campaign->GetPlayerGroup();
+
67 
+
68  if (campaign->GetTime() < start_after)
+
69  return false;
+
70 
+
71  if (campaign->GetTime() > start_before)
+
72  return false;
+
73 
+
74  if (region.length() && player_group->GetRegion() != region)
+
75  return false;
+
76 
+
77  if (min_rank && player->Rank() < min_rank)
+
78  return false;
+
79 
+
80  if (max_rank && player->Rank() > max_rank)
+
81  return false;
+
82 
+
83  if (exec_once < 0)
+
84  return false;
+
85 
+
86  if (exec_once > 0)
+
87  exec_once = -1;
+
88 
+
89  return true;
+
90 }
+
91 
+
92 // +====================================================================+
+
93 
+ +
95 : mission_type(0), group_type(0), index(0)
+
96 { }
+
97 
+ +
99 {
+
100  missions.destroy();
+
101 }
+
102 
+
103 // +====================================================================+
+
104 
+
105 static List<Campaign> campaigns;
+
106 static Campaign* current_campaign = 0;
+
107 
+
108 // +--------------------------------------------------------------------+
+
109 
+
110 Campaign::Campaign(int id, const char* n)
+
111 : campaign_id(id), name(n), mission_id(-1), mission(0), net_mission(0),
+
112 scripted(false), sequential(false), time(0), startTime(0), loadTime(0),
+
113 player_group(0), player_unit(0), status(CAMPAIGN_INIT), lockout(0),
+
114 loaded_from_savegame(false)
+
115 {
+
116  ZeroMemory(path, sizeof(path));
+
117  Load();
+
118 }
+
119 
+
120 Campaign::Campaign(int id, const char* n, const char* p)
+
121 : campaign_id(id), name(n), mission_id(-1), mission(0), net_mission(0),
+
122 scripted(false), sequential(false), time(0), startTime(0), loadTime(0),
+
123 player_group(0), player_unit(0), status(CAMPAIGN_INIT), lockout(0),
+
124 loaded_from_savegame(false)
+
125 {
+
126  ZeroMemory(path, sizeof(path));
+
127  strncpy(path, p, sizeof(path));
+
128  Load();
+
129 }
+
130 
+
131 // +--------------------------------------------------------------------+
+
132 
+ +
134 {
+
135  for (int i = 0; i < NUM_IMAGES; i++)
+
136  image[i].ClearImage();
+
137 
+
138  delete net_mission;
+
139 
+
140  actions.destroy();
+
141  events.destroy();
+
142  missions.destroy();
+
143  templates.destroy();
+
144  planners.destroy();
+
145  zones.destroy();
+ +
147 }
+
148 
+
149 // +--------------------------------------------------------------------+
+
150 
+
151 void
+ +
153 {
+
154  Campaign* c = 0;
+
155  DataLoader* loader = DataLoader::GetLoader();
+
156 
+
157  for (int i = 1; i < 100; i++) {
+
158  char path[256];
+
159  sprintf_s(path, "Campaigns/%02d/", i);
+
160 
+
161  loader->UseFileSystem(true);
+
162  loader->SetDataPath(path);
+
163 
+
164  if (loader->FindFile("campaign.def")) {
+
165  char txt[256];
+
166  sprintf_s(txt, "Dynamic Campaign %02d", i);
+
167  c = new(__FILE__,__LINE__) Campaign(i, txt);
+
168 
+
169  if (c) {
+
170  campaigns.insertSort(c);
+
171  }
+
172  }
+
173  }
+
174 
+
175  c = new(__FILE__,__LINE__) Campaign(SINGLE_MISSIONS, "Single Missions");
+
176  if (c) {
+
177  campaigns.insertSort(c);
+
178  current_campaign = c;
+
179  }
+
180 
+
181  c = new(__FILE__,__LINE__) Campaign(MULTIPLAYER_MISSIONS, "Multiplayer Missions");
+
182  if (c) {
+
183  campaigns.insertSort(c);
+
184  }
+
185 
+
186  c = new(__FILE__,__LINE__) Campaign(CUSTOM_MISSIONS, "Custom Missions");
+
187  if (c) {
+
188  campaigns.insertSort(c);
+
189  }
+
190 }
+
191 
+
192 void
+ +
194 {
+
195  Print("Campaign::Close() - destroying all campaigns\n");
+
196  current_campaign = 0;
+
197  campaigns.destroy();
+
198 }
+
199 
+
200 Campaign*
+ +
202 {
+
203  return current_campaign;
+
204 }
+
205 
+
206 Campaign*
+
207 Campaign::SelectCampaign(const char* name)
+
208 {
+
209  Campaign* c = 0;
+
210  ListIter<Campaign> iter = campaigns;
+
211 
+
212  while (++iter && !c) {
+
213  if (!_stricmp(iter->Name(), name))
+
214  c = iter.value();
+
215  }
+
216 
+
217  if (c) {
+
218  Print("Campaign: Selected '%s'\n", c->Name());
+
219  current_campaign = c;
+
220  }
+
221  else {
+
222  Print("Campaign: could not find '%s'\n", name);
+
223  }
+
224 
+
225  return c;
+
226 }
+
227 
+
228 Campaign*
+
229 Campaign::CreateCustomCampaign(const char* name, const char* path)
+
230 {
+
231  int id = 0;
+
232 
+
233  if (name && *name && path && *path) {
+
234  ListIter<Campaign> iter = campaigns;
+
235 
+
236  while (++iter) {
+
237  Campaign* c = iter.value();
+
238  if (c->GetCampaignId() >= id)
+
239  id = c->GetCampaignId() + 1;
+
240 
+
241  if (!strcmp(c->Name(), name)) {
+
242  Print("Campaign: custom campaign '%s' already exists.\n", name);
+
243  return 0;
+
244  }
+
245  }
+
246  }
+
247 
+
248  if (id == 0)
+
249  id = CUSTOM_MISSIONS + 1;
+
250 
+
251  Campaign* c = new(__FILE__,__LINE__) Campaign(id, name, path);
+
252  Print("Campaign: created custom campaign %d '%s'\n", id, name);
+
253  campaigns.append(c);
+
254 
+
255  return c;
+
256 }
+
257 
+ + +
260 {
+
261  return campaigns;
+
262 }
+
263 
+
264 int
+ +
266 {
+
267  int result = 0;
+
268 
+
269  for (int i = 0; i < campaigns.size(); i++) {
+
270  Campaign* c = campaigns.at(i);
+
271 
+
272  if (c->IsDynamic() && c->GetCampaignId() > result) {
+
273  result = c->GetCampaignId();
+
274  }
+
275  }
+
276 
+
277  return result;
+
278 }
+
279 
+
280 // +--------------------------------------------------------------------+
+
281 
+ + +
284 {
+
285  CombatEvent* result = 0;
+
286 
+
287  if (!events.isEmpty())
+
288  result = events.last();
+
289 
+
290  return result;
+
291 }
+
292 
+
293 // +--------------------------------------------------------------------+
+
294 
+
295 int
+ +
297 {
+
298  int result = 0;
+
299 
+
300  for (int i = 0; i < events.size(); i++)
+
301  if (/*events[i]->Source() != CombatEvent::TACNET &&*/ !events[i]->Visited())
+
302  result++;
+
303 
+
304  return result;
+
305 }
+
306 
+
307 // +--------------------------------------------------------------------+
+
308 
+
309 void
+ +
311 {
+
312  missions.destroy();
+
313  planners.destroy();
+ +
315  events.destroy();
+
316  actions.destroy();
+
317 
+
318  player_group = 0;
+
319  player_unit = 0;
+
320 
+
321  updateTime = time;
+
322 }
+
323 
+
324 // +--------------------------------------------------------------------+
+
325 
+
326 void
+ +
328 {
+
329  // first, unload any existing data:
+
330  Unload();
+
331 
+
332  if (!path[0]) {
+
333  // then load the campaign from files:
+
334  switch (campaign_id) {
+
335  case SINGLE_MISSIONS: strcpy_s(path, "Missions/"); break;
+
336  case CUSTOM_MISSIONS: strcpy_s(path, "Mods/Missions/"); break;
+
337  case MULTIPLAYER_MISSIONS: strcpy_s(path, "Multiplayer/"); break;
+
338  default: sprintf_s(path, "Campaigns/%02d/", campaign_id); break;
+
339  }
+
340  }
+
341 
+
342  DataLoader* loader = DataLoader::GetLoader();
+
343  loader->UseFileSystem(true);
+
344  loader->SetDataPath(path);
+
345  systems.clear();
+
346 
+
347  if (loader->FindFile("zones.def"))
+
348  zones.append(CombatZone::Load("zones.def"));
+
349 
+
350  for (int i = 0; i < zones.size(); i++) {
+
351  Text s = zones[i]->System();
+
352  bool found = false;
+
353 
+
354  for (int n = 0; !found && n < systems.size(); n++) {
+
355  if (s == systems[n]->Name())
+
356  found = true;
+
357  }
+
358 
+
359  if (!found)
+ +
361  }
+
362 
+ +
364 
+
365  if (loader->FindFile("campaign.def"))
+
366  LoadCampaign(loader);
+
367 
+
368  if (campaign_id == CUSTOM_MISSIONS) {
+
369  loader->SetDataPath(path);
+
370  LoadCustomMissions(loader);
+
371  }
+
372  else {
+
373  bool found = false;
+
374 
+
375  if (loader->FindFile("missions.def")) {
+
376  loader->SetDataPath(path);
+
377  LoadMissionList(loader);
+
378  found = true;
+
379  }
+
380 
+
381  if (loader->FindFile("templates.def")) {
+
382  loader->SetDataPath(path);
+
383  LoadTemplateList(loader);
+
384  found = true;
+
385  }
+
386 
+
387  if (!found) {
+
388  loader->SetDataPath(path);
+
389  LoadCustomMissions(loader);
+
390  }
+
391  }
+
392 
+
393  loader->UseFileSystem(true);
+
394  loader->SetDataPath(path);
+
395 
+
396  if (loader->FindFile("image.pcx")) {
+
397  loader->LoadBitmap("image.pcx", image[ 0]);
+
398  loader->LoadBitmap("selected.pcx", image[ 1]);
+
399  loader->LoadBitmap("unavail.pcx", image[ 2]);
+
400  loader->LoadBitmap("banner.pcx", image[ 3]);
+
401  }
+
402 
+
403  loader->SetDataPath(0);
+ +
405 }
+
406 
+
407 void
+ +
409 {
+ +
411 
+ + +
414 
+
415  startTime = Stardate();
+ +
417  lockout = 0;
+
418 
+
419  for (int i = 0; i < NUM_IMAGES; i++)
+
420  image[i].ClearImage();
+
421 
+
422  Clear();
+
423 
+
424  zones.destroy();
+
425 }
+
426 
+
427 void
+ +
429 {
+
430  BYTE* block = 0;
+
431  const char* filename = "campaign.def";
+
432 
+
433  loader->UseFileSystem(true);
+
434  loader->LoadBuffer(filename, block, true);
+ +
436  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
+
437 
+
438  Term* term = parser.ParseTerm();
+
439 
+
440  if (!term) {
+
441  return;
+
442  }
+
443  else {
+
444  TermText* file_type = term->isText();
+
445  if (!file_type || file_type->value() != "CAMPAIGN") {
+
446  return;
+
447  }
+
448  }
+
449 
+
450  do {
+
451  delete term; term = 0;
+
452  term = parser.ParseTerm();
+
453 
+
454  if (term) {
+
455  TermDef* def = term->isDef();
+
456  if (def) {
+
457  if (def->name()->value() == "name") {
+
458  if (!def->term() || !def->term()->isText()) {
+
459  ::Print("WARNING: name missing in '%s/%s'\n", loader->GetDataPath(), filename);
+
460  }
+
461  else {
+
462  name = def->term()->isText()->value();
+ +
464  }
+
465  }
+
466  else if (def->name()->value() == "desc") {
+
467  if (!def->term() || !def->term()->isText()) {
+
468  ::Print("WARNING: description missing in '%s/%s'\n", loader->GetDataPath(), filename);
+
469  }
+
470  else {
+
471  description = def->term()->isText()->value();
+ +
473  }
+
474  }
+
475  else if (def->name()->value() == "situation") {
+
476  if (!def->term() || !def->term()->isText()) {
+
477  ::Print("WARNING: situation missing in '%s/%s'\n", loader->GetDataPath(), filename);
+
478  }
+
479  else {
+
480  situation = def->term()->isText()->value();
+ +
482  }
+
483  }
+
484  else if (def->name()->value() == "orders") {
+
485  if (!def->term() || !def->term()->isText()) {
+
486  ::Print("WARNING: orders missing in '%s/%s'\n", loader->GetDataPath(), filename);
+
487  }
+
488  else {
+
489  orders = def->term()->isText()->value();
+ +
491  }
+
492  }
+
493  else if (def->name()->value() == "scripted") {
+
494  if (def->term() && def->term()->isBool()) {
+
495  scripted = def->term()->isBool()->value();
+
496  }
+
497  }
+
498  else if (def->name()->value() == "sequential") {
+
499  if (def->term() && def->term()->isBool()) {
+
500  sequential = def->term()->isBool()->value();
+
501  }
+
502  }
+
503  else if (full && def->name()->value() == "combatant") {
+
504  if (!def->term() || !def->term()->isStruct()) {
+
505  ::Print("WARNING: combatant struct missing in '%s/%s'\n", loader->GetDataPath(), filename);
+
506  }
+
507  else {
+
508  TermStruct* val = def->term()->isStruct();
+
509 
+
510  char name[64];
+
511  int iff = 0;
+
512  CombatGroup* force = 0;
+
513  CombatGroup* clone = 0;
+
514 
+
515  ZeroMemory(name, sizeof(name));
+
516 
+
517  for (int i = 0; i < val->elements()->size(); i++) {
+
518  TermDef* pdef = val->elements()->at(i)->isDef();
+
519  if (pdef) {
+
520  if (pdef->name()->value() == "name") {
+
521  GetDefText(name, pdef, filename);
+
522 
+
523  force = CombatRoster::GetInstance()->GetForce(name);
+
524 
+
525  if (force)
+
526  clone = force->Clone(false); // shallow copy
+
527  }
+
528 
+
529  else if (pdef->name()->value() == "group") {
+
530  ParseGroup(pdef->term()->isStruct(), force, clone, filename);
+
531  }
+
532  }
+
533  }
+
534 
+
535  loader->SetDataPath(path);
+
536  Combatant* c = new(__FILE__,__LINE__) Combatant(name, clone);
+
537  if (c) {
+
538  combatants.append(c);
+
539  }
+
540  else {
+
541  Unload();
+
542  return;
+
543  }
+
544  }
+
545  }
+
546  else if (full && def->name()->value() == "action") {
+
547  if (!def->term() || !def->term()->isStruct()) {
+
548  ::Print("WARNING: action struct missing in '%s/%s'\n", loader->GetDataPath(), filename);
+
549  }
+
550  else {
+
551  TermStruct* val = def->term()->isStruct();
+
552  ParseAction(val, filename);
+
553  }
+
554  }
+
555  }
+
556  }
+
557  }
+
558  while (term);
+
559 
+
560  loader->ReleaseBuffer(block);
+
561 }
+
562 
+
563 // +--------------------------------------------------------------------+
+
564 
+
565 void
+ +
567 CombatGroup* force,
+
568 CombatGroup* clone,
+
569 const char* filename)
+
570 {
+
571  if (!val) {
+
572  ::Print("invalid combat group in campaign %s\n", name.data());
+
573  return;
+
574  }
+
575 
+
576  int type = 0;
+
577  int id = 0;
+
578 
+
579  for (int i = 0; i < val->elements()->size(); i++) {
+
580  TermDef* pdef = val->elements()->at(i)->isDef();
+
581  if (pdef) {
+
582  if (pdef->name()->value() == "type") {
+
583  char type_name[64];
+
584  GetDefText(type_name, pdef, filename);
+
585  type = CombatGroup::TypeFromName(type_name);
+
586  }
+
587 
+
588  else if (pdef->name()->value() == "id") {
+
589  GetDefNumber(id, pdef, filename);
+
590  }
+
591  }
+
592  }
+
593 
+
594  if (type && id) {
+
595  CombatGroup* g = force->FindGroup(type, id);
+
596 
+
597  // found original group, now clone it over
+
598  if (g && g->GetParent()) {
+
599  CombatGroup* parent = CloneOver(force, clone, g->GetParent());
+
600  parent->AddComponent(g->Clone());
+
601  }
+
602  }
+
603 }
+
604 
+
605 // +--------------------------------------------------------------------+
+
606 
+
607 void
+
608 Campaign::ParseAction(TermStruct* val, const char* filename)
+
609 {
+
610  if (!val) {
+
611  ::Print("invalid action in campaign %s\n", name.data());
+
612  return;
+
613  }
+
614 
+
615  int id = 0;
+
616  int type = 0;
+
617  int subtype = 0;
+
618  int opp_type = -1;
+
619  int team = 0;
+
620  int source = 0;
+
621  Vec3 loc(0.0f, 0.0f, 0.0f);
+
622  Text system;
+
623  Text region;
+
624  Text file;
+
625  Text image;
+
626  Text scene;
+
627  Text text;
+
628  int count = 1;
+
629  int start_before = TIME_NEVER;
+
630  int start_after = 0;
+
631  int min_rank = 0;
+
632  int max_rank = 100;
+
633  int delay = 0;
+
634  int probability = 100;
+
635 
+
636  int asset_type = 0;
+
637  int asset_id = 0;
+
638  int target_type = 0;
+
639  int target_id = 0;
+
640  int target_iff = 0;
+
641 
+
642  CombatAction* action = 0;
+
643 
+
644  for (int i = 0; i < val->elements()->size(); i++) {
+
645  TermDef* pdef = val->elements()->at(i)->isDef();
+
646  if (pdef) {
+
647  if (pdef->name()->value() == "id") {
+
648  GetDefNumber(id, pdef, filename);
+
649  }
+
650  else if (pdef->name()->value() == "type") {
+
651  char txt[64];
+
652  GetDefText(txt, pdef, filename);
+
653  type = CombatAction::TypeFromName(txt);
+
654  }
+
655  else if (pdef->name()->value() == "subtype") {
+
656  if (pdef->term()->isNumber()) {
+
657  GetDefNumber(subtype, pdef, filename);
+
658  }
+
659 
+
660  else if (pdef->term()->isText()) {
+
661  char txt[64];
+
662  GetDefText(txt, pdef, filename);
+
663 
+
664  if (type == CombatAction::MISSION_TEMPLATE) {
+
665  subtype = Mission::TypeFromName(txt);
+
666  }
+
667  else if (type == CombatAction::COMBAT_EVENT) {
+
668  subtype = CombatEvent::TypeFromName(txt);
+
669  }
+
670  else if (type == CombatAction::INTEL_EVENT) {
+
671  subtype = Intel::IntelFromName(txt);
+
672  }
+
673  }
+
674  }
+
675  else if (pdef->name()->value() == "opp_type") {
+
676  if (pdef->term()->isNumber()) {
+
677  GetDefNumber(opp_type, pdef, filename);
+
678  }
+
679 
+
680  else if (pdef->term()->isText()) {
+
681  char txt[64];
+
682  GetDefText(txt, pdef, filename);
+
683 
+
684  if (type == CombatAction::MISSION_TEMPLATE) {
+
685  opp_type = Mission::TypeFromName(txt);
+
686  }
+
687  }
+
688  }
+
689  else if (pdef->name()->value() == "source") {
+
690  char txt[64];
+
691  GetDefText(txt, pdef, filename);
+
692  source = CombatEvent::SourceFromName(txt);
+
693  }
+
694  else if (pdef->name()->value() == "team") {
+
695  GetDefNumber(team, pdef, filename);
+
696  }
+
697  else if (pdef->name()->value() == "iff") {
+
698  GetDefNumber(team, pdef, filename);
+
699  }
+
700  else if (pdef->name()->value() == "count") {
+
701  GetDefNumber(count, pdef, filename);
+
702  }
+
703  else if (pdef->name()->value().contains("before")) {
+
704  if (pdef->term()->isNumber()) {
+
705  GetDefNumber(start_before, pdef, filename);
+
706  }
+
707  else {
+
708  GetDefTime(start_before, pdef, filename);
+
709  start_before -= ONE_DAY;
+
710  }
+
711  }
+
712  else if (pdef->name()->value().contains("after")) {
+
713  if (pdef->term()->isNumber()) {
+
714  GetDefNumber(start_after, pdef, filename);
+
715  }
+
716  else {
+
717  GetDefTime(start_after, pdef, filename);
+
718  start_after -= ONE_DAY;
+
719  }
+
720  }
+
721  else if (pdef->name()->value() == "min_rank") {
+
722  if (pdef->term()->isNumber()) {
+
723  GetDefNumber(min_rank, pdef, filename);
+
724  }
+
725  else {
+
726  char rank_name[64];
+
727  GetDefText(rank_name, pdef, filename);
+
728  min_rank = Player::RankFromName(rank_name);
+
729  }
+
730  }
+
731  else if (pdef->name()->value() == "max_rank") {
+
732  if (pdef->term()->isNumber()) {
+
733  GetDefNumber(max_rank, pdef, filename);
+
734  }
+
735  else {
+
736  char rank_name[64];
+
737  GetDefText(rank_name, pdef, filename);
+
738  max_rank = Player::RankFromName(rank_name);
+
739  }
+
740  }
+
741  else if (pdef->name()->value() == "delay") {
+
742  GetDefNumber(delay, pdef, filename);
+
743  }
+
744  else if (pdef->name()->value() == "probability") {
+
745  GetDefNumber(probability, pdef, filename);
+
746  }
+
747  else if (pdef->name()->value() == "asset_type") {
+
748  char type_name[64];
+
749  GetDefText(type_name, pdef, filename);
+
750  asset_type = CombatGroup::TypeFromName(type_name);
+
751  }
+
752  else if (pdef->name()->value() == "target_type") {
+
753  char type_name[64];
+
754  GetDefText(type_name, pdef, filename);
+
755  target_type = CombatGroup::TypeFromName(type_name);
+
756  }
+
757  else if (pdef->name()->value() == "location" ||
+
758  pdef->name()->value() == "loc") {
+
759  GetDefVec(loc, pdef, filename);
+
760  }
+
761  else if (pdef->name()->value() == "system" ||
+
762  pdef->name()->value() == "sys") {
+
763  GetDefText(system, pdef, filename);
+
764  }
+
765  else if (pdef->name()->value() == "region" ||
+
766  pdef->name()->value() == "rgn" ||
+
767  pdef->name()->value() == "zone") {
+
768  GetDefText(region, pdef, filename);
+
769  }
+
770  else if (pdef->name()->value() == "file") {
+
771  GetDefText(file, pdef, filename);
+
772  }
+
773  else if (pdef->name()->value() == "image") {
+
774  GetDefText(image, pdef, filename);
+
775  }
+
776  else if (pdef->name()->value() == "scene") {
+
777  GetDefText(scene, pdef, filename);
+
778  }
+
779  else if (pdef->name()->value() == "text") {
+
780  GetDefText(text, pdef, filename);
+
781  text = Game::GetText(text);
+
782  }
+
783  else if (pdef->name()->value() == "asset_id") {
+
784  GetDefNumber(asset_id, pdef, filename);
+
785  }
+
786  else if (pdef->name()->value() == "target_id") {
+
787  GetDefNumber(target_id, pdef, filename);
+
788  }
+
789  else if (pdef->name()->value() == "target_iff") {
+
790  GetDefNumber(target_iff, pdef, filename);
+
791  }
+
792 
+
793  else if (pdef->name()->value() == "asset_kill") {
+
794  if (!action)
+
795  action = new(__FILE__,__LINE__) CombatAction(id, type, subtype, team);
+
796 
+
797  if (action) {
+
798  char txt[64];
+
799  GetDefText(txt, pdef, filename);
+
800  action->AssetKills().append(new (__FILE__,__LINE__) Text(txt));
+
801  }
+
802  }
+
803 
+
804  else if (pdef->name()->value() == "target_kill") {
+
805  if (!action)
+
806  action = new(__FILE__,__LINE__) CombatAction(id, type, subtype, team);
+
807 
+
808  if (action) {
+
809  char txt[64];
+
810  GetDefText(txt, pdef, filename);
+
811  action->TargetKills().append(new (__FILE__,__LINE__) Text(txt));
+
812  }
+
813  }
+
814 
+
815  else if (pdef->name()->value() == "req") {
+
816  if (!action)
+
817  action = new(__FILE__,__LINE__) CombatAction(id, type, subtype, team);
+
818 
+
819  if (!pdef->term() || !pdef->term()->isStruct()) {
+
820  ::Print("WARNING: action req struct missing in '%s'\n", filename);
+
821  }
+
822  else if (action) {
+
823  TermStruct* val2 = pdef->term()->isStruct();
+
824 
+
825  int act = 0;
+
826  int stat = CombatAction::COMPLETE;
+
827  bool not = false;
+
828 
+
829  Combatant* c1 = 0;
+
830  Combatant* c2 = 0;
+
831  int comp = 0;
+
832  int score = 0;
+
833  int intel = 0;
+
834  int gtype = 0;
+
835  int gid = 0;
+
836 
+
837  for (int i = 0; i < val2->elements()->size(); i++) {
+
838  TermDef* pdef2 = val2->elements()->at(i)->isDef();
+
839  if (pdef2) {
+
840  if (pdef2->name()->value() == "action") {
+
841  GetDefNumber(act, pdef2, filename);
+
842  }
+
843  else if (pdef2->name()->value() == "status") {
+
844  char txt[64];
+
845  GetDefText(txt, pdef2, filename);
+
846  stat = CombatAction::StatusFromName(txt);
+
847  }
+
848  else if (pdef2->name()->value() == "not") {
+
849  GetDefBool(not, pdef2, filename);
+
850  }
+
851 
+
852  else if (pdef2->name()->value() == "c1") {
+
853  char txt[64];
+
854  GetDefText(txt, pdef2, filename);
+
855  c1 = GetCombatant(txt);
+
856  }
+
857  else if (pdef2->name()->value() == "c2") {
+
858  char txt[64];
+
859  GetDefText(txt, pdef2, filename);
+
860  c2 = GetCombatant(txt);
+
861  }
+
862  else if (pdef2->name()->value() == "comp") {
+
863  char txt[64];
+
864  GetDefText(txt, pdef2, filename);
+
865  comp = CombatActionReq::CompFromName(txt);
+
866  }
+
867  else if (pdef2->name()->value() == "score") {
+
868  GetDefNumber(score, pdef2, filename);
+
869  }
+
870  else if (pdef2->name()->value() == "intel") {
+
871  if (pdef2->term()->isNumber()) {
+
872  GetDefNumber(intel, pdef2, filename);
+
873  }
+
874  else if (pdef2->term()->isText()) {
+
875  char txt[64];
+
876  GetDefText(txt, pdef2, filename);
+
877  intel = Intel::IntelFromName(txt);
+
878  }
+
879  }
+
880  else if (pdef2->name()->value() == "group_type") {
+
881  char type_name[64];
+
882  GetDefText(type_name, pdef2, filename);
+
883  gtype = CombatGroup::TypeFromName(type_name);
+
884  }
+
885  else if (pdef2->name()->value() == "group_id") {
+
886  GetDefNumber(gid, pdef2, filename);
+
887  }
+
888  }
+
889  }
+
890 
+
891  if (act)
+
892  action->AddRequirement(act, stat, not);
+
893 
+
894  else if (gtype)
+
895  action->AddRequirement(c1, gtype, gid, comp, score, intel);
+
896 
+
897  else
+
898  action->AddRequirement(c1, c2, comp, score);
+
899  }
+
900  }
+
901  }
+
902  }
+
903 
+
904  if (!action)
+
905  action = new(__FILE__,__LINE__) CombatAction(id, type, subtype, team);
+
906 
+
907  if (action) {
+
908  action->SetSource(source);
+
909  action->SetOpposingType(opp_type);
+
910  action->SetLocation(loc);
+
911  action->SetSystem(system);
+
912  action->SetRegion(region);
+
913  action->SetFilename(file);
+
914  action->SetImageFile(image);
+
915  action->SetSceneFile(scene);
+
916  action->SetCount(count);
+
917  action->SetStartAfter(start_after);
+
918  action->SetStartBefore(start_before);
+
919  action->SetMinRank(min_rank);
+
920  action->SetMaxRank(max_rank);
+
921  action->SetDelay(delay);
+
922  action->SetProbability(probability);
+
923 
+
924  action->SetAssetId(asset_id);
+
925  action->SetAssetType(asset_type);
+
926  action->SetTargetId(target_id);
+
927  action->SetTargetIFF(target_iff);
+
928  action->SetTargetType(target_type);
+
929  action->SetText(text);
+
930 
+
931  actions.append(action);
+
932  }
+
933 }
+
934 
+
935 // +--------------------------------------------------------------------+
+
936 
+ + +
939 {
+
940  CombatGroup* orig_parent = group->GetParent();
+
941 
+
942  if (orig_parent) {
+
943  CombatGroup* clone_parent = clone->FindGroup(orig_parent->Type(), orig_parent->GetID());
+
944 
+
945  if (!clone_parent)
+
946  clone_parent = CloneOver(force, clone, orig_parent);
+
947 
+
948  CombatGroup* new_clone = clone->FindGroup(group->Type(), group->GetID());
+
949 
+
950  if (!new_clone) {
+
951  new_clone = group->Clone(false);
+
952  clone_parent->AddComponent(new_clone);
+
953  }
+
954 
+
955  return new_clone;
+
956  }
+
957  else {
+
958  return clone;
+
959  }
+
960 }
+
961 
+
962 // +--------------------------------------------------------------------+
+
963 
+
964 void
+ +
966 {
+
967  bool ok = true;
+
968  BYTE* block = 0;
+
969  const char* filename = "Missions.def";
+
970 
+
971  loader->UseFileSystem(true);
+
972  loader->LoadBuffer(filename, block, true);
+ +
974  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
+
975 
+
976  Term* term = parser.ParseTerm();
+
977 
+
978  if (!term) {
+
979  return;
+
980  }
+
981  else {
+
982  TermText* file_type = term->isText();
+
983  if (!file_type || file_type->value() != "MISSIONLIST") {
+
984  ::Print("WARNING: invalid mission list file '%s'\n", filename);
+
985  term->print(10);
+
986  return;
+
987  }
+
988  }
+
989 
+
990  do {
+
991  delete term; term = 0;
+
992  term = parser.ParseTerm();
+
993 
+
994  if (term) {
+
995  TermDef* def = term->isDef();
+
996  if (def) {
+
997  if (def->name()->value() == "mission") {
+
998  if (!def->term() || !def->term()->isStruct()) {
+
999  ::Print("WARNING: mission struct missing in '%s'\n", filename);
+
1000  }
+
1001  else {
+
1002  TermStruct* val = def->term()->isStruct();
+
1003 
+
1004  int id = 0;
+
1005  Text name;
+
1006  Text desc;
+
1007  char script[256];
+
1008  char system[256];
+
1009  char region[256];
+
1010  int start = 0;
+
1011  int type = 0;
+
1012 
+
1013  ZeroMemory(script, sizeof(script));
+
1014 
+
1015  strcpy_s(system, "Unknown");
+
1016  strcpy_s(region, "Unknown");
+
1017 
+
1018  for (int i = 0; i < val->elements()->size(); i++) {
+
1019  TermDef* pdef = val->elements()->at(i)->isDef();
+
1020  if (pdef) {
+
1021  if (pdef->name()->value() == "id")
+
1022  GetDefNumber(id, pdef, filename);
+
1023 
+
1024  else if (pdef->name()->value() == "name") {
+
1025  GetDefText(name, pdef, filename);
+
1026  name = Game::GetText(name);
+
1027  }
+
1028 
+
1029  else if (pdef->name()->value() == "desc") {
+
1030  GetDefText(desc, pdef, filename);
+
1031  if (desc.length() > 0 && desc.length() < 32)
+
1032  desc = Game::GetText(desc);
+
1033  }
+
1034 
+
1035  else if (pdef->name()->value() == "start")
+
1036  GetDefTime(start, pdef, filename);
+
1037 
+
1038  else if (pdef->name()->value() == "system")
+
1039  GetDefText(system, pdef, filename);
+
1040 
+
1041  else if (pdef->name()->value() == "region")
+
1042  GetDefText(region, pdef, filename);
+
1043 
+
1044  else if (pdef->name()->value() == "script")
+
1045  GetDefText(script, pdef, filename);
+
1046 
+
1047  else if (pdef->name()->value() == "type") {
+
1048  char typestr[64];
+
1049  GetDefText(typestr, pdef, filename);
+
1050  type = Mission::TypeFromName(typestr);
+
1051  }
+
1052  }
+
1053  }
+
1054 
+
1055  MissionInfo* info = new(__FILE__,__LINE__) MissionInfo;
+
1056  if (info) {
+
1057  info->id = id;
+
1058  info->name = name;
+
1059  info->description = desc;
+
1060  info->system = system;
+
1061  info->region = region;
+
1062  info->script = script;
+
1063  info->start = start;
+
1064  info->type = type;
+
1065  info->mission = 0;
+
1066 
+
1067  info->script.setSensitive(false);
+
1068 
+
1069  missions.append(info);
+
1070  }
+
1071  else {
+
1072  ok = false;
+
1073  }
+
1074  }
+
1075  }
+
1076  }
+
1077  }
+
1078  }
+
1079  while (term);
+
1080 
+
1081  loader->ReleaseBuffer(block);
+
1082 
+
1083  if (!ok)
+
1084  Unload();
+
1085 }
+
1086 
+
1087 void
+ +
1089 {
+
1090  bool ok = true;
+
1091  List<Text> files;
+
1092  loader->UseFileSystem(true);
+
1093  loader->ListFiles("*.*", files);
+
1094 
+
1095  for (int i = 0; i < files.size(); i++) {
+
1096  Text file = *files[i];
+
1097  file.setSensitive(false);
+
1098 
+
1099  if (file.contains(".def")) {
+
1100  BYTE* block = 0;
+
1101  const char* filename = file.data();
+
1102 
+
1103  loader->UseFileSystem(true);
+
1104  loader->LoadBuffer(filename, block, true);
+ +
1106 
+
1107  if (strstr((const char*) block, "MISSION") == (const char*) block) {
+
1108  Text name;
+
1109  Text desc;
+
1110  Text system = "Unknown";
+
1111  Text region = "Unknown";
+
1112  int start = 0;
+
1113  int type = 0;
+
1114  int msn_id = 0;
+
1115 
+
1116  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
+
1117  Term* term = parser.ParseTerm();
+
1118 
+
1119  if (!term) {
+
1120  Print("ERROR: could not parse '%s'\n", filename);
+
1121  continue;
+
1122  }
+
1123  else {
+
1124  TermText* file_type = term->isText();
+
1125  if (!file_type || file_type->value() != "MISSION") {
+
1126  Print("ERROR: invalid mission file '%s'\n", filename);
+
1127  term->print(10);
+
1128  continue;
+
1129  }
+
1130  }
+
1131 
+
1132  do {
+
1133  delete term; term = 0;
+
1134  term = parser.ParseTerm();
+
1135 
+
1136  if (term) {
+
1137  TermDef* def = term->isDef();
+
1138  if (def) {
+
1139  if (def->name()->value() == "name") {
+
1140  GetDefText(name, def, filename);
+
1141  name = Game::GetText(name);
+
1142  }
+
1143 
+
1144  else if (def->name()->value() == "type") {
+
1145  char typestr[64];
+
1146  GetDefText(typestr, def, filename);
+
1147  type = Mission::TypeFromName(typestr);
+
1148  }
+
1149 
+
1150  else if (def->name()->value() == "id")
+
1151  GetDefNumber(msn_id, def, filename);
+
1152 
+
1153  else if (def->name()->value() == "desc") {
+
1154  GetDefText(desc, def, filename);
+
1155  if (desc.length() > 0 && desc.length() < 32)
+
1156  desc = Game::GetText(desc);
+
1157  }
+
1158 
+
1159  else if (def->name()->value() == "system")
+
1160  GetDefText(system, def, filename);
+
1161 
+
1162  else if (def->name()->value() == "region")
+
1163  GetDefText(region, def, filename);
+
1164 
+
1165  else if (def->name()->value() == "start")
+
1166  GetDefTime(start, def, filename);
+
1167  }
+
1168  }
+
1169  }
+
1170  while (term);
+
1171 
+
1172  loader->ReleaseBuffer(block);
+
1173 
+
1174  if (strstr(filename, "custom") == filename) {
+
1175  sscanf_s(filename+6, "%d", &msn_id);
+
1176 
+
1177  if (msn_id <= i)
+
1178  msn_id = i+1;
+
1179  }
+
1180  else if (msn_id < 1) {
+
1181  msn_id = i+1;
+
1182  }
+
1183 
+
1184  MissionInfo* info = new(__FILE__,__LINE__) MissionInfo;
+
1185  if (info) {
+
1186  info->id = msn_id;
+
1187  info->name = name;
+
1188  info->type = type;
+
1189  info->description = desc;
+
1190  info->system = system;
+
1191  info->region = region;
+
1192  info->script = filename;
+
1193  info->start = start;
+
1194  info->mission = 0;
+
1195 
+
1196  info->script.setSensitive(false);
+
1197 
+
1198  missions.append(info);
+
1199  }
+
1200  else {
+
1201  ok = false;
+
1202  }
+
1203  }
+
1204  else {
+
1205  Print("Invalid Custom Mission File: '%s'\n", filename);
+
1206  }
+
1207 
+
1208  loader->ReleaseBuffer(block);
+
1209  }
+
1210  }
+
1211 
+
1212  files.destroy();
+
1213 
+
1214  if (!ok)
+
1215  Unload();
+
1216  else
+
1217  missions.sort();
+
1218 }
+
1219 
+
1220 void
+ +
1222 {
+
1223  BYTE* block = 0;
+
1224  const char* filename = "Templates.def";
+
1225 
+
1226  loader->UseFileSystem(true);
+
1227  loader->LoadBuffer(filename, block, true);
+ +
1229  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
+
1230 
+
1231  Term* term = parser.ParseTerm();
+
1232 
+
1233  if (!term) {
+
1234  return;
+
1235  }
+
1236  else {
+
1237  TermText* file_type = term->isText();
+
1238  if (!file_type || file_type->value() != "TEMPLATELIST") {
+
1239  ::Print("WARNING: invalid template list file '%s'\n", filename);
+
1240  term->print(10);
+
1241  return;
+
1242  }
+
1243  }
+
1244 
+
1245  do {
+
1246  delete term; term = 0;
+
1247  term = parser.ParseTerm();
+
1248 
+
1249  if (term) {
+
1250  TermDef* def = term->isDef();
+
1251  if (def) {
+
1252  if (def->name()->value() == "mission") {
+
1253  if (!def->term() || !def->term()->isStruct()) {
+
1254  ::Print("WARNING: mission struct missing in '%s'\n", filename);
+
1255  }
+
1256  else {
+
1257  TermStruct* val = def->term()->isStruct();
+
1258 
+
1259  char name[256];
+
1260  char script[256];
+
1261  char region[256];
+
1262  int id = 0;
+
1263  int msn_type = 0;
+
1264  int grp_type = 0;
+
1265 
+
1266  int min_rank = 0;
+
1267  int max_rank = 0;
+
1268  int action_id = 0;
+
1269  int action_status = 0;
+
1270  int exec_once = 0;
+
1271  int start_before = TIME_NEVER;
+
1272  int start_after = 0;
+
1273 
+
1274  name[0] = 0;
+
1275  script[0] = 0;
+
1276  region[0] = 0;
+
1277 
+
1278  for (int i = 0; i < val->elements()->size(); i++) {
+
1279  TermDef* pdef = val->elements()->at(i)->isDef();
+
1280  if (pdef) {
+
1281  if (pdef->name()->value() == "id")
+
1282  GetDefNumber(id, pdef, filename);
+
1283 
+
1284  else if (pdef->name()->value() == "name")
+
1285  GetDefText(name, pdef, filename);
+
1286 
+
1287  else if (pdef->name()->value() == "script")
+
1288  GetDefText(script, pdef, filename);
+
1289 
+
1290  else if (pdef->name()->value() == "rgn" || pdef->name()->value() == "region")
+
1291  GetDefText(region, pdef, filename);
+
1292 
+
1293  else if (pdef->name()->value() == "type") {
+
1294  char typestr[64];
+
1295  GetDefText(typestr, pdef, filename);
+
1296  msn_type = Mission::TypeFromName(typestr);
+
1297  }
+
1298 
+
1299  else if (pdef->name()->value() == "group") {
+
1300  char typestr[64];
+
1301  GetDefText(typestr, pdef, filename);
+
1302  grp_type = CombatGroup::TypeFromName(typestr);
+
1303  }
+
1304 
+
1305  else if (pdef->name()->value() == "min_rank")
+
1306  GetDefNumber(min_rank, pdef, filename);
+
1307 
+
1308  else if (pdef->name()->value() == "max_rank")
+
1309  GetDefNumber(max_rank, pdef, filename);
+
1310 
+
1311  else if (pdef->name()->value() == "action_id")
+
1312  GetDefNumber(action_id, pdef, filename);
+
1313 
+
1314  else if (pdef->name()->value() == "action_status")
+
1315  GetDefNumber(action_status, pdef, filename);
+
1316 
+
1317  else if (pdef->name()->value() == "exec_once")
+
1318  GetDefNumber(exec_once, pdef, filename);
+
1319 
+
1320  else if (pdef->name()->value().contains("before")) {
+
1321  if (pdef->term()->isNumber()) {
+
1322  GetDefNumber(start_before, pdef, filename);
+
1323  }
+
1324  else {
+
1325  GetDefTime(start_before, pdef, filename);
+
1326  start_before -= ONE_DAY;
+
1327  }
+
1328  }
+
1329  else if (pdef->name()->value().contains("after")) {
+
1330  if (pdef->term()->isNumber()) {
+
1331  GetDefNumber(start_after, pdef, filename);
+
1332  }
+
1333  else {
+
1334  GetDefTime(start_after, pdef, filename);
+
1335  start_after -= ONE_DAY;
+
1336  }
+
1337  }
+
1338  }
+
1339  }
+
1340 
+
1341  MissionInfo* info = new(__FILE__,__LINE__) MissionInfo;
+
1342  if (info) {
+
1343  info->id = id;
+
1344  info->name = name;
+
1345  info->script = script;
+
1346  info->region = region;
+
1347  info->type = msn_type;
+
1348  info->min_rank = min_rank;
+
1349  info->max_rank = max_rank;
+
1350  info->action_id = action_id;
+
1351  info->action_status = action_status;
+
1352  info->exec_once = exec_once;
+
1353  info->start_before = start_before;
+
1354  info->start_after = start_after;
+
1355 
+
1356  info->script.setSensitive(false);
+
1357 
+
1358  TemplateList* templist = GetTemplateList(msn_type, grp_type);
+
1359 
+
1360  if (!templist) {
+
1361  templist = new(__FILE__,__LINE__) TemplateList;
+
1362  templist->mission_type = msn_type;
+
1363  templist->group_type = grp_type;
+
1364  templates.append(templist);
+
1365  }
+
1366 
+
1367  templist->missions.append(info);
+
1368  }
+
1369  }
+
1370  }
+
1371  }
+
1372  }
+
1373  }
+
1374  while (term);
+
1375 
+
1376  loader->ReleaseBuffer(block);
+
1377 }
+
1378 
+
1379 // +--------------------------------------------------------------------+
+
1380 
+
1381 void
+ +
1383 {
+
1384  if (planners.size() > 0)
+
1385  planners.destroy();
+
1386 
+
1387  CampaignPlan* p;
+
1388 
+
1389  // PLAN EVENT MUST BE FIRST PLANNER:
+
1390  p = new(__FILE__,__LINE__) CampaignPlanEvent(this);
+
1391  if (p)
+
1392  planners.append(p);
+
1393 
+
1394  p = new(__FILE__,__LINE__) CampaignPlanStrategic(this);
+
1395  if (p)
+
1396  planners.append(p);
+
1397 
+
1398  p = new(__FILE__,__LINE__) CampaignPlanAssignment(this);
+
1399  if (p)
+
1400  planners.append(p);
+
1401 
+
1402  p = new(__FILE__,__LINE__) CampaignPlanMovement(this);
+
1403  if (p)
+
1404  planners.append(p);
+
1405 
+
1406  p = new(__FILE__,__LINE__) CampaignPlanMission(this);
+
1407  if (p)
+
1408  planners.append(p);
+
1409 
+
1410  if (lockout > 0 && planners.size()) {
+ +
1412  while (++plan)
+
1413  plan->SetLockout(lockout);
+
1414  }
+
1415 }
+
1416 
+
1417 // +--------------------------------------------------------------------+
+
1418 
+
1419 int
+ +
1421 {
+
1422  int iff = 1;
+
1423 
+
1424  if (player_group)
+
1425  iff = player_group->GetIFF();
+
1426 
+
1427  return iff;
+
1428 }
+
1429 
+
1430 void
+ +
1432 {
+
1433  if (player_group != pg) {
+
1434  ::Print("Campaign::SetPlayerGroup(%s)\n", pg ? pg->Name().data() : "0");
+
1435 
+
1436  // should verify that the player group is
+
1437  // actually part of this campaign, first!
+
1438 
+
1439  player_group = pg;
+
1440  player_unit = 0;
+
1441 
+
1442  // need to regenerate missions when changing
+
1443  // player combat group:
+
1444  if (IsDynamic()) {
+
1445  ::Print(" destroying mission list...\n");
+
1446  missions.destroy();
+
1447  }
+
1448  }
+
1449 }
+
1450 
+
1451 void
+ +
1453 {
+
1454  if (player_unit != unit) {
+
1455  ::Print("Campaign::SetPlayerUnit(%s)\n", unit ? unit->Name().data() : "0");
+
1456 
+
1457  // should verify that the player unit is
+
1458  // actually part of this campaign, first!
+
1459 
+
1460  player_unit = unit;
+
1461 
+
1462  if (unit)
+
1463  player_group = unit->GetCombatGroup();
+
1464 
+
1465  // need to regenerate missions when changing
+
1466  // player combat unit:
+
1467  if (IsDynamic()) {
+
1468  ::Print(" destroying mission list...\n");
+
1469  missions.destroy();
+
1470  }
+
1471  }
+
1472 }
+
1473 
+
1474 // +--------------------------------------------------------------------+
+
1475 
+
1476 CombatZone*
+
1477 Campaign::GetZone(const char* rgn)
+
1478 {
+ +
1480  while (++z) {
+
1481  if (z->HasRegion(rgn))
+
1482  return z.value();
+
1483  }
+
1484 
+
1485  return 0;
+
1486 }
+
1487 
+
1488 StarSystem*
+
1489 Campaign::GetSystem(const char* sys)
+
1490 {
+
1491  return Galaxy::GetInstance()->GetSystem(sys);
+
1492 }
+
1493 
+
1494 Combatant*
+
1495 Campaign::GetCombatant(const char* cname)
+
1496 {
+ +
1498  while (++iter) {
+
1499  Combatant* c = iter.value();
+
1500  if (!strcmp(c->Name(), cname))
+
1501  return c;
+
1502  }
+
1503 
+
1504  return 0;
+
1505 }
+
1506 
+
1507 // +--------------------------------------------------------------------+
+
1508 
+
1509 Mission*
+ +
1511 {
+
1512  return GetMission(mission_id);
+
1513 }
+
1514 
+
1515 Mission*
+ +
1517 {
+
1518  if (id < 0) {
+
1519  ::Print("ERROR - Campaign::GetMission(%d) invalid mission id\n", id);
+
1520  return 0;
+
1521  }
+
1522 
+
1523  if (mission && mission->Identity() == id) {
+
1524  return mission;
+
1525  }
+
1526 
+
1527  MissionInfo* info = 0;
+
1528  for (int i = 0; !info && i < missions.size(); i++)
+
1529  if (missions[i]->id == id)
+
1530  info = missions[i];
+
1531 
+
1532  if (info) {
+
1533  if (!info->mission) {
+
1534  ::Print("Campaign::GetMission(%d) loading mission...\n", id);
+
1535  info->mission = new(__FILE__,__LINE__) Mission(id, info->script, path);
+
1536  if (info->mission)
+
1537  info->mission->Load();
+
1538  }
+
1539 
+
1540  if (IsDynamic()) {
+
1541  if (info->mission) {
+
1542  if (!_stricmp(info->mission->Situation(), "Unknown")) {
+
1543  ::Print("Campaign::GetMission(%d) generating sitrep...\n", id);
+
1544  CampaignSituationReport sitrep(this, info->mission);
+
1545  sitrep.GenerateSituationReport();
+
1546  }
+
1547  }
+
1548  else {
+
1549  ::Print("Campaign::GetMission(%d) could not find/load mission.\n", id);
+
1550  }
+
1551  }
+
1552 
+
1553  return info->mission;
+
1554  }
+
1555 
+
1556  return 0;
+
1557 }
+
1558 
+
1559 Mission*
+
1560 Campaign::GetMissionByFile(const char* filename)
+
1561 {
+
1562  if (!filename || !*filename) {
+
1563  ::Print("ERROR - Campaign::GetMissionByFile() invalid filename\n");
+
1564  return 0;
+
1565  }
+
1566 
+
1567  int id = 0;
+
1568  int maxid = 0;
+
1569  MissionInfo* info = 0;
+
1570 
+
1571  for (int i = 0; !info && i < missions.size(); i++) {
+
1572  MissionInfo* m = missions[i];
+
1573 
+
1574  if (m->id > maxid)
+
1575  maxid = m->id;
+
1576 
+
1577  if (m->script == filename)
+
1578  info = m;
+
1579  }
+
1580 
+
1581  if (info) {
+
1582  id = info->id;
+
1583 
+
1584  if (!info->mission) {
+
1585  ::Print("Campaign::GetMission(%d) loading mission...\n", id);
+
1586  info->mission = new(__FILE__,__LINE__) Mission(id, info->script, path);
+
1587  if (info->mission)
+
1588  info->mission->Load();
+
1589  }
+
1590 
+
1591  if (IsDynamic()) {
+
1592  if (info->mission) {
+
1593  if (!_stricmp(info->mission->Situation(), "Unknown")) {
+
1594  ::Print("Campaign::GetMission(%d) generating sitrep...\n", id);
+
1595  CampaignSituationReport sitrep(this, info->mission);
+
1596  sitrep.GenerateSituationReport();
+
1597  }
+
1598  }
+
1599  else {
+
1600  ::Print("Campaign::GetMission(%d) could not find/load mission.\n", id);
+
1601  }
+
1602  }
+
1603  }
+
1604 
+
1605  else {
+
1606  info = new(__FILE__,__LINE__) MissionInfo;
+
1607  if (info) {
+
1608  info->id = maxid+1;
+
1609  info->name = "New Custom Mission";
+
1610  info->script = filename;
+
1611  info->mission = new(__FILE__,__LINE__) Mission(info->id, info->script, "Mods/Missions/");
+
1612  info->mission->SetName(info->name);
+
1613 
+
1614  info->script.setSensitive(false);
+
1615 
+
1616  missions.append(info);
+
1617  }
+
1618  }
+
1619 
+
1620  return info->mission;
+
1621 }
+
1622 
+
1623 MissionInfo*
+ +
1625 {
+
1626  int id = 0;
+
1627  int maxid = 0;
+
1628  MissionInfo* info = 0;
+
1629 
+ +
1631  maxid = 10;
+
1632 
+
1633  for (int i = 0; !info && i < missions.size(); i++) {
+
1634  MissionInfo* m = missions[i];
+
1635 
+
1636  if (m->id > maxid)
+
1637  maxid = m->id;
+
1638  }
+
1639 
+
1640  char filename[64];
+
1641  sprintf_s(filename, "custom%03d.def", maxid+1);
+
1642 
+
1643  info = new(__FILE__,__LINE__) MissionInfo;
+
1644  if (info) {
+
1645  info->id = maxid+1;
+
1646  info->name = "New Custom Mission";
+
1647  info->script = filename;
+
1648  info->mission = new(__FILE__,__LINE__) Mission(info->id, filename, path);
+
1649  info->mission->SetName(info->name);
+
1650 
+
1651  info->script.setSensitive(false);
+
1652 
+
1653  missions.append(info);
+
1654  }
+
1655 
+
1656  return info;
+
1657 }
+
1658 
+
1659 void
+ +
1661 {
+
1662  if (id < 0) {
+
1663  ::Print("ERROR - Campaign::DeleteMission(%d) invalid mission id\n", id);
+
1664  return;
+
1665  }
+
1666 
+
1667  MissionInfo* m = 0;
+
1668  int index = -1;
+
1669 
+
1670  for (int i = 0; !m && i < missions.size(); i++) {
+
1671  if (missions[i]->id == id) {
+
1672  m = missions[i];
+
1673  index = i;
+
1674  }
+
1675  }
+
1676 
+
1677  if (m) {
+
1678  char full_path[256];
+
1679 
+
1680  if (path[strlen(path)-1] == '/')
+
1681  sprintf_s(full_path, "%s%s", path, m->script.data());
+
1682  else
+
1683  sprintf_s(full_path, "%s/%s", path, m->script.data());
+
1684 
+
1685  DeleteFile(full_path);
+
1686  Load();
+
1687  }
+
1688 
+
1689  else {
+
1690  ::Print("ERROR - Campaign::DeleteMission(%d) could not find mission\n", id);
+
1691  }
+
1692 }
+
1693 
+
1694 MissionInfo*
+ +
1696 {
+
1697  if (id < 0) {
+
1698  ::Print("ERROR - Campaign::GetMissionInfo(%d) invalid mission id\n", id);
+
1699  return 0;
+
1700  }
+
1701 
+
1702  MissionInfo* m = 0;
+
1703  for (int i = 0; !m && i < missions.size(); i++)
+
1704  if (missions[i]->id == id)
+
1705  m = missions[i];
+
1706 
+
1707  if (m) {
+
1708  if (!m->mission) {
+
1709  m->mission = new(__FILE__,__LINE__) Mission(id, m->script);
+
1710  if (m->mission)
+
1711  m->mission->Load();
+
1712  }
+
1713 
+
1714  return m;
+
1715  }
+
1716 
+
1717  else {
+
1718  ::Print("ERROR - Campaign::GetMissionInfo(%d) could not find mission\n", id);
+
1719  }
+
1720 
+
1721  return 0;
+
1722 }
+
1723 
+
1724 void
+ +
1726 {
+
1727  if (mission && mission == net_mission) {
+
1728  delete net_mission;
+
1729  net_mission = 0;
+
1730  }
+
1731 
+
1732  mission = 0;
+
1733 
+
1734  if (id >= 0 && id < missions.size()) {
+
1735  MissionInfo* m = missions[id];
+
1736  delete m->mission;
+
1737  m->mission = 0;
+
1738  }
+
1739 }
+
1740 
+
1741 void
+
1742 Campaign::LoadNetMission(int id, const char* net_mission_script)
+
1743 {
+
1744  if (mission && mission == net_mission) {
+
1745  delete net_mission;
+
1746  net_mission = 0;
+
1747  }
+
1748 
+
1749  mission_id = id;
+
1750  mission = new(__FILE__,__LINE__) Mission(id);
+
1751 
+
1752  if (mission && mission->ParseMission(net_mission_script))
+
1753  mission->Validate();
+
1754 
+
1755  net_mission = mission;
+
1756 }
+
1757 
+
1758 // +--------------------------------------------------------------------+
+
1759 
+
1760 CombatAction*
+
1761 Campaign::FindAction(int action_id)
+
1762 {
+ +
1764  while (++iter) {
+
1765  CombatAction* a = iter.value();
+
1766 
+
1767  if (a->Identity() == action_id)
+
1768  return a;
+
1769  }
+
1770 
+
1771  return 0;
+
1772 }
+
1773 
+
1774 // +--------------------------------------------------------------------+
+
1775 
+
1776 MissionInfo*
+
1777 Campaign::FindMissionTemplate(int mission_type, CombatGroup* player_group)
+
1778 {
+
1779  MissionInfo* info = 0;
+
1780 
+
1781  if (!player_group)
+
1782  return info;
+
1783 
+
1784  TemplateList* templates = GetTemplateList(mission_type, player_group->Type());
+
1785 
+
1786  if (!templates || !templates->missions.size())
+
1787  return info;
+
1788 
+
1789  int tries = 0;
+
1790  int msize = templates->missions.size();
+
1791 
+
1792  while (!info && tries < msize) {
+
1793  // get next template:
+
1794  int index = templates->index;
+
1795 
+
1796  if (index >= msize)
+
1797  index = 0;
+
1798 
+
1799  info = templates->missions[index];
+
1800  templates->index = index + 1;
+
1801  tries++;
+
1802 
+
1803  // validate the template:
+
1804  if (info) {
+
1805  if (info->action_id) {
+
1806  CombatAction* a = FindAction(info->action_id);
+
1807 
+
1808  if (a && a->Status() != info->action_status)
+
1809  info = 0;
+
1810  }
+
1811 
+
1812  if (info && !info->IsAvailable()) {
+
1813  info = 0;
+
1814  }
+
1815  }
+
1816  }
+
1817 
+
1818  return info;
+
1819 }
+
1820 
+
1821 // +--------------------------------------------------------------------+
+
1822 
+
1823 TemplateList*
+
1824 Campaign::GetTemplateList(int msn_type, int grp_type)
+
1825 {
+
1826  for (int i = 0; i < templates.size(); i++) {
+
1827  if (templates[i]->mission_type == msn_type &&
+
1828  templates[i]->group_type == grp_type)
+
1829  return templates[i];
+
1830  }
+
1831 
+
1832  return 0;
+
1833 }
+
1834 
+
1835 // +--------------------------------------------------------------------+
+
1836 
+
1837 void
+ +
1839 {
+
1840  ::Print("Campaign::SetMissionId(%d)\n", id);
+
1841 
+
1842  if (id > 0)
+
1843  mission_id = id;
+
1844  else
+
1845  ::Print(" retaining mission id = %d\n", mission_id);
+
1846 }
+
1847 
+
1848 // +--------------------------------------------------------------------+
+
1849 
+
1850 double
+ +
1852 {
+
1853  return StarSystem::Stardate();
+
1854 }
+
1855 
+
1856 // +--------------------------------------------------------------------+
+
1857 
+
1858 void
+ +
1860 {
+
1861  if (player_group || !g) return;
+
1862 
+
1863  if (g->Type() == type && !g->IsReserve() && g->Value() > 0) {
+
1864  player_group = g;
+
1865  player_unit = 0;
+
1866  return;
+
1867  }
+
1868 
+
1869  for (int i = 0; i < g->GetComponents().size(); i++)
+
1870  SelectDefaultPlayerGroup(g->GetComponents()[i], type);
+
1871 }
+
1872 
+
1873 // +--------------------------------------------------------------------+
+
1874 
+
1875 void
+ +
1877 {
+
1878  // if this is a new campaign,
+
1879  // create combatants from roster and template:
+
1880  if (IsDynamic() && combatants.isEmpty()) {
+
1881  DataLoader* loader = DataLoader::GetLoader();
+
1882  loader->SetDataPath(path);
+
1883  LoadCampaign(loader, true);
+
1884  }
+
1885 
+ +
1887 
+
1888  // load scripted missions:
+
1889  if (IsScripted() && actions.isEmpty()) {
+
1890  DataLoader* loader = DataLoader::GetLoader();
+
1891  loader->SetDataPath(path);
+
1892  LoadCampaign(loader, true);
+
1893 
+ +
1895  while (++m) {
+
1896  GetMission(m->id);
+
1897  }
+
1898  }
+
1899 
+
1900  CheckPlayerGroup();
+
1901 }
+
1902 
+
1903 void
+ +
1905 {
+
1906  ::Print("Campaign::Start()\n");
+
1907 
+
1908  Prep();
+
1909 
+
1910  // create planners:
+
1911  CreatePlanners();
+ +
1913 }
+
1914 
+
1915 void
+ +
1917 {
+
1918  if (InCutscene())
+
1919  return;
+
1920 
+
1921  time = Stardate() - startTime;
+
1922 
+
1923  if (status < CAMPAIGN_ACTIVE)
+
1924  return;
+
1925 
+
1926  if (IsDynamic()) {
+
1927  bool completed = false;
+ +
1929  while (++m) {
+
1930  if (m->mission && m->mission->IsComplete()) {
+
1931  ::Print("Campaign::ExecFrame() completed mission %d '%s'\n", m->id, m->name.data());
+
1932  completed = true;
+
1933  }
+
1934  }
+
1935 
+
1936  if (completed) {
+
1937  ::Print("Campaign::ExecFrame() destroying mission list after completion...\n");
+
1938  missions.destroy();
+
1939 
+ +
1941  time += 10 * 3600;
+
1942  else
+
1943  time += 20 * 3600;
+
1944 
+ +
1946  }
+
1947  else {
+
1948  m.reset();
+
1949 
+
1950  while (++m) {
+
1951  if (m->start < time && !m->mission->IsActive()) {
+
1952  MissionInfo* info = m.removeItem();
+
1953 
+
1954  if (info)
+
1955  ::Print("Campaign::ExecFrame() deleting expired mission %d start: %d current: %d\n",
+
1956  info->id,
+
1957  info->start,
+
1958  (int) time);
+
1959 
+
1960  delete info;
+
1961  }
+
1962  }
+
1963  }
+
1964 
+
1965  // PLAN EVENT MUST BE FIRST PLANNER:
+
1966  if (loaded_from_savegame && planners.size() > 0) {
+ +
1968  plan_event->ExecScriptedEvents();
+
1969 
+
1970  loaded_from_savegame = false;
+
1971  }
+
1972 
+ +
1974  while (++plan) {
+
1975  CheckPlayerGroup();
+
1976  plan->ExecFrame();
+
1977  }
+
1978 
+
1979  CheckPlayerGroup();
+
1980 
+
1981  // Auto save game AFTER planners have run!
+
1982  // This is done to ensure that campaign status
+
1983  // is properly recorded after winning or losing
+
1984  // the campaign.
+
1985 
+
1986  if (completed) {
+
1987  CampaignSaveGame save(this);
+
1988  save.SaveAuto();
+
1989  }
+
1990  }
+
1991  else {
+
1992  // PLAN EVENT MUST BE FIRST PLANNER:
+
1993  if (planners.size() > 0) {
+ +
1995  plan_event->ExecScriptedEvents();
+
1996  }
+
1997  }
+
1998 }
+
1999 
+
2000 // +--------------------------------------------------------------------+
+
2001 
+
2002 void
+ +
2004 {
+
2005  lockout = seconds;
+
2006 }
+
2007 
+
2008 void
+ +
2010 {
+
2011  if (!player_group || player_group->IsReserve() || player_group->CalcValue() < 1) {
+
2012  int player_iff = GetPlayerIFF();
+
2013  player_group = 0;
+
2014 
+
2015  CombatGroup* force = 0;
+
2016  for (int i = 0; i < combatants.size() && !force; i++) {
+
2017  if (combatants[i]->GetIFF() == player_iff) {
+
2018  force = combatants[i]->GetForce();
+
2019  }
+
2020  }
+
2021 
+
2022  if (force) {
+
2023  force->CalcValue();
+ +
2025 
+
2026  if (!player_group)
+ +
2028  }
+
2029  }
+
2030 
+
2031  if (player_unit && player_unit->GetValue() < 1)
+
2032  SetPlayerUnit(0);
+
2033 }
+
2034 
+
2035 // +--------------------------------------------------------------------+
+
2036 
+
2037 void FPU2Extended();
+
2038 void FPURestore();
+
2039 
+
2040 void
+ +
2042 {
+
2043  Mission* m = GetMission();
+
2044 
+
2045  if (m) {
+
2046  ::Print("\n\nCampaign Start Mission - %d. '%s'\n", m->Identity(), m->Name());
+
2047 
+
2048  if (!scripted) {
+
2049  FPU2Extended();
+
2050 
+
2051  double gtime = (double) Game::GameTime() / 1000.0;
+
2052  double base = startTime + m->Start() - 15 - gtime;
+
2053 
+ +
2055 
+
2056  double current_time = Stardate() - startTime;
+
2057 
+
2058  char buffer[32];
+
2059  FormatDayTime(buffer, current_time);
+
2060  ::Print(" current time: %s\n", buffer);
+
2061 
+
2062  FormatDayTime(buffer, m->Start());
+
2063  ::Print(" mission start: %s\n", buffer);
+
2064  ::Print("\n");
+
2065  }
+
2066  }
+
2067 }
+
2068 
+
2069 void
+ +
2071 {
+
2072  ::Print("Campaign::RollbackMission()\n");
+
2073 
+
2074  Mission* m = GetMission();
+
2075 
+
2076  if (m) {
+
2077  if (!scripted) {
+
2078  FPU2Extended();
+
2079 
+
2080  double gtime = (double) Game::GameTime() / 1000.0;
+
2081  double base = startTime + m->Start() - 60 - gtime;
+
2082 
+ +
2084 
+
2085  double current_time = Stardate() - startTime;
+
2086  ::Print(" mission start: %d\n", m->Start());
+
2087  ::Print(" current time: %d\n", (int) current_time);
+
2088  }
+
2089 
+
2090  m->SetActive(false);
+
2091  m->SetComplete(false);
+
2092  }
+
2093 }
+
2094 
+
2095 // +--------------------------------------------------------------------+
+
2096 
+
2097 bool
+ +
2099 {
+ +
2101  return stars ? stars->InCutscene() : false;
+
2102 }
+
2103 
+
2104 bool
+ +
2106 {
+
2107  return campaign_id >= DYNAMIC_CAMPAIGN &&
+ +
2109 }
+
2110 
+
2111 bool
+ +
2113 {
+
2114  return campaign_id == TRAINING_CAMPAIGN;
+
2115 }
+
2116 
+
2117 bool
+ +
2119 {
+
2120  return scripted;
+
2121 }
+
2122 
+
2123 bool
+ +
2125 {
+
2126  return sequential;
+
2127 }
+
2128 
+
2129 // +--------------------------------------------------------------------+
+
2130 
+
2131 static CombatGroup* FindGroup(CombatGroup* g, int type, int id)
+
2132 {
+
2133  if (g->Type() == type && g->GetID() == id)
+
2134  return g;
+
2135 
+
2136  CombatGroup* result = 0;
+
2137 
+
2138  ListIter<CombatGroup> subgroup = g->GetComponents();
+
2139  while (++subgroup && !result)
+
2140  result = FindGroup(subgroup.value(), type, id);
+
2141 
+
2142  return result;
+
2143 }
+
2144 
+
2145 CombatGroup*
+
2146 Campaign::FindGroup(int iff, int type, int id)
+
2147 {
+
2148  CombatGroup* result = 0;
+
2149 
+
2150  ListIter<Combatant> combatant = combatants;
+
2151  while (++combatant && !result) {
+
2152  if (combatant->GetIFF() == iff) {
+
2153  result = ::FindGroup(combatant->GetForce(), type, id);
+
2154  }
+
2155  }
+
2156 
+
2157  return result;
+
2158 }
+
2159 
+
2160 // +--------------------------------------------------------------------+
+
2161 
+
2162 static void FindGroups(CombatGroup* g, int type, CombatGroup* near_group,
+
2163 List<CombatGroup>& groups)
+
2164 {
+
2165  if (g->Type() == type && g->IntelLevel() > Intel::RESERVE) {
+
2166  if (!near_group || g->GetAssignedZone() == near_group->GetAssignedZone())
+
2167  groups.append(g);
+
2168  }
+
2169 
+
2170  ListIter<CombatGroup> subgroup = g->GetComponents();
+
2171  while (++subgroup)
+
2172  FindGroups(subgroup.value(), type, near_group, groups);
+
2173 }
+
2174 
+
2175 CombatGroup*
+
2176 Campaign::FindGroup(int iff, int type, CombatGroup* near_group)
+
2177 {
+
2178  CombatGroup* result = 0;
+
2179  List<CombatGroup> groups;
+
2180 
+
2181  ListIter<Combatant> combatant = combatants;
+
2182  while (++combatant) {
+
2183  if (combatant->GetIFF() == iff) {
+
2184  FindGroups(combatant->GetForce(), type, near_group, groups);
+
2185  }
+
2186  }
+
2187 
+
2188  if (groups.size() > 0) {
+
2189  int index = (int) Random(0, groups.size());
+
2190  if (index >= groups.size()) index = groups.size() - 1;
+
2191  result = groups[index];
+
2192  }
+
2193 
+
2194  return result;
+
2195 }
+
2196 
+
2197 // +--------------------------------------------------------------------+
+
2198 
+
2199 static void FindStrikeTargets(CombatGroup* g, CombatGroup* strike_group,
+
2200 List<CombatGroup>& groups)
+
2201 {
+
2202  if (!strike_group || !strike_group->GetAssignedZone()) return;
+
2203 
+
2204  if (g->IsStrikeTarget() && g->IntelLevel() > Intel::RESERVE) {
+
2205  if (strike_group->GetAssignedZone() == g->GetAssignedZone() ||
+
2206  strike_group->GetAssignedZone()->HasRegion(g->GetRegion()))
+
2207  groups.append(g);
+
2208  }
+
2209 
+
2210  ListIter<CombatGroup> subgroup = g->GetComponents();
+
2211  while (++subgroup)
+
2212  FindStrikeTargets(subgroup.value(), strike_group, groups);
+
2213 }
+
2214 
+
2215 CombatGroup*
+ +
2217 {
+
2218  CombatGroup* result = 0;
+
2219 
+
2220  List<CombatGroup> groups;
+
2221 
+
2222  ListIter<Combatant> combatant = GetCombatants();
+
2223  while (++combatant) {
+
2224  if (combatant->GetIFF() != 0 && combatant->GetIFF() != iff) {
+
2225  FindStrikeTargets(combatant->GetForce(), strike_group, groups);
+
2226  }
+
2227  }
+
2228 
+
2229  if (groups.size() > 0) {
+
2230  int index = rand() % groups.size();
+
2231  result = groups[index];
+
2232  }
+
2233 
+
2234  return result;
+
2235 }
+
2236 
+
2237 // +--------------------------------------------------------------------+
+
2238 
+
2239 void
+ +
2241 {
+ +
2243  while (++iter) {
+
2244  CombatAction* a = iter.value();
+
2245 
+
2246  if (a->IsAvailable())
+ +
2248  }
+
2249 
+
2250  updateTime = time;
+
2251 }
+
2252 
+
2253 // +--------------------------------------------------------------------+
+
2254 
+
2255 int
+ +
2257 {
+
2258  int score_us = 0;
+
2259  int score_them = 0;
+
2260 
+
2261  if (player_group) {
+
2262  int iff = player_group->GetIFF();
+
2263 
+ +
2265  while (++iter) {
+
2266  Combatant* c = iter.value();
+
2267 
+
2268  if (iff <= 1) {
+
2269  if (c->GetIFF() <= 1)
+
2270  score_us += c->Score();
+
2271  else
+
2272  score_them += c->Score();
+
2273  }
+
2274 
+
2275  else {
+
2276  if (c->GetIFF() <= 1)
+
2277  score_them += c->Score();
+
2278  else
+
2279  score_us += c->Score();
+
2280  }
+
2281  }
+
2282  }
+
2283 
+
2284  return score_us - score_them;
+
2285 }
+
2286 
+
2287 // +--------------------------------------------------------------------+
+
2288 
+
2289 void
+ +
2291 {
+
2292  status = s;
+
2293 
+
2294  // record the win in player profile:
+
2295  if (status == CAMPAIGN_SUCCESS) {
+
2296  Player* player = Player::GetCurrentPlayer();
+
2297 
+
2298  if (player)
+ +
2300  }
+
2301 
+
2302  if (status > CAMPAIGN_ACTIVE) {
+
2303  ::Print("Campaign::SetStatus() destroying mission list at campaign end\n");
+
2304  missions.destroy();
+
2305  }
+
2306 }
+
2307 
+
2308 // +--------------------------------------------------------------------+
+
2309 
+
2310 static void GetCombatUnits(CombatGroup* g, List<CombatUnit>& units)
+
2311 {
+
2312  if (g) {
+
2313  ListIter<CombatUnit> unit = g->GetUnits();
+
2314  while (++unit) {
+
2315  CombatUnit* u = unit.value();
+
2316 
+
2317  if (u->Count() - u->DeadCount() > 0)
+
2318  units.append(u);
+
2319  }
+
2320 
+ +
2322  while (++comp) {
+
2323  CombatGroup* g2 = comp.value();
+
2324 
+
2325  if (!g2->IsReserve())
+
2326  GetCombatUnits(g2, units);
+
2327  }
+
2328  }
+
2329 }
+
2330 
+
2331 int
+ +
2333 {
+
2334  units.clear();
+
2335 
+ +
2337  while (++iter) {
+
2338  Combatant* c = iter.value();
+
2339 
+
2340  if (iff < 0 || c->GetIFF() == iff) {
+
2341  GetCombatUnits(c->GetForce(), units);
+
2342  }
+
2343  }
+
2344 
+
2345  return units.size();
+
2346 }
+
+
+ + + + -- cgit v1.1