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
unit_xml.cpp
Go to the documentation of this file.
1 #include "unit_xml.h"
2 #include "unit_factory.h"
3 #include "audiolib.h"
4 #include "xml_support.h"
5 #include <fstream>
6 #include <expat.h>
7 #include <float.h>
8 #include <limits.h>
9 #include "configxml.h"
10 #include "vs_globals.h"
11 #include "vegastrike.h"
12 #include <assert.h>
13 #include "images.h"
14 #include "xml_serializer.h"
15 #include "vsfilesystem.h"
16 #include "gfx/cockpit_generic.h"
17 #include "unit_collide.h"
18 #include "unit_generic.h"
19 #include "gfx/sphere.h"
20 #include "role_bitmask.h"
21 #include "cmd/collide2/Stdafx.h"
23 
24 #include "networking/netclient.h"
25 #define VS_PI (3.1415926536)
26 
27 /*ADDED FOR extensible use of unit pretty print and unit load */
29 extern float getFuelConversion();
30 
31 string KillQuadZeros( string inp )
32 {
33  std::string::size_type text = 0;
34  while ( ( text = inp.find( ".000000", text ) ) != string::npos )
35  inp = inp.substr( 0, text )+inp.substr( text+7 );
36  return inp;
37 }
38 
39 string MakeUnitXMLPretty( string str, Unit *un )
40 {
41  string writestr;
42  if (un) {
43  writestr += "Name: "+un->name;
44  writestr += " "+un->getFullname();
45  Flightgroup *fg = un->getFlightgroup();
46  if (fg)
47  writestr += " Designation "+fg->name+" "+XMLSupport::tostring( un->getFgSubnumber() );
48  writestr += "\n";
49  }
50  static std::set< string >lookfor;
51  if ( lookfor.empty() ) {
52  lookfor.insert( "Shie" );
53  lookfor.insert( "Armo" );
54 //lookfor.insert ("Hull");
55  lookfor.insert( "Reac" );
56  lookfor.insert( "Moun" );
57  lookfor.insert( "Comp" );
58 //lookfor.insert ("Desc");
59  lookfor.insert( "Engi" );
60  lookfor.insert( "Mane" );
61  lookfor.insert( "Jump" );
62 //lookfor.insert ("Defe");
63  lookfor.insert( "Stat" );
64  lookfor.insert( "Engi" );
65 //lookfor.insert ("Hold");
66  lookfor.insert( "Rada" );
67  }
68  std::string::size_type foundpos;
69  while ( ( foundpos = str.find( "<" ) ) != string::npos ) {
70  if (str.size() <= foundpos+1)
71  break;
72  str = str.substr( foundpos+1 );
73  if (str.size() > 3) {
74  char mycomp[5] = {str[0], str[1], str[2], str[3], 0};
75  if ( lookfor.find( mycomp ) != lookfor.end() ) {
76  int newline = str.find( ">" );
77  if (newline > 0)
78  if (str[newline-1] == '/')
79  newline -= 1;
80  writestr += KillQuadZeros( str.substr( 0, newline )+"\n" );
81  }
82  }
83  }
84  return writestr;
85 }
86 
87 int GetModeFromName( const char *input_buffer )
88 {
89  if (strlen( input_buffer ) > 3) {
90  if (input_buffer[0] == 'a'
91  && input_buffer[1] == 'd'
92  && input_buffer[2] == 'd')
93  return 1;
94  if (input_buffer[0] == 'm'
95  && input_buffer[1] == 'u'
96  && input_buffer[2] == 'l')
97  return 2;
98  }
99  return 0;
100 }
101 
102 extern bool CheckAccessory( Unit* );
103 
104 void Unit::beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
105 {
106  ( (Unit*) userData )->beginElement( name, AttributeList( atts ) );
107 }
108 
109 void Unit::endElement( void *userData, const XML_Char *name )
110 {
111  ( (Unit*) userData )->endElement( name );
112 }
113 
114 namespace UnitXML
115 {
116 enum Names
117 {
128  X,
129  Y,
130  Z,
131  RI,
132  RJ,
133  RK,
134  QI,
135  QJ,
136  QK,
267 };
268 
270  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
271  EnumMap::Pair( "Unit", UNIT ),
272  EnumMap::Pair( "SubUnit", SUBUNIT ),
273  EnumMap::Pair( "Sound", SOUND ),
274  EnumMap::Pair( "MeshFile", MESHFILE ),
275  EnumMap::Pair( "ShieldMesh", SHIELDMESH ),
276  EnumMap::Pair( "RapidMesh", RAPIDMESH ),
277  EnumMap::Pair( "Light", MESHLIGHT ),
278  EnumMap::Pair( "Defense", DEFENSE ),
279  EnumMap::Pair( "Armor", ARMOR ),
280  EnumMap::Pair( "Shields", SHIELDS ),
281  EnumMap::Pair( "Hull", HULL ),
282  EnumMap::Pair( "Stats", STATS ),
283  EnumMap::Pair( "Thrust", THRUST ),
284  EnumMap::Pair( "Maneuver", MANEUVER ),
285  EnumMap::Pair( "Engine", ENGINE ),
286  EnumMap::Pair( "Computer", COMPUTER ),
287  EnumMap::Pair( "Cloak", CLOAK ),
288  EnumMap::Pair( "Energy", ENERGY ),
289  EnumMap::Pair( "Reactor", REACTOR ),
290  EnumMap::Pair( "Restricted", RESTRICTED ),
291  EnumMap::Pair( "Yaw", YAW ),
292  EnumMap::Pair( "Pitch", PITCH ),
293  EnumMap::Pair( "Roll", ROLL ),
294  EnumMap::Pair( "Mount", MOUNT ),
295  EnumMap::Pair( "Radar", RADAR ),
296  EnumMap::Pair( "Cockpit", COCKPIT ),
297  EnumMap::Pair( "Jump", JUMP ),
298  EnumMap::Pair( "Netcomm", NETCOM ),
299  EnumMap::Pair( "Dock", DOCK ),
300  EnumMap::Pair( "Hold", HOLD ),
301  EnumMap::Pair( "Cargo", CARGO ),
302  EnumMap::Pair( "Category", CATEGORY ),
303  EnumMap::Pair( "Import", IMPORT ),
304  EnumMap::Pair( "CockpitDamage", COCKPITDAMAGE ),
305  EnumMap::Pair( "Upgrade", UPGRADE ),
306  EnumMap::Pair( "Description", DESCRIPTION ),
307 };
308 
310  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
311  EnumMap::Pair( "missing", MISSING ),
312  EnumMap::Pair( "file", XFILE ),
313  EnumMap::Pair( "x", X ),
314  EnumMap::Pair( "y", Y ),
315  EnumMap::Pair( "z", Z ),
316  EnumMap::Pair( "xyscale", XYSCALE ),
317  EnumMap::Pair( "zscale", ZSCALE ),
318  EnumMap::Pair( "ri", RI ),
319  EnumMap::Pair( "rj", RJ ),
320  EnumMap::Pair( "rk", RK ),
321  EnumMap::Pair( "qi", QI ),
322  EnumMap::Pair( "qj", QJ ),
323  EnumMap::Pair( "qk", QK ),
324  EnumMap::Pair( "activationSpeed", ACTIVATIONSPEED ),
325  EnumMap::Pair( "red", RED ),
326  EnumMap::Pair( "green", GREEN ),
327  EnumMap::Pair( "blue", BLUE ),
328  EnumMap::Pair( "alpha", ALPHA ),
329  EnumMap::Pair( "size", MOUNTSIZE ),
330  EnumMap::Pair( "forward", FORWARD ),
331  EnumMap::Pair( "retro", RETRO ),
332  EnumMap::Pair( "frontrighttop", FRONTRIGHTTOP ),
333  EnumMap::Pair( "backrighttop", BACKRIGHTTOP ),
334  EnumMap::Pair( "frontlefttop", FRONTLEFTTOP ),
335  EnumMap::Pair( "backlefttop", BACKLEFTTOP ),
336  EnumMap::Pair( "frontrightbottom", FRONTRIGHTBOTTOM ),
337  EnumMap::Pair( "backrightbottom", BACKRIGHTBOTTOM ),
338  EnumMap::Pair( "frontleftbottom", FRONTLEFTBOTTOM ),
339  EnumMap::Pair( "backleftbottom", BACKLEFTBOTTOM ),
340  EnumMap::Pair( "front", FRONT ),
341  EnumMap::Pair( "back", BACK ),
342  EnumMap::Pair( "left", LEFT ),
343  EnumMap::Pair( "right", RIGHT ),
344  EnumMap::Pair( "top", TOP ),
345  EnumMap::Pair( "bottom", BOTTOM ),
346  EnumMap::Pair( "recharge", RECHARGE ),
347  EnumMap::Pair( "warpenergy", WARPENERGY ),
348  EnumMap::Pair( "insysenergy", INSYSENERGY ),
349  EnumMap::Pair( "leak", LEAK ),
350  EnumMap::Pair( "strength", STRENGTH ),
351  EnumMap::Pair( "mass", MASS ),
352  EnumMap::Pair( "momentofinertia", MOMENTOFINERTIA ),
353  EnumMap::Pair( "fuel", FUEL ),
354  EnumMap::Pair( "yaw", YAW ),
355  EnumMap::Pair( "pitch", PITCH ),
356  EnumMap::Pair( "roll", ROLL ),
357  EnumMap::Pair( "accel", AACCEL ),
358  EnumMap::Pair( "limit", LIMIT ),
359  EnumMap::Pair( "max", MAX ),
360  EnumMap::Pair( "min", MIN ),
361  EnumMap::Pair( "weapon", WEAPON ),
362  EnumMap::Pair( "maxspeed", MAXSPEED ),
363  EnumMap::Pair( "afterburner", AFTERBURNER ),
364  EnumMap::Pair( "tightness", SHIELDTIGHT ),
365  EnumMap::Pair( "itts", ITTS ),
366  EnumMap::Pair( "ammo", AMMO ),
367  EnumMap::Pair( "HudImage", HUDIMAGE ),
368  EnumMap::Pair( "ExplosionAni", EXPLOSIONANI ),
369  EnumMap::Pair( "MaxCone", MAXCONE ),
370  EnumMap::Pair( "TrackingCone", TRACKINGCONE ),
371  EnumMap::Pair( "LockCone", LOCKCONE ),
372  EnumMap::Pair( "MinTargetSize", MINTARGETSIZE ),
373  EnumMap::Pair( "Range", RANGE ),
374  EnumMap::Pair( "EngineMp3", ENGINEMP3 ),
375  EnumMap::Pair( "EngineWav", ENGINEWAV ),
376  EnumMap::Pair( "HullMp3", HULLMP3 ),
377  EnumMap::Pair( "HullWav", HULLWAV ),
378  EnumMap::Pair( "ArmorMp3", ARMORMP3 ),
379  EnumMap::Pair( "ArmorWav", ARMORWAV ),
380  EnumMap::Pair( "ShieldMp3", SHIELDMP3 ),
381  EnumMap::Pair( "ShieldWav", SHIELDWAV ),
382  EnumMap::Pair( "ExplodeMp3", EXPLODEMP3 ),
383  EnumMap::Pair( "ExplodeWav", EXPLODEWAV ),
384  EnumMap::Pair( "CloakRate", CLOAKRATE ),
385  EnumMap::Pair( "CloakGlass", CLOAKGLASS ),
386  EnumMap::Pair( "CloakEnergy", CLOAKENERGY ),
387  EnumMap::Pair( "CloakMin", CLOAKMIN ),
388  EnumMap::Pair( "CloakMp3", CLOAKMP3 ),
389  EnumMap::Pair( "CloakWav", CLOAKWAV ),
390  EnumMap::Pair( "Color", ISCOLOR ),
391  EnumMap::Pair( "Restricted", RESTRICTED ),
392  EnumMap::Pair( "Delay", DELAY ),
393  EnumMap::Pair( "AfterburnEnergy", AFTERBURNENERGY ),
394  EnumMap::Pair( "JumpEnergy", JUMPENERGY ),
395  EnumMap::Pair( "JumpWav", JUMPWAV ),
396  EnumMap::Pair( "min_freq", NETCOMM_MINFREQ ),
397  EnumMap::Pair( "max_freq", NETCOMM_MAXFREQ ),
398  EnumMap::Pair( "secured", NETCOMM_SECURED ),
399  EnumMap::Pair( "video", NETCOMM_VIDEO ),
400  EnumMap::Pair( "crypto_method", NETCOMM_CRYPTO ),
401  EnumMap::Pair( "DockInternal", DOCKINTERNAL ),
402  EnumMap::Pair( "RAPID", RAPID ),
403  EnumMap::Pair( "Wormhole", WORMHOLE ),
404  EnumMap::Pair( "Scale", UNITSCALE ),
405  EnumMap::Pair( "Price", PRICE ),
406  EnumMap::Pair( "Volume", VOLUME ),
407  EnumMap::Pair( "Quantity", QUANTITY ),
408  EnumMap::Pair( "PriceStdDev", PRICESTDDEV ),
409  EnumMap::Pair( "PriceStDev", PRICESTDDEV ),
410  EnumMap::Pair( "QuantityStdDev", QUANTITYSTDDEV ),
411  EnumMap::Pair( "Damage", DAMAGE ),
412  EnumMap::Pair( "RepairDroid", REPAIRDROID ),
413  EnumMap::Pair( "ECM", ECM ),
414  EnumMap::Pair( "Description", DESCRIPTION ),
415  EnumMap::Pair( "MountOffset", MOUNTOFFSET ),
416  EnumMap::Pair( "SubunitOffset", SUBUNITOFFSET ),
417  EnumMap::Pair( "SlideEnd", SLIDE_START ),
418  EnumMap::Pair( "SlideStart", SLIDE_END ),
419  EnumMap::Pair( "MissionCargo", MISSIONCARGO ),
420  EnumMap::Pair( "Maximum", MAXIMUM ),
421  EnumMap::Pair( "LightType", LIGHTTYPE ),
422  EnumMap::Pair( "CombatRole", COMBATROLE ),
423  EnumMap::Pair( "RecurseSubunitCollision", RECURSESUBUNITCOLLISION ),
424  EnumMap::Pair( "FaceCamera", FACECAMERA ),
425  EnumMap::Pair( "NumAnimationStages", NUMANIMATIONSTAGES ),
426  EnumMap::Pair( "StartFrame", STARTFRAME ),
427  EnumMap::Pair( "TextureStartTime", TEXTURESTARTTIME ),
428  EnumMap::Pair( "WarpDriveRating", WARPDRIVERATING )
429 };
430 
431 const EnumMap element_map( element_names, 37 );
433 } //end of namespace
434 
435 std::string delayucharStarHandler( const XMLType &input, void *mythis )
436 {
437  static int jumpdelaymult = XMLSupport::parse_int( vs_config->getVariable( "physics", "jump_delay_multiplier", "5" ) );
438  unsigned char uc = (*input.w.uc)/jumpdelaymult;
439  if (uc < 1)
440  uc = 1;
441  return XMLSupport::tostring( (int) uc );
442 }
443 
444 //USED TO BE IN UNIT_FUNCTIONS*.CPP BUT NOW ON BOTH CLIENT AND SERVER SIDE
445 std::vector< Mesh* >MakeMesh( unsigned int mysize )
446 {
447  std::vector< Mesh* >temp;
448  for (unsigned int i = 0; i < mysize; i++)
449  temp.push_back( NULL );
450  return temp;
451 }
452 
453 void addShieldMesh( Unit::XML *xml, const char *filename, const float scale, int faction, class Flightgroup *fg )
454 {
455  static bool forceit = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "forceOneOneShieldBlend", "true" ) );
456  xml->shieldmesh = Mesh::LoadMesh( filename, Vector( scale, scale, scale ), faction, fg );
457  if (xml->shieldmesh && forceit) {
458  xml->shieldmesh->SetBlendMode( ONE, ONE, true );
459  xml->shieldmesh->setEnvMap( false, true );
460  xml->shieldmesh->setLighting( true, true );
461  }
462 }
463 
464 void addRapidMesh( Unit::XML *xml, const char *filename, const float scale, int faction, class Flightgroup *fg )
465 {
466  xml->rapidmesh = Mesh::LoadMesh( filename, Vector( scale, scale, scale ), faction, fg );
467 }
468 
469 void pushMesh( std::vector< Mesh* > &meshes,
470  float &randomstartframe,
471  float &randomstartseconds,
472  const char *filename,
473  const float scale,
474  int faction,
475  class Flightgroup *fg,
476  int startframe,
477  double texturestarttime )
478 {
479  vector< Mesh* >m = Mesh::LoadMeshes( filename, Vector( scale, scale, scale ), faction, fg );
480  for (unsigned int i = 0; i < m.size(); ++i) {
481  meshes.push_back( m[i] );
482  if (startframe >= 0) {
483  meshes.back()->setCurrentFrame( startframe );
484  } else if (startframe == -2) {
485  float r = ( (float) rand() )/RAND_MAX;
486  meshes.back()->setCurrentFrame( r*meshes.back()->getFramesPerSecond() );
487  } else if (startframe == -1) {
488  if (randomstartseconds == 0)
489  randomstartseconds = randomstartframe*meshes.back()->getNumLOD()/meshes.back()->getFramesPerSecond();
490  meshes.back()->setCurrentFrame( randomstartseconds*meshes.back()->getFramesPerSecond() );
491  }
492  if (texturestarttime > 0) {
493  meshes.back()->setTextureCumulativeTime( texturestarttime );
494  } else {
495  float fps = meshes.back()->getTextureFramesPerSecond();
496  int frames = meshes.back()->getNumTextureFrames();
497  double ran = randomstartframe;
498  if (fps > 0 && frames > 1) {
499  ran *= frames/fps;
500  } else {
501  ran *= 1000;
502  }
503  meshes.back()->setTextureCumulativeTime( ran );
504  }
505  }
506 }
507 
508 Mount * createMount( const std::string &name, int ammo, int volume, float xyscale, float zscale, bool banked ) //short fix
509 {
510  return new Mount( name.c_str(), ammo, volume, xyscale, zscale, 1, 1, banked );
511 }
512 
513 using XMLSupport::EnumMap;
516 
517 extern int GetModeFromName( const char* );
518 
519 extern int parseMountSizes( const char *str );
520 
521 static unsigned int CLAMP_UINT( float x )
522 {
523  return (unsigned int) ( ( (x) > 4294967295.0 ) ? (unsigned int) 4294967295U : ( (x) < 0 ? 0 : (x) ) );
524 } //short fix
525 
526 #define ADDTAGNAME( a ) do {pImage->unitwriter->AddTag( a );} \
527  while (0)
528 #define ADDTAG do {pImage->unitwriter->AddTag( name );} \
529  while (0)
530 #define ADDELEMNAME( a, b, c ) do {pImage->unitwriter->AddElement( a, b, c );} \
531  while (0)
532 #define ADDELEM( b, c ) do {pImage->unitwriter->AddElement( (*iter).name, b, c );} \
533  while (0)
534 #define ADDDEFAULT do {pImage->unitwriter->AddElement( (*iter).name, stringHandler, XMLType( (*iter).value ) );} \
535  while (0)
536 #define ADDELEMI( b ) do {ADDELEM( intStarHandler, XMLType( &b ) );} \
537  while (0)
538 #define ADDELEMF( b ) do {ADDELEM( floatStarHandler, XMLType( &b ) );} \
539  while (0)
540 
541 void Unit::beginElement( const string &name, const AttributeList &attributes )
542 {
543  using namespace UnitXML;
544  static float game_speed = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_speed", "1" ) );
545  static float game_accel = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_accel", "1" ) );
546  Cargo carg;
547  float act_speed = 0;
548  int volume = -1; //short fix
549  string filename;
550  QVector P;
551  int indx;
552  QVector Q;
553  QVector R;
554  QVector pos;
555  float xyscale = -1;
556  float zscale = -1;
557  bool tempbool;
558  unsigned int dirfrac = 0;
559  float fbrltb[6] = {-1};
560  AttributeList::const_iterator iter;
561  float halocolor[4];
562  int ammo = -1; //short fix
563  int mntsiz = weapon_info::NOWEAP;
564  string light_type;
565  Names elem = (Names) element_map.lookup( name );
566  switch (elem)
567  {
568  case SHIELDMESH:
569  ADDTAG;
570  assert( xml->unitlevel == 1 );
571  xml->unitlevel++;
572  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
573  switch ( attribute_map.lookup( (*iter).name ) )
574  {
575  case XFILE:
576  ADDELEM( stringHandler, (*iter).value );
577  addShieldMesh( xml, (*iter).value.c_str(), xml->unitscale, faction, flightgroup );
578  break;
579  case SHIELDTIGHT:
580  ADDDEFAULT;
581  shieldtight = parse_float( (*iter).value );
582  break;
583  }
584  }
585  break;
586  case RAPIDMESH:
587  ADDTAG;
588  assert( xml->unitlevel == 1 );
589  xml->unitlevel++;
590  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
591  switch ( attribute_map.lookup( (*iter).name ) )
592  {
593  case XFILE:
594  ADDDEFAULT;
595  addRapidMesh( xml, (*iter).value.c_str(), xml->unitscale, faction, NULL );
596  xml->hasColTree = true;
597  break;
598  case RAPID:
599  ADDDEFAULT;
600  xml->hasColTree = parse_bool( (*iter).value );
601  break;
602  }
603  }
604  break;
605  case HOLD:
606  ADDTAG;
607  assert( xml->unitlevel == 1 );
608  xml->unitlevel++;
609  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
610  switch ( attribute_map.lookup( (*iter).name ) )
611  {
612  case VOLUME:
615  pImage->UpgradeVolume = pImage->CargoVolume = parse_float( (*iter).value );
616  break;
617  }
618  }
619  pImage->unitwriter->AddTag( "Category" );
620  pImage->unitwriter->AddElement( "file", Unit::cargoSerializer, XMLType( (int) 0 ) );
621  pImage->unitwriter->EndTag( "Category" );
622  break;
623  case IMPORT:
624  Q.i = Q.k = 0;
625  xml->unitlevel++;
626  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
627  switch ( attribute_map.lookup( (*iter).name ) )
628  {
629  case QUANTITY:
630  carg.quantity = parse_int( (*iter).value );
631  //import cargo from ze maztah liztz
632  break;
633  case PRICE:
634  carg.price = parse_float( (*iter).value );
635  break;
636  case PRICESTDDEV:
637  Q.i = parse_float( (*iter).value );
638  break;
639  case QUANTITYSTDDEV:
640  Q.k = parse_float( (*iter).value );
641  break;
642  }
643  }
644  ImportPartList( xml->cargo_category, carg.price, Q.i, carg.quantity, Q.k );
645  break;
646  case CATEGORY:
647  //this is autogenerated by the handler
648  xml->unitlevel++;
649  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
650  switch ( attribute_map.lookup( (*iter).name ) )
651  {
652  case XFILE:
653  xml->cargo_category = XMLSupport::replace_space( (*iter).value );
654  break;
655  }
656  }
657  break;
658  case CARGO:
660  assert( xml->unitlevel >= 2 );
661  xml->unitlevel++;
662  carg.category = xml->cargo_category;
663  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
664  switch ( attribute_map.lookup( (*iter).name ) )
665  {
666  case QUANTITY:
667  carg.quantity = parse_int( (*iter).value );
668  break;
669  case MASS:
670  carg.mass = parse_float( (*iter).value );
671  break;
672  case VOLUME:
673  carg.volume = parse_float( (*iter).value );
674  break;
675  case PRICE:
676  carg.price = parse_float( (*iter).value );
677  break;
678  case MISSIONCARGO:
679  carg.mission = parse_bool( (*iter).value );
680  break;
681  case XFILE:
682  carg.content = XMLSupport::replace_space( (*iter).value );
683  break;
684  case DESCRIPTION:
685  carg.description = strdup( (*iter).value.c_str() ); //mem leak...but hey--only for mpl
686  break;
687  }
688  }
689  if (carg.mass != 0)
690  AddCargo( carg, false );
691  break;
692  case MESHFILE:
693  {
694  std::string file = "box.bfxm";
695  int startframe = 0;
696  double texturestarttime = 0;
697  ADDTAG;
698  assert( xml->unitlevel == 1 );
699  xml->unitlevel++;
700  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
701  switch ( attribute_map.lookup( (*iter).name ) )
702  {
703  case XFILE:
704  ADDDEFAULT;
705  file = (*iter).value;
706  break;
707  case STARTFRAME:
708  if (strtoupper( (*iter).value ) == "RANDOM")
709  startframe = -1;
710  else if (strtoupper( (*iter).value ) == "ASYNC")
711  startframe = -2;
712  else
713  startframe = parse_int( (*iter).value );
714  break;
715  case TEXTURESTARTTIME:
716  if (strtoupper( (*iter).value ) == "RANDOM")
717  texturestarttime = -1;
718  else
719  texturestarttime = parse_float( (*iter).value );
720  }
721  }
722  switch (current_unit_load_mode)
723  {
724  case NO_MESH:
725  break;
726  default:
728  file.c_str(), xml->unitscale, faction, flightgroup, startframe, texturestarttime );
729  }
730  break;
731  }
732  case UPGRADE:
733  {
734  assert( xml->unitlevel >= 1 );
735  xml->unitlevel++;
736 
737  double percent;
738  int moffset = 0;
739  int soffset = 0;
740  //don't serialize
741  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
742  switch ( attribute_map.lookup( (*iter).name ) )
743  {
744  case XFILE:
745  filename = (*iter).value.c_str();
746  break;
747  case SUBUNITOFFSET:
748  soffset = parse_int( (*iter).value );
749  break;
750  case MOUNTOFFSET:
751  moffset = parse_int( (*iter).value );
752  break;
753  }
754  }
755  int upgrfac = FactionUtil::GetUpgradeFaction();
756  Unit *upgradee = UnitFactory::createUnit( filename.c_str(), true, upgrfac );
757  Unit::Upgrade( upgradee, moffset, soffset, GetModeFromName( filename.c_str() ), true, percent, NULL );
758  upgradee->Kill();
759  break;
760  }
761  case DOCK:
762  {
763  ADDTAG;
765  assert( xml->unitlevel == 1 );
766  xml->unitlevel++;
767  pos = QVector( 0, 0, 0 );
768  P = QVector( 1, 1, 1 );
769  Q = QVector( FLT_MAX, FLT_MAX, FLT_MAX );
770  R = QVector( FLT_MAX, FLT_MAX, FLT_MAX );
771  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
772  switch ( attribute_map.lookup( (*iter).name ) )
773  {
774  case DOCKINTERNAL:
775  ADDDEFAULT;
776  dockType = DockingPorts::Type::Value(parse_int((*iter).value));
777  break;
778  case X:
779  ADDDEFAULT;
780  pos.i = xml->unitscale*parse_float( (*iter).value );
781  break;
782  case Y:
783  ADDDEFAULT;
784  pos.j = xml->unitscale*parse_float( (*iter).value );
785  break;
786  case Z:
787  ADDDEFAULT;
788  pos.k = xml->unitscale*parse_float( (*iter).value );
789  break;
790  case TOP:
791  ADDDEFAULT;
792  R.j = xml->unitscale*parse_float( (*iter).value );
793  break;
794  case BOTTOM:
795  ADDDEFAULT;
796  Q.j = xml->unitscale*parse_float( (*iter).value );
797  break;
798  case LEFT:
799  ADDDEFAULT;
800  Q.i = xml->unitscale*parse_float( (*iter).value );
801  break;
802  case RIGHT:
803  ADDDEFAULT;
804  R.i = parse_float( (*iter).value );
805  break;
806  case BACK:
807  ADDDEFAULT;
808  Q.k = xml->unitscale*parse_float( (*iter).value );
809  break;
810  case FRONT:
811  ADDDEFAULT;
812  R.k = xml->unitscale*parse_float( (*iter).value );
813  break;
814  case MOUNTSIZE:
815  ADDDEFAULT;
816  P.i = xml->unitscale*parse_float( (*iter).value );
817  P.j = xml->unitscale*parse_float( (*iter).value );
818  break;
819  }
820  }
821  if (Q.i == FLT_MAX || Q.j == FLT_MAX || Q.k == FLT_MAX || R.i == FLT_MAX || R.j == FLT_MAX || R.k == FLT_MAX) {
822  pImage->dockingports.push_back( DockingPorts( pos.Cast(), P.i, 0, dockType ) );
823  } else {
824  QVector tQ = Q.Min( R );
825  QVector tR = R.Max( Q );
826  pImage->dockingports.push_back( DockingPorts( tQ.Cast(), tR.Cast(), 0, dockType ) );
827  }
828  }
829  break;
830  case MESHLIGHT:
831  ADDTAG;
832  vs_config->gethColor( "unit", "engine", halocolor, 0xffffffff );
833  assert( xml->unitlevel == 1 );
834  xml->unitlevel++;
835  P = QVector( 1, 1, 1 );
836  Q = QVector( 1, 1, 1 );
837  pos = QVector( 0, 0, 0 );
838  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
839  switch ( attribute_map.lookup( (*iter).name ) )
840  {
841  case LIGHTTYPE:
842  ADDDEFAULT;
843  light_type = (*iter).value;
844  break;
845  case X:
846  ADDDEFAULT;
847  pos.i = xml->unitscale*parse_float( (*iter).value );
848  break;
849  case Y:
850  ADDDEFAULT;
851  pos.j = xml->unitscale*parse_float( (*iter).value );
852  break;
853  case Z:
854  ADDDEFAULT;
855  pos.k = xml->unitscale*parse_float( (*iter).value );
856  break;
857  case RED:
858  ADDDEFAULT;
859  halocolor[0] = parse_float( (*iter).value );
860  break;
861  case GREEN:
862  ADDDEFAULT;
863  halocolor[1] = parse_float( (*iter).value );
864  break;
865  case BLUE:
866  ADDDEFAULT;
867  halocolor[2] = parse_float( (*iter).value );
868  break;
869  case ALPHA:
870  ADDDEFAULT;
871  halocolor[3] = parse_float( (*iter).value );
872  break;
873  case XFILE:
874  ADDDEFAULT;
875  filename = (*iter).value;
876  break;
877  case ACTIVATIONSPEED:
878  act_speed = parse_float( (*iter).value );
879  break;
880  case MOUNTSIZE:
881  ADDDEFAULT;
882  P.i = xml->unitscale*parse_float( (*iter).value );
883  P.j = xml->unitscale*parse_float( (*iter).value );
884  P.k = xml->unitscale*parse_float( (*iter).value );
885  break;
886  }
887  }
888  addHalo( filename.c_str(), pos, P.Cast(), GFXColor( halocolor[0],
889  halocolor[1],
890  halocolor[2],
891  halocolor[3] ), light_type, act_speed );
892  break;
893  case MOUNT:
894  ADDTAG;
895  assert( xml->unitlevel == 1 );
896  xml->unitlevel++;
897  Q = QVector( 0, 1, 0 );
898  R = QVector( 0, 0, 1 );
899  pos = QVector( 0, 0, 0 );
900  tempbool = false;
902  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
903  switch ( attribute_map.lookup( (*iter).name ) )
904  {
905  case VOLUME:
906  volume = XMLSupport::parse_int( (*iter).value );
907  break;
908  case XYSCALE:
909  xyscale = XMLSupport::parse_float( (*iter).value );
910  break;
911  case ZSCALE:
912  zscale = XMLSupport::parse_float( (*iter).value );
913  break;
914  case WEAPON:
915  filename = (*iter).value;
916  break;
917  case AMMO:
918  ammo = XMLSupport::parse_int( (*iter).value );
919  break;
920  case MOUNTSIZE:
921  tempbool = true;
922  mntsiz = parseMountSizes( (*iter).value.c_str() );
923  break;
924  case X:
925  pos.i = xml->unitscale*parse_float( (*iter).value );
926  break;
927  case Y:
928  pos.j = xml->unitscale*parse_float( (*iter).value );
929  break;
930  case Z:
931  pos.k = xml->unitscale*parse_float( (*iter).value );
932  break;
933  case RI:
934  R.i = parse_float( (*iter).value );
935  break;
936  case RJ:
937  R.j = parse_float( (*iter).value );
938  break;
939  case RK:
940  R.k = parse_float( (*iter).value );
941  break;
942  case QI:
943  Q.i = parse_float( (*iter).value );
944  break;
945  case QJ:
946  Q.j = parse_float( (*iter).value );
947  break;
948  case QK:
949  Q.k = parse_float( (*iter).value );
950  break;
951  }
952  }
953  Q.Normalize();
954  if ( fabs( Q.i ) == fabs( R.i ) && fabs( Q.j ) == fabs( R.j ) && fabs( Q.k ) == fabs( R.k ) ) {
955  Q.i = -1;
956  Q.j = 0;
957  Q.k = 0;
958  }
959  R.Normalize();
960  CrossProduct( Q, R, P );
961  CrossProduct( R, P, Q );
962  Q.Normalize();
963  //Transformation(Quaternion (from_vectors (P,Q,R),pos);
964  indx = xml->mountz.size();
965  xml->mountz.push_back( createMount( filename.c_str(), ammo, volume, xyscale, zscale, false /*no way to do banked in XML*/ ) );
966  xml->mountz[indx]->SetMountOrientation( Quaternion::from_vectors( P.Cast(), Q.Cast(), R.Cast() ) );
967  xml->mountz[indx]->SetMountPosition( pos.Cast() );
968  if (tempbool)
969  xml->mountz[indx]->size = mntsiz;
970  else
971  xml->mountz[indx]->size = xml->mountz[indx]->type->size;
973  break;
974  case SUBUNIT:
975  ADDTAG;
976  assert( xml->unitlevel == 1 );
977  ADDELEMNAME( "file", Unit::subunitSerializer, XMLType( (int) xml->units.size() ) );
978  xml->unitlevel++;
979  Q = QVector( 0, 1, 0 );
980  R = QVector( 0, 0, 1 );
981  pos = QVector( 0, 0, 0 );
982  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
983  switch ( attribute_map.lookup( (*iter).name ) )
984  {
985  case XFILE:
986  filename = (*iter).value;
987  break;
988  case X:
989  ADDDEFAULT;
990  pos.i = xml->unitscale*parse_float( (*iter).value );
991  break;
992  case Y:
993  ADDDEFAULT;
994  pos.j = xml->unitscale*parse_float( (*iter).value );
995  break;
996  case Z:
997  ADDDEFAULT;
998  pos.k = xml->unitscale*parse_float( (*iter).value );
999  break;
1000  case RI:
1001  ADDDEFAULT;
1002  R.i = parse_float( (*iter).value );
1003  break;
1004  case RJ:
1005  ADDDEFAULT;
1006  R.j = parse_float( (*iter).value );
1007  break;
1008  case RK:
1009  ADDDEFAULT;
1010  R.k = parse_float( (*iter).value );
1011  break;
1012  case QI:
1013  ADDDEFAULT;
1014  Q.i = parse_float( (*iter).value );
1015  break;
1016  case QJ:
1017  ADDDEFAULT;
1018  Q.j = parse_float( (*iter).value );
1019  break;
1020  case QK:
1021  ADDDEFAULT;
1022  Q.k = parse_float( (*iter).value );
1023  break;
1024  case RESTRICTED:
1025  ADDDEFAULT;
1026  fbrltb[0] = parse_float( (*iter).value ); //minimum dot turret can have with "fore" vector
1027  break;
1028  }
1029  }
1030  indx = xml->units.size();
1031  xml->units.push_back( UnitFactory::createUnit( filename.c_str(), true, faction, xml->unitModifications, NULL ) ); //I set here the fg arg to NULL
1032  if (xml->units.back()->name == "LOAD_FAILED") {
1033  xml->units.back()->limits.yaw = 0;
1034  xml->units.back()->limits.pitch = 0;
1035  xml->units.back()->limits.roll = 0;
1036  xml->units.back()->limits.lateral = xml->units.back()->limits.retro = xml->units.back()->limits.forward =
1037  xml->units.back()->limits.afterburn = 0.0;
1038  }
1039  xml->units.back()->SetRecursiveOwner( this );
1040  xml->units[indx]->SetOrientation( Q, R );
1041  R.Normalize();
1042  xml->units[indx]->prev_physical_state = xml->units[indx]->curr_physical_state;
1043  xml->units[indx]->SetPosition( pos );
1044  xml->units[indx]->limits.structurelimits = R.Cast();
1045  xml->units[indx]->limits.limitmin = fbrltb[0];
1046  xml->units[indx]->name = filename;
1047  if (xml->units[indx]->pImage->unitwriter != NULL)
1048  xml->units[indx]->pImage->unitwriter->setName( filename );
1049  CheckAccessory( xml->units[indx] ); //turns on the ceerazy rotation for the turret
1050  break;
1051  case COCKPITDAMAGE:
1052  xml->unitlevel++;
1053  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1054  switch ( attribute_map.lookup( (*iter).name ) )
1055  {
1056  case DAMAGE:
1057  pImage->cockpit_damage[xml->damageiterator++] = parse_float( (*iter).value );
1058  break;
1059  }
1060  }
1061  break;
1062  case NETCOM:
1063  {
1064  float minfreq = 0, maxfreq = 0;
1065  bool video = false, secured = false;
1066  string method;
1067  assert( xml->unitlevel == 1 );
1068  xml->unitlevel++;
1069  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1070  switch ( attribute_map.lookup( (*iter).name ) )
1071  {
1072  case NETCOMM_MINFREQ:
1073  minfreq = parse_float( (*iter).value );
1074  break;
1075  case NETCOMM_MAXFREQ:
1076  maxfreq = parse_float( (*iter).value );
1077  break;
1078  case NETCOMM_SECURED:
1079  secured = parse_bool( (*iter).value );
1080  break;
1081  case NETCOMM_VIDEO:
1082  video = parse_bool( (*iter).value );
1083  break;
1084  case NETCOMM_CRYPTO:
1085  method = (*iter).value;
1086  break;
1087  }
1088  }
1089  break;
1090  }
1091  case JUMP:
1092  {
1093  static float insys_jump_cost =
1094  XMLSupport::parse_float( vs_config->getVariable( "physics", "insystem_jump_cost", ".1" ) );
1095  bool foundinsysenergy = false;
1096  //serialization covered in LoadXML
1097  assert( xml->unitlevel == 1 );
1098  xml->unitlevel++;
1099  jump.drive = -1; //activate the jump unit
1100  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1101  switch ( attribute_map.lookup( (*iter).name ) )
1102  {
1103  case MISSING:
1104  //serialization covered in LoadXML
1105  if ( parse_bool( (*iter).value ) )
1106  jump.drive = -2;
1107  break;
1108  case JUMPENERGY:
1109  //serialization covered in LoadXML
1110  jump.energy = parse_float( (*iter).value ); //short fix
1111  if (!foundinsysenergy)
1112  jump.insysenergy = jump.energy*insys_jump_cost;
1113  break;
1114  case INSYSENERGY:
1115  //serialization covered in LoadXML
1116  jump.insysenergy = parse_float( (*iter).value ); //short fix
1117  foundinsysenergy = true;
1118  break;
1119  case WARPDRIVERATING:
1120  jump.warpDriveRating = parse_float( (*iter).value );
1121  break;
1122  case DAMAGE:
1123  jump.damage = float_to_int( parse_float( (*iter).value ) ); //short fix
1124  break;
1125  case DELAY:
1126  //serialization covered in LoadXML
1127  {
1128  static int jumpdelaymult =
1129  XMLSupport::parse_int( vs_config->getVariable( "physics", "jump_delay_multiplier", "5" ) );
1130  jump.delay = parse_int( (*iter).value )*jumpdelaymult;
1131  break;
1132  }
1133  case FUEL:
1134  //serialization covered in LoadXML
1135  jump.energy = -parse_float( (*iter).value ); //short fix
1136  break;
1137  case WORMHOLE:
1138  //serialization covered in LoadXML
1139  pImage->forcejump = parse_bool( (*iter).value );
1140  if (pImage->forcejump)
1141  jump.drive = -2;
1142  break;
1143  }
1144  }
1145  break;
1146  }
1147  case SOUND:
1148  ADDTAG;
1149  assert( xml->unitlevel == 1 );
1150  xml->unitlevel++;
1151  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1152  switch ( attribute_map.lookup( (*iter).name ) )
1153  {
1154  case CLOAKWAV:
1155  ADDDEFAULT;
1156  sound->cloak = AUDCreateSoundWAV( (*iter).value, false );
1157  break;
1158  case JUMPWAV:
1159  ADDDEFAULT;
1160  sound->jump = AUDCreateSoundWAV( (*iter).value, false );
1161  break;
1162  case CLOAKMP3:
1163  ADDDEFAULT;
1164  sound->cloak = AUDCreateSoundMP3( (*iter).value, false );
1165  break;
1166  case ENGINEWAV:
1167  ADDDEFAULT;
1168  sound->engine = AUDCreateSoundWAV( (*iter).value, true );
1169  break;
1170  case ENGINEMP3:
1171  ADDDEFAULT;
1172  sound->engine = AUDCreateSoundMP3( (*iter).value, true );
1173  break;
1174  case SHIELDMP3:
1175  ADDDEFAULT;
1176  sound->shield = AUDCreateSoundMP3( (*iter).value, false );
1177  break;
1178  case SHIELDWAV:
1179  ADDDEFAULT;
1180  sound->shield = AUDCreateSoundWAV( (*iter).value, false );
1181  break;
1182  case EXPLODEMP3:
1183  ADDDEFAULT;
1184  sound->explode = AUDCreateSoundMP3( (*iter).value, false );
1185  break;
1186  case EXPLODEWAV:
1187  ADDDEFAULT;
1188  sound->explode = AUDCreateSoundWAV( (*iter).value, false );
1189  break;
1190  case ARMORMP3:
1191  ADDDEFAULT;
1192  sound->armor = AUDCreateSoundMP3( (*iter).value, false );
1193  break;
1194  case ARMORWAV:
1195  ADDDEFAULT;
1196  sound->armor = AUDCreateSoundWAV( (*iter).value, false );
1197  break;
1198  case HULLWAV:
1199  ADDDEFAULT;
1200  sound->hull = AUDCreateSoundWAV( (*iter).value, false );
1201  break;
1202  case HULLMP3:
1203  ADDDEFAULT;
1204  sound->hull = AUDCreateSoundMP3( (*iter).value, false );
1205  break;
1206  }
1207  }
1208  if (sound->cloak == -1) {
1209  static std::string ssound = vs_config->getVariable( "unitaudio", "cloak", "sfx43.wav" );
1210  sound->cloak = AUDCreateSound( ssound, false );
1211  }
1212  if (sound->engine == -1) {
1213  static std::string ssound = vs_config->getVariable( "unitaudio", "afterburner", "sfx10.wav" );
1214  sound->engine = AUDCreateSound( ssound, false );
1215  }
1216  if (sound->shield == -1) {
1217  static std::string ssound = vs_config->getVariable( "unitaudio", "shield", "sfx09.wav" );
1218  sound->shield = AUDCreateSound( ssound, false );
1219  }
1220  if (sound->armor == -1) {
1221  static std::string ssound = vs_config->getVariable( "unitaudio", "armor", "sfx08.wav" );
1222  sound->armor = AUDCreateSound( ssound, false );
1223  }
1224  if (sound->hull == -1) {
1225  static std::string ssound = vs_config->getVariable( "unitaudio", "armor", "sfx08.wav" );
1226  sound->hull = AUDCreateSound( ssound, false );
1227  }
1228  if (sound->explode == -1) {
1229  static std::string ssound = vs_config->getVariable( "unitaudio", "explode", "explosion.wav" );
1230  sound->explode = AUDCreateSound( ssound, false );
1231  }
1232  if (sound->jump == -1) {
1233  static std::string ssound = vs_config->getVariable( "unitaudio", "explode", "sfx43.wav" );
1234  sound->jump = AUDCreateSound( ssound, false );
1235  }
1236  break;
1237  case CLOAK:
1238  //serialization covered elsewhere
1239  assert( xml->unitlevel == 2 );
1240  xml->unitlevel++;
1241  pImage->cloakrate = (int) ( .2*(2147483647) ); //short fix
1242  cloakmin = 1;
1243  pImage->cloakenergy = 0;
1244  cloaking = INT_MIN; //lowest negative number //short fix
1245  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1246  switch ( attribute_map.lookup( (*iter).name ) )
1247  {
1248  case MISSING:
1249  //serialization covered in LoadXML
1250  if ( parse_bool( (*iter).value ) )
1251  cloaking = -1; //short fix
1252  break;
1253  case CLOAKMIN:
1254  //serialization covered in LoadXML
1255  cloakmin = (int) ( ( (-1) > 1 )*parse_float( (*iter).value ) ); //short fix
1256  break;
1257  case CLOAKGLASS:
1258  //serialization covered in LoadXML
1259  pImage->cloakglass = parse_bool( (*iter).value );
1260  break;
1261  case CLOAKRATE:
1262  //serialization covered in LoadXML
1263  pImage->cloakrate = (int) ( (2147483647)*parse_float( (*iter).value ) ); //short fix
1264  break;
1265  case CLOAKENERGY:
1266  //serialization covered in LoadXML
1267  pImage->cloakenergy = parse_float( (*iter).value );
1268  break;
1269  }
1270  }
1271  if ( (cloakmin&0x1) && !pImage->cloakglass )
1272  cloakmin -= 1;
1273  if ( (cloakmin&0x1) == 0 && pImage->cloakglass )
1274  cloakmin += 1;
1275  break;
1276  case ARMOR:
1277  assert( xml->unitlevel == 2 );
1278  xml->unitlevel++;
1279  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1280  switch ( attribute_map.lookup( (*iter).name ) )
1281  {
1282  case FRONT:
1283  dirfrac = ( CLAMP_UINT( parse_float( (*iter).value ) ) )/4;
1284  armor.frontrighttop += dirfrac;
1285  armor.frontlefttop += dirfrac;
1286  armor.frontrightbottom += dirfrac;
1287  armor.frontleftbottom += dirfrac;
1288  break;
1289  case BACK:
1290  dirfrac = ( CLAMP_UINT( parse_float( (*iter).value ) ) )/4;
1291  armor.backrighttop += dirfrac;
1292  armor.backlefttop += dirfrac;
1293  armor.backrightbottom += dirfrac;
1294  armor.backleftbottom += dirfrac;
1295  break;
1296  case RIGHT:
1297  dirfrac = ( CLAMP_UINT( parse_float( (*iter).value ) ) )/4;
1298  armor.frontrighttop += dirfrac;
1299  armor.backrighttop += dirfrac;
1300  armor.frontrightbottom += dirfrac;
1301  armor.backrightbottom += dirfrac;
1302  break;
1303  case LEFT:
1304  dirfrac = ( CLAMP_UINT( parse_float( (*iter).value ) ) )/4;
1305  armor.backlefttop += dirfrac;
1306  armor.frontlefttop += dirfrac;
1307  armor.backleftbottom += dirfrac;
1308  armor.frontleftbottom += dirfrac;
1309  break;
1310 
1311  case FRONTRIGHTTOP:
1312  //serialization covered in LoadXML
1313  armor.frontrighttop = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1314  break;
1315  case BACKRIGHTTOP:
1316  //serialization covered in LoadXML
1317  armor.backrighttop = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1318  break;
1319  case FRONTLEFTTOP:
1320  //serialization covered in LoadXML
1321  armor.frontlefttop = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1322  break;
1323  case BACKLEFTTOP:
1324  //serialization covered in LoadXML
1325  armor.backlefttop = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1326  break;
1327  case FRONTRIGHTBOTTOM:
1328  //serialization covered in LoadXML
1329  armor.frontrightbottom = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1330  break;
1331  case BACKRIGHTBOTTOM:
1332  //serialization covered in LoadXML
1333  armor.backrightbottom = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1334  break;
1335  case FRONTLEFTBOTTOM:
1336  //serialization covered in LoadXML
1337  armor.frontleftbottom = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1338  break;
1339  case BACKLEFTBOTTOM:
1340  //serialization covered in LoadXML
1341  armor.backleftbottom = CLAMP_UINT( parse_float( (*iter).value ) ); //short fix
1342  break;
1343  }
1344  }
1345  break;
1346  case SHIELDS:
1347  //serialization covered in LoadXML
1348  assert( xml->unitlevel == 2 );
1349  xml->unitlevel++;
1350  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1351  switch ( attribute_map.lookup( (*iter).name ) )
1352  {
1353  case FRONT:
1354  //serialization covered in LoadXML
1355  fbrltb[0] = parse_float( (*iter).value );
1356  shield.number++;
1357  break;
1358  case BACK:
1359  //serialization covered in LoadXML
1360  fbrltb[1] = parse_float( (*iter).value );
1361  shield.number++;
1362  break;
1363  case LEFT:
1364  //serialization covered in LoadXML
1365  fbrltb[3] = parse_float( (*iter).value );
1366  shield.number++;
1367  break;
1368  case RIGHT:
1369  //serialization covered in LoadXML
1370  fbrltb[2] = parse_float( (*iter).value );
1371  shield.number++;
1372  break;
1373  case TOP:
1374  //serialization covered in LoadXML
1375  fbrltb[4] = parse_float( (*iter).value );
1376  shield.number++;
1377  break;
1378  case BOTTOM:
1379  //serialization covered in LoadXML
1380  fbrltb[5] = parse_float( (*iter).value );
1381  shield.number++;
1382  break;
1383  case RECHARGE:
1384  //serialization covered in LoadXML
1385  shield.recharge = parse_float( (*iter).value );
1386  break;
1387  case LEAK:
1388  //serialization covered in LoadXML
1389  shield.leak = parse_int( (*iter).value );
1390  break;
1391  }
1392  }
1393  switch (shield.number)
1394  {
1395  case 2:
1396  shield.shield2fb.frontmax = shield.shield2fb.front = fbrltb[0]; //short fix
1397  shield.shield2fb.backmax = shield.shield2fb.back = fbrltb[1]; //short fix
1398  break;
1399  case 8: //short fix
1400  shield.shield8.frontrighttop = CLAMP_UINT( .25*fbrltb[0]+.25*fbrltb[2] ); //short fix
1401  shield.shield8.backrighttop = CLAMP_UINT( .25*fbrltb[1]+.25*fbrltb[2] ); //short fix
1402  shield.shield8.frontlefttop = CLAMP_UINT( .25*fbrltb[0]+.25*fbrltb[3] ); //short fix
1403  shield.shield8.backlefttop = CLAMP_UINT( .25*fbrltb[1]+.25*fbrltb[3] ); //short fix
1404  shield.shield8.frontrightbottom = CLAMP_UINT( .25*fbrltb[0]+.25*fbrltb[2] ); //short fix
1405  shield.shield8.backrightbottom = CLAMP_UINT( .25*fbrltb[1]+.25*fbrltb[2] ); //short fix
1406  shield.shield8.frontleftbottom = CLAMP_UINT( .25*fbrltb[0]+.25*fbrltb[3] ); //short fix
1407  shield.shield8.backleftbottom = CLAMP_UINT( .25*fbrltb[1]+.25*fbrltb[3] ); //short fix
1408 
1409  break;
1410  case 4:
1411  default:
1412  shield.shield4fbrl.frontmax = shield.shield4fbrl.front = (fbrltb[0]); //short fix
1413  shield.shield4fbrl.backmax = shield.shield4fbrl.back = (fbrltb[1]); //short fix
1414  shield.shield4fbrl.rightmax = shield.shield4fbrl.right = (fbrltb[2]); //short fix
1415  shield.shield4fbrl.leftmax = shield.shield4fbrl.left = fbrltb[3]; //short fix
1416  }
1417  break;
1418  case HULL:
1419  assert( xml->unitlevel == 2 );
1420  xml->unitlevel++;
1421  maxhull = 0;
1422  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1423  switch ( attribute_map.lookup( (*iter).name ) )
1424  {
1425  case STRENGTH:
1426  hull = parse_float( (*iter).value );
1427  break;
1428  case MAXIMUM:
1429  maxhull = parse_float( (*iter).value );
1430  break;
1431  }
1432  }
1433  if (maxhull == 0) {
1434  maxhull = hull;
1435  if (maxhull == 0)
1436  maxhull = 1;
1437  }
1438  break;
1439  case STATS:
1440  assert( xml->unitlevel == 1 );
1441  xml->unitlevel++;
1442  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1443  switch ( attribute_map.lookup( (*iter).name ) )
1444  {
1445  case MASS:
1446  Mass = parse_float( (*iter).value );
1447  break;
1448  case MOMENTOFINERTIA:
1449  Momentofinertia = parse_float( (*iter).value );
1450  break;
1451  case FUEL:
1452  fuel = Mass*60*getFuelConversion();
1453  //FIXME! This is a hack until we get csv support
1454  //FIXME FIXME FIXME got support a long time ago! --chuck_starchaser
1455  break;
1456  }
1457  }
1458  break;
1459  case MANEUVER:
1460  assert( xml->unitlevel == 2 );
1461  xml->unitlevel++;
1462  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1463  switch ( attribute_map.lookup( (*iter).name ) )
1464  {
1465  case YAW:
1466  limits.yaw = parse_float( (*iter).value )*(VS_PI/180);
1467  break;
1468  case PITCH:
1469  limits.pitch = parse_float( (*iter).value )*(VS_PI/180);
1470  break;
1471  case ROLL:
1472  limits.roll = parse_float( (*iter).value )*(VS_PI/180);
1473  break;
1474  }
1475  }
1476  break;
1477  case ENGINE:
1478  assert( xml->unitlevel == 2 );
1479  xml->unitlevel++;
1480  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1481  switch ( attribute_map.lookup( (*iter).name ) )
1482  {
1483  case AACCEL:
1484  break;
1485  case FORWARD:
1486  limits.forward = game_speed*game_accel*parse_float( (*iter).value );
1487  break;
1488  case RETRO:
1489  limits.retro = game_speed*game_accel*parse_float( (*iter).value );
1490  break;
1491  case AFTERBURNER:
1492  limits.afterburn = game_speed*game_accel*parse_float( (*iter).value );
1493  break;
1494  case LEFT:
1495  limits.lateral = game_speed*game_accel*parse_float( (*iter).value );
1496  break;
1497  case RIGHT:
1498  limits.lateral = game_speed*game_accel*parse_float( (*iter).value );
1499  break;
1500  case TOP:
1501  limits.vertical = game_speed*game_accel*parse_float( (*iter).value );
1502  break;
1503  case BOTTOM:
1504  limits.vertical = game_speed*game_accel*parse_float( (*iter).value );
1505  break;
1506  }
1507  }
1508  break;
1509  case COMPUTER:
1510  ADDTAG;
1511  assert( xml->unitlevel == 1 );
1512  xml->unitlevel++;
1513  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1514  switch ( attribute_map.lookup( (*iter).name ) )
1515  {
1516  case MAXSPEED:
1517  computer.max_combat_speed = game_speed*parse_float( (*iter).value );
1519  break;
1520  case AFTERBURNER:
1521  computer.max_combat_ab_speed = game_speed*parse_float( (*iter).value );
1523  break;
1524  case YAW:
1525  computer.max_yaw_right = computer.max_yaw_left = parse_float( (*iter).value )*(VS_PI/180);
1527  break;
1528  case PITCH:
1529  computer.max_pitch_up = computer.max_pitch_down = parse_float( (*iter).value )*(VS_PI/180);
1531  break;
1532  case ROLL:
1533  computer.max_roll_right = computer.max_roll_left = parse_float( (*iter).value )*(VS_PI/180);
1535  break;
1536  case SLIDE_START:
1537  computer.slide_start = parse_int( (*iter).value );
1539  break;
1540  case SLIDE_END:
1541  computer.slide_end = parse_int( (*iter).value );
1543  break;
1544  }
1545  }
1546  pImage->unitwriter->AddTag( "Radar" );
1554  pImage->unitwriter->EndTag( "Radar" );
1555  break;
1556  case RADAR:
1557  //handled above
1558  assert( xml->unitlevel == 2 );
1559  xml->unitlevel++;
1560  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1561  switch ( attribute_map.lookup( (*iter).name ) )
1562  {
1563  case ITTS:
1564  computer.itts = parse_bool( (*iter).value );
1565  break;
1566  case MINTARGETSIZE:
1567  computer.radar.mintargetsize = parse_float( (*iter).value );
1568  break;
1569  case MAXCONE:
1570  computer.radar.maxcone = parse_float( (*iter).value );
1571  break;
1572  case LOCKCONE:
1573  computer.radar.lockcone = parse_float( (*iter).value );
1574  break;
1575  case TRACKINGCONE:
1576  computer.radar.trackingcone = parse_float( (*iter).value );
1577  break;
1578  case RANGE:
1579  computer.radar.maxrange = parse_float( (*iter).value );
1580  break;
1581  case ISCOLOR:
1582  computer.radar.capability = atoi( (*iter).value.c_str() );
1583  if (computer.radar.capability == 0)
1584  computer.radar.capability = parse_bool( (*iter).value );
1585  break;
1586  }
1587  }
1588  break;
1589  case REACTOR:
1590  assert( xml->unitlevel == 2 );
1591  xml->unitlevel++;
1592  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1593  switch ( attribute_map.lookup( (*iter).name ) )
1594  {
1595  case RECHARGE:
1596  recharge = parse_float( (*iter).value );
1597  break;
1598  case WARPENERGY:
1599  maxwarpenergy = ( parse_float( (*iter).value ) ); //short fix
1600  break;
1601  case LIMIT:
1602  maxenergy = energy = parse_float( (*iter).value );
1603  break;
1604  }
1605  }
1606  break;
1607  case YAW:
1608  ADDTAG;
1610  assert( xml->unitlevel == 2 );
1611  xml->unitlevel++;
1612  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1613  switch ( attribute_map.lookup( (*iter).name ) )
1614  {
1615  case MAX:
1616  ADDDEFAULT;
1617  xml->ymax = parse_float( (*iter).value )*(VS_PI/180);
1618  break;
1619  case MIN:
1620  ADDDEFAULT;
1621  xml->ymin = parse_float( (*iter).value )*(VS_PI/180);
1622  break;
1623  }
1624  }
1625  break;
1626 
1627  case PITCH:
1628  ADDTAG;
1630  assert( xml->unitlevel == 2 );
1631  xml->unitlevel++;
1632  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1633  switch ( attribute_map.lookup( (*iter).name ) )
1634  {
1635  case MAX:
1636  ADDDEFAULT;
1637  xml->pmax = parse_float( (*iter).value )*(VS_PI/180);
1638  break;
1639  case MIN:
1640  ADDDEFAULT;
1641  xml->pmin = parse_float( (*iter).value )*(VS_PI/180);
1642  break;
1643  }
1644  }
1645  break;
1646  case DESCRIPTION:
1647  ADDTAG;
1648  xml->unitlevel++;
1649  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1650  switch ( attribute_map.lookup( (*iter).name ) )
1651  {
1653  ADDDEFAULT;
1655  break;
1656  case FACECAMERA:
1657  ADDDEFAULT;
1659  break;
1660  case COMBATROLE:
1661  ADDDEFAULT;
1662  xml->calculated_role = true;
1663  this->setCombatRole( iter->value );
1664  break;
1665  case NUMANIMATIONSTAGES:
1669  break;
1670  }
1671  }
1672  break;
1673  case ROLL:
1674  ADDTAG;
1676  assert( xml->unitlevel == 2 );
1677  xml->unitlevel++;
1678  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1679  switch ( attribute_map.lookup( (*iter).name ) )
1680  {
1681  case MAX:
1682  ADDDEFAULT;
1683  xml->rmax = parse_float( (*iter).value )*(VS_PI/180);
1684  break;
1685  case MIN:
1686  ADDDEFAULT;
1687  xml->rmin = parse_float( (*iter).value )*(VS_PI/180);
1688  break;
1689  }
1690  }
1691  break;
1692  case UNIT:
1693  assert( xml->unitlevel == 0 );
1694  xml->unitlevel++;
1695  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1696  switch ( attribute_map.lookup( (*iter).name ) )
1697  {
1698  default:
1699  break;
1700  case UNITSCALE:
1701  xml->unitscale = parse_float( (*iter).value );
1702  break;
1703  case COCKPIT:
1704  VSFileSystem::vs_fprintf( stderr, "Cockpit attrib deprecated use tag" );
1705  break;
1706  }
1707  }
1708  break;
1709  case COCKPIT:
1710  ADDTAG;
1711  assert( xml->unitlevel == 1 );
1712  xml->unitlevel++;
1713  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1714  switch ( attribute_map.lookup( (*iter).name ) )
1715  {
1716  case XFILE:
1717  pImage->cockpitImage = (*iter).value;
1719  break;
1720  case X:
1721  pImage->CockpitCenter.i = xml->unitscale*parse_float( (*iter).value );
1723  break;
1724  case Y:
1725  pImage->CockpitCenter.j = xml->unitscale*parse_float( (*iter).value );
1727  break;
1728  case Z:
1729  pImage->CockpitCenter.k = xml->unitscale*parse_float( (*iter).value );
1731  break;
1732  }
1733  }
1734  break;
1735  case DEFENSE:
1736  assert( xml->unitlevel == 1 );
1737  xml->unitlevel++;
1738  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1739  switch ( attribute_map.lookup( (*iter).name ) )
1740  {
1741  case HUDIMAGE:
1742  if ( (*iter).value.length() ) {
1743  pImage->pHudImage = createVSSprite( (*iter).value.c_str() );
1744  xml->hudimage = (*iter).value;
1745  }
1746  break;
1747  case EXPLOSIONANI:
1748  if ( (*iter).value.length() ) {
1749  pImage->explosion_type = (*iter).value;
1750  {
1752  }
1753  }
1754  break;
1755  case REPAIRDROID:
1756  pImage->repair_droid = (unsigned char) parse_float( (*iter).value );
1757  break;
1758  case ECM:
1759 
1760  pImage->ecm = (int) ( ( (-1) > 1 )*parse_float( (*iter).value ) ); //short fix
1761  pImage->ecm = pImage->ecm > 0 ? -pImage->ecm : pImage->ecm;
1762  break;
1763  default:
1764  break;
1765  }
1766  }
1767  break;
1768  case THRUST:
1769  assert( xml->unitlevel == 1 );
1770  xml->unitlevel++;
1771  break;
1772  case ENERGY:
1773  assert( xml->unitlevel == 1 );
1774  xml->unitlevel++;
1775  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
1776  switch ( attribute_map.lookup( (*iter).name ) )
1777  {
1778  case AFTERBURNENERGY:
1779  afterburnenergy = ( parse_float( (*iter).value ) ); //short fix
1780  break;
1781  default:
1782  break;
1783  }
1784  }
1785  break;
1786  case RESTRICTED:
1787  ADDTAG;
1788  assert( xml->unitlevel == 1 );
1789  xml->unitlevel++;
1790  break;
1791  case UNKNOWN:
1792  ADDTAG;
1793  default:
1794  for (iter = attributes.begin(); iter != attributes.end(); iter++)
1795  ADDDEFAULT;
1796  xml->unitlevel++;
1797  break;
1798  }
1799 }
1800 
1801 #undef ADDELEMF
1802 #undef ADDELEMI
1803 #undef ADDDEFAULT
1804 #undef ADDELEM
1805 #undef ADDELEMNAME
1806 #undef ADDTAG
1807 #undef ADDTAGNAME
1808 
1809 void Unit::endElement( const string &name )
1810 {
1811  using namespace UnitXML;
1812  pImage->unitwriter->EndTag( name );
1813  Names elem = (Names) element_map.lookup( name );
1814  switch (elem)
1815  {
1816  case UNKNOWN:
1817  xml->unitlevel--;
1818  break;
1819  default:
1820  xml->unitlevel--;
1821  break;
1822  }
1823 }
1824 
1825 using namespace VSFileSystem;
1826 
1827 void Unit::LoadXML( const char *filename, const char *modifications, string *xmlbuffer )
1828 {}
1829 
1830 void Unit::LoadXML( VSFileSystem::VSFile &f, const char *modifications, string *xmlbuffer )
1831 {
1832  shield.number = 0;
1833  string filename( f.GetFilename() );
1835  std::string collideTreeHash = VSFileSystem::GetHashName( string( modifications )+"#"+filename );
1836  pImage->unitwriter = new XMLSerializer( name.get().c_str(), modifications, this );
1837  pImage->unitwriter->AddTag( "Unit" );
1838  string *myhudim = &pImage->unitwriter->randomdata[0];
1839  float *myscale = &pImage->unitscale;
1840  pImage->unitwriter->AddElement( "scale", floatStarHandler, XMLType( myscale ) );
1841  {
1842  pImage->unitwriter->AddTag( "Jump" );
1845  pImage->unitwriter->AddElement( "jumpenergy", floatStarHandler, XMLType( &jump.energy ) ); //short fix
1846  pImage->unitwriter->AddElement( "insysenergy", floatStarHandler, XMLType( &jump.insysenergy ) ); //short fix
1850  pImage->unitwriter->EndTag( "Jump" );
1851  }
1852  {
1853  unsigned int i;
1854  for (i = 0; i <= (UnitImages< void >::NUMGAUGES+MAXVDUS); i++) {
1855  pImage->unitwriter->AddTag( "CockpitDamage" );
1857  pImage->unitwriter->EndTag( "CockpitDamage" );
1858  }
1859  }
1860  {
1861  pImage->unitwriter->AddTag( "Defense" );
1862  pImage->unitwriter->AddElement( "HudImage", stringStarHandler, XMLType( myhudim ) );
1863  if ( pImage->explosion_type.get().length() )
1866  pImage->unitwriter->AddElement( "ECM", intToFloatHandler, XMLType( &pImage->ecm ) ); //short fix
1867  {
1868  pImage->unitwriter->AddTag( "Cloak" );
1870  pImage->unitwriter->AddElement( "cloakmin", intToFloatHandler, XMLType( &cloakmin ) ); //short fix
1872  pImage->unitwriter->AddElement( "cloakrate", intToFloatHandler, XMLType( &pImage->cloakrate ) ); //short fix
1874  pImage->unitwriter->EndTag( "Cloak" );
1875  }
1876  {
1877  pImage->unitwriter->AddTag( "Armor" );
1878  pImage->unitwriter->AddElement( "frontrighttop", floatStarHandler, XMLType( &armor.frontrighttop ) ); //short fix
1879  pImage->unitwriter->AddElement( "backrighttop", floatStarHandler, XMLType( &armor.backrighttop ) ); //short fix
1880  pImage->unitwriter->AddElement( "frontlefttop", floatStarHandler, XMLType( &armor.frontlefttop ) ); //short fix
1881  pImage->unitwriter->AddElement( "backlefttop", floatStarHandler, XMLType( &armor.backlefttop ) ); //short fix
1882  pImage->unitwriter->AddElement( "frontrightbottom", floatStarHandler, XMLType( &armor.frontrightbottom ) ); //short fix
1883  pImage->unitwriter->AddElement( "backrightbottom", floatStarHandler, XMLType( &armor.backrightbottom ) ); //short fix
1884  pImage->unitwriter->AddElement( "frontleftbottom", floatStarHandler, XMLType( &armor.frontleftbottom ) ); //short fix
1885  pImage->unitwriter->AddElement( "backleftbottom", floatStarHandler, XMLType( &armor.backleftbottom ) ); //short fix
1886  pImage->unitwriter->EndTag( "Armor" );
1887  }
1888  {
1889  pImage->unitwriter->AddTag( "Shields" );
1890  pImage->unitwriter->AddElement( "front", shieldSerializer, XMLType( (void*) &shield ) );
1893 
1894  pImage->unitwriter->EndTag( "Shields" );
1895  }
1896  {
1897  pImage->unitwriter->AddTag( "Hull" );
1898  pImage->unitwriter->AddElement( "strength", floatStarHandler, XMLType( &hull ) );
1900  pImage->unitwriter->EndTag( "Hull" );
1901  }
1902 
1903  pImage->unitwriter->EndTag( "Defense" );
1904  }
1905  {
1906  pImage->unitwriter->AddTag( "Energy" );
1907  pImage->unitwriter->AddElement( "afterburnenergy", floatStarHandler, XMLType( &afterburnenergy ) ); //short fix
1908  pImage->unitwriter->AddTag( "Reactor" );
1911  pImage->unitwriter->AddElement( "warpenergy", floatStarHandler, XMLType( &maxwarpenergy ) ); //short fix
1912  pImage->unitwriter->EndTag( "Reactor" );
1913 
1914  pImage->unitwriter->EndTag( "Energy" );
1915  }
1916  {
1917  pImage->unitwriter->AddTag( "Stats" );
1919  pImage->unitwriter->AddElement( "momentofinertia", floatStarHandler, XMLType( &Momentofinertia ) );
1921  pImage->unitwriter->EndTag( "Stats" );
1922  pImage->unitwriter->AddTag( "Thrust" );
1923  {
1924  pImage->unitwriter->AddTag( "Maneuver" );
1928  pImage->unitwriter->EndTag( "Maneuver" );
1929  }
1930  {
1931  pImage->unitwriter->AddTag( "Engine" );
1939  pImage->unitwriter->EndTag( "Engine" );
1940  }
1941  pImage->unitwriter->EndTag( "Thrust" );
1942  }
1943  pImage->CockpitCenter.Set( 0, 0, 0 );
1944  xml = new XML();
1945  xml->randomstartframe = ( (float) rand() )/RAND_MAX;
1946  xml->randomstartseconds = 0;
1947  xml->calculated_role = false;
1948  xml->damageiterator = 0;
1949  xml->unitModifications = modifications;
1950  xml->shieldmesh = NULL;
1951  xml->rapidmesh = NULL;
1952  xml->hasColTree = true;
1953  xml->unitlevel = 0;
1954  xml->unitscale = 1;
1955  XML_Parser parser = XML_ParserCreate( NULL );
1956  XML_SetUserData( parser, this );
1957  XML_SetElementHandler( parser, &Unit::beginElement, &Unit::endElement );
1958  if (xmlbuffer != NULL)
1959  XML_Parse( parser, xmlbuffer->c_str(), xmlbuffer->length(), 1 );
1960  else
1961  XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 );
1962  XML_ParserFree( parser );
1963  //Load meshes into subunit
1964  pImage->unitwriter->EndTag( "Unit" );
1965  meshdata = xml->meshes;
1966  meshdata.push_back( NULL );
1967  corner_min = Vector( FLT_MAX, FLT_MAX, FLT_MAX );
1968  corner_max = Vector( -FLT_MAX, -FLT_MAX, -FLT_MAX );
1970  *myhudim = xml->hudimage;
1971  unsigned int a;
1972  if ( xml->mountz.size() ) {
1973  //DO not destroy anymore, just affect address
1974  for (a = 0; a < xml->mountz.size(); a++)
1975  mounts.push_back( *xml->mountz[a] );
1976  }
1977  unsigned char parity = 0;
1978  for (a = 0; a < xml->mountz.size(); a++) {
1979  static bool half_sounds = XMLSupport::parse_bool( vs_config->getVariable( "audio", "every_other_mount", "false" ) );
1980  if (a%2 == parity) {
1981  int b = a;
1982  if ( a%4 == 2 && (int) a < (GetNumMounts()-1) )
1983  if (mounts[a].type->type != weapon_info::PROJECTILE && mounts[a+1].type->type != weapon_info::PROJECTILE)
1984  b = a+1;
1985  mounts[b].sound = AUDCreateSound( mounts[b].type->sound, mounts[b].type->type != weapon_info::PROJECTILE );
1986  } else if ( (!half_sounds) || mounts[a].type->type == weapon_info::PROJECTILE ) {
1987  mounts[a].sound = AUDCreateSound( mounts[a].type->sound, mounts[a].type->type != weapon_info::PROJECTILE ); //lloping also flase in unit_customize
1988  }
1989  if (a > 0)
1990  if (mounts[a].sound == mounts[a-1].sound && mounts[a].sound != -1)
1991  printf( "error" );
1992  }
1993  for (a = 0; a < xml->units.size(); a++)
1994  SubUnits.prepend( xml->units[a] );
1995  calculate_extent( false );
1997  string tmpname( filename );
1998  vector< mesh_polygon >polies;
1999  this->colTrees = collideTrees::Get( collideTreeHash );
2000  if (this->colTrees)
2001  this->colTrees->Inc();
2002  csOPCODECollider *colShield = NULL;
2003  if (xml->shieldmesh) {
2004  meshdata.back() = xml->shieldmesh;
2005  if (!this->colTrees) {
2006  if ( meshdata.back() ) {
2007  meshdata.back()->GetPolys( polies );
2008  colShield = new csOPCODECollider( polies );
2009  }
2010  }
2011  } else {
2012  Mesh *tmp = NULL;
2013  static int shieldstacks = XMLSupport::parse_int( vs_config->getVariable( "graphics", "shield_detail", "16" ) );
2014  static std::string shieldtex = vs_config->getVariable( "graphics", "shield_texture", "shield.bmp" );
2015  static std::string shieldtechnique = vs_config->getVariable( "graphics", "shield_technique", "" );
2016  meshdata.back() = new SphereMesh( rSize(), shieldstacks, shieldstacks, shieldtex.c_str(), shieldtechnique, NULL, false, ONE, ONE );
2017  tmp = meshdata.back();
2018  }
2019  meshdata.back()->EnableSpecialFX();
2020  if (!this->colTrees) {
2021  polies.clear();
2022  if (xml->rapidmesh)
2023  xml->rapidmesh->GetPolys( polies );
2024  csOPCODECollider *csrc = NULL;
2025  if (xml->hasColTree)
2026  csrc = getCollideTree( Vector( 1, 1, 1 ),
2027  xml->rapidmesh
2028  ? &polies : NULL );
2029  this->colTrees = new collideTrees( collideTreeHash,
2030  csrc,
2031  colShield );
2032  if (xml->rapidmesh && xml->hasColTree) //if we have a speciaal rapid mesh we need to generate things now
2033  for (unsigned int i = 1; i < collideTreesMaxTrees; ++i)
2034  if (!this->colTrees->rapidColliders[i]) {
2035  unsigned int which = 1<<i;
2036  this->colTrees->rapidColliders[i] = getCollideTree( Vector( which, which, which ),
2037  &polies );
2038  }
2039  }
2040  if (xml->rapidmesh)
2041  delete xml->rapidmesh;
2042  delete xml;
2043 }
2044 
2045 csOPCODECollider* Unit::getCollideTree( const Vector &scale, const std::vector< mesh_polygon > *pol )
2046 {
2047  vector< mesh_polygon >polies;
2048  if (!pol)
2049  for (int j = 0; j < nummesh(); j++)
2050  meshdata[j]->GetPolys( polies );
2051  else
2052  polies = *pol;
2053  if (scale.i != 1 || scale.j != 1 || scale.k != 1) {
2054  for (vector< mesh_polygon >::iterator i = polies.begin(); i != polies.end(); ++i)
2055  for (unsigned int j = 0; j < i->v.size(); ++j) {
2056  i->v[j].i *= scale.i;
2057  i->v[j].j *= scale.j;
2058  i->v[j].k *= scale.k;
2059  }
2060  }
2061  return new csOPCODECollider( polies );
2062 }
2063