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/_ship_design_8cpp_source.html | 3817 ++++++++++++++++++++++++ 1 file changed, 3817 insertions(+) create mode 100644 Doc/doxygen/html/_ship_design_8cpp_source.html (limited to 'Doc/doxygen/html/_ship_design_8cpp_source.html') diff --git a/Doc/doxygen/html/_ship_design_8cpp_source.html b/Doc/doxygen/html/_ship_design_8cpp_source.html new file mode 100644 index 0000000..77202de --- /dev/null +++ b/Doc/doxygen/html/_ship_design_8cpp_source.html @@ -0,0 +1,3817 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/ShipDesign.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
ShipDesign.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 5.0
+
2  Destroyer Studios LLC
+
3  Copyright (C) 1997-2007. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: ShipDesign.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Starship Design parameters class
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "ShipDesign.h"
+
17 #include "Ship.h"
+
18 #include "Shot.h"
+
19 #include "Power.h"
+
20 #include "HardPoint.h"
+
21 #include "Weapon.h"
+
22 #include "WeaponDesign.h"
+
23 #include "Shield.h"
+
24 #include "Sensor.h"
+
25 #include "NavLight.h"
+
26 #include "NavSystem.h"
+
27 #include "Drive.h"
+
28 #include "QuantumDrive.h"
+
29 #include "Farcaster.h"
+
30 #include "Thruster.h"
+
31 #include "FlightDeck.h"
+
32 #include "LandingGear.h"
+
33 #include "Computer.h"
+
34 #include "SystemDesign.h"
+
35 #include "Component.h"
+
36 
+
37 #include "Game.h"
+
38 #include "Solid.h"
+
39 #include "Skin.h"
+
40 #include "Sprite.h"
+
41 #include "Light.h"
+
42 #include "Bitmap.h"
+
43 #include "Sound.h"
+
44 #include "DataLoader.h"
+
45 #include "ParseUtil.h"
+
46 
+
47 // +--------------------------------------------------------------------+
+
48 
+
49 const char* ship_design_class_name[32] = {
+
50  "Drone", "Fighter",
+
51  "Attack", "LCA",
+
52  "Courier", "Cargo",
+
53  "Corvette", "Freighter",
+
54 
+
55  "Frigate", "Destroyer",
+
56  "Cruiser", "Battleship",
+
57  "Carrier", "Dreadnaught",
+
58 
+
59  "Station", "Farcaster",
+
60 
+
61  "Mine", "DEFSAT",
+
62  "COMSAT", "SWACS",
+
63 
+
64  "Building", "Factory",
+
65  "SAM", "EWR",
+
66  "C3I", "Starbase",
+
67 
+
68  "0x04000000", "0x08000000",
+
69  "0x10000000", "0x20000000",
+
70  "0x40000000", "0x80000000"
+
71 };
+
72 
+
73 // +--------------------------------------------------------------------+
+
74 
+
75 static const int NAMELEN = 64;
+
76 static bool degrees = false;
+
77 
+ +
79  static const char* TYPENAME() { return "ShipCatalogEntry"; }
+
80 
+
81  ShipCatalogEntry() : hide(false), design(0) {}
+
82 
+
83  ShipCatalogEntry(const char* n, const char* t, const char* p, const char* f, bool h=false) :
+
84  name(n), type(t), path(p), file(f), hide(h), design(0) {}
+
85 
+
86  ~ShipCatalogEntry() { delete design; }
+
87 
+ + + + +
92  bool hide;
+
93 
+ +
95 };
+
96 
+
97 static List<ShipCatalogEntry> catalog;
+
98 static List<ShipCatalogEntry> mod_catalog;
+
99 
+
100 // +--------------------------------------------------------------------+
+
101 
+
102 #define GET_DEF_BOOL(n) if (defname==(#n)) GetDefBool((n), def, filename)
+
103 #define GET_DEF_TEXT(n) if (defname==(#n)) GetDefText((n), def, filename)
+
104 #define GET_DEF_NUM(n) if (defname==(#n)) GetDefNumber((n), def, filename)
+
105 #define GET_DEF_VEC(n) if (defname==(#n)) GetDefVec((n), def, filename)
+
106 
+
107 static char cockpit_name[80];
+
108 static List<Text> detail[4];
+
109 static List<Point> offset[4];
+
110 
+
111 static char errmsg[256];
+
112 
+
113 // +--------------------------------------------------------------------+
+
114 
+ +
116 {
+
117  ZeroMemory(name, sizeof(name));
+
118  ZeroMemory(load, sizeof(load));
+
119  mass = 0;
+
120 }
+
121 
+ +
123 {
+
124  name[0] = 0;
+
125  design = 0;
+
126  count = 4;
+
127  avail = 4;
+
128 }
+
129 
+
130 static void PrepareModel(Model& model)
+
131 {
+
132  bool uses_bumps = false;
+
133 
+
134  ListIter<Material> iter = model.GetMaterials();
+
135  while (++iter && !uses_bumps) {
+
136  Material* mtl = iter.value();
+
137  if (mtl->tex_bumpmap != 0 && mtl->bump != 0)
+
138  uses_bumps = true;
+
139  }
+
140 
+
141  if (uses_bumps)
+
142  model.ComputeTangents();
+
143 }
+
144 
+
145 // +--------------------------------------------------------------------+
+
146 
+ +
148 : sensor(0), navsys(0), shield(0), type(0), decoy(0),
+
149 probe(0), gear(0), valid(false), secret(false), auto_roll(1), cockpit_model(0),
+
150 bolt_hit_sound_resource(0), beam_hit_sound_resource(0), lod_levels(0)
+
151 {
+
152  ZeroMemory(filename, sizeof(filename));
+
153  ZeroMemory(path_name, sizeof(path_name));
+
154  ZeroMemory(name, sizeof(name));
+
155  ZeroMemory(display_name, sizeof(display_name));
+
156  ZeroMemory(abrv, sizeof(abrv));
+
157 
+
158  for (int i = 0; i < 4; i++)
+
159  feature_size[i] = 0.0f;
+
160 }
+
161 
+
162 // +--------------------------------------------------------------------+
+
163 
+
164 ShipDesign::ShipDesign(const char* n, const char* p, const char* fname, bool s)
+
165 : sensor(0), navsys(0), shield(0), type(0),
+
166 quantum_drive(0), farcaster(0), thruster(0), shield_model(0), decoy(0),
+
167 probe(0), gear(0), valid(false), secret(s), auto_roll(1), cockpit_model(0),
+
168 bolt_hit_sound_resource(0), beam_hit_sound_resource(0), lod_levels(0)
+
169 {
+
170  ZeroMemory(filename, sizeof(filename));
+
171  ZeroMemory(path_name, sizeof(path_name));
+
172  ZeroMemory(name, sizeof(name));
+
173  ZeroMemory(display_name, sizeof(display_name));
+
174  ZeroMemory(abrv, sizeof(abrv));
+
175 
+
176  strcpy_s(name, n);
+
177 
+
178  if (!strstr(fname, ".def"))
+
179  sprintf_s(filename, "%s.def", fname);
+
180  else
+
181  strcpy_s(filename, fname);
+
182 
+
183  for (int i = 0; i < 4; i++)
+
184  feature_size[i] = 0.0f;
+
185 
+
186  scale = 1.0f;
+
187 
+
188  agility = 2e2f;
+
189  air_factor = 0.1f;
+
190  vlimit = 8e3f;
+
191  drag = 2.5e-5f;
+
192  arcade_drag = 1.0f;
+
193  roll_drag = 5.0f;
+
194  pitch_drag = 5.0f;
+
195  yaw_drag = 5.0f;
+
196 
+
197  roll_rate = 0.0f;
+
198  pitch_rate = 0.0f;
+
199  yaw_rate = 0.0f;
+
200 
+
201  trans_x = 0.0f;
+
202  trans_y = 0.0f;
+
203  trans_z = 0.0f;
+
204 
+
205  turn_bank = (float) (PI/8);
+
206 
+
207  CL = 0.0f;
+
208  CD = 0.0f;
+
209  stall = 0.0f;
+
210 
+
211  prep_time = 30.0f;
+
212  avoid_time = 0.0f;
+
213  avoid_fighter = 0.0f;
+
214  avoid_strike = 0.0f;
+
215  avoid_target = 0.0f;
+
216  commit_range = 0.0f;
+
217 
+
218  splash_radius = -1.0f;
+
219  scuttle = 5e3f;
+
220  repair_speed = 1.0f;
+
221  repair_teams = 2;
+
222  repair_auto = true;
+
223  repair_screen = true;
+
224  wep_screen = true;
+
225 
+
226  chase_vec = Vec3(0, -100, 20);
+
227  bridge_vec = Vec3(0, 0, 0);
+
228  beauty_cam = Vec3(0, 0, 0);
+
229  cockpit_scale = 1.0f;
+
230 
+
231  radius = 1.0f;
+
232  integrity = 500.0f;
+
233 
+
234  primary = 0;
+
235  secondary = 1;
+
236  main_drive = -1;
+
237 
+
238  pcs = 3.0f;
+
239  acs = 1.0f;
+
240  detet = 250.0e3f;
+
241  e_factor[0] = 0.1f;
+
242  e_factor[1] = 0.3f;
+
243  e_factor[2] = 1.0f;
+
244 
+
245  explosion_scale = 0.0f;
+
246  death_spiral_time = 3.0f;
+
247 
+
248  if (!secret)
+
249  Print("Loading ShipDesign '%s'\n", name);
+
250 
+
251  strcpy_s(path_name, p);
+
252  if (path_name[strlen(path_name)-1] != '/')
+
253  strcat_s(path_name, "/");
+
254 
+
255  // Load Design File:
+
256  DataLoader* loader = DataLoader::GetLoader();
+
257  loader->SetDataPath(path_name);
+
258 
+
259  BYTE* block;
+
260  int blocklen = loader->LoadBuffer(filename, block, true);
+
261 
+
262  // file not found:
+
263  if (blocklen <= 4) {
+
264  valid = false;
+
265  return;
+
266  }
+
267 
+
268  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
+
269  Term* term = parser.ParseTerm();
+
270 
+
271  if (!term) {
+
272  Print("ERROR: could not parse '%s'\n", filename);
+
273  valid = false;
+
274  return;
+
275  }
+
276  else {
+
277  TermText* file_type = term->isText();
+
278  if (!file_type || file_type->value() != "SHIP") {
+
279  Print("ERROR: invalid ship design file '%s'\n", filename);
+
280  valid = false;
+
281  return;
+
282  }
+
283  }
+
284 
+
285  cockpit_name[0] = 0;
+
286  valid = true;
+
287  degrees = false;
+
288 
+
289  do {
+
290  delete term;
+
291 
+
292  term = parser.ParseTerm();
+
293 
+
294  if (term) {
+
295  TermDef* def = term->isDef();
+
296  if (def) {
+
297  ParseShip(def);
+
298  }
+
299  else {
+
300  Print("WARNING: term ignored in '%s'\n", filename);
+
301  term->print();
+
302  }
+
303  }
+
304  }
+
305  while (term);
+
306 
+
307  for (int i = 0; i < 4; i++) {
+
308  int n = 0;
+
309  ListIter<Text> iter = detail[i];
+
310  while (++iter) {
+
311  const char* model_name = iter.value()->data();
+
312 
+
313  Model* model = new(__FILE__,__LINE__) Model;
+
314  if (!model->Load(model_name, scale)) {
+
315  Print("ERROR: Could not load detail %d, model '%s'\n", i, model_name);
+
316  delete model;
+
317  model = 0;
+
318  valid = false;
+
319  }
+
320 
+
321  else {
+
322  lod_levels = i+1;
+
323 
+
324  if (model->Radius() > radius)
+
325  radius = (float) model->Radius();
+
326 
+
327  models[i].append(model);
+
328  PrepareModel(*model);
+
329 
+
330  if (offset[i].size()) {
+
331  *offset[i].at(n) *= scale;
+
332  offsets[i].append(offset[i].at(n)); // transfer ownership
+
333  }
+
334  else
+
335  offsets[i].append(new(__FILE__,__LINE__) Point);
+
336 
+
337  n++;
+
338  }
+
339  }
+
340 
+
341  detail[i].destroy();
+
342  }
+
343 
+
344  if (!secret)
+
345  Print(" Ship Design Radius = %f\n", radius);
+
346 
+
347  if (cockpit_name[0]) {
+
348  const char* model_name = cockpit_name;
+
349 
+
350  cockpit_model = new(__FILE__,__LINE__) Model;
+
351  if (!cockpit_model->Load(model_name, cockpit_scale)) {
+
352  Print("ERROR: Could not load cockpit model '%s'\n", model_name);
+
353  delete cockpit_model;
+
354  cockpit_model = 0;
+
355  }
+
356  else {
+
357  if (!secret)
+
358  Print(" Loaded cockpit model '%s', preparing tangents\n", model_name);
+
359  PrepareModel(*cockpit_model);
+
360  }
+
361  }
+
362 
+
363  if (beauty.Width() < 1 && loader->FindFile("beauty.pcx"))
+
364  loader->LoadBitmap("beauty.pcx", beauty);
+
365 
+
366  if (hud_icon.Width() < 1 && loader->FindFile("hud_icon.pcx"))
+
367  loader->LoadBitmap("hud_icon.pcx", hud_icon);
+
368 
+
369  loader->ReleaseBuffer(block);
+
370  loader->SetDataPath(0);
+
371 
+
372  if (abrv[0] == 0) {
+
373  switch (type) {
+
374  case Ship::DRONE: strcpy_s(abrv, "DR"); break;
+
375  case Ship::FIGHTER: strcpy_s(abrv, "F"); break;
+
376  case Ship::ATTACK: strcpy_s(abrv, "F/A"); break;
+
377  case Ship::LCA: strcpy_s(abrv, "LCA"); break;
+
378  case Ship::CORVETTE: strcpy_s(abrv, "FC"); break;
+
379  case Ship::COURIER:
+
380  case Ship::CARGO:
+
381  case Ship::FREIGHTER: strcpy_s(abrv, "MV"); break;
+
382  case Ship::FRIGATE: strcpy_s(abrv, "FF"); break;
+
383  case Ship::DESTROYER: strcpy_s(abrv, "DD"); break;
+
384  case Ship::CRUISER: strcpy_s(abrv, "CA"); break;
+
385  case Ship::BATTLESHIP: strcpy_s(abrv, "BB"); break;
+
386  case Ship::CARRIER: strcpy_s(abrv, "CV"); break;
+
387  case Ship::DREADNAUGHT: strcpy_s(abrv, "DN"); break;
+
388  case Ship::MINE: strcpy_s(abrv, "MINE"); break;
+
389  case Ship::COMSAT: strcpy_s(abrv, "COMS"); break;
+
390  case Ship::DEFSAT: strcpy_s(abrv, "DEFS"); break;
+
391  case Ship::SWACS: strcpy_s(abrv, "SWAC"); break;
+
392  default: break;
+
393  }
+
394  }
+
395 
+
396  if (scuttle < 1)
+
397  scuttle = 1;
+
398 
+
399  if (splash_radius < 0)
+
400  splash_radius = radius * 12.0f;
+
401 
+
402  if (repair_speed <= 1e-6)
+
403  repair_speed = 1.0e-6f;
+
404 
+
405  if (commit_range <= 0) {
+
406  if (type <= Ship::LCA)
+
407  commit_range = 80.0e3f;
+
408  else
+
409  commit_range = 200.0e3f;
+
410  }
+
411 
+
412  // calc standard loadout weights:
+ +
414  while (++sl) {
+
415  for (int i = 0; i < hard_points.size(); i++) {
+
416  HardPoint* hp = hard_points[i];
+
417  sl->mass += hp->GetCarryMass(sl->load[i]);
+
418  }
+
419  }
+
420 }
+
421 
+
422 // +--------------------------------------------------------------------+
+
423 
+ +
425 {
+ + +
428  delete cockpit_model;
+
429  delete navsys;
+
430  delete sensor;
+
431  delete shield;
+
432  delete thruster;
+
433  delete farcaster;
+
434  delete quantum_drive;
+
435  delete decoy;
+
436  delete probe;
+
437  delete gear;
+
438 
+
439  navlights.destroy();
+ + +
442  computers.destroy();
+
443  weapons.destroy();
+
444  drives.destroy();
+
445  reactors.destroy();
+
446  loadouts.destroy();
+ +
448 
+
449  delete shield_model;
+
450  for (int i = 0; i < 4; i++) {
+
451  models[i].destroy();
+
452  offsets[i].destroy();
+
453  }
+
454 
+ +
456 
+
457  for (int i = 0; i < 10; i++) {
+
458  delete debris[i].model;
+
459  }
+
460 }
+
461 
+
462 const char*
+ +
464 {
+
465  if (display_name[0])
+
466  return display_name;
+
467 
+
468  return name;
+
469 }
+
470 
+
471 // +--------------------------------------------------------------------+
+
472 
+
473 void AddModCatalogEntry(const char* design_name, const char* design_path)
+
474 {
+
475  if (!design_name || !*design_name)
+
476  return;
+
477 
+
478  ShipCatalogEntry* entry = 0;
+
479 
+
480  for (int i = 0; i < catalog.size(); i++) {
+
481  ShipCatalogEntry* e = catalog[i];
+
482  if (e->name == design_name) {
+
483  if (design_path && *design_path && e->path != design_path)
+
484  continue;
+
485  entry = e;
+
486  return;
+
487  }
+
488  }
+
489 
+
490  for (int i = 0; i < mod_catalog.size(); i++) {
+
491  ShipCatalogEntry* e = mod_catalog[i];
+
492  if (e->name == design_name) {
+
493  if (design_path && *design_path) {
+
494  Text full_path = "Mods/Ships/";
+
495  full_path += design_path;
+
496 
+
497  if (e->path != full_path)
+
498  continue;
+
499  }
+
500 
+
501  entry = e;
+
502  return;
+
503  }
+
504  }
+
505 
+
506  // still here? not found yet:
+
507  Text file = Text(design_name) + ".def";
+
508  Text path = Text("Mods/Ships/");
+
509  Text name;
+
510  Text type;
+
511  bool valid = false;
+
512 
+
513  if (design_path && *design_path)
+
514  path += design_path;
+
515  else
+
516  path += design_name;
+
517 
+
518  path += "/";
+
519 
+
520  DataLoader* loader = DataLoader::GetLoader();
+
521  loader->SetDataPath(path);
+
522 
+
523  BYTE* block;
+
524  int blocklen = loader->LoadBuffer(file, block, true);
+
525 
+
526  // file not found:
+
527  if (blocklen <= 4) {
+
528  return;
+
529  }
+
530 
+
531  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
+
532  Term* term = parser.ParseTerm();
+
533 
+
534  if (!term) {
+
535  Print("ERROR: could not parse '%s'\n", file.data());
+
536  delete block;
+
537  return;
+
538  }
+
539  else {
+
540  TermText* file_type = term->isText();
+
541  if (!file_type || file_type->value() != "SHIP") {
+
542  Print("ERROR: invalid ship design file '%s'\n", file.data());
+
543  delete block;
+
544  return;
+
545  }
+
546  }
+
547 
+
548  valid = true;
+
549 
+
550  do {
+
551  delete term;
+
552 
+
553  term = parser.ParseTerm();
+
554 
+
555  if (term) {
+
556  TermDef* def = term->isDef();
+
557  if (def) {
+
558  Text defname = def->name()->value();
+
559  defname.setSensitive(false);
+
560 
+
561  if (defname == "class") {
+
562  if (!GetDefText(type, def, file)) {
+
563  Print("WARNING: invalid or missing ship class in '%s'\n", file.data());
+
564  valid = false;
+
565  }
+
566  }
+
567 
+
568  else if (defname == "name") {
+
569  if (!GetDefText(name, def, file)) {
+
570  Print("WARNING: invalid or missing ship name in '%s'\n", file.data());
+
571  valid = false;
+
572  }
+
573  }
+
574  }
+
575  else {
+
576  Print("WARNING: term ignored in '%s'\n", file.data());
+
577  term->print();
+
578  }
+
579  }
+
580  }
+
581  while (term && valid && (name.length() < 1 || type.length() < 1));
+
582 
+
583  delete block;
+
584 
+
585  if (valid && name.length() && type.length()) {
+
586  Print("Add Mod Catalog Entry '%s' Class '%s'\n", name.data(), type.data());
+
587 
+
588  ShipCatalogEntry* entry = new(__FILE__,__LINE__) ShipCatalogEntry(name, type, path, file);
+
589  mod_catalog.append(entry);
+
590  }
+
591 }
+
592 
+
593 void
+ +
595 {
+
596  if (catalog.size()) return;
+
597 
+
598  LoadCatalog("Ships/", "catalog.def");
+
599  LoadSkins("Mods/Skins/");
+
600 
+
601  List<Text> mod_designs;
+
602  DataLoader* loader = DataLoader::GetLoader();
+
603  loader->SetDataPath("Mods/Ships/");
+
604  loader->ListFiles("*.def", mod_designs, true);
+
605 
+
606  for (int i = 0; i < mod_designs.size(); i++) {
+
607  Text full_name = *mod_designs[i];
+
608  full_name.setSensitive(false);
+
609 
+
610  if (full_name.contains('/') && !full_name.contains("catalog")) {
+
611  char path[1024];
+
612  strcpy_s(path, full_name.data());
+
613 
+
614  char* name = path + full_name.length();
+
615  while (*name != '/')
+
616  name--;
+
617 
+
618  *name++ = 0;
+
619 
+
620  char* p = strrchr(name, '.');
+
621  if (p && strlen(p) > 3) {
+
622  if ((p[1] == 'd' || p[1] == 'D') &&
+
623  (p[2] == 'e' || p[2] == 'E') &&
+
624  (p[3] == 'f' || p[3] == 'F')) {
+
625 
+
626  *p = 0;
+
627  }
+
628  }
+
629 
+
630  // Just do a quick parse of the def file and add the
+
631  // info to the catalog. DON'T preload all of the models,
+
632  // textures, and weapons at this time. That takes way
+
633  // too long with some of the larger user mods.
+
634 
+
635  AddModCatalogEntry(name, path);
+
636  }
+
637  }
+
638 
+
639  mod_designs.destroy();
+
640  loader->SetDataPath(0);
+
641 }
+
642 
+
643 void
+ +
645 {
+
646  mod_catalog.destroy();
+
647  catalog.destroy();
+
648 }
+
649 
+
650 // +--------------------------------------------------------------------+
+
651 
+
652 int
+
653 ShipDesign::LoadCatalog(const char* path, const char* fname, bool mod)
+
654 {
+
655  int result = 0;
+
656 
+
657  // Load Design Catalog File:
+
658  DataLoader* loader = DataLoader::GetLoader();
+
659  loader->SetDataPath(path);
+
660 
+
661  char filename[NAMELEN];
+
662  ZeroMemory(filename, NAMELEN);
+
663  strncpy(filename, fname, NAMELEN-1);
+
664 
+
665  Print("Loading ship design catalog: %s%s\n", path, filename);
+
666 
+
667  BYTE* block;
+
668  int blocklen = loader->LoadBuffer(filename, block, true);
+
669  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
+
670  Term* term = parser.ParseTerm();
+
671 
+
672  if (!term) {
+
673  Print("ERROR: could not parse '%s'\n", filename);
+
674  loader->ReleaseBuffer(block);
+
675  loader->SetDataPath(0);
+
676  return result;
+
677  }
+
678  else {
+
679  TermText* file_type = term->isText();
+
680  if (!file_type || file_type->value() != "SHIPCATALOG") {
+
681  Print("ERROR: invalid ship catalog file '%s'\n", filename);
+
682  loader->ReleaseBuffer(block);
+
683  loader->SetDataPath(0);
+
684  return result;
+
685  }
+
686  }
+
687 
+
688  do {
+
689  delete term;
+
690 
+
691  term = parser.ParseTerm();
+
692 
+
693  Text name, type, fname, path;
+
694  bool hide = false;
+
695 
+
696  if (term) {
+
697  TermDef* def = term->isDef();
+
698  if (def && def->term() && def->term()->isStruct()) {
+
699  TermStruct* val = def->term()->isStruct();
+
700 
+
701  for (int i = 0; i < val->elements()->size(); i++) {
+
702  TermDef* pdef = val->elements()->at(i)->isDef();
+
703  if (pdef) {
+
704  Text defname = pdef->name()->value();
+
705  defname.setSensitive(false);
+
706 
+
707  if (defname == "name") {
+
708  if (!GetDefText(name, pdef, filename))
+
709  Print("WARNING: invalid or missing ship name in '%s'\n", filename);
+
710  }
+
711  else if (defname == "type") {
+
712  if (!GetDefText(type, pdef, filename))
+
713  Print("WARNING: invalid or missing ship type in '%s'\n", filename);
+
714  }
+
715  else if (defname == "path") {
+
716  if (!GetDefText(path, pdef, filename))
+
717  Print("WARNING: invalid or missing ship path in '%s'\n", filename);
+
718  }
+
719  else if (defname == "file") {
+
720  if (!GetDefText(fname, pdef, filename))
+
721  Print("WARNING: invalid or missing ship file in '%s'\n", filename);
+
722  }
+
723  else if (defname == "hide" || defname == "secret") {
+
724  GetDefBool(hide, pdef, filename);
+
725  }
+
726  }
+
727  }
+
728 
+
729  ShipCatalogEntry* entry = new(__FILE__,__LINE__) ShipCatalogEntry(name, type, path, fname, hide);
+
730 
+
731  if (mod) mod_catalog.append(entry);
+
732  else catalog.append(entry);
+
733 
+
734  result++;
+
735  }
+
736  else {
+
737  Print("WARNING: term ignored in '%s'\n", filename);
+
738  term->print();
+
739  }
+
740  }
+
741  }
+
742  while (term);
+
743 
+
744  loader->ReleaseBuffer(block);
+
745  loader->SetDataPath(0);
+
746 
+
747  return result;
+
748 }
+
749 
+
750 // +--------------------------------------------------------------------+
+
751 
+
752 void
+
753 ShipDesign::LoadSkins(const char* path, const char* archive)
+
754 {
+
755  // Load MOD Skin Files:
+
756  List<Text> list;
+
757  DataLoader* loader = DataLoader::GetLoader();
+
758  bool oldfs = loader->IsFileSystemEnabled();
+
759 
+
760  loader->UseFileSystem(true);
+
761  loader->SetDataPath(path);
+
762  loader->ListArchiveFiles(archive, "*.def", list);
+
763 
+
764  ListIter<Text> iter = list;
+
765  while (++iter) {
+
766  Text filename = *iter.value();
+
767  BYTE* block;
+
768  int blocklen = loader->LoadBuffer(filename, block, true);
+
769 
+
770  // file not found:
+
771  if (blocklen <= 4) {
+
772  continue;
+
773  }
+
774 
+
775  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
+
776  Term* term = parser.ParseTerm();
+
777  ShipDesign* design = 0;
+
778 
+
779  if (!term) {
+
780  Print("ERROR: could not parse '%s'\n", filename.data());
+
781  return;
+
782  }
+
783  else {
+
784  TermText* file_type = term->isText();
+
785  if (!file_type || file_type->value() != "SKIN") {
+
786  Print("ERROR: invalid skin file '%s'\n", filename.data());
+
787  return;
+
788  }
+
789  }
+
790 
+
791  do {
+
792  delete term;
+
793 
+
794  term = parser.ParseTerm();
+
795 
+
796  if (term) {
+
797  TermDef* def = term->isDef();
+
798  if (def) {
+
799  Text defname = def->name()->value();
+
800  defname.setSensitive(false);
+
801 
+
802  if (defname == "name") {
+
803  Text name;
+
804  GetDefText(name, def, filename);
+
805  design = Get(name);
+
806  }
+
807 
+
808  else if (defname == "skin" && design != 0) {
+
809  if (!def->term() || !def->term()->isStruct()) {
+
810  Print("WARNING: skin struct missing in '%s'\n", filename.data());
+
811  }
+
812  else {
+
813  TermStruct* val = def->term()->isStruct();
+
814  Skin* skin = design->ParseSkin(val);
+
815 
+
816  if (skin)
+
817  skin->SetPath(archive);
+
818  }
+
819  }
+
820  }
+
821  }
+
822  }
+
823  while (term);
+
824  }
+
825 
+
826  loader->UseFileSystem(oldfs);
+
827 }
+
828 
+
829 // +--------------------------------------------------------------------+
+
830 
+
831 int
+ +
833 {
+
834  return catalog.size();
+
835 }
+
836 
+
837 void
+ +
839 {
+
840  if (index >= 0 && index < catalog.size()) {
+
841  ShipCatalogEntry* entry = catalog[index];
+
842 
+
843  if (entry->hide)
+
844  return;
+
845 
+
846  int ship_class = ClassForName(entry->type);
+
847  if (ship_class > Ship::STARSHIPS)
+
848  return;
+
849 
+
850  if (!entry->path.contains("Alliance_"))
+
851  return;
+
852 
+
853  if (!entry->design) {
+
854  entry->design = new(__FILE__,__LINE__) ShipDesign(entry->name,
+
855  entry->path,
+
856  entry->file,
+
857  entry->hide);
+
858  }
+
859  }
+
860 
+
861  else {
+
862  ListIter<ShipCatalogEntry> iter = catalog;
+
863  while (++iter) {
+
864  ShipCatalogEntry* entry = iter.value();
+
865 
+
866  if (!entry->design) {
+
867  entry->design = new(__FILE__,__LINE__) ShipDesign(entry->name,
+
868  entry->path,
+
869  entry->file,
+
870  entry->hide);
+
871  }
+
872  }
+
873  }
+
874 }
+
875 
+
876 // +--------------------------------------------------------------------+
+
877 
+
878 bool
+
879 ShipDesign::CheckName(const char* design_name)
+
880 {
+
881  ShipCatalogEntry* entry = 0;
+
882 
+
883  for (int i = 0; i < catalog.size(); i++) {
+
884  if (catalog.at(i)->name == design_name) {
+
885  entry = catalog.at(i);
+
886  break;
+
887  }
+
888  }
+
889 
+
890  if (!entry) {
+
891  for (int i = 0; i < mod_catalog.size(); i++) {
+
892  if (mod_catalog.at(i)->name == design_name) {
+
893  entry = mod_catalog.at(i);
+
894  break;
+
895  }
+
896  }
+
897  }
+
898 
+
899  return entry != 0;
+
900 }
+
901 
+
902 // +--------------------------------------------------------------------+
+
903 
+
904 ShipDesign*
+
905 ShipDesign::Get(const char* design_name, const char* design_path)
+
906 {
+
907  if (!design_name || !*design_name)
+
908  return 0;
+
909 
+
910  ShipCatalogEntry* entry = 0;
+
911 
+
912  for (int i = 0; i < catalog.size(); i++) {
+
913  ShipCatalogEntry* e = catalog[i];
+
914  if (e->name == design_name) {
+
915  if (design_path && *design_path && e->path != design_path)
+
916  continue;
+
917  entry = e;
+
918  break;
+
919  }
+
920  }
+
921 
+
922  if (!entry) {
+
923  for (int i = 0; i < mod_catalog.size(); i++) {
+
924  ShipCatalogEntry* e = mod_catalog[i];
+
925  if (e->name == design_name) {
+
926  if (design_path && *design_path) {
+
927  Text full_path = "Mods/Ships/";
+
928  full_path += design_path;
+
929 
+
930  if (e->path != full_path)
+
931  continue;
+
932  }
+
933 
+
934  entry = e;
+
935  break;
+
936  }
+
937  }
+
938  }
+
939 
+
940  if (entry) {
+
941  if (!entry->design) {
+
942  entry->design = new(__FILE__,__LINE__) ShipDesign(entry->name,
+
943  entry->path,
+
944  entry->file,
+
945  entry->hide);
+
946  }
+
947  return entry->design;
+
948  }
+
949  else {
+
950  Print("ShipDesign: no catalog entry for design '%s', checking mods...\n", design_name);
+
951  return ShipDesign::FindModDesign(design_name, design_path);
+
952  }
+
953 }
+
954 
+
955 ShipDesign*
+
956 ShipDesign::FindModDesign(const char* design_name, const char* design_path)
+
957 {
+
958  Text file = Text(design_name) + ".def";
+
959  Text path = Text("Mods/Ships/");
+
960 
+
961  if (design_path && *design_path)
+
962  path += design_path;
+
963  else
+
964  path += design_name;
+
965 
+
966  DataLoader* loader = DataLoader::GetLoader();
+
967  loader->SetDataPath(path);
+
968 
+
969  ShipDesign* design = new(__FILE__,__LINE__) ShipDesign(design_name, path, file);
+
970 
+
971  if (design->valid) {
+
972  Print("ShipDesign: found mod design '%s'\n", design->name);
+
973 
+
974  ShipCatalogEntry* entry = new(__FILE__,__LINE__) ShipCatalogEntry(design->name,
+
975  ClassName(design->type),
+
976  path,
+
977  file);
+
978  mod_catalog.append(entry);
+
979  entry->design = design;
+
980  return entry->design;
+
981  }
+
982  else {
+
983  delete design;
+
984  }
+
985 
+
986  return 0;
+
987 }
+
988 
+
989 void
+ +
991 {
+
992  mod_catalog.destroy();
+
993 
+
994  for (int i = 0; i < catalog.size(); i++) {
+
995  ShipCatalogEntry* e = catalog[i];
+
996 
+
997  if (e && e->design) {
+
998  ListIter<Skin> iter = e->design->skins;
+
999 
+
1000  while (++iter) {
+
1001  Skin* skin = iter.value();
+
1002  if (*skin->Path())
+
1003  iter.removeItem();
+
1004  }
+
1005  }
+
1006  }
+
1007 }
+
1008 
+
1009 // +--------------------------------------------------------------------+
+
1010 
+
1011 int
+ +
1013 {
+
1014  designs.clear();
+
1015 
+
1016  for (int i = 0; i < catalog.size(); i++) {
+
1017  ShipCatalogEntry* e = catalog[i];
+
1018 
+
1019  int etype = ClassForName(e->type);
+
1020  if (etype & type) {
+
1021  if (!e->design)
+
1022  e->design = new(__FILE__,__LINE__) ShipDesign(e->name,
+
1023  e->path,
+
1024  e->file,
+
1025  e->hide);
+
1026 
+
1027  if (e->hide || !e->design || !e->design->valid || e->design->secret)
+
1028  continue;
+
1029 
+
1030  designs.append(&e->name);
+
1031  }
+
1032  }
+
1033 
+
1034  for (int i = 0; i < mod_catalog.size(); i++) {
+
1035  ShipCatalogEntry* e = mod_catalog[i];
+
1036 
+
1037  int etype = ClassForName(e->type);
+
1038  if (etype & type) {
+
1039  designs.append(&e->name);
+
1040  }
+
1041  }
+
1042 
+
1043  return designs.size();
+
1044 }
+
1045 
+
1046 // +--------------------------------------------------------------------+
+
1047 
+
1048 int
+
1049 ShipDesign::ClassForName(const char* name)
+
1050 {
+
1051  if (!name || !name[0])
+
1052  return 0;
+
1053 
+
1054  for (int i = 0; i < 32; i++) {
+
1055  if (!_stricmp(name, ship_design_class_name[i])) {
+
1056  return 1 << i;
+
1057  }
+
1058  }
+
1059 
+
1060  return 0;
+
1061 }
+
1062 
+
1063 const char*
+ +
1065 {
+
1066  if (type != 0) {
+
1067  int index = 0;
+
1068 
+
1069  while (!(type & 1)) {
+
1070  type >>= 1;
+
1071  index++;
+
1072  }
+
1073 
+
1074  if (index >= 0 && index < 32)
+
1075  return ship_design_class_name[index];
+
1076  }
+
1077 
+
1078  return "Unknown";
+
1079 }
+
1080 
+
1081 // +--------------------------------------------------------------------+
+
1082 
+
1083 void
+ +
1085 {
+
1086  char detail_name[NAMELEN];
+
1087  Vec3 off_loc;
+
1088  Vec3 spin;
+
1089  Text defname = def->name()->value();
+
1090 
+
1091  defname.setSensitive(false);
+
1092 
+
1093  if (defname == "cockpit_model") {
+
1094  if (!GetDefText(cockpit_name, def, filename))
+
1095  Print("WARNING: invalid or missing cockpit_model in '%s'\n", filename);
+
1096  }
+
1097 
+
1098  else if (defname == "model" || defname == "detail_0") {
+
1099  if (!GetDefText(detail_name, def, filename))
+
1100  Print("WARNING: invalid or missing model in '%s'\n", filename);
+
1101 
+
1102  detail[0].append(new(__FILE__,__LINE__) Text(detail_name));
+
1103  }
+
1104 
+
1105  else if (defname == "detail_1") {
+
1106  if (!GetDefText(detail_name, def, filename))
+
1107  Print("WARNING: invalid or missing detail_1 in '%s'\n", filename);
+
1108 
+
1109  detail[1].append(new(__FILE__,__LINE__) Text(detail_name));
+
1110  }
+
1111 
+
1112  else if (defname == "detail_2") {
+
1113  if (!GetDefText(detail_name, def, filename))
+
1114  Print("WARNING: invalid or missing detail_2 in '%s'\n", filename);
+
1115 
+
1116  detail[2].append(new(__FILE__,__LINE__) Text(detail_name));
+
1117  }
+
1118 
+
1119  else if (defname == "detail_3") {
+
1120  if (!GetDefText(detail_name, def, filename))
+
1121  Print("WARNING: invalid or missing detail_3 in '%s'\n", filename);
+
1122 
+
1123  detail[3].append(new(__FILE__,__LINE__) Text(detail_name));
+
1124  }
+
1125 
+
1126  else if (defname == "spin") {
+
1127  if (!GetDefVec(spin, def, filename))
+
1128  Print("WARNING: invalid or missing spin in '%s'\n", filename);
+
1129 
+
1130  spin_rates.append(new(__FILE__,__LINE__) Point(spin));
+
1131  }
+
1132 
+
1133  else if (defname == "offset_0") {
+
1134  if (!GetDefVec(off_loc, def, filename))
+
1135  Print("WARNING: invalid or missing offset_0 in '%s'\n", filename);
+
1136 
+
1137  offset[0].append(new(__FILE__,__LINE__) Point(off_loc));
+
1138  }
+
1139 
+
1140  else if (defname == "offset_1") {
+
1141  if (!GetDefVec(off_loc, def, filename))
+
1142  Print("WARNING: invalid or missing offset_1 in '%s'\n", filename);
+
1143 
+
1144  offset[1].append(new(__FILE__,__LINE__) Point(off_loc));
+
1145  }
+
1146 
+
1147  else if (defname == "offset_2") {
+
1148  if (!GetDefVec(off_loc, def, filename))
+
1149  Print("WARNING: invalid or missing offset_2 in '%s'\n", filename);
+
1150 
+
1151  offset[2].append(new(__FILE__,__LINE__) Point(off_loc));
+
1152  }
+
1153 
+
1154  else if (defname == "offset_3") {
+
1155  if (!GetDefVec(off_loc, def, filename))
+
1156  Print("WARNING: invalid or missing offset_3 in '%s'\n", filename);
+
1157 
+
1158  offset[3].append(new(__FILE__,__LINE__) Point(off_loc));
+
1159  }
+
1160 
+
1161  else if (defname == "beauty") {
+
1162  if (def->term() && def->term()->isArray()) {
+
1163  GetDefVec(beauty_cam, def, filename);
+
1164 
+
1165  if (degrees) {
+
1166  beauty_cam.x *= (float) DEGREES;
+
1167  beauty_cam.y *= (float) DEGREES;
+
1168  }
+
1169  }
+
1170 
+
1171  else {
+
1172  char beauty_name[64];
+
1173  if (!GetDefText(beauty_name, def, filename))
+
1174  Print("WARNING: invalid or missing beauty in '%s'\n", filename);
+
1175 
+
1176  DataLoader* loader = DataLoader::GetLoader();
+
1177  loader->LoadBitmap(beauty_name, beauty);
+
1178  }
+
1179  }
+
1180 
+
1181  else if (defname == "hud_icon") {
+
1182  char hud_icon_name[64];
+
1183  if (!GetDefText(hud_icon_name, def, filename))
+
1184  Print("WARNING: invalid or missing hud_icon in '%s'\n", filename);
+
1185 
+
1186  DataLoader* loader = DataLoader::GetLoader();
+
1187  loader->LoadBitmap(hud_icon_name, hud_icon);
+
1188  }
+
1189 
+
1190  else if (defname == "feature_0") {
+
1191  if (!GetDefNumber(feature_size[0], def, filename))
+
1192  Print("WARNING: invalid or missing feature_0 in '%s'\n", filename);
+
1193  }
+
1194 
+
1195  else if (defname == "feature_1") {
+
1196  if (!GetDefNumber(feature_size[1], def, filename))
+
1197  Print("WARNING: invalid or missing feature_1 in '%s'\n", filename);
+
1198  }
+
1199 
+
1200  else if (defname == "feature_2") {
+
1201  if (!GetDefNumber(feature_size[2], def, filename))
+
1202  Print("WARNING: invalid or missing feature_2 in '%s'\n", filename);
+
1203  }
+
1204 
+
1205  else if (defname == "feature_3") {
+
1206  if (!GetDefNumber(feature_size[3], def, filename))
+
1207  Print("WARNING: invalid or missing feature_3 in '%s'\n", filename);
+
1208  }
+
1209 
+
1210 
+
1211  else if (defname == "class") {
+
1212  char typestr[64];
+
1213  if (!GetDefText(typestr, def, filename))
+
1214  Print("WARNING: invalid or missing ship class in '%s'\n", filename);
+
1215 
+
1216  type = ClassForName(typestr);
+
1217 
+
1218  if (type <= Ship::LCA) {
+
1219  repair_auto = false;
+
1220  repair_screen = false;
+
1221  wep_screen = false;
+
1222  }
+
1223  }
+
1224 
+
1225  else GET_DEF_TEXT(name);
+
1226  else GET_DEF_TEXT(description);
+
1227  else GET_DEF_TEXT(display_name);
+
1228  else GET_DEF_TEXT(abrv);
+
1229  else GET_DEF_NUM(pcs);
+
1230  else GET_DEF_NUM(acs);
+
1231  else GET_DEF_NUM(detet);
+
1232  else GET_DEF_NUM(scale);
+ +
1234  else GET_DEF_NUM(mass);
+
1235  else GET_DEF_NUM(vlimit);
+
1236  else GET_DEF_NUM(agility);
+
1237  else GET_DEF_NUM(air_factor);
+
1238  else GET_DEF_NUM(roll_rate);
+
1239  else GET_DEF_NUM(pitch_rate);
+
1240  else GET_DEF_NUM(yaw_rate);
+
1241  else GET_DEF_NUM(integrity);
+
1242  else GET_DEF_NUM(drag);
+
1243  else GET_DEF_NUM(arcade_drag);
+
1244  else GET_DEF_NUM(roll_drag);
+
1245  else GET_DEF_NUM(pitch_drag);
+
1246  else GET_DEF_NUM(yaw_drag);
+
1247  else GET_DEF_NUM(trans_x);
+
1248  else GET_DEF_NUM(trans_y);
+
1249  else GET_DEF_NUM(trans_z);
+
1250  else GET_DEF_NUM(turn_bank);
+
1251  else GET_DEF_NUM(cockpit_scale);
+
1252  else GET_DEF_NUM(auto_roll);
+
1253 
+
1254  else GET_DEF_NUM(CL);
+
1255  else GET_DEF_NUM(CD);
+
1256  else GET_DEF_NUM(stall);
+
1257 
+
1258  else GET_DEF_NUM(prep_time);
+
1259  else GET_DEF_NUM(avoid_time);
+
1260  else GET_DEF_NUM(avoid_fighter);
+
1261  else GET_DEF_NUM(avoid_strike);
+
1262  else GET_DEF_NUM(avoid_target);
+
1263  else GET_DEF_NUM(commit_range);
+
1264 
+
1265  else GET_DEF_NUM(splash_radius);
+
1266  else GET_DEF_NUM(scuttle);
+
1267  else GET_DEF_NUM(repair_speed);
+
1268  else GET_DEF_NUM(repair_teams);
+
1269  else GET_DEF_BOOL(secret);
+
1270  else GET_DEF_BOOL(repair_auto);
+ +
1272  else GET_DEF_BOOL(wep_screen);
+
1273  else GET_DEF_BOOL(degrees);
+
1274 
+
1275  else if (defname == "emcon_1") {
+
1276  GetDefNumber(e_factor[0], def, filename);
+
1277  }
+
1278 
+
1279  else if (defname == "emcon_2") {
+
1280  GetDefNumber(e_factor[1], def, filename);
+
1281  }
+
1282 
+
1283  else if (defname == "emcon_3") {
+
1284  GetDefNumber(e_factor[2], def, filename);
+
1285  }
+
1286 
+
1287  else if (defname == "chase") {
+
1288  if (!GetDefVec(chase_vec, def, filename))
+
1289  Print("WARNING: invalid or missing chase cam loc in '%s'\n", filename);
+
1290 
+
1291  chase_vec *= (float) scale;
+
1292  }
+
1293 
+
1294  else if (defname == "bridge") {
+
1295  if (!GetDefVec(bridge_vec, def, filename))
+
1296  Print("WARNING: invalid or missing bridge cam loc in '%s'\n", filename);
+
1297 
+
1298  bridge_vec *= (float) scale;
+
1299  }
+
1300 
+
1301  else if (defname == "power") {
+
1302  if (!def->term() || !def->term()->isStruct()) {
+
1303  Print("WARNING: power source struct missing in '%s'\n", filename);
+
1304  }
+
1305  else {
+
1306  TermStruct* val = def->term()->isStruct();
+
1307  ParsePower(val);
+
1308  }
+
1309  }
+
1310 
+
1311  else if (defname == "main_drive" || defname == "drive") {
+
1312  if (!def->term() || !def->term()->isStruct()) {
+
1313  Print("WARNING: main drive struct missing in '%s'\n", filename);
+
1314  }
+
1315  else {
+
1316  TermStruct* val = def->term()->isStruct();
+
1317  ParseDrive(val);
+
1318  }
+
1319  }
+
1320 
+
1321  else if (defname == "quantum" || defname == "quantum_drive") {
+
1322  if (!def->term() || !def->term()->isStruct()) {
+
1323  Print("WARNING: quantum_drive struct missing in '%s'\n", filename);
+
1324  }
+
1325  else {
+
1326  TermStruct* val = def->term()->isStruct();
+
1327  ParseQuantumDrive(val);
+
1328  }
+
1329  }
+
1330 
+
1331  else if (defname == "sender" || defname == "farcaster") {
+
1332  if (!def->term() || !def->term()->isStruct()) {
+
1333  Print("WARNING: farcaster struct missing in '%s'\n", filename);
+
1334  }
+
1335  else {
+
1336  TermStruct* val = def->term()->isStruct();
+
1337  ParseFarcaster(val);
+
1338  }
+
1339  }
+
1340 
+
1341  else if (defname == "thruster") {
+
1342  if (!def->term() || !def->term()->isStruct()) {
+
1343  Print("WARNING: thruster struct missing in '%s'\n", filename);
+
1344  }
+
1345  else {
+
1346  TermStruct* val = def->term()->isStruct();
+
1347  ParseThruster(val);
+
1348  }
+
1349  }
+
1350 
+
1351  else if (defname == "navlight") {
+
1352  if (!def->term() || !def->term()->isStruct()) {
+
1353  Print("WARNING: navlight struct missing in '%s'\n", filename);
+
1354  }
+
1355  else {
+
1356  TermStruct* val = def->term()->isStruct();
+
1357  ParseNavlight(val);
+
1358  }
+
1359  }
+
1360 
+
1361  else if (defname == "flightdeck") {
+
1362  if (!def->term() || !def->term()->isStruct()) {
+
1363  Print("WARNING: flightdeck struct missing in '%s'\n", filename);
+
1364  }
+
1365  else {
+
1366  TermStruct* val = def->term()->isStruct();
+
1367  ParseFlightDeck(val);
+
1368  }
+
1369  }
+
1370 
+
1371  else if (defname == "gear") {
+
1372  if (!def->term() || !def->term()->isStruct()) {
+
1373  Print("WARNING: gear struct missing in '%s'\n", filename);
+
1374  }
+
1375  else {
+
1376  TermStruct* val = def->term()->isStruct();
+
1377  ParseLandingGear(val);
+
1378  }
+
1379  }
+
1380 
+
1381  else if (defname == "weapon") {
+
1382  if (!def->term() || !def->term()->isStruct()) {
+
1383  Print("WARNING: weapon struct missing in '%s'\n", filename);
+
1384  }
+
1385  else {
+
1386  TermStruct* val = def->term()->isStruct();
+
1387  ParseWeapon(val);
+
1388  }
+
1389  }
+
1390 
+
1391  else if (defname == "hardpoint") {
+
1392  if (!def->term() || !def->term()->isStruct()) {
+
1393  Print("WARNING: hardpoint struct missing in '%s'\n", filename);
+
1394  }
+
1395  else {
+
1396  TermStruct* val = def->term()->isStruct();
+
1397  ParseHardPoint(val);
+
1398  }
+
1399  }
+
1400 
+
1401  else if (defname == "loadout") {
+
1402  if (!def->term() || !def->term()->isStruct()) {
+
1403  Print("WARNING: loadout struct missing in '%s'\n", filename);
+
1404  }
+
1405  else {
+
1406  TermStruct* val = def->term()->isStruct();
+
1407  ParseLoadout(val);
+
1408  }
+
1409  }
+
1410 
+
1411  else if (defname == "decoy") {
+
1412  if (!def->term() || !def->term()->isStruct()) {
+
1413  Print("WARNING: decoy struct missing in '%s'\n", filename);
+
1414  }
+
1415  else {
+
1416  TermStruct* val = def->term()->isStruct();
+
1417  ParseWeapon(val);
+
1418  }
+
1419  }
+
1420 
+
1421  else if (defname == "probe") {
+
1422  if (!def->term() || !def->term()->isStruct()) {
+
1423  Print("WARNING: probe struct missing in '%s'\n", filename);
+
1424  }
+
1425  else {
+
1426  TermStruct* val = def->term()->isStruct();
+
1427  ParseWeapon(val);
+
1428  }
+
1429  }
+
1430 
+
1431  else if (defname == "sensor") {
+
1432  if (!def->term() || !def->term()->isStruct()) {
+
1433  Print("WARNING: sensor struct missing in '%s'\n", filename);
+
1434  }
+
1435  else {
+
1436  TermStruct* val = def->term()->isStruct();
+
1437  ParseSensor(val);
+
1438  }
+
1439  }
+
1440 
+
1441  else if (defname == "nav") {
+
1442  if (!def->term() || !def->term()->isStruct()) {
+
1443  Print("WARNING: nav struct missing in '%s'\n", filename);
+
1444  }
+
1445  else {
+
1446  TermStruct* val = def->term()->isStruct();
+
1447  ParseNavsys(val);
+
1448  }
+
1449  }
+
1450 
+
1451  else if (defname == "computer") {
+
1452  if (!def->term() || !def->term()->isStruct()) {
+
1453  Print("WARNING: computer struct missing in '%s'\n", filename);
+
1454  }
+
1455  else {
+
1456  TermStruct* val = def->term()->isStruct();
+
1457  ParseComputer(val);
+
1458  }
+
1459  }
+
1460 
+
1461  else if (defname == "shield") {
+
1462  if (!def->term() || !def->term()->isStruct()) {
+
1463  Print("WARNING: shield struct missing in '%s'\n", filename);
+
1464  }
+
1465  else {
+
1466  TermStruct* val = def->term()->isStruct();
+
1467  ParseShield(val);
+
1468  }
+
1469  }
+
1470 
+
1471  else if (defname == "death_spiral") {
+
1472  if (!def->term() || !def->term()->isStruct()) {
+
1473  Print("WARNING: death spiral struct missing in '%s'\n", filename);
+
1474  }
+
1475  else {
+
1476  TermStruct* val = def->term()->isStruct();
+
1477  ParseDeathSpiral(val);
+
1478  }
+
1479  }
+
1480 
+
1481  else if (defname == "map") {
+
1482  if (!def->term() || !def->term()->isStruct()) {
+
1483  Print("WARNING: map struct missing in '%s'\n", filename);
+
1484  }
+
1485  else {
+
1486  TermStruct* val = def->term()->isStruct();
+
1487  ParseMap(val);
+
1488  }
+
1489  }
+
1490 
+
1491  else if (defname == "squadron") {
+
1492  if (!def->term() || !def->term()->isStruct()) {
+
1493  Print("WARNING: squadron struct missing in '%s'\n", filename);
+
1494  }
+
1495  else {
+
1496  TermStruct* val = def->term()->isStruct();
+
1497  ParseSquadron(val);
+
1498  }
+
1499  }
+
1500 
+
1501  else if (defname == "skin") {
+
1502  if (!def->term() || !def->term()->isStruct()) {
+
1503  Print("WARNING: skin struct missing in '%s'\n", filename);
+
1504  }
+
1505  else {
+
1506  TermStruct* val = def->term()->isStruct();
+
1507  ParseSkin(val);
+
1508  }
+
1509  }
+
1510 
+
1511  else {
+
1512  Print("WARNING: unknown parameter '%s' in '%s'\n",
+
1513  defname.data(), filename);
+
1514  }
+
1515 
+
1516  if (description.length())
+ +
1518 }
+
1519 
+
1520 // +--------------------------------------------------------------------+
+
1521 
+
1522 void
+ +
1524 {
+
1525  int stype = 0;
+
1526  float output = 1000.0f;
+
1527  float fuel = 0.0f;
+
1528  Vec3 loc(0.0f, 0.0f, 0.0f);
+
1529  float size = 0.0f;
+
1530  float hull = 0.5f;
+
1531  Text design_name;
+
1532  Text pname;
+
1533  Text pabrv;
+
1534  int etype = 0;
+
1535  int emcon_1 = -1;
+
1536  int emcon_2 = -1;
+
1537  int emcon_3 = -1;
+
1538 
+
1539  for (int i = 0; i < val->elements()->size(); i++) {
+
1540  TermDef* pdef = val->elements()->at(i)->isDef();
+
1541  if (pdef) {
+
1542  Text defname = pdef->name()->value();
+
1543  defname.setSensitive(false);
+
1544 
+
1545  if (defname == "type") {
+
1546  TermText* tname = pdef->term()->isText();
+
1547 
+
1548  if (tname) {
+
1549  if (tname->value()[0] == 'B') stype = PowerSource::BATTERY;
+
1550  else if (tname->value()[0] == 'A') stype = PowerSource::AUX;
+
1551  else if (tname->value()[0] == 'F') stype = PowerSource::FUSION;
+
1552  else Print("WARNING: unknown power source type '%s' in '%s'\n", tname->value().data(), filename);
+
1553  }
+
1554  }
+
1555 
+
1556  else if (defname == "name") {
+
1557  GetDefText(pname, pdef, filename);
+
1558  }
+
1559 
+
1560  else if (defname == "abrv") {
+
1561  GetDefText(pabrv, pdef, filename);
+
1562  }
+
1563 
+
1564  else if (defname == "design") {
+
1565  GetDefText(design_name, pdef, filename);
+
1566  }
+
1567 
+
1568  else if (defname == "max_output") {
+
1569  GetDefNumber(output, pdef, filename);
+
1570  }
+
1571  else if (defname == "fuel_range") {
+
1572  GetDefNumber(fuel, pdef, filename);
+
1573  }
+
1574 
+
1575  else if (defname == "loc") {
+
1576  GetDefVec(loc, pdef, filename);
+
1577  loc *= (float) scale;
+
1578  }
+
1579  else if (defname == "size") {
+
1580  GetDefNumber(size, pdef, filename);
+
1581  size *= (float) scale;
+
1582  }
+
1583  else if (defname == "hull_factor") {
+
1584  GetDefNumber(hull, pdef, filename);
+
1585  }
+
1586 
+
1587  else if (defname == "explosion") {
+
1588  GetDefNumber(etype, pdef, filename);
+
1589  }
+
1590 
+
1591  else if (defname == "emcon_1") {
+
1592  GetDefNumber(emcon_1, pdef, filename);
+
1593  }
+
1594 
+
1595  else if (defname == "emcon_2") {
+
1596  GetDefNumber(emcon_2, pdef, filename);
+
1597  }
+
1598 
+
1599  else if (defname == "emcon_3") {
+
1600  GetDefNumber(emcon_3, pdef, filename);
+
1601  }
+
1602  }
+
1603  }
+
1604 
+
1605  PowerSource* source = new(__FILE__,__LINE__) PowerSource((PowerSource::SUBTYPE) stype, output);
+
1606  if (pname.length()) source->SetName(pname);
+
1607  if (pabrv.length()) source->SetName(pabrv);
+
1608  source->SetFuelRange(fuel);
+
1609  source->Mount(loc, size, hull);
+
1610  source->SetExplosionType(etype);
+
1611 
+
1612  if (design_name.length()) {
+
1613  SystemDesign* sd = SystemDesign::Find(design_name);
+
1614  if (sd)
+
1615  source->SetDesign(sd);
+
1616  }
+
1617 
+
1618  if (emcon_1 >= 0 && emcon_1 <= 100)
+
1619  source->SetEMCONPower(1, emcon_1);
+
1620 
+
1621  if (emcon_2 >= 0 && emcon_2 <= 100)
+
1622  source->SetEMCONPower(1, emcon_2);
+
1623 
+
1624  if (emcon_3 >= 0 && emcon_3 <= 100)
+
1625  source->SetEMCONPower(1, emcon_3);
+
1626 
+
1627  reactors.append(source);
+
1628 }
+
1629 
+
1630 // +--------------------------------------------------------------------+
+
1631 
+
1632 void
+ +
1634 {
+
1635  Text dname;
+
1636  Text dabrv;
+
1637  int dtype = 0;
+
1638  int etype = 0;
+
1639  float dthrust = 1.0f;
+
1640  float daug = 0.0f;
+
1641  float dscale = 1.0f;
+
1642  Vec3 loc(0.0f, 0.0f, 0.0f);
+
1643  float size = 0.0f;
+
1644  float hull = 0.5f;
+
1645  Text design_name;
+
1646  int emcon_1 = -1;
+
1647  int emcon_2 = -1;
+
1648  int emcon_3 = -1;
+
1649  bool trail = true;
+
1650  Drive* drive = 0;
+
1651 
+
1652  for (int i = 0; i < val->elements()->size(); i++) {
+
1653  TermDef* pdef = val->elements()->at(i)->isDef();
+
1654  if (pdef) {
+
1655  Text defname = pdef->name()->value();
+
1656  defname.setSensitive(false);
+
1657 
+
1658  if (defname == "type") {
+
1659  TermText* tname = pdef->term()->isText();
+
1660 
+
1661  if (tname) {
+
1662  Text tval = tname->value();
+
1663  tval.setSensitive(false);
+
1664 
+
1665  if (tval == "Plasma") dtype = Drive::PLASMA;
+
1666  else if (tval == "Fusion") dtype = Drive::FUSION;
+
1667  else if (tval == "Alien") dtype = Drive::GREEN;
+
1668  else if (tval == "Green") dtype = Drive::GREEN;
+
1669  else if (tval == "Red") dtype = Drive::RED;
+
1670  else if (tval == "Blue") dtype = Drive::BLUE;
+
1671  else if (tval == "Yellow") dtype = Drive::YELLOW;
+
1672  else if (tval == "Stealth") dtype = Drive::STEALTH;
+
1673 
+
1674  else Print("WARNING: unknown drive type '%s' in '%s'\n", tname->value().data(), filename);
+
1675  }
+
1676  }
+
1677  else if (defname == "name") {
+
1678  if (!GetDefText(dname, pdef, filename))
+
1679  Print("WARNING: invalid or missing name for drive in '%s'\n", filename);
+
1680  }
+
1681 
+
1682  else if (defname == "abrv") {
+
1683  if (!GetDefText(dabrv, pdef, filename))
+
1684  Print("WARNING: invalid or missing abrv for drive in '%s'\n", filename);
+
1685  }
+
1686 
+
1687  else if (defname == "design") {
+
1688  if (!GetDefText(design_name, pdef, filename))
+
1689  Print("WARNING: invalid or missing design for drive in '%s'\n", filename);
+
1690  }
+
1691 
+
1692  else if (defname == "thrust") {
+
1693  if (!GetDefNumber(dthrust, pdef, filename))
+
1694  Print("WARNING: invalid or missing thrust for drive in '%s'\n", filename);
+
1695  }
+
1696 
+
1697  else if (defname == "augmenter") {
+
1698  if (!GetDefNumber(daug, pdef, filename))
+
1699  Print("WARNING: invalid or missing augmenter for drive in '%s'\n", filename);
+
1700  }
+
1701 
+
1702  else if (defname == "scale") {
+
1703  if (!GetDefNumber(dscale, pdef, filename))
+
1704  Print("WARNING: invalid or missing scale for drive in '%s'\n", filename);
+
1705  }
+
1706 
+
1707  else if (defname == "port") {
+
1708  Vec3 port;
+
1709  float flare_scale = 0;
+
1710 
+
1711  if (pdef->term()->isArray()) {
+
1712  GetDefVec(port, pdef, filename);
+
1713  port *= scale;
+
1714  flare_scale = dscale;
+
1715  }
+
1716 
+
1717  else if (pdef->term()->isStruct()) {
+
1718  TermStruct* val = pdef->term()->isStruct();
+
1719 
+
1720  for (int i = 0; i < val->elements()->size(); i++) {
+
1721  TermDef* pdef2 = val->elements()->at(i)->isDef();
+
1722  if (pdef2) {
+
1723  if (pdef2->name()->value() == "loc") {
+
1724  GetDefVec(port, pdef2, filename);
+
1725  port *= scale;
+
1726  }
+
1727 
+
1728  else if (pdef2->name()->value() == "scale") {
+
1729  GetDefNumber(flare_scale, pdef2, filename);
+
1730  }
+
1731  }
+
1732  }
+
1733 
+
1734  if (flare_scale <= 0)
+
1735  flare_scale = dscale;
+
1736  }
+
1737 
+
1738  if (!drive)
+
1739  drive = new(__FILE__,__LINE__) Drive((Drive::SUBTYPE) dtype, dthrust, daug, trail);
+
1740 
+
1741  drive->AddPort(port, flare_scale);
+
1742  }
+
1743 
+
1744  else if (defname == "loc") {
+
1745  if (!GetDefVec(loc, pdef, filename))
+
1746  Print("WARNING: invalid or missing loc for drive in '%s'\n", filename);
+
1747  loc *= (float) scale;
+
1748  }
+
1749 
+
1750  else if (defname == "size") {
+
1751  if (!GetDefNumber(size, pdef, filename))
+
1752  Print("WARNING: invalid or missing size for drive in '%s'\n", filename);
+
1753  size *= (float) scale;
+
1754  }
+
1755 
+
1756  else if (defname == "hull_factor") {
+
1757  if (!GetDefNumber(hull, pdef, filename))
+
1758  Print("WARNING: invalid or missing hull_factor for drive in '%s'\n", filename);
+
1759  }
+
1760 
+
1761  else if (defname == "explosion") {
+
1762  if (!GetDefNumber(etype, pdef, filename))
+
1763  Print("WARNING: invalid or missing explosion for drive in '%s'\n", filename);
+
1764  }
+
1765 
+
1766  else if (defname == "emcon_1") {
+
1767  GetDefNumber(emcon_1, pdef, filename);
+
1768  }
+
1769 
+
1770  else if (defname == "emcon_2") {
+
1771  GetDefNumber(emcon_2, pdef, filename);
+
1772  }
+
1773 
+
1774  else if (defname == "emcon_3") {
+
1775  GetDefNumber(emcon_3, pdef, filename);
+
1776  }
+
1777 
+
1778  else if (defname == "trail" || defname == "show_trail") {
+
1779  GetDefBool(trail, pdef, filename);
+
1780  }
+
1781  }
+
1782  }
+
1783 
+
1784  if (!drive)
+
1785  drive = new(__FILE__,__LINE__) Drive((Drive::SUBTYPE) dtype, dthrust, daug, trail);
+
1786 
+
1787  drive->SetSourceIndex(reactors.size()-1);
+
1788  drive->Mount(loc, size, hull);
+
1789  if (dname.length()) drive->SetName(dname);
+
1790  if (dabrv.length()) drive->SetAbbreviation(dabrv);
+
1791  drive->SetExplosionType(etype);
+
1792 
+
1793  if (design_name.length()) {
+
1794  SystemDesign* sd = SystemDesign::Find(design_name);
+
1795  if (sd)
+
1796  drive->SetDesign(sd);
+
1797  }
+
1798 
+
1799  if (emcon_1 >= 0 && emcon_1 <= 100)
+
1800  drive->SetEMCONPower(1, emcon_1);
+
1801 
+
1802  if (emcon_2 >= 0 && emcon_2 <= 100)
+
1803  drive->SetEMCONPower(1, emcon_2);
+
1804 
+
1805  if (emcon_3 >= 0 && emcon_3 <= 100)
+
1806  drive->SetEMCONPower(1, emcon_3);
+
1807 
+
1808  main_drive = drives.size();
+
1809  drives.append(drive);
+
1810 }
+
1811 
+
1812 // +--------------------------------------------------------------------+
+
1813 
+
1814 void
+ +
1816 {
+
1817  double capacity = 250e3;
+
1818  double consumption = 1e3;
+
1819  Vec3 loc(0.0f, 0.0f, 0.0f);
+
1820  float size = 0.0f;
+
1821  float hull = 0.5f;
+
1822  float countdown = 5.0f;
+
1823  Text design_name;
+
1824  Text type_name;
+
1825  Text abrv;
+
1826  int subtype = QuantumDrive::QUANTUM;
+
1827  int emcon_1 = -1;
+
1828  int emcon_2 = -1;
+
1829  int emcon_3 = -1;
+
1830 
+
1831  for (int i = 0; i < val->elements()->size(); i++) {
+
1832  TermDef* pdef = val->elements()->at(i)->isDef();
+
1833  if (pdef) {
+
1834  Text defname = pdef->name()->value();
+
1835  defname.setSensitive(false);
+
1836 
+
1837  if (defname == "design") {
+
1838  GetDefText(design_name, pdef, filename);
+
1839  }
+
1840  else if (defname == "abrv") {
+
1841  GetDefText(abrv, pdef, filename);
+
1842  }
+
1843  else if (defname == "type") {
+
1844  GetDefText(type_name, pdef, filename);
+
1845  type_name.setSensitive(false);
+
1846 
+
1847  if (type_name.contains("hyper")) {
+
1848  subtype = QuantumDrive::HYPER;
+
1849  }
+
1850  }
+
1851  else if (defname == "capacity") {
+
1852  GetDefNumber(capacity, pdef, filename);
+
1853  }
+
1854  else if (defname == "consumption") {
+
1855  GetDefNumber(consumption, pdef, filename);
+
1856  }
+
1857  else if (defname == "loc") {
+
1858  GetDefVec(loc, pdef, filename);
+
1859  loc *= (float) scale;
+
1860  }
+
1861  else if (defname == "size") {
+
1862  GetDefNumber(size, pdef, filename);
+
1863  size *= (float) scale;
+
1864  }
+
1865  else if (defname == "hull_factor") {
+
1866  GetDefNumber(hull, pdef, filename);
+
1867  }
+
1868  else if (defname == "jump_time") {
+
1869  GetDefNumber(countdown, pdef, filename);
+
1870  }
+
1871  else if (defname == "countdown") {
+
1872  GetDefNumber(countdown, pdef, filename);
+
1873  }
+
1874 
+
1875  else if (defname == "emcon_1") {
+
1876  GetDefNumber(emcon_1, pdef, filename);
+
1877  }
+
1878 
+
1879  else if (defname == "emcon_2") {
+
1880  GetDefNumber(emcon_2, pdef, filename);
+
1881  }
+
1882 
+
1883  else if (defname == "emcon_3") {
+
1884  GetDefNumber(emcon_3, pdef, filename);
+
1885  }
+
1886  }
+
1887  }
+
1888 
+
1889  QuantumDrive* drive = new(__FILE__,__LINE__) QuantumDrive((QuantumDrive::SUBTYPE) subtype, capacity, consumption);
+
1890  drive->SetSourceIndex(reactors.size()-1);
+
1891  drive->Mount(loc, size, hull);
+
1892  drive->SetCountdown(countdown);
+
1893 
+
1894  if (design_name.length()) {
+
1895  SystemDesign* sd = SystemDesign::Find(design_name);
+
1896  if (sd)
+
1897  drive->SetDesign(sd);
+
1898  }
+
1899 
+
1900  if (abrv.length())
+
1901  drive->SetAbbreviation(abrv);
+
1902 
+
1903  if (emcon_1 >= 0 && emcon_1 <= 100)
+
1904  drive->SetEMCONPower(1, emcon_1);
+
1905 
+
1906  if (emcon_2 >= 0 && emcon_2 <= 100)
+
1907  drive->SetEMCONPower(1, emcon_2);
+
1908 
+
1909  if (emcon_3 >= 0 && emcon_3 <= 100)
+
1910  drive->SetEMCONPower(1, emcon_3);
+
1911 
+
1912  quantum_drive = drive;
+
1913 }
+
1914 
+
1915 // +--------------------------------------------------------------------+
+
1916 
+
1917 void
+ +
1919 {
+
1920  Text design_name;
+
1921  double capacity = 300e3;
+
1922  double consumption = 15e3; // twenty second recharge
+
1923  int napproach = 0;
+ +
1925  Vec3 loc(0.0f, 0.0f, 0.0f);
+
1926  Vec3 start(0.0f, 0.0f, 0.0f);
+
1927  Vec3 end(0.0f, 0.0f, 0.0f);
+
1928  float size = 0.0f;
+
1929  float hull = 0.5f;
+
1930  int emcon_1 = -1;
+
1931  int emcon_2 = -1;
+
1932  int emcon_3 = -1;
+
1933 
+
1934  for (int i = 0; i < val->elements()->size(); i++) {
+
1935  TermDef* pdef = val->elements()->at(i)->isDef();
+
1936  if (pdef) {
+
1937  Text defname = pdef->name()->value();
+
1938  defname.setSensitive(false);
+
1939 
+
1940  if (defname == "design") {
+
1941  GetDefText(design_name, pdef, filename);
+
1942  }
+
1943  else if (defname == "capacity") {
+
1944  GetDefNumber(capacity, pdef, filename);
+
1945  }
+
1946  else if (defname == "consumption") {
+
1947  GetDefNumber(consumption, pdef, filename);
+
1948  }
+
1949  else if (defname == "loc") {
+
1950  GetDefVec(loc, pdef, filename);
+
1951  loc *= (float) scale;
+
1952  }
+
1953  else if (defname == "size") {
+
1954  GetDefNumber(size, pdef, filename);
+
1955  size *= (float) scale;
+
1956  }
+
1957  else if (defname == "hull_factor") {
+
1958  GetDefNumber(hull, pdef, filename);
+
1959  }
+
1960 
+
1961  else if (defname == "start") {
+
1962  GetDefVec(start, pdef, filename);
+
1963  start *= (float) scale;
+
1964  }
+
1965  else if (defname == "end") {
+
1966  GetDefVec(end, pdef, filename);
+
1967  end *= (float) scale;
+
1968  }
+
1969  else if (defname == "approach") {
+
1970  if (napproach < Farcaster::NUM_APPROACH_PTS) {
+
1971  GetDefVec(approach[napproach], pdef, filename);
+
1972  approach[napproach++] *= (float) scale;
+
1973  }
+
1974  else {
+
1975  Print("WARNING: farcaster approach point ignored in '%s' (max=%d)\n",
+ +
1977  }
+
1978  }
+
1979 
+
1980  else if (defname == "emcon_1") {
+
1981  GetDefNumber(emcon_1, pdef, filename);
+
1982  }
+
1983 
+
1984  else if (defname == "emcon_2") {
+
1985  GetDefNumber(emcon_2, pdef, filename);
+
1986  }
+
1987 
+
1988  else if (defname == "emcon_3") {
+
1989  GetDefNumber(emcon_3, pdef, filename);
+
1990  }
+
1991  }
+
1992  }
+
1993 
+
1994  Farcaster* caster = new(__FILE__,__LINE__) Farcaster(capacity, consumption);
+
1995  caster->SetSourceIndex(reactors.size()-1);
+
1996  caster->Mount(loc, size, hull);
+
1997 
+
1998  if (design_name.length()) {
+
1999  SystemDesign* sd = SystemDesign::Find(design_name);
+
2000  if (sd)
+
2001  caster->SetDesign(sd);
+
2002  }
+
2003 
+
2004  caster->SetStartPoint(start);
+
2005  caster->SetEndPoint(end);
+
2006 
+
2007  for (int i = 0; i < napproach; i++)
+
2008  caster->SetApproachPoint(i, approach[i]);
+
2009 
+
2010  if (emcon_1 >= 0 && emcon_1 <= 100)
+
2011  caster->SetEMCONPower(1, emcon_1);
+
2012 
+
2013  if (emcon_2 >= 0 && emcon_2 <= 100)
+
2014  caster->SetEMCONPower(1, emcon_2);
+
2015 
+
2016  if (emcon_3 >= 0 && emcon_3 <= 100)
+
2017  caster->SetEMCONPower(1, emcon_3);
+
2018 
+
2019  farcaster = caster;
+
2020 }
+
2021 
+
2022 // +--------------------------------------------------------------------+
+
2023 
+
2024 void
+ +
2026 {
+
2027  if (thruster) {
+
2028  Print("WARNING: additional thruster ignored in '%s'\n", filename);
+
2029  return;
+
2030  }
+
2031 
+
2032  double thrust = 100;
+
2033 
+
2034  Vec3 loc(0.0f, 0.0f, 0.0f);
+
2035  float size = 0.0f;
+
2036  float hull = 0.5f;
+
2037  Text design_name;
+
2038  float tscale = 1.0f;
+
2039  int emcon_1 = -1;
+
2040  int emcon_2 = -1;
+
2041  int emcon_3 = -1;
+
2042  int dtype = 0;
+
2043 
+
2044  Thruster* drive = 0;
+
2045 
+
2046  for (int i = 0; i < val->elements()->size(); i++) {
+
2047  TermDef* pdef = val->elements()->at(i)->isDef();
+
2048  if (pdef) {
+
2049  Text defname = pdef->name()->value();
+
2050  defname.setSensitive(false);
+
2051 
+
2052 
+
2053  if (defname == "type") {
+
2054  TermText* tname = pdef->term()->isText();
+
2055 
+
2056  if (tname) {
+
2057  Text tval = tname->value();
+
2058  tval.setSensitive(false);
+
2059 
+
2060  if (tval == "Plasma") dtype = Drive::PLASMA;
+
2061  else if (tval == "Fusion") dtype = Drive::FUSION;
+
2062  else if (tval == "Alien") dtype = Drive::GREEN;
+
2063  else if (tval == "Green") dtype = Drive::GREEN;
+
2064  else if (tval == "Red") dtype = Drive::RED;
+
2065  else if (tval == "Blue") dtype = Drive::BLUE;
+
2066  else if (tval == "Yellow") dtype = Drive::YELLOW;
+
2067  else if (tval == "Stealth") dtype = Drive::STEALTH;
+
2068 
+
2069  else Print("WARNING: unknown thruster type '%s' in '%s'\n", tname->value().data(), filename);
+
2070  }
+
2071  }
+
2072 
+
2073  else if (defname == "thrust") {
+
2074  GetDefNumber(thrust, pdef, filename);
+
2075  }
+
2076 
+
2077  else if (defname == "design") {
+
2078  GetDefText(design_name, pdef, filename);
+
2079  }
+
2080 
+
2081  else if (defname == "loc") {
+
2082  GetDefVec(loc, pdef, filename);
+
2083  loc *= (float) scale;
+
2084  }
+
2085  else if (defname == "size") {
+
2086  GetDefNumber(size, pdef, filename);
+
2087  size *= (float) scale;
+
2088  }
+
2089  else if (defname == "hull_factor") {
+
2090  GetDefNumber(hull, pdef, filename);
+
2091  }
+
2092  else if (defname == "scale") {
+
2093  GetDefNumber(tscale, pdef, filename);
+
2094  }
+
2095  else if (defname.contains("port") && pdef->term()) {
+
2096  Vec3 port;
+
2097  float port_scale = 0;
+
2098  DWORD fire = 0;
+
2099 
+
2100  if (pdef->term()->isArray()) {
+
2101  GetDefVec(port, pdef, filename);
+
2102  port *= scale;
+
2103  port_scale = tscale;
+
2104  }
+
2105 
+
2106  else if (pdef->term()->isStruct()) {
+
2107  TermStruct* val = pdef->term()->isStruct();
+
2108 
+
2109  for (int i = 0; i < val->elements()->size(); i++) {
+
2110  TermDef* pdef2 = val->elements()->at(i)->isDef();
+
2111  if (pdef2) {
+
2112  if (pdef2->name()->value() == "loc") {
+
2113  GetDefVec(port, pdef2, filename);
+
2114  port *= scale;
+
2115  }
+
2116 
+
2117  else if (pdef2->name()->value() == "fire") {
+
2118  GetDefNumber(fire, pdef2, filename);
+
2119  }
+
2120 
+
2121  else if (pdef2->name()->value() == "scale") {
+
2122  GetDefNumber(port_scale, pdef2, filename);
+
2123  }
+
2124  }
+
2125  }
+
2126 
+
2127  if (port_scale <= 0)
+
2128  port_scale = tscale;
+
2129  }
+
2130 
+
2131  if (!drive)
+
2132  drive = new(__FILE__,__LINE__) Thruster(dtype, thrust, tscale);
+
2133 
+
2134  if (defname == "port" || defname == "port_bottom")
+
2135  drive->AddPort(Thruster::BOTTOM, port, fire, port_scale);
+
2136 
+
2137  else if (defname == "port_top")
+
2138  drive->AddPort(Thruster::TOP, port, fire, port_scale);
+
2139 
+
2140  else if (defname == "port_left")
+
2141  drive->AddPort(Thruster::LEFT, port, fire, port_scale);
+
2142 
+
2143  else if (defname == "port_right")
+
2144  drive->AddPort(Thruster::RIGHT, port, fire, port_scale);
+
2145 
+
2146  else if (defname == "port_fore")
+
2147  drive->AddPort(Thruster::FORE, port, fire, port_scale);
+
2148 
+
2149  else if (defname == "port_aft")
+
2150  drive->AddPort(Thruster::AFT, port, fire, port_scale);
+
2151  }
+
2152 
+
2153  else if (defname == "emcon_1") {
+
2154  GetDefNumber(emcon_1, pdef, filename);
+
2155  }
+
2156 
+
2157  else if (defname == "emcon_2") {
+
2158  GetDefNumber(emcon_2, pdef, filename);
+
2159  }
+
2160 
+
2161  else if (defname == "emcon_3") {
+
2162  GetDefNumber(emcon_3, pdef, filename);
+
2163  }
+
2164  }
+
2165  }
+
2166 
+
2167  if (!drive)
+
2168  drive = new(__FILE__,__LINE__) Thruster(dtype, thrust, tscale);
+
2169  drive->SetSourceIndex(reactors.size()-1);
+
2170  drive->Mount(loc, size, hull);
+
2171 
+
2172  if (design_name.length()) {
+
2173  SystemDesign* sd = SystemDesign::Find(design_name);
+
2174  if (sd)
+
2175  drive->SetDesign(sd);
+
2176  }
+
2177 
+
2178  if (emcon_1 >= 0 && emcon_1 <= 100)
+
2179  drive->SetEMCONPower(1, emcon_1);
+
2180 
+
2181  if (emcon_2 >= 0 && emcon_2 <= 100)
+
2182  drive->SetEMCONPower(1, emcon_2);
+
2183 
+
2184  if (emcon_3 >= 0 && emcon_3 <= 100)
+
2185  drive->SetEMCONPower(1, emcon_3);
+
2186 
+
2187  thruster = drive;
+
2188 }
+
2189 
+
2190 // +--------------------------------------------------------------------+
+
2191 
+
2192 void
+ +
2194 {
+
2195  Text dname;
+
2196  Text dabrv;
+
2197  Text design_name;
+
2198  int nlights = 0;
+
2199  float dscale = 1.0f;
+
2200  float period = 10.0f;
+
2201  Vec3 bloc[NavLight::MAX_LIGHTS];
+
2202  int btype[NavLight::MAX_LIGHTS];
+
2203  DWORD pattern[NavLight::MAX_LIGHTS];
+
2204 
+
2205  for (int i = 0; i < val->elements()->size(); i++) {
+
2206  TermDef* pdef = val->elements()->at(i)->isDef();
+
2207  if (pdef) {
+
2208  Text defname = pdef->name()->value();
+
2209  defname.setSensitive(false);
+
2210 
+
2211  if (defname == "name")
+
2212  GetDefText(dname, pdef, filename);
+
2213  else if (defname == "abrv")
+
2214  GetDefText(dabrv, pdef, filename);
+
2215 
+
2216  else if (defname == "design") {
+
2217  GetDefText(design_name, pdef, filename);
+
2218  }
+
2219 
+
2220  else if (defname == "scale") {
+
2221  GetDefNumber(dscale, pdef, filename);
+
2222  }
+
2223  else if (defname == "period") {
+
2224  GetDefNumber(period, pdef, filename);
+
2225  }
+
2226  else if (defname == "light") {
+
2227  if (!pdef->term() || !pdef->term()->isStruct()) {
+
2228  Print("WARNING: light struct missing for ship '%s' in '%s'\n", name, filename);
+
2229  }
+
2230  else {
+
2231  TermStruct* val = pdef->term()->isStruct();
+
2232 
+
2233  Vec3 loc;
+
2234  int t = 0;
+
2235  DWORD ptn = 0;
+
2236 
+
2237  for (int i = 0; i < val->elements()->size(); i++) {
+
2238  TermDef* pdef = val->elements()->at(i)->isDef();
+
2239  if (pdef) {
+
2240  Text defname = pdef->name()->value();
+
2241  defname.setSensitive(false);
+
2242 
+
2243  if (defname == "type") {
+
2244  GetDefNumber(t, pdef, filename);
+
2245  }
+
2246  else if (defname == "loc") {
+
2247  GetDefVec(loc, pdef, filename);
+
2248  }
+
2249  else if (defname == "pattern") {
+
2250  GetDefNumber(ptn, pdef, filename);
+
2251  }
+
2252  }
+
2253  }
+
2254 
+
2255  if (t < 1 || t > 4)
+
2256  t = 1;
+
2257 
+
2258  if (nlights < NavLight::MAX_LIGHTS) {
+
2259  bloc[nlights] = loc * scale;
+
2260  btype[nlights] = t-1;
+
2261  pattern[nlights] = ptn;
+
2262  nlights++;
+
2263  }
+
2264  else {
+
2265  Print("WARNING: Too many lights ship '%s' in '%s'\n", name, filename);
+
2266  }
+
2267  }
+
2268  }
+
2269  }
+
2270  }
+
2271 
+
2272  NavLight* nav = new(__FILE__,__LINE__) NavLight(period, dscale);
+
2273  if (dname.length()) nav->SetName(dname);
+
2274  if (dabrv.length()) nav->SetAbbreviation(dabrv);
+
2275 
+
2276  if (design_name.length()) {
+
2277  SystemDesign* sd = SystemDesign::Find(design_name);
+
2278  if (sd)
+
2279  nav->SetDesign(sd);
+
2280  }
+
2281 
+
2282  for (int i = 0; i < nlights; i++)
+
2283  nav->AddBeacon(bloc[i], pattern[i], btype[i]);
+
2284 
+
2285  navlights.append(nav);
+
2286 }
+
2287 
+
2288 // +--------------------------------------------------------------------+
+
2289 
+
2290 void
+ +
2292 {
+
2293  Text dname;
+
2294  Text dabrv;
+
2295  Text design_name;
+
2296  float dscale = 1.0f;
+
2297  float az = 0.0f;
+
2298  int etype = 0;
+
2299 
+
2300  bool launch = false;
+
2301  bool recovery = false;
+
2302  int nslots = 0;
+
2303  int napproach = 0;
+
2304  int nrunway = 0;
+
2305  DWORD filters[10];
+
2306  Vec3 spots[10];
+ +
2308  Vec3 runway[2];
+
2309  Vec3 loc(0,0,0);
+
2310  Vec3 start(0,0,0);
+
2311  Vec3 end(0,0,0);
+
2312  Vec3 cam(0,0,0);
+
2313  Vec3 box(0,0,0);
+
2314  float cycle_time = 0.0f;
+
2315  float size = 0.0f;
+
2316  float hull = 0.5f;
+
2317 
+
2318  float light = 0.0f;
+
2319 
+
2320  for (int i = 0; i < val->elements()->size(); i++) {
+
2321  TermDef* pdef = val->elements()->at(i)->isDef();
+
2322  if (pdef) {
+
2323  Text defname = pdef->name()->value();
+
2324  defname.setSensitive(false);
+
2325 
+
2326  if (defname == "name")
+
2327  GetDefText(dname, pdef, filename);
+
2328  else if (defname == "abrv")
+
2329  GetDefText(dabrv, pdef, filename);
+
2330  else if (defname == "design")
+
2331  GetDefText(design_name, pdef, filename);
+
2332 
+
2333  else if (defname == "start") {
+
2334  GetDefVec(start, pdef, filename);
+
2335  start *= (float) scale;
+
2336  }
+
2337  else if (defname == "end") {
+
2338  GetDefVec(end, pdef, filename);
+
2339  end *= (float) scale;
+
2340  }
+
2341  else if (defname == "cam") {
+
2342  GetDefVec(cam, pdef, filename);
+
2343  cam *= (float) scale;
+
2344  }
+
2345  else if (defname == "box" || defname == "bounding_box") {
+
2346  GetDefVec(box, pdef, filename);
+
2347  box *= (float) scale;
+
2348  }
+
2349  else if (defname == "approach") {
+
2350  if (napproach < FlightDeck::NUM_APPROACH_PTS) {
+
2351  GetDefVec(approach[napproach], pdef, filename);
+
2352  approach[napproach++] *= (float) scale;
+
2353  }
+
2354  else {
+
2355  Print("WARNING: flight deck approach point ignored in '%s' (max=%d)\n",
+ +
2357  }
+
2358  }
+
2359  else if (defname == "runway") {
+
2360  GetDefVec(runway[nrunway], pdef, filename);
+
2361  runway[nrunway++] *= (float) scale;
+
2362  }
+
2363  else if (defname == "spot") {
+
2364  if (pdef->term()->isStruct()) {
+
2365  TermStruct* s = pdef->term()->isStruct();
+
2366  for (int i = 0; i < s->elements()->size(); i++) {
+
2367  TermDef* d = s->elements()->at(i)->isDef();
+
2368  if (d) {
+
2369  if (d->name()->value() == "loc") {
+
2370  GetDefVec(spots[nslots], d, filename);
+
2371  spots[nslots] *= (float) scale;
+
2372  }
+
2373  else if (d->name()->value() == "filter") {
+
2374  GetDefNumber(filters[nslots], d, filename);
+
2375  }
+
2376  }
+
2377  }
+
2378 
+
2379  nslots++;
+
2380  }
+
2381 
+
2382  else if (pdef->term()->isArray()) {
+
2383  GetDefVec(spots[nslots], pdef, filename);
+
2384  spots[nslots] *= (float) scale;
+
2385  filters[nslots++] = 0xf;
+
2386  }
+
2387  }
+
2388 
+
2389  else if (defname == "light") {
+
2390  GetDefNumber(light, pdef, filename);
+
2391  }
+
2392 
+
2393  else if (defname == "cycle_time") {
+
2394  GetDefNumber(cycle_time, pdef, filename);
+
2395  }
+
2396 
+
2397  else if (defname == "launch") {
+
2398  GetDefBool(launch, pdef, filename);
+
2399  }
+
2400 
+
2401  else if (defname == "recovery") {
+
2402  GetDefBool(recovery, pdef, filename);
+
2403  }
+
2404 
+
2405  else if (defname == "azimuth") {
+
2406  GetDefNumber(az, pdef, filename);
+
2407  if (degrees) az *= (float) DEGREES;
+
2408  }
+
2409 
+
2410  else if (defname == "loc") {
+
2411  GetDefVec(loc, pdef, filename);
+
2412  loc *= (float) scale;
+
2413  }
+
2414  else if (defname == "size") {
+
2415  GetDefNumber(size, pdef, filename);
+
2416  size *= (float) scale;
+
2417  }
+
2418  else if (defname == "hull_factor") {
+
2419  GetDefNumber(hull, pdef, filename);
+
2420  }
+
2421  else if (defname == "explosion") {
+
2422  GetDefNumber(etype, pdef, filename);
+
2423  }
+
2424  }
+
2425  }
+
2426 
+
2427  FlightDeck* deck = new(__FILE__,__LINE__) FlightDeck();
+
2428  deck->Mount(loc, size, hull);
+
2429  if (dname.length()) deck->SetName(dname);
+
2430  if (dabrv.length()) deck->SetAbbreviation(dabrv);
+
2431 
+
2432  if (design_name.length()) {
+
2433  SystemDesign* sd = SystemDesign::Find(design_name);
+
2434  if (sd)
+
2435  deck->SetDesign(sd);
+
2436  }
+
2437 
+
2438  if (launch)
+
2439  deck->SetLaunchDeck();
+
2440  else if (recovery)
+
2441  deck->SetRecoveryDeck();
+
2442 
+
2443  deck->SetAzimuth(az);
+
2444  deck->SetBoundingBox(box);
+
2445  deck->SetStartPoint(start);
+
2446  deck->SetEndPoint(end);
+
2447  deck->SetCamLoc(cam);
+
2448  deck->SetExplosionType(etype);
+
2449 
+
2450  if (light > 0)
+
2451  deck->SetLight(light);
+
2452 
+
2453  for (int i = 0; i < napproach; i++)
+
2454  deck->SetApproachPoint(i, approach[i]);
+
2455 
+
2456  for (int i = 0; i < nrunway; i++)
+
2457  deck->SetRunwayPoint(i, runway[i]);
+
2458 
+
2459  for (int i = 0; i < nslots; i++)
+
2460  deck->AddSlot(spots[i], filters[i]);
+
2461 
+
2462  if (cycle_time > 0)
+
2463  deck->SetCycleTime(cycle_time);
+
2464 
+
2465  flight_decks.append(deck);
+
2466 }
+
2467 
+
2468 // +--------------------------------------------------------------------+
+
2469 
+
2470 void
+ +
2472 {
+
2473  Text dname;
+
2474  Text dabrv;
+
2475  Text design_name;
+
2476  int ngear = 0;
+
2477  Vec3 start[LandingGear::MAX_GEAR];
+ +
2479  Model* model[LandingGear::MAX_GEAR];
+
2480 
+
2481  for (int i = 0; i < val->elements()->size(); i++) {
+
2482  TermDef* pdef = val->elements()->at(i)->isDef();
+
2483  if (pdef) {
+
2484  Text defname = pdef->name()->value();
+
2485  defname.setSensitive(false);
+
2486 
+
2487  if (defname == "name")
+
2488  GetDefText(dname, pdef, filename);
+
2489  else if (defname == "abrv")
+
2490  GetDefText(dabrv, pdef, filename);
+
2491 
+
2492  else if (defname == "design") {
+
2493  GetDefText(design_name, pdef, filename);
+
2494  }
+
2495 
+
2496  else if (defname == "gear") {
+
2497  if (!pdef->term() || !pdef->term()->isStruct()) {
+
2498  Print("WARNING: gear struct missing for ship '%s' in '%s'\n", name, filename);
+
2499  }
+
2500  else {
+
2501  TermStruct* val = pdef->term()->isStruct();
+
2502 
+
2503  Vec3 v1, v2;
+
2504  char mod_name[256];
+
2505 
+
2506  ZeroMemory(mod_name, sizeof(mod_name));
+
2507 
+
2508  for (int i = 0; i < val->elements()->size(); i++) {
+
2509  TermDef* pdef = val->elements()->at(i)->isDef();
+
2510  if (pdef) {
+
2511  defname = pdef->name()->value();
+
2512  defname.setSensitive(false);
+
2513 
+
2514  if (defname == "model") {
+
2515  GetDefText(mod_name, pdef, filename);
+
2516  }
+
2517  else if (defname == "start") {
+
2518  GetDefVec(v1, pdef, filename);
+
2519  }
+
2520  else if (defname == "end") {
+
2521  GetDefVec(v2, pdef, filename);
+
2522  }
+
2523  }
+
2524  }
+
2525 
+
2526  if (ngear < LandingGear::MAX_GEAR) {
+
2527  Model* m = new(__FILE__,__LINE__) Model;
+
2528  if (!m->Load(mod_name, scale)) {
+
2529  Print("WARNING: Could not load landing gear model '%s'\n", mod_name);
+
2530  delete m;
+
2531  m = 0;
+
2532  }
+
2533  else {
+
2534  model[ngear] = m;
+
2535  start[ngear] = v1 * scale;
+
2536  end[ngear] = v2 * scale;
+
2537  ngear++;
+
2538  }
+
2539  }
+
2540  else {
+
2541  Print("WARNING: Too many landing gear ship '%s' in '%s'\n", name, filename);
+
2542  }
+
2543  }
+
2544  }
+
2545  }
+
2546  }
+
2547 
+
2548  gear = new(__FILE__,__LINE__) LandingGear();
+
2549  if (dname.length()) gear->SetName(dname);
+
2550  if (dabrv.length()) gear->SetAbbreviation(dabrv);
+
2551 
+
2552  if (design_name.length()) {
+
2553  SystemDesign* sd = SystemDesign::Find(design_name);
+
2554  if (sd)
+
2555  gear->SetDesign(sd);
+
2556  }
+
2557 
+
2558  for (int i = 0; i < ngear; i++)
+
2559  gear->AddGear(model[i], start[i], end[i]);
+
2560 }
+
2561 
+
2562 // +--------------------------------------------------------------------+
+
2563 
+
2564 void
+ +
2566 {
+
2567  Text wtype;
+
2568  Text wname;
+
2569  Text wabrv;
+
2570  Text design_name;
+
2571  Text group_name;
+
2572  int nmuz = 0;
+
2573  Vec3 muzzles[Weapon::MAX_BARRELS];
+
2574  Vec3 loc(0.0f, 0.0f, 0.0f);
+
2575  float size = 0.0f;
+
2576  float hull = 0.5f;
+
2577  float az = 0.0f;
+
2578  float el = 0.0f;
+
2579  float az_max = 1e6f;
+
2580  float az_min = 1e6f;
+
2581  float el_max = 1e6f;
+
2582  float el_min = 1e6f;
+
2583  float az_rest = 1e6f;
+
2584  float el_rest = 1e6f;
+
2585  int etype = 0;
+
2586  int emcon_1 = -1;
+
2587  int emcon_2 = -1;
+
2588  int emcon_3 = -1;
+
2589 
+
2590  for (int i = 0; i < val->elements()->size(); i++) {
+
2591  TermDef* pdef = val->elements()->at(i)->isDef();
+
2592  if (pdef) {
+
2593  Text defname = pdef->name()->value();
+
2594  defname.setSensitive(false);
+
2595 
+
2596  if (defname == "type")
+
2597  GetDefText(wtype, pdef, filename);
+
2598  else if (defname == "name")
+
2599  GetDefText(wname, pdef, filename);
+
2600  else if (defname == "abrv")
+
2601  GetDefText(wabrv, pdef, filename);
+
2602  else if (defname == "design")
+
2603  GetDefText(design_name, pdef, filename);
+
2604  else if (defname == "group")
+
2605  GetDefText(group_name, pdef, filename);
+
2606 
+
2607  else if (defname == "muzzle") {
+
2608  if (nmuz < Weapon::MAX_BARRELS) {
+
2609  GetDefVec(muzzles[nmuz], pdef, filename);
+
2610  nmuz++;
+
2611  }
+
2612  else {
+
2613  Print("WARNING: too many muzzles (max=%d) for weapon in '%s'\n", filename, Weapon::MAX_BARRELS);
+
2614  }
+
2615  }
+
2616  else if (defname == "loc") {
+
2617  GetDefVec(loc, pdef, filename);
+
2618  loc *= (float) scale;
+
2619  }
+
2620  else if (defname == "size") {
+
2621  GetDefNumber(size, pdef, filename);
+
2622  size *= (float) scale;
+
2623  }
+
2624  else if (defname == "hull_factor") {
+
2625  GetDefNumber(hull, pdef, filename);
+
2626  }
+
2627  else if (defname == "azimuth") {
+
2628  GetDefNumber(az, pdef, filename);
+
2629  if (degrees) az *= (float) DEGREES;
+
2630  }
+
2631  else if (defname == "elevation") {
+
2632  GetDefNumber(el, pdef, filename);
+
2633  if (degrees) el *= (float) DEGREES;
+
2634  }
+
2635 
+
2636  else if (defname==("aim_az_max")) {
+
2637  GetDefNumber(az_max,pdef,filename);
+
2638  if (degrees) az_max *= (float) DEGREES;
+
2639  az_min = 0.0f - az_max;
+
2640  }
+
2641 
+
2642  else if (defname==("aim_el_max")) {
+
2643  GetDefNumber(el_max,pdef,filename);
+
2644  if (degrees) el_max *= (float) DEGREES;
+
2645  el_min = 0.0f - el_max;
+
2646  }
+
2647 
+
2648  else if (defname==("aim_az_min")) {
+
2649  GetDefNumber(az_min,pdef,filename);
+
2650  if (degrees) az_min *= (float) DEGREES;
+
2651  }
+
2652 
+
2653  else if (defname==("aim_el_min")) {
+
2654  GetDefNumber(el_min,pdef,filename);
+
2655  if (degrees) el_min *= (float) DEGREES;
+
2656  }
+
2657 
+
2658  else if (defname==("aim_az_rest")) {
+
2659  GetDefNumber(az_rest,pdef,filename);
+
2660  if (degrees) az_rest *= (float) DEGREES;
+
2661  }
+
2662 
+
2663  else if (defname==("aim_el_rest")) {
+
2664  GetDefNumber(el_rest,pdef,filename);
+
2665  if (degrees) el_rest *= (float) DEGREES;
+
2666  }
+
2667 
+
2668  else if (defname == "rest_azimuth") {
+
2669  GetDefNumber(az_rest, pdef, filename);
+
2670  if (degrees) az_rest *= (float) DEGREES;
+
2671  }
+
2672  else if (defname == "rest_elevation") {
+
2673  GetDefNumber(el_rest, pdef, filename);
+
2674  if (degrees) el_rest *= (float) DEGREES;
+
2675  }
+
2676  else if (defname == "explosion") {
+
2677  GetDefNumber(etype, pdef, filename);
+
2678  }
+
2679 
+
2680  else if (defname == "emcon_1") {
+
2681  GetDefNumber(emcon_1, pdef, filename);
+
2682  }
+
2683 
+
2684  else if (defname == "emcon_2") {
+
2685  GetDefNumber(emcon_2, pdef, filename);
+
2686  }
+
2687 
+
2688  else if (defname == "emcon_3") {
+
2689  GetDefNumber(emcon_3, pdef, filename);
+
2690  }
+
2691  else {
+
2692  Print("WARNING: unknown weapon parameter '%s' in '%s'\n",
+
2693  defname.data(), filename);
+
2694  }
+
2695  }
+
2696  }
+
2697 
+
2698  WeaponDesign* meta = WeaponDesign::Find(wtype);
+
2699  if (!meta) {
+
2700  Print("WARNING: unusual weapon name '%s' in '%s'\n", (const char*) wtype, filename);
+
2701  }
+
2702  else {
+
2703  // non-turret weapon muzzles are relative to ship scale:
+
2704  if (meta->turret_model == 0) {
+
2705  for (int i = 0; i < nmuz; i++)
+
2706  muzzles[i] *= (float) scale;
+
2707  }
+
2708 
+
2709  // turret weapon muzzles are relative to weapon scale:
+
2710  else {
+
2711  for (int i = 0; i < nmuz; i++)
+
2712  muzzles[i] *= (float) meta->scale;
+
2713  }
+
2714 
+
2715  Weapon* gun = new(__FILE__,__LINE__) Weapon(meta, nmuz, muzzles, az, el);
+
2716  gun->SetSourceIndex(reactors.size()-1);
+
2717  gun->Mount(loc, size, hull);
+
2718 
+
2719  if (az_max < 1e6) gun->SetAzimuthMax(az_max);
+
2720  if (az_min < 1e6) gun->SetAzimuthMin(az_min);
+
2721  if (az_rest < 1e6) gun->SetRestAzimuth(az_rest);
+
2722 
+
2723  if (el_max < 1e6) gun->SetElevationMax(el_max);
+
2724  if (el_min < 1e6) gun->SetElevationMin(el_min);
+
2725  if (el_rest < 1e6) gun->SetRestElevation(el_rest);
+
2726 
+
2727  if (emcon_1 >= 0 && emcon_1 <= 100)
+
2728  gun->SetEMCONPower(1, emcon_1);
+
2729 
+
2730  if (emcon_2 >= 0 && emcon_2 <= 100)
+
2731  gun->SetEMCONPower(1, emcon_2);
+
2732 
+
2733  if (emcon_3 >= 0 && emcon_3 <= 100)
+
2734  gun->SetEMCONPower(1, emcon_3);
+
2735 
+
2736  if (wname.length()) gun->SetName(wname);
+
2737  if (wabrv.length()) gun->SetAbbreviation(wabrv);
+
2738 
+
2739  if (design_name.length()) {
+
2740  SystemDesign* sd = SystemDesign::Find(design_name);
+
2741  if (sd)
+
2742  gun->SetDesign(sd);
+
2743  }
+
2744 
+
2745  if (group_name.length()) {
+
2746  gun->SetGroup(group_name);
+
2747  }
+
2748 
+
2749  gun->SetExplosionType(etype);
+
2750 
+
2751  if (meta->decoy_type && !decoy)
+
2752  decoy = gun;
+
2753  else if (meta->probe && !probe)
+
2754  probe = gun;
+
2755  else
+
2756  weapons.append(gun);
+
2757  }
+
2758 
+
2759  DataLoader* loader = DataLoader::GetLoader();
+
2760  loader->SetDataPath(path_name);
+
2761 }
+
2762 
+
2763 // +--------------------------------------------------------------------+
+
2764 
+
2765 void
+ +
2767 {
+
2768  Text wtypes[8];
+
2769  Text wname;
+
2770  Text wabrv;
+
2771  Text design;
+
2772  Vec3 muzzle;
+
2773  Vec3 loc(0.0f, 0.0f, 0.0f);
+
2774  float size = 0.0f;
+
2775  float hull = 0.5f;
+
2776  float az = 0.0f;
+
2777  float el = 0.0f;
+
2778  int ntypes = 0;
+
2779  int emcon_1 = -1;
+
2780  int emcon_2 = -1;
+
2781  int emcon_3 = -1;
+
2782 
+
2783  for (int i = 0; i < val->elements()->size(); i++) {
+
2784  TermDef* pdef = val->elements()->at(i)->isDef();
+
2785  if (pdef) {
+
2786  Text defname = pdef->name()->value();
+
2787  defname.setSensitive(false);
+
2788 
+
2789  if (defname == "type")
+
2790  GetDefText(wtypes[ntypes++], pdef, filename);
+
2791  else if (defname == "name")
+
2792  GetDefText(wname, pdef, filename);
+
2793  else if (defname == "abrv")
+
2794  GetDefText(wabrv, pdef, filename);
+
2795  else if (defname == "design")
+
2796  GetDefText(design, pdef, filename);
+
2797 
+
2798  else if (defname == "muzzle") {
+
2799  GetDefVec(muzzle, pdef, filename);
+
2800  muzzle *= (float) scale;
+
2801  }
+
2802  else if (defname == "loc") {
+
2803  GetDefVec(loc, pdef, filename);
+
2804  loc *= (float) scale;
+
2805  }
+
2806  else if (defname == "size") {
+
2807  GetDefNumber(size, pdef, filename);
+
2808  size *= (float) scale;
+
2809  }
+
2810  else if (defname == "hull_factor") {
+
2811  GetDefNumber(hull, pdef, filename);
+
2812  }
+
2813  else if (defname == "azimuth") {
+
2814  GetDefNumber(az, pdef, filename);
+
2815  if (degrees) az *= (float) DEGREES;
+
2816  }
+
2817  else if (defname == "elevation") {
+
2818  GetDefNumber(el, pdef, filename);
+
2819  if (degrees) el *= (float) DEGREES;
+
2820  }
+
2821 
+
2822  else if (defname == "emcon_1") {
+
2823  GetDefNumber(emcon_1, pdef, filename);
+
2824  }
+
2825 
+
2826  else if (defname == "emcon_2") {
+
2827  GetDefNumber(emcon_2, pdef, filename);
+
2828  }
+
2829 
+
2830  else if (defname == "emcon_3") {
+
2831  GetDefNumber(emcon_3, pdef, filename);
+
2832  }
+
2833  else {
+
2834  Print("WARNING: unknown weapon parameter '%s' in '%s'\n",
+
2835  defname.data(), filename);
+
2836  }
+
2837  }
+
2838  }
+
2839 
+
2840  HardPoint* hp = new(__FILE__,__LINE__) HardPoint(muzzle, az, el);
+
2841  if (hp) {
+
2842  for (int i = 0; i < ntypes; i++) {
+
2843  WeaponDesign* meta = WeaponDesign::Find(wtypes[i]);
+
2844  if (!meta) {
+
2845  Print("WARNING: unusual weapon name '%s' in '%s'\n", (const char*) wtypes[i], filename);
+
2846  }
+
2847  else {
+
2848  hp->AddDesign(meta);
+
2849  }
+
2850  }
+
2851 
+
2852  hp->Mount(loc, size, hull);
+
2853  if (wname.length()) hp->SetName(wname);
+
2854  if (wabrv.length()) hp->SetAbbreviation(wabrv);
+
2855  if (design.length()) hp->SetDesign(design);
+
2856 
+
2857  hard_points.append(hp);
+
2858  }
+
2859 
+
2860  DataLoader* loader = DataLoader::GetLoader();
+
2861  loader->SetDataPath(path_name);
+
2862 }
+
2863 
+
2864 // +--------------------------------------------------------------------+
+
2865 
+
2866 void
+ +
2868 {
+
2869  ShipLoad* load = new(__FILE__,__LINE__) ShipLoad;
+
2870 
+
2871  if (!load) return;
+
2872 
+
2873  for (int i = 0; i < val->elements()->size(); i++) {
+
2874  TermDef* pdef = val->elements()->at(i)->isDef();
+
2875  if (pdef) {
+
2876  Text defname = pdef->name()->value();
+
2877  defname.setSensitive(false);
+
2878 
+
2879  if (defname == "name")
+
2880  GetDefText(load->name, pdef, filename);
+
2881 
+
2882  else if (defname == "stations")
+
2883  GetDefArray(load->load, 16, pdef, filename);
+
2884 
+
2885  else
+
2886  Print("WARNING: unknown loadout parameter '%s' in '%s'\n",
+
2887  defname.data(), filename);
+
2888  }
+
2889  }
+
2890 
+
2891  loadouts.append(load);
+
2892 }
+
2893 
+
2894 // +--------------------------------------------------------------------+
+
2895 
+
2896 void
+ +
2898 {
+
2899  Text design_name;
+
2900  Vec3 loc(0.0f, 0.0f, 0.0f);
+
2901  float size = 0.0f;
+
2902  float hull = 0.5f;
+
2903  int nranges = 0;
+
2904  float ranges[8];
+
2905  int emcon_1 = -1;
+
2906  int emcon_2 = -1;
+
2907  int emcon_3 = -1;
+
2908 
+
2909  ZeroMemory(ranges, sizeof(ranges));
+
2910 
+
2911  for (int i = 0; i < val->elements()->size(); i++) {
+
2912  TermDef* pdef = val->elements()->at(i)->isDef();
+
2913  if (pdef) {
+
2914  Text defname = pdef->name()->value();
+
2915  defname.setSensitive(false);
+
2916 
+
2917  if (defname == "range") {
+
2918  GetDefNumber(ranges[nranges++], pdef, filename);
+
2919  }
+
2920  else if (defname == "loc") {
+
2921  GetDefVec(loc, pdef, filename);
+
2922  loc *= (float) scale;
+
2923  }
+
2924  else if (defname == "size") {
+
2925  size *= (float) scale;
+
2926  GetDefNumber(size, pdef, filename);
+
2927  }
+
2928  else if (defname == "hull_factor") {
+
2929  GetDefNumber(hull, pdef, filename);
+
2930  }
+
2931  else if (defname == "design") {
+
2932  GetDefText(design_name, pdef, filename);
+
2933  }
+
2934  else if (defname == "emcon_1") {
+
2935  GetDefNumber(emcon_1, pdef, filename);
+
2936  }
+
2937 
+
2938  else if (defname == "emcon_2") {
+
2939  GetDefNumber(emcon_2, pdef, filename);
+
2940  }
+
2941 
+
2942  else if (defname == "emcon_3") {
+
2943  GetDefNumber(emcon_3, pdef, filename);
+
2944  }
+
2945  }
+
2946  }
+
2947 
+
2948  if (!sensor) {
+
2949  sensor = new(__FILE__,__LINE__) Sensor();
+
2950 
+
2951  if (design_name.length()) {
+
2952  SystemDesign* sd = SystemDesign::Find(design_name);
+
2953  if (sd)
+
2954  sensor->SetDesign(sd);
+
2955  }
+
2956 
+
2957  for (int i = 0; i < nranges; i++)
+
2958  sensor->AddRange(ranges[i]);
+
2959 
+
2960  if (emcon_1 >= 0 && emcon_1 <= 100)
+
2961  sensor->SetEMCONPower(1, emcon_1);
+
2962 
+
2963  if (emcon_2 >= 0 && emcon_2 <= 100)
+
2964  sensor->SetEMCONPower(1, emcon_2);
+
2965 
+
2966  if (emcon_3 >= 0 && emcon_3 <= 100)
+
2967  sensor->SetEMCONPower(1, emcon_3);
+
2968 
+
2969  sensor->Mount(loc, size, hull);
+ +
2971  }
+
2972  else {
+
2973  Print("WARNING: additional sensor ignored in '%s'\n", filename);
+
2974  }
+
2975 }
+
2976 
+
2977 // +--------------------------------------------------------------------+
+
2978 
+
2979 void
+ +
2981 {
+
2982  Text design_name;
+
2983  Vec3 loc(0.0f, 0.0f, 0.0f);
+
2984  float size = 0.0f;
+
2985  float hull = 0.5f;
+
2986 
+
2987  for (int i = 0; i < val->elements()->size(); i++) {
+
2988  TermDef* pdef = val->elements()->at(i)->isDef();
+
2989  if (pdef) {
+
2990  Text defname = pdef->name()->value();
+
2991  defname.setSensitive(false);
+
2992 
+
2993  if (defname == "loc") {
+
2994  GetDefVec(loc, pdef, filename);
+
2995  loc *= (float) scale;
+
2996  }
+
2997  else if (defname == "size") {
+
2998  size *= (float) scale;
+
2999  GetDefNumber(size, pdef, filename);
+
3000  }
+
3001  else if (defname == "hull_factor") {
+
3002  GetDefNumber(hull, pdef, filename);
+
3003  }
+
3004  else if (defname == "design")
+
3005  GetDefText(design_name, pdef, filename);
+
3006  }
+
3007  }
+
3008 
+
3009  if (!navsys) {
+
3010  navsys = new(__FILE__,__LINE__) NavSystem;
+
3011 
+
3012  if (design_name.length()) {
+
3013  SystemDesign* sd = SystemDesign::Find(design_name);
+
3014  if (sd)
+
3015  navsys->SetDesign(sd);
+
3016  }
+
3017 
+
3018  navsys->Mount(loc, size, hull);
+ +
3020  }
+
3021  else {
+
3022  Print("WARNING: additional nav system ignored in '%s'\n", filename);
+
3023  }
+
3024 }
+
3025 
+
3026 // +--------------------------------------------------------------------+
+
3027 
+
3028 void
+ +
3030 {
+
3031  Text comp_name("Computer");
+
3032  Text comp_abrv("Comp");
+
3033  Text design_name;
+
3034  int comp_type = 1;
+
3035  Vec3 loc(0.0f, 0.0f, 0.0f);
+
3036  float size = 0.0f;
+
3037  float hull = 0.5f;
+
3038 
+
3039  for (int i = 0; i < val->elements()->size(); i++) {
+
3040  TermDef* pdef = val->elements()->at(i)->isDef();
+
3041  if (pdef) {
+
3042  Text defname = pdef->name()->value();
+
3043  defname.setSensitive(false);
+
3044 
+
3045  if (defname == "name") {
+
3046  GetDefText(comp_name, pdef, filename);
+
3047  }
+
3048  else if (defname == "abrv") {
+
3049  GetDefText(comp_abrv, pdef, filename);
+
3050  }
+
3051  else if (defname == "design") {
+
3052  GetDefText(design_name, pdef, filename);
+
3053  }
+
3054  else if (defname == "type") {
+
3055  GetDefNumber(comp_type, pdef, filename);
+
3056  }
+
3057  else if (defname == "loc") {
+
3058  GetDefVec(loc, pdef, filename);
+
3059  loc *= (float) scale;
+
3060  }
+
3061  else if (defname == "size") {
+
3062  size *= (float) scale;
+
3063  GetDefNumber(size, pdef, filename);
+
3064  }
+
3065  else if (defname == "hull_factor") {
+
3066  GetDefNumber(hull, pdef, filename);
+
3067  }
+
3068  }
+
3069  }
+
3070 
+
3071  Computer* comp = new(__FILE__,__LINE__) Computer(comp_type, comp_name);
+
3072  comp->Mount(loc, size, hull);
+
3073  comp->SetAbbreviation(comp_abrv);
+
3074  comp->SetSourceIndex(reactors.size()-1);
+
3075 
+
3076  if (design_name.length()) {
+
3077  SystemDesign* sd = SystemDesign::Find(design_name);
+
3078  if (sd)
+
3079  comp->SetDesign(sd);
+
3080  }
+
3081 
+
3082  computers.append(comp);
+
3083 }
+
3084 
+
3085 // +--------------------------------------------------------------------+
+
3086 
+
3087 void
+ +
3089 {
+
3090  Text dname;
+
3091  Text dabrv;
+
3092  Text design_name;
+
3093  Text model_name;
+
3094  double factor = 0;
+
3095  double capacity = 0;
+
3096  double consumption = 0;
+
3097  double cutoff = 0;
+
3098  double curve = 0;
+
3099  double def_cost = 1;
+
3100  int shield_type = 0;
+
3101  Vec3 loc(0.0f, 0.0f, 0.0f);
+
3102  float size = 0.0f;
+
3103  float hull = 0.5f;
+
3104  int etype = 0;
+
3105  bool shield_capacitor = false;
+
3106  bool shield_bubble = false;
+
3107  int emcon_1 = -1;
+
3108  int emcon_2 = -1;
+
3109  int emcon_3 = -1;
+
3110 
+
3111  for (int i = 0; i < val->elements()->size(); i++) {
+
3112  TermDef* pdef = val->elements()->at(i)->isDef();
+
3113  if (pdef) {
+
3114  Text defname = pdef->name()->value();
+
3115  defname.setSensitive(false);
+
3116 
+
3117  if (defname == "type") {
+
3118  GetDefNumber(shield_type, pdef, filename);
+
3119  }
+
3120  else if (defname == "name")
+
3121  GetDefText(dname, pdef, filename);
+
3122  else if (defname == "abrv")
+
3123  GetDefText(dabrv, pdef, filename);
+
3124  else if (defname == "design")
+
3125  GetDefText(design_name, pdef, filename);
+
3126  else if (defname == "model")
+
3127  GetDefText(model_name, pdef, filename);
+
3128 
+
3129  else if (defname == "loc") {
+
3130  GetDefVec(loc, pdef, filename);
+
3131  loc *= (float) scale;
+
3132  }
+
3133  else if (defname == "size") {
+
3134  GetDefNumber(size, pdef, filename);
+
3135  size *= (float) scale;
+
3136  }
+
3137  else if (defname == "hull_factor")
+
3138  GetDefNumber(hull, pdef, filename);
+
3139 
+
3140  else if (defname.contains("factor"))
+
3141  GetDefNumber(factor, pdef, filename);
+
3142  else if (defname.contains("cutoff"))
+
3143  GetDefNumber(cutoff, pdef, filename);
+
3144  else if (defname.contains("curve"))
+
3145  GetDefNumber(curve, pdef, filename);
+
3146  else if (defname.contains("capacitor"))
+
3147  GetDefBool(shield_capacitor, pdef, filename);
+
3148  else if (defname.contains("bubble"))
+
3149  GetDefBool(shield_bubble, pdef, filename);
+
3150  else if (defname == "capacity")
+
3151  GetDefNumber(capacity, pdef, filename);
+
3152  else if (defname == "consumption")
+
3153  GetDefNumber(consumption, pdef, filename);
+
3154  else if (defname == "deflection_cost")
+
3155  GetDefNumber(def_cost, pdef, filename);
+
3156  else if (defname == "explosion")
+
3157  GetDefNumber(etype, pdef, filename);
+
3158 
+
3159  else if (defname == "emcon_1") {
+
3160  GetDefNumber(emcon_1, pdef, filename);
+
3161  }
+
3162 
+
3163  else if (defname == "emcon_2") {
+
3164  GetDefNumber(emcon_2, pdef, filename);
+
3165  }
+
3166 
+
3167  else if (defname == "emcon_3") {
+
3168  GetDefNumber(emcon_3, pdef, filename);
+
3169  }
+
3170 
+
3171  else if (defname == "bolt_hit_sound") {
+ +
3173  }
+
3174 
+
3175  else if (defname == "beam_hit_sound") {
+ +
3177  }
+
3178  }
+
3179  }
+
3180 
+
3181  if (!shield) {
+
3182  if (shield_type) {
+
3183  shield = new(__FILE__,__LINE__) Shield((Shield::SUBTYPE) shield_type);
+ +
3185  shield->Mount(loc, size, hull);
+
3186  if (dname.length()) shield->SetName(dname);
+
3187  if (dabrv.length()) shield->SetAbbreviation(dabrv);
+
3188 
+
3189  if (design_name.length()) {
+
3190  SystemDesign* sd = SystemDesign::Find(design_name);
+
3191  if (sd)
+
3192  shield->SetDesign(sd);
+
3193  }
+
3194 
+
3195  shield->SetExplosionType(etype);
+
3196  shield->SetShieldCapacitor(shield_capacitor);
+
3197  shield->SetShieldBubble(shield_bubble);
+
3198 
+
3199  if (factor > 0) shield->SetShieldFactor(factor);
+
3200  if (capacity > 0) shield->SetCapacity(capacity);
+
3201  if (cutoff > 0) shield->SetShieldCutoff(cutoff);
+
3202  if (consumption > 0) shield->SetConsumption(consumption);
+
3203  if (def_cost > 0) shield->SetDeflectionCost(def_cost);
+
3204  if (curve > 0) shield->SetShieldCurve(curve);
+
3205 
+
3206  if (emcon_1 >= 0 && emcon_1 <= 100)
+
3207  shield->SetEMCONPower(1, emcon_1);
+
3208 
+
3209  if (emcon_2 >= 0 && emcon_2 <= 100)
+
3210  shield->SetEMCONPower(1, emcon_2);
+
3211 
+
3212  if (emcon_3 >= 0 && emcon_3 <= 100)
+
3213  shield->SetEMCONPower(1, emcon_3);
+
3214 
+
3215  if (model_name.length()) {
+
3216  shield_model = new(__FILE__,__LINE__) Model;
+
3217  if (!shield_model->Load(model_name, scale)) {
+
3218  Print("ERROR: Could not load shield model '%s'\n", model_name.data());
+
3219  delete shield_model;
+
3220  shield_model = 0;
+
3221  valid = false;
+
3222  }
+
3223  else {
+
3224  shield_model->SetDynamic(true);
+
3225  shield_model->SetLuminous(true);
+
3226  }
+
3227  }
+
3228 
+
3229  DataLoader* loader = DataLoader::GetLoader();
+
3230  DWORD SOUND_FLAGS = Sound::LOCALIZED | Sound::LOC_3D;
+
3231 
+
3232  if (bolt_hit_sound.length()) {
+
3233  if (!loader->LoadSound(bolt_hit_sound, bolt_hit_sound_resource, SOUND_FLAGS, true)) {
+
3234  loader->SetDataPath("Sounds/");
+
3235  loader->LoadSound(bolt_hit_sound, bolt_hit_sound_resource, SOUND_FLAGS);
+
3236  loader->SetDataPath(path_name);
+
3237  }
+
3238  }
+
3239 
+
3240  if (beam_hit_sound.length()) {
+
3241  if (!loader->LoadSound(beam_hit_sound, beam_hit_sound_resource, SOUND_FLAGS, true)) {
+
3242  loader->SetDataPath("Sounds/");
+
3243  loader->LoadSound(beam_hit_sound, beam_hit_sound_resource, SOUND_FLAGS);
+
3244  loader->SetDataPath(path_name);
+
3245  }
+
3246  }
+
3247  }
+
3248  else {
+
3249  Print("WARNING: invalid shield type in '%s'\n", filename);
+
3250  }
+
3251  }
+
3252  else {
+
3253  Print("WARNING: additional shield ignored in '%s'\n", filename);
+
3254  }
+
3255 }
+
3256 
+
3257 // +--------------------------------------------------------------------+
+
3258 
+
3259 void
+ +
3261 {
+
3262  int exp_index = -1;
+
3263  int debris_index = -1;
+
3264  int fire_index = -1;
+
3265 
+
3266  for (int i = 0; i < val->elements()->size(); i++) {
+
3267  TermDef* def = val->elements()->at(i)->isDef();
+
3268  if (def) {
+
3269  Text defname = def->name()->value();
+
3270  defname.setSensitive(false);
+
3271 
+
3272  if (defname == "time") {
+ +
3274  }
+
3275 
+
3276  else if (defname == "explosion") {
+
3277  if (!def->term() || !def->term()->isStruct()) {
+
3278  Print("WARNING: explosion struct missing in '%s'\n", filename);
+
3279  }
+
3280  else {
+
3281  TermStruct* val = def->term()->isStruct();
+
3282  ParseExplosion(val, ++exp_index);
+
3283  }
+
3284  }
+
3285 
+
3286  // BACKWARD COMPATIBILITY:
+
3287  else if (defname == "explosion_type") {
+
3288  GetDefNumber(explosion[++exp_index].type, def, filename);
+
3289  }
+
3290 
+
3291  else if (defname == "explosion_time") {
+
3292  GetDefNumber(explosion[exp_index].time, def, filename);
+
3293  }
+
3294 
+
3295  else if (defname == "explosion_loc") {
+
3296  GetDefVec(explosion[exp_index].loc, def, filename);
+
3297  explosion[exp_index].loc *= (float) scale;
+
3298  }
+
3299 
+
3300  else if (defname == "final_type") {
+
3301  GetDefNumber(explosion[++exp_index].type, def, filename);
+
3302  explosion[exp_index].final = true;
+
3303  }
+
3304 
+
3305  else if (defname == "final_loc") {
+
3306  GetDefVec(explosion[exp_index].loc, def, filename);
+
3307  explosion[exp_index].loc *= (float) scale;
+
3308  }
+
3309 
+
3310 
+
3311  else if (defname == "debris") {
+
3312  if (def->term() && def->term()->isText()) {
+
3313  Text model_name;
+
3314  GetDefText(model_name, def, filename);
+
3315  Model* model = new(__FILE__,__LINE__) Model;
+
3316  if (!model->Load(model_name, scale)) {
+
3317  Print("Could not load debris model '%s'\n", model_name.data());
+
3318  delete model;
+
3319  return;
+
3320  }
+
3321 
+
3322  PrepareModel(*model);
+
3323  debris[++debris_index].model = model;
+
3324  fire_index = -1;
+
3325  }
+
3326  else if (!def->term() || !def->term()->isStruct()) {
+
3327  Print("WARNING: debris struct missing in '%s'\n", filename);
+
3328  }
+
3329  else {
+
3330  TermStruct* val = def->term()->isStruct();
+
3331  ParseDebris(val, ++debris_index);
+
3332  }
+
3333  }
+
3334 
+
3335  else if (defname == "debris_mass") {
+
3336  GetDefNumber(debris[debris_index].mass, def, filename);
+
3337  }
+
3338 
+
3339  else if (defname == "debris_speed") {
+
3340  GetDefNumber(debris[debris_index].speed, def, filename);
+
3341  }
+
3342 
+
3343  else if (defname == "debris_drag") {
+
3344  GetDefNumber(debris[debris_index].drag, def, filename);
+
3345  }
+
3346 
+
3347  else if (defname == "debris_loc") {
+
3348  GetDefVec(debris[debris_index].loc, def, filename);
+
3349  debris[debris_index].loc *= (float) scale;
+
3350  }
+
3351 
+
3352  else if (defname == "debris_count") {
+
3353  GetDefNumber(debris[debris_index].count, def, filename);
+
3354  }
+
3355 
+
3356  else if (defname == "debris_life") {
+
3357  GetDefNumber(debris[debris_index].life, def, filename);
+
3358  }
+
3359 
+
3360  else if (defname == "debris_fire") {
+
3361  if (++fire_index < 5) {
+
3362  GetDefVec(debris[debris_index].fire_loc[fire_index], def, filename);
+
3363  debris[debris_index].fire_loc[fire_index] *= (float) scale;
+
3364  }
+
3365  }
+
3366 
+
3367  else if (defname == "debris_fire_type") {
+
3368  GetDefNumber(debris[debris_index].fire_type, def, filename);
+
3369  }
+
3370  }
+
3371  }
+
3372 }
+
3373 
+
3374 // +--------------------------------------------------------------------+
+
3375 
+
3376 void
+ +
3378 {
+
3379  ShipExplosion* exp = &explosion[index];
+
3380 
+
3381  for (int i = 0; i < val->elements()->size(); i++) {
+
3382  TermDef* def = val->elements()->at(i)->isDef();
+
3383  if (def) {
+
3384  Text defname = def->name()->value();
+
3385  defname.setSensitive(false);
+
3386 
+
3387  if (defname == "time") {
+
3388  GetDefNumber(exp->time, def, filename);
+
3389  }
+
3390 
+
3391  else if (defname == "type") {
+
3392  GetDefNumber(exp->type, def, filename);
+
3393  }
+
3394 
+
3395  else if (defname == "loc") {
+
3396  GetDefVec(exp->loc, def, filename);
+
3397  exp->loc *= (float) scale;
+
3398  }
+
3399 
+
3400  else if (defname == "final") {
+
3401  GetDefBool(exp->final, def, filename);
+
3402  }
+
3403  }
+
3404  }
+
3405 }
+
3406 
+
3407 // +--------------------------------------------------------------------+
+
3408 
+
3409 void
+ +
3411 {
+
3412  char model_name[NAMELEN];
+
3413  int fire_index = 0;
+
3414  ShipDebris* deb = &debris[index];
+
3415 
+
3416  for (int i = 0; i < val->elements()->size(); i++) {
+
3417  TermDef* def = val->elements()->at(i)->isDef();
+
3418  if (def) {
+
3419  Text defname = def->name()->value();
+
3420 
+
3421  if (defname == "model") {
+
3422  GetDefText(model_name, def, filename);
+
3423  Model* model = new(__FILE__,__LINE__) Model;
+
3424  if (!model->Load(model_name, scale)) {
+
3425  Print("Could not load debris model '%s'\n", model_name);
+
3426  delete model;
+
3427  return;
+
3428  }
+
3429 
+
3430  PrepareModel(*model);
+
3431  deb->model = model;
+
3432  }
+
3433 
+
3434  else if (defname == "mass") {
+
3435  GetDefNumber(deb->mass, def, filename);
+
3436  }
+
3437 
+
3438  else if (defname == "speed") {
+
3439  GetDefNumber(deb->speed, def, filename);
+
3440  }
+
3441 
+
3442  else if (defname == "drag") {
+
3443  GetDefNumber(deb->drag, def, filename);
+
3444  }
+
3445 
+
3446  else if (defname == "loc") {
+
3447  GetDefVec(deb->loc, def, filename);
+
3448  deb->loc *= (float) scale;
+
3449  }
+
3450 
+
3451  else if (defname == "count") {
+
3452  GetDefNumber(deb->count, def, filename);
+
3453  }
+
3454 
+
3455  else if (defname == "life") {
+
3456  GetDefNumber(deb->life, def, filename);
+
3457  }
+
3458 
+
3459  else if (defname == "fire") {
+
3460  if (fire_index < 5) {
+
3461  GetDefVec(deb->fire_loc[fire_index], def, filename);
+
3462  deb->fire_loc[fire_index] *= (float) scale;
+
3463  fire_index++;
+
3464  }
+
3465  }
+
3466 
+
3467  else if (defname == "fire_type") {
+
3468  GetDefNumber(deb->fire_type, def, filename);
+
3469  }
+
3470  }
+
3471  }
+
3472 }
+
3473 
+
3474 // +--------------------------------------------------------------------+
+
3475 
+
3476 void
+ +
3478 {
+
3479  char sprite_name[NAMELEN];
+
3480 
+
3481  for (int i = 0; i < val->elements()->size(); i++) {
+
3482  TermDef* pdef = val->elements()->at(i)->isDef();
+
3483  if (pdef) {
+
3484  Text defname = pdef->name()->value();
+
3485  defname.setSensitive(false);
+
3486 
+
3487  if (defname == "sprite") {
+
3488  GetDefText(sprite_name, pdef, filename);
+
3489 
+
3490  Bitmap* sprite = new(__FILE__,__LINE__) Bitmap();
+
3491  DataLoader* loader = DataLoader::GetLoader();
+
3492  loader->LoadBitmap(sprite_name, *sprite, Bitmap::BMP_TRANSLUCENT);
+
3493 
+
3494  map_sprites.append(sprite);
+
3495  }
+
3496  }
+
3497  }
+
3498 }
+
3499 
+
3500 // +--------------------------------------------------------------------+
+
3501 
+
3502 void
+ +
3504 {
+
3505  char name[NAMELEN];
+
3506  char design[NAMELEN];
+
3507  int count = 4;
+
3508  int avail = 4;
+
3509 
+
3510  name[0] = 0;
+
3511  design[0] = 0;
+
3512 
+
3513  for (int i = 0; i < val->elements()->size(); i++) {
+
3514  TermDef* pdef = val->elements()->at(i)->isDef();
+
3515  if (pdef) {
+
3516  Text defname = pdef->name()->value();
+
3517  defname.setSensitive(false);
+
3518 
+
3519  if (defname == "name") {
+
3520  GetDefText(name, pdef, filename);
+
3521  }
+
3522  else if (defname == "design") {
+
3523  GetDefText(design, pdef, filename);
+
3524  }
+
3525  else if (defname == "count") {
+
3526  GetDefNumber(count, pdef, filename);
+
3527  }
+
3528  else if (defname == "avail") {
+
3529  GetDefNumber(avail, pdef, filename);
+
3530  }
+
3531  }
+
3532  }
+
3533 
+
3534  ShipSquadron* s = new(__FILE__,__LINE__) ShipSquadron;
+
3535  strcpy_s(s->name, name);
+
3536 
+
3537  s->design = Get(design);
+
3538  s->count = count;
+
3539  s->avail = avail;
+
3540 
+
3541  squadrons.append(s);
+
3542 }
+
3543 
+
3544 // +--------------------------------------------------------------------+
+
3545 
+
3546 Skin*
+ +
3548 {
+
3549  Skin* skin = 0;
+
3550  char name[NAMELEN];
+
3551 
+
3552  name[0] = 0;
+
3553 
+
3554  for (int i = 0; i < val->elements()->size(); i++) {
+
3555  TermDef* def = val->elements()->at(i)->isDef();
+
3556  if (def) {
+
3557  Text defname = def->name()->value();
+
3558  defname.setSensitive(false);
+
3559 
+
3560  if (defname == "name") {
+
3561  GetDefText(name, def, filename);
+
3562 
+
3563  skin = new(__FILE__,__LINE__) Skin(name);
+
3564  }
+
3565  else if (defname == "material" || defname == "mtl") {
+
3566  if (!def->term() || !def->term()->isStruct()) {
+
3567  Print("WARNING: skin struct missing in '%s'\n", filename);
+
3568  }
+
3569  else {
+
3570  TermStruct* val = def->term()->isStruct();
+
3571  ParseSkinMtl(val, skin);
+
3572  }
+
3573  }
+
3574  }
+
3575  }
+
3576 
+
3577  if (skin && skin->NumCells()) {
+
3578  skins.append(skin);
+
3579  }
+
3580 
+
3581  else if (skin) {
+
3582  delete skin;
+
3583  skin = 0;
+
3584  }
+
3585 
+
3586  return skin;
+
3587 }
+
3588 
+
3589 void
+ +
3591 {
+
3592  Material* mtl = new(__FILE__,__LINE__) Material;
+
3593 
+
3594  for (int i = 0; i < val->elements()->size(); i++) {
+
3595  TermDef* def = val->elements()->at(i)->isDef();
+
3596  if (def) {
+
3597  Text defname = def->name()->value();
+
3598  defname.setSensitive(false);
+
3599 
+
3600  if (defname == "name") {
+
3601  GetDefText(mtl->name, def, filename);
+
3602  }
+
3603  else if (defname == "Ka") {
+
3604  GetDefColor(mtl->Ka, def, filename);
+
3605  }
+
3606  else if (defname == "Kd") {
+
3607  GetDefColor(mtl->Kd, def, filename);
+
3608  }
+
3609  else if (defname == "Ks") {
+
3610  GetDefColor(mtl->Ks, def, filename);
+
3611  }
+
3612  else if (defname == "Ke") {
+
3613  GetDefColor(mtl->Ke, def, filename);
+
3614  }
+
3615  else if (defname == "Ns" || defname == "power") {
+
3616  GetDefNumber(mtl->power, def, filename);
+
3617  }
+
3618  else if (defname == "bump") {
+
3619  GetDefNumber(mtl->bump, def, filename);
+
3620  }
+
3621  else if (defname == "luminous") {
+
3622  GetDefBool(mtl->luminous, def, filename);
+
3623  }
+
3624 
+
3625  else if (defname == "blend") {
+
3626  if (def->term() && def->term()->isNumber())
+
3627  GetDefNumber(mtl->blend, def, filename);
+
3628 
+
3629  else if (def->term() && def->term()->isText()) {
+
3630  Text val;
+
3631  GetDefText(val, def, filename);
+
3632  val.setSensitive(false);
+
3633 
+
3634  if (val == "alpha" || val == "translucent")
+ +
3636 
+
3637  else if (val == "additive")
+ +
3639 
+
3640  else
+
3641  mtl->blend = Material::MTL_SOLID;
+
3642  }
+
3643  }
+
3644 
+
3645  else if (defname.indexOf("tex_d") == 0) {
+
3646  char tex_name[64];
+
3647  if (!GetDefText(tex_name, def, filename))
+
3648  Print("WARNING: invalid or missing tex_diffuse in '%s'\n", filename);
+
3649 
+
3650  DataLoader* loader = DataLoader::GetLoader();
+
3651  loader->LoadTexture(tex_name, mtl->tex_diffuse);
+
3652  }
+
3653 
+
3654  else if (defname.indexOf("tex_s") == 0) {
+
3655  char tex_name[64];
+
3656  if (!GetDefText(tex_name, def, filename))
+
3657  Print("WARNING: invalid or missing tex_specular in '%s'\n", filename);
+
3658 
+
3659  DataLoader* loader = DataLoader::GetLoader();
+
3660  loader->LoadTexture(tex_name, mtl->tex_specular);
+
3661  }
+
3662 
+
3663  else if (defname.indexOf("tex_b") == 0) {
+
3664  char tex_name[64];
+
3665  if (!GetDefText(tex_name, def, filename))
+
3666  Print("WARNING: invalid or missing tex_bumpmap in '%s'\n", filename);
+
3667 
+
3668  DataLoader* loader = DataLoader::GetLoader();
+
3669  loader->LoadTexture(tex_name, mtl->tex_bumpmap);
+
3670  }
+
3671 
+
3672  else if (defname.indexOf("tex_e") == 0) {
+
3673  char tex_name[64];
+
3674  if (!GetDefText(tex_name, def, filename))
+
3675  Print("WARNING: invalid or missing tex_emissive in '%s'\n", filename);
+
3676 
+
3677  DataLoader* loader = DataLoader::GetLoader();
+
3678  loader->LoadTexture(tex_name, mtl->tex_emissive);
+
3679  }
+
3680  }
+
3681  }
+
3682 
+
3683  if (skin && mtl)
+
3684  skin->AddMaterial(mtl);
+
3685 }
+
3686 
+
3687 const Skin*
+
3688 ShipDesign::FindSkin(const char* skin_name) const
+
3689 {
+
3690  int n = skins.size();
+
3691 
+
3692  for (int i = 0; i < n; i++) {
+
3693  Skin* s = skins[n-1-i];
+
3694 
+
3695  if (!strcmp(s->Name(), skin_name))
+
3696  return s;
+
3697  }
+
3698 
+
3699  return 0;
+
3700 }
+
+
+ + + + -- cgit v1.1