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_call_unit_generic.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * xml Mission Scripting written by Alexander Rawass <alexannika@users.sourceforge.net>
24  */
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <time.h>
30 #include <ctype.h>
31 #include <assert.h>
32 #ifndef WIN32
33 //this file isn't available on my system (all win32 machines?) i dun even know what it has or if we need it as I can compile without it
34 #include <unistd.h>
35 #endif
36 #include "cmd/unit_generic.h"
37 #include "cmd/unit_factory.h"
38 #include <expat.h>
39 #include "xml_support.h"
40 
41 #include "vegastrike.h"
42 #include "cmd/collection.h"
43 #include "cmd/planet_generic.h"
44 #include "cmd/ai/order.h"
45 #include "cmd/ai/aggressive.h"
46 #include "cmd/ai/missionscript.h"
47 #include "mission.h"
48 #include "easydom.h"
49 #include "msgcenter.h"
50 #include "flightgroup.h"
51 #include "vs_globals.h"
52 #include "configxml.h"
53 #include "gfx/cockpit_generic.h"
54 #include "cmd/images.h"
55 #include "savegame.h"
56 #include "cmd/nebula_generic.h"
57 #include "hashtable.h"
58 #include "flightgroup.h"
59 #include "cmd/unit_factory.h"
60 #include "cmd/asteroid_generic.h"
61 #include "gfxlib.h"
62 #include "cmd/pilot.h"
63 
64 extern const vector< string >& ParseDestinations( const string &value );
65 extern Unit& GetUnitMasterPartList();
66 extern bool PlanetHasLights( Unit *un );
67 
68 #if 0
69 NEVER NEVER NEVER use Unit*to save a unit across frames
70 extern Unit *player_unit;
71 BAD BAD BAD
72 
73 Better:
74 extern UnitContainer player_unit;
75 
76 Best:
78 #endif
79 
80 static Unit * getIthUnit( un_iter uiter, int i );
81 
82 varInst* Mission::call_unit( missionNode *node, int mode )
83 {
84 #ifdef ORDERDEBUG
85  VSFileSystem::vs_fprintf( stderr, "callun%x", this );
86  fflush( stderr );
87 #endif
88  varInst *viret = NULL;
89  trace( node, mode );
90  if (mode == SCRIPT_PARSE) {
91  string cmd = node->attr_value( "name" );
92  node->script.method_id = module_unit_map[cmd];
93  }
95  if (method_id == CMT_UNIT_getUnit) {
96  missionNode *nr_node = getArgument( node, mode, 0 );
97  int unit_nr = doIntVar( nr_node, mode );
98  Unit *my_unit = NULL;
99  if (mode == SCRIPT_RUN) {
100  StarSystem *ssystem = _Universe->scriptStarSystem();
101  un_iter uiter = ssystem->getUnitList().createIterator();
102  my_unit = getIthUnit( uiter, unit_nr );
103  }
104  viret = newVarInst( VI_TEMP );
105  viret->type = VAR_OBJECT;
106  viret->objectname = "unit";
107  viret->object = (void*) my_unit;
108  debug( 3, node, mode, "unit getUnit: " );
109  printVarInst( 3, viret );
110  return viret;
111  } else if (method_id == CMT_UNIT_getPlayer) {
112  Unit *my_unit = NULL;
113  if (mode == SCRIPT_RUN)
114  my_unit = _Universe->AccessCockpit()->GetParent();
115  viret = newVarInst( VI_TEMP );
116  viret->type = VAR_OBJECT;
117  viret->objectname = "unit";
118  viret->object = (void*) my_unit;
119  debug( 3, node, mode, "unit getUnit: " );
120  printVarInst( 3, viret );
121  return viret;
122  } else if (method_id == CMT_UNIT_getPlayerX) {
123  int which = getIntArg( node, mode, 0 );
124  Unit *my_unit = NULL;
125  if (mode == SCRIPT_RUN) {
126  int j = 0;
127  for (unsigned int i = 0; i < _Universe->numPlayers(); ++i) {
128  Unit *un;
129  if ( NULL != ( un = _Universe->AccessCockpit( i )->GetParent() ) ) {
130  if (j == which) {
131  my_unit = un;
132  break;
133  }
134  j++;
135  }
136  }
137  }
138  viret = newVarInst( VI_TEMP );
139  viret->type = VAR_OBJECT;
140  viret->objectname = "unit";
141  viret->object = (void*) my_unit;
142  debug( 3, node, mode, "unit getUnit: " );
143  printVarInst( 3, viret );
144  return viret;
145  } else if (method_id == CMT_UNIT_launch || method_id == CMT_UNIT_launchNebula || method_id == CMT_UNIT_launchPlanet
146  || method_id == CMT_UNIT_launchJumppoint) {
147  missionNode *name_node = getArgument( node, mode, 0 );
148  varInst *name_vi = checkObjectExpr( name_node, mode );
149  missionNode *faction_node = getArgument( node, mode, 1 );
150  varInst *faction_vi = checkObjectExpr( faction_node, mode );
151  missionNode *type_node = getArgument( node, mode, 2 );
152  varInst *type_vi = checkObjectExpr( type_node, mode );
153  missionNode *ai_node = getArgument( node, mode, 3 );
154  varInst *ai_vi = checkObjectExpr( ai_node, mode );
155  missionNode *nr_node = getArgument( node, mode, 4 );
156  int nr_of_ships = checkIntExpr( nr_node, mode );
157  missionNode *nrw_node = getArgument( node, mode, 5 );
158  int nr_of_waves = checkIntExpr( nrw_node, mode );
159  varInst *destination_vi;
160  string destinations;
161  string logo_tex;
162  string logo_alp;
163  if (method_id == CMT_UNIT_launchJumppoint) {
164  destination_vi = checkObjectExpr( faction_node, mode );
165  if (mode == SCRIPT_RUN)
166  destinations = *( (string*) destination_vi->object );
167  }
168  QVector pos( getFloatArg( node, mode, 6 ),
169  getFloatArg( node, mode, 7 ),
170  getFloatArg( node, mode, 8 ) );
171  if (node->subnodes.size() > 9) {
172  logo_tex = getStringArgument( node, mode, 9 );
173  if (node->subnodes.size() > 10)
174  logo_alp = getStringArgument( node, mode, 10 );
175  }
176  Unit *my_unit = NULL;
177  if (mode == SCRIPT_RUN) {
178  clsptr clstyp = UNITPTR;
179  if (method_id == CMT_UNIT_launchJumppoint || method_id == CMT_UNIT_launchPlanet)
180  clstyp = PLANETPTR;
181  else if (method_id == CMT_UNIT_launchNebula)
182  clstyp = NEBULAPTR;
183  string name_string = *( (string*) name_vi->object );
184  string faction_string = *( (string*) faction_vi->object );
185  string type_string = *( (string*) type_vi->object );
186  string ai_string = *( (string*) ai_vi->object );
188  cf.fg = Flightgroup::newFlightgroup( name_string,
189  type_string,
190  faction_string,
191  ai_string,
192  nr_of_ships,
193  nr_of_waves,
194  logo_tex,
195  logo_alp,
196  this );
198  cf.terrain_nr = -1;
199  cf.waves = nr_of_waves;
200  cf.nr_ships = nr_of_ships;
201  cf.fg->pos = pos;
202  for (int i = 0; i < 3; i++)
203  cf.rot[i] = 0.0;
204 #ifdef ORDERDEBUG
205  VSFileSystem::vs_fprintf( stderr, "cunl%x", this );
206  fflush( stderr );
207 #endif
208  Unit *tmp = call_unit_launch( &cf, clstyp, destinations );
209  number_of_ships += nr_of_ships;
210  if (!my_unit)
211  my_unit = tmp;
212 #ifdef ORDERDEBUG
213  VSFileSystem::vs_fprintf( stderr, "ecun" );
214  fflush( stderr );
215 #endif
216  }
217  deleteVarInst( name_vi );
218  deleteVarInst( faction_vi );
219  deleteVarInst( type_vi );
220  deleteVarInst( ai_vi );
221  viret = newVarInst( VI_TEMP );
222  viret->type = VAR_OBJECT;
223  viret->objectname = "unit";
224  viret->object = (void*) my_unit;
225  debug( 3, node, mode, "unit getUnit: " );
226  return viret;
227  } else if (method_id == CMT_UNIT_getRandCargo) {
228  int quantity = getIntArg( node, mode, 0 );
229  string category;
230  if (node->subnodes.size() > 1)
231  category = getStringArgument( node, mode, 1 );
232  varInst *vireturn = NULL;
233  vireturn = call_olist_new( node, mode );
234  if (mode == SCRIPT_RUN) {
235  Cargo *ret = NULL;
236  Unit *mpl = &GetUnitMasterPartList();
237  unsigned int max = mpl->numCargo();
238  if ( !category.empty() ) {
239  size_t Begin, End;
240  mpl->GetSortedCargoCat( category, Begin, End );
241  if (Begin < End) {
242  unsigned int i = Begin+( rand()%(End-Begin) );
243  ret = &mpl->GetCargo( i );
244  }
245  } else {
246  if ( mpl->numCargo() ) {
247  for (unsigned int i = 0; i < 500; i++) {
248  ret = &mpl->GetCargo( rand()%max );
249  if (ret->GetContent().find( "mission" ) == string::npos)
250  break;
251  }
252  } else {
253  ret = new Cargo(); //mem leak--won't happen
254  }
255  }
256  if (ret) {
257  ret->quantity = quantity;
258  viret = newVarInst( VI_IN_OBJECT );
259  viret->type = VAR_OBJECT;
260  viret->objectname = "string";
261  viret->object = &ret->content;
262  ( (olist_t*) vireturn->object )->push_back( viret );
263  viret = newVarInst( VI_IN_OBJECT );
264  viret->type = VAR_OBJECT;
265  viret->objectname = "string";
266  viret->object = &ret->category;
267  ( (olist_t*) vireturn->object )->push_back( viret );
268  viret = newVarInst( VI_IN_OBJECT );
269  viret->type = VAR_FLOAT;
270  viret->float_val = ret->price;
271  ( (olist_t*) vireturn->object )->push_back( viret );
272  viret = newVarInst( VI_IN_OBJECT );
273  viret->type = VAR_INT;
274  viret->int_val = quantity;
275  ( (olist_t*) vireturn->object )->push_back( viret );
276  viret = newVarInst( VI_IN_OBJECT );
277  viret->type = VAR_FLOAT;
278  viret->float_val = ret->mass;
279  ( (olist_t*) vireturn->object )->push_back( viret );
280  viret = newVarInst( VI_IN_OBJECT );
281  viret->type = VAR_FLOAT;
282  viret->float_val = ret->volume;
283  ( (olist_t*) vireturn->object )->push_back( viret );
284  }
285  }
286  debug( 3, node, mode, "unit getRandCargo: " );
287  printVarInst( 3, vireturn );
288  return vireturn;
289  } else {
290  varInst *ovi = getObjectArg( node, mode );
291  Unit *my_unit = getUnitObject( node, mode, ovi );
292  debug( 3, node, mode, "unit object: " );
293  printVarInst( 3, ovi );
294  if (method_id == CMT_UNIT_getContainer) {
295  UnitContainer *cont = NULL;
296  if (mode == SCRIPT_RUN)
297  cont = new UnitContainer( my_unit );
298  viret = newVarInst( VI_TEMP );
299  viret->type = VAR_OBJECT;
300  viret->objectname = "unitContainer";
301  viret->object = cont;
302  } else if (method_id == CMT_UNIT_getUnitFromContainer) {
303  Unit *ret = NULL;
304  if (mode == SCRIPT_RUN)
305  ret = ( (UnitContainer*) my_unit )->GetUnit();
306  viret = newVarInst( VI_TEMP );
307  viret->type = VAR_OBJECT;
308  viret->objectname = "unit";
309  viret->object = ret;
310  } else if (method_id == CMT_UNIT_deleteContainer) {
311  UnitContainer *cont = (UnitContainer*) my_unit;
312  if (mode == SCRIPT_RUN)
313  delete cont;
314  viret = newVarInst( VI_TEMP );
315  viret->type = VAR_VOID;
316  } else if (method_id == CMT_UNIT_getPosition) {
317  viret = newVarInst( VI_TEMP );
318  viret->type = VAR_OBJECT;
319  viret->objectname = "olist";
320  if (mode == SCRIPT_RUN) {
321  QVector pos = my_unit->Position();
322 
323  call_vector_into_olist( viret, pos );
324  }
325  } else if (method_id == CMT_UNIT_getFaction) {
326  if (mode == SCRIPT_RUN) {
327  string factionname = FactionUtil::GetFaction( my_unit->faction );
328  varInst *str_vi = call_string_new( node, mode, factionname );
329  viret = str_vi;
330  } else {
331  varInst *str_vi = call_string_new( node, mode, "" );
332  viret = str_vi;
333  }
334  } else if (method_id == CMT_UNIT_getVelocity) {
335  if (mode == SCRIPT_RUN) {
336  varInst *vec3_vi = call_olist_new( node, mode );
337  float vel_mag = my_unit->GetVelocity().Magnitude();
338  Vector pos;
339  printf( "VELMAG:%f\n", vel_mag );
340  if (fabs( vel_mag ) > 10e-6) {
341  pos = my_unit->GetVelocity()/vel_mag;
342  } else {
343  Vector p, q, r;
344 
345  my_unit->GetOrientation( p, q, r );
346  pos = r;
347  }
348  varInst *pos_vi;
349 
350  pos_vi = newVarInst( VI_TEMP );
351  pos_vi->type = VAR_FLOAT;
352  pos_vi->float_val = pos.i;
353  call_olist_push_back( node, mode, vec3_vi, pos_vi );
354 
355  pos_vi = newVarInst( VI_TEMP );
356  pos_vi->type = VAR_FLOAT;
357  pos_vi->float_val = pos.j;
358  call_olist_push_back( node, mode, vec3_vi, pos_vi );
359 
360  pos_vi = newVarInst( VI_TEMP );
361  pos_vi->type = VAR_FLOAT;
362  pos_vi->float_val = pos.k;
363  call_olist_push_back( node, mode, vec3_vi, pos_vi );
364  viret = vec3_vi;
365  } else {
366  viret = newVarInst( VI_TEMP );
367  viret->type = VAR_OBJECT;
368  viret->objectname = "olist";
369  }
370  } else if (method_id == CMT_UNIT_getTarget) {
371  Unit *res_unit = NULL;
372  if (mode == SCRIPT_RUN)
373  res_unit = my_unit->Target();
374  viret = newVarInst( VI_TEMP );
375  viret->type = VAR_OBJECT;
376  viret->objectname = "unit";
377  viret->object = res_unit;
378  } else if (method_id == CMT_UNIT_getName) {
379  if (mode == SCRIPT_RUN) {
380  string unit_name;
381  unit_name = my_unit->name;
382  viret = call_string_new( node, mode, unit_name );
383  } else {
384  viret = newVarInst( VI_TEMP );
385  viret->type = VAR_OBJECT;
386  viret->objectname = "string";
387  }
388  } else if (method_id == CMT_UNIT_setName) {
389  string s = getStringArgument( node, mode, 1 );
390  if (mode == SCRIPT_RUN)
391  my_unit->name = s;
392  viret = newVarInst( VI_TEMP );
393  viret->type = VAR_VOID;
394  } else if (method_id == CMT_UNIT_getThreat) {
395  Unit *res_unit = NULL;
396  if (mode == SCRIPT_RUN)
397  res_unit = my_unit->Threat();
398  viret = newVarInst( VI_TEMP );
399  viret->type = VAR_OBJECT;
400  viret->objectname = "unit";
401  viret->object = res_unit;
402  } else if (method_id == CMT_UNIT_setTarget) {
403  Unit *other_unit = getUnitArg( node, mode, 1 );
404  if (mode == SCRIPT_RUN)
405  my_unit->Target( other_unit );
406  viret = newVarInst( VI_TEMP );
407  viret->type = VAR_VOID;
408  } else if (method_id == CMT_UNIT_equal) {
409  Unit *other_unit = getUnitArg( node, mode, 1 );
410  viret = newVarInst( VI_TEMP );
411  viret->type = VAR_BOOL;
412  viret->bool_val = (my_unit == other_unit); //doesn't dereference anything
413  } else if (method_id == CMT_UNIT_getDistance) {
414  float dist = 0.0;
415  Unit *un = getUnitArg( node, mode, 1 );
416  if (mode == SCRIPT_RUN)
417  dist = ( my_unit->Position()-un->Position() ).Magnitude()-my_unit->rSize()-un->rSize();
418  viret = newVarInst( VI_TEMP );
419  viret->type = VAR_FLOAT;
420  viret->float_val = dist;
421  } else if (method_id == CMT_UNIT_getMinDis) {
422  QVector vec3 = getVec3Arg( node, mode, 1 );
423  double dist = 0.0;
424  if (mode == SCRIPT_RUN)
425  dist = (my_unit->Position()-vec3).Magnitude()-my_unit->rSize();
426  viret = newVarInst( VI_TEMP );
427  viret->type = VAR_FLOAT;
428  viret->float_val = dist;
429  } else if (method_id == CMT_UNIT_getAngle) {
430  Unit *other_unit = getUnitArg( node, mode, 1 );
431  float angle = 0.0;
432  if (mode == SCRIPT_RUN) {
433  Vector p, q, r;
434  QVector vectothem = QVector( other_unit->Position()-my_unit->Position() ).Normalize();
435  my_unit->GetOrientation( p, q, r );
436  angle = acos( vectothem.Dot( r.Cast() ) );
437  angle = (angle/PI)*180.0;
438  }
439  viret = newVarInst( VI_TEMP );
440  viret->type = VAR_FLOAT;
441  viret->float_val = angle;
442  } else if (method_id == CMT_UNIT_getAngleToPos) {
443  QVector other_pos = getVec3Arg( node, mode, 1 );
444  double angle = 0.0;
445  if (mode == SCRIPT_RUN) {
446  Vector p, q, r;
447  QVector vectothem = QVector( other_pos-my_unit->Position() ).Normalize();
448  my_unit->GetOrientation( p, q, r );
449  angle = acos( vectothem.Dot( r.Cast() ) );
450  angle = (angle/PI)*180.0;
451  }
452  viret = newVarInst( VI_TEMP );
453  viret->type = VAR_FLOAT;
454  viret->float_val = angle;
455  } else if (method_id == CMT_UNIT_getFShieldData) {
456  float res = 0.0;
457  if (mode == SCRIPT_RUN)
458  res = my_unit->FShieldData();
459  viret = newVarInst( VI_TEMP );
460  viret->type = VAR_FLOAT;
461  viret->float_val = res;
462  } else if (method_id == CMT_UNIT_getRShieldData) {
463  float res = 0.0;
464  if (mode == SCRIPT_RUN)
465  res = my_unit->RShieldData();
466  viret = newVarInst( VI_TEMP );
467  viret->type = VAR_FLOAT;
468  viret->float_val = res;
469  } else if (method_id == CMT_UNIT_getLShieldData) {
470  float res = 0.0;
471  if (mode == SCRIPT_RUN)
472  res = my_unit->LShieldData();
473  viret = newVarInst( VI_TEMP );
474  viret->type = VAR_FLOAT;
475  viret->float_val = res;
476  } else if (method_id == CMT_UNIT_getBShieldData) {
477  float res = 0.0;
478  if (mode == SCRIPT_RUN)
479  res = my_unit->BShieldData();
480  viret = newVarInst( VI_TEMP );
481  viret->type = VAR_FLOAT;
482  viret->float_val = res;
483  } else if (method_id == CMT_UNIT_getEnergyData) {
484  float res = 0.0;
485  if (mode == SCRIPT_RUN)
486  res = my_unit->EnergyData();
487  viret = newVarInst( VI_TEMP );
488  viret->type = VAR_FLOAT;
489  viret->float_val = res;
490  } else if (method_id == CMT_UNIT_getHullData) {
491  float res = 0.0;
492  if (mode == SCRIPT_RUN)
493  res = my_unit->GetHull();
494  viret = newVarInst( VI_TEMP );
495  viret->type = VAR_FLOAT;
496  viret->float_val = res;
497  } else if (method_id == CMT_UNIT_getRSize) {
498  float res = 0.0;
499  if (mode == SCRIPT_RUN)
500  res = my_unit->rSize();
501  viret = newVarInst( VI_TEMP );
502  viret->type = VAR_FLOAT;
503  viret->float_val = res;
504  } else if (method_id == CMT_UNIT_isStarShip) {
505  bool res = false;
506  if (mode == SCRIPT_RUN)
507  res = my_unit->isStarShip();
508  viret = newVarInst( VI_TEMP );
509  viret->type = VAR_BOOL;
510  viret->bool_val = res;
511  } else if (method_id == CMT_UNIT_isPlanet) {
512  bool res = false;
513  if (mode == SCRIPT_RUN) {
514  res = my_unit->isPlanet();
515  if (res)
516  res = !PlanetHasLights( my_unit );
517  }
518  viret = newVarInst( VI_TEMP );
519  viret->type = VAR_BOOL;
520  viret->bool_val = res;
521  } else if (method_id == CMT_UNIT_isSignificant) {
522  bool res = false;
523  if (mode == SCRIPT_RUN) {
524  clsptr typ = my_unit->isUnit();
525  string s = my_unit->getFlightgroup() ? my_unit->getFlightgroup()->name : "";
526  res =
527  ( typ == PLANETPTR
528  && !PlanetHasLights( my_unit ) ) || typ == ASTEROIDPTR || typ == NEBULAPTR || s == "Base";
529  }
530  viret = newVarInst( VI_TEMP );
531  viret->type = VAR_BOOL;
532  viret->bool_val = res;
533  } else if (method_id == CMT_UNIT_isSun) {
534  bool res = false;
535  if (mode == SCRIPT_RUN) {
536  res = my_unit->isPlanet();
537  if (res)
538  res = PlanetHasLights( my_unit );
539  }
540  viret = newVarInst( VI_TEMP );
541  viret->type = VAR_BOOL;
542  viret->bool_val = res;
543  } else if (method_id == CMT_UNIT_isJumppoint) {
544  bool res = false;
545  if (mode == SCRIPT_RUN)
546  res = my_unit->isJumppoint();
547  viret = newVarInst( VI_TEMP );
548  viret->type = VAR_BOOL;
549  viret->bool_val = res;
550  } else if (method_id == CMT_UNIT_getRelation) {
551  float res = 0.0;
552  Unit *other_unit = getUnitArg( node, mode, 1 );
553  if (mode == SCRIPT_RUN)
554  res = my_unit->getRelation( other_unit );
555  viret = newVarInst( VI_TEMP );
556  viret->type = VAR_FLOAT;
557  viret->float_val = res;
558  } else if (method_id == CMT_UNIT_getCredits) {
559  viret = newVarInst( VI_TEMP );
560  viret->type = VAR_FLOAT;
561  viret->float_val = 0;
562  if (mode == SCRIPT_RUN) {
563  Cockpit *tmp;
564  if ( ( tmp = _Universe->isPlayerStarship( my_unit ) ) )
565  viret->float_val = tmp->credits;
566  }
567  return viret;
568  } else if (method_id == CMT_UNIT_addCredits) {
569  missionNode *nr_node = getArgument( node, mode, 1 );
570  float credits = doFloatVar( nr_node, mode );
571  if (mode == SCRIPT_RUN) {
572  Cockpit *tmp;
573  if ( ( tmp = _Universe->isPlayerStarship( my_unit ) ) )
574  tmp->credits += credits;
575  }
576  viret = newVarInst( VI_TEMP );
577  viret->type = VAR_VOID;
578  return viret;
579  } else if (method_id == CMT_UNIT_Jump) {
580  if (mode == SCRIPT_RUN)
581  my_unit->ActivateJumpDrive();
582  viret = newVarInst( VI_TEMP );
583  viret->type = VAR_VOID;
584  } else if (method_id == CMT_UNIT_getOrientationP) {
585 #if 0
586  //TODO
587  if (mode == SCRIPT_RUN)
588  res = my_unit->FShieldData();
589  viret = newVarInst( VI_TEMP );
590  viret->type = VAR_VOID;
591  viret->float_val = res;
592 #endif
593  } else if (method_id == CMT_UNIT_getOrder) {
594  Order *my_order = NULL;
595  if (mode == SCRIPT_RUN)
596  my_order = my_unit->getAIState();
597  viret = newVarInst( VI_TEMP );
598  viret->type = VAR_OBJECT;
599  viret->objectname = "order";
600  viret->object = (void*) my_order;
601  } else if (method_id == CMT_UNIT_correctStarSystem) {
602  bool ret = false;
603  if (mode == SCRIPT_RUN)
604  ret = my_unit->InCorrectStarSystem( _Universe->activeStarSystem() );
605  viret = newVarInst( VI_TEMP );
606  viret->type = VAR_BOOL;
607  viret->bool_val = ret;
608  } else if (method_id == CMT_UNIT_removeFromGame) {
609  if (mode == SCRIPT_RUN)
610  my_unit->Kill();
611  viret = newVarInst( VI_TEMP );
612  viret->type = VAR_VOID;
613  } else if (method_id == CMT_UNIT_getFgName) {
614  if (mode == SCRIPT_RUN) {
615  string fgname;
616  Flightgroup *fg = my_unit->getFlightgroup();
617  if (fg)
618  fgname = fg->name;
619  if ( fgname.empty() )
620  fgname = "-none-";
621  varInst *str_vi = call_string_new( node, mode, fgname );
622  viret = str_vi;
623  } else {
624  viret = newVarInst( VI_TEMP );
625  viret->type = VAR_OBJECT;
626  viret->objectname = "string";
627  }
628  } else if (method_id == CMT_UNIT_getFgLeader) {
629  Unit *ret_unit = NULL;
630  if (mode == SCRIPT_RUN) {
631  ret_unit = (my_unit->getFlightgroup() != NULL) ? my_unit->getFlightgroup()->leader.GetUnit() : my_unit;
632  if (ret_unit == NULL)
633  ret_unit = my_unit;
634  }
635  viret = newVarInst( VI_TEMP );
636  viret->type = VAR_OBJECT;
637  viret->objectname = "unit";
638  viret->object = (void*) ret_unit;
639  } else if (method_id == CMT_UNIT_setFgLeader) {
640  Unit *un = getUnitArg( node, mode, 1 );
641  if (mode == SCRIPT_RUN)
642  if (my_unit->getFlightgroup() != NULL)
643  my_unit->getFlightgroup()->leader.SetUnit( un );
644  viret = newVarInst( VI_TEMP );
645  viret->type = VAR_VOID;
646  } else if (method_id == CMT_UNIT_getFgDirective) {
647  string fgdir( "b" );
648  if (mode == SCRIPT_RUN)
649  fgdir = (my_unit->getFlightgroup() != NULL) ? my_unit->getFlightgroup()->directive : string( "b" );
650  viret = call_string_new( node, mode, fgdir );
651  } else if (method_id == CMT_UNIT_setFgDirective) {
652  string inp = getStringArgument( node, mode, 1 );
653  if (mode == SCRIPT_RUN)
654  if (my_unit->getFlightgroup() != NULL)
655  my_unit->getFlightgroup()->directive = inp;
656  viret = newVarInst( VI_TEMP );
657  viret->type = VAR_VOID;
658  } else if (method_id == CMT_UNIT_getFgSubnumber) {
659  int num = 0;
660  if (mode == SCRIPT_RUN)
661  num = my_unit->getFgSubnumber();
662  viret = newVarInst( VI_TEMP );
663  viret->type = VAR_INT;
664  viret->int_val = num;
665  } else if (method_id == CMT_UNIT_scanSystem) {
666  if (mode == SCRIPT_RUN)
667  assert( 0 );
668  viret = newVarInst( VI_TEMP );
669  viret->type = VAR_VOID;
670  } else if (method_id == CMT_UNIT_scannerNearestEnemy) {
671  Unit *ret_unit = NULL;
672  if (mode == SCRIPT_RUN)
673  assert( 0 );
674  viret = newVarInst( VI_TEMP );
675  viret->type = VAR_OBJECT;
676  viret->objectname = "unit";
677  viret->object = (void*) ret_unit;
678  } else if (method_id == CMT_UNIT_scannerNearestFriend) {
679  Unit *ret_unit = NULL;
680  if (mode == SCRIPT_RUN)
681  assert( 0 );
682  viret = newVarInst( VI_TEMP );
683  viret->type = VAR_OBJECT;
684  viret->objectname = "unit";
685  viret->object = (void*) ret_unit;
686  } else if (method_id == CMT_UNIT_scannerNearestShip) {
687  Unit *ret_unit = NULL;
688  if (mode == SCRIPT_RUN)
689  assert( 0 );
690  viret = newVarInst( VI_TEMP );
691  viret->type = VAR_OBJECT;
692  viret->objectname = "unit";
693  viret->object = (void*) ret_unit;
694  } else if (method_id == CMT_UNIT_scannerLeader) {
695  Unit *ret_unit = NULL;
696  if (mode == SCRIPT_RUN)
697  assert( 0 );
698  viret = newVarInst( VI_TEMP );
699  viret->type = VAR_OBJECT;
700  viret->objectname = "unit";
701  viret->object = (void*) ret_unit;
702  } else if (method_id == CMT_UNIT_scannerNearestEnemyDist) {
703  float ret = 9999999.0;
704  if (mode == SCRIPT_RUN)
705  assert( 0 );
706  viret = newVarInst( VI_TEMP );
707  viret->type = VAR_FLOAT;
708  viret->float_val = ret;
709  } else if (method_id == CMT_UNIT_scannerNearestFriendDist) {
710  float ret = 9999999.0;
711  if (mode == SCRIPT_RUN)
712  assert( 0 );
713  viret = newVarInst( VI_TEMP );
714  viret->type = VAR_FLOAT;
715  viret->float_val = ret;
716  } else if (method_id == CMT_UNIT_scannerNearestShipDist) {
717  float ret = 9999999.0;
718  if (mode == SCRIPT_RUN)
719  assert( 0 );
720  viret = newVarInst( VI_TEMP );
721  viret->type = VAR_FLOAT;
722  viret->float_val = ret;
723  } else if (method_id == CMT_UNIT_getTurret) {
724  missionNode *nr_node = getArgument( node, mode, 1 );
725  int unit_nr = doIntVar( nr_node, mode );
726  Unit *turret_unit = NULL;
727  if (mode == SCRIPT_RUN) {
728  un_iter uiter = my_unit->getSubUnits();
729  turret_unit = getIthUnit( uiter, unit_nr );
730  }
731  viret = newVarInst( VI_TEMP );
732  viret->type = VAR_OBJECT;
733  viret->objectname = "unit";
734  viret->object = (void*) turret_unit;
735  debug( 3, node, mode, "unit getUnit: " );
736  printVarInst( 3, viret );
737  } else if (method_id == CMT_UNIT_getFgId) {
738  if (mode == SCRIPT_RUN) {
739  string fgname = my_unit->getFgID();
740  if ( fgname.empty() )
741  fgname = "-unknown";
742  varInst *str_vi = call_string_new( node, mode, fgname );
743 
744  viret = str_vi;
745  } else {
746  viret = newVarInst( VI_TEMP );
747  viret->type = VAR_OBJECT;
748  viret->objectname = "string";
749  }
750  } else if (method_id == CMT_UNIT_removeCargo) {
751  string s = getStringArgument( node, mode, 1 );
752 
753  int quantity = getIntArg( node, mode, 2 );
754  bool erasezero = getBoolArg( node, mode, 3 );
755  if (mode == SCRIPT_RUN) {
756  unsigned int index;
757  if ( my_unit->GetCargo( s, index ) )
758  quantity = my_unit->RemoveCargo( index, quantity, erasezero );
759  else
760  quantity = 0;
761  }
762  viret = newVarInst( VI_TEMP );
763  viret->type = VAR_INT;
764  viret->int_val = quantity;
765  } else if (method_id == CMT_UNIT_addCargo) {
766  Cargo carg;
767  carg.content = getStringArgument( node, mode, 1 );
768  carg.category = getStringArgument( node, mode, 2 );
769  carg.price = getFloatArg( node, mode, 3 );
770  carg.quantity = getIntArg( node, mode, 4 );
771  carg.mass = getFloatArg( node, mode, 5 );
772  carg.volume = getFloatArg( node, mode, 6 );
773  if (mode == SCRIPT_RUN) {
774  int i;
775  for (i = carg.quantity; i > 0 && !my_unit->CanAddCargo( carg ); i--)
776  carg.quantity = i;
777  if (i > 0) {
778  carg.quantity = i;
779  my_unit->AddCargo( carg );
780  } else {
781  carg.quantity = 0;
782  }
783  }
784  viret = newVarInst( VI_TEMP );
785  viret->type = VAR_INT;
786  viret->int_val = carg.quantity;
787  } else if (method_id == CMT_UNIT_setPosition) {
788  double x = getFloatArg( node, mode, 1 );
789  double y = getFloatArg( node, mode, 2 );
790  double z = getFloatArg( node, mode, 3 );
791  if (mode == SCRIPT_RUN)
792  my_unit->SetCurPosition( QVector( x, y, z ) );
793  viret = newVarInst( VI_TEMP );
794  viret->type = VAR_VOID;
795  } else if (method_id == CMT_UNIT_upgrade) {
796  string file = getStringArgument( node, mode, 1 );
797  double percentage = 0;
798  bool force = true;
799  bool loop_through_mounts = false;
800  int mountoffset = getIntArg( node, mode, 2 );
801  int subunitoffset = getIntArg( node, mode, 3 );
802  unsigned int siz = node->subnodes.size();
803  if (siz > 4) {
804  force = getBoolArg( node, mode, 4 );
805  if (siz > 5)
806  loop_through_mounts = getBoolArg( node, mode, 5 );
807  }
808  if (mode == SCRIPT_RUN) {
809  printf( "upgrading %s %s %d %d %s\n", my_unit->name.get().c_str(),
810  file.c_str(), mountoffset, subunitoffset, loop_through_mounts ? "true" : "false" );
811  fflush( stdout );
812  percentage = my_unit->Upgrade( file, mountoffset, subunitoffset, force, loop_through_mounts );
813  my_unit->SetTurretAI();
814  }
815  viret = newVarInst( VI_TEMP );
816  viret->type = VAR_FLOAT;
817  viret->float_val = percentage;
818  } else if (method_id == CMT_UNIT_incrementCargo) {
819  double percentagechange = getFloatArg( node, mode, 1 );
820  int quantity = getIntArg( node, mode, 2 );
821  if (mode == SCRIPT_RUN) {
822  if (my_unit->numCargo() > 0) {
823  unsigned int index;
824  index = rand()%my_unit->numCargo();
825  Cargo c( my_unit->GetCargo( index ) );
826  c.quantity = quantity;
827  if ( my_unit->CanAddCargo( c ) ) {
828  my_unit->AddCargo( c );
829  my_unit->GetCargo( index ).price *= percentagechange;
830  }
831  }
832  }
833  viret = newVarInst( VI_TEMP );
834  viret->type = VAR_VOID;
835  } else if (method_id == CMT_UNIT_decrementCargo) {
836  float percentagechange;
837  percentagechange = getFloatArg( node, mode, 1 );
838  if (mode == SCRIPT_RUN) {
839  if (my_unit->numCargo() > 0) {
840  unsigned int index;
841  index = rand()%my_unit->numCargo();
842  if ( my_unit->RemoveCargo( index, 1, false ) )
843  my_unit->GetCargo( index ).price *= percentagechange;
844  }
845  }
846  viret = newVarInst( VI_TEMP );
847  viret->type = VAR_VOID;
848  } else if (method_id == CMT_UNIT_getSaveData) {
849  std::string magic_num;
850  void *my_obj = NULL;
851  magic_num = getStringArgument( node, mode, 1 );
852  if (mode == SCRIPT_RUN) {
853  Cockpit *tmp;
854  if ( ( tmp = _Universe->isPlayerStarship( my_unit ) ) )
855  my_obj = (void*) &tmp->savegame->getMissionData( magic_num );
856  }
857  viret = newVarInst( VI_TEMP );
858  viret->type = VAR_OBJECT;
859  viret->objectname = "olist";
860  viret->object = my_obj;
861  } else if (method_id == CMT_UNIT_toxml) {
862  if (mode == SCRIPT_RUN)
863  call_unit_toxml( node, mode, ovi );
864  viret = newVarInst( VI_TEMP );
865  viret->type = VAR_VOID;
866  } else if (method_id == CMT_UNIT_switchFg) {
867  string arg = getStringArgument( node, mode, 1 );
868  if (mode == SCRIPT_RUN) {
869  string type = my_unit->name;
870  int nr_waves_left = 0;
871  int nr_ships = 1;
872  string order( "default" );
873  Flightgroup *fg = my_unit->getFlightgroup();
874  if (fg) {
875  type = fg->type;
876  nr_waves_left = fg->nr_waves_left;
877  nr_ships = 1;
878  fg->Decrement( my_unit );
879  order = fg->ainame;
880  }
882  my_unit->faction ), order, nr_ships, nr_waves_left, "", "", this );
883  my_unit->SetFg( fg, fg->nr_ships_left-1 );
884  }
885  viret = newVarInst( VI_TEMP );
886  viret->type = VAR_VOID;
887  } else if (method_id == CMT_UNIT_frameOfReference) {
888  Unit *other_unit = getUnitArg( node, mode, 1 );
889  if (mode == SCRIPT_RUN)
890  my_unit->VelocityReference( other_unit );
891  viret = newVarInst( VI_TEMP );
892  viret->type = VAR_VOID;
893  } else if (method_id == CMT_UNIT_communicateTo) {
894  Unit *other_unit = getUnitArg( node, mode, 1 );
895  float mood = getFloatArg( node, mode, 2 );
896  unsigned char sex = 0;
897  if (mode == SCRIPT_RUN) {
898  Cockpit *tmp;
899  if ( ( tmp = _Universe->isPlayerStarship( my_unit ) ) ) {
900  Animation *ani = other_unit->pilot->getCommFace( other_unit, mood, sex );
901  if (NULL != ani)
902  tmp->SetCommAnimation( ani, NULL );
903  }
904  }
905  viret = newVarInst( VI_TEMP );
906  viret->type = VAR_INT;
907  viret->int_val = sex;
908  } else if (method_id == CMT_UNIT_commAnimation) {
909  string anim = getStringArgument( node, mode, 1 );
910  if (mode == SCRIPT_RUN) {
911  Cockpit *tmp;
912  if ( ( tmp = _Universe->isPlayerStarship( my_unit ) ) ) {}
913  }
914  viret = newVarInst( VI_TEMP );
915  viret->type = VAR_VOID;
916  } else {
917  fatalError( node, mode, "no such method "+node->script.name );
918  assert( 0 );
919  }
920 #ifdef ORDERDEBUG
921  VSFileSystem::vs_fprintf( stderr, "callundel%x", ovi );
922  fflush( stderr );
923 #endif
924  deleteVarInst( ovi );
925 #ifdef ORDERDEBUG
926  VSFileSystem::vs_fprintf( stderr, "undel1" );
927  fflush( stderr );
928 #endif
929  return viret;
930  } //else (objects)
931 #ifdef ORDERDEBUG
932  VSFileSystem::vs_fprintf( stderr, "endcallun%x", this );
933  fflush( stderr );
934 #endif
935  return NULL; //never reach
936 }
937 
938 extern BLENDFUNC parse_alpha( const char* );
939 
940 Unit* Mission::call_unit_launch( CreateFlightgroup *fg, int type, const string &destinations )
941 {
942  int faction_nr = FactionUtil::GetFactionIndex( fg->fg->faction );
943  Unit **units = new Unit*[fg->nr_ships];
944  int u;
945  Unit *par = _Universe->AccessCockpit()->GetParent();
946  CollideMap::iterator metahint[2] = {
949  };
950  CollideMap::iterator *hint = metahint;
951  if ( par && !is_null( par->location[Unit::UNIT_ONLY] ) && !is_null( par->location[Unit::UNIT_BOLT] )
953  hint = par->location;
954  for (u = 0; u < fg->nr_ships; u++) {
955  Unit *my_unit;
956  if (type == PLANETPTR) {
957  float radius = 1;
958  char *tex = strdup( fg->fg->type.c_str() );
959  char *nam = strdup( fg->fg->type.c_str() );
960  char *bsrc = strdup( fg->fg->type.c_str() );
961  char *bdst = strdup( fg->fg->type.c_str() );
962  char *citylights = strdup( fg->fg->type.c_str() );
963  tex[0] = '\0';
964  bsrc[0] = '\0'; //have at least 1 char
965  bdst[0] = '\0';
966  citylights[0] = '\0';
967  GFXMaterial mat;
968  GFXGetMaterial( 0, mat );
969  BLENDFUNC s = ONE;
970  BLENDFUNC d = ZERO;
971  if (bdst[0] != '\0')
972  d = parse_alpha( bdst );
973  if (bsrc[0] != '\0')
974  s = parse_alpha( bsrc );
975  my_unit = UnitFactory::createPlanet( QVector( 0, 0, 0 ), QVector( 0, 0, 0 ), 0, Vector( 0, 0, 0 ),
976  0, 0, radius, tex, "", "", s,
977  d, ParseDestinations( destinations ),
978  QVector( 0, 0, 0 ), NULL, mat,
979  vector< GFXLightLocal > (), faction_nr, nam, getUniqueSerial() );
980  free( bsrc );
981  free( bdst );
982  free( tex );
983  free( nam );
984  free( citylights );
985  } else if (type == NEBULAPTR) {
986  my_unit = UnitFactory::createNebula(
987  fg->fg->type.c_str(), false, faction_nr, fg->fg, u+fg->fg->nr_ships-fg->nr_ships, getUniqueSerial() );
988  } else if (type == ASTEROIDPTR) {
989  my_unit = UnitFactory::createAsteroid(
990  fg->fg->type.c_str(), faction_nr, fg->fg, u+fg->fg->nr_ships-fg->nr_ships, .01, getUniqueSerial() );
991  } else {
992  my_unit = UnitFactory::createUnit( fg->fg->type.c_str(), false, faction_nr, string(
993  "" ), fg->fg, u+fg->fg->nr_ships-fg->nr_ships, NULL, getUniqueSerial() );
994  }
995  units[u] = my_unit;
996  }
997  float fg_radius = units[0]->rSize();
998  Unit *my_unit;
999  for (u = 0; u < fg->nr_ships; u++) {
1000  my_unit = units[u];
1001  QVector pox;
1002  pox.i = fg->fg->pos.i+u*fg_radius*3;
1003  pox.j = fg->fg->pos.j+u*fg_radius*3;
1004  pox.k = fg->fg->pos.k+u*fg_radius*3;
1005  my_unit->SetPosAndCumPos( pox );
1006  if (type == ASTEROIDPTR || type == NEBULAPTR) {
1007  my_unit->PrimeOrders();
1008  } else {
1009  my_unit->LoadAIScript( fg->fg->ainame );
1010  my_unit->SetTurretAI();
1011  }
1012  _Universe->scriptStarSystem()->AddUnit( my_unit );
1013  my_unit->UpdateCollideQueue( _Universe->scriptStarSystem(), hint );
1014  if ( !is_null( my_unit->location[Unit::UNIT_ONLY] ) && !is_null( my_unit->location[Unit::UNIT_BOLT] ) )
1015  hint = my_unit->location;
1016  my_unit->Target( NULL );
1017  }
1018  my_unit = units[0];
1019  if ( !_Universe->isPlayerStarship( fg->fg->leader.GetUnit() ) )
1020  fg->fg->leader.SetUnit( my_unit );
1021  delete[] units;
1022  return my_unit;
1023 }
1024 
1025 void Mission::findNextEnemyTarget( Unit *my_unit )
1026 {
1027  StarSystem *ssystem = _Universe->scriptStarSystem();
1028  un_iter uiter( ssystem->getUnitList().createIterator() );
1029  Unit *unit;
1030  Unit *target_unit = NULL;
1031  for (; (unit = *uiter); ++uiter)
1032  if (my_unit->getRelation( unit ) < 0.0) {
1033  target_unit = *uiter;
1034  break;
1035  }
1036  if (target_unit)
1037  my_unit->Target( target_unit );
1038 }
1039 
1040 static Unit * getIthUnit( un_iter uiter, int unit_nr )
1041 {
1042  Unit *unit = NULL;
1043  for (int i = 0; (unit = *uiter); ++uiter, ++i)
1044  if (i == unit_nr)
1045  return unit;
1046  return NULL;
1047 }
1048