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
script.cpp
Go to the documentation of this file.
1 #include "script.h"
2 #include "navigation.h"
3 #include "xml_support.h"
4 #include "flybywire.h"
5 #include <stdio.h>
6 #include <vector>
7 #include <stack>
8 #include "vsfilesystem.h"
9 #include "tactics.h"
10 #include "cmd/unit_generic.h"
11 #include "hard_coded_scripts.h"
12 #include "universe_util.h"
13 #include <assert.h>
14 
15 typedef vsUMap< string, CCScript* >HardCodedMap;
17 {
18  HardCodedMap tmp;
19  typedef std::pair< std::string, CCScript* >MyPair;
20  tmp.insert( MyPair( "loop around fast", &LoopAroundFast ) );
21  tmp.insert( MyPair( "aggressive loop around fast", &AggressiveLoopAroundFast ) );
22  tmp.insert( MyPair( "loop around slow", &LoopAroundSlow ) );
23  tmp.insert( MyPair( "aggressive loop around slow", &AggressiveLoopAroundSlow ) );
24  tmp.insert( MyPair( "loop around", &LoopAround ) );
25  tmp.insert( MyPair( "aggressive loop around", &AggressiveLoopAround ) );
26  tmp.insert( MyPair( "barrel roll", &BarrelRoll ) );
27  tmp.insert( MyPair( "veer away", &VeerAway ) );
28  tmp.insert( MyPair( "veer away itts", &VeerAwayITTS ) );
29  tmp.insert( MyPair( "veer and turn away", &VeerAndVectorAway ) );
30  tmp.insert( MyPair( "veer and vector away", &VeerAndVectorAway ) );
31  tmp.insert( MyPair( "afterburn veer away", &AfterburnVeerAndTurnAway ) );
32  tmp.insert( MyPair( "afterburn vector away", &AfterburnVeerAndVectorAway ) );
33  tmp.insert( MyPair( "match velocity", &MatchVelocity ) );
34  tmp.insert( MyPair( "fly straight", &FlyStraight ) );
35  tmp.insert( MyPair( "fly straight afterburner", &FlyStraightAfterburner ) );
36  tmp.insert( MyPair( "afterburn fly straight", &FlyStraightAfterburner ) );
37  tmp.insert( MyPair( "do nothing", &DoNothing ) );
38  tmp.insert( MyPair( "take off", &Takeoff ) );
39  tmp.insert( MyPair( "coast to stop", &CoastToStop ) );
40  tmp.insert( MyPair( "self destruct", &SelfDestruct ) );
41  tmp.insert( MyPair( "take off every zig", &TakeoffEveryZig ) );
42  tmp.insert( MyPair( "afterburn turn towards", &AfterburnTurnTowards ) );
43  tmp.insert( MyPair( "afterburn turn towards itts", &AfterburnTurnTowardsITTS ) );
44  tmp.insert( MyPair( "cloak", &CloakForScript ) );
45  tmp.insert( MyPair( "evade", &AfterburnEvadeLeftRight ) );
46  tmp.insert( MyPair( "kick stop", &Kickstop ) );
47  tmp.insert( MyPair( "move to", &MoveTo ) );
48  tmp.insert( MyPair( "shelton slide", &SheltonSlide ) );
49  tmp.insert( MyPair( "skilled afterburner slide", &SkilledABSlide ) );
50  tmp.insert( MyPair( "afterburner slide", &AfterburnerSlide ) );
51  tmp.insert( MyPair( "stop", &Stop ) );
52  tmp.insert( MyPair( "turn away", &TurnAway ) );
53  tmp.insert( MyPair( "afterburn turn away", &AfterburnTurnAway ) );
54  tmp.insert( MyPair( "turn towards", &TurnTowards ) );
55  tmp.insert( MyPair( "turn towards itts", &TurnTowardsITTS ) );
56  tmp.insert( MyPair( "drop cargo", &DropCargo ) );
57  tmp.insert( MyPair( "drop half cargo", &DropHalfCargo ) );
58  tmp.insert( MyPair( "drop one cargo", &DropOneCargo ) );
59  tmp.insert( MyPair( "roll right", &RollRight ) );
60  tmp.insert( MyPair( "roll right hard", &RollRightHard ) );
61  tmp.insert( MyPair( "roll left", &RollLeft ) );
62  tmp.insert( MyPair( "roll left hard", &RollLeftHard ) );
63  tmp.insert( MyPair( "evade left right", &EvadeLeftRight ) );
64  tmp.insert( MyPair( "evade up down", &EvadeUpDown ) );
65  tmp.insert( MyPair( "afterburn evade left right", &AfterburnEvadeLeftRight ) );
66  tmp.insert( MyPair( "afterburn evade up down", &AfterburnEvadeUpDown ) );
67  tmp.insert( MyPair( "face perpendicular", &FacePerpendicular ) );
68  tmp.insert( MyPair( "face perpendicular slow", &FacePerpendicularSlow ) );
69  tmp.insert( MyPair( "face perpendicular fast", &FacePerpendicularFast ) );
70  tmp.insert( MyPair( "roll perpendicular", &RollFacePerpendicular ) );
71  tmp.insert( MyPair( "roll perpendicular slow", &RollFacePerpendicularSlow ) );
72  tmp.insert( MyPair( "roll perpendicular fast", &RollFacePerpendicularFast ) );
73  if (tmp.find("roll perpendicular fast")==tmp.end()){
74  exit(1);
75  }
76  return tmp;
77 }
78 
80 bool validateHardCodedScript( std::string s )
81 {
82  if (s.length() == 0) return true;
83  return hard_coded_scripts.find( s ) != hard_coded_scripts.end();
84 }
86 {
87  int unitlevel;
88  int acc;
89  vector< float >executefor;
90  bool itts;
91  bool afterburn;
92  bool terminate;
93  char lin;
95  float defaultf;
96  std::stack< QVector >vectors;
97  std::stack< float > floats;
98  std::vector< Order* >orders;
99 };
100 float& AIScript::topf()
101 {
102  if ( !xml->floats.size() ) {
103  xml->floats.push( xml->defaultf );
104  VSFileSystem::vs_fprintf( stderr, "\nERROR: Float stack is empty... Will return %f\n", xml->defaultf );
105  }
106  return xml->floats.top();
107 }
108 void AIScript::popf()
109 {
110  if (xml->floats.size() <= 0) {
111  VSFileSystem::vs_fprintf( stderr, "\nERROR: Float stack is empty... Will not delete\n" );
112  return;
113  }
114  xml->floats.pop();
115 }
116 QVector& AIScript::topv()
117 {
118  if ( !xml->vectors.size() ) {
119  xml->vectors.push( xml->defaultvec );
120  VSFileSystem::vs_fprintf( stderr,
121  "\nERROR: Vector stack is empty... Will return <%f, %f, %f>\n",
122  xml->defaultvec.i,
123  xml->defaultvec.j,
124  xml->defaultvec.k );
125  }
126  return xml->vectors.top();
127 }
128 void AIScript::popv()
129 {
130  if (xml->vectors.size() <= 0) {
131  VSFileSystem::vs_fprintf( stderr, "\nERROR: Vector stack is empty... Will not delete\n" );
132  return;
133  }
134  xml->vectors.pop();
135 }
136 
137 void AIScript::beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
138 {
139  ( (AIScript*) userData )->beginElement( name, AttributeList( atts ) );
140 }
141 
142 void AIScript::endElement( void *userData, const XML_Char *name )
143 {
144  ( (AIScript*) userData )->endElement( name );
145 }
146 
147 namespace AiXml
148 {
149 enum Names
150 {
155  X,
156  Y,
157  Z,
201 };
202 
204  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
205  EnumMap::Pair( "Float", FFLOAT ),
206  EnumMap::Pair( "Script", SCRIPT ),
207  EnumMap::Pair( "Vector", VECTOR ),
208  EnumMap::Pair( "Moveto", MOVETO ),
209  EnumMap::Pair( "Default", DEFAULT ),
210  EnumMap::Pair( "Targetworld", TARGETWORLD ),
211  EnumMap::Pair( "Yourworld", YOURWORLD ),
212  EnumMap::Pair( "Targetlocal", TARGETLOCAL ),
213  EnumMap::Pair( "Yourlocal", YOURLOCAL ),
214  EnumMap::Pair( "FaceTarget", FACETARGET ),
215  EnumMap::Pair( "CloakFor", CLOAKFOR ),
216  EnumMap::Pair( "ExecuteFor", EXECUTEFOR ),
217  EnumMap::Pair( "ChangeHead", CHANGEHEAD ),
218  EnumMap::Pair( "MatchLin", MATCHLIN ),
219  EnumMap::Pair( "MatchAng", MATCHANG ),
220  EnumMap::Pair( "MatchVel", MATCHVEL ),
221  EnumMap::Pair( "Angular", ANGULAR ),
222  EnumMap::Pair( "Add", ADD ),
223  EnumMap::Pair( "Neg", NEG ),
224  EnumMap::Pair( "Sub", SUB ),
225  EnumMap::Pair( "Normalize", NORMALIZE ),
226  EnumMap::Pair( "Scale", SCALE ),
227  EnumMap::Pair( "Cross", CROSS ),
228  EnumMap::Pair( "Dot", DOT ),
229  EnumMap::Pair( "Multf", MULTF ),
230  EnumMap::Pair( "Addf", ADDF ),
231  EnumMap::Pair( "Fromf", FROMF ),
232  EnumMap::Pair( "Tof", TOF ),
233  EnumMap::Pair( "Linear", LINEAR ),
234  EnumMap::Pair( "Threatworld", THREATWORLD ),
235  EnumMap::Pair( "Threatlocal", THREATLOCAL )
236 };
238  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
239  EnumMap::Pair( "accuracy", ACCURACY ),
240  EnumMap::Pair( "x", X ),
241  EnumMap::Pair( "y", Y ),
242  EnumMap::Pair( "z", Z ),
243  EnumMap::Pair( "Time", TIME ),
244  EnumMap::Pair( "Terminate", TERMINATE ),
245  EnumMap::Pair( "Local", LOCAL ),
246  EnumMap::Pair( "Value", VALUE ),
247  EnumMap::Pair( "ITTS", ITTTS ),
248  EnumMap::Pair( "Afterburn", AFTERBURN ),
249  EnumMap::Pair( "Position", YOURPOS ),
250  EnumMap::Pair( "TargetPos", TARGETPOS ),
251  EnumMap::Pair( "ThreatPos", THREATPOS ),
252  EnumMap::Pair( "Velocity", YOURV ),
253  EnumMap::Pair( "TargetV", TARGETV ),
254  EnumMap::Pair( "ThreatV", THREATV ),
255  EnumMap::Pair( "SimlationAtom", SIMATOM ),
256  EnumMap::Pair( "Dup", DUPLIC )
257 };
258 
259 const EnumMap element_map( element_names, 32 );
261 }
262 
263 using XMLSupport::EnumMap;
266 
267 void AIScript::beginElement( const string &name, const AttributeList &attributes )
268 {
269  using namespace AiXml;
270  xml->itts = false;
271  Unit *tmp;
272 #ifdef AIDBG
273  VSFileSystem::vs_fprintf( stderr, "0" );
274 #endif
275  Names elem = (Names) element_map.lookup( name );
276 #ifdef AIDBG
277  VSFileSystem::vs_fprintf( stderr, "1%x ", &elem );
278 #endif
279  AttributeList::const_iterator iter;
280  switch (elem)
281  {
282  case DEFAULT:
283  xml->unitlevel += 2; //pretend it's at a reasonable level
284  break;
285  case UNKNOWN:
286  xml->unitlevel++;
287  return;
288  case SCRIPT:
289  xml->unitlevel++;
290  break;
291  case LINEAR:
292  xml->lin = 1;
293  case ANGULAR:
294  case VECTOR:
295  xml->unitlevel++;
296  xml->vectors.push( QVector( 0, 0, 0 ) );
297  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
298  switch ( attribute_map.lookup( (*iter).name ) )
299  {
300  case X:
301  topv().i = parse_float( (*iter).value );
302  break;
303  case Y:
304  topv().j = parse_float( (*iter).value );
305  break;
306  case Z:
307  topv().k = parse_float( (*iter).value );
308  break;
309  case DUPLIC:
310 #ifdef AIDBG
311  VSFileSystem::vs_fprintf( stderr, "1%x ", &elem );
312 #endif
313  xml->vectors.pop(); //get rid of dummy vector pushed on above
314  xml->vectors.push( xml->vectors.top() );
315  break;
316  case THREATPOS:
317  if ( ( tmp = this->parent->Threat() ) ) {
318  topv() = ( tmp->Position() );
319  } else {
320  if ( ( tmp = this->parent->Target() ) )
321  topv() = ( tmp->Position() );
322  else
323  topv() = (xml->defaultvec);
324  }
325  break;
326  case TARGETPOS:
327  if ( ( tmp = this->parent->Target() ) )
328  topv() = ( tmp->Position() );
329  else
330  topv() = (xml->defaultvec);
331  break;
332 
333  case YOURPOS:
334  topv() = ( this->parent->Position() );
335  break;
336 
337  case THREATV:
338  if ( ( tmp = this->parent->Threat() ) ) {
339  topv() = ( tmp->GetVelocity() );
340  } else {
341  if ( ( tmp = this->parent->Target() ) )
342  topv() = ( tmp->GetVelocity() );
343  else
344  topv() = (xml->defaultvec);
345  }
346  break;
347  case TARGETV:
348  if ( ( tmp = this->parent->Target() ) )
349  topv() = ( tmp->GetVelocity() );
350  else
351  topv() = (xml->defaultvec);
352  break;
353 
354  case YOURV:
355  topv() = ( this->parent->GetVelocity() );
356  break;
357  }
358  }
359  break;
360  case MOVETO:
361  xml->unitlevel++;
362  xml->acc = 2;
363  xml->afterburn = true;
364  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
365  switch ( attribute_map.lookup( (*iter).name ) )
366  {
367  case AFTERBURN:
368  xml->afterburn = parse_bool( (*iter).value );
369  case ACCURACY:
370  xml->acc = parse_int( (*iter).value );
371  break;
372  }
373  }
374  break;
375  case FACETARGET:
376 #ifdef AIDBG
377  VSFileSystem::vs_fprintf( stderr, "ft" );
378 #endif
379  xml->unitlevel++;
380  xml->acc = 3;
381  xml->itts = false;
382  xml->afterburn = true;
383  xml->terminate = true;
384  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
385  switch ( attribute_map.lookup( (*iter).name ) )
386  {
387  case TERMINATE:
388  xml->terminate = parse_bool( (*iter).value );
389  break;
390  case ACCURACY:
391  xml->acc = parse_int( (*iter).value );
392  break;
393  case ITTTS:
394  xml->itts = parse_bool( (*iter).value );
395  break;
396  }
397  }
398 #ifdef AIDBG
399  VSFileSystem::vs_fprintf( stderr, "eft" );
400 #endif
401 
402  break;
403 
404  case CHANGEHEAD:
405  xml->unitlevel++;
406  xml->acc = 2;
407  xml->afterburn = true;
408  xml->terminate = true;
409  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
410  switch ( attribute_map.lookup( (*iter).name ) )
411  {
412  case TERMINATE:
413  xml->terminate = parse_bool( (*iter).value );
414  break;
415  case ACCURACY:
416  xml->acc = parse_int( (*iter).value );
417  break;
418  }
419  }
420  break;
421  case YOURPOS:
422  xml->unitlevel++;
423  xml->vectors.push( this->parent->Position() );
424 
425  break;
426  case THREATWORLD:
427  xml->unitlevel++;
428  break;
429  case TARGETWORLD:
430  xml->unitlevel++;
431  break;
432  case THREATLOCAL:
433  xml->unitlevel++;
434  break;
435  case TARGETLOCAL:
436  xml->unitlevel++;
437  break;
438  case YOURLOCAL:
439  xml->unitlevel++;
440  break;
441  case YOURWORLD:
442  xml->unitlevel++;
443  break;
444 
445  case NORMALIZE:
446  case SCALE:
447  case CROSS:
448  case DOT:
449  case MULTF:
450  case ADDF:
451  case FROMF:
452  case TOF:
453  case ADD:
454  case SUB:
455  case NEG:
456  xml->unitlevel++;
457  break;
458 
459  case FFLOAT:
460  xml->unitlevel++;
461  xml->floats.push( 0 );
462  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
463  switch ( attribute_map.lookup( (*iter).name ) )
464  {
465  case VALUE:
466  topf() = parse_float( (*iter).value );
467  break;
468  case SIMATOM:
469  topf() = SIMULATION_ATOM;
470  case DUPLIC:
471  xml->floats.pop(); //get rid of dummy vector pushed on above
472  xml->floats.push( xml->floats.top() );
473  break;
474  }
475  }
476  break;
477  case MATCHLIN:
478  case MATCHANG:
479  case MATCHVEL:
480 #ifdef AIDBG
481  VSFileSystem::vs_fprintf( stderr, "mlv" );
482 #endif
483 
484  xml->unitlevel++;
485  xml->acc = 0;
486  xml->afterburn = false;
487  xml->terminate = true;
488  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
489  switch ( attribute_map.lookup( (*iter).name ) )
490  {
491  case AFTERBURN:
492  xml->afterburn = parse_bool( (*iter).value );
493  break;
494  case TERMINATE:
495  xml->terminate = parse_bool( (*iter).value );
496  break;
497  case LOCAL:
498  xml->acc = parse_bool( (*iter).value );
499  break;
500  }
501  }
502 #ifdef AIDBG
503  VSFileSystem::vs_fprintf( stderr, "emlv " );
504 #endif
505 
506  break;
507  case CLOAKFOR:
508  xml->unitlevel++;
509  xml->executefor.push_back( 0 );
510  xml->terminate = true;
511  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
512  switch ( attribute_map.lookup( (*iter).name ) )
513  {
514  case TERMINATE:
515  xml->terminate = parse_bool( (*iter).value );
516  break;
517  case TIME:
518  xml->executefor.back() = parse_float( (*iter).value );
519  break;
520  }
521  }
522  break;
523  case EXECUTEFOR:
524  xml->unitlevel++;
525  xml->executefor.push_back( 0 );
526  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
527  switch ( attribute_map.lookup( (*iter).name ) )
528  {
529  case TIME:
530  xml->executefor.back() = parse_float( (*iter).value );
531  break;
532  }
533  }
534  break;
535 
536  default:
537 
538  break;
539  }
540 }
541 
542 void AIScript::endElement( const string &name )
543 {
544  using namespace AiXml;
545  QVector temp( 0, 0, 0 );
546  Names elem = (Names) element_map.lookup( name );
547  Unit *tmp;
548  switch (elem)
549  {
550  case UNKNOWN:
551  xml->unitlevel--;
552  break;
553  //Vector
554  case THREATWORLD:
555  xml->unitlevel++;
556  if ( ( tmp = parent->Threat() ) ) {
557  xml->vectors.push( tmp->ToWorldCoordinates( topv() ) );
558  } else {
559  if ( ( tmp = parent->Target() ) )
560  xml->vectors.push( tmp->ToWorldCoordinates( topv() ) );
561  else
562  xml->vectors.push( xml->defaultvec );
563  }
564  break;
565  case THREATLOCAL:
566  xml->unitlevel++;
567  if ( ( tmp = parent->Threat() ) ) {
568  xml->vectors.push( tmp->ToLocalCoordinates( topv() ) );
569  } else {
570  if ( ( tmp = parent->Target() ) )
571  xml->vectors.push( tmp->ToLocalCoordinates( topv() ) );
572  else
573  xml->vectors.push( xml->defaultvec );
574  }
575  break;
576 
577  case TARGETWORLD:
578  xml->unitlevel++;
579  if ( ( tmp = parent->Target() ) )
580  xml->vectors.push( tmp->ToWorldCoordinates( topv() ) );
581  else
582  xml->vectors.push( xml->defaultvec );
583  break;
584  case TARGETLOCAL:
585  xml->unitlevel++;
586  if ( ( tmp = parent->Target() ) )
587  xml->vectors.push( tmp->ToLocalCoordinates( topv() ) );
588  else
589  xml->vectors.push( xml->defaultvec );
590  break;
591  case YOURLOCAL:
592  xml->unitlevel++;
593  xml->vectors.push( this->parent->ToLocalCoordinates( topv() ) );
594  break;
595  case YOURWORLD:
596  xml->unitlevel++;
597  xml->vectors.push( this->parent->ToWorldCoordinates( topv() ) );
598  break;
599 
600  case NORMALIZE:
601  xml->unitlevel--;
602  if (topv().i || topv().j || topv().k)
603  topv().Normalize();
604  break;
605  case SCALE:
606  xml->unitlevel--;
607  topv() *= topf();
608  popf();
609  break;
610  case CROSS:
611  xml->unitlevel--;
612  temp = topv();
613  popv();
614  topv() = CrossProduct( topv(), temp );
615  break;
616  case DOT:
617  xml->unitlevel--;
618  xml->floats.push( 0 );
619  temp = topv();
620  popv();
621  topf() = DotProduct( topv(), temp );
622  popv();
623  break;
624  case MULTF:
625  xml->unitlevel--;
626  temp.i = topf();
627  popf();
628  topf() *= temp.i;
629  break;
630  case ADDF:
631  xml->unitlevel--;
632  temp.i = topf();
633  popf();
634  topf() += temp.i;
635  break;
636  case FROMF:
637  xml->unitlevel--;
638  temp.i = topf();
639  popf();
640  temp.j = topf();
641  popf();
642  xml->vectors.push( QVector( temp.i, temp.j, topf() ) );
643  popf();
644  break;
645  case TOF:
646  xml->unitlevel--;
647  xml->floats.push( topv().i );
648  xml->floats.push( topv().j );
649  xml->floats.push( topv().k );
650  popv();
651  break;
652  case ADD:
653  xml->unitlevel--;
654  temp = topv();
655  popv();
656  topv() += temp;
657  break;
658  case SUB:
659  xml->unitlevel--;
660  temp = topv();
661  popv();
662  topv() = topv()-temp;
663  break;
664  case NEG:
665  xml->unitlevel--;
666  topv() = -topv();
667  break;
668  case MOVETO:
669  VSFileSystem::vs_fprintf( stderr, "Moveto <%f,%f,%f>", topv().i, topv().j, topv().k );
670  xml->unitlevel--;
671  xml->orders.push_back( new Orders::MoveTo( topv(), xml->afterburn, xml->acc ) );
672  popv();
673  break;
674  case CHANGEHEAD:
675  xml->unitlevel--;
676  xml->orders.push_back( new Orders::ChangeHeading( topv(), xml->acc ) );
677  popv();
678  break;
679  case MATCHANG:
680  xml->unitlevel--;
681  xml->orders.push_back( new Orders::MatchAngularVelocity( parent->ClampAngVel( topv() ), ( (bool) xml->acc ),
682  xml->terminate ) );
683  popv();
684  break;
685  case FACETARGET:
686  xml->unitlevel--;
687  if (xml->itts || parent->GetComputerData().itts)
688  xml->orders.push_back( new Orders::FaceTargetITTS( xml->terminate,
689  (bool) xml->acc ) );
690  else
691  xml->orders.push_back( new Orders::FaceTarget( xml->terminate,
692  (bool) xml->acc ) );
693  break;
694  case MATCHLIN:
695  xml->unitlevel--;
696  xml->orders.push_back( new Orders::MatchLinearVelocity( parent->ClampVelocity( topv(),
697  xml->afterburn ), ( (bool) xml->acc ),
698  xml->afterburn, xml->terminate ) );
699  popv();
700  break;
701  case MATCHVEL:
702  xml->unitlevel--;
703  temp = topv();
704  popv();
705  if (xml->lin == 1) {
706  xml->orders.push_back( new Orders::MatchVelocity( parent->ClampVelocity( topv(),
707  xml->afterburn ),
708  parent->ClampAngVel( temp ), ( (bool) xml->acc ), xml->afterburn,
709  xml->terminate ) );
710  } else {
711  xml->orders.push_back( new Orders::MatchVelocity( parent->ClampVelocity( temp,
712  xml->afterburn ),
713  parent->ClampAngVel( topv() ), ( (bool) xml->acc ),
714  xml->afterburn, xml->terminate ) );
715  }
716  xml->lin = 0;
717  popv();
718  break;
719  case EXECUTEFOR:
720  xml->unitlevel--;
721  if ( !xml->executefor.empty() ) {
722  if (xml->executefor.back() > 0) {
723  xml->orders[xml->orders.size()-1] = new Orders::ExecuteFor( xml->orders[xml->orders.size()-1], xml->executefor.back() );
724  xml->executefor.pop_back();
725  }
726  }
727  break;
728  case CLOAKFOR:
729  xml->unitlevel--;
730  if ( !xml->executefor.empty() ) {
731  xml->orders.push_back( new CloakFor( xml->terminate, xml->executefor.back() ) );
732  xml->executefor.pop_back();
733  }
734  break;
735  case DEFAULT:
736  xml->unitlevel -= 2;
737  xml->defaultvec = topv();
738  popv();
739  xml->defaultf = topf();
740  popf();
741  break;
742  default:
743  xml->unitlevel--;
744  break;
745  }
746 }
747 
748 void AIScript::LoadXML()
749 {
750  static int aidebug = XMLSupport::parse_int( vs_config->getVariable( "AI", "debug_level", "0" ) );
751  using namespace AiXml;
752  using namespace VSFileSystem;
753  string full_filename = filename;
754  bool doroll = false;
755  HardCodedMap::const_iterator iter = hard_coded_scripts.find( full_filename );
756  if (iter==hard_coded_scripts.end() && full_filename.length() > 5 && full_filename[0] == 'r' && full_filename[1] == 'o' && full_filename[2] == 'l'
757  && full_filename[3] == 'l' && full_filename[4] == ' ') {
758  doroll = true;
759  full_filename = full_filename.substr( 5 );
760  iter = hard_coded_scripts.find( full_filename );
761  }
762  if ( iter != hard_coded_scripts.end() ) {
763  CCScript *myscript = (*iter).second;
764  (*myscript)(this, parent);
765  if (doroll) {
766  unsigned int val = rand();
767  if (val < RAND_MAX/4)
768  RollRightHard( this, parent );
769  else if (val < RAND_MAX/2)
770  RollLeftHard( this, parent );
771  else
772  RollLeft( this, parent );
773  }
774  if (aidebug > 1) {
775  VSFileSystem::vs_fprintf( stderr, "%f using hcs %s for %s threat %f\n",
776  mission->getGametime(), filename, parent->name.get().c_str(),
778  }
779  if ( _Universe->isPlayerStarship( parent->Target() ) ) {
780  float value;
781  static float game_speed = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_speed", "1" ) );
782  static float game_accel = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_accel", "1" ) );
783  {
784  Unit *targ = parent->Target();
785  if (targ) {
786  Vector PosDifference = ( targ->Position()-parent->Position() ).Cast();
787  float pdmag = PosDifference.Magnitude();
788  value = ( pdmag-parent->rSize()-targ->rSize() );
789  float myvel = pdmag > 0 ? PosDifference.Dot( parent->GetVelocity()-targ->GetVelocity() )/pdmag : 0;
790  if (myvel > 0)
791  value -= myvel*myvel/( 2*( parent->Limits().retro/parent->GetMass() ) );
792  } else {
793  value = 10000;
794  }
795  value /= game_speed*game_accel;
796  }
797  if (aidebug > 0) {
798  UniverseUtil::IOmessage( 0, parent->name, "all", string( "using script " )+string(
799  filename )+" threat "+XMLSupport::tostring(
800  parent->GetComputerData().threatlevel )+" dis "
801  +XMLSupport::tostring( value ) );
802  }
803  }
804  return;
805  } else {
806  if (aidebug > 1)
807  VSFileSystem::vs_fprintf( stderr, "using soft coded script %s", filename );
808  if (aidebug > 0)
809  UniverseUtil::IOmessage( 0, parent->name, "all", string( "FAILED(or missile) script " )+string(
810  filename )+" threat "+XMLSupport::tostring( parent->GetComputerData().threatlevel ) );
811  }
812 #ifdef AIDBG
813  VSFileSystem::vs_fprintf( stderr, "chd" );
814 #endif
815 
816 #ifdef AIDBG
817  VSFileSystem::vs_fprintf( stderr, "echd" );
818 #endif
819  VSFile f;
820  VSError err = f.OpenReadOnly( filename, AiFile );
821 #ifdef AIDBG
822  VSFileSystem::vs_fprintf( stderr, "backup " );
823 #endif
824  if (err > Ok) {
825  VSFileSystem::vs_fprintf( stderr, "cannot find AI script %s\n", filename );
826  if (hard_coded_scripts.find(filename)!=hard_coded_scripts.end()) {
827  assert(0);
828  }
829  return;
830  }
831 #ifdef BIDBG
832  VSFileSystem::vs_fprintf( stderr, "nxml" );
833 #endif
834  xml = new AIScriptXML;
835  xml->unitlevel = 0;
836  xml->terminate = true;
837  xml->afterburn = true;
838  xml->acc = 2;
839  xml->defaultvec = QVector( 0, 0, 0 );
840  xml->defaultf = 0;
841 #ifdef BIDBG
842  VSFileSystem::vs_fprintf( stderr, "parscrea" );
843 #endif
844  XML_Parser parser = XML_ParserCreate( NULL );
845 #ifdef BIDBG
846  VSFileSystem::vs_fprintf( stderr, "usdat %x", parser );
847 #endif
848  XML_SetUserData( parser, this );
849 #ifdef BIDBG
850  VSFileSystem::vs_fprintf( stderr, "elha" );
851 #endif
852  XML_SetElementHandler( parser, &AIScript::beginElement, &AIScript::endElement );
853 #ifdef BIDBG
854  VSFileSystem::vs_fprintf( stderr, "do" );
855 #endif
856  XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 );
857 #ifdef BIDBG
858  VSFileSystem::vs_fprintf( stderr, "%xxml_free", parser );
859  fflush( stderr );
860 #endif
861  XML_ParserFree( parser );
862 #ifdef BIDBG
863  VSFileSystem::vs_fprintf( stderr, "xml_freed" );
864 #endif
865  f.Close();
866  for (unsigned int i = 0; i < xml->orders.size(); i++) {
867 #ifdef BIDBG
868  VSFileSystem::vs_fprintf( stderr, "parset" );
869 #endif
870  xml->orders[i]->SetParent( parent );
871  EnqueueOrder( xml->orders[i] );
872 #ifdef BIDBG
873  VSFileSystem::vs_fprintf( stderr, "cachunkx" );
874 #endif
875  }
876 #ifdef BIDBG
877  VSFileSystem::vs_fprintf( stderr, "xml%x", xml );
878  fflush( stderr );
879 #endif
880  delete xml;
881 #ifdef BIDBG
882  VSFileSystem::vs_fprintf( stderr, "\\xml\n" );
883  fflush( stderr );
884 #endif
885 }
886 
887 AIScript::AIScript( const char *scriptname ) : Order( Order::MOVEMENT|Order::FACING, STARGET )
888 {
889  filename = new char[strlen( scriptname )+1];
890  strcpy( filename, scriptname );
891 }
892 
894 {
895 #ifdef ORDERDEBUG
896  VSFileSystem::vs_fprintf( stderr, "sc%x", this );
897  fflush( stderr );
898 #endif
899  if (filename)
900  delete[] filename;
901 #ifdef ORDERDEBUG
902  VSFileSystem::vs_fprintf( stderr, "sc\n" );
903  fflush( stderr );
904 #endif
905 }
906 
908 {
909  if (filename) {
910  LoadXML();
911 #ifdef ORDERDEBUG
912  VSFileSystem::vs_fprintf( stderr, "fn%x", this );
913  fflush( stderr );
914 #endif
915  delete[] filename;
916  filename = NULL;
917 #ifdef ORDERDEBUG
918  VSFileSystem::vs_fprintf( stderr, "fn" );
919  fflush( stderr );
920 #endif
921  }
922  Order::Execute();
923 }
924