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/_combat_group_8cpp_source.html | 1708 +++++++++++++++++++++++ 1 file changed, 1708 insertions(+) create mode 100644 Doc/doxygen/html/_combat_group_8cpp_source.html (limited to 'Doc/doxygen/html/_combat_group_8cpp_source.html') diff --git a/Doc/doxygen/html/_combat_group_8cpp_source.html b/Doc/doxygen/html/_combat_group_8cpp_source.html new file mode 100644 index 0000000..a7760c7 --- /dev/null +++ b/Doc/doxygen/html/_combat_group_8cpp_source.html @@ -0,0 +1,1708 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/CombatGroup.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
CombatGroup.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 4.5
+
2  Destroyer Studios LLC
+
3  Copyright (C) 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: CombatGroup.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  An element in the dynamic campaign
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "CombatGroup.h"
+
17 #include "CombatUnit.h"
+
18 #include "CombatZone.h"
+
19 #include "Combatant.h"
+
20 #include "CombatAssignment.h"
+
21 #include "Campaign.h"
+
22 #include "ShipDesign.h"
+
23 #include "Ship.h"
+
24 
+
25 #include "Game.h"
+
26 #include "DataLoader.h"
+
27 #include "ParseUtil.h"
+
28 
+
29 // +----------------------------------------------------------------------+
+
30 
+
31 CombatGroup::CombatGroup(int t, int n, const char* s, int iff_code, int e, CombatGroup* p)
+
32 : type(t), id(n), name(s), iff(iff_code), enemy_intel(e),
+
33 parent(p), value(0), plan_value(0), unit_index(0), combatant(0),
+
34 expanded(false), sorties(0), kills(0), points(0),
+
35 current_zone(0), assigned_zone(0), zone_lock(false)
+
36 {
+
37  if (parent)
+
38  parent->AddComponent(this);
+
39 }
+
40 
+ +
42 {
+
43  assignments.destroy();
+
44  components.destroy();
+
45  units.destroy();
+
46 }
+
47 
+
48 // +--------------------------------------------------------------------+
+
49 
+
50 void
+ +
52 {
+
53  if (g) {
+
54  g->parent = this;
+
55  components.append(g);
+
56  }
+
57 }
+
58 
+
59 // +--------------------------------------------------------------------+
+
60 
+
61 bool
+ +
63 {
+
64  switch (type) {
+
65  case CARRIER_GROUP:
+
66  case BATTLE_GROUP:
+
67  case DESTROYER_SQUADRON:
+
68  case ATTACK_SQUADRON:
+
69  case FIGHTER_SQUADRON:
+
70  case INTERCEPT_SQUADRON:
+
71  case LCA_SQUADRON:
+
72  return ((CombatGroup*) this)->CalcValue() > 0;
+
73  }
+
74 
+
75  return false;
+
76 }
+
77 
+
78 bool
+ +
80 {
+
81  // neutral / non-combatants are not *strategic* targets
+
82  // for any combatant:
+
83  if (iff < 1 || iff >= 100)
+
84  return false;
+
85 
+
86  // civilian / non-combatant are not strategic targets:
+
87  if (type == PASSENGER ||
+
88  type == PRIVATE ||
+
89  type == MEDICAL ||
+
90  type == HABITAT)
+
91  return false;
+
92 
+
93  // must have units of our own to be targetable:
+
94  if (units.size() < 1)
+
95  return false;
+
96 
+
97  return ((CombatGroup*) this)->CalcValue() > 0;
+
98 }
+
99 
+
100 bool
+ +
102 {
+
103  if (type >= SUPPORT)
+
104  return ((CombatGroup*) this)->CalcValue() > 0;
+
105 
+
106  return false;
+
107 }
+
108 
+
109 bool
+ +
111 {
+
112  if (type < BATTALION ||
+
113  type == MINEFIELD || // assault, not strike
+
114  type == PASSENGER ||
+
115  type == PRIVATE ||
+
116  type == MEDICAL ||
+
117  type == HABITAT)
+
118  return false;
+
119 
+
120  return ((CombatGroup*) this)->CalcValue() > 0;
+
121 }
+
122 
+
123 // +--------------------------------------------------------------------+
+
124 
+
125 bool
+ +
127 {
+
128  switch (type) {
+
129  case CARRIER_GROUP:
+
130  case BATTLE_GROUP:
+
131  case DESTROYER_SQUADRON:
+
132  case ATTACK_SQUADRON:
+
133  case FIGHTER_SQUADRON:
+
134  case INTERCEPT_SQUADRON:
+
135  case LCA_SQUADRON:
+
136  case COURIER:
+
137  case MEDICAL:
+
138  case SUPPLY:
+
139  case REPAIR:
+
140  case FREIGHT:
+
141  case PASSENGER:
+
142  case PRIVATE:
+
143  return true;
+
144  }
+
145 
+
146  return false;
+
147 }
+
148 
+
149 // +--------------------------------------------------------------------+
+
150 
+
151 bool
+ +
153 {
+
154  switch (type) {
+
155  case WING:
+
156  case INTERCEPT_SQUADRON:
+
157  case FIGHTER_SQUADRON:
+
158  case ATTACK_SQUADRON:
+
159  return true;
+
160  }
+
161 
+
162  return false;
+
163 }
+
164 
+
165 bool
+ +
167 {
+
168  switch (type) {
+
169  case DESTROYER_SQUADRON:
+
170  case BATTLE_GROUP:
+
171  case CARRIER_GROUP:
+
172  return true;
+
173  }
+
174 
+
175  return false;
+
176 }
+
177 
+
178 // +--------------------------------------------------------------------+
+
179 
+
180 bool
+ +
182 {
+
183  if (enemy_intel <= Intel::RESERVE)
+
184  return true;
+
185 
+
186  if (parent)
+
187  return parent->IsReserve();
+
188 
+
189  return false;
+
190 }
+
191 
+
192 // +--------------------------------------------------------------------+
+
193 
+
194 const int*
+ +
196 {
+
197  static int p[8];
+
198 
+
199  ZeroMemory(p, sizeof(p));
+
200 
+
201  switch (type) {
+
202  //case FLEET:
+ +
204  p[1] = BATTLE_GROUP;
+
205  p[2] = CARRIER_GROUP;
+
206  p[3] = ATTACK_SQUADRON;
+
207  break;
+
208 
+
209  case BATTLE_GROUP: p[0] = BATTLE_GROUP;
+
210  p[1] = DESTROYER_SQUADRON;
+
211  p[2] = CARRIER_GROUP;
+
212  p[3] = ATTACK_SQUADRON;
+
213  break;
+
214 
+
215  case CARRIER_GROUP: p[0] = ATTACK_SQUADRON;
+
216  p[1] = BATTLE_GROUP;
+
217  p[2] = DESTROYER_SQUADRON;
+
218  p[3] = CARRIER_GROUP;
+
219  break;
+
220 
+
221  //case WING:
+
222  case LCA_SQUADRON:
+
223  case ATTACK_SQUADRON:
+
224  case INTERCEPT_SQUADRON:
+ +
226  p[1] = FIGHTER_SQUADRON;
+
227  break;
+
228 
+
229  //case BATTALION:
+
230  case STATION: p[0] = BATTLE_GROUP;
+
231  p[1] = CARRIER_GROUP;
+
232  break;
+
233 
+
234  case STARBASE:
+
235  case BATTERY:
+
236  case MISSILE: p[0] = ATTACK_SQUADRON;
+
237  p[1] = FIGHTER_SQUADRON;
+
238  break;
+
239 
+
240  //case C3I:
+
241  case MINEFIELD:
+
242  case COMM_RELAY:
+
243  case EARLY_WARNING:
+
244  case FWD_CONTROL_CTR:
+
245  case ECM: p[0] = ATTACK_SQUADRON;
+
246  p[1] = FIGHTER_SQUADRON;
+
247  p[2] = DESTROYER_SQUADRON;
+
248  break;
+
249 
+
250  //case SUPPORT:
+
251  case COURIER:
+
252  case MEDICAL:
+
253  case SUPPLY:
+
254  case REPAIR: p[0] = DESTROYER_SQUADRON;
+
255  p[1] = BATTLE_GROUP;
+
256  p[2] = ATTACK_SQUADRON;
+
257  break;
+
258 
+
259  //case CIVILIAN:
+
260 
+
261  //case WAR_PRODuCTION:
+
262  case FACTORY:
+
263  case REFINERY:
+
264  case RESOURCE: p[0] = ATTACK_SQUADRON;
+
265  p[1] = FIGHTER_SQUADRON;
+
266  break;
+
267 
+
268  //case INFRASTRUCTURE:
+
269  case TRANSPORT:
+
270  case NETWORK:
+
271  case HABITAT:
+
272  case STORAGE: p[0] = ATTACK_SQUADRON;
+
273  p[1] = FIGHTER_SQUADRON;
+
274  break;
+
275 
+
276  //case NON_COM:
+
277  case FREIGHT:
+
278  case PASSENGER:
+
279  case PRIVATE: p[0] = DESTROYER_SQUADRON;
+
280  p[1] = ATTACK_SQUADRON;
+
281  break;
+
282  }
+
283 
+
284  return p;
+
285 }
+
286 
+
287 // +--------------------------------------------------------------------+
+
288 
+
289 const int*
+ +
291 {
+
292  static int p[8];
+
293 
+
294  ZeroMemory(p, sizeof(p));
+
295 
+
296  switch (type) {
+
297  //case FLEET:
+
298  case CARRIER_GROUP:
+
299  case BATTLE_GROUP:
+
300  case DESTROYER_SQUADRON:
+
301 
+
302  //case WING:
+
303  case LCA_SQUADRON:
+
304  case ATTACK_SQUADRON:
+
305  case INTERCEPT_SQUADRON:
+
306  case FIGHTER_SQUADRON: break;
+
307 
+
308  //case BATTALION:
+
309  case STATION: p[0] = BATTLE_GROUP;
+
310  p[1] = CARRIER_GROUP;
+
311  p[2] = DESTROYER_SQUADRON;
+
312  break;
+
313  case STARBASE:
+
314  case MINEFIELD:
+
315  case BATTERY:
+
316  case MISSILE: p[0] = FIGHTER_SQUADRON;
+
317  p[1] = INTERCEPT_SQUADRON;
+
318  break;
+
319 
+
320  //case C3I:
+
321  case COMM_RELAY:
+
322  case EARLY_WARNING:
+
323  case FWD_CONTROL_CTR:
+
324  case ECM: p[0] = FIGHTER_SQUADRON;
+
325  p[1] = INTERCEPT_SQUADRON;
+
326  break;
+
327 
+
328  //case SUPPORT:
+
329  case COURIER:
+
330  case MEDICAL:
+
331  case SUPPLY:
+
332  case REPAIR: p[0] = DESTROYER_SQUADRON;
+
333  p[1] = BATTLE_GROUP;
+
334  p[2] = ATTACK_SQUADRON;
+
335  break;
+
336 
+
337  //case CIVILIAN:
+
338 
+
339  //case WAR_PRODuCTION:
+
340  case FACTORY:
+
341  case REFINERY:
+
342  case RESOURCE: p[0] = FIGHTER_SQUADRON;
+
343  p[1] = INTERCEPT_SQUADRON;
+
344  break;
+
345 
+
346  //case INFRASTRUCTURE:
+
347  case TRANSPORT:
+
348  case NETWORK:
+
349  case HABITAT:
+
350  case STORAGE: p[0] = FIGHTER_SQUADRON;
+
351  p[1] = INTERCEPT_SQUADRON;
+
352  break;
+
353 
+
354  //case NON_COM:
+
355  case FREIGHT:
+
356  case PASSENGER:
+
357  case PRIVATE: p[0] = DESTROYER_SQUADRON;
+
358  p[1] = BATTLE_GROUP;
+
359  break;
+
360  }
+
361 
+
362  return p;
+
363 }
+
364 
+
365 // +--------------------------------------------------------------------+
+
366 
+ + +
369 {
+
370  CombatGroup* result = 0;
+
371 
+
372  if (type == t && (n < 0 || id == n))
+
373  result = this;
+
374 
+
375  ListIter<CombatGroup> group = components;
+
376  while (!result && ++group) {
+
377  result = group->FindGroup(t, n);
+
378  }
+
379 
+
380  return result;
+
381 }
+
382 
+
383 // +--------------------------------------------------------------------+
+
384 
+ + +
387 {
+
388  CombatGroup* clone = new(__FILE__,__LINE__)
+
389  CombatGroup(type, id, name, iff, enemy_intel);
+
390 
+
391  clone->combatant = combatant;
+
392  clone->region = region;
+
393  clone->location = location;
+
394  clone->value = value;
+
395  clone->expanded = expanded;
+
396 
+
397  for (int i = 0; i < units.size(); i++) {
+
398  CombatUnit* u = new(__FILE__,__LINE__) CombatUnit(*units[i]);
+
399  u->SetCombatGroup(clone);
+
400  clone->units.append(u);
+
401  }
+
402 
+
403  if (deep) {
+
404  for (int i = 0; i < components.size(); i++) {
+
405  CombatGroup* g = components[i]->Clone(deep);
+
406  clone->AddComponent(g);
+
407 
+
408  if (g->Type() == FIGHTER_SQUADRON ||
+
409  g->Type() == INTERCEPT_SQUADRON ||
+
410  g->Type() == ATTACK_SQUADRON ||
+
411  g->Type() == LCA_SQUADRON) {
+
412 
+
413  if (units.size() > 0) {
+
414  CombatUnit* carrier = units[0];
+
415 
+
416  for (int u = 0; u < g->GetUnits().size(); u++) {
+
417  CombatUnit* unit = g->GetUnits()[u];
+
418 
+
419  if (unit->Type() >= Ship::FIGHTER ||
+
420  unit->Type() <= Ship::LCA) {
+
421  unit->SetCarrier(carrier);
+
422  unit->SetRegion(carrier->GetRegion());
+
423  }
+
424  }
+
425  }
+
426  }
+
427  }
+
428  }
+
429 
+
430  return clone;
+
431 }
+
432 
+
433 // +--------------------------------------------------------------------+
+
434 
+
435 const char*
+
436 CombatGroup::GetOrdinal() const
+
437 {
+
438  static char ordinal[16];
+
439 
+
440  int last_two_digits = id % 100;
+
441 
+
442  if (last_two_digits > 10 && last_two_digits < 20) {
+
443  sprintf_s(ordinal, "ordinal.%d", last_two_digits);
+
444  Text suffix = Game::GetText(ordinal);
+
445 
+
446  if (suffix != ordinal)
+
447  sprintf_s(ordinal, "%d%s", id, suffix.data());
+
448  else
+
449  sprintf_s(ordinal, "%dth", id);
+
450  }
+
451  else {
+
452  int last_digit = last_two_digits % 10;
+
453  sprintf_s(ordinal, "ordinal.%d", last_digit);
+
454  Text suffix = Game::GetText(ordinal);
+
455  if (suffix != ordinal)
+
456  sprintf_s(ordinal, "%d%s", id, suffix.data());
+
457  else if (last_digit == 1)
+
458  sprintf_s(ordinal, "%dst", id);
+
459  else if (last_digit == 2)
+
460  sprintf_s(ordinal, "%dnd", id);
+
461  else if (last_digit == 3)
+
462  sprintf_s(ordinal, "%drd", id);
+
463  else
+
464  sprintf_s(ordinal, "%dth", id);
+
465  }
+
466 
+
467  return ordinal;
+
468 }
+
469 
+
470 const char*
+ +
472 {
+
473  static char desc[256];
+
474  static char name_desc[256];
+
475 
+
476  if (name.length())
+
477  sprintf_s(name_desc, " \"%s\"", (const char*) name);
+
478  else
+
479  name_desc[0] = 0;
+
480 
+
481  switch (type) {
+
482  case FORCE: strcpy_s(desc, (const char*) name); break;
+
483 
+
484  case FLEET: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.FLEET").data(), name_desc); break;
+
485  case CARRIER_GROUP: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.CARRIER_GROUP").data(), name_desc); break;
+
486  case BATTLE_GROUP: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.BATTLE_GROUP").data(), name_desc); break;
+
487  case DESTROYER_SQUADRON: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.DESTROYER_SQUADRON").data(), name_desc); break;
+
488 
+
489  case WING: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.WING").data(), name_desc); break;
+
490  case ATTACK_SQUADRON: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.ATTACK_SQUADRON").data(), name_desc); break;
+
491  case FIGHTER_SQUADRON: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.FIGHTER_SQUADRON").data(), name_desc); break;
+
492  case INTERCEPT_SQUADRON: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.INTERCEPT_SQUADRON").data(), name_desc); break;
+
493  case LCA_SQUADRON: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.LCA_SQUADRON").data(), name_desc); break;
+
494 
+
495  case BATTALION: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.BATTALION").data(), name_desc); break;
+
496  case STATION: sprintf_s(desc, "%s %s", Game::GetText("CombatGroup.STATION").data(), name.data()); break;
+
497  case STARBASE: sprintf_s(desc, "%s %d%s", Game::GetText("CombatGroup.STARBASE").data(), id, name_desc); break;
+
498  case MINEFIELD: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.MINEFIELD").data(), name_desc); break;
+
499  case BATTERY: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.BATTERY").data(), name_desc); break;
+
500  case MISSILE: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.MISSILE").data(), name_desc); break;
+
501 
+
502  case C3I: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.C3I").data(), name_desc); break;
+
503  case COMM_RELAY: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.COMM_RELAY").data(), name_desc); break;
+
504  case EARLY_WARNING: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.EARLY_WARNING").data(), name_desc); break;
+
505  case FWD_CONTROL_CTR: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.FWD_CONTROL_CTR").data(), name_desc); break;
+
506  case ECM: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.ECM").data(), name_desc); break;
+
507 
+
508  case SUPPORT: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.SUPPORT").data(), name_desc); break;
+
509  case COURIER: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.COURIER").data(), name_desc); break;
+
510  case SUPPLY: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.SUPPLY").data(), name_desc); break;
+
511  case REPAIR: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.REPAIR").data(), name_desc); break;
+
512  case MEDICAL: sprintf_s(desc, "%s %s%s", GetOrdinal(), Game::GetText("CombatGroup.MEDICAL").data(), name_desc); break;
+
513 
+
514  case CIVILIAN:
+
515  case WAR_PRODUCTION:
+
516  case FACTORY:
+
517  case REFINERY:
+
518  case RESOURCE: strcpy_s(desc, (const char*) name); break;
+
519 
+
520  case INFRASTRUCTURE:
+
521  case TRANSPORT:
+
522  case NETWORK:
+
523  case HABITAT:
+
524  case STORAGE:
+
525  case FREIGHT:
+
526  case PASSENGER:
+
527  case PRIVATE: strcpy_s(desc, (const char*) name); break;
+
528 
+
529  default: sprintf_s(desc, "%s%s", Game::GetText("CombatGroup.default").data(), name_desc); break;
+
530  }
+
531 
+
532  return desc;
+
533 }
+
534 
+
535 const char*
+ +
537 {
+
538  static char desc[256];
+
539 
+
540  switch (type) {
+
541  case FORCE: strcpy_s(desc, (const char*) name); break;
+
542 
+
543  case FLEET: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.FLEET").data()); break;
+
544  case CARRIER_GROUP: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.CARRIER_GROUP").data()); break;
+
545  case BATTLE_GROUP: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.BATTLE_GROUP").data()); break;
+
546  case DESTROYER_SQUADRON: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.DESTROYER_SQUADRON").data()); break;
+
547 
+
548  case WING: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.WING").data()); break;
+
549  case ATTACK_SQUADRON: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.ATTACK_SQUADRON").data()); break;
+
550  case FIGHTER_SQUADRON: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.FIGHTER_SQUADRON").data()); break;
+
551  case INTERCEPT_SQUADRON: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.INTERCEPT_SQUADRON").data()); break;
+
552  case LCA_SQUADRON: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.LCA_SQUADRON").data()); break;
+
553 
+
554  case BATTALION: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.BATTALION").data()); break;
+
555  case STATION: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.STATION").data()); break;
+
556  case STARBASE: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.STARBASE").data()); break;
+
557  case MINEFIELD: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.MINEFIELD").data()); break;
+
558  case BATTERY: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.BATTERY").data()); break;
+
559 
+
560  case C3I: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.C3I").data()); break;
+
561  case COMM_RELAY: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.COMM_RELAY").data()); break;
+
562  case EARLY_WARNING: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.EARLY_WARNING").data()); break;
+
563  case FWD_CONTROL_CTR: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.FWD_CONTROL_CTR").data()); break;
+
564  case ECM: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.ECM").data()); break;
+
565 
+
566  case SUPPORT: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.SUPPORT").data()); break;
+
567  case COURIER: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.COURIER").data()); break;
+
568  case MEDICAL: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.MEDICAL").data()); break;
+
569  case SUPPLY: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.SUPPLY").data()); break;
+
570  case REPAIR: sprintf_s(desc, "%s %s", GetOrdinal(), Game::GetText("CombatGroup.abrv.REPAIR").data()); break;
+
571 
+
572  case CIVILIAN:
+
573  case WAR_PRODUCTION:
+
574  case FACTORY:
+
575  case REFINERY:
+
576  case RESOURCE: strcpy_s(desc, (const char*) name); break;
+
577 
+
578  case INFRASTRUCTURE:
+
579  case TRANSPORT:
+
580  case NETWORK:
+
581  case HABITAT:
+
582  case STORAGE:
+
583  case FREIGHT:
+
584  case PASSENGER:
+
585  case PRIVATE: strcpy_s(desc, (const char*) name); break;
+
586 
+
587  default: sprintf_s(desc, "%s", Game::GetText("CombatGroup.abrv.default").data()); break;
+
588  }
+
589 
+
590  return desc;
+
591 }
+
592 
+
593 // +--------------------------------------------------------------------+
+
594 
+
595 double
+ +
597 {
+
598  double t = 0;
+
599 
+
600  ListIter<CombatUnit> unit = ((CombatGroup*) this)->units;
+
601  while (++unit)
+
602  if (unit->GetNextJumpTime() > t)
+
603  t = unit->GetNextJumpTime();
+
604 
+
605  return t;
+
606 }
+
607 
+
608 // +--------------------------------------------------------------------+
+
609 
+
610 void
+ +
612 {
+
613  location = loc;
+
614 }
+
615 
+
616 // +--------------------------------------------------------------------+
+
617 
+
618 void
+ +
620 {
+
621  assigned_system = s;
+
622  assigned_zone = 0;
+
623  zone_lock = false;
+
624 
+
625  ListIter<CombatGroup> iter = components;
+
626  while (++iter) {
+
627  CombatGroup* g = iter.value();
+
628  g->SetAssignedSystem(s);
+
629  }
+
630 }
+
631 
+
632 void
+ +
634 {
+
635  assigned_zone = z;
+
636 
+
637  if (!assigned_zone)
+
638  zone_lock = false;
+
639 
+
640  ListIter<CombatGroup> iter = components;
+
641  while (++iter) {
+
642  CombatGroup* g = iter.value();
+
643  g->SetAssignedZone(z);
+
644  }
+
645 }
+
646 
+
647 void
+ +
649 {
+
650  if (!zone_lock)
+
651  assigned_zone = 0;
+
652 
+
653  ListIter<CombatGroup> iter = components;
+
654  while (++iter) {
+
655  CombatGroup* g = iter.value();
+
656  g->ClearUnlockedZones();
+
657  }
+
658 }
+
659 
+
660 void
+ +
662 {
+
663  if (!assigned_zone)
+
664  zone_lock = false;
+
665  else
+
666  zone_lock = lock;
+
667 
+
668  if (zone_lock)
+
669  assigned_system = Text();
+
670 
+
671  ListIter<CombatGroup> iter = components;
+
672  while (++iter) {
+
673  CombatGroup* g = iter.value();
+
674  g->SetZoneLock(lock);
+
675  }
+
676 }
+
677 
+
678 // +--------------------------------------------------------------------+
+
679 
+
680 void
+ +
682 {
+
683  if (n < Intel::RESERVE || n > Intel::TRACKED) return;
+
684 
+
685  enemy_intel = n;
+
686 
+
687  // if this group has been discovered, the entire
+
688  // branch of the OOB tree must be exposed. Otherwise,
+
689  // no missions would ever be planned against this
+
690  // combat group.
+
691 
+
692  if (n > Intel::SECRET) {
+
693  CombatGroup* p = parent;
+
694  while (p) {
+
695  if (p->enemy_intel < Intel::KNOWN)
+
696  p->enemy_intel = Intel::KNOWN;
+
697 
+
698  p = p->parent;
+
699  }
+
700  }
+
701 }
+
702 
+
703 // +--------------------------------------------------------------------+
+
704 
+
705 int
+ +
707 {
+
708  int val = 0;
+
709 
+
710  ListIter<CombatUnit> unit = units;
+
711  while (++unit)
+
712  val += unit->GetValue();
+
713 
+
714  ListIter<CombatGroup> comp = components;
+
715  while (++comp)
+
716  val += comp->CalcValue();
+
717 
+
718  value = val;
+
719  return value;
+
720 }
+
721 
+
722 int
+ +
724 {
+
725  int n = 0;
+
726 
+
727  CombatGroup* g = (CombatGroup*) this;
+
728 
+
729  ListIter<CombatUnit> unit = g->units;
+
730  while (++unit)
+
731  n += unit->Count() - unit->DeadCount();
+
732 
+
733  CombatGroup* pThis = ((CombatGroup*) this);
+
734  pThis->live_comp.clear();
+
735  ListIter<CombatGroup> iter = g->components;
+
736  while (++iter) {
+
737  CombatGroup* comp = iter.value();
+
738 
+
739  if (!comp->IsReserve()) {
+
740  int unit_count = comp->CountUnits();
+
741  if (unit_count > 0)
+
742  pThis->live_comp.append(comp);
+
743 
+
744  n += unit_count;
+
745  }
+
746  }
+
747 
+
748  return n;
+
749 }
+
750 
+
751 // +--------------------------------------------------------------------+
+
752 
+
753 void
+ +
755 {
+
756  assignments.destroy();
+
757 
+
758  ListIter<CombatGroup> comp = components;
+
759  while (++comp)
+
760  comp->ClearAssignments();
+
761 }
+
762 
+
763 // +--------------------------------------------------------------------+
+
764 
+ + +
767 {
+
768  CombatGroup* p = GetParent();
+
769 
+
770  while (p != 0 &&
+ +
772  p->Type() != CombatGroup::STATION &&
+
773  p->Type() != CombatGroup::STARBASE)
+
774  p = p->GetParent();
+
775 
+
776  if (p && p->GetUnits().size())
+
777  return p;
+
778 
+
779  return 0;
+
780 }
+
781 
+
782 CombatUnit*
+ +
784 {
+
785  CombatUnit* result = 0;
+
786  List<CombatUnit> live;
+
787 
+
788  ListIter<CombatUnit> unit = units;
+
789  while (++unit) {
+
790  if (unit->Count() - unit->DeadCount() > 0)
+
791  live.append(unit.value());
+
792  }
+
793 
+
794  if (live.size() > 0) {
+
795  int ntries = 5;
+
796  while (!result && ntries-- > 0) {
+
797  int index = rand() % live.size();
+
798  result = live[index];
+
799 
+
800  int ship_class = result->GetShipClass();
+
801  if (ship_class >= Ship::CRUISER &&
+
802  ship_class <= Ship::FARCASTER)
+
803  result = 0;
+
804  }
+
805  }
+
806 
+
807  if (!result) {
+
808  ListIter<CombatGroup> comp = components;
+
809  while (++comp && !result) {
+
810  CombatUnit* u = comp->GetRandomUnit();
+
811  if (u)
+
812  result = u;
+
813  }
+
814  }
+
815 
+
816  return result;
+
817 }
+
818 
+
819 CombatUnit*
+ +
821 {
+
822  int tmp_index = unit_index;
+
823  unit_index = 0;
+
824  CombatUnit* result = GetNextUnit();
+
825  unit_index = tmp_index;
+
826 
+
827  return result;
+
828 }
+
829 
+
830 CombatUnit*
+ +
832 {
+
833  if (units.size() > 0) {
+
834  List<CombatUnit> live;
+
835 
+
836  ListIter<CombatUnit> unit = units;
+
837  while (++unit) {
+
838  if (unit->Count() - unit->DeadCount() > 0)
+
839  live.append(unit.value());
+
840  }
+
841 
+
842  if (live.size() > 0) {
+
843  return live[unit_index++ % live.size()];
+
844  }
+
845  }
+
846 
+
847  if (components.size() > 0) {
+
848  return components[unit_index % components.size()]->GetNextUnit();
+
849  }
+
850 
+
851  return 0;
+
852 }
+
853 
+
854 CombatUnit*
+
855 CombatGroup::FindUnit(const char* name)
+
856 {
+
857  if (units.size() > 0) {
+
858  ListIter<CombatUnit> iter = units;
+
859  while (++iter) {
+
860  CombatUnit* unit = iter.value();
+
861  if (unit->Name() == name) {
+
862  if (unit->Count() - unit->DeadCount() > 0)
+
863  return unit;
+
864  else
+
865  return 0;
+
866  }
+
867  }
+
868  }
+
869 
+
870  return 0;
+
871 }
+
872 
+
873 void
+ +
875 {
+
876  region = rgn;
+
877 
+
878  ListIter<CombatGroup> comp = components;
+
879  while (++comp)
+
880  comp->AssignRegion(rgn);
+
881 
+
882  ListIter<CombatUnit> unit = units;
+
883  while (++unit)
+
884  unit->SetRegion(rgn);
+
885 }
+
886 
+
887 // +--------------------------------------------------------------------+
+
888 
+
889 static const char* group_name[] = {
+
890  "",
+
891  "force",
+
892  "wing",
+
893  "intercept_squadron",
+
894  "fighter_squadron",
+
895  "attack_squadron",
+
896  "lca_squadron",
+
897  "fleet",
+
898  "destroyer_squadron",
+
899  "battle_group",
+
900  "carrier_group",
+
901  "battalion",
+
902  "minefield",
+
903  "battery",
+
904  "missile",
+
905  "station",
+
906  "starbase",
+
907  "c3i",
+
908  "comm_relay",
+
909  "early_warning",
+
910  "fwd_control_ctr",
+
911  "ecm",
+
912  "support",
+
913  "courier",
+
914  "medical",
+
915  "supply",
+
916  "repair",
+
917  "civilian",
+
918  "war_production",
+
919  "factory",
+
920  "refinery",
+
921  "resource",
+
922  "infrastructure",
+
923  "transport",
+
924  "network",
+
925  "habitat",
+
926  "storage",
+
927  "non_com",
+
928  "freight",
+
929  "passenger",
+
930  "private"
+
931 };
+
932 
+
933 // +--------------------------------------------------------------------+
+
934 
+
935 int
+
936 CombatGroup::TypeFromName(const char* type_name)
+
937 {
+
938  for (int i = FORCE; i < PRIVATE; i++)
+
939  if (!_stricmp(type_name, group_name[i]))
+
940  return i;
+
941 
+
942  return 0;
+
943 }
+
944 
+
945 const char*
+ +
947 {
+
948  return group_name[type];
+
949 }
+
950 
+
951 // +--------------------------------------------------------------------+
+
952 
+
953 int ShipClassFromName(const char* type_name)
+
954 {
+
955  return Ship::ClassForName(type_name);
+
956 }
+
957 
+
958 // +--------------------------------------------------------------------+
+
959 
+
960 #define GET_DEF_BOOL(n) if (pdef->name()->value()==(#n)) GetDefBool((n), pdef, filename)
+
961 #define GET_DEF_TEXT(n) if (pdef->name()->value()==(#n)) GetDefText((n), pdef, filename)
+
962 #define GET_DEF_NUM(n) if (pdef->name()->value()==(#n)) GetDefNumber((n), pdef, filename)
+
963 #define GET_DEF_VEC(n) if (pdef->name()->value()==(#n)) GetDefVec((n), pdef, filename)
+
964 
+ +
966 CombatGroup::LoadOrderOfBattle(const char* filename, int team, Combatant* combatant)
+
967 {
+
968  CombatGroup* force = 0;
+
969  DataLoader* loader = DataLoader::GetLoader();
+
970  BYTE* block;
+
971  loader->LoadBuffer(filename, block, true);
+
972 
+
973  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
+
974  Term* term = parser.ParseTerm();
+
975 
+
976  if (!term) {
+
977  Print("ERROR: could not parse order of battle '%s'\n", filename);
+
978  return 0;
+
979  }
+
980  else {
+
981  TermText* file_type = term->isText();
+
982  if (!file_type || file_type->value() != "ORDER_OF_BATTLE") {
+
983  Print("ERROR: invalid Order of Battle file '%s'\n", filename);
+
984  term->print(10);
+
985  return 0;
+
986  }
+
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() == "group") {
+
998  if (!def->term() || !def->term()->isStruct()) {
+
999  Print("WARNING: group struct missing in '%s'\n", filename);
+
1000  }
+
1001  else {
+
1002  TermStruct* val = def->term()->isStruct();
+
1003 
+
1004  char name[256];
+
1005  char type[64];
+
1006  char intel[64];
+
1007  char region[64];
+
1008  char system[64];
+
1009  char parent_type[64];
+
1010  int parent_id = 0;
+
1011  int id = 0;
+
1012  int iff = -1;
+
1013  Vec3 loc = Vec3(1.0e9f,0.0f,0.0f);
+
1014 
+
1015  List<CombatUnit> unit_list;
+
1016  char unit_name[64];
+
1017  char unit_regnum[16];
+
1018  char unit_design[64];
+
1019  char unit_skin[64];
+
1020  int unit_class = 0;
+
1021  int unit_count = 1;
+
1022  int unit_dead = 0;
+
1023  int unit_damage = 0;
+
1024  int unit_heading= 0;
+
1025  int unit_index = 0;
+
1026 
+
1027  *name = 0;
+
1028  *type = 0;
+
1029  *intel = 0;
+
1030  *region = 0;
+
1031  *system = 0;
+
1032  *parent_type = 0;
+
1033  *unit_name = 0;
+
1034  *unit_regnum = 0;
+
1035  *unit_design = 0;
+
1036  *unit_skin = 0;
+
1037 
+
1038  strcpy_s(intel, "KNOWN");
+
1039 
+
1040  // all groups in this OOB default to the IFF of the main force
+
1041  if (force)
+
1042  iff = force->GetIFF();
+
1043 
+
1044  for (int i = 0; i < val->elements()->size(); i++) {
+
1045  TermDef* pdef = val->elements()->at(i)->isDef();
+
1046  if (pdef && (iff < 0 || team < 0 || iff == team)) {
+
1047  GET_DEF_TEXT(name);
+
1048  else GET_DEF_TEXT(type);
+
1049  else GET_DEF_TEXT(intel);
+
1050  else GET_DEF_TEXT(region);
+
1051  else GET_DEF_TEXT(system);
+
1052  else GET_DEF_VEC(loc);
+
1053  else GET_DEF_TEXT(parent_type);
+
1054  else GET_DEF_NUM(parent_id);
+
1055  else GET_DEF_NUM(iff);
+
1056  else GET_DEF_NUM(id);
+
1057  else GET_DEF_NUM(unit_index);
+
1058 
+
1059  else if ((iff == team || team < 0) && pdef->name()->value() == "unit") {
+
1060  if (!pdef->term() || !pdef->term()->isStruct()) {
+
1061  Print("WARNING: unit struct missing for group '%s' in '%s'\n", name, filename);
+
1062  }
+
1063  else {
+
1064  TermStruct* val = pdef->term()->isStruct();
+
1065 
+
1066  char unit_region[64];
+
1067  char design[256];
+
1068  Vec3 unit_loc = Vec3(1.0e9f,0.0f,0.0f);
+
1069  unit_count = 1;
+
1070 
+
1071  ZeroMemory(unit_region, sizeof(unit_region));
+
1072  ZeroMemory(design, sizeof(design));
+
1073 
+
1074  for (int i = 0; i < val->elements()->size(); i++) {
+
1075  TermDef* pdef = val->elements()->at(i)->isDef();
+
1076  if (pdef) {
+
1077  if (pdef->name()->value() == "name") {
+
1078  GetDefText(unit_name, pdef, filename);
+
1079  }
+
1080  else if (pdef->name()->value() == "regnum") {
+
1081  GetDefText(unit_regnum, pdef, filename);
+
1082  }
+
1083  else if (pdef->name()->value() == "region") {
+
1084  GetDefText(unit_region, pdef, filename);
+
1085  }
+
1086  else if (pdef->name()->value() == "loc") {
+
1087  GetDefVec(unit_loc, pdef, filename);
+
1088  }
+
1089  else if (pdef->name()->value() == "type") {
+
1090  char typestr[32];
+
1091  GetDefText(typestr, pdef, filename);
+
1092  unit_class = ShipDesign::ClassForName(typestr);
+
1093  }
+
1094  else if (pdef->name()->value() == "design") {
+
1095  GetDefText(unit_design, pdef, filename);
+
1096  }
+
1097  else if (pdef->name()->value() == "skin") {
+
1098  GetDefText(unit_skin, pdef, filename);
+
1099  }
+
1100  else if (pdef->name()->value() == "count") {
+
1101  GetDefNumber(unit_count, pdef, filename);
+
1102  }
+
1103  else if (pdef->name()->value() == "dead_count") {
+
1104  GetDefNumber(unit_dead, pdef, filename);
+
1105  }
+
1106  else if (pdef->name()->value() == "damage") {
+
1107  GetDefNumber(unit_damage, pdef, filename);
+
1108  }
+
1109  else if (pdef->name()->value() == "heading") {
+
1110  GetDefNumber(unit_heading, pdef, filename);
+
1111  }
+
1112  }
+
1113  }
+
1114 
+
1115  if (!ShipDesign::CheckName(unit_design)) {
+
1116  Print("ERROR: invalid design '%s' for unit '%s' in '%s'\n", unit_design, unit_name, filename);
+
1117  return 0;
+
1118  }
+
1119 
+
1120  CombatUnit* cu = new(__FILE__,__LINE__) CombatUnit(unit_name, unit_regnum, unit_class, unit_design, unit_count, iff);
+
1121  cu->SetRegion(unit_region);
+
1122  cu->SetSkin(unit_skin);
+
1123  cu->MoveTo(unit_loc);
+
1124  cu->Kill(unit_dead);
+
1125  cu->SetSustainedDamage(unit_damage);
+
1126  cu->SetHeading(unit_heading * DEGREES);
+
1127  unit_list.append(cu);
+
1128  }
+
1129  }
+
1130  }
+
1131  } // elements
+
1132 
+
1133  if (iff >= 0 && (iff == team || team < 0)) {
+
1134  CombatGroup* parent_group = 0;
+
1135 
+
1136  if (force) {
+
1137  parent_group = force->FindGroup(TypeFromName(parent_type), parent_id);
+
1138  }
+
1139 
+
1140  CombatGroup* g = new(__FILE__,__LINE__)
+
1141  CombatGroup(TypeFromName(type), id, name, iff, Intel::IntelFromName(intel), parent_group);
+
1142 
+
1143  g->region = region;
+
1144  g->combatant = combatant;
+
1145  g->unit_index = unit_index;
+
1146 
+
1147  if (loc.x >= 1e9) {
+
1148  if (parent_group)
+
1149  g->location = parent_group->location;
+
1150  else
+
1151  g->location = Vec3(0,0,0);
+
1152  }
+
1153  else {
+
1154  g->location = loc;
+
1155  }
+
1156 
+
1157  if (unit_list.size()) {
+
1158  unit_list[0]->SetLeader(true);
+
1159 
+
1160  ListIter<CombatUnit> u = unit_list;
+
1161  while (++u) {
+
1162  u->SetCombatGroup(g);
+
1163 
+
1164  if (u->GetRegion().length() < 1) {
+
1165  u->SetRegion(g->GetRegion());
+
1166  u->MoveTo(g->Location());
+
1167  }
+
1168 
+
1169  if (parent_group &&
+
1170  (u->Type() == Ship::FIGHTER ||
+
1171  u->Type() == Ship::ATTACK)) {
+
1172 
+
1173  CombatUnit* carrier = 0;
+
1174  CombatGroup* p = parent_group;
+
1175 
+
1176  while (p && !carrier) {
+
1177  if (p->units.size() && p->units[0]->Type() == Ship::CARRIER) {
+
1178  carrier = p->units[0];
+
1179  u->SetCarrier(carrier);
+
1180  u->SetRegion(carrier->GetRegion());
+
1181  }
+
1182 
+
1183  p = p->parent;
+
1184  }
+
1185  }
+
1186  }
+
1187 
+
1188  g->units.append(unit_list);
+
1189  }
+
1190 
+
1191  if (!force)
+
1192  force = g;
+
1193  } // iff == team?
+
1194  } // group-struct
+
1195  } // group
+
1196  } // def
+
1197  } // term
+
1198  }
+
1199  while (term);
+
1200 
+
1201  loader->ReleaseBuffer(block);
+
1202  Print("Order of Battle Loaded (%s).\n", force ? force->Name().data() : "unknown force");
+
1203 
+
1204  if (force)
+
1205  force->CalcValue();
+
1206 
+
1207  return force;
+
1208 }
+
1209 
+
1210 // +--------------------------------------------------------------------+
+
1211 
+
1212 void
+
1213 CombatGroup::MergeOrderOfBattle(BYTE* block, const char* filename, int team, Combatant* combatant, Campaign* campaign)
+
1214 {
+
1215  CombatGroup* force = 0;
+
1216 
+
1217  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
+
1218  Term* term = parser.ParseTerm();
+
1219 
+
1220  if (!term) {
+
1221  Print("ERROR: could not parse order of battle '%s'\n", filename);
+
1222  return;
+
1223  }
+
1224  else {
+
1225  TermText* file_type = term->isText();
+
1226  if (!file_type || file_type->value() != "SAVEGAME") {
+
1227  Print("ERROR: invalid Save Game file '%s'\n", filename);
+
1228  term->print(10);
+
1229  return;
+
1230  }
+
1231  }
+
1232 
+
1233 
+
1234  do {
+
1235  delete term; term = 0;
+
1236  term = parser.ParseTerm();
+
1237 
+
1238  if (term) {
+
1239  TermDef* def = term->isDef();
+
1240  if (def) {
+
1241  if (def->name()->value() == "group") {
+
1242  if (!def->term() || !def->term()->isStruct()) {
+
1243  Print("WARNING: group struct missing in '%s'\n", filename);
+
1244  }
+
1245  else {
+
1246  TermStruct* val = def->term()->isStruct();
+
1247 
+
1248  char name[256];
+
1249  char type[64];
+
1250  char intel[64];
+
1251  char region[64];
+
1252  char system[64];
+
1253  char zone[64];
+
1254  bool zone_locked = false;
+
1255  int id = 0;
+
1256  int iff = -1;
+
1257  int sorties = -1;
+
1258  int kills = -1;
+
1259  int points = -1;
+
1260  Vec3 loc = Vec3(1.0e9f,0.0f,0.0f);
+
1261 
+
1262  List<CombatUnit> unit_list;
+
1263  char unit_name[64];
+
1264  char unit_regnum[16];
+
1265  char unit_design[64];
+
1266  int unit_class = 0;
+
1267  int unit_count = 1;
+
1268  int unit_dead = 0;
+
1269  int unit_damage = 0;
+
1270  int unit_heading= 0;
+
1271  int unit_index = 0;
+
1272 
+
1273  *name = 0;
+
1274  *type = 0;
+
1275  *intel = 0;
+
1276  *region = 0;
+
1277  *system = 0;
+
1278  *zone = 0;
+
1279  *unit_name = 0;
+
1280  *unit_regnum = 0;
+
1281  *unit_design = 0;
+
1282 
+
1283  strcpy_s(intel, "KNOWN");
+
1284 
+
1285  // all groups in this OOB default to the IFF of the main force
+
1286  if (force)
+
1287  iff = force->GetIFF();
+
1288 
+
1289  for (int i = 0; i < val->elements()->size(); i++) {
+
1290  TermDef* pdef = val->elements()->at(i)->isDef();
+
1291  if (pdef && (iff < 0 || team < 0 || iff == team)) {
+
1292  GET_DEF_TEXT(name);
+
1293  else GET_DEF_TEXT(type);
+
1294  else GET_DEF_TEXT(intel);
+
1295  else GET_DEF_TEXT(region);
+
1296  else GET_DEF_TEXT(system);
+
1297  else GET_DEF_TEXT(zone);
+
1298  else GET_DEF_BOOL(zone_locked);
+
1299  else GET_DEF_VEC(loc);
+
1300  else GET_DEF_NUM(iff);
+
1301  else GET_DEF_NUM(id);
+
1302  else GET_DEF_NUM(sorties);
+
1303  else GET_DEF_NUM(kills);
+
1304  else GET_DEF_NUM(points);
+
1305  else GET_DEF_NUM(unit_index);
+
1306 
+
1307  else if ((iff == team || team < 0) && pdef->name()->value() == "unit") {
+
1308  if (!pdef->term() || !pdef->term()->isStruct()) {
+
1309  Print("WARNING: unit struct missing for group '%s' in '%s'\n", name, filename);
+
1310  }
+
1311  else {
+
1312  TermStruct* val = pdef->term()->isStruct();
+
1313 
+
1314  char unit_region[64];
+
1315  char design[256];
+
1316  Vec3 unit_loc=Vec3(0.0f,0.0f,0.0f);
+
1317  unit_count = 1;
+
1318 
+
1319  ZeroMemory(unit_region, sizeof(unit_region));
+
1320  ZeroMemory(design, sizeof(design));
+
1321 
+
1322  for (int i = 0; i < val->elements()->size(); i++) {
+
1323  TermDef* pdef = val->elements()->at(i)->isDef();
+
1324  if (pdef) {
+
1325  if (pdef->name()->value() == "name") {
+
1326  GetDefText(unit_name, pdef, filename);
+
1327  }
+
1328  else if (pdef->name()->value() == "regnum") {
+
1329  GetDefText(unit_regnum, pdef, filename);
+
1330  }
+
1331  else if (pdef->name()->value() == "region") {
+
1332  GetDefText(unit_region, pdef, filename);
+
1333  }
+
1334  else if (pdef->name()->value() == "loc") {
+
1335  GetDefVec(unit_loc, pdef, filename);
+
1336  }
+
1337  else if (pdef->name()->value() == "type") {
+
1338  char typestr[32];
+
1339  GetDefText(typestr, pdef, filename);
+
1340  unit_class = ShipDesign::ClassForName(typestr);
+
1341  }
+
1342  else if (pdef->name()->value() == "design") {
+
1343  GetDefText(unit_design, pdef, filename);
+
1344  }
+
1345  else if (pdef->name()->value() == "count") {
+
1346  GetDefNumber(unit_count, pdef, filename);
+
1347  }
+
1348  else if (pdef->name()->value() == "dead_count") {
+
1349  GetDefNumber(unit_dead, pdef, filename);
+
1350  }
+
1351  else if (pdef->name()->value() == "damage") {
+
1352  GetDefNumber(unit_damage, pdef, filename);
+
1353  }
+
1354  else if (pdef->name()->value() == "heading") {
+
1355  GetDefNumber(unit_heading, pdef, filename);
+
1356  }
+
1357  }
+
1358  }
+
1359 
+
1360  if (!ShipDesign::CheckName(unit_design)) {
+
1361  Print("ERROR: invalid design '%s' for unit '%s' in '%s'\n", unit_design, unit_name, filename);
+
1362  return;
+
1363  }
+
1364 
+
1365  if (force) {
+
1366  CombatUnit* cu = new(__FILE__,__LINE__) CombatUnit(unit_name, unit_regnum, unit_class, unit_design, unit_count, iff);
+
1367  cu->SetRegion(unit_region);
+
1368  cu->MoveTo(unit_loc);
+
1369  cu->Kill(unit_dead);
+
1370  cu->SetSustainedDamage(unit_damage);
+
1371  cu->SetHeading(unit_heading * DEGREES);
+
1372  unit_list.append(cu);
+
1373  }
+
1374  }
+
1375  }
+
1376  }
+
1377  } // elements
+
1378 
+
1379  if (iff >= 0 && (iff == team || team < 0)) {
+
1380  // have we found the force group we are looking for yet?
+
1381  if (!force && !_stricmp(name, combatant->Name())) {
+
1382  force = combatant->GetForce();
+
1383  }
+
1384 
+
1385  else {
+
1386  if (!force)
+
1387  continue;
+
1388 
+
1389  // if we already have a force, and we find a second one,
+
1390  // it must be the start of a different combatant.
+
1391  // So don't process any further:
+
1392  if (TypeFromName(type) == CombatGroup::FORCE) {
+
1393  break;
+
1394  }
+
1395  }
+
1396 
+
1397  CombatGroup* g = force->FindGroup(TypeFromName(type), id);
+
1398 
+
1399  if (!g) {
+
1400  ::Print("WARNING: unexpected combat group %s %d '%s' in '%s'\n", type, id, name, filename);
+
1401  continue;
+
1402  }
+
1403 
+
1404  g->region = region;
+
1405  g->combatant = combatant;
+
1406  g->location = loc;
+
1407  g->enemy_intel = Intel::IntelFromName(intel);
+
1408  g->unit_index = unit_index;
+
1409 
+
1410  if (*zone) {
+
1411  CombatZone* combat_zone = campaign->GetZone(zone);
+
1412 
+
1413  if (combat_zone) {
+
1414  g->SetAssignedZone(combat_zone);
+
1415  g->SetZoneLock(zone_locked);
+
1416  }
+
1417  else {
+
1418  ::Print("WARNING: could not find combat zone '%s' for group %s %d '%s' in '%s'\n", zone, type, id, name, filename);
+
1419  }
+
1420  }
+
1421  else if (*system) {
+
1422  g->SetAssignedSystem(system);
+
1423  }
+
1424 
+
1425  if (sorties >= 0) g->SetSorties(sorties);
+
1426  if (kills >= 0) g->SetKills(kills);
+
1427  if (points >= 0) g->SetPoints(points);
+
1428 
+
1429  if (unit_list.size()) {
+
1430  ListIter<CombatUnit> u_iter = unit_list;
+
1431  while (++u_iter) {
+
1432  CombatUnit* load_unit = u_iter.value();
+
1433  CombatUnit* u = g->FindUnit(load_unit->Name());
+
1434 
+
1435  if (u) {
+
1436  if (load_unit->GetRegion().length() > 0) {
+
1437  u->SetRegion(load_unit->GetRegion());
+
1438  u->MoveTo(load_unit->Location());
+
1439  }
+
1440  else {
+
1441  u->SetRegion(g->GetRegion());
+
1442  u->MoveTo(g->Location());
+
1443  }
+
1444  u->SetDeadCount(load_unit->DeadCount());
+
1445  u->SetSustainedDamage(load_unit->GetSustainedDamage());
+
1446  u->SetHeading(load_unit->GetHeading());
+
1447  }
+
1448  }
+
1449 
+
1450  unit_list.destroy();
+
1451  }
+
1452 
+
1453  if (!force)
+
1454  force = g;
+
1455  } // iff == team?
+
1456  } // group-struct
+
1457  } // group
+
1458  } // def
+
1459  } // term
+
1460  }
+
1461  while (term);
+
1462 
+
1463  Print("Order of Battle Loaded (%s).\n", force ? force->Name().data() : "unknown force");
+
1464 
+
1465  if (force)
+
1466  force->CalcValue();
+
1467 }
+
1468 
+
1469 // +--------------------------------------------------------------------+
+
1470 
+ +
1472 {
+
1473  char buffer[64];
+
1474 
+
1475  if (fabs(n) < 1000)
+
1476  sprintf_s(buffer, "%d", (int) n);
+
1477 
+
1478  else if (fabs(n) < 1e6) {
+
1479  int nn = (int) n / 1000;
+
1480  sprintf_s(buffer, "%de3", nn);
+
1481  }
+
1482 
+
1483  else
+
1484  sprintf_s(buffer, "%g", n);
+
1485 
+
1486  return buffer;
+
1487 }
+
1488 
+
1489 void
+ +
1491 {
+
1492  int type = u->Type();
+
1493 
+
1494  if (type == 0 && u->GetDesign())
+
1495  type = u->GetDesign()->type;
+
1496 
+
1497  fprintf(f, "\n unit: {");
+
1498  fprintf(f, " name: \"%s\",", u->Name().data());
+
1499  fprintf(f, " type: \"%s\",", Ship::ClassName(type));
+
1500  fprintf(f, " design: \"%s\",", u->DesignName().data());
+
1501 
+
1502  if (u->Count() > 1) {
+
1503  fprintf(f, " count: %d,", u->Count());
+
1504  }
+
1505  else {
+
1506  fprintf(f, " regnum:\"%s\",", u->Registry().data());
+
1507  }
+
1508 
+
1509  if (u->GetRegion().length() > 0) {
+
1510  fprintf(f, " region:\"%s\",", u->GetRegion().data());
+
1511 
+
1512  Text x = FormatNumber(u->Location().x);
+
1513  Text y = FormatNumber(u->Location().y);
+
1514  Text z = FormatNumber(u->Location().z);
+
1515 
+
1516  fprintf(f, " loc:(%s, %s, %s),", x.data(), y.data(), z.data());
+
1517  }
+
1518 
+
1519  fprintf(f, " dead_count: %d, damage: %d, heading: %d },",
+
1520  (int) u->DeadCount(),
+
1521  (int) u->GetSustainedDamage(),
+
1522  (int) (u->GetHeading() / DEGREES));
+
1523 }
+
1524 
+
1525 void
+ +
1527 {
+
1528  fprintf(f, "group: {");
+
1529  fprintf(f, " type: %s,", CombatGroup::NameFromType(g->Type()));
+
1530  fprintf(f, " id: %d,", g->GetID());
+
1531  fprintf(f, " name: \"%s\",", g->Name().data());
+
1532  fprintf(f, " intel: %s,", Intel::NameFromIntel(g->IntelLevel()));
+
1533  fprintf(f, " iff: %d,", g->GetIFF());
+
1534  fprintf(f, " unit_index: %d,", g->UnitIndex());
+
1535 
+
1536  if (g->GetRegion().length()) {
+
1537  fprintf(f, " region:\"%s\",", g->GetRegion().data());
+
1538  }
+
1539 
+
1540  if (g->GetAssignedSystem().length()) {
+
1541  fprintf(f, " system: \"%s\",", g->GetAssignedSystem().data());
+
1542  }
+
1543 
+
1544  if (g->GetAssignedZone()) {
+
1545  fprintf(f, " zone: \"%s\",", g->GetAssignedZone()->Name().data());
+
1546  if (g->IsZoneLocked()) {
+
1547  fprintf(f, " zone_locked: true,");
+
1548  }
+
1549  }
+
1550 
+
1551  Text x = FormatNumber(g->Location().x);
+
1552  Text y = FormatNumber(g->Location().y);
+
1553  Text z = FormatNumber(g->Location().z);
+
1554 
+
1555  fprintf(f, " loc: (%s, %s, %s),", x.data(), y.data(), z.data());
+
1556 
+
1557  CombatGroup* parent = g->GetParent();
+
1558  if (parent) {
+
1559  fprintf(f, " parent_type:%s,", CombatGroup::NameFromType(parent->Type()));
+
1560  fprintf(f, " parent_id:%d,", parent->GetID());
+
1561  }
+
1562 
+
1563  fprintf(f, " sorties: %d,", g->Sorties());
+
1564  fprintf(f, " kills: %d,", g->Kills());
+
1565  fprintf(f, " points: %d,", g->Points());
+
1566 
+
1567  ListIter<CombatUnit> u = g->GetUnits();
+
1568  while (++u) {
+
1569  SaveCombatUnit(f, u.value());
+
1570  }
+
1571 
+
1572  fprintf(f, " }\n");
+
1573 
+ +
1575  while (++c) {
+
1576  SaveCombatGroup(f, c.value());
+
1577  }
+
1578 }
+
1579 
+
1580 void
+
1581 CombatGroup::SaveOrderOfBattle(const char* filename, CombatGroup* force)
+
1582 {
+
1583  FILE* f;
+
1584  ::fopen_s(&f, filename, "a+");
+
1585 
+
1586  if (f) {
+
1587  SaveCombatGroup(f, force);
+
1588  fprintf(f, "\n");
+
1589  fclose(f);
+
1590  }
+
1591 }
+
+
+ + + + -- cgit v1.1