Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
star_system_xml.cpp
Go to the documentation of this file.
1 #include <expat.h>
2 #include "xml_support.h"
3 #include "star_system_generic.h"
4 #include "cmd/planet_generic.h"
5 #include "cmd/unit_factory.h"
6 #include "vs_globals.h"
7 #include "vsfilesystem.h"
8 #include "configxml.h"
9 #include "vegastrike.h"
10 #include <assert.h>
11 #include "gfx/mesh.h"
12 #include "cmd/building_generic.h"
13 #include "cmd/ai/aggressive.h"
14 #include "cmd/ai/fire.h"
15 #include "cmd/nebula_generic.h"
16 #include "cmd/asteroid_generic.h"
18 #include "cmd/script/flightgroup.h"
19 #include "universe_util.h"
20 #include "cmd/atmosphere.h"
21 
22 #include "options.h"
24 
25 #include <stdlib.h>
26 
27 #include <string>
28 #include <vector>
29 #include <map>
30 
31 using std::string;
32 using std::vector;
33 using std::map;
34 
35 extern const vector< string >& ParseDestinations( const string &value );
36 extern void bootstrap_draw( const string &message, Animation *SplashScreen = NULL );
37 extern void disableTerrainDraw( ContinuousTerrain *ct );
38 
40 {
41  er = eg = eb = ea = .5;
42  dr = dg = db = da = .5;
43  meshname = "sphereatm.bfxm";
44  scale = 1.05;
45  focus = .5;
46  concavity = 0;
47  tail_mode_start = -1;
48  tail_mode_end = -1;
49  min_alpha = 0;
50  max_alpha = 255;
51 }
52 namespace StarXML
53 {
54 enum Names
55 {
58  X,
59  Y,
60  Z,
61  RI,
62  RJ,
63  RK,
64  SI,
65  SJ,
66  SK,
67  QI,
68  QJ,
69  QK,
75  DAY,
152 };
153 
155  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
156  EnumMap::Pair( "Planet", PLANET ),
157  EnumMap::Pair( "System", SYSTEM ),
158  EnumMap::Pair( "Unit", UNIT ),
159  EnumMap::Pair( "Enhancement", ENHANCEMENT ),
160  EnumMap::Pair( "Jump", JUMP ),
161  EnumMap::Pair( "Light", LIGHT ),
162  EnumMap::Pair( "Attenuated", ATTEN ),
163  EnumMap::Pair( "Diffuse", DIFF ),
164  EnumMap::Pair( "Specular", SPEC ),
165  EnumMap::Pair( "Ambient", AMB ),
166  EnumMap::Pair( "Terrain", TERRAIN ),
167  EnumMap::Pair( "ContinuousTerrain", CONTTERRAIN ),
168  EnumMap::Pair( "Building", BUILDING ),
169  EnumMap::Pair( "Vehicle", VEHICLE ),
170  EnumMap::Pair( "Atmosphere", ATMOSPHERE ),
171  EnumMap::Pair( "Nebula", NEBULA ),
172  EnumMap::Pair( "Asteroid", ASTEROID ),
173  EnumMap::Pair( "RING", RING ),
174  EnumMap::Pair( "citylights", CITYLIGHTS ),
175  EnumMap::Pair( "SpaceElevator", SPACEELEVATOR ),
176  EnumMap::Pair( "Fog", FOG ),
177  EnumMap::Pair( "FogElement", FOGELEMENT ),
178  EnumMap::Pair( "Condition", CONDITION ),
179 };
181  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
182  EnumMap::Pair( "background", BACKGROUND ),
183  EnumMap::Pair( "backgroundColor", BACKGROUND_COLOR ),
184  EnumMap::Pair( "backgroundDegamma", BACKGROUND_DEGAMMA ),
185  EnumMap::Pair( "stars", STARS ),
186  EnumMap::Pair( "nearstars", NEARSTARS ),
187  EnumMap::Pair( "fadestars", FADESTARS ),
188  EnumMap::Pair( "starspread", STARSPREAD ),
189  EnumMap::Pair( "reflectivity", REFLECTIVITY ),
190  EnumMap::Pair( "file", XFILE ),
191  EnumMap::Pair( "alpha", ALPHA ),
192  EnumMap::Pair( "destination", DESTINATION ),
193  EnumMap::Pair( "direction", DIRECTION ),
194  EnumMap::Pair( "x", X ),
195  EnumMap::Pair( "y", Y ),
196  EnumMap::Pair( "z", Z ),
197  EnumMap::Pair( "ri", RI ),
198  EnumMap::Pair( "rj", RJ ),
199  EnumMap::Pair( "rk", RK ),
200  EnumMap::Pair( "si", SI ),
201  EnumMap::Pair( "sj", SJ ),
202  EnumMap::Pair( "sk", SK ),
203  EnumMap::Pair( "qi", QI ),
204  EnumMap::Pair( "qj", QJ ),
205  EnumMap::Pair( "qk", QK ),
206  EnumMap::Pair( "name", NAME ),
207  EnumMap::Pair( "radius", RADIUS ),
208  EnumMap::Pair( "gravity", GRAVITY ),
209  EnumMap::Pair( "year", YEAR ),
210  EnumMap::Pair( "day", DAY ),
211  EnumMap::Pair( "position", PPOSITION ),
212  EnumMap::Pair( "MaxAlpha", MAXALPHA ),
213  EnumMap::Pair( "MinAlpha", MINALPHA ),
214  EnumMap::Pair( "DRed", DIRED ),
215  EnumMap::Pair( "DGreen", DIGREEN ),
216  EnumMap::Pair( "DBlue", DIBLUE ),
217  EnumMap::Pair( "DAlpha", DIALPHA ),
218  EnumMap::Pair( "Red", EMRED ),
219  EnumMap::Pair( "Green", EMGREEN ),
220  EnumMap::Pair( "Blue", EMBLUE ),
221  EnumMap::Pair( "Alfa", EMALPHA ),
222  EnumMap::Pair( "SRed", SRED ),
223  EnumMap::Pair( "SGreen", SGREEN ),
224  EnumMap::Pair( "SBlue", SBLUE ),
225  EnumMap::Pair( "SAlfa", SALPHA ),
226  EnumMap::Pair( "SPower", SPOWER ),
227  EnumMap::Pair( "ReflectNoLight", REFLECTNOLIGHT ),
228  EnumMap::Pair( "faction", FACTION ),
229  EnumMap::Pair( "Light", LIGHT ),
230  EnumMap::Pair( "Mass", MASS ),
231  EnumMap::Pair( "ScaleX", SCALEX ),
232  EnumMap::Pair( "NumWraps", NUMWRAPS ),
233  EnumMap::Pair( "NumSlices", NUMSLICES ),
234  EnumMap::Pair( "Difficulty", DIFFICULTY ),
235  EnumMap::Pair( "ScaleAtmosphereHeight", SCALEATMOS ),
236  EnumMap::Pair( "ScaleSystem", SCALESYSTEM ),
237  EnumMap::Pair( "InsideOut", INSIDEOUT ),
238  EnumMap::Pair( "InnerRadius", INNERRADIUS ),
239  EnumMap::Pair( "OuterRadius", OUTERRADIUS ),
240  EnumMap::Pair( "WrapX", WRAPX ),
241  EnumMap::Pair( "WrapY", WRAPY ),
242  EnumMap::Pair( "Focus", FOCUS ),
243  EnumMap::Pair( "Concavity", CONCAVITY ),
244  EnumMap::Pair( "TailModeStart", TAILMODESTART ),
245  EnumMap::Pair( "TailModeEnd", TAILMODEEND ),
246  EnumMap::Pair( "OpticalIllusion", OPTICALILLUSION ),
247  EnumMap::Pair( "serial", SERIAL ),
248  EnumMap::Pair( "VarName", VARNAME ),
249  EnumMap::Pair( "VarValue", VARVALUE ),
250  EnumMap::Pair( "Condition", CONDITION ),
251  EnumMap::Pair( "expression", EXPRESSION ),
252  EnumMap::Pair( "technique", TECHNIQUE ),
253  EnumMap::Pair( "unit", UNIT ),
254  EnumMap::Pair( "override", OVERRIDE )
255 };
256 
257 //By Klauss - more flexible this way
258 const EnumMap element_map( element_names, sizeof (element_names)/sizeof (element_names[0]) );
259 //By Klauss - more flexible this way
261 }
262 
263 using XMLSupport::EnumMap;
266 
270 
271 template < typename T >
272 static bool EvalCondition( const char *op, const T &left, const T &right )
273 {
274  switch (op[0])
275  {
276  case '>':
277  switch (op[1])
278  {
279  case 0:
280  return left > right;
281 
282  case '=':
283  return left >= right;
284 
285  default:
286  return false;
287  }
288  case '=':
289  switch (op[1])
290  {
291  case 0:
292  case '=':
293  return left == right;
294 
295  default:
296  return false;
297  }
298  case '<':
299  switch (op[1])
300  {
301  case 0:
302  return left < right;
303 
304  case '=':
305  return left <= right;
306 
307  default:
308  return false;
309  }
310  case '!':
311  switch (op[1])
312  {
313  case '=':
314  return left != right;
315 
316  default:
317  return false;
318  }
319  default:
320  return false;
321  }
322 }
323 
324 static bool ConfigCondition( const string &cond )
325 {
326  if ( cond.empty() )
327  return true;
328  char varname[64];
329  char op[3];
330  char varval[64];
331  bool ok = 3 == sscanf( cond.c_str(), "%63[-a-zA-Z_0-9] %2[<>=!] %63[-0-9.Ee]",
332  varname,
333  op,
334  varval );
335  if (!ok)
336  return false;
337  //finalize character strings, for security
338  varname[sizeof (varname)/sizeof (*varname)-1] = 0;
339  op[sizeof (op)/sizeof (*op)-1] = 0;
340  varval[sizeof (varval)/sizeof (*varval)-1] = 0;
341  //try to parse varval - if not parseable as float, assume it's a string
342  char *endptr = 0;
343  bool rv;
344  if (endptr == varval) {
345  string sval = vs_config->getVariable( "graphics", varname, "0.0" );
346  rv = EvalCondition< string > ( op, sval, varval );
347  } else {
348  float fval = XMLSupport::parse_floatf( vs_config->getVariable( "graphics", varname, "0.0" ) );
349  float fref = XMLSupport::parse_floatf( varval );
350  rv = EvalCondition< float > ( op, fval, fref );
351  }
352  return rv;
353 }
354 
355 static bool ConfigAllows( string var, float val )
356 {
357  bool invert = false;
358  if (var.length() == 0)
359  return true;
360  if (var[0] == '-') {
361  var = var.substr( 1 );
362  invert = true;
363  }
364  float x = XMLSupport::parse_floatf( vs_config->getVariable( "graphics", var, "0.0" ) );
365  if (var.length() == 0)
366  return true;
367  return invert ? -x >= val : x >= val;
368 }
369 
370 static Vector ComputeRotVel( float rotvel, const QVector &r, const QVector &s )
371 {
372  if ( (r.i || r.j || r.k) && (s.i || s.j || s.k) ) {
373  QVector retval = r.Cross( s );
374  retval.Normalize();
375  retval = retval*rotvel;
376  return retval.Cast();
377  } else {
378  return Vector( 0, rotvel, 0 );
379  }
380 }
381 
382 static void GetLights( const vector< GFXLight > &origlights, vector< GFXLightLocal > &curlights, const char *str, float lightSize )
383 {
384  int tint;
385  char isloc;
386  char *tmp = strdup( str );
387  GFXLightLocal lloc;
388  char *st = tmp;
389  int numel;
390  while ( ( numel = sscanf( st, "%d%c", &tint, &isloc ) ) > 0 ) {
391  assert( tint < (int) origlights.size() );
392  lloc.ligh = origlights[tint];
393  lloc.islocal = (numel > 1 && isloc == 'l');
394 
395  lloc.ligh.setSize(lightSize);
396 
397  curlights.push_back( lloc );
398  while ( isspace( *st ) )
399  ++st;
400  while ( isalnum( *st ) )
401  ++st;
402  }
403  free( tmp );
404 }
405 
406 extern Unit * getTopLevelOwner();
407 extern BLENDFUNC parse_alpha( const char* );
408 static void SetSubunitRotation( Unit *un, float difficulty )
409 {
410  Unit *unit;
411  for (un_iter iter = un->getSubUnits(); (unit = *iter); ++iter) {
412  float x = 2*difficulty*( (float) rand() )/RAND_MAX-difficulty;
413  float y = 2*difficulty*( (float) rand() )/RAND_MAX-difficulty;
414  float z = 2*difficulty*( (float) rand() )/RAND_MAX-difficulty;
415  unit->SetAngularVelocity( Vector( x, y, z ) );
416  SetSubunitRotation( unit, difficulty );
417  }
418 }
419 
420 void parse_dual_alpha( const char *alpha, BLENDFUNC &blendSrc, BLENDFUNC &blendDst )
421 {
422  blendSrc = ONE;
423  blendDst = ZERO;
424  if (alpha == NULL) {} else if (alpha[0] == '\0') {} else {
425  char *s = strdup( alpha );
426  char *d = strdup( alpha );
427  blendSrc = SRCALPHA;
428  blendDst = INVSRCALPHA;
429  if ( 2 == sscanf( alpha, "%s %s", s, d ) ) {
430  if (strcmp( s, "true" ) != 0) {
431  blendSrc = parse_alpha( s );
432  blendDst = parse_alpha( d );
433  }
434  }
435  free( s );
436  free( d );
437  }
438 }
439 
441 {
442  return game_options.num_near_stars;
443 }
444 
446 {
447  return game_options.num_far_stars;
448 }
449 
451 {
452  return game_options.star_spreading*game_options.game_speed;
453 }
454 
455 float ScaleOrbitDist( bool autogenerated )
456 {
457  if (autogenerated)
458  return game_options.autogen_compactness*game_options.runtime_compactness;
459  return game_options.runtime_compactness;
460 }
461 
462 extern float ScaleJumpRadius( float radius );
463 
464 void StarSystem::beginElement( const string &name, const AttributeList &attributes )
465 {
466  using namespace StarXML;
467  int neutralfaction = FactionUtil::GetNeutralFaction();
468  string myfile;
469  vector< GFXLightLocal >curlights;
470  xml->cursun.i = 0;
471  string varname, condition;
472  float varvalue = 0;
473  GFXColor tmpcol( 0, 0, 0, 1 );
474  LIGHT_TARGET tmptarg = POSITION;
475  xml->cursun.j = 0;
476  string citylights;
477  string technique;
478  ObjSerial serial = 0;
479  float scaleatmos = 10;
480  char *nebfile;
481  bool insideout = false;
482  int faction = 0;
483  string truncatedfilename = this->filename;
484  {
485  string::size_type tmp;
486  if ( ( tmp = truncatedfilename.find( ".system" ) ) != string::npos )
487  truncatedfilename = truncatedfilename.substr( 0, tmp );
488  }
489  BLENDFUNC blendSrc = ONE;
490  BLENDFUNC blendDst = ZERO;
491  bool isdest = false;
492 
493  xml->cursun.k = 0;
494  GFXMaterial ourmat;
495  GFXGetMaterial( 0, ourmat );
496  vs_config->getColor( "planet_mat_ambient", &ourmat.ar );
497  vs_config->getColor( "planet_mat_diffuse", &ourmat.dr );
498  vs_config->getColor( "planet_mat_specular", &ourmat.sr );
499  vs_config->getColor( "planet_mat_emmissive", &ourmat.er );
500  int numwraps = 1;
501  float scalex = 1;
502  vector< string >dest;
503  map< string, string > paramOverrides;
504  string filename;
505  string unitname;
506  string fullname = "unknw";
507  float gravity = 0;
508  float velocity = 0;
509  float position = 0;
510  float rotvel = 0;
511  QVector S( 0, 0, 0 ), R( 0, 0, 0 );
512  QVector pos( 0, 0, 0 );
513  Names elem = (Names) element_map.lookup( name );
514  float radius = 1.0f;
515  AttributeList::const_iterator iter;
516  switch (elem)
517  {
518  case UNKNOWN:
519  ++xml->unitlevel;
520 
521  return;
522 
523  case SYSTEM:
524  assert( xml->unitlevel == 0 );
525  ++xml->unitlevel;
526  pos = QVector( 0, 0, 0 );
527  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
528  switch ( attribute_map.lookup( (*iter).name ) )
529  {
530  case SCALESYSTEM:
531  xml->scale *= parse_float( (*iter).value );
532  break;
533  case REFLECTIVITY:
534  xml->reflectivity = parse_float( (*iter).value );
535  break;
536  case BACKGROUND:
537  xml->backgroundname = (*iter).value;
538  break;
539  case BACKGROUND_COLOR:
540  parse_floatfv( (*iter).value, 4,
544  &xml->backgroundColor.a);
545  break;
546  case BACKGROUND_DEGAMMA:
547  xml->backgroundDegamma = XMLSupport::parse_bool((*iter).value);
548  break;
549  case NEARSTARS:
550  case STARS:
551  case STARSPREAD:
552  case FADESTARS:
553  break;
554  case NAME:
555  this->name = new char[strlen( (*iter).value.c_str() )+1];
556  strcpy( this->name, (*iter).value.c_str() );
557  break;
558  case X:
559  pos.i = parse_float( (*iter).value );
560  break;
561  case Y:
562  pos.j = parse_float( (*iter).value );
563  break;
564  case Z:
565  pos.k = parse_float( (*iter).value );
566  break;
567  }
568  }
569  break;
570  case RING:
571  {
572  ++xml->unitlevel;
573  string myfile( "planets/ring.png" );
574 
575  blendSrc = SRCALPHA;
576  blendDst = INVSRCALPHA;
577  Unit *p = (Unit*) xml->moons.back()->GetTopPlanet( xml->unitlevel-1 );
578  if (p != NULL) {
579  if (p->isUnit() == PLANETPTR) {
580  int wrapx = 1;
581  int wrapy = 1;
582  int numslices = 8;
583  float iradius = p->rSize()*1.25f;
584  float oradius = p->rSize()*1.75f;
585  R.Set( 1, 0, 0 );
586  S.Set( 0, 1, 0 );
587  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
588  switch ( attribute_map.lookup( (*iter).name ) )
589  {
590  case XFILE:
591  myfile = (*iter).value;
592  break;
593  case ALPHA:
594  parse_dual_alpha( (*iter).value.c_str(), blendSrc, blendDst );
595  break;
596  case INNERRADIUS:
597  iradius = parse_floatf( (*iter).value )*xml->scale;
598  break;
599  case OUTERRADIUS:
600  oradius = parse_floatf( (*iter).value )*xml->scale;
601  break;
602  case NUMSLICES:
603  numslices = parse_int( (*iter).value );
604  break;
605  case WRAPX:
606  wrapx = parse_int( (*iter).value );
607  break;
608  case WRAPY:
609  wrapy = parse_int( (*iter).value );
610  break;
611  case RI:
612  R.i = parse_float( (*iter).value );
613  break;
614  case RJ:
615  R.j = parse_float( (*iter).value );
616  break;
617  case RK:
618  R.k = parse_float( (*iter).value );
619  break;
620  case SI:
621  S.i = parse_float( (*iter).value );
622  break;
623  case SJ:
624  S.j = parse_float( (*iter).value );
625  break;
626  case SK:
627  S.k = parse_float( (*iter).value );
628  break;
629  case VARNAME:
630  varname = (*iter).value;
631  break;
632  case VARVALUE:
633  varvalue = parse_floatf( (*iter).value );
634  break;
635  default:
636  break;
637  }
638  }
639  if ( p != NULL && ConfigAllows( varname, varvalue ) )
640  ( (Planet*) p )->AddRing( myfile, iradius, oradius, R, S, numslices, wrapx, wrapy, blendSrc, blendDst );
641  }
642  }
643  break;
644  }
645 
646  case SPACEELEVATOR:
647  {
648  ++xml->unitlevel;
649  string myfile( "elevator" );
650 
651  blendSrc = SRCALPHA;
652  blendDst = INVSRCALPHA;
653  Unit *p = (Unit*) xml->moons.back()->GetTopPlanet( xml->unitlevel-1 );
654  if (p != NULL) {
655  if (p->isUnit() == PLANETPTR) {
656  string faction( UniverseUtil::GetGalaxyFaction( truncatedfilename ) );
657  char direction = 'b';
658 
659  R.Set( 1, 0, 0 );
660  S.Set( 0, 1, 0 );
661  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
662  switch ( attribute_map.lookup( (*iter).name ) )
663  {
664  case XFILE:
665  myfile = (*iter).value;
666  break;
667  case VARNAME:
668  varname = (*iter).value;
669  break;
670  case VARVALUE:
671  varvalue = parse_floatf( (*iter).value );
672  break;
673 
674  case DIRECTION:
675  if ( !(*iter).value.empty() )
676  direction = (*iter).value[0];
677  break;
678  case FACTION:
679  faction = (*iter).value;
680  if ( faction == UniverseUtil::GetGalaxyProperty( truncatedfilename, "faction" ) ) {
681  string ownerfaction = UniverseUtil::GetGalaxyFaction( truncatedfilename );
682  faction = ownerfaction;
683  }
684  break;
685  default:
686  break;
687  }
688  }
689  if ( p != NULL && ConfigAllows( varname, varvalue ) )
690  ( (Planet*) p )->AddSpaceElevator( myfile, faction, direction );
691  }
692  }
693  break;
694  }
695 
696  case FOG:
697  ++xml->unitlevel;
698  if (!game_options.usePlanetFog)
699  break;
700  xml->fogopticalillusion = true;
701  xml->fog.clear();
702  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
703  switch ( attribute_map.lookup( (*iter).name ) )
704  {
705  case OPTICALILLUSION:
707  break;
708  }
709  }
710  break;
711  case FOGELEMENT:
712  ++xml->unitlevel;
713  if (!game_options.usePlanetFog)
714  break;
715  xml->fog.push_back( AtmosphericFogMesh() );
716  xml->fog.back().scale = 1.1-.075+.075*xml->fog.size();
717  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
718  switch ( attribute_map.lookup( (*iter).name ) )
719  {
720  case EMRED:
721  xml->fog.back().er = XMLSupport::parse_float( iter->value );
722  break;
723  case EMGREEN:
724  xml->fog.back().eg = XMLSupport::parse_float( iter->value );
725  break;
726  case EMBLUE:
727  xml->fog.back().eb = XMLSupport::parse_float( iter->value );
728  break;
729  case EMALPHA:
730  case ALPHA:
731  xml->fog.back().ea = XMLSupport::parse_float( iter->value );
732  break;
733  case DIRED:
734  xml->fog.back().dr = XMLSupport::parse_float( iter->value );
735  break;
736  case DIGREEN:
737  xml->fog.back().dg = XMLSupport::parse_float( iter->value );
738  break;
739  case DIBLUE:
740  xml->fog.back().db = XMLSupport::parse_float( iter->value );
741  break;
742  case DIALPHA:
743  xml->fog.back().da = XMLSupport::parse_float( iter->value );
744  break;
745  case XFILE:
746  xml->fog.back().meshname = iter->value;
747  break;
748  case MINALPHA:
749  xml->fog.back().min_alpha = (int) (XMLSupport::parse_float( iter->value )*255);
750  break;
751  case MAXALPHA:
752  xml->fog.back().max_alpha = (int) (XMLSupport::parse_float( iter->value )*255);
753  break;
754  case CONCAVITY:
755  xml->fog.back().concavity = XMLSupport::parse_float( iter->value );
756  break;
757  case FOCUS:
758  xml->fog.back().focus = XMLSupport::parse_float( iter->value );
759  break;
760  case TAILMODESTART:
761  xml->fog.back().tail_mode_start = (int) ( XMLSupport::parse_float( iter->value ) );
762  break;
763  case TAILMODEEND:
764  xml->fog.back().tail_mode_end = (int) ( XMLSupport::parse_float( iter->value ) );
765  break;
766  case SCALEATMOS:
767  xml->fog.back().scale = XMLSupport::parse_float( iter->value );
768 
769  default:
770  break;
771  }
772  }
773  break;
774  case CITYLIGHTS:
775  {
776  string myfile( "planets/Dirt_light.png" );
777  ++xml->unitlevel;
778  blendSrc = SRCALPHA;
779  blendDst = ONE;
780  int wrapx = 1;
781  bool inside_out = false;
782  int wrapy = 1;
783  Unit *p = (Unit*) xml->moons.back()->GetTopPlanet( xml->unitlevel-1 );
784  if (p != NULL) {
785  if (p->isUnit() == PLANETPTR) {
786  float radius = p->rSize();
787  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
788  switch ( attribute_map.lookup( (*iter).name ) )
789  {
790  case XFILE:
791  myfile = (*iter).value;
792  break;
793  case ALPHA:
794  parse_dual_alpha( (*iter).value.c_str(), blendSrc, blendDst );
795  break;
796  case RADIUS:
797  radius = parse_float( (*iter).value )*xml->scale;
798  break;
799  case WRAPX:
800  wrapx = parse_int( (*iter).value );
801  break;
802  case WRAPY:
803  wrapy = parse_int( (*iter).value );
804  break;
805  case INSIDEOUT:
806  inside_out = parse_bool( (*iter).value );
807  break;
808  case VARNAME:
809  varname = (*iter).value;
810  break;
811  case VARVALUE:
812  varvalue = parse_float( (*iter).value );
813  break;
814 
815  default:
816  break;
817  }
818  }
819  if ( ConfigAllows( varname, varvalue ) )
820  ( (Planet*) p )->AddCity( myfile, radius, wrapx, wrapy, blendSrc, blendDst, inside_out );
821  }
822  }
823  break;
824  }
825  case ATMOSPHERE:
826  {
827  ++xml->unitlevel;
828  if (!game_options.usePlanetAtmosphere)
829  break;
830  string myfile( "sol/earthcloudmaptrans.png" );
831  blendSrc = SRCALPHA;
832  blendDst = INVSRCALPHA;
833  bool inside_out = false;
834  Unit *p = (Unit*) xml->moons.back()->GetTopPlanet( xml->unitlevel-1 );
835  if (p != NULL) {
836  if (p->isUnit() == PLANETPTR) {
837  float radius = p->rSize()*1.075;
838  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
839  switch ( attribute_map.lookup( (*iter).name ) )
840  {
841  case XFILE:
842  myfile = (*iter).value;
843  break;
844  case ALPHA:
845  parse_dual_alpha( (*iter).value.c_str(), blendSrc, blendDst );
846  break;
847  case RADIUS:
848  radius = parse_float( (*iter).value )*xml->scale;
849  break;
850  case VARNAME:
851  varname = (*iter).value;
852  break;
853  case VARVALUE:
854  varvalue = parse_float( (*iter).value );
855  break;
856  case INSIDEOUT:
857  inside_out = parse_bool( (*iter).value );
858  break;
859 
860  default:
861  break;
862  }
863  }
864  if ( ConfigAllows( varname, varvalue ) )
865  ( (Planet*) p )->AddAtmosphere( myfile, radius, blendSrc, blendDst, inside_out );
866  }
867  }
868  break;
869  }
870  case TERRAIN:
871  case CONTTERRAIN:
872  ++xml->unitlevel;
873  S = QVector( 1, 0, 0 );
874  R = QVector( 0, 0, 1 );
875  pos = QVector( 0, 0, 0 );
876  radius = -1;
877  {
878  position = game_options.mass;
879  }
880  gravity = 0;
881  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
882  switch ( attribute_map.lookup( (*iter).name ) )
883  {
884  case NUMWRAPS:
885  numwraps = parse_int( (*iter).value );
886  break;
887  case SCALEX:
888  scalex = parse_float( (*iter).value );
889  break;
890  case SCALEATMOS:
891  scaleatmos = parse_float( (*iter).value );
892  break;
893  case XFILE:
894  myfile = (*iter).value;
895  break;
896  case GRAVITY:
897  gravity = parse_float( (*iter).value );
898  break;
899  case MASS:
900  position = parse_float( (*iter).value );
901  break;
902  case RADIUS:
903  radius = parse_float( (*iter).value );
904  break;
905  case X:
906  pos.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
907  break;
908  case Y:
909  pos.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
910  break;
911  case Z:
912  pos.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
913  break;
914  case RI:
915  R.i = parse_float( (*iter).value );
916  break;
917  case RJ:
918  R.j = parse_float( (*iter).value );
919  break;
920  case RK:
921  R.k = parse_float( (*iter).value );
922  break;
923  case QI:
924  S.i = parse_float( (*iter).value );
925  break;
926  case QJ:
927  S.j = parse_float( (*iter).value );
928  break;
929  case QK:
930  S.k = parse_float( (*iter).value );
931  break;
932  }
933  }
934  {
935  static Vector TerrainScale( game_options.xscale, game_options.yscale, game_options.zscale );
936  Matrix t;
937  Identity( t );
938  float y = S.Magnitude();
939  Normalize( S );
940  float z = R.Magnitude();
941  Normalize( R );
942  TerrainScale.i *= z;
943  TerrainScale.k *= z;
944  TerrainScale.j *= y;
945  t.r[3] = S.i*TerrainScale.j;
946  t.r[4] = S.j*TerrainScale.j;
947  t.r[5] = S.k*TerrainScale.j;
948  t.r[6] = R.i*TerrainScale.k;
949  t.r[7] = R.j*TerrainScale.k;
950  t.r[8] = R.k*TerrainScale.k;
951  S = S.Cross( R );
952  t.r[0] = S.i*TerrainScale.i;
953  t.r[1] = S.j*TerrainScale.i;
954  t.r[2] = S.k*TerrainScale.i;
955  t.p = pos+xml->systemcentroid.Cast();
956  if ( myfile.length() ) {
957  if (elem == TERRAIN) {
958  terrains.push_back( UnitFactory::createTerrain( myfile.c_str(), TerrainScale, position, radius, t ) );
959  xml->parentterrain = terrains.back();
960  } else {
961  contterrains.push_back( UnitFactory::createContinuousTerrain( myfile.c_str(), TerrainScale, position, t ) );
962  xml->ct = contterrains.back();
963  if (xml->unitlevel > 2) {
964  assert( xml->moons.size() != 0 );
965  Planet *p = xml->moons.back()->GetTopPlanet( xml->unitlevel-1 );
966  if (p) {
968  p->setTerrain( xml->ct, scalex, numwraps, scaleatmos );
969  PlanetaryTransform **tmpp = (PlanetaryTransform**) &xml->parentterrain;
970  p->getTerrain( *tmpp );
971  }
972  }
973  }
974  }
975  }
976  break;
977  case LIGHT:
978  assert( xml->unitlevel == 1 );
979  ++xml->unitlevel;
980  xml->lights.push_back( GFXLight( true, Vector( 0, 0, 0 ) ) );
981  break;
982  case ATTEN:
983  tmptarg = ATTENUATE;
984  goto addlightprop;
985  case AMB:
986  tmptarg = AMBIENT;
987  goto addlightprop;
988  case SPEC:
989  tmptarg = SPECULAR;
990  goto addlightprop;
991  case DIFF:
992  tmptarg = DIFFUSE;
993  goto addlightprop;
994 addlightprop:
995  assert( xml->unitlevel == 2 );
996  assert( xml->lights.size() );
997  ++xml->unitlevel;
998  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
999  switch ( attribute_map.lookup( (*iter).name ) )
1000  {
1001  case EMRED:
1002  tmpcol.r = parse_float( (*iter).value );
1003  break;
1004  case EMGREEN:
1005  tmpcol.g = parse_float( (*iter).value );
1006  break;
1007  case EMBLUE:
1008  tmpcol.b = parse_float( (*iter).value );
1009  break;
1010  case EMALPHA:
1011  tmpcol.a = parse_float( (*iter).value );
1012  break;
1013  }
1014  }
1015  xml->lights.back().SetProperties( tmptarg, tmpcol );
1016  break;
1017  case JUMP:
1018  case PLANET:
1019  assert( xml->unitlevel > 0 );
1020  ++xml->unitlevel;
1021  S = QVector( 1, 0, 0 );
1022  R = QVector( 0, 0, 1 );
1023  filename = string( "" );
1024  citylights = string( "" );
1025  technique = string( "" );
1026  blendSrc = ONE;
1027  blendDst = ZERO;
1028  paramOverrides.clear();
1029  serial = 0;
1030  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1031  switch ( attribute_map.lookup( (*iter).name ) )
1032  {
1033  case SERIAL:
1034  serial = parse_int( (*iter).value );
1035  break;
1036  case NAME:
1037  fullname = (*iter).value;
1038  bootstrap_draw( "Loading "+fullname );
1039  break;
1040  case XFILE:
1041  filename = (*iter).value;
1042  break;
1043  case DESTINATION:
1044  dest = ParseDestinations( (*iter).value );
1045  isdest = true;
1046  break;
1047  case TECHNIQUE:
1048  technique = (*iter).value;
1049  break;
1050  case UNIT:
1051  unitname = (*iter).value;
1052  break;
1053  case ALPHA:
1054  parse_dual_alpha( (*iter).value.c_str(), blendSrc, blendDst );
1055  break;
1056  case CITYLIGHTS:
1057  citylights = (*iter).value;
1058  break;
1059 
1060  case INSIDEOUT:
1061  insideout = XMLSupport::parse_bool( (*iter).value );
1062  break;
1063  case LIGHT:
1064  GetLights( xml->lights, curlights, (*iter).value.c_str(), radius );
1065  break;
1066  case FACTION:
1067  {
1068  int originalowner =
1069  FactionUtil::GetFactionIndex( UniverseUtil::GetGalaxyProperty( truncatedfilename, "faction" ) );
1070  faction = FactionUtil::GetFactionIndex( (*iter).value );
1071  if (faction == originalowner) {
1072  int ownerfaction = FactionUtil::GetFactionIndex( UniverseUtil::GetGalaxyFaction( truncatedfilename ) );
1073  faction = ownerfaction;
1074  }
1075  break;
1076  }
1077  case EMRED:
1078  ourmat.er = parse_float( (*iter).value );
1079  break;
1080  case EMGREEN:
1081  ourmat.eg = parse_float( (*iter).value );
1082  break;
1083  case EMBLUE:
1084  ourmat.eb = parse_float( (*iter).value );
1085  break;
1086  case EMALPHA:
1087  ourmat.ea = parse_float( (*iter).value );
1088  break;
1089  case DIRED:
1090  ourmat.dr = parse_float( (*iter).value );
1091  break;
1092  case DIGREEN:
1093  ourmat.dg = parse_float( (*iter).value );
1094  break;
1095  case DIBLUE:
1096  ourmat.db = parse_float( (*iter).value );
1097  break;
1098  case DIALPHA:
1099  ourmat.da = parse_float( (*iter).value );
1100  break;
1101  case SRED:
1102  ourmat.sr = parse_float( (*iter).value );
1103  break;
1104  case SGREEN:
1105  ourmat.sg = parse_float( (*iter).value );
1106  break;
1107  case SBLUE:
1108  ourmat.sb = parse_float( (*iter).value );
1109  break;
1110  case SALPHA:
1111  ourmat.sa = parse_float( (*iter).value );
1112  break;
1113  case SPOWER:
1114  ourmat.power = parse_float( (*iter).value );
1115  break;
1116  case REFLECTNOLIGHT:
1117  ourmat.sr = ourmat.sg = ourmat.sb = ourmat.dr = ourmat.dg = ourmat.db =
1118  ourmat.ar = ourmat.ag = ourmat.ab = 0;
1119  break;
1120  case RI:
1121  R.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1122  break;
1123  case RJ:
1124  R.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1125  break;
1126  case RK:
1127  R.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1128  break;
1129  case SI:
1130  S.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1131  break;
1132  case SJ:
1133  S.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1134  break;
1135  case SK:
1136  S.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1137  break;
1138  case X:
1139  xml->cursun.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1140  break;
1141 
1142  case Y:
1143  xml->cursun.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1144  break;
1145 
1146  case Z:
1147  xml->cursun.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1148  break;
1149 
1150  case RADIUS:
1151  radius = parse_float( (*iter).value );
1152  break;
1153  case PPOSITION:
1154  position = parse_float( (*iter).value );
1155  break;
1156  case DAY:
1157  if (fabs( parse_float( (*iter).value ) ) > .00001)
1158  rotvel = 2.0f*M_PI/( game_options.YearScale*parse_floatf( (*iter).value ) );
1159  break;
1160  case YEAR:
1161  if (fabs( parse_float( (*iter).value ) ) > .00001)
1162  velocity = 2*M_PI/( game_options.YearScale*parse_float( (*iter).value ) );
1163  break;
1164  case GRAVITY:
1165  gravity = parse_float( (*iter).value );
1166  break;
1167 
1168  case OVERRIDE:
1169  {
1170  string::size_type eqpos = (*iter).value.find_first_of('=');
1171  if (eqpos != string::npos) {
1172  string name = (*iter).value.substr(0,eqpos);
1173  string value = (*iter).value.substr(eqpos+1);
1174  paramOverrides[name] = value;
1175  }
1176  }
1177  }
1178  }
1179  if (isdest == true)
1180  if (xml->fade) //xml->fade saves if it's autogenerated system
1181  radius = ScaleJumpRadius( radius );
1182  radius *= xml->scale;
1183  if (xml->unitlevel > 2) {
1184  assert( xml->moons.size() != 0 );
1185  fprintf(stderr, "Creating planet %s with texture %s and technique %s - unitlevel > 2\n", fullname.c_str(), filename.c_str(), technique.c_str());
1186  Unit *un = xml->moons[xml->moons.size()-1]->beginElement( R, S, velocity, ComputeRotVel( rotvel, R, S ),
1187  position, gravity, radius,
1188  filename, technique, unitname, blendSrc, blendDst, dest,
1189  xml->unitlevel-1, ourmat, curlights, false,
1190  faction
1192  UniverseUtil::GetGalaxyFaction( truncatedfilename ) ),
1193  fullname, insideout );
1194  if (un) {
1195  un->SetOwner( getTopLevelOwner() );
1196  un->SetSerial( serial );
1197  un->applyTechniqueOverrides(paramOverrides);
1198  }
1199  } else {
1200  Planet *planet;
1201  fprintf(stderr, "Creating planet %s with texture %s and technique %s - unitlevel <= 2\n", fullname.c_str(), filename.c_str(), technique.c_str());
1202  xml->moons.push_back( ( planet =
1203  UnitFactory::createPlanet( R, S, velocity,
1204  ComputeRotVel( rotvel, R, S ),
1205  position, gravity, radius,
1206  filename, technique, unitname,
1207  blendSrc, blendDst, dest, xml->cursun.Cast()
1208  +xml->systemcentroid.Cast(),
1209  NULL, ourmat, curlights, faction
1211  UniverseUtil::GetGalaxyFaction( truncatedfilename ) ),
1212  fullname,
1213  insideout ) ) );
1214 
1215  xml->moons[xml->moons.size()-1]->SetPosAndCumPos( R+S+xml->cursun.Cast()+xml->systemcentroid.Cast() );
1216  xml->moons.back()->SetOwner( getTopLevelOwner() );
1217  planet->SetSerial( serial );
1218  planet->applyTechniqueOverrides(paramOverrides);
1219 
1220  break;
1221 
1222  }
1223  break;
1224  case CONDITION:
1225  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1226  switch ( attribute_map.lookup( (*iter).name ) )
1227  {
1228  case EXPRESSION:
1229  condition = (*iter).value;
1230  break;
1231  }
1232  }
1233  xml->conditionStack.push_back(
1234  ( !xml->conditionStack.size() || xml->conditionStack.back() )
1235  && ConfigCondition( condition )
1236  );
1237  break;
1238  case UNIT:
1239  case BUILDING:
1240  case VEHICLE:
1241  if (Network && !SERVER) {
1242  ++xml->unitlevel;
1243  break; //don't spawn these clientside
1244  }
1245  case NEBULA:
1246  case ASTEROID:
1247  case ENHANCEMENT:
1248  assert( xml->unitlevel > 0 );
1249  ++xml->unitlevel;
1250  S = QVector( 0, 1, 0 );
1251  R = QVector( 0, 0, 1 );
1252  nebfile = new char[1];
1253  nebfile[0] = '\0';
1254  filename = string( "" );
1255  fullname = "unkn-unit";
1256  scalex = game_options.AsteroidDifficulty;
1257  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1258  switch ( attribute_map.lookup( (*iter).name ) )
1259  {
1260  case SERIAL:
1261  serial = parse_int( (*iter).value );
1262  break;
1263  case NAME:
1264  fullname = (*iter).value;
1265  break;
1266  case XFILE:
1267  filename = (*iter).value;
1268  break;
1269  case NEBFILE:
1270  delete[] nebfile;
1271  nebfile = new char[strlen( (*iter).value.c_str() )+1];
1272  strcpy( nebfile, (*iter).value.c_str() );
1273  break;
1274  case DIFFICULTY:
1275  scalex = -parse_float( (*iter).value );
1276  break;
1277  case DESTINATION:
1278  dest = ParseDestinations( (*iter).value );
1279  break;
1280  case FACTION:
1281  faction = FactionUtil::GetFactionIndex( (*iter).value );
1282  {
1283  int originalowner =
1284  FactionUtil::GetFactionIndex( UniverseUtil::GetGalaxyProperty( truncatedfilename, "faction" ) );
1285  if (faction == originalowner) {
1286  int ownerfaction = FactionUtil::GetFactionIndex( UniverseUtil::GetGalaxyFaction( truncatedfilename ) );
1287  faction = ownerfaction;
1288  }
1289  }
1290  break;
1291  case RI:
1292  R.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1293  break;
1294  case RJ:
1295  R.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1296  break;
1297  case RK:
1298  R.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1299  break;
1300  case SI:
1301  S.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1302  break;
1303  case SJ:
1304  S.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1305  break;
1306  case SK:
1307  S.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1308  break;
1309  case X:
1310  xml->cursun.i = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1311  break;
1312  case Y:
1313  xml->cursun.j = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1314  break;
1315  case Z:
1316  xml->cursun.k = parse_float( (*iter).value )*xml->scale*ScaleOrbitDist( xml->fade );
1317  break;
1318  case PPOSITION:
1319  position = parse_floatf( (*iter).value );
1320  break;
1321  case DAY:
1322  if (fabs( parse_floatf( (*iter).value ) ) > .00001)
1323  rotvel = 2.0f*M_PI/( game_options.YearScale*parse_floatf( (*iter).value ) );
1324  break;
1325  case YEAR:
1326  if (fabs( parse_floatf( (*iter).value ) ) > .00001)
1327  velocity = 2.0f*M_PI/( game_options.YearScale*parse_floatf( (*iter).value ) );
1328  break;
1329  case VARNAME:
1330  varname = (*iter).value;
1331  break;
1332  case VARVALUE:
1333  varvalue = parse_floatf( (*iter).value );
1334  break;
1335  case CONDITION:
1336  condition = (*iter).value;
1337  break;
1338  }
1339  }
1340  if ( ( !xml->conditionStack.size() || xml->conditionStack.back() )
1341  && ConfigAllows( varname, varvalue )
1342  && ConfigCondition( condition ) ) {
1343  if ( ( (elem == UNIT || elem == NEBULA || elem == ENHANCEMENT
1344  || elem == ASTEROID) || (xml->ct == NULL && xml->parentterrain == NULL) ) && (xml->unitlevel > 2) ) {
1345  assert( xml->moons.size() != 0 );
1346  Unit *un = NULL; //FIXME !!! un appears to never be allocated memory !!! "= NULL" added by chuck_starchaser
1347  Planet *plan = xml->moons.back()->GetTopPlanet( xml->unitlevel-1 );
1348  if (elem == UNIT) {
1350  plan->AddSatellite( un = UnitFactory::createUnit( filename.c_str(), false, faction, "", fg, fg->nr_ships-1 ) );
1351  un->SetSerial( serial ); //FIXME un de-referenced before allocation
1352  un->setFullname( fullname ); //FIXME un de-referenced before allocation
1353  } else if (elem == NEBULA) {
1355  plan->AddSatellite( un = UnitFactory::createNebula( filename.c_str(), false, faction, fg, fg->nr_ships-1 ) );
1356  un->SetSerial( serial ); //FIXME un de-referenced before allocation
1357  } else if (elem == ASTEROID) {
1359  plan->AddSatellite( un =
1360  UnitFactory::createAsteroid( filename.c_str(), faction, fg, fg->nr_ships-1, scalex
1361  < 0 ? -scalex : scalex ) );
1362  un->SetSerial( serial ); //FIXME un de-referenced before allocation
1363  } else if (elem == ENHANCEMENT) {
1364  plan->AddSatellite( un = UnitFactory::createEnhancement( filename.c_str(), faction, string( "" ) ) );
1365  un->SetSerial( serial ); //FIXME un de-referenced before allocation
1366  }
1367  {
1368  for (unsigned int i = 0; i < dest.size(); ++i)
1369  un->AddDestination( dest[i] ); //FIXME un de-referenced before allocation
1370  dest.clear();
1371  }
1372  un->SetAI( new PlanetaryOrbit( un, velocity, position, R, S, QVector( 0, 0, 0 ), plan ) );
1373  if (elem == UNIT && un->faction != neutralfaction) {
1374  un->SetTurretAI(); //FIXME un de-referenced before allocation
1375  un->EnqueueAI( new Orders::FireAt( 15 ) ); //FIXME un de-referenced before allocation
1376  }
1377  if (scalex < 0 && elem != ASTEROID)
1378  SetSubunitRotation( un, -scalex ); //FIXME un de-referenced before allocation
1379  //cheating so nothing collides at top lev
1380  un->SetOwner( getTopLevelOwner() ); //FIXME un de-referenced before allocation
1381  un->SetAngularVelocity( ComputeRotVel( rotvel, R, S ) ); //FIXME un de-referenced before allocation
1382  } else {
1383  if ( (elem == BUILDING || elem == VEHICLE) && xml->ct == NULL && xml->parentterrain != NULL ) {
1385  xml->parentterrain, elem == VEHICLE, filename.c_str(), false, faction, string("") );
1386  b->SetSerial( serial );
1387  b->SetPosAndCumPos( xml->cursun.Cast()+xml->systemcentroid.Cast() );
1388  b->EnqueueAI( new Orders::AggressiveAI( "default.agg.xml" ) );
1389  AddUnit( b );
1390  {
1391  for (unsigned int i = 0; i < dest.size(); ++i)
1392  b->AddDestination( dest[i] );
1393  dest.clear();
1394  }
1395  } else if ( (elem == BUILDING || elem == VEHICLE) && xml->ct != NULL ) {
1397  xml->ct, elem == VEHICLE, filename.c_str(), false, faction );
1398  b->SetSerial( serial );
1399  b->SetPosAndCumPos( xml->cursun.Cast()+xml->systemcentroid.Cast() );
1400  b->EnqueueAI( new Orders::AggressiveAI( "default.agg.xml" ) );
1401  b->SetTurretAI();
1402  b->EnqueueAI( new Orders::FireAt( 15 ) );
1403  AddUnit( b );
1404  {
1405  for (unsigned int i = 0; i < dest.size(); ++i)
1406  b->AddDestination( dest[i] );
1407  dest.clear();
1408  }
1409  } else {
1410  if (elem == UNIT) {
1412  Unit *moon_unit = UnitFactory::createUnit( filename.c_str(), false, faction, "", fg, fg->nr_ships-1 );
1413  moon_unit->SetSerial( serial );
1414  moon_unit->setFullname( fullname );
1415  xml->moons.push_back( (Planet*) moon_unit );
1416  } else if (elem == NEBULA) {
1418  xml->moons.push_back( (Planet*) UnitFactory::createNebula( filename.c_str(), false, faction, fg, fg->nr_ships-1 ) );
1419  } else if (elem == ASTEROID) {
1421  Planet *ast;
1422  xml->moons.push_back( ast =
1424  scalex ) );
1425  ast->SetSerial( serial );
1426  } else if (elem == ENHANCEMENT) {
1427  Planet *enh;
1428  xml->moons.push_back( enh = (Planet*) UnitFactory::createEnhancement( filename.c_str(), faction, string( "" ) ) );
1429  enh->SetSerial( serial );
1430  }
1431  {
1432  Unit *un = xml->moons.back();
1433  for (unsigned int i = 0; i < dest.size(); ++i)
1434  un->AddDestination( dest[i] );
1435  dest.clear();
1436  }
1437  xml->moons.back()->SetAI( new PlanetaryOrbit( xml->moons[xml->moons.size()-1], velocity, position, R, S,
1438  xml->cursun.Cast()+xml->systemcentroid.Cast(), NULL ) );
1439 
1440  xml->moons.back()->SetPosAndCumPos( R+S+xml->cursun.Cast()+xml->systemcentroid.Cast() );
1441  xml->moons.back()->SetOwner( getTopLevelOwner() );
1442  if (elem == UNIT && xml->moons.back()->faction != neutralfaction) {
1443  xml->moons.back()->SetTurretAI();
1444  xml->moons.back()->EnqueueAI( new Orders::FireAt( 15 ) );
1445  } else if (scalex < 0 && elem != ASTEROID) {
1446  SetSubunitRotation( xml->moons.back(), -scalex );
1447  }
1448  }
1449  }
1450  }
1451  delete[] nebfile;
1452  break;
1453  default:
1454  break;
1455  }
1456 }
1457 
1458 void StarSystem::endElement( const string &name )
1459 {
1460  using namespace StarXML;
1461  Names elem = (Names) element_map.lookup( name );
1462  switch (elem)
1463  {
1464  case FOG:
1465  {
1466  --xml->unitlevel;
1467  if (!game_options.usePlanetFog)
1468  break;
1469  Unit *p = (Unit*) xml->moons.back()->GetTopPlanet( xml->unitlevel );
1470  if (p != NULL)
1471  if (p->isUnit() == PLANETPTR)
1472  ( (Planet*) p )->AddFog( xml->fog, xml->fogopticalillusion );
1473  break;
1474  }
1475  case UNKNOWN:
1476  --xml->unitlevel;
1477  break;
1478  case CONTTERRAIN:
1479  --xml->unitlevel;
1480  xml->ct = NULL;
1481  break;
1482  case TERRAIN:
1483  xml->parentterrain = NULL;
1484  --xml->unitlevel;
1485  break;
1486  case CONDITION:
1487  if ( xml->conditionStack.size() )
1488  xml->conditionStack.pop_back();
1489  break;
1490  default:
1491  --xml->unitlevel;
1492  break;
1493  }
1494  if (xml->unitlevel == 0) {}
1495 }
1496 
1497 using namespace VSFileSystem;
1498 void StarSystem::LoadXML( const char *filename, const Vector &centroid, const float timeofyear )
1499 {
1500  using namespace StarXML;
1501  bool autogenerated = false;
1502  this->filename = filename;
1503  string file = VSFileSystem::GetCorrectStarSysPath( filename, autogenerated );
1504  if ( file.empty() )
1505  file = filename;
1506  if (game_options.game_speed_affects_autogen_systems)
1507  autogenerated = false;
1508  VSFile f;
1509  VSError err;
1510  //if (file.length()) {
1511  err = f.OpenReadOnly( file, SystemFile );
1512  if (err > Ok) {
1513  printf( "StarSystem: file not found %s\n", file.c_str() );
1514  return;
1515  }
1516  xml = new StarXML;
1517  xml->scale = 1;
1518  xml->fade = autogenerated;
1519  xml->scale *= game_options.star_system_scale;
1520  xml->parentterrain = NULL;
1521  xml->ct = NULL;
1522  xml->systemcentroid = centroid;
1523  xml->timeofyear = timeofyear;
1527  xml->backgroundname = string( "cube" );
1528  xml->backgroundColor = GFXColor(1.0,1.0,1.0,1.0);
1529  xml->backgroundDegamma = false;
1530  xml->reflectivity = game_options.reflectivity;
1531  xml->unitlevel = 0;
1532  XML_Parser parser = XML_ParserCreate( NULL );
1533  XML_SetUserData( parser, this );
1534  XML_SetElementHandler( parser, &StarSystem::beginElement, &StarSystem::endElement );
1535  {
1536  string fcontents = f.ReadFull();
1537  VSFileSystem::vs_dprintf( 2, "Contents of star system:\n%s\n", fcontents.c_str() );
1538  XML_Parse( parser, (fcontents).c_str(), f.Size(), 1 );
1539  }
1540  f.Close();
1541  XML_ParserFree( parser );
1542  unsigned int i;
1543  for (i = 0; i < xml->moons.size(); ++i) {
1544  if (xml->moons[i]->isUnit() == PLANETPTR) {
1545  Unit *un = NULL;
1546  for ( Planet::PlanetIterator iter( (Planet*) xml->moons[i] ); (un = *iter); iter.advance() )
1547  AddUnit( un );
1548  } else {
1549  AddUnit( xml->moons[i] );
1550  }
1551  }
1552  createBackground( xml );
1553  delete xml;
1554 }
1555