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
cockpit.cpp
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*-
2 
5 
6 #include <boost/version.hpp>
7 #if BOOST_VERSION != 102800
8 #include <boost/python/object.hpp>
9 #include <boost/python/dict.hpp>
10 #else
11 #include <boost/python/objects.hpp>
12 #endif
13 
14 #include "vsfilesystem.h"
15 #include "vs_globals.h"
16 #include "vegastrike.h"
17 #include "gauge.h"
18 #include "cockpit.h"
19 #include "universe.h"
20 #include "star_system.h"
21 #include "cmd/unit_generic.h"
22 #include "cmd/unit_factory.h"
23 #include "cmd/collection.h"
24 #include "cmd/unit_util.h"
25 #include "cmd/unit_find.h" //for radar iteration.
26 #include "cmd/base_util.h"
27 #include "hud.h"
28 #include "vdu.h"
29 #include "lin_time.h" //for fps
30 #include "cmd/beam.h"
31 #include "config_xml.h"
32 #include "lin_time.h"
33 #include "cmd/images.h"
34 #include "cmd/script/mission.h"
35 #include "cmd/script/msgcenter.h"
36 #include "cmd/ai/flyjoystick.h"
37 #include "cmd/ai/firekeyboard.h"
38 #include "cmd/ai/aggressive.h"
39 #include "cmd/ai/autodocking.h"
40 #include "main_loop.h"
41 #include <assert.h> //needed for assert() calls
42 #include "savegame.h"
43 #include "animation.h"
44 #include "mesh.h"
45 #include "universe_util.h"
46 #include "in_mouse.h"
47 #include "gui/glut_support.h"
48 #include "networking/netclient.h"
49 #include "audiolib.h"
50 #include "save_util.h"
51 #include "cmd/base.h"
52 #include "in_kb_data.h"
53 #include "main_loop.h"
54 #include <set>
55 #include <string>
56 #include "cmd/unit_const_cache.h"
57 #include "options.h"
58 
60 
61 using std::min;
62 using std::max;
63 
64 extern float rand01();
66 #define SWITCH_CONST (.9)
67 /* The smaller VERYNEAR_CONST is, the worse Z-Buffer precision will be. So keep this above 0.004) */
68 #define VERYNEAR_CONST (0.004f)
69 /*so that znear/zfar are not too close to max/min values, and account for off-center cockpits */
70 #define COCKPITZ_HEADROOM (1.01f)
71 
72 static GFXColor RetrColor( const string &name, GFXColor def = GFXColor( 1, 1, 1, 1 ) )
73 {
74  vs_config->getColor( name, &def.r );
75  return def;
76 }
77 
80 
81 #define sqr( x ) ( ( (x) )*( (x) ) )
83 {
85 }
86 
87 void soundContainer::loadsound( string soundfile, bool looping )
88 {
89  if ( this->sound == -2 && soundfile.size() ) {
90  string sound = GameCockpit::getsoundfile( soundfile );
91  if ( sound.size() )
92  this->sound = AUDCreateSoundWAV( sound, looping );
93  else
94  this->sound = -1;
95  }
96 }
97 
99 {
100  if (sound >= 0) {
101  AUDAdjustSound( sound, QVector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
102  AUDPlay( sound, QVector( 0, 0, 0 ), Vector( 0, 0, 0 ), 1 );
103  }
104 }
105 
107 {
108  if (sound >= 0) {
109 #if 0
111  AUDDeleteSound( sound, false );
112 #endif
113  sound = -2;
114  }
115 }
116 
118 {
119  for (size_t j = 0; j < vdu.size(); j++)
120  vdu[j]->ReceivedTargetData();
121 }
122 
123 void GameCockpit::SetSoundFile( string sound )
124 {
125  soundfile = AUDCreateSoundWAV( sound, false );
126 }
127 
128 void GameCockpit::DrawNavigationSymbol( const Vector &Loc, const Vector &P, const Vector &Q, float size )
129 {
130  if (1) {
131  static float crossthick =
132  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "NavCrossLineThickness", "1" ) ); //1.05;
133  GFXLineWidth( crossthick );
134  size = .125*size;
136  GFXEnable( SMOOTH );
137  GFXBegin( GFXLINE );
138  GFXVertexf( Loc+P*size );
139  GFXVertexf( Loc+.125*P*size );
140  GFXVertexf( Loc-P*size );
141  GFXVertexf( Loc-.125*P*size );
142  GFXVertexf( Loc+Q*size );
143  GFXVertexf( Loc+.125*Q*size );
144  GFXVertexf( Loc-Q*size );
145  GFXVertexf( Loc-.125*Q*size );
146  GFXVertexf( Loc+.0625*Q*size );
147  GFXVertexf( Loc+.0625*P*size );
148  GFXVertexf( Loc-.0625*Q*size );
149  GFXVertexf( Loc-.0625*P*size );
150  GFXVertexf( Loc+.9*P*size+.125*Q*size );
151  GFXVertexf( Loc+.9*P*size-.125*Q*size );
152  GFXVertexf( Loc-.9*P*size+.125*Q*size );
153  GFXVertexf( Loc-.9*P*size-.125*Q*size );
154  GFXVertexf( Loc+.9*Q*size+.125*P*size );
155  GFXVertexf( Loc+.9*Q*size-.125*P*size );
156  GFXVertexf( Loc-.9*Q*size+.125*P*size );
157  GFXVertexf( Loc-.9*Q*size-.125*P*size );
158  GFXEnd();
159  GFXDisable( SMOOTH );
160  GFXLineWidth( 1 );
161  }
162 }
163 
164 float GameCockpit::computeLockingSymbol( Unit *par )
165 {
166  return par->computeLockingPercent();
167 }
168 
169 inline void DrawOneTargetBox( const QVector &Loc,
170  float rSize,
171  const Vector &CamP,
172  const Vector &CamQ,
173  const Vector &CamR,
174  float lock_percent,
175  bool ComputerLockon,
176  bool Diamond = false )
177 {
178  static float boxthick = XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "BoxLineThickness", "1" ) );
179  static float rat = XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "min_target_box_size", ".01" ) );
180  float len = (Loc).Magnitude();
181  float curratio = rSize/len;
182  if (curratio < rat)
183  rSize = len*rat;
184  GFXLineWidth( boxthick );
185  GFXEnable( SMOOTH );
187  if (Diamond) {
188  float ModrSize = rSize/1.41;
190  GFXVertexf( Loc+(.75*CamP+CamQ).Cast()*ModrSize );
191  GFXVertexf( Loc+(CamP+.75*CamQ).Cast()*ModrSize );
192  GFXVertexf( Loc+(CamP-.75*CamQ).Cast()*ModrSize );
193  GFXVertexf( Loc+(.75*CamP-CamQ).Cast()*ModrSize );
194  GFXVertexf( Loc+(-.75*CamP-CamQ).Cast()*ModrSize );
195  GFXVertexf( Loc+(-CamP-.75*CamQ).Cast()*ModrSize );
196  GFXVertexf( Loc+(.75*CamQ-CamP).Cast()*ModrSize );
197  GFXVertexf( Loc+(CamQ-.75*CamP).Cast()*ModrSize );
198  GFXVertexf( Loc+(.75*CamP+CamQ).Cast()*ModrSize );
199  GFXEnd();
200  } else if (ComputerLockon) {
202  GFXVertexf( Loc+(CamP+CamQ).Cast()*rSize );
203  GFXVertexf( Loc+(CamP-CamQ).Cast()*rSize );
204  GFXVertexf( Loc+(-CamP-CamQ).Cast()*rSize );
205  GFXVertexf( Loc+(CamQ-CamP).Cast()*rSize );
206  GFXVertexf( Loc+(CamP+CamQ).Cast()*rSize );
207  GFXEnd();
208  } else {
209  GFXBegin( GFXLINE );
210  GFXVertexf( Loc+(CamP+CamQ).Cast()*rSize );
211  GFXVertexf( Loc+(CamP+.66*CamQ).Cast()*rSize );
212 
213  GFXVertexf( Loc+(CamP-CamQ).Cast()*rSize );
214  GFXVertexf( Loc+(CamP-.66*CamQ).Cast()*rSize );
215 
216  GFXVertexf( Loc+(-CamP-CamQ).Cast()*rSize );
217  GFXVertexf( Loc+(-CamP-.66*CamQ).Cast()*rSize );
218 
219  GFXVertexf( Loc+(CamQ-CamP).Cast()*rSize );
220  GFXVertexf( Loc+(CamQ-.66*CamP).Cast()*rSize );
221 
222  GFXVertexf( Loc+(CamP+CamQ).Cast()*rSize );
223  GFXVertexf( Loc+(CamP+.66*CamQ).Cast()*rSize );
224 
225  GFXVertexf( Loc+(CamP+CamQ).Cast()*rSize );
226  GFXVertexf( Loc+(.66*CamP+CamQ).Cast()*rSize );
227 
228  GFXVertexf( Loc+(CamP-CamQ).Cast()*rSize );
229  GFXVertexf( Loc+(.66*CamP-CamQ).Cast()*rSize );
230 
231  GFXVertexf( Loc+(-CamP-CamQ).Cast()*rSize );
232  GFXVertexf( Loc+(-.66*CamP-CamQ).Cast()*rSize );
233 
234  GFXVertexf( Loc+(CamQ-CamP).Cast()*rSize );
235  GFXVertexf( Loc+(.66*CamQ-CamP).Cast()*rSize );
236 
237  GFXVertexf( Loc+(CamP+CamQ).Cast()*rSize );
238  GFXVertexf( Loc+(.66*CamP+CamQ).Cast()*rSize );
239 
240  GFXEnd();
241  }
242  if (lock_percent < .99) {
243  if (lock_percent < 0)
244  lock_percent = 0;
245  //eallySwitch=XMLSupport::parse_bool(vs_config->getVariable("graphics","hud","switchToTargetModeOnKey","true"));
246  static float diamondthick =
247  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "DiamondLineThickness", "1" ) ); //1.05;
248  glLineWidth( diamondthick );
249  static bool center =
250  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "LockCenterCrosshair", "false" ) );
251  static float absmin =
252  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "min_lock_box_size", ".001" ) );
253  static float endreticle =
254  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "MinMissileBracketSize", "1.05" ) ); //1.05;
255  static float startreticle =
256  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "MaxMissileBracketSize", "2.05" ) ); //2.05;
257  static float diamondsize = XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "DiamondSize", "2.05" ) ); //1.05;
258  static float bracketsize =
259  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "RotatingBracketSize", "0.58" ) ); //1.05;
260  static float thetaspeed =
261  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "DiamondRotationSpeed", "1" ) ); //1.05;
262  static float lockline =
263  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "LockConfirmLineLength", "1.5" ) ); //1.05;
264  if (center) {
265  static float bracketwidth =
266  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "RotatingBracketWidth", "0.1" ) ); //1.05;
267  static bool bracketinnerouter =
268  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "RotatingBracketInner", "true" ) ); //1.05;
269  float innerdis = endreticle+(startreticle-endreticle)*lock_percent;
270  float outerdis = innerdis+bracketsize;
271  float bracketdis = (bracketinnerouter ? innerdis : outerdis);
272  float r = rSize < absmin ? absmin : rSize;
273  GFXBegin( GFXLINE );
274 
275  GFXVertexf( Loc+CamP*(innerdis*r) );
276  GFXVertexf( Loc+CamP*(outerdis*r) );
277 
278  GFXVertexf( Loc+CamP*(bracketdis*r)+CamQ*(bracketwidth*r) );
279  GFXVertexf( Loc+CamP*(bracketdis*r)-CamQ*(bracketwidth*r) );
280 
281  GFXVertexf( Loc-CamP*(innerdis*r) );
282  GFXVertexf( Loc-CamP*(outerdis*r) );
283 
284  GFXVertexf( Loc-CamP*(bracketdis*r)+CamQ*(bracketwidth*r) );
285  GFXVertexf( Loc-CamP*(bracketdis*r)-CamQ*(bracketwidth*r) );
286 
287  GFXVertexf( Loc+CamQ*(innerdis*r) );
288  GFXVertexf( Loc+CamQ*(outerdis*r) );
289 
290  GFXVertexf( Loc+CamQ*(bracketdis*r)+CamP*(bracketwidth*r) );
291  GFXVertexf( Loc+CamQ*(bracketdis*r)-CamP*(bracketwidth*r) );
292 
293  GFXVertexf( Loc-CamQ*(innerdis*r) );
294  GFXVertexf( Loc-CamQ*(outerdis*r) );
295 
296  GFXVertexf( Loc-CamQ*(bracketdis*r)+CamP*(bracketwidth*r) );
297  GFXVertexf( Loc-CamQ*(bracketdis*r)-CamP*(bracketwidth*r) );
298 
299  GFXEnd();
300  } else {
301  float max = diamondsize;
302  //VSFileSystem::Fprintf (stderr,"lock percent %f\n",lock_percent);
303  float coord = endreticle+(startreticle-endreticle)*lock_percent; //rSize/(1-lock_percent);//this is a number between 1 and 100
304  double rtot = 1./sqrtf( 2 );
305 
306  //this causes the rotation!
307  float theta = 4*M_PI*lock_percent*thetaspeed;
308  Vector LockBox( -cos( theta )*rtot, -rtot, sin( theta )*rtot );
309  //Vector LockBox (0*rtot,-rtot,1*rtot);
310 
311  static float diamondthick =
312  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "DiamondLineThickness", "1" ) ); //1.05;
313  GFXLineWidth( diamondthick );
314  Vector TLockBox( rtot*LockBox.i+rtot*LockBox.j, rtot*LockBox.j-rtot*LockBox.i, LockBox.k );
315  Vector SLockBox( TLockBox.j, TLockBox.i, TLockBox.k );
316  QVector Origin = (CamP+CamQ).Cast()*(rSize*coord);
317  TLockBox = (TLockBox.i*CamP+TLockBox.j*CamQ+TLockBox.k*CamR);
318  SLockBox = (SLockBox.i*CamP+SLockBox.j*CamQ+SLockBox.k*CamR);
319  double r1Size = rSize*bracketsize;
320  if (r1Size < absmin)
321  r1Size = absmin;
323  max *= rSize*.75*endreticle;
324  if (lock_percent == 0) {
325  GFXVertexf( Loc+CamQ.Cast()*max*lockline );
326  GFXVertexf( Loc+CamQ.Cast()*max );
327  }
328  GFXVertexf( Loc+Origin+(TLockBox.Cast()*r1Size) );
329  GFXVertexf( Loc+Origin );
330  GFXVertexf( Loc+Origin+(SLockBox.Cast()*r1Size) );
331  if (lock_percent == 0) {
332  GFXVertexf( Loc+CamP.Cast()*max );
333  GFXVertexf( Loc+CamP.Cast()*max*lockline );
334 
335  GFXEnd();
337  GFXVertexf( Loc-CamP.Cast()*max );
338  } else {
339  GFXEnd();
341  }
342  GFXVertexf( Loc-Origin-(SLockBox.Cast()*r1Size) );
343  GFXVertexf( Loc-Origin );
344  GFXVertexf( Loc-Origin-(TLockBox.Cast()*r1Size) );
345 
346  Origin = (CamP-CamQ).Cast()*(rSize*coord);
347  if (lock_percent == 0) {
348  GFXVertexf( Loc-CamQ.Cast()*max );
349  GFXVertexf( Loc-CamQ.Cast()*max*lockline );
350 
351  GFXVertexf( Loc-CamQ.Cast()*max );
352  } else {
353  GFXEnd();
355  }
356  GFXVertexf( Loc+Origin+(TLockBox.Cast()*r1Size) );
357  GFXVertexf( Loc+Origin );
358  GFXVertexf( Loc+Origin-(SLockBox.Cast()*r1Size) );
359  if (lock_percent == 0) {
360  GFXVertexf( Loc+CamP.Cast()*max );
361  GFXEnd();
363  GFXVertexf( Loc-CamP.Cast()*max*lockline );
364 
365  GFXVertexf( Loc-CamP.Cast()*max );
366  } else {
367  GFXEnd();
369  }
370  GFXVertexf( Loc-Origin+(SLockBox.Cast()*r1Size) );
371  GFXVertexf( Loc-Origin );
372  GFXVertexf( Loc-Origin-(TLockBox.Cast()*r1Size) );
373  if (lock_percent == 0)
374  GFXVertexf( Loc+CamQ.Cast()*max );
375  GFXEnd();
376  }
377  }
378  GFXLineWidth( 1 );
379  GFXDisable( SMOOTH );
380 }
381 
382 static GFXColor DockBoxColor( const string &name, GFXColor deflt = GFXColor(1,1,1,1) )
383 {
384  vs_config->getColor( name, &deflt.r, true );
385  return deflt;
386 }
387 
388 inline void DrawDockingBoxes( Unit *un, Unit *target, const Vector &CamP, const Vector &CamQ, const Vector &CamR )
389 {
390  if ( target->IsCleared( un ) ) {
392  static GFXColor dockboxstop = DockBoxColor( "docking_box_halt", GFXColor(1,0,0,1) );
393  static GFXColor dockboxgo = DockBoxColor( "docking_box_proceed", GFXColor(0,1,.5,1) );
394  const vector< DockingPorts >d = target->DockingPortLocations();
395  for (unsigned int i = 0; i < d.size(); i++)
396  {
397  float rad = d[i].GetRadius() / sqrt( 2.0 );
398  QVector dockpos = Transform(
399  target->GetTransformation(),
400  d[i].GetPosition().Cast()
402 
403  if (!d[i].IsDockable())
404  {
405  static GFXColor waypointcolor = DockBoxColor( "docking_box_waypoint", GFXColor(0, 1, 1, 0.3) );
406  if (waypointcolor.a > 0.01) {
407  GFXColorf( waypointcolor );
408  DrawOneTargetBox( dockpos, rad, CamP, CamQ, CamR, 1,
409  true, true );
410  }
411  continue;
412  }
413 
416  GFXColorf( dockboxstop );
417  DrawOneTargetBox( dockpos, rad, CamP, CamQ, CamR, 1,
418  true, true );
419  GFXEnable( DEPTHTEST );
421  GFXColorf( dockboxgo );
422  DrawOneTargetBox( dockpos, rad, CamP, CamQ, CamR, 1,
423  true, true );
424  }
427  GFXColor4f( 1, 1, 1, 1 );
428  }
429 }
430 
431 void GameCockpit::DrawTargetBoxes(const Radar::Sensor& sensor)
432 {
433  if (sensor.InsideNebula())
434  return;
435 
436  StarSystem *ssystem = _Universe->activeStarSystem();
437  UnitCollection *unitlist = &ssystem->getUnitList();
438  //UnitCollection::UnitIterator *uiter=unitlist->createIterator();
439 
440  Vector CamP, CamQ, CamR;
441  _Universe->AccessCamera()->GetPQR( CamP, CamQ, CamR );
442 
443  GFXDisable( TEXTURE0 );
444  GFXDisable( TEXTURE1 );
448  GFXDisable( LIGHTING );
449  Unit *target;
450  Unit *player = sensor.GetPlayer();
451  assert(player);
452  for (un_kiter uiter = unitlist->constIterator(); (target=*uiter)!=NULL; ++uiter) {
453  if (target != player) {
454  QVector Loc( target->Position() );
455  Radar::Track track = sensor.CreateTrack(target, Loc);
456 
457  GFXColorf(sensor.GetColor(track));
458  switch (track.GetType())
459  {
463  if (sensor.IsTracking(track))
464  {
465  static bool draw_dock_box =
466  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_docking_boxes", "true" ) );
467  if (draw_dock_box)
468  DrawDockingBoxes( player, target, CamP, CamQ, CamR );
469  DrawOneTargetBox( Loc, target->rSize(), CamP, CamQ, CamR, computeLockingSymbol( player ), true );
470  } else {
471  DrawOneTargetBox( Loc, target->rSize(), CamP, CamQ, CamR, computeLockingSymbol( player ), false );
472  }
473  break;
474 
475  default:
476  break;
477  }
478  }
479  }
480 }
481 
482 // got to move this to some more generic place
483 #define SCATTER_CUBE \
484  QVector( rand()/RAND_MAX -.5, rand()/RAND_MAX -.5, rand()/RAND_MAX -.5 )
485 
486 
487 
488 inline void DrawITTSLine( QVector fromLoc, QVector aimLoc, GFXColor linecolor=GFXColor( 1, 1, 1, 1 ) )
489 {
490  GFXColorf( linecolor );
491  GFXEnable( SMOOTH );
494  GFXVertexf( fromLoc );
495  GFXVertexf( aimLoc );
496  GFXEnd();
497  GFXDisable( SMOOTH );
498 }
499 
500 inline void DrawITTSMark( float Size, QVector p, QVector q, QVector aimLoc, GFXColor markcolor=GFXColor( 1, 1, 1, 1 ) )
501 {
502  GFXColorf( markcolor );
503  GFXEnable( SMOOTH );
506  GFXVertexf( aimLoc + p*Size );
507  GFXVertexf( aimLoc - q*Size );
508  GFXVertexf( aimLoc - p*Size );
509  GFXVertexf( aimLoc + q*Size );
510  GFXVertexf( aimLoc + p*Size );
511  GFXEnd();
512  GFXDisable( SMOOTH );
513 }
514 
515 void GameCockpit::DrawTargetBox(const Radar::Sensor& sensor)
516 {
517  if (sensor.InsideNebula())
518  return;
519  Unit *player = sensor.GetPlayer();
520  assert(player);
521  Unit *target = player->Target();
522  if (!target)
523  return;
524 
525  float speed, range;
526  static GFXColor black_and_white = DockBoxColor( "black_and_white" );
527  int neutral = FactionUtil::GetNeutralFaction();
528  Vector CamP, CamQ, CamR;
529  _Universe->AccessCamera()->GetPQR( CamP, CamQ, CamR );
530  //Vector Loc (un->ToLocalCoordinates(target->Position()-un->Position()));
531  QVector Loc( target->Position()-_Universe->AccessCamera()->GetPosition() );
532 
533  GFXDisable( TEXTURE0 );
534  GFXDisable( TEXTURE1 );
538  GFXDisable( LIGHTING );
539  static bool draw_nav_symbol = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawNavSymbol", "false" ) );
540  if (draw_nav_symbol) {
541  static GFXColor suncol = RetrColor( "nav", GFXColor( 1, 1, 1, 1 ) );
542  DrawNavigationSymbol(player->GetComputerData().NavPoint, CamP, CamQ,
543  CamR.Cast().Dot( (player->GetComputerData().NavPoint).Cast()-_Universe->AccessCamera()->GetPosition() ) );
544  }
545  Radar::Track track = sensor.CreateTrack(target, Loc);
546  GFXColor trackcolor=sensor.GetColor(track);
547  GFXColorf(trackcolor);
548  if (draw_line_to_target) {
550  GFXEnable( SMOOTH );
551  QVector my_loc( _Universe->AccessCamera()->GetPosition() );
553  GFXVertexf( my_loc );
554  GFXVertexf( Loc );
555 
556  Unit *targets_target = target->Target();
557  if (draw_line_to_targets_target && targets_target != NULL) {
558  QVector ttLoc( targets_target->Position() );
559  GFXVertexf( ttLoc );
560  }
561  GFXEnd();
562  GFXDisable( SMOOTH );
563  }
564  static bool draw_target_nav_symbol =
565  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_target_nav_symbol", "true" ) );
566  static bool draw_jump_nav_symbol =
567  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_jump_target_nav_symbol", "true" ) );
568  bool nav_symbol = false;
569  // FIXME: Replace with UnitUtil::isDockableUnit?
570  if ( draw_target_nav_symbol
571  && ( (target->faction == neutral
572  && target->isUnit() == UNITPTR) || target->isUnit() == ASTEROIDPTR
573  || ( target->isPlanet() && ( (Planet*) target )->isAtmospheric()
574  && ( draw_jump_nav_symbol
575  || target->GetDestinations().empty() ) ) || !sensor.InRange(track)) ) {
576  static float nav_symbol_size = XMLSupport::parse_float( vs_config->getVariable( "graphics", "nav_symbol_size", ".25" ) );
577  GFXColor4f( 1, 1, 1, 1 );
578  DrawNavigationSymbol( Loc, CamP, CamQ, Loc.Magnitude()*nav_symbol_size );
579  nav_symbol = true;
580  } else {
581  static bool lock_nav_symbol =
582  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "lock_significant_target_box", "true" ) );
583  DrawOneTargetBox( Loc, target->rSize(), CamP, CamQ, CamR, computeLockingSymbol(player), player->TargetLocked()
584  && ( lock_nav_symbol || !UnitUtil::isSignificant( target ) ) );
585  }
586 
587  static bool draw_dock_box = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_docking_boxes", "true" ) );
588  if (draw_dock_box)
589  DrawDockingBoxes(player, target, CamP, CamQ, CamR);
590  if ( (always_itts || player->GetComputerData().itts) && !nav_symbol ) {
591  float mrange;
592  float err = .01*( 1 - player->CloakVisible() );
593  float scatter = .25*player->rSize();
594  static bool ITTS_averageguns =
595  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "ITTSUseAverageGunSpeed", "true" ) );
596  static bool ITTS_for_locks =
597  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "ITTSForLockable", "false" ) );
598  static bool ITTS_for_beams =
599  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "ITTSForBeams", "false" ) );
600  static bool line_to_itts_alpha =
601  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "ITTSLineToMarkAlpha", "0.1" ) );
602  QVector p = CamP.Cast();
603  QVector q = CamQ.Cast();
604  QVector offs = _Universe->AccessCamera()->GetPosition() - SCATTER_CUBE*scatter*10*err;
605  QVector iLoc;
606  Vector PlayerPosition = player->Position();
607  Vector PlayerVelocity = player->GetVelocity();
608  GFXColor mntcolor;
609  if (ITTS_averageguns) {
610  player->getAverageGunSpeed( speed, range, mrange );
611  iLoc = target->PositionITTS( PlayerPosition, PlayerVelocity, speed, steady_itts ) - offs;
612  if (draw_line_to_itts)
613  DrawITTSLine(Loc, iLoc, trackcolor);
614  DrawITTSMark(scatter, p, q, iLoc, trackcolor);
615  }
616  else { // per-mount ITTS
617  int nummounts = player->GetNumMounts();
618  if (draw_line_to_itts) {
619  for (int i = 0; i < nummounts; i++) {
620  if ( (player->mounts[i].status == Mount::ACTIVE)
621  && (ITTS_for_beams || (player->mounts[i].type->type != weapon_info::BEAM))
622  && (ITTS_for_locks || (player->mounts[i].type->LockTime == 0)) )
623  {
624  iLoc = target->PositionITTS( PlayerPosition, PlayerVelocity, player->mounts[i].type->Speed, steady_itts ) - offs;
625  DrawITTSLine( Loc, iLoc, GFXColor(trackcolor.r, trackcolor.g, trackcolor.b, line_to_itts_alpha) );
626  }
627  }
628  }
629  for (int i = 0; i < nummounts; i++) {
630  if ( (player->mounts[i].status == Mount::ACTIVE)
631  && (ITTS_for_beams || (player->mounts[i].type->type != weapon_info::BEAM))
632  && (ITTS_for_locks || (player->mounts[i].type->LockTime == 0)) )
633  {
634  mntcolor = MountColor( &player->mounts[i] );
635  iLoc = target->PositionITTS( PlayerPosition, PlayerVelocity, player->mounts[i].type->Speed, steady_itts ) - offs;
636  DrawITTSMark(scatter, p, q, iLoc, mntcolor);
637  }
638  }
639  } // per mount
640  } // draw ITTS
641 }
642 
643 void GameCockpit::DrawCommunicatingBoxes()
644 {
645  Vector CamP, CamQ, CamR;
646  _Universe->AccessCamera()->GetPQR( CamP, CamQ, CamR );
647  //Vector Loc (un->ToLocalCoordinates(target->Position()-un->Position()));
648  for (unsigned int i = 0; i < vdu.size(); ++i) {
649  Unit *target = vdu[i]->GetCommunicating();
650  if (target) {
651  static GFXColor black_and_white = DockBoxColor( "communicating" );
652  QVector Loc( target->Position()-_Universe->AccessCamera()->GetPosition() );
653  GFXDisable( TEXTURE0 );
654  GFXDisable( TEXTURE1 );
658  GFXDisable( LIGHTING );
659  GFXColorf( black_and_white );
660 
661  DrawOneTargetBox( Loc, target->rSize()*1.05, CamP, CamQ, CamR, 1, 0 );
662  }
663  }
664 }
665 
667 {
668  if (sensor.InsideNebula())
669  return;
670 
671  static GFXColor black_and_white = DockBoxColor( "black_and_white" );
672 
673  GFXDisable( TEXTURE0 );
674  GFXDisable( TEXTURE1 );
677  GFXDisable( LIGHTING );
678 
679  //This avoids rendering the same target box more than once
680  Unit *subunit;
681  std::set<Unit *> drawn_targets;
682  for (un_kiter iter = sensor.GetPlayer()->viewSubUnits(); (subunit=*iter)!=NULL; ++iter) {
683  if (!subunit)
684  return;
685  Unit *target = subunit->Target();
686  if (!target || (drawn_targets.find(target) != drawn_targets.end()))
687  continue;
688  drawn_targets.insert(target);
689 
690  Vector CamP, CamQ, CamR;
691  _Universe->AccessCamera()->GetPQR( CamP, CamQ, CamR );
692  //Vector Loc (un->ToLocalCoordinates(target->Position()-un->Position()));
693  QVector Loc( target->Position()-_Universe->AccessCamera()->GetPosition() );
694  Radar::Track track = sensor.CreateTrack(target, Loc);
695  static bool draw_nav_symbol =
696  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawNavSymbol", "false" ) );
697  if (draw_nav_symbol) {
698  GFXColor4f( 1, 1, 1, 1 );
699  DrawNavigationSymbol( subunit->GetComputerData().NavPoint, CamP, CamQ,
700  CamR.Cast().Dot( (subunit->GetComputerData().NavPoint).Cast()
702  }
703  GFXColorf(sensor.GetColor(track));
704 
705  //DrawOneTargetBox (Loc, target->rSize(), CamP, CamQ, CamR,computeLockingSymbol(un),un->TargetLocked());
706 
707  //** jay
708  float rSize = track.GetSize();
709 
710  GFXEnable( SMOOTH );
712  GFXBegin( GFXLINE );
713  GFXVertexf( Loc+(CamP).Cast()*rSize*1.3 );
714  GFXVertexf( Loc+(CamP).Cast()*rSize*.8 );
715 
716  GFXVertexf( Loc+(-CamP).Cast()*rSize*1.3 );
717  GFXVertexf( Loc+(-CamP).Cast()*rSize*.8 );
718 
719  GFXVertexf( Loc+(CamQ).Cast()*rSize*1.3 );
720  GFXVertexf( Loc+(CamQ).Cast()*rSize*.8 );
721 
722  GFXVertexf( Loc+(-CamQ).Cast()*rSize*1.3 );
723  GFXVertexf( Loc+(-CamQ).Cast()*rSize*.8 );
724  GFXEnd();
725  GFXDisable( SMOOTH );
726  }
727 }
728 
730 {
731  static bool drawtactarg =
732  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "DrawTacticalTarget", "false" ) );
733  if (!drawtactarg)
734  return;
735  static GFXColor black_and_white = DockBoxColor( "black_and_white" );
736  if (sensor.GetPlayer()->getFlightgroup() == NULL)
737  return;
738  Unit *target = sensor.GetPlayer()->getFlightgroup()->target.GetUnit();
739  if (target) {
740  Vector CamP, CamQ, CamR;
741  _Universe->AccessCamera()->GetPQR( CamP, CamQ, CamR );
742  //Vector Loc (un->ToLocalCoordinates(target->Position()-un->Position()));
743  QVector Loc( target->Position()-_Universe->AccessCamera()->GetPosition() );
744  GFXDisable( TEXTURE0 );
745  GFXDisable( TEXTURE1 );
749  GFXDisable( LIGHTING );
750 
751  static float thethick = XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "TacTargetThickness", "1.0" ) );
752  static float fudge = XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "TacTargetLength", "0.1" ) );
753  static float foci = XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "TacTargetFoci", "0.5" ) );
754  glLineWidth( (int) thethick ); //temp
755  Radar::Track track = sensor.CreateTrack(target, Loc);
756  GFXColorf(sensor.GetColor(track));
757 
758  //DrawOneTargetBox (Loc, target->rSize(), CamP, CamQ, CamR,computeLockingSymbol(un),un->TargetLocked());
759 
760  //** jay
761  float rSize = track.GetSize();
762 
763  GFXBegin( GFXLINE );
764  GFXVertexf( Loc+( (-CamP).Cast()+(-CamQ).Cast() )*rSize*(foci+fudge) );
765  GFXVertexf( Loc+( (-CamP).Cast()+(-CamQ).Cast() )*rSize*(foci-fudge) );
766 
767  GFXVertexf( Loc+( (-CamP).Cast()+(CamQ).Cast() )*rSize*(foci+fudge) );
768  GFXVertexf( Loc+( (-CamP).Cast()+(CamQ).Cast() )*rSize*(foci-fudge) );
769 
770  GFXVertexf( Loc+( (CamP).Cast()+(-CamQ).Cast() )*rSize*(foci+fudge) );
771  GFXVertexf( Loc+( (CamP).Cast()+(-CamQ).Cast() )*rSize*(foci-fudge) );
772 
773  GFXVertexf( Loc+( (CamP).Cast()+(CamQ).Cast() )*rSize*(foci+fudge) );
774  GFXVertexf( Loc+( (CamP).Cast()+(CamQ).Cast() )*rSize*(foci-fudge) );
775  GFXEnd();
776 
777  glLineWidth( (int) 1 ); //temp
778  }
779 }
780 
782 {
783  ejecting = true;
784  going_to_dock_screen = false;
785 }
786 
788 {
789  ejecting = true;
790  going_to_dock_screen = true;
791 }
792 
794 {
795  if (!un || !target)
796  return;
797  if (UnitUtil::isDockableUnit( target ) == false)
798  return;
799  static std::set< std::string >autoLandingExcludeList;
800  static std::set< std::string >autoLandingExcludeWarningList;
801  static bool autoLandingExcludeList_initialised = false;
802  if (!autoLandingExcludeList_initialised) {
803  autoLandingExcludeList_initialised = true;
804  std::string excludes;
805 
806  excludes = vs_config->getVariable( "physics", "AutoLandingExcludeList", "" );
807  if ( !excludes.empty() ) {
808  std::string::size_type pos = 0, epos = 0;
809  while (epos != std::string::npos) {
810  std::string xx (excludes.substr( pos, epos = excludes.find( ' ', pos ) ));
811  autoLandingExcludeList.insert( xx );
812  pos = epos+1;
813  }
814  }
815  excludes = vs_config->getVariable( "physics", "AutoLandingExcludeWarningList", "" );
816  if ( !excludes.empty() ) {
817  std::string::size_type pos = 0, epos = 0;
818  while (epos != std::string::npos) {
819  std::string yy(excludes.substr( pos, epos = excludes.find( ' ', pos ) ));
820  autoLandingExcludeWarningList.insert( yy );
821  pos = epos+1;
822  }
823  }
824  }
825  std::string tname=target->name;
826  if (autoLandingExcludeList.find(tname) != autoLandingExcludeList.end())
827  return;
828  static float lessthan = XMLSupport::parse_float( vs_config->getVariable( "physics", "AutoLandingDockDistance", "50" ) );
829  static float warnless = XMLSupport::parse_float( vs_config->getVariable( "physics", "AutoLandingWarningDistance", "350" ) );
830  static float AutoLandingMoveDistance =
831  XMLSupport::parse_float( vs_config->getVariable( "physics", "AutoLandingMoveDistance", "50" ) );
832  static float moveout = XMLSupport::parse_float( vs_config->getVariable( "physics", "AutoLandingDisplaceDistance", "50" ) );
833  static float autorad = XMLSupport::parse_float( vs_config->getVariable( "physics", "unit_default_autodock_radius", "0" ) );
834  static bool adjust_unit_radius =
835  XMLSupport::parse_float( vs_config->getVariable( "physics", "use_unit_autodock_radius", "false" ) );
836  float rsize = target->isPlanet() ? target->rSize() : ( autorad+(adjust_unit_radius ? target->rSize() : 0) );
837  QVector diffvec = un->Position()-target->Position();
838  float dist = diffvec.Magnitude()-un->rSize()-rsize;
839  diffvec.Normalize();
840 
841  static bool haswarned = false;
842  static void *lastwarned = NULL;
843  static float docktime = -FLT_MAX;
844  if (dist < lessthan && haswarned && lastwarned == target) {
845  //CrashForceDock(target,un,true);
846  un->SetPosAndCumPos( target->Position()+diffvec.Scale( un->rSize()+rsize+AutoLandingMoveDistance ) );
848  haswarned = false;
849  lastwarned = target;
850  docktime = getNewTime();
851  } else if (haswarned == false && lastwarned == target) {
852  if (getNewTime()-docktime > SIMULATION_ATOM*2) {
853  haswarned = false;
854  un->SetPosAndCumPos( UniverseUtil::SafeEntrancePoint( target->Position()+diffvec*( rsize+moveout+un->rSize() ),
855  un->rSize()*1.1 ) );
856  lastwarned = NULL;
857  }
858  } else if (dist < warnless) {
859  if (lastwarned != target || !haswarned) {
860  if (autoLandingExcludeWarningList.count( target->name ) == 0) {
861  static string str = vs_config->getVariable( "cockpitaudio", "automatic_landing_zone", "als" );
862  static string str1 = vs_config->getVariable( "cockpitaudio", "automatic_landing_zone1", "als" );
863  static string str2 = vs_config->getVariable( "cockpitaudio", "automatic_landing_zone2", "als" );
864  static string autolandinga = vs_config->getVariable( "graphics",
865  "automatic_landing_zone_warning",
866  "comm_docking.ani" );
867  static string autolandinga1 = vs_config->getVariable( "graphics",
868  "automatic_landing_zone_warning1",
869  "comm_docking.ani" );
870  static string autolandinga2 = vs_config->getVariable( "graphics",
871  "automatic_landing_zone_warning2",
872  "comm_docking.ani" );
873  static string message = vs_config->getVariable( "graphics",
874  "automatic_landing_zone_warning_text",
875  "Now Entering an \"Automatic Landing Zone\"." );
876  UniverseUtil::IOmessage( 0, "game", "all", message );
877  static Animation *ani0 = new Animation( autolandinga.c_str() );
878  static Animation *ani1 = new Animation( autolandinga1.c_str() );
879  static Animation *ani2 = new Animation( autolandinga2.c_str() );
880  static soundContainer warnsound;
881  static soundContainer warnsound1;
882  static soundContainer warnsound2;
883  int num = rand() < RAND_MAX/2 ? 0 : (rand() < RAND_MAX/2 ? 1 : 2);
884  if (warnsound.sound < 0) {
885  warnsound.loadsound( str );
886  warnsound1.loadsound( str1 );
887  warnsound2.loadsound( str2 );
888  }
889  switch (num)
890  {
891  case 0:
892  warnsound.playsound();
893  SetCommAnimation( ani0, target );
894  break;
895  case 1:
896  warnsound1.playsound();
897  SetCommAnimation( ani1, target );
898  break;
899  default:
900  warnsound2.playsound();
901  SetCommAnimation( ani2, target );
902  break;
903  }
904  }
905  haswarned = true;
906  lastwarned = target;
907  }
908  } else if (lastwarned == target) {
909  haswarned = false;
910  lastwarned = NULL;
911  }
912 }
913 
915 {
916  static bool autolanding_enable =
917  XMLSupport::parse_bool( vs_config->getVariable( "physics", "AutoLandingEnable", "false" ) );
918  if (autolanding_enable)
919  {
920  Unit *player = GetParent();
921  if (player == NULL)
922  return;
923 
925  for (CollideMap::iterator it = collideMap->begin(); it != collideMap->end(); ++it)
926  {
927  if (it->radius <= 0)
928  continue;
929 
930  Unit *target = it->ref.unit;
931  if (target == NULL)
932  continue;
933 
934  DoAutoLanding(player, target);
935  }
936  }
937 }
938 
939 void GameCockpit::DrawRadar(const Radar::Sensor& sensor)
940 {
941  if (radarSprites[0] || radarSprites[1])
942  {
945 
946  assert(radarDisplay.get() != 0);
947  radarDisplay->Draw(sensor, radarSprites[0], radarSprites[1]);
948 
950 
951  // Draw radar damage
952  float damage = (sensor.GetPlayer()->GetImageInformation().cockpit_damage[0]);
953  if (sensor.GetMaxRange() < 1.0)
954  damage = std::min(damage, 0.25f);
955  if (damage < .985) {
956  if (radar_time >= 0) {
957  if ( damage > .001 && ( cockpit_time > radar_time+(1-damage) ) ) {
958  if (rand01() > SWITCH_CONST)
960  } else {
961  static Animation radar_ani( "static_round.ani", true, .1, BILINEAR );
962  radar_ani.DrawAsVSSprite( radarSprites[0] );
963  radar_ani.DrawAsVSSprite( radarSprites[1] );
964  }
965  } else if ( cockpit_time > ( ( 1-(-radar_time) )+damage ) ) {
966  if (rand01() > SWITCH_CONST)
968  }
969  }
970  }
971 }
972 
974 {
975  switch (stat)
976  {
978  return target->FShieldData();
979 
981  return target->RShieldData();
982 
984  return target->LShieldData();
985 
987  return target->BShieldData();
988  }
989  return 1;
990 }
991 
992 float GameCockpit::LookupUnitStat( int stat, Unit *target )
993 {
994  static float game_speed = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_speed", "1" ) );
995  static bool display_in_meters = XMLSupport::parse_bool( vs_config->getVariable( "physics", "display_in_meters", "true" ) );
996  static bool lie = XMLSupport::parse_bool( vs_config->getVariable( "physics", "game_speed_lying", "true" ) );
997  static float fpsval = 0;
998  const float fpsmax = 1;
999  static float numtimes = fpsmax;
1000  float armordat[8]; //short fix
1001  int armori;
1002  Unit *tmpunit;
1003  if (shield8) {
1004  switch (stat)
1005  {
1014  if (target->shield.shield.max[stat-UnitImages < void > ::SHIELDF])
1015  return target->shield.shield.cur[stat-UnitImages < void
1016  > ::SHIELDF]/target->shield.shield.max[stat-UnitImages < void > ::SHIELDF];
1017  else return 0;
1018  default:
1019  break;
1020  }
1021  }
1022  switch (stat)
1023  {
1025  return target->FShieldData();
1026 
1028  return target->RShieldData();
1029 
1031  return target->LShieldData();
1032 
1034  return target->BShieldData();
1035 
1044  target->ArmorData( armordat );
1045  if (armor8) {
1046  return armordat[stat-UnitImages < void > ::ARMORF]/StartArmor[stat-UnitImages < void > ::ARMORF];
1047  } else {
1048  for (armori = 0; armori < 8; ++armori) {
1049  if (armordat[armori] > StartArmor[armori])
1050  StartArmor[armori] = armordat[armori];
1051  armordat[armori] /= StartArmor[armori];
1052  }
1053  }
1054  switch (stat)
1055  {
1057  return .25*(armordat[0]+armordat[1]+armordat[4]+armordat[5]);
1058 
1060  return .25*(armordat[2]+armordat[3]+armordat[6]+armordat[7]);
1061 
1063  return .25*(armordat[1]+armordat[3]+armordat[5]+armordat[7]);
1064 
1066  default:
1067  return .25*(armordat[0]+armordat[2]+armordat[4]+armordat[6]);
1068  }
1070  if (target->FuelData() > maxfuel)
1071  maxfuel = target->FuelData();
1072  if (maxfuel > 0) return target->FuelData()/maxfuel;
1073  return 0;
1074 
1076  return target->EnergyData();
1077 
1079  {
1080  static bool warpifnojump =
1081  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "display_warp_energy_if_no_jump_drive",
1082  "true" ) );
1083  return (warpifnojump || target->GetJumpStatus().drive != -2) ? target->WarpEnergyData() : 0;
1084  }
1086  if ( maxhull < target->GetHull() )
1087  maxhull = target->GetHull();
1088  return target->GetHull()/maxhull;
1089 
1091  {
1092  int go =
1093  ( ( (target->GetHull()/maxhull) < .25 )
1094  && (target->BShieldData() < .25 || target->FShieldData() < .25) ) ? 1 : 0;
1095  static int overload = 0;
1096  if (overload != go) {
1097  if (go == 0) {
1098  static soundContainer ejectstopsound;
1099  if (ejectstopsound.sound < 0) {
1100  static string str = vs_config->getVariable( "cockpitaudio", "overload_stopped", "overload_stopped" );
1101  ejectstopsound.loadsound( str );
1102  }
1103  ejectstopsound.playsound();
1104  } else {
1105  static soundContainer ejectsound;
1106  if (ejectsound.sound < 0) {
1107  static string str = vs_config->getVariable( "cockpitaudio", "overload", "overload" );
1108  ejectsound.loadsound( str );
1109  }
1110  ejectsound.playsound();
1111  }
1112  overload = go;
1113  }
1114  return go;
1115  }
1117  {
1118  static float locklight_time = XMLSupport::parse_float( vs_config->getVariable( "graphics", "locklight_time", "1" ) );
1119  bool res = false;
1120  if ( ( tmpunit = target->GetComputerData().threat.GetUnit() ) ) {
1121  res = tmpunit->cosAngleTo( target, *&armordat[0], FLT_MAX, FLT_MAX ) > .95;
1122  if (res) last_locktime = UniverseUtil::GetGameTime();
1123  }
1124  return ( res || ( (UniverseUtil::GetGameTime()-last_locktime) < locklight_time ) ) ? 1.0f : 0.0f;
1125  }
1127  {
1128  static float locklight_time = XMLSupport::parse_float( vs_config->getVariable( "graphics", "locklight_time", "1" ) );
1129  bool res = target->graphicOptions.missilelock;
1130  if (res) last_mlocktime = UniverseUtil::GetGameTime();
1131  return ( res || ( (UniverseUtil::GetGameTime()-last_mlocktime) < locklight_time ) ) ? 1.0f : 0.0f;
1132  }
1134  {
1135  static double collidepanic =
1136  XMLSupport::parse_float( vs_config->getVariable( "physics", "collision_inertial_time", "1.25" ) );
1137  return (getNewTime()-TimeOfLastCollision) < collidepanic;
1138  }
1140  return (UnitUtil::getECM(target) > 0) ? 1 : 0;
1141 
1143  return target->graphicOptions.WarpFieldStrength;
1144 
1146  return jumpok ? 1 : 0;
1147 
1153  {
1154  static bool use_relative_velocity =
1155  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "display_relative_velocity", "true" ) );
1156  float value;
1157  switch (stat)
1158  {
1160  if (target->graphicOptions.WarpFieldStrength != 1.0) {
1161  if ( use_relative_velocity && target->computer.velocity_ref.GetUnit() ) {
1163  value =
1164  ( target->GetWarpVelocity()
1166  } else {
1167  value =
1168  (target->GetWarpVelocity()
1170  }
1171  } else {
1172  value = target->GetWarpVelocity().Magnitude();
1173  }
1174  } else {
1175  if ( use_relative_velocity && target->computer.velocity_ref.GetUnit() ) {
1177  value =
1178  ( target->cumulative_velocity
1180  } else {
1181  value =
1182  (target->cumulative_velocity
1184  }
1185  } else {
1186  value = target->cumulative_velocity.Magnitude();
1187  }
1188  }
1189  break;
1191  value = target->GetComputerData().set_speed;
1192  break;
1194  value = target->GetComputerData().max_speed();
1195  break;
1197  value = target->GetComputerData().max_combat_speed;
1198  break;
1200  value = target->GetComputerData().max_combat_ab_speed;
1201  break;
1202  default:
1203  value = 0;
1204  }
1205  if (lie)
1206  return value/game_speed;
1207  else
1208  return display_in_meters ? value : value*3.6; //JMS 6/28/05 - converted back to raw meters/second
1209  }
1211  {
1212  float basemass = atof( UniverseUtil::LookupUnitStat( target->name, "", "Mass" ).c_str() );
1213  if (basemass > 0)
1214  return 100*target->Mass/basemass;
1215  else
1216  return 0;
1217  }
1219  {
1220  static int wasautopilot = 0;
1221  int abletoautopilot = 0;
1222  static bool auto_valid =
1223  XMLSupport::parse_bool( vs_config->getVariable( "physics", "insystem_jump_or_timeless_auto-pilot", "false" ) );
1224  if (target) {
1225  if (!auto_valid) {
1226  abletoautopilot = (target->graphicOptions.InWarp);
1227  } else {
1228  abletoautopilot = (target->AutoPilotTo( target, false ) ? 1 : 0);
1229  static float no_auto_light_below =
1230  XMLSupport::parse_float( vs_config->getVariable( "physics", "no_auto_light_below", "2000" ) );
1231  Unit *targtarg = target->Target();
1232  if (targtarg) {
1233  if ( ( target->Position()-targtarg->Position() ).Magnitude()-targtarg->rSize()-target->rSize()
1234  < no_auto_light_below )
1235  abletoautopilot = false;
1236  }
1237  }
1238  }
1239  if (abletoautopilot != wasautopilot) {
1240  if (abletoautopilot == 0) {
1241  static soundContainer autostopsound;
1242  if (autostopsound.sound < 0) {
1243  static string str = vs_config->getVariable( "cockpitaudio",
1244  "autopilot_available",
1245  "autopilot_available" );
1246  autostopsound.loadsound( str );
1247  }
1248  autostopsound.playsound();
1249  } else {
1250  static soundContainer autosound;
1251  if (autosound.sound < 0) {
1252  static string str = vs_config->getVariable( "cockpitaudio",
1253  "autopilot_unavailable",
1254  "autopilot_unavailable" );
1255  autosound.loadsound( str );
1256  }
1257  autosound.playsound();
1258  }
1259  wasautopilot = abletoautopilot;
1260  }
1261  return abletoautopilot;
1262  }
1264  if (fpsval >= 0 && fpsval < .5*FLT_MAX)
1265  numtimes -= .1+fpsval;
1266  if (numtimes <= 0) {
1267  numtimes = fpsmax;
1268  fpsval = GetElapsedTime();
1269  }
1270  if (fpsval)
1271  return 1./fpsval;
1273  if (target->autopilotactive)
1274  return (float) UnitImages< void >::ACTIVE;
1275  else
1276  return (float) UnitImages< void >::OFF;
1278  if (target->graphicOptions.WarpRamping)
1279  return (float) UnitImages< void >::SWITCHING;
1280  else if (target->graphicOptions.InWarp)
1281  return (float) UnitImages< void >::ACTIVE;
1282  else
1283  return (float) UnitImages< void >::OFF;
1285  if (target->inertialmode)
1286  return (float) UnitImages< void >::OFF;
1287  else
1288  return (float) UnitImages< void >::ON;
1290  if (0 == target->turretstatus)
1291  return (float) UnitImages< void >::NOTAPPLICABLE;
1292  else if (2 == target->turretstatus) //FIXME -- need to check if turrets are active
1293  return (float) UnitImages< void >::ACTIVE;
1294  else if (3 == target->turretstatus) //FIXME -- need to check if turrets are in FireAtWill state
1295  return (float) UnitImages< void >::FAW;
1296  else
1297  return (float) UnitImages< void >::OFF;
1299  if (target->GetImageInformation().ecm > 0)
1301  else
1302  return (float) UnitImages< void >::NOTAPPLICABLE;
1304  if (-1 == target->cloaking)
1305  return (float) UnitImages< void >::NOTAPPLICABLE;
1306  else if ( ( (int) (-2147483647)-1 ) == target->cloaking )
1307  return (float) UnitImages< void >::READY;
1308  else if (target->cloaking == target->cloakmin)
1309  return (float) UnitImages< void >::ACTIVE;
1310  else
1311  return (float) UnitImages< void >::SWITCHING;
1313  if ( target->CombatMode() )
1314  return (float) UnitImages< void >::MANEUVER;
1315  else
1316  return (float) UnitImages< void >::TRAVEL;
1318  if (!target) //FIXME
1319  return (float) UnitImages< void >::WARNING;
1320  else
1321  return (float) UnitImages< void >::NOMINAL;
1323  if (!target) //FIXME
1324  return (float) UnitImages< void >::WARNING;
1325  else
1326  return (float) UnitImages< void >::NOMINAL;
1328  if (!target) //FIXME
1329  return (float) UnitImages< void >::WARNING;
1330  else
1331  return (float) UnitImages< void >::NOMINAL;
1333  if (!target) //FIXME
1334  return (float) UnitImages< void >::WARNING;
1335  else
1336  return (float) UnitImages< void >::NOMINAL;
1338  if (!target) //FIXME
1339  return (float) UnitImages< void >::WARNING;
1340  else
1341  return (float) UnitImages< void >::NOMINAL;
1343  if (-2 == target->GetJumpStatus().drive)
1344  return (float) UnitImages< void >::NODRIVE;
1345  else if (target->GetWarpEnergy() < target->GetJumpStatus().energy)
1346  return (float) UnitImages< void >::NOTENOUGHENERGY;
1347  else if (target->graphicOptions.InWarp) //FIXME
1348  return (float) UnitImages< void >::OFF;
1349  else if (jumpok)
1350  return (float) UnitImages< void >::READY;
1351  else
1352  return (float) UnitImages< void >::TOOFAR;
1354  {
1355  Unit *station = target->Target();
1356  if (station)
1357  {
1358  if (station->CanDockWithMe(target, true) != -1)
1359  {
1360  if (station->CanDockWithMe(target, false) != -1)
1361  {
1362  return (float) UnitImages<void>::READY;
1363  }
1364  if (Orders::AutoDocking::CanDock(target, station))
1365  {
1366  return (float) UnitImages<void>::AUTOREADY;
1367  }
1368  return (float) UnitImages<void>::TOOFAR;
1369  }
1370  }
1371  return (float) UnitImages< void >::NOMINAL;
1372  }
1373  }
1374  return 1.0f;
1375 }
1376 
1377 void GameCockpit::DrawTargetGauges( Unit *target )
1378 {
1379  int i;
1380  //printf ("(debug)UNIT NAME:%s\n",UnitUtil::getName(target).c_str());
1381  //printf ("(debug)TARGETSHIELDF:%1.2f\n",target->FShieldData());
1382  for (i = UnitImages< void >::TARGETSHIELDF; i < UnitImages< void >::KPS; i++)
1383  if (gauges[i])
1384  gauges[i]->Draw( LookupTargetStat( i, target ) );
1385  if (!text)
1386  return;
1387 }
1388 
1389 void GameCockpit::DrawGauges( Unit *un )
1390 {
1391  int i;
1392  for (i = 0; i < UnitImages< void >::TARGETSHIELDF; i++) {
1393  if (gauges[i]) {
1394  gauges[i]->Draw( LookupUnitStat( i, un ) );
1395  float damage =
1397  if (gauge_time[i] >= 0) {
1398  if ( damage > .0001 && ( cockpit_time > ( gauge_time[i]+(1-damage) ) ) )
1399  if (rand01() > SWITCH_CONST)
1400  gauge_time[i] = -cockpit_time;
1401  /*else {
1402  * static string gauge_static = vs_config->getVariable("graphics","gauge_static","static.ani");
1403  * static Animation vdu_ani(gauge_static.c_str(),true,.1,BILINEAR);
1404  * vdu_ani.DrawAsVSSprite(gauges[i]);
1405  * }*/
1406  } else if ( cockpit_time > ( ( ( 1-(-gauge_time[i]) )+damage ) ) ) {
1407  if (rand01() > SWITCH_CONST)
1408  gauge_time[i] = cockpit_time;
1409  }
1410  }
1411  }
1412  if (!text)
1413  return;
1414  GFXColorf( textcol );
1415  GFXColor origbgcol = text->bgcol;
1416  static float background_alpha =
1417  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "text_background_alpha", "0.0625" ) );
1418  bool automatte = (0 == origbgcol.a);
1419  if (automatte) text->bgcol = GFXColor( 0, 0, 0, background_alpha );
1420  for (i = UnitImages< void >::KPS; i < UnitImages< void >::AUTOPILOT_MODAL; i++) {
1421  if (gauges[i]) {
1422  float sx, sy, px, py;
1423  gauges[i]->GetSize( sx, sy );
1424  gauges[i]->GetPosition( px, py );
1425  text->SetCharSize( sx, sy );
1426  text->SetPos( px, py );
1427  float tmp = LookupUnitStat( i, un );
1428  float tmp2 = 0;
1429  char ourchar[64];
1430  int len = sprintf( ourchar, "%.0f", tmp );
1431  if (i == UnitImages< void >::KPS) {
1432  float c = 300000000.0f;
1433  if (tmp > c/10) {
1434  tmp2 = tmp/c;
1435  len = sprintf( ourchar, "%.2f C", tmp2 );
1436  }
1437  }
1439  len = sprintf( ourchar, "MASS:%.0f%% (base)", tmp );
1440  GFXColorf( textcol );
1441  text->SetSize( 2, -2 );
1442  text->Draw( string( ourchar ), 0, false, false, automatte );
1443  }
1444  }
1445  for (i = UnitImages< void >::AUTOPILOT_MODAL; i < UnitImages< void >::NUMGAUGES; i++) {
1446  if (gauges[i]) {
1447  float sx, sy, px, py;
1448  gauges[i]->GetSize( sx, sy );
1449  gauges[i]->GetPosition( px, py );
1450  text->SetCharSize( sx, sy );
1451  text->SetPos( px, py );
1452  float tmp = LookupUnitStat( i, un );
1453  int ivalue = (int) tmp;
1454  std::string modename;
1455  std::string modevalue;
1456  switch (i)
1457  {
1459  modename = "AUTO:";
1460  break;
1462  modename = "SPEC:";
1463  break;
1465  modename = "FCMP:";
1466  break;
1468  modename = "TCNT:";
1469  break;
1471  modename = "ECM :";
1472  break;
1474  modename = "CLK :";
1475  break;
1477  modename = "GCNT:";
1478  break;
1480  modename = "RFIR:";
1481  break;
1483  modename = "RMIS:";
1484  break;
1486  modename = "RML :";
1487  break;
1489  modename = "RTL :";
1490  break;
1492  modename = "COL :";
1493  break;
1495  modename = "JUMP:";
1496  break;
1498  modename = "DOCK:";
1499  break;
1500  default:
1501  modename = "UNK :";
1502  }
1503  switch (ivalue)
1504  {
1506  modevalue = "OFF";
1507  break;
1509  modevalue = "ON";
1510  break;
1512  modevalue = "<>";
1513  break;
1515  modevalue = "ACTIVE";
1516  break;
1518  modevalue = "FAW";
1519  break;
1521  modevalue = "MANEUVER";
1522  break;
1524  modevalue = "TRAVEL";
1525  break;
1527  modevalue = "N / A";
1528  break;
1530  modevalue = "READY";
1531  break;
1533  modevalue = "NO DRIVE";
1534  break;
1536  modevalue = "TOO FAR";
1537  break;
1539  modevalue = "LOW ENERGY";
1540  break;
1542  modevalue = "WARNING!";
1543  break;
1545  modevalue = " - ";
1546  break;
1548  modevalue = "AUTO READY";
1549  break;
1550  default:
1551  modevalue = "MALFUNCTION!";
1552  }
1553  GFXColorf( textcol );
1554  //text->SetSize(px+textwidthapproxHACK*(modename.size()+modevalue.size()), -2);
1555  text->SetSize( 2, -2 );
1556  text->Draw( modename+modevalue, 0, false, false, automatte );
1557  }
1558  }
1559  text->bgcol = origbgcol;
1560  GFXColor4f( 1, 1, 1, 1 );
1561 }
1562 
1563 void GameCockpit::Init( const char *file )
1564 {
1565  smooth_fov = g_game.fov;
1566  editingTextMessage = false;
1567  armor8 = false;
1568  shield8 = false;
1569  Cockpit::Init( file );
1570  if (Panel.size() > 0) {
1571  float x, y;
1572  Panel.front()->GetPosition( x, y );
1573  Panel.front()->SetPosition( x, y+viewport_offset );
1574  }
1575 }
1576 
1577 void GameCockpit::Delete()
1578 {
1579  Cockpit::Delete();
1580 
1581  int i;
1582  if (text) {
1583  delete text;
1584  text = NULL;
1585  }
1586  for (i = 0; i < (int) mesh.size(); ++i) {
1587  if (mesh[i])
1588  delete mesh[i];
1589  mesh[i] = NULL;
1590  }
1591  mesh.clear();
1592  if (soundfile >= 0) {
1593  AUDStopPlaying( soundfile );
1594  AUDDeleteSound( soundfile, false );
1595  soundfile = -1;
1596  }
1597  for (i = 0; i < 4; i++) {
1598  /*
1599  * if (Pit[i]) {
1600  * delete Pit[i];
1601  * Pit[i] = NULL;
1602  * }
1603  */
1604  }
1605  for (i = 0; i < UnitImages< void >::NUMGAUGES; i++)
1606  if (gauges[i]) {
1607  delete gauges[i];
1608  gauges[i] = NULL;
1609  }
1610  if (radarSprites[0]) {
1611  delete radarSprites[0];
1612  radarSprites[0] = NULL;
1613  }
1614  if (radarSprites[1]) {
1615  delete radarSprites[1];
1616  radarSprites[1] = NULL;
1617  }
1618  unsigned int j;
1619  for (j = 0; j < vdu.size(); j++)
1620  if (vdu[j]) {
1621  delete vdu[j];
1622  vdu[j] = NULL;
1623  }
1624  vdu.clear();
1625  for (j = 0; j < Panel.size(); j++) {
1626  assert( Panel[j] );
1627  delete Panel[j];
1628  }
1629  Panel.clear();
1630 }
1631 
1633 {
1634  int i;
1635  for (i = 0; i < UnitImages< void >::NUMGAUGES; i++)
1636  gauge_time[i] = 0;
1637  for (i = 0; i < MAXVDUS; i++)
1638  vdu_time[i] = 0;
1639  radar_time = 0;
1640  cockpit_time = 0;
1641 }
1642 
1643 /***** WARNING CHANGED ORDER *****/
1644 GameCockpit::GameCockpit( const char *file, Unit *parent, const std::string &pilot_name )
1645  : Cockpit( file, parent, pilot_name )
1646  , insidePanYaw( 0 )
1647  , insidePanPitch( 0 )
1648  , insidePanYawSpeed( 0 )
1649  , insidePanPitchSpeed( 0 )
1650  , shake_time( 0 )
1651  , shake_type( 0 )
1652  , radarDisplay(0)
1653  , textcol( 1, 1, 1, 1 )
1654  , text( NULL )
1655 {
1656  autoMessageTime = 0;
1657  shield8 = armor8 = false;
1658  editingTextMessage = false;
1659  static int headlag = XMLSupport::parse_int( vs_config->getVariable( "graphics", "head_lag", "10" ) );
1660  int i;
1661  for (i = 0; i < headlag; i++) {
1662  headtrans.push_back( Matrix() );
1663  Identity( headtrans.back() );
1664  }
1665  for (i = 0; i < UnitImages< void >::NUMGAUGES; i++)
1666  gauges[i] = NULL;
1667  radarSprites[0] = radarSprites[1] = Pit[0] = Pit[1] = Pit[2] = Pit[3] = NULL;
1668 
1669  static bool st_draw_all_boxes =
1670  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawAllTargetBoxes", "false" ) );
1671  static bool st_draw_line_to_target =
1672  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawLineToTarget", "false" ) );
1673  static bool st_draw_line_to_targets_target =
1674  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawLineToTargetsTarget", "false" ) );
1675  static bool st_draw_line_to_itts =
1676  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawLineToITTS", "false" ) );
1677  static bool st_always_itts = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "drawAlwaysITTS", "false" ) );
1678  static bool st_steady_itts = XMLSupport::parse_bool( vs_config->getVariable( "physics", "steady_itts", "false" ) );
1679 
1680  draw_all_boxes = st_draw_all_boxes;
1681  draw_line_to_target = st_draw_line_to_target;
1682  draw_line_to_targets_target = st_draw_line_to_targets_target;
1683  draw_line_to_itts = st_draw_line_to_itts;
1684  always_itts = st_always_itts;
1685  steady_itts = st_steady_itts;
1686  last_locktime = last_mlocktime = -FLT_MAX;
1687 
1688  radarDisplay = Radar::Factory(Radar::Type::NullDisplay);
1689 
1690  //Compute the screen limits. Used to display the arrow pointing to the selected target.
1691  static float st_projection_limit_y = XMLSupport::parse_float( vs_config->getVariable( "graphics", "fov", "78" ) );
1692  smooth_fov = st_projection_limit_y;
1693  projection_limit_y = st_projection_limit_y;
1694  //The angle betwwen the center of the screen and the border is half the fov.
1695  projection_limit_y = tan( projection_limit_y*M_PI/(180*2) );
1696  projection_limit_x = projection_limit_y*g_game.aspect;
1697  //Precompute this division... performance.
1698  inv_screen_aspect_ratio = 1/g_game.aspect;
1699 
1700  oaccel = Vector( 0, 0, 0 );
1701 
1702  friendly = GFXColor( -1, -1, -1, -1 );
1703  enemy = GFXColor( -1, -1, -1, -1 );
1704  neutral = GFXColor( -1, -1, -1, -1 );
1705  targeted = GFXColor( -1, -1, -1, -1 );
1706  targetting = GFXColor( -1, -1, -1, -1 );
1707  planet = GFXColor( -1, -1, -1, -1 );
1708  soundfile = -1;
1709  if (friendly.r == -1) {
1710  vs_config->getColor( "enemy", &enemy.r );
1711  vs_config->getColor( "friend", &friendly.r );
1712  vs_config->getColor( "neutral", &neutral.r );
1713  vs_config->getColor( "target", &targeted.r );
1714  vs_config->getColor( "targetting_ship", &targetting.r );
1715  vs_config->getColor( "planet", &planet.r );
1716  }
1717  InitStatic();
1718  updateRadar(parent);
1719 }
1720 
1722 {
1723  SelectCamera( view );
1724 }
1725 
1726 extern vector< int >respawnunit;
1727 extern vector< int >switchunit;
1728 extern vector< int >turretcontrol;
1729 
1731 {
1734 }
1735 
1737 {
1738  //scheherazade
1739  if (k == PRESS) {
1740  //UniverseUtil::IOmessage(0,"game","all","hit key");
1741  if ( ( _Universe->AccessCockpit() )->CanDrawNavSystem() ) {
1743  //UniverseUtil::IOmessage(0,"game","all","DRAWNAV - OFF");
1744  RestoreMouse();
1745  } else {
1747  //UniverseUtil::IOmessage(0,"game","all","DRAWNAV - ON");
1748 
1752  }
1753  }
1754 }
1755 
1757 {
1758  ThisNav.SetDraw( what );
1759  return what;
1760 }
1761 
1763 {
1764  return ThisNav.CheckDraw();
1765 }
1766 
1768 {
1769  Cockpit::visitSystem( systemname );
1770  if ( AccessNavSystem() ) {
1771  static bool AlwaysUpdateNavMap =
1772  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "update_nav_after_jump", "false" ) ); //causes occasional crash--only may have tracked it down
1773  if (AlwaysUpdateNavMap)
1775  AccessNavSystem()->setCurrentSystem( systemname );
1776  }
1777 }
1778 
1780 {
1781  bool ret = ThisNav.CheckDraw();
1782  if (ret) {
1784  float c_o = cockpit_offset;
1785  float o_fov = cam->GetFov();
1786  static float standard_fov = XMLSupport::parse_float( vs_config->getVariable( "graphics", "base_fov", "90" ) );
1787  cam->SetFov( standard_fov );
1788  cam->setCockpitOffset( 0 );
1789  cam->UpdateGFX( GFXFALSE, GFXFALSE, GFXTRUE );
1790  ThisNav.Draw();
1791  cockpit_offset = c_o;
1792  cam->SetFov( o_fov );
1793  cam->setCockpitOffset( c_o );
1794  cam->UpdateGFX( GFXFALSE, GFXFALSE, GFXTRUE );
1795  }
1796  return ret;
1797 }
1798 
1799 void RespawnNow( Cockpit *cp )
1800 {
1801  while ( respawnunit.size() <= _Universe->numPlayers() )
1802  respawnunit.push_back( 0 );
1803  for (unsigned int i = 0; i < _Universe->numPlayers(); i++)
1804  if (_Universe->AccessCockpit( i ) == cp)
1805  respawnunit[i] = 2;
1806 }
1807 
1809 {
1810  if (k == PRESS) {
1811  while ( switchunit.size() <= _Universe->CurrentCockpit() )
1812  switchunit.push_back( 0 );
1813  switchunit[_Universe->CurrentCockpit()] = 1;
1814  }
1815 }
1816 
1818 {
1819  while ( switchunit.size() <= _Universe->CurrentCockpit() )
1820  switchunit.push_back( 0 );
1821  switchunit[_Universe->CurrentCockpit()] = 1;
1822 }
1823 
1824 void SuicideKey( const KBData&, KBSTATE k )
1825 {
1826  static int orig = 0;
1827  if (k == PRESS) {
1828  int newtime = time( NULL );
1829  if (newtime-orig > 8 || orig == 0) {
1830  orig = newtime;
1831  Unit *un = NULL;
1832  if ( ( un = _Universe->AccessCockpit()->GetParent() ) ) {
1833  float armor[8]; //short fix
1834  un->ArmorData( armor );
1835  un->DealDamageToHull( Vector( 0, 0,
1836  .1 ), un->GetHull()*256.+2+2
1837  *(armor[1]+armor[2]+armor[3]+armor[4]+armor[5]+armor[6]+armor[7]+armor[0]) );
1838  }
1839  }
1840  }
1841 }
1842 
1843 class UnivMap
1844 {
1845  VSSprite *ul;
1846  VSSprite *ur;
1847  VSSprite *ll;
1848  VSSprite *lr;
1849 public:
1850  bool isNull()
1851  {
1852  return ul == NULL;
1853  }
1854  UnivMap( VSSprite *ull, VSSprite *url, VSSprite *lll, VSSprite *lrl )
1855  {
1856  ul = ull;
1857  ur = url;
1858  ll = lll;
1859  lr = lrl;
1860  }
1861  void Draw()
1862  {
1863  if (ul || ur || ll || lr) {
1865  GFXEnable( TEXTURE0 );
1866  GFXDisable( TEXTURE1 );
1867  GFXColor4f( 1, 1, 1, 1 );
1868  }
1869  if (ul)
1870  ul->Draw();
1871  if (ur)
1872  ur->Draw();
1873  if (ll)
1874  ll->Draw();
1875  if (lr)
1876  lr->Draw();
1877  }
1878 };
1879 
1880 std::vector< UnivMap >univmap;
1881 
1882 void MapKey( const KBData&, KBSTATE k )
1883 {
1884  if (k == PRESS) {
1885  static VSSprite ul( "upper-left-map.spr" );
1886  static VSSprite ur( "upper-right-map.spr" );
1887  static VSSprite ll( "lower-left-map.spr" );
1888  static VSSprite lr( "lower-right-map.spr" );
1889  while ( univmap.size() <= _Universe->CurrentCockpit() )
1890  univmap.push_back( UnivMap( NULL, NULL, NULL, NULL ) );
1891  if ( univmap[_Universe->CurrentCockpit()].isNull() )
1892  univmap[_Universe->CurrentCockpit()] = UnivMap( &ul, &ur, &ll, &lr );
1893  else
1894  univmap[_Universe->CurrentCockpit()] = UnivMap( NULL, NULL, NULL, NULL );
1895  }
1896 }
1897 
1899 {
1900  if (k == PRESS) {
1901  while ( turretcontrol.size() <= _Universe->CurrentCockpit() )
1902  turretcontrol.push_back( 0 );
1903  turretcontrol[_Universe->CurrentCockpit()] = 1;
1904  }
1905 }
1906 
1908 {
1909  if (k == PRESS) {
1910  while ( respawnunit.size() <= _Universe->CurrentCockpit() )
1911  respawnunit.push_back( 0 );
1912  respawnunit[_Universe->CurrentCockpit()] = 1;
1913  }
1914 }
1915 
1916 //SAME AS IN COCKPIT BUT ADDS SETVIEW and ACCESSCAMERA -> ~ DUPLICATE CODE
1918 {
1919  static bool autopan = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "pan_on_auto", "true" ) );
1920  int retauto = 0;
1921  if (target) {
1922  if (enableautosound.sound < 0) {
1923  static string str = vs_config->getVariable( "cockpitaudio", "autopilot_enabled", "autopilot" );
1924  enableautosound.loadsound( str );
1925  }
1926  enableautosound.playsound();
1927  Unit *un = NULL;
1928  if ( ( un = GetParent() ) ) {
1929  autoMessage = std::string();
1931  QVector posA = un->LocalPosition();
1932  bool retautoA = false;
1933  if ( ( retauto = retautoA = un->AutoPilotToErrorMessage( un, false, autoMessage ) ) ) {
1934  //can he even start to autopilot
1935  retauto = un->AutoPilotToErrorMessage( target, false, autoMessage );
1936  QVector posB = un->LocalPosition();
1937  bool movedatall = (posA-posB).Magnitude() > un->rSize();
1938  if (autoMessage.length() == 0 && !movedatall) {
1939  autoMessage =
1940  XMLSupport::escaped_string( vs_config->getVariable( "graphics", "hud", "AlreadyNearMessage",
1941  "#ff0000Already Near#000000" ) );
1942  retauto = false;
1943  } else if ( (retauto || retautoA) && movedatall ) {
1944  if (autopan) {
1945  SetView( CP_FIXEDPOS );
1946  Vector P( 1, 0, 0 ), Q( 0, 1, 0 ), R( 0, 0, 1 );
1947  Vector uP, uQ, uR;
1948  un->GetOrientation( uP, uQ, uR );
1949  static float auto_side_bias =
1950  XMLSupport::parse_float( vs_config->getVariable( "graphics", "autopilot_side_bias", "1.1" ) );
1951  static float auto_front_bias =
1952  XMLSupport::parse_float( vs_config->getVariable( "graphics", "autopilot_front_bias", "1.65" ) );
1953  P += uP*auto_side_bias+uR*auto_front_bias;
1954  P.Normalize();
1955  R = P.Cross( Q );
1956  AccessCamera( CP_FIXED )->SetPosition( un->LocalPosition()+2*un->rSize()*P,
1957  Vector( 0, 0, 0 ), Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
1958  AccessCamera( CP_FIXED )->SetOrientation( R, Q, -P );
1959  AccessCamera( CP_FIXEDPOS )->SetPosition( un->LocalPosition()+2*un->rSize()*P, Vector( 0,
1960  0,
1961  0 ),
1962  Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
1963  AccessCamera( CP_FIXEDPOS )->SetOrientation( R, Q, -P );
1964  }
1965 
1966  static float autotime = XMLSupport::parse_float( vs_config->getVariable( "physics", "autotime", "10" ) ); //10 seconds for auto to kick in;
1967 
1968  autopilot_time = autotime;
1969  autopilot_target.SetUnit( target );
1970  }
1971  }
1972  }
1973  }
1974  return retauto;
1975 }
1976 
1977 extern void reset_time_compression( const KBData&, KBSTATE a );
1978 
1979 void GameCockpit::Shake( float amt, int dtype )
1980 {
1981  static float shak = XMLSupport::parse_float( vs_config->getVariable( "graphics", "cockpit_shake", "3" ) );
1982  static float shak_max = XMLSupport::parse_float( vs_config->getVariable( "graphics", "cockpit_shake_max", "20" ) );
1983  shakin += shak;
1984  if (shakin > shak_max)
1985  shakin = shak_max;
1986  this->shake_time = getNewTime();
1987  this->shake_type = dtype;
1988 }
1989 
1990 static void DrawDamageFlash( int dtype )
1991 {
1992  const int numtypes = 3;
1993  static string shieldflash = vs_config->getVariable( "graphics", "shield_flash_animation", "" );
1994  static string armorflash = vs_config->getVariable( "graphics", "armor_flash_animation", "armorflash.ani" );
1995  static string hullflash = vs_config->getVariable( "graphics", "hull_flash_animation", "hullflash.ani" );
1996  string flashes[numtypes];
1997  flashes[0] = shieldflash;
1998  flashes[1] = armorflash;
1999  flashes[2] = hullflash;
2000  float fallbackcolor[numtypes][4] = {
2001  {0, 1, .5, .2}, {1, 0, .2, .25}, {1, 0, 0, .5}
2002  };
2003 
2004  static bool init = false;
2005  static Animation *aflashes[numtypes];
2006  static bool doflash[numtypes];
2007  if (!init) {
2008  init = true;
2009  for (int i = 0; i < numtypes; ++i) {
2010  doflash[i] = (flashes[i].length() > 0);
2011  if (doflash[i])
2012  aflashes[i] = new Animation( flashes[i].c_str(), true, .1, BILINEAR, false, false );
2013  else
2014  aflashes[i] = NULL;
2015  }
2016  vs_config->getColor( "shield_flash", fallbackcolor[0] );
2017  vs_config->getColor( "armor_flash", fallbackcolor[1] );
2018  vs_config->getColor( "hull_flash", fallbackcolor[2] );
2019  }
2020  if (dtype < numtypes) {
2021  int i = dtype;
2022  if (aflashes[i]) {
2023  GFXPushBlendMode();
2024  static bool damage_flash_alpha =
2025  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "damage_flash_alpha", "true" ) );
2026  if (damage_flash_alpha)
2028  else
2029  GFXBlendMode( ONE, ZERO );
2030  if ( aflashes[i]->LoadSuccess() ) {
2031  aflashes[i]->MakeActive();
2032  GFXColor4f( 1, 1, 1, 1 );
2033  GFXBegin( GFXQUAD );
2034  float width = 1, height = 1;
2035  GFXTexCoord2f( 0.00F, 1.00F );
2036  GFXVertex3f( -width, -height, 1.00F ); //lower left
2037  GFXTexCoord2f( 1.00F, 1.00F );
2038  GFXVertex3f( width, -height, 1.00F ); //upper left
2039  GFXTexCoord2f( 1.00F, 0.00F );
2040  GFXVertex3f( width, height, 1.00F ); //upper right
2041  GFXTexCoord2f( 0.00F, 0.00F );
2042  GFXVertex3f( -width, height, 1.00F ); //lower right
2043  GFXEnd();
2044  } else {
2045  GFXColor4f( fallbackcolor[i][0],
2046  fallbackcolor[i][1],
2047  fallbackcolor[i][2],
2048  fallbackcolor[i][3] );
2049  GFXDisable( TEXTURE0 );
2050  GFXBegin( GFXQUAD );
2051  GFXVertex3f( -1.0f, -1.0f, 1.0f );
2052  GFXVertex3f( -1.0f, 1.0f, 1.0f );
2053  GFXVertex3f( 1.0f, 1.0f, 1.0f );
2054  GFXVertex3f( 1.0f, -1.0f, 1.0f );
2055  GFXEnd();
2056  GFXEnable( TEXTURE0 );
2057  }
2058  GFXPopBlendMode();
2059  }
2060  }
2061  GFXColor4f( 1, 1, 1, 1 );
2062 }
2063 
2064 static void DrawCrosshairs( float x, float y, float wid, float hei, const GFXColor &col )
2065 {
2066  GFXColorf( col );
2067  GFXDisable( TEXTURE0 );
2068  GFXDisable( LIGHTING );
2070  GFXEnable( SMOOTH );
2071  GFXCircle( x, y, wid/4, hei/4 );
2072  GFXCircle( x, y, wid/7, hei/7 );
2073  GFXDisable( SMOOTH );
2074  GFXBegin( GFXLINE );
2075  GFXVertex3f( x-(wid/2), y, 0 );
2076  GFXVertex3f( x-(wid/6), y, 0 );
2077  GFXVertex3f( x+(wid/2), y, 0 );
2078  GFXVertex3f( x+(wid/6), y, 0 );
2079  GFXVertex3f( x, y-(hei/2), 0 );
2080  GFXVertex3f( x, y-(hei/6), 0 );
2081  GFXVertex3f( x, y+(hei/2), 0 );
2082  GFXVertex3f( x, y+(hei/6), 0 );
2083  GFXVertex3f( x-.001, y+.001, 0 );
2084  GFXVertex3f( x+.001, y-.001, 0 );
2085  GFXVertex3f( x+.001, y+.001, 0 );
2086  GFXVertex3f( x-.001, y-.001, 0 );
2087  GFXEnd();
2088  GFXEnable( TEXTURE0 );
2089 }
2090 
2091 extern bool QuitAllow;
2092 extern bool screenshotkey;
2093 QVector SystemLocation( std::string system );
2094 double howFarToJump();
2095 
2097 {
2098  static bool draw_star_destination_arrow =
2099  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "draw_star_direction", "true" ) );
2100  static GFXColor destination_system_color = DockBoxColor( "destination_system_color" );
2101  Vector destination_system_location( 0, 0, 0 );
2103  if (cockpit_time >= 100000)
2104  InitStatic();
2105  _Universe->AccessCamera()->UpdateGFX( GFXFALSE, GFXFALSE, GFXTRUE ); //Preliminary frustum
2106  GFXDisable( TEXTURE0 );
2107  GFXDisable( TEXTURE1 );
2109  GFXDisable( LIGHTING );
2110  GFXDisable( DEPTHTEST );
2112  GFXColor4f( 1, 1, 1, 1 );
2113  std::string nav_current = AccessNavSystem()->getCurrentSystem();
2114  std::string universe_current = _Universe->activeStarSystem()->getFileName();
2115  if (nav_current != universe_current)
2116  AccessNavSystem()->Setup();
2117  static bool draw_any_boxes =
2118  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "DrawTargettingBoxes", "true" ) );
2119  static bool draw_boxes_inside_only =
2120  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "DrawTargettingBoxesInside", "true" ) );
2121  if ( draw_any_boxes && screenshotkey == false && (draw_boxes_inside_only == false || view < CP_CHASE) )
2122  {
2123  Unit *player = GetParent();
2124  if (player)
2125  {
2126  Radar::Sensor sensor(player);
2127  DrawTargetBox(sensor);
2128  DrawTurretTargetBoxes(sensor);
2129  DrawTacticalTargetBox(sensor);
2130  DrawCommunicatingBoxes();
2131  if (draw_all_boxes)
2132  DrawTargetBoxes(sensor);
2133  }
2134  if (draw_star_destination_arrow) {
2135  std::string destination_system = AccessNavSystem()->getSelectedSystem();
2136  std::string current_system = _Universe->activeStarSystem()->getFileName();
2137  if (destination_system != current_system) {
2138  QVector cur = SystemLocation( current_system );
2139  QVector dest = SystemLocation( destination_system );
2140  QVector delta = dest-cur;
2141  if (delta.i != 0 || dest.j != 0 || dest.k != 0) {
2142  delta.Normalize();
2143  Unit *par = GetParent();
2144  delta = delta*howFarToJump()*1.01-( par ? ( par->Position() ) : QVector( 0, 0, 0 ) );
2145  destination_system_location = delta.Cast();
2146  Vector P, Q, R;
2147  static float nav_symbol_size =
2148  XMLSupport::parse_float( vs_config->getVariable( "graphics", "nav_symbol_size", ".25" ) );
2149  AccessCamera()->GetPQR( P, Q, R );
2150 
2151  GFXColor4f( destination_system_color.r,
2152  destination_system_color.g,
2153  destination_system_color.b,
2154  destination_system_color.a );
2155 
2156  static GFXColor suncol = RetrColor( "remote_star", GFXColor( 0, 1, 1, .8 ) );
2157  GFXColorf( suncol );
2158  DrawNavigationSymbol( delta.Cast(), P, Q, delta.Magnitude()*nav_symbol_size );
2159 
2160  GFXColor4f( 1, 1, 1, 1 );
2161  }
2162  }
2163  }
2164  }
2165  GFXEnable( TEXTURE0 );
2166  GFXEnable( DEPTHTEST );
2167  GFXEnable( DEPTHWRITE );
2168  if (view < CP_CHASE) {
2169 /*broken velocity inidcator
2170  * static bool draw_velocity_indicator=XMLSupport::parse_bool(vs_config->getVariable("graphics","draw_velocity_indicator","true"));
2171  * if (draw_velocity_indicator) {
2172  * Vector P,Q,R;
2173  * Unit *par=GetParent();
2174  * if (par ) {
2175  * Vector vel=par->Velocity;
2176  * float speed=vel.Magnitude();
2177  * static float nav_symbol_size = XMLSupport::parse_float(vs_config->getVariable("graphics","nav_symbol_size",".25"));
2178  * AccessCamera()->GetPQR (P,Q,R);
2179  * DrawNavigationSymbol(vel,P,Q,speed*nav_symbol_size);
2180  * }
2181  * }*/
2182  if ( mesh.size() ) {
2183  Unit *par = GetParent();
2184  if (par) {
2185  //cockpit is unaffected by FOV WARP-Link
2186  float oldfov = AccessCamera()->GetFov();
2187  AccessCamera()->SetFov( g_game.fov );
2188 
2190 
2191  size_t i, j;
2192  float cockpitradial = 1; //LET IT NOT BE ZERO!
2193  for (i = 0; i < mesh.size(); ++i) {
2194  float meshmaxdepth = mesh[i]->corner_min().Max( mesh[i]->corner_max() ).Magnitude();
2195  if (meshmaxdepth > cockpitradial)
2196  cockpitradial = meshmaxdepth;
2197  }
2198  cockpitradial *= COCKPITZ_HEADROOM;
2199 
2200  GFXEnable( DEPTHTEST );
2201  GFXEnable( DEPTHWRITE );
2202  GFXEnable( TEXTURE0 );
2203  GFXEnable( LIGHTING );
2204  Vector P, Q, R;
2205  AccessCamera( CP_FRONT )->GetPQR( P, Q, R );
2206 
2207  headtrans.clear();
2208 
2209  headtrans.push_back( Matrix() );
2210  VectorAndPositionToMatrix( headtrans.back(), P, Q, R, QVector( 0, 0, 0 ) );
2211  static float theta = 0, wtheta = 0;
2212  static float shake_speed =
2213  XMLSupport::parse_float( vs_config->getVariable( "graphics", "shake_speed", "50" ) );
2214  static float shake_reduction =
2215  XMLSupport::parse_float( vs_config->getVariable( "graphics", "shake_reduction", "8" ) );
2216  static float shake_limit =
2217  XMLSupport::parse_float( vs_config->getVariable( "graphics", "shake_limit", "25" ) );
2218  static float shake_mag = XMLSupport::parse_float( vs_config->getVariable( "graphics", "shake_magnitude", "0.3" ) );
2219  static float drift_limit =
2220  XMLSupport::parse_float( vs_config->getVariable( "graphics", "cockpit_drift_limit", "1.00" ) );
2221  static float drift_amount =
2222  XMLSupport::parse_float( vs_config->getVariable( "graphics", "cockpit_drift_amount", "0.15" ) );
2223  static float drift_ref_accel =
2224  XMLSupport::parse_float( vs_config->getVariable( "graphics", "cockpit_drift_ref_accel", "100" ) );
2225 
2226  static float warp_shake_mag =
2227  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp_shake_magnitude", "0.125" ) );
2228  static float warp_shake_speed =
2229  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp_shake_speed", "70" ) );
2230  static float warp_shake_ref =
2231  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp_shake_ref", "2000" ) );
2232  if (warp_shake_ref <= 0) warp_shake_ref = 1;
2233  theta += shake_speed*GetElapsedTime()*sqrt( fabs( shakin ) )/10; //For small shakes, slower shakes
2234  wtheta += warp_shake_speed*GetElapsedTime(); //SPEC-related shaking
2235 
2236  float self_kps = ( (GetParent() != NULL) ? LookupUnitStat( UnitImages< void >::KPS, GetParent() ) : 0 );
2237  float self_setkps =
2238  max( 1.0f, ( (GetParent() != NULL) ? LookupUnitStat( UnitImages< void >::SETKPS, GetParent() ) : 0 ) );
2239  float warp_strength =
2240  max( 0.0f,
2241  min( max( 0.0f,
2242  min( 1.0f,
2243  self_kps/self_setkps ) ),
2245  GetParent() ) : 0.0f )/warp_shake_ref ) );
2246  if (shakin > shake_limit) shakin = shake_limit;
2247  headtrans.front().p.i = shake_mag*shakin*cos( theta )*cockpitradial/100; //AccessCamera()->GetPosition().i+shakin*cos(theta);
2248  headtrans.front().p.j = shake_mag*shakin*cos( 1.3731*theta )*cockpitradial/100; //AccessCamera()->GetPosition().j+shakin*cos(theta);
2249  headtrans.front().p.k = 0; //AccessCamera()->GetPosition().k;
2250  headtrans.front().p.i += warp_shake_mag*cos( wtheta )*sqr( warp_strength )*cockpitradial/100; //AccessCamera()->GetPosition().i+shakin*cos(theta);
2251  headtrans.front().p.j += warp_shake_mag*cos( 1.165864*wtheta )*sqr( warp_strength )*cockpitradial/100; //AccessCamera()->GetPosition().j+shakin*cos(theta);
2252  if (shakin > 0) {
2253  shakin -= GetElapsedTime()*shake_reduction*(shakin/5); //Fast convergence to 5% shaking, slow stabilization
2254  if (shakin <= 0)
2255  shakin = 0;
2256  }
2257  //Now, compute head drift
2259  float mag = caccel.Magnitude();
2260  float ref = drift_ref_accel*drift_ref_accel;
2261  if ( (mag > 0) && (ref > 0) ) caccel *= -( drift_amount*min( drift_limit, (float) (mag*mag/ref) ) )/mag;
2262 
2263  else caccel = Vector( 0, 0, 0 );
2264  float driftphase = pow( 0.25, GetElapsedTime() );
2265  oaccel = (1-driftphase)*caccel+driftphase*oaccel;
2266  headtrans.front().p += -cockpitradial*oaccel;
2267  float driftmag = cockpitradial*oaccel.Magnitude();
2268 
2269  //if (COCKPITZ_PARTITIONS>1) GFXClear(GFXFALSE,GFXFALSE,GFXTRUE);//only clear stencil buffer
2270  static size_t COCKPITZ_PARTITIONS =
2271  XMLSupport::parse_int( vs_config->getVariable( "graphics", "cockpit_z_partitions", "1" ) ); //Should not be needed if VERYNEAR_CONST is propperly set, but would be useful with stenciled inverse order rendering.
2272  float zrange = cockpitradial*(1-VERYNEAR_CONST)+driftmag;
2273  float zfloor = cockpitradial*VERYNEAR_CONST;
2274  for (j = COCKPITZ_PARTITIONS-1; j < COCKPITZ_PARTITIONS; j--) { //FIXME This is a program lockup!!! (actually, no; j is a size_t...)
2276  GFXTRUE,
2277  GFXTRUE,
2278  GFXTRUE,
2279  zfloor+zrange*j/COCKPITZ_PARTITIONS,
2280  zfloor+zrange*(j+1)/COCKPITZ_PARTITIONS ); //cockpit-specific frustrum (with clipping, with frustrum update)
2281  GFXClear( GFXFALSE, GFXTRUE, GFXFALSE ); //only clear Z
2282  /*if (COCKPITZ_PARTITIONS>1) {
2283  * //Setup stencil
2284  * GFXStencilOp(KEEP,KEEP,REPLACE);
2285  * GFXStencilFunc(LEQUAL,COCKPITZ_PARTITIONS-j,~0);
2286  * GFXStencilMask(~0);
2287  * GFXEnable(STENCIL);
2288  * };*/
2290  for (i = 0; i < mesh.size(); ++i)
2291  //mesh[i]->DrawNow(1,true,headtrans.front());
2292  mesh[i]->Draw( FLT_MAX, headtrans.front() );
2293  //Whether cockpits shouldn't cull faces - not sure why, probably because
2294  //modellers always set normals the wrong way for cockpits.
2295  static bool nocockpitcull =
2296  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "cockpit_no_face_cull", "true" ) );
2297 
2298  Mesh::ProcessZFarMeshes( true );
2299  if (nocockpitcull) GFXDisable( CULLFACE );
2300  Mesh::ProcessUndrawnMeshes( false, true );
2301  }
2302  headtrans.pop_front();
2303  //if (COCKPITZ_PARTITIONS>1) GFXDisable(STENCIL);
2304  GFXDisable( LIGHTING );
2305  GFXDisable( TEXTURE0 );
2306  GFXDisable( TEXTURE1 );
2307  AccessCamera()->SetFov( oldfov );
2308  }
2309  }
2310  _Universe->AccessCamera()->UpdateGFX( GFXFALSE, GFXFALSE, GFXTRUE, GFXFALSE, 0, 1000000 ); //Restore normal frustrum
2311  }
2312  GFXHudMode( true );
2313  static float damage_flash_length = XMLSupport::parse_float( vs_config->getVariable( "graphics", "damage_flash_length", ".1" ) );
2314  static bool damage_flash_first = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "flash_behind_hud", "true" ) );
2315  if (view < CP_CHASE && damage_flash_first && getNewTime()-shake_time < damage_flash_length)
2316  DrawDamageFlash( shake_type );
2317  GFXColor4f( 1, 1, 1, 1 );
2318  GFXBlendMode( ONE, ONE );
2319  GFXDisable( DEPTHTEST );
2321 
2322  Unit *un;
2323  float crosscenx = 0, crossceny = 0;
2324  static bool crosshairs_on_chasecam =
2325  parse_bool( vs_config->getVariable( "graphics", "hud", "crosshairs_on_chasecam", "false" ) );
2326  static bool crosshairs_on_padlock =
2327  parse_bool( vs_config->getVariable( "graphics", "hud", "crosshairs_on_padlock", "false" ) );
2328  if ( (view == CP_FRONT)
2329  || (view == CP_CHASE && crosshairs_on_chasecam)
2330  || ((view == CP_VIEWTARGET || view == CP_PANINSIDE) && crosshairs_on_padlock) ) {
2331  if (Panel.size() > 0 && Panel.front() && screenshotkey == false) {
2332  static bool drawCrosshairs =
2333  parse_bool( vs_config->getVariable( "graphics", "hud", "draw_rendered_crosshairs",
2334  vs_config->getVariable( "graphics", "draw_rendered_crosshairs", "true" ) ) );
2335  Panel.front()->GetPosition( crosscenx, crossceny );
2336  if (drawCrosshairs) {
2337  float x, y, wid, hei;
2338  Panel.front()->GetSize( wid, hei );
2339  x = crosscenx;
2340  y = crossceny;
2341  DrawCrosshairs( x, y, wid, hei, textcol );
2342  } else {
2344  GFXEnable( TEXTURE0 );
2345  Panel.front()->Draw(); //draw crosshairs
2346  }
2347  }
2348  }
2350  GFXEnable( TEXTURE0 );
2351 
2352  RestoreViewPort();
2353 
2354  static bool blend_panels = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "blend_panels", "false" ) );
2355  static bool blend_cockpit = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "blend_cockpit", "false" ) );
2356  static bool drawChaseVDU =
2357  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_vdus_from_chase_cam", "false" ) );
2358  static bool drawPanVDU =
2359  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_vdus_from_panning_cam", "false" ) );
2360  static bool drawTgtVDU =
2361  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_vdus_from_target_cam", "false" ) );
2362  static bool drawPadVDU =
2363  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_vdus_from_padlock_cam", "false" ) );
2364 
2365  static bool drawChasecp =
2366  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_cockpit_from_chase_cam", "false" ) );
2367  static bool drawPancp =
2368  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_cockpit_from_panning_cam", "false" ) );
2369  static bool drawTgtcp =
2370  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_cockpit_from_target_cam", "false" ) );
2371  static bool drawPadcp =
2372  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "draw_cockpit_from_padlock_cam", "false" ) );
2373 
2374  static float AlphaTestingCutoff = XMLSupport::parse_float( vs_config->getVariable( "graphics", "AlphaTestCutoff", ".8" ) );
2375  if (blend_cockpit) {
2376  GFXAlphaTest( ALWAYS, 0 );
2378  } else {
2379  GFXBlendMode( ONE, ZERO );
2380  GFXAlphaTest( GREATER, AlphaTestingCutoff );
2381  }
2382  GFXColor4f( 1, 1, 1, 1 );
2383  if (view < CP_CHASE) {
2384  if (Pit[view])
2385  Pit[view]->Draw();
2386  } else if ( (view == CP_CHASE
2387  && drawChasecp)
2388  || (view == CP_PAN && drawPancp) || (view == CP_TARGET && drawTgtcp) || ((view == CP_VIEWTARGET || view == CP_PANINSIDE) && drawPadcp) ) {
2389  if (Pit[0])
2390  Pit[0]->Draw();
2391  }
2392  if (blend_panels) {
2393  GFXAlphaTest( ALWAYS, 0 );
2395  } else {
2396  GFXBlendMode( ONE, ZERO );
2397  GFXAlphaTest( GREATER, AlphaTestingCutoff );
2398  }
2399  GFXColor4f( 1, 1, 1, 1 );
2400  if ( view == CP_FRONT
2401  || (view == CP_CHASE
2402  && drawChaseVDU)
2403  || (view == CP_PAN && drawPanVDU) || (view == CP_TARGET && drawTgtVDU) || ((view == CP_VIEWTARGET || view == CP_PANINSIDE) && drawPadVDU) ) {
2404  for (unsigned int j = 1; j < Panel.size(); j++)
2405  if (Panel[j])
2406  Panel[j]->Draw();
2407  }
2408  GFXAlphaTest( ALWAYS, 0 );
2410  GFXColor4f( 1, 1, 1, 1 );
2411  bool die = true;
2412  //draw target gauges
2413  for (unsigned int vd = 0; vd < vdu.size(); vd++)
2414  if (vdu[vd]->getMode() == VDU::TARGET) {
2415  if ( ( un = parent.GetUnit() ) ) {
2416  Unit *target = parent.GetUnit()->Target();
2417  if (target != NULL) {
2418  if ( view == CP_FRONT
2419  || (view == CP_CHASE
2420  && drawChaseVDU)
2421  || (view == CP_PAN
2422  && drawPanVDU) || (view == CP_TARGET && drawTgtVDU) || ((view == CP_VIEWTARGET || view == CP_PANINSIDE) && drawPadVDU) ) //{ //only draw crosshairs for front view
2423  //if (!UnitUtil::isSignificant(target)&&!UnitUtil::isSun(target)||UnitUtil::isCapitalShip(target)) //{
2424  DrawTargetGauges( target );
2425  }
2426  }
2427  }
2428  //draw unit gauges
2429  if ( ( un = parent.GetUnit() ) ) {
2430  if ( view == CP_FRONT
2431  || (view == CP_CHASE
2432  && drawChaseVDU)
2433  || (view == CP_PAN && drawPanVDU) || (view == CP_TARGET && drawTgtVDU) || ((view == CP_VIEWTARGET || view == CP_PANINSIDE) && drawPadVDU) ) {
2434  //only draw crosshairs for front view
2435  DrawGauges( un );
2436  Radar::Sensor sensor(un);
2437  DrawRadar(sensor);
2438 
2439  GFXColor4f( 1, 1, 1, 1 );
2440  for (unsigned int vd = 0; vd < vdu.size(); vd++)
2441  if (vdu[vd]) {
2442  vdu[vd]->Draw( this, un, textcol );
2443  GFXColor4f( 1, 1, 1, 1 );
2444  float damage = un->GetImageInformation().cockpit_damage[(1+vd)%(MAXVDUS+1)];
2445  if ( vdu[vd]->staticable() ) {
2446  if (damage < .985) {
2447  if (vdu_time[vd] >= 0) {
2448  if ( damage > .001 && ( cockpit_time > ( vdu_time[vd]+(1-damage) ) ) )
2449  if (rand01() > SWITCH_CONST)
2450  vdu_time[vd] = -cockpit_time;
2451  /*else {
2452  * static string vdustatic=vs_config->getVariable("graphics","vdu_static","static.ani");
2453  * static Animation vdu_ani(vdustatic.c_str(),true,.1,BILINEAR);
2454  * static soundContainer ejectstopsound;
2455  * if (ejectstopsound.sound<0) {
2456  * static string str=vs_config->getVariable("cockpitaudio","vdu_static","vdu_static");
2457  * ejectstopsound.loadsound(str);
2458  * }
2459  * if (!AUDIsPlaying(ejectstopsound.sound)) {
2460  * ejectstopsound.playsound();
2461  * }
2462  *
2463  * GFXEnable(TEXTURE0);
2464  * vdu_ani.DrawAsVSSprite(vdu[vd]);
2465  *
2466  * }*/
2467  } else if ( cockpit_time > ( ( 1-(-vdu_time[vd]) )+(damage) ) ) {
2468  if (rand01() > SWITCH_CONST)
2469  vdu_time[vd] = cockpit_time;
2470  }
2471  }
2472  }
2473  }
2474  //process VDU, damage VDU, targetting VDU
2476  static bool debug_position =
2477  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "debug_position", "false" ) );
2478  if (debug_position) {
2479  TextPlane tp;
2480  char str[400]; //don't make the sprintf format too big... :-P
2481  Unit *you = parent.GetUnit();
2482  if (you) {
2483  sprintf( str, "Your Position: (%lf,%lf,%lf); Velocity: (%f,%f,%f); Frame: %lf\n",
2485  you->curr_physical_state.position.k, you->Velocity.i, you->Velocity.j, you->Velocity.k,
2486  getNewTime() );
2487  Unit *yourtarg = you->computer.target.GetUnit();
2488  if (yourtarg) {
2489  sprintf( str+strlen(
2490  str ), "Target Position: (%lf,%lf,%lf); Velocity: (%f,%f,%f); Now: %lf\n",
2491  yourtarg->curr_physical_state.position.i, yourtarg->curr_physical_state.position.j,
2492  yourtarg->curr_physical_state.position.k, yourtarg->Velocity.i, yourtarg->Velocity.j,
2493  yourtarg->Velocity.k, queryTime() );
2494  }
2495  }
2496  tp.SetPos( -0.8, -0.8 );
2497  tp.SetText( str );
2498  tp.Draw();
2499  }
2501  }
2502  GFXColor4f( 1, 1, 1, 1 );
2503  if (un->GetHull() >= 0)
2504  die = false;
2505  if (un->Threat() != NULL) {
2506  if (0 && getTimeCompression() > 1)
2507  reset_time_compression( std::string(), PRESS );
2508  un->Threaten( NULL, 0 );
2509  }
2510  if ( _Universe->CurrentCockpit() < univmap.size() )
2511  univmap[_Universe->CurrentCockpit()].Draw();
2512  //Draw the arrow to the target.
2513  static bool drawarrow =
2514  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "draw_arrow_to_target", "true" ) );
2515  static bool drawarrow_on_pancam =
2516  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "draw_arrow_on_pancam", "false" ) );
2517  static bool drawarrow_on_pantgt =
2518  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "draw_arrow_on_pantgt", "false" ) );
2519  static bool drawarrow_on_chasecam =
2520  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "draw_arrow_on_chasecam", "true" ) );
2521  {
2522  //printf("view: %i\n",view);
2523  Unit *parent = NULL;
2524  if ( drawarrow && ( parent = this->parent.GetUnit() ) ) {
2525  Radar::Sensor sensor(parent);
2526  if ( (view == CP_PAN
2527  && !drawarrow_on_pancam)
2528  || (view == CP_PANTARGET
2529  && !drawarrow_on_pantgt) || (view == CP_CHASE && !drawarrow_on_chasecam) ) {} else {
2530  DrawArrowToTarget(sensor, parent->Target());
2531  if ( draw_star_destination_arrow
2532  && (destination_system_location.i || destination_system_location.j
2533  || destination_system_location.k) ) {
2534  GFXColorf( destination_system_color );
2535  DrawArrowToTarget(sensor, parent->ToLocalCoordinates(destination_system_location));
2536  }
2537  }
2538  }
2539  } //end: draw arrow
2540  }
2541  AutoLanding();
2542  GFXColor4f( 1, 1, 1, 1 );
2543  if (QuitAllow || getTimeCompression() < .5) {
2544  if (QuitAllow) {
2545  if (!die) {
2546  static VSSprite QuitSprite( "quit.sprite", BILINEAR, GFXTRUE );
2547  static VSSprite QuitCompatSprite( "quit.spr", BILINEAR, GFXTRUE );
2548 
2549  GFXEnable( TEXTURE0 );
2550  if ( QuitSprite.LoadSuccess() )
2551  QuitSprite.Draw();
2552  else
2553  QuitCompatSprite.Draw();
2554  }
2555  } else {
2556  static VSSprite PauseSprite( "pause.sprite", BILINEAR, GFXTRUE );
2557  static VSSprite PauseCompatSprite( "pause.spr", BILINEAR, GFXTRUE );
2558  GFXEnable( TEXTURE0 );
2559  if ( PauseSprite.LoadSuccess() )
2560  PauseSprite.Draw();
2561  else
2562  PauseCompatSprite.Draw();
2563  }
2564  }
2565  static float dietime = 0;
2566  if (die) {
2567  if (un)
2568  if (un->GetHull() >= 0)
2569  die = false;
2570  if (die) {
2571  if (text) {
2572  GFXColor4f( 1, 1, 1, 1 );
2573  text->SetSize( 1, -1 );
2574  float x;
2575  float y;
2576  if (dietime == 0) {
2577  editingTextMessage = false;
2578  RestoreKB();
2579  if ( respawnunit.size() > _Universe->CurrentCockpit() )
2580  if (respawnunit[_Universe->CurrentCockpit()] == 1 && _Universe->numPlayers() == 1)
2581  respawnunit[_Universe->CurrentCockpit()] = 0;
2582  text->GetCharSize( x, y );
2583  text->SetCharSize( x*4, y*4 );
2584  text->SetPos( 0-(x*2*14), 0-(y*2) );
2585  char playr[3];
2586  playr[0] = 'p';
2587  playr[1] = '0'+_Universe->CurrentCockpit();
2588  playr[2] = '\0';
2589  }
2590  GFXColorf( textcol );
2591  static bool show_died_text =
2592  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "show_respawn_text", "false" ) );
2593  if (show_died_text)
2594  text->Draw(
2595  "#ff5555You Have Died!\n#000000Press #8080FF;#000000 (semicolon) to respawn\nOr Press #8080FFEsc and 'q'#000000 to quit" );
2596  GFXColor4f( 1, 1, 1, 1 );
2597 
2598  static float min_die_time =
2599  XMLSupport::parse_float( vs_config->getVariable( "graphics", "death_scene_time", "4" ) );
2600  if (dietime > min_die_time) {
2601  static std::string death_menu_script = vs_config->getVariable( "graphics", "death_menu_script", "" );
2602  if ( death_menu_script.empty() ) {
2603  static VSSprite DieSprite( "died.sprite", BILINEAR, GFXTRUE );
2604  static VSSprite DieCompatSprite( "died.spr", BILINEAR, GFXTRUE );
2606  GFXEnable( TEXTURE0 );
2607  if ( DieSprite.LoadSuccess() )
2608  DieSprite.Draw();
2609  else
2610  DieCompatSprite.Draw();
2611  } else {
2612  BaseUtil::LoadBaseInterface( death_menu_script );
2613  dietime = 0;
2614  }
2615  }
2616  dietime += GetElapsedTime();
2617  SetView( CP_PAN );
2618  CockpitKeys::YawLeft( std::string(), RELEASE );
2619  CockpitKeys::YawRight( std::string(), RELEASE );
2620  CockpitKeys::PitchUp( std::string(), RELEASE );
2621  CockpitKeys::PitchDown( std::string(), RELEASE );
2622  zoomfactor = dietime*10;
2623  }
2624  QuitAllow = true;
2625  } else {}
2626  } else if (dietime != 0) {
2627  QuitAllow = false;
2628  dietime = 0;
2629  }
2630  //if(CommandInterpretor.console){
2631  //GFXColorf(textcol);
2632  //CommandInterpretor.renderconsole();
2633  //}
2634  GFXAlphaTest( ALWAYS, 0 );
2635  static bool mouseCursor = XMLSupport::parse_bool( vs_config->getVariable( "joystick", "mouse_cursor", "false" ) );
2636  static bool mousecursor_pancam =
2637  XMLSupport::parse_bool( vs_config->getVariable( "joystick", "mouse_cursor_pancam", "false" ) );
2638  static bool mousecursor_pantgt =
2639  XMLSupport::parse_bool( vs_config->getVariable( "joystick", "mouse_cursor_pantgt", "false" ) );
2640  static bool mousecursor_chasecam =
2641  XMLSupport::parse_bool( vs_config->getVariable( "joystick", "mouse_cursor_chasecam", "true" ) );
2642  if (mouseCursor && screenshotkey == false) {
2643  if ( (view == CP_PAN
2644  && !mousecursor_pancam)
2645  || (view == CP_PANTARGET && !mousecursor_pantgt) || (view == CP_CHASE && !mousecursor_chasecam) ) {} else {
2647  GFXColor4f( 1, 1, 1, 1 );
2648  GFXEnable( TEXTURE0 );
2649  //GFXDisable (DEPTHTEST);
2650  //GFXDisable(TEXTURE1);
2651  static float deadband = game_options.mouse_deadband;
2652  static int revspr =
2653  XMLSupport::parse_bool( vs_config->getVariable( "joystick", "reverse_mouse_spr", "true" ) ) ? 1 : -1;
2654  static string blah = vs_config->getVariable( "joystick", "mouse_crosshair", "crosshairs.spr" );
2655  static VSSprite MouseVSSprite( blah.c_str(), BILINEAR, GFXTRUE );
2656  float xcoord = ( -1+float(mousex)/(.5*g_game.x_resolution) );
2657  float ycoord = ( -revspr+float(revspr*mousey)/(.5*g_game.y_resolution) );
2658  MouseVSSprite.SetPosition( xcoord*( 1-fabs( crosscenx ) )+crosscenx, ycoord*( 1-fabs( crossceny ) )+crossceny );
2659  float xs, ys;
2660  MouseVSSprite.GetSize( xs, ys );
2661  if (xcoord < deadband && ycoord < deadband && xcoord > -deadband && ycoord > -deadband) {
2662  //The other option would be to place it in the center.
2663  //but it's sometimes useful to know where the mouse actually is.
2664  MouseVSSprite.SetSize( xs/2, ys/2 );
2665  } else if (xcoord < deadband && xcoord > -deadband) {
2666  MouseVSSprite.SetSize( xs/2, ys*5/6 );
2667  } else if (ycoord < deadband && ycoord > -deadband) {
2668  MouseVSSprite.SetSize( xs*5/6, ys/2 );
2669  }
2670  MouseVSSprite.Draw();
2671  MouseVSSprite.SetSize( xs, ys );
2672  //DrawGlutMouse(mousex,mousey,&MouseVSSprite);
2673  //DrawGlutMouse(mousex,mousey,&MouseVSSprite);
2674  }
2675  }
2676  if (view < CP_CHASE && damage_flash_first == false && getNewTime()-shake_time < damage_flash_length)
2677  DrawDamageFlash( shake_type );
2678  GFXHudMode( false );
2679 
2680  {
2681  //again, NAV computer is unaffected by FOV WARP-Link
2682  float oldfov = AccessCamera()->GetFov();
2683  AccessCamera()->SetFov( g_game.fov );
2685  DrawNavSystem();
2686  AccessCamera()->SetFov( oldfov );
2688  }
2689 
2690  GFXEnable( DEPTHWRITE );
2691  GFXEnable( DEPTHTEST );
2692  GFXEnable( TEXTURE0 );
2693 }
2694 
2695 int GameCockpit::getScrollOffset( unsigned int whichtype )
2696 {
2697  for (unsigned int i = 0; i < vdu.size(); i++)
2698  if (vdu[i]->getMode()&whichtype)
2699  return vdu[i]->scrolloffset;
2700  return 0;
2701 }
2702 
2703 string GameCockpit::getsoundending( int which )
2704 {
2705  static bool gotten = false;
2706  static string strs[9];
2707  if (gotten == false) {
2708  char tmpstr[2] = {'\0'};
2709  for (int i = 0; i < 9; i++) {
2710  tmpstr[0] = i+'1';
2711  string vsconfigvar = string( "sounds_extension_" )+tmpstr;
2712  strs[i] = vs_config->getVariable( "cockpitaudio", vsconfigvar, "\n" );
2713  if (strs[i] == "\n") {
2714  strs[i] = "";
2715  break;
2716  }
2717  }
2718  gotten = true;
2719  }
2720  return strs[which];
2721 }
2722 
2723 #include <algorithm>
2724 string GameCockpit::getsoundfile( string sound )
2725 {
2726  bool ok = false;
2727  int i;
2728  string lastsound = "";
2729  string anothertmpstr = "";
2730  for (i = 0; i < 9 && !ok; i++) {
2731  anothertmpstr = getsoundending( i );
2732  bool foundyet = false;
2733  while (1) {
2734  std::string::iterator found = std::find( anothertmpstr.begin(), anothertmpstr.end(), '*' );
2735  if ( found != anothertmpstr.end() ) {
2736  anothertmpstr.erase( found );
2737  anothertmpstr.insert( ( found-anothertmpstr.begin() ), sound );
2738  foundyet = true;
2739  } else {
2740  if (!foundyet)
2741  anothertmpstr = sound+anothertmpstr;
2742  break;
2743  }
2744  }
2745  if (VSFileSystem::LookForFile( anothertmpstr, SoundFile ) < Ok)
2746  ok = true;
2747  }
2748  if (ok)
2749  //return lastsound;
2750  return anothertmpstr;
2751  else
2752  return "";
2753 }
2754 
2755 void SetStartupView( Cockpit* );
2756 
2758 {
2759  static bool autopan = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "pan_on_auto", "true" ) );
2760  if (autopilot_time != 0) {
2762  {
2763  if (autopan) {
2764  Vector origR = Vector( 0, 0, 1 );
2765  Vector origP = Vector( 1, 0, 0 );
2766 
2767  static float rotspd =
2768  XMLSupport::parse_float( vs_config->getVariable( "graphics", "autopilot_rotation_speed", ".15" ) );
2769 
2770  static float curtime = 0;
2771  curtime += SIMULATION_ATOM;
2772  float ang = curtime*rotspd;
2773  origR.Yaw( ang );
2774  origP.Yaw( ang );
2775  Vector origQ = Vector( 0, 1, 0 );
2776  origP.Normalize();
2777  origQ.Normalize();
2778  origR.Normalize();
2779  AccessCamera( CP_FIXED )->myPhysics.SetAngularVelocity( Vector( 0, 0, 0 ) ); //hack
2780  static float initialzoom =
2781  XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) );
2782  zoomfactor = initialzoom;
2783  }
2784  }
2785  if (autopilot_time <= 0) {
2787  if (disableautosound.sound < 0) {
2788  static string str = vs_config->getVariable( "cockpitaudio", "autopilot_disabled", "autopilot_disabled" );
2789  disableautosound.loadsound( str );
2790  }
2791  disableautosound.playsound();
2792  if (autopan) {
2794  SetStartupView( this );
2795  }
2796  autopilot_time = 0;
2797  Unit *par = GetParent();
2798  if (par) {
2799  Unit *autoun = autopilot_target.GetUnit();
2800  autopilot_target.SetUnit( NULL );
2801  if (autoun && autopan)
2802  par->AutoPilotTo( autoun, false );
2803  }
2804  }
2805  }
2806 }
2807 
2808 void SwitchUnits2( Unit *nw )
2809 {
2810  if (nw) {
2811  nw->PrimeOrders();
2814 
2815  nw->SetTurretAI();
2816  nw->DisableTurretAI();
2817 
2818  static bool LoadNewCockpit =
2819  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "UnitSwitchCockpitChange", "false" ) );
2820  static bool DisCockpit =
2821  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "SwitchCockpitToDefaultOnUnitSwitch", "false" ) );
2822  if (nw->getCockpit().length() > 0 || DisCockpit)
2823  _Universe->AccessCockpit()->Init( nw->getCockpit().c_str(), LoadNewCockpit == false );
2824  /* Here is the old code:
2825  *
2826  * if (nw->getCockpit().length()>0&&LoadNewCockpit) {
2827  * _Universe->AccessCockpit()->Init (nw->getCockpit().c_str());
2828  * }else {
2829  * if (DisCockpit) {
2830  * _Universe->AccessCockpit()->Init ("disabled-cockpit.cpt");
2831  * }
2832  * }
2833  *
2834  */
2835  }
2836 }
2837 
2839 {
2840  Delete();
2841  int i;
2842  for (i = 0; i < 4; i++)
2843  if (Pit[i]) {
2844  delete Pit[i];
2845  Pit[i] = NULL;
2846  }
2847  delete savegame;
2848 }
2849 
2850 int GameCockpit::getVDUMode( int vdunum )
2851 {
2852  if ( vdunum < (int) vdu.size() )
2853  if (vdu[vdunum])
2854  return vdu[vdunum]->getMode();
2855  return 0;
2856 }
2857 
2858 void GameCockpit::VDUSwitch( int vdunum )
2859 {
2860  if (soundfile >= 0)
2861  //AUDPlay (soundfile, AccessCamera()->GetPosition(), Vector (0,0,0), .5);
2862  AUDPlay( soundfile, QVector( 0, 0, 0 ), Vector( 0, 0, 0 ), 1 );
2863  if ( vdunum < (int) vdu.size() )
2864  if (vdu[vdunum])
2865  vdu[vdunum]->SwitchMode( this->parent.GetUnit() );
2866 }
2867 
2868 void GameCockpit::ScrollVDU( int vdunum, int howmuch )
2869 {
2870  if (soundfile >= 0)
2871  //AUDPlay (soundfile, AccessCamera()->GetPosition(), Vector (0,0,0),.5);
2872  AUDPlay( soundfile, QVector( 0, 0, 0 ), Vector( 0, 0, 0 ), 1 );
2873  if ( vdunum < (int) vdu.size() )
2874  if (vdu[vdunum])
2875  vdu[vdunum]->Scroll( howmuch );
2876 }
2877 
2878 void GameCockpit::ScrollAllVDU( int howmuch )
2879 {
2880  if ( ThisNav.CheckDraw() )
2881  ThisNav.scroll( howmuch );
2882  else
2883  for (unsigned int i = 0; i < vdu.size(); i++)
2884  ScrollVDU( i, howmuch );
2885 }
2886 
2888 {
2889  static string comm_static = vs_config->getVariable( "graphics", "comm_static", "static.ani" );
2890  static Animation Statuc( comm_static.c_str() );
2891  for (unsigned int i = 0; i < vdu.size(); i++)
2892  if (vdu[i]->getMode() == VDU::COMM)
2893  vdu[i]->SetCommAnimation( &Statuc, NULL, true );
2894 }
2895 
2897 {
2898  bool seti = false;
2899  for (unsigned int i = 0; i < vdu.size(); i++)
2900  if ( vdu[i]->SetCommAnimation( ani, un, false ) ) {
2901  seti = true;
2902  break;
2903  }
2904  if (!seti) {
2905  for (unsigned int i = 0; i < vdu.size(); i++)
2906  if ( vdu[i]->SetCommAnimation( ani, un, true ) )
2907  break;
2908  }
2909 }
2910 
2912 {
2913  Unit *par = GetParent();
2914  if ( ( !targetLabel.empty() )
2915  && (!par || ( (void*) par->Target() ) != labeledTargetUnit) ) {
2916  targetLabel = string();
2917  if (par)
2918  labeledTargetUnit = par->Target();
2919  }
2920  return targetLabel;
2921 }
2922 
2923 void GameCockpit::setTargetLabel( const string &newLabel )
2924 {
2925  if ( GetParent() ) {
2926  targetLabel = newLabel;
2927  labeledTargetUnit = GetParent()->Target();
2928  }
2929 }
2930 
2932 {
2934 }
2935 
2936 static void FaceCamTarget( Cockpit *cp, int cam, Unit *un )
2937 {
2938  QVector diff = un->Position()-cp->AccessCamera()->GetPosition();
2939  diff.Normalize();
2940  if (diff.i != 0 && diff.k != 0) {
2941  Vector z = diff.Cross( QVector( 0, 1, 0 ) ).Cast();
2942  cp->AccessCamera( cam )->SetOrientation( z, Vector( 0, 1, 0 ), diff.Cast() );
2943  }
2944 }
2945 
2946 static void ShoveCamBehindUnit( int cam, Unit *un, float zoomfactor )
2947 {
2948  //commented out by chuck_starchaser; --never used
2949  QVector unpos = (/*un->GetPlanetOrbit() && !un->isSubUnit()*/ NULL) ? un->LocalPosition() : un->Position();
2951  unpos-_Universe->AccessCamera()->GetR().Cast()*(un->rSize()+g_game.znear*2)*zoomfactor,
2952  un->GetWarpVelocity(), un->GetAngularVelocity(), un->GetAcceleration() );
2953 }
2954 
2955 static void ShoveCamBelowUnit( int cam, Unit *un, float zoomfactor )
2956 {
2957  //commented out by chuck_starchaser; --never used
2958  QVector unpos = (/*un->GetPlanetOrbit() && !un->isSubUnit()*/ NULL) ? un->LocalPosition() : un->Position();
2959  Vector p, q, r;
2960  _Universe->AccessCamera( cam )->GetOrientation( p, q, r );
2961  static float ammttoshovecam = XMLSupport::parse_float( vs_config->getVariable( "graphics", "shove_camera_down", ".3" ) );
2963  unpos-(r-ammttoshovecam*q).Cast()*(un->rSize()+g_game.znear*2)*zoomfactor, un->GetWarpVelocity(),
2964  un->GetAngularVelocity(), un->GetAcceleration() );
2965 }
2966 
2967 static Vector lerp( const Vector &a, const Vector &b, float t )
2968 {
2969  t = min( 1.0f, max( 0.0f, t ) );
2970  return a*(1-t)+b*t;
2971 }
2972 
2973 static void translate_as( Vector &p, Vector &q, Vector &r, Vector p1, Vector q1, Vector r1, Vector p2, Vector q2, Vector r2 )
2974 {
2975  //Translate p,q,r to <p1,q1,r1> base
2976  p = Vector( p.Dot( p1 ), p.Dot( q1 ), p.Dot( r1 ) );
2977  q = Vector( q.Dot( p1 ), q.Dot( q1 ), q.Dot( r1 ) );
2978  r = Vector( r.Dot( p1 ), r.Dot( q1 ), r.Dot( r1 ) );
2979  //Interpret now as if it were in <p2,q2,r2> base
2980  p = p2*p.i+q2*p.j+r2*p.k;
2981  q = p2*q.i+q2*q.j+r2*q.k;
2982  r = p2*r.i+q2*r.j+r2*r.k;
2983 }
2984 
2986 {
2988  GFXViewPort( 0,
2989  (int) ( (view == CP_FRONT ? viewport_offset : 0)*g_game.y_resolution ),
2991  g_game.y_resolution );
2993  Unit *un, *tgt;
2994  if ( ( un = parent.GetUnit() ) ) {
2995  //Previous frontal orientation - useful, sometimes...
2996  Vector prev_fp, prev_fq, prev_fr;
2997  _Universe->AccessCamera( CP_FRONT )->GetOrientation( prev_fp, prev_fq, prev_fr );
2998 
2999  un->UpdateHudMatrix( CP_FRONT );
3000  un->UpdateHudMatrix( CP_LEFT );
3001  un->UpdateHudMatrix( CP_RIGHT );
3002  un->UpdateHudMatrix( CP_BACK );
3003  un->UpdateHudMatrix( CP_CHASE );
3005 
3006  insidePanYaw += insidePanYawSpeed * GetElapsedTime();
3007  insidePanPitch += insidePanPitchSpeed * GetElapsedTime();
3008 
3009  Vector p, q, r, tmp;
3011  _Universe->AccessCamera( CP_LEFT )->SetOrientation( r, q, -p );
3012  _Universe->AccessCamera( CP_RIGHT )->SetOrientation( -r, q, p );
3013  _Universe->AccessCamera( CP_BACK )->SetOrientation( -p, q, -r );
3014 #ifdef IWANTTOPVIEW
3015  _Universe->AccessCamera( CP_CHASE )->SetOrientation( p, r, -q );
3016 #endif
3017 
3018  Matrix pitchMatrix, yawMatrix, panMatrix;
3019  RotateAxisAngle(pitchMatrix, Vector( 1, 0, 0 ), insidePanPitch);
3020  RotateAxisAngle(yawMatrix, Transform(pitchMatrix, Vector( 0, 1, 0 )), insidePanYaw);
3021  panMatrix = yawMatrix * pitchMatrix;
3023  Transform(panMatrix, p),
3024  Transform(panMatrix, q),
3025  Transform(panMatrix, r) );
3026 
3027  tgt = un->Target();
3028  if (tgt) {
3029  un->GetOrientation( p, q, r );
3030  r = ( tgt->Position()-un->Position() ).Cast();
3031  r.Normalize();
3032  CrossProduct( r, q, tmp );
3033  CrossProduct( tmp, r, q );
3034  //Padlock block
3035  if (view == CP_VIEWTARGET) {
3036  static float PadlockViewLag =
3037  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "PadlockViewLag", "1.5" ) );
3038  static float PadlockViewLag_inv = 1.f/PadlockViewLag;
3039  static float PadlockViewLag_fix =
3040  XMLSupport::parse_float( vs_config->getVariable( "graphics", "hud", "PadlockViewLagFixZone", "0.0872" ) ); //~5 deg
3041  static float PadlockViewLag_fixcos = (float) cos( PadlockViewLag_fix );
3042 
3043  //pp,qq,rr <-- world-relative padlock target
3044  //p_p,p_q,p_r <-- previous head orientation translated to new front orientation
3045  Vector p_p, p_q, p_r, f_p, f_q, f_r, pp = tmp, qq = q, rr = r;
3046  _Universe->AccessCamera( CP_VIEWTARGET )->GetOrientation( p_p, p_q, p_r );
3047  _Universe->AccessCamera( CP_FRONT )->GetOrientation( f_p, f_q, f_r );
3048  translate_as( p_p, p_q, p_r, prev_fp, prev_fq, prev_fr, f_p, f_q, f_r );
3049 
3050  //Compute correction amount (vtphase), accounting for lag and fix-zone
3052  bool fixzone = (rr.Dot( p_r ) >= PadlockViewLag_fixcos) && (qq.Dot( p_q ) >= PadlockViewLag_fixcos);
3053  float vtphase = 1.0f-(float) pow( 0.1, GetElapsedTime()*PadlockViewLag_inv*(fixzone ? 0.1f : 1.0f) );
3054 
3055  //Apply correction
3057  lerp( p_p, pp, vtphase ).Normalize(),
3058  lerp( p_q, qq, vtphase ).Normalize(),
3059  lerp( p_r, rr, vtphase ).Normalize() );
3060  } else {
3061  //Reset padlock matrix
3063  }
3064  _Universe->AccessCamera( CP_TARGET )->SetOrientation( tmp, q, r );
3065  //_Universe->AccessCamera(CP_PANTARGET)->SetOrientation(tmp,q,r);
3068  FaceCamTarget( this, CP_FIXEDPOSTARGET, tgt );
3069  } else {
3071  un->UpdateHudMatrix( CP_TARGET );
3073  }
3074  static bool draw_unit_on_chasecam =
3075  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "hud", "draw_unit_on_chasecam", "true" ) );
3076  if (view == CP_CHASE && !draw_unit_on_chasecam) {} else {
3078  //ShoveCamBehindUnit (CP_PANTARGET,un,zoomfactor);
3079  }
3080  FaceCamTarget( this, CP_FIXEDPOS, un );
3081 
3083  un->SetVisible( view >= CP_CHASE );
3084 
3085  //WARP-FOV link
3086  {
3087  static float stable_lowarpref =
3088  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.loref", "1" ) );
3089  static float stable_hiwarpref =
3090  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.hiref", "100000" ) );
3091  static float stable_refexp =
3092  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.exp", "0.5" ) );
3093  static bool stable_asymptotic =
3094  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "warp.fovlink.stable.asymptotic", "1" ) );
3095  static float stable_offset_f =
3096  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.offset.front", "0" ) );
3097  static float stable_offset_b =
3098  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.offset.back", "0" ) );
3099  static float stable_offset_p =
3100  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.offset.perpendicular", "0" ) );
3101  static float stable_multiplier_f =
3102  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.multiplier.front", "0.85" ) );
3103  static float stable_multiplier_b =
3104  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.multiplier.back", "1.5" ) );
3105  static float stable_multiplier_p =
3106  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.stable.multiplier.perpendicular",
3107  "1.25" ) );
3108 
3109  static float shake_lowarpref =
3110  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.loref", "10000" ) );
3111  static float shake_hiwarpref =
3112  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.hiref", "200000" ) );
3113  static float shake_refexp =
3114  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.exp", "1.5" ) );
3115  static bool shake_asymptotic =
3116  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "warp.fovlink.shake.asymptotic", "1" ) );
3117  static float shake_speed =
3118  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.speed", "10" ) );
3119  static float shake_offset_f =
3120  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.offset.front", "0" ) );
3121  static float shake_offset_b =
3122  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.offset.back", "0" ) );
3123  static float shake_offset_p =
3124  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.offset.perpendicular", "0" ) );
3125  static float shake_multiplier_f =
3126  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.multiplier.front", "0" ) );
3127  static float shake_multiplier_b =
3128  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.multiplier.back", "0" ) );
3129  static float shake_multiplier_p =
3130  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.shake.multiplier.perpendicular", "0" ) );
3131 
3132  static float refkpsoverride =
3133  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.referencekps", "0" ) ); //0 means automatic
3134 
3135  static float theta = 0;
3136  theta += shake_speed*GetElapsedTime();
3137  if (stable_lowarpref == stable_hiwarpref) stable_hiwarpref = stable_lowarpref+1;
3138  if (shake_lowarpref == shake_hiwarpref) shake_hiwarpref = shake_lowarpref+1;
3139  float warpfieldstrength = LookupUnitStat( UnitImages< void >::WARPFIELDSTRENGTH, un );
3140  float refkps = (refkpsoverride > 0) ? refkpsoverride : LookupUnitStat( UnitImages< void >::MAXCOMBATABKPS, un ); //This one is stable, as opposed to SETKPS - for full stability, use the override (user override of governor settings will create weird behaviour if done under SPEC)
3141  float kps = LookupUnitStat( UnitImages< void >::KPS, un );
3142  float st_warpfieldstrength =
3143  pow( (max( stable_lowarpref,
3144  min( stable_asymptotic ? FLT_MAX : stable_hiwarpref,
3145  warpfieldstrength ) )-stable_lowarpref)/(stable_hiwarpref-stable_lowarpref), stable_refexp );
3146  float sh_warpfieldstrength =
3147  pow( (max( shake_lowarpref, min( shake_asymptotic ? FLT_MAX : shake_hiwarpref,
3148  warpfieldstrength ) )-shake_lowarpref)/(shake_hiwarpref-shake_lowarpref),
3149  shake_refexp );
3150  float costheta = cos( theta );
3151  if (stable_asymptotic) st_warpfieldstrength = atan( st_warpfieldstrength );
3152  if (shake_asymptotic) sh_warpfieldstrength = atan( sh_warpfieldstrength );
3153  if (refkps <= 1) refkps = 1;
3154  if (kps > refkps) kps = refkps;
3155  float unv = un->GetVelocity().Magnitude();
3156  float camv = _Universe->AccessCamera()->GetR().Magnitude();
3157  if (unv <= 1) unv = 1;
3158  if (camv <= 1) camv = 1;
3159  float cosangle = ( un->GetVelocity()*_Universe->AccessCamera()->GetR() )/(unv*camv)*(kps/refkps);
3160  float st_offs, sh_offs, st_mult, sh_mult;
3161  if (cosangle > 0) {
3162  st_offs = stable_offset_f*cosangle+stable_offset_p*(1-cosangle);
3163  sh_offs = shake_offset_f*cosangle+shake_offset_p*(1-cosangle);
3164  st_mult = stable_multiplier_f*cosangle+stable_multiplier_p*(1-cosangle);
3165  sh_mult = shake_multiplier_f*cosangle+shake_multiplier_p*(1-cosangle);
3166  } else {
3167  st_offs = stable_offset_b* -cosangle+stable_offset_p*(1+cosangle);
3168  sh_offs = shake_offset_b* -cosangle+shake_offset_p*(1+cosangle);
3169  st_mult = stable_multiplier_b* -cosangle+stable_multiplier_p*(1+cosangle);
3170  sh_mult = shake_multiplier_b* -cosangle+shake_multiplier_p*(1+cosangle);
3171  }
3172  st_offs *= st_warpfieldstrength;
3173  sh_offs *= sh_warpfieldstrength*costheta;
3174  st_mult = (1-st_warpfieldstrength)+st_mult*st_warpfieldstrength;
3175  sh_mult *= sh_warpfieldstrength*costheta;
3176  static float fov_smoothing =
3177  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.smoothing", ".4" ) );
3178  float fov_smoot = pow( double(fov_smoothing), GetElapsedTime() );
3179  smooth_fov =
3180  min( 170.0f, max( 5.0f, (1-fov_smoot)*smooth_fov+fov_smoot*(g_game.fov*(st_mult+sh_mult)+st_offs+sh_offs) ) );
3181  _Universe->AccessCamera()->SetFov( smooth_fov );
3182  }
3183  }
3185 
3186  //parent->UpdateHudMatrix();
3187 }
3188 
3190 {
3191  if (cam < NUM_CAM && cam >= 0)
3192  currentcamera = cam;
3193 }
3194 
3196 {
3197  if (num < NUM_CAM && num >= 0)
3198  return &cam[num];
3199  else
3200  return NULL;
3201 }
3202 
3206 //THETA : angle between the arrow head and the two branches (divided by 2) (20 degrees here).
3207 #define TARGET_ARROW_COS_THETA (0.93969262078590838405410927732473)
3208 #define TARGET_ARROW_SIN_THETA (0.34202014332566873304409961468226)
3209 #define TARGET_ARROW_SIZE (0.05)
3210 
3211 void GameCockpit::DrawArrowToTarget(const Radar::Sensor& sensor, Unit *target)
3212 {
3213  Unit *player = sensor.GetPlayer();
3214  if (player && target) {
3215  Radar::Track track = sensor.CreateTrack(target);
3216  GFXColorf(sensor.GetColor(track));
3217  DrawArrowToTarget(sensor, track.GetPosition());
3218  }
3219 }
3220 
3221 void GameCockpit::DrawArrowToTarget(const Radar::Sensor& sensor, Vector localcoord)
3222 {
3223  float s, t, s_normalized, t_normalized, inv_len;
3224  Vector p1, p2, p_n;
3225 
3226  //Project target position on k.
3227  inv_len = 1/fabs( localcoord.k );
3228  s = -localcoord.i*inv_len;
3229  t = localcoord.j*inv_len;
3230  if (localcoord.k > 0) {
3231  //The unit is in front of us.
3232  //Check if the unit is in the screen.
3233  if ( (fabs( s ) < projection_limit_x) && (fabs( t ) < projection_limit_y) )
3234  return; //The unit is in the screen, do not display the arrow.
3235  }
3236  inv_len = 1/sqrt( s*s+t*t );
3237  s_normalized = s*inv_len; //Save the normalized projected coordinates.
3238  t_normalized = t*inv_len;
3239 
3240  //Apply screen aspect ratio correction.
3241  s *= inv_screen_aspect_ratio;
3242  if ( fabs( t ) > fabs( s ) ) {
3243  //Normalize t.
3244  if (t > 0) {
3245  s /= t;
3246  t = 1;
3247  } else if (t < 0) {
3248  s /= -t;
3249  t = -1;
3250  } //case t == 0, do nothing everything is ok.
3251  } else {
3252  //Normalize s.
3253  if (s > 0) {
3254  t /= s;
3255  s = 1;
3256  } else if (s < 0) {
3257  t /= -s;
3258  s = -1;
3259  } //case s == 0, do nothing everything is ok.
3260  }
3261  //Compute points p1 and p2 composing the arrow. Hard code a 2D rotation.
3262  //p1 = p - TARGET_ARROW_SIZE * p.normalize().rot(THETA), p being the arrow head position (s,t).
3263  //p2 = p - TARGET_ARROW_SIZE * p.normalize().rot(-THETA)
3264  p_n.i = -TARGET_ARROW_SIZE*s_normalized; //Vector p will be used to compute the two branches of the arrow.
3265  p_n.j = -TARGET_ARROW_SIZE*t_normalized;
3266  p1.i = p_n.i*TARGET_ARROW_COS_THETA-p_n.j*TARGET_ARROW_SIN_THETA; //p1 = p.rot(THETA)
3268  p2.i = p_n.i*TARGET_ARROW_COS_THETA-p_n.j*(-TARGET_ARROW_SIN_THETA); //p2 = p.rot(-THETA)
3269  p2.j = p_n.j*TARGET_ARROW_COS_THETA+p_n.i*(-TARGET_ARROW_SIN_THETA);
3270  p1.i += s;
3271  p1.j *= g_game.aspect;
3272  p1.j += t;
3273  p2.i += s;
3274  p2.j *= g_game.aspect;
3275  p2.j += t;
3276  p2.k = p1.k = 0;
3277 
3278  static GFXColor black_and_white = DockBoxColor( "black_and_white" );
3279  GFXEnable( SMOOTH );
3280  GFXDisable( TEXTURE0 );
3281  GFXDisable( TEXTURE1 );
3283 
3284  glBegin( GL_LINE_LOOP );
3285  GFXVertex3f( s, t, 0 );
3286  GFXVertexf( p1 );
3287  GFXVertexf( p2 );
3288  GFXEnd();
3289  GFXColor4f( 1, 1, 1, 1 );
3290 
3291  GFXDisable( SMOOTH );
3292 }
3293 
3295 {
3296  for (unsigned int i = 0; i < vdu.size(); ++i)
3297  if ( vdu[i]->CheckCommAnimation( un ) )
3298  return true;
3299  return false;
3300 }
3301 
3303 {
3304  return (GetElapsedTime() <= 0.001);
3305 }
3306 
3308 {
3309  radarDisplay->OnPauseBegin();
3310 }
3311 
3313 {
3314  radarDisplay->OnPauseEnd();
3315 }
3316 
3317 void GameCockpit::updateRadar(Unit*ship) {
3318  if (ship)
3319  {
3320  // We may have bought a new radar brand while docked, so the actual
3321  // radar display is instantiated when we undock.
3322  switch (ship->GetComputerData().radar.GetBrand())
3323  {
3326  break;
3327 
3329  radarDisplay = Radar::Factory(Radar::Type::PlaneDisplay);
3330  break;
3331 
3332  default:
3334  break;
3335  }
3336  // Send notification that I have undocked
3337  radarDisplay->OnDockEnd();
3338  }
3339 
3340 }
3341 void GameCockpit::SetParent( Unit *unit, const char *filename, const char *unitmodname, const QVector &startloc ){
3342  this->Cockpit::SetParent(unit,filename,unitmodname,startloc);
3343  updateRadar(unit);
3344 }
3345 void GameCockpit::OnDockEnd(Unit *station, Unit *ship)
3346 {
3347  if (_Universe->isPlayerStarship(ship))
3348  updateRadar(ship);
3349 }
3350 
3352 {
3353  if (_Universe->isPlayerStarship(ship))
3354  {
3355  radarDisplay->OnJumpBegin();
3356  }
3357 }
3358 
3360 {
3361  if (_Universe->isPlayerStarship(ship))
3362  {
3363  radarDisplay->OnJumpEnd();
3364  }
3365 }
3366 
3368 {
3369  insidePanYawSpeed = speed;
3370 }
3371 
3373 {
3374  insidePanPitchSpeed = speed;
3375 }
3376