From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_h_u_d_view_8cpp_source.html | 4482 +++++++++++++++++++++++++ 1 file changed, 4482 insertions(+) create mode 100644 Doc/doxygen/html/_h_u_d_view_8cpp_source.html (limited to 'Doc/doxygen/html/_h_u_d_view_8cpp_source.html') diff --git a/Doc/doxygen/html/_h_u_d_view_8cpp_source.html b/Doc/doxygen/html/_h_u_d_view_8cpp_source.html new file mode 100644 index 0000000..a3c1662 --- /dev/null +++ b/Doc/doxygen/html/_h_u_d_view_8cpp_source.html @@ -0,0 +1,4482 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/HUDView.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
HUDView.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 4.5
+
2  Destroyer Studios LLC
+
3  Copyright (C) 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: HUDView.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  View class for Heads Up Display
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "HUDView.h"
+
17 #include "HUDSounds.h"
+
18 #include "Ship.h"
+
19 #include "Element.h"
+
20 #include "Computer.h"
+
21 #include "Drive.h"
+
22 #include "Instruction.h"
+
23 #include "NavSystem.h"
+
24 #include "Power.h"
+
25 #include "Shield.h"
+
26 #include "Sensor.h"
+
27 #include "Contact.h"
+
28 #include "ShipDesign.h"
+
29 #include "Shot.h"
+
30 #include "Drone.h"
+
31 #include "Thruster.h"
+
32 #include "Weapon.h"
+
33 #include "WeaponGroup.h"
+
34 #include "FlightDeck.h"
+
35 #include "SteerAI.h"
+
36 #include "Sim.h"
+
37 #include "StarSystem.h"
+
38 #include "Starshatter.h"
+
39 #include "CameraDirector.h"
+
40 #include "MFD.h"
+
41 #include "RadioView.h"
+
42 #include "FormatUtil.h"
+
43 #include "Hoop.h"
+
44 #include "QuantumDrive.h"
+
45 #include "KeyMap.h"
+
46 #include "AudioConfig.h"
+
47 #include "Player.h"
+
48 
+
49 #include "NetGame.h"
+
50 #include "NetPlayer.h"
+
51 
+
52 #include "Color.h"
+
53 #include "CameraView.h"
+
54 #include "Screen.h"
+
55 #include "DataLoader.h"
+
56 #include "Scene.h"
+
57 #include "FontMgr.h"
+
58 #include "Graphic.h"
+
59 #include "Sprite.h"
+
60 #include "Keyboard.h"
+
61 #include "Mouse.h"
+
62 #include "MouseController.h"
+
63 #include "Polygon.h"
+
64 #include "Sound.h"
+
65 #include "Game.h"
+
66 #include "Window.h"
+
67 
+
68 static Bitmap hud_left_air;
+
69 static Bitmap hud_right_air;
+
70 static Bitmap hud_left_fighter;
+
71 static Bitmap hud_right_fighter;
+
72 static Bitmap hud_left_starship;
+
73 static Bitmap hud_right_starship;
+
74 static Bitmap instr_left;
+
75 static Bitmap instr_right;
+
76 static Bitmap warn_left;
+
77 static Bitmap warn_right;
+
78 static Bitmap lead;
+
79 static Bitmap cross;
+
80 static Bitmap cross1;
+
81 static Bitmap cross2;
+
82 static Bitmap cross3;
+
83 static Bitmap cross4;
+
84 static Bitmap fpm;
+
85 static Bitmap hpm;
+
86 static Bitmap pitch_ladder_pos;
+
87 static Bitmap pitch_ladder_neg;
+
88 static Bitmap chase_left;
+
89 static Bitmap chase_right;
+
90 static Bitmap chase_top;
+
91 static Bitmap chase_bottom;
+
92 static Bitmap icon_ship;
+
93 static Bitmap icon_target;
+
94 
+
95 static BYTE* hud_left_shade_air = 0;
+
96 static BYTE* hud_right_shade_air = 0;
+
97 static BYTE* hud_left_shade_fighter = 0;
+
98 static BYTE* hud_right_shade_fighter = 0;
+
99 static BYTE* hud_left_shade_starship = 0;
+
100 static BYTE* hud_right_shade_starship = 0;
+
101 static BYTE* instr_left_shade = 0;
+
102 static BYTE* instr_right_shade = 0;
+
103 static BYTE* warn_left_shade = 0;
+
104 static BYTE* warn_right_shade = 0;
+
105 static BYTE* lead_shade = 0;
+
106 static BYTE* cross_shade = 0;
+
107 static BYTE* cross1_shade = 0;
+
108 static BYTE* cross2_shade = 0;
+
109 static BYTE* cross3_shade = 0;
+
110 static BYTE* cross4_shade = 0;
+
111 static BYTE* fpm_shade = 0;
+
112 static BYTE* hpm_shade = 0;
+
113 static BYTE* pitch_ladder_pos_shade = 0;
+
114 static BYTE* pitch_ladder_neg_shade = 0;
+
115 static BYTE* chase_left_shade = 0;
+
116 static BYTE* chase_right_shade = 0;
+
117 static BYTE* chase_top_shade = 0;
+
118 static BYTE* chase_bottom_shade = 0;
+
119 static BYTE* icon_ship_shade = 0;
+
120 static BYTE* icon_target_shade = 0;
+
121 
+
122 static Sprite* hud_left_sprite = 0;
+
123 static Sprite* hud_right_sprite = 0;
+
124 static Sprite* fpm_sprite = 0;
+
125 static Sprite* hpm_sprite = 0;
+
126 static Sprite* lead_sprite = 0;
+
127 static Sprite* aim_sprite = 0;
+
128 static Sprite* tgt1_sprite = 0;
+
129 static Sprite* tgt2_sprite = 0;
+
130 static Sprite* tgt3_sprite = 0;
+
131 static Sprite* tgt4_sprite = 0;
+
132 static Sprite* chase_sprite = 0;
+
133 static Sprite* instr_left_sprite = 0;
+
134 static Sprite* instr_right_sprite = 0;
+
135 static Sprite* warn_left_sprite = 0;
+
136 static Sprite* warn_right_sprite = 0;
+
137 static Sprite* icon_ship_sprite = 0;
+
138 static Sprite* icon_target_sprite = 0;
+
139 
+
140 static Sound* missile_lock_sound;
+
141 
+
142 const int NUM_HUD_COLORS = 4;
+
143 
+ +
145  Color(130,190,140), // green
+
146  Color(130,200,220), // cyan
+
147  Color(250,170, 80), // orange
+
148  // Color(220,220,100), // yellow
+
149  Color( 16, 16, 16) // dark gray
+
150 };
+
151 
+ +
153  Color(150,200,170), // green w/ green gray
+
154  Color(220,220,180), // cyan w/ light yellow
+
155  Color(220,220, 80), // orange w/ yellow
+
156  // Color(180,200,220), // yellow w/ white
+
157  Color( 32, 32, 32) // dark gray
+
158 };
+
159 
+ +
161  Color( 20, 80, 20), // green
+
162  Color( 30, 80, 80), // cyan
+
163  Color( 80, 80, 20), // yellow
+
164  // Color(180,200,220), // not used
+
165  Color( 0, 0, 0) // no night vision
+
166 };
+
167 
+
168 static Font* hud_font = 0;
+
169 static Font* big_font = 0;
+
170 
+
171 static bool mouse_in = false;
+
172 static int mouse_latch = 0;
+
173 static int mouse_index = -1;
+
174 
+
175 static int ship_status = System::NOMINAL;
+
176 static int tgt_status = System::NOMINAL;
+
177 
+
178 // +--------------------------------------------------------------------+
+
179 
+
180 static enum TXT {
+ +
182 
+ + + + + + +
189 
+ + + + + + + + + + + + + +
203 
+ + + + + + + + + + + + + + + + + + + +
223 
+ + + + + + +
230 
+ + + + + + +
237 
+ + +
240 };
+
241 
+
242 static HUDText hud_text[TXT_LAST];
+
243 
+
244 void
+
245 HUDView::DrawHUDText(int index, const char* txt, Rect& rect, int align, int upcase, bool box)
+
246 {
+
247  if (index < 0 || index >= TXT_LAST)
+
248  return;
+
249 
+
250  HUDText& ht = hud_text[index];
+
251  Color hc = ht.color;
+
252 
+
253  char txt_buf[256];
+
254  int n = strlen(txt);
+
255 
+
256  if (n > 250) n = 250;
+
257 
+
258  int i;
+
259  for (i = 0; i < n; i++) {
+
260  if (upcase && islower(txt[i]))
+
261  txt_buf[i] = toupper(txt[i]);
+
262  else
+
263  txt_buf[i] = txt[i];
+
264  }
+
265 
+
266  txt_buf[i] = 0;
+
267 
+
268  if (box) {
+
269  ht.font->DrawText(txt_buf, n, rect, DT_LEFT | DT_SINGLELINE | DT_CALCRECT);
+
270 
+
271  if ((align & DT_CENTER) != 0) {
+
272  int cx = width/2;
+
273  rect.x = cx - rect.w/2;
+
274  }
+
275  }
+
276 
+
277  if (!cockpit_hud_texture && rect.Contains(Mouse::X(), Mouse::Y())) {
+
278  mouse_in = true;
+
279 
+
280  if (index <= TXT_LAST_ACTIVE)
+
281  hc = Color::White;
+
282 
+
283  if (Mouse::LButton() && !mouse_latch) {
+
284  mouse_latch = 2;
+
285  mouse_index = index;
+
286  }
+
287  }
+
288 
+
289  if (cockpit_hud_texture &&
+
290  index >= TXT_HUD_MODE &&
+
291  index <= TXT_TARGET_ETA &&
+
292  ht.font != big_font) {
+
293 
+
294  Sprite* s = hud_sprite[0];
+
295 
+
296  int cx = (int) s->Location().x;
+
297  int cy = (int) s->Location().y;
+
298  int w2 = s->Width() / 2;
+
299  int h2 = s->Height() / 2;
+
300 
+
301  Rect txt_rect(rect);
+
302  txt_rect.x -= (cx-w2);
+
303  txt_rect.y -= (cy-h2);
+
304 
+
305  if (index == TXT_ICON_SHIP_TYPE)
+
306  txt_rect = Rect(0, 500, 128, 12);
+
307 
+
308  else if (index == TXT_ICON_TARGET_TYPE)
+
309  txt_rect = Rect(128, 500, 128, 12);
+
310 
+
311  ht.font->SetColor(hc);
+
312  ht.font->DrawText(txt_buf, n, txt_rect, align | DT_SINGLELINE, cockpit_hud_texture);
+
313  ht.hidden = false;
+
314  }
+
315  else {
+
316  ht.font->SetColor(hc);
+
317  ht.font->DrawText(txt_buf, n, rect, align | DT_SINGLELINE);
+
318  ht.rect = rect;
+
319  ht.hidden = false;
+
320 
+
321  if (box) {
+
322  rect.Inflate(3,2);
+
323  rect.h--;
+
324  window->DrawRect(rect, hud_color);
+
325  }
+
326  }
+
327 }
+
328 
+
329 void
+ +
331 {
+
332  if (index >= TXT_LAST)
+
333  return;
+
334 
+
335  hud_text[index].hidden = true;
+
336 }
+
337 
+
338 // +--------------------------------------------------------------------+
+
339 
+ +
341 bool HUDView::arcade = false;
+
342 bool HUDView::show_fps = false;
+
343 int HUDView::def_color_set = 1;
+
344 int HUDView::gunsight = 1;
+
345 
+
346 // +--------------------------------------------------------------------+
+
347 
+ +
349 : View(c), projector(0), camview(0),
+
350 sim(0), ship(0), target(0), mode(HUD_MODE_TAC),
+
351 tactical(0), overlay(0), cockpit_hud_texture(0),
+
352 threat(0), active_region(0), transition(false), docking(false),
+
353 az_ring(0), az_pointer(0), el_ring(0), el_pointer(0), compass_scale(1),
+
354 show_warn(false), show_inst(false), inst_page(0)
+
355 {
+
356  hud_view = this;
+
357 
+
358  sim = Sim::GetSim();
+
359 
+
360  if (sim)
+
361  sim->ShowGrid(false);
+
362 
+
363  int i;
+
364 
+
365  width = window->Width();
+
366  height = window->Height();
+
367  xcenter = (width / 2.0) - 0.5;
+
368  ycenter = (height / 2.0) + 0.5;
+
369 
+
370  PrepareBitmap("HUDleftA.pcx", hud_left_air, hud_left_shade_air);
+
371  PrepareBitmap("HUDrightA.pcx", hud_right_air, hud_right_shade_air);
+
372  PrepareBitmap("HUDleft.pcx", hud_left_fighter, hud_left_shade_fighter);
+
373  PrepareBitmap("HUDright.pcx", hud_right_fighter, hud_right_shade_fighter);
+
374  PrepareBitmap("HUDleft1.pcx", hud_left_starship, hud_left_shade_starship);
+
375  PrepareBitmap("HUDright1.pcx", hud_right_starship, hud_right_shade_starship);
+
376  PrepareBitmap("INSTR_left.pcx", instr_left, instr_left_shade);
+
377  PrepareBitmap("INSTR_right.pcx", instr_right, instr_right_shade);
+
378  PrepareBitmap("CAUTION_left.pcx", warn_left, warn_left_shade);
+
379  PrepareBitmap("CAUTION_right.pcx", warn_right, warn_right_shade);
+
380  PrepareBitmap("hud_icon.pcx", icon_ship, icon_ship_shade);
+
381  PrepareBitmap("hud_icon.pcx", icon_target, icon_target_shade);
+
382 
+
383  PrepareBitmap("lead.pcx", lead, lead_shade);
+
384  PrepareBitmap("cross.pcx", cross, cross_shade);
+
385  PrepareBitmap("cross1.pcx", cross1, cross1_shade);
+
386  PrepareBitmap("cross2.pcx", cross2, cross2_shade);
+
387  PrepareBitmap("cross3.pcx", cross3, cross3_shade);
+
388  PrepareBitmap("cross4.pcx", cross4, cross4_shade);
+
389  PrepareBitmap("fpm.pcx", fpm, fpm_shade);
+
390  PrepareBitmap("hpm.pcx", hpm, hpm_shade);
+
391  PrepareBitmap("chase_l.pcx", chase_left, chase_left_shade);
+
392  PrepareBitmap("chase_r.pcx", chase_right, chase_right_shade);
+
393  PrepareBitmap("chase_t.pcx", chase_top, chase_top_shade);
+
394  PrepareBitmap("chase_b.pcx", chase_bottom, chase_bottom_shade);
+
395  PrepareBitmap("ladder1.pcx", pitch_ladder_pos,
+
396  pitch_ladder_pos_shade);
+
397  PrepareBitmap("ladder2.pcx", pitch_ladder_neg,
+
398  pitch_ladder_neg_shade);
+
399 
+
400  hud_left_air.SetType(Bitmap::BMP_TRANSLUCENT);
+
401  hud_right_air.SetType(Bitmap::BMP_TRANSLUCENT);
+
402  hud_left_fighter.SetType(Bitmap::BMP_TRANSLUCENT);
+
403  hud_right_fighter.SetType(Bitmap::BMP_TRANSLUCENT);
+
404  hud_left_starship.SetType(Bitmap::BMP_TRANSLUCENT);
+
405  hud_right_starship.SetType(Bitmap::BMP_TRANSLUCENT);
+
406  instr_left.SetType(Bitmap::BMP_TRANSLUCENT);
+
407  instr_right.SetType(Bitmap::BMP_TRANSLUCENT);
+
408  warn_left.SetType(Bitmap::BMP_TRANSLUCENT);
+
409  warn_right.SetType(Bitmap::BMP_TRANSLUCENT);
+
410  icon_ship.SetType(Bitmap::BMP_TRANSLUCENT);
+
411  icon_target.SetType(Bitmap::BMP_TRANSLUCENT);
+ + + + + + + + +
420  chase_left.SetType(Bitmap::BMP_TRANSLUCENT);
+
421  chase_right.SetType(Bitmap::BMP_TRANSLUCENT);
+
422  chase_top.SetType(Bitmap::BMP_TRANSLUCENT);
+
423  chase_bottom.SetType(Bitmap::BMP_TRANSLUCENT);
+
424  pitch_ladder_pos.SetType(Bitmap::BMP_TRANSLUCENT);
+
425  pitch_ladder_neg.SetType(Bitmap::BMP_TRANSLUCENT);
+
426 
+
427  hud_left_sprite = new(__FILE__,__LINE__) Sprite(&hud_left_fighter);
+
428  hud_right_sprite = new(__FILE__,__LINE__) Sprite(&hud_right_fighter);
+
429  instr_left_sprite = new(__FILE__,__LINE__) Sprite(&instr_left);
+
430  instr_right_sprite = new(__FILE__,__LINE__) Sprite(&instr_right);
+
431  warn_left_sprite = new(__FILE__,__LINE__) Sprite(&warn_left);
+
432  warn_right_sprite = new(__FILE__,__LINE__) Sprite(&warn_right);
+
433  icon_ship_sprite = new(__FILE__,__LINE__) Sprite(&icon_ship);
+
434  icon_target_sprite = new(__FILE__,__LINE__) Sprite(&icon_target);
+
435  fpm_sprite = new(__FILE__,__LINE__) Sprite(&fpm);
+
436  hpm_sprite = new(__FILE__,__LINE__) Sprite(&hpm);
+
437  lead_sprite = new(__FILE__,__LINE__) Sprite(&lead);
+
438  aim_sprite = new(__FILE__,__LINE__) Sprite(&cross);
+
439  tgt1_sprite = new(__FILE__,__LINE__) Sprite(&cross1);
+
440  tgt2_sprite = new(__FILE__,__LINE__) Sprite(&cross2);
+
441  tgt3_sprite = new(__FILE__,__LINE__) Sprite(&cross3);
+
442  tgt4_sprite = new(__FILE__,__LINE__) Sprite(&cross4);
+
443  chase_sprite = new(__FILE__,__LINE__) Sprite(&chase_left);
+
444 
+
445  ZeroMemory(hud_sprite, sizeof(hud_sprite));
+
446 
+
447  hud_sprite[ 0] = hud_left_sprite;
+
448  hud_sprite[ 1] = hud_right_sprite;
+
449  hud_sprite[ 2] = instr_left_sprite;
+
450  hud_sprite[ 3] = instr_right_sprite;
+
451  hud_sprite[ 4] = warn_left_sprite;
+
452  hud_sprite[ 5] = warn_right_sprite;
+
453  hud_sprite[ 6] = icon_ship_sprite;
+
454  hud_sprite[ 7] = icon_target_sprite;
+
455  hud_sprite[ 8] = fpm_sprite;
+
456  hud_sprite[ 9] = hpm_sprite;
+
457  hud_sprite[10] = lead_sprite;
+
458  hud_sprite[11] = aim_sprite;
+
459  hud_sprite[12] = tgt1_sprite;
+
460  hud_sprite[13] = tgt2_sprite;
+
461  hud_sprite[14] = tgt3_sprite;
+
462  hud_sprite[15] = tgt4_sprite;
+
463  hud_sprite[16] = chase_sprite;
+
464 
+
465  double pitch_ladder_UV[8] = { 0.125,0.0625, 0.875,0.0625, 0.875,0, 0.125,0 };
+
466  double UV[8];
+
467 
+
468  for (i = 0; i < 15; i++) {
+
469  pitch_ladder[i] = new(__FILE__,__LINE__) Sprite(&pitch_ladder_pos);
+
470 
+
471  CopyMemory(UV, pitch_ladder_UV, sizeof(UV));
+
472  UV[1] = UV[3] = (pitch_ladder_UV[1] * (i ));
+
473  UV[5] = UV[7] = (pitch_ladder_UV[1] * (i+1));
+
474 
+
475  pitch_ladder[i]->Reshape(192, 16);
+
476  pitch_ladder[i]->SetTexCoords(UV);
+
477  pitch_ladder[i]->SetBlendMode(2);
+
478  pitch_ladder[i]->Hide();
+
479  }
+
480 
+
481  // zero mark at i=15
+
482  {
+
483  pitch_ladder[i] = new(__FILE__,__LINE__) Sprite(&pitch_ladder_pos);
+
484 
+
485  UV[0] = UV[6] = 0;
+
486  UV[2] = UV[4] = 1;
+
487  UV[1] = UV[3] = (pitch_ladder_UV[1] * (i+1));
+
488  UV[5] = UV[7] = (pitch_ladder_UV[1] * (i ));
+
489 
+
490  pitch_ladder[i]->Reshape(256, 16);
+
491  pitch_ladder[i]->SetTexCoords(UV);
+
492  pitch_ladder[i]->SetBlendMode(2);
+
493  pitch_ladder[i]->Hide();
+
494  }
+
495 
+
496  for (i = 16; i < 31; i++) {
+
497  pitch_ladder[i] = new(__FILE__,__LINE__) Sprite(&pitch_ladder_neg);
+
498 
+
499  CopyMemory(UV, pitch_ladder_UV, sizeof(UV));
+
500  UV[1] = UV[3] = (pitch_ladder_UV[1] * (30 - i ));
+
501  UV[5] = UV[7] = (pitch_ladder_UV[1] * (30 - i+1));
+
502 
+
503  pitch_ladder[i]->Reshape(192, 16);
+
504  pitch_ladder[i]->SetTexCoords(UV);
+
505  pitch_ladder[i]->SetBlendMode(2);
+
506  pitch_ladder[i]->Hide();
+
507  }
+
508 
+
509  for (i = 0; i < 3; i++)
+
510  mfd[i] = new(__FILE__,__LINE__) MFD(window, i);
+
511 
+
512  mfd[0]->SetRect(Rect( 8, height - 136, 128, 128));
+
513  mfd[1]->SetRect(Rect(width - 136, height - 136, 128, 128));
+
514  mfd[2]->SetRect(Rect( 8, 8, 128, 128));
+
515 
+
516  hud_left_sprite->MoveTo( Point(width/2-128, height/2, 1));
+
517  hud_right_sprite->MoveTo(Point(width/2+128, height/2, 1));
+
518  hud_left_sprite->SetBlendMode(2);
+
519  hud_left_sprite->SetFilter(0);
+
520  hud_right_sprite->SetBlendMode(2);
+
521  hud_right_sprite->SetFilter(0);
+
522 
+
523  instr_left_sprite->MoveTo( Point(width/2-128, height-128, 1));
+
524  instr_right_sprite->MoveTo(Point(width/2+128, height-128, 1));
+
525  instr_left_sprite->SetBlendMode(2);
+
526  instr_left_sprite->SetFilter(0);
+
527  instr_right_sprite->SetBlendMode(2);
+
528  instr_right_sprite->SetFilter(0);
+
529 
+
530  warn_left_sprite->MoveTo( Point(width/2-128, height-128, 1));
+
531  warn_right_sprite->MoveTo(Point(width/2+128, height-128, 1));
+
532  warn_left_sprite->SetBlendMode(2);
+
533  warn_left_sprite->SetFilter(0);
+
534  warn_right_sprite->SetBlendMode(2);
+
535  warn_right_sprite->SetFilter(0);
+
536 
+
537  icon_ship_sprite->MoveTo( Point( 184, height-72, 1));
+
538  icon_target_sprite->MoveTo(Point(width - 184, height-72, 1));
+
539  icon_ship_sprite->SetBlendMode(2);
+
540  icon_ship_sprite->SetFilter(0);
+
541  icon_target_sprite->SetBlendMode(2);
+
542  icon_target_sprite->SetFilter(0);
+
543 
+
544  fpm_sprite->MoveTo(Point(width/2, height/2, 1));
+
545  hpm_sprite->MoveTo(Point(width/2, height/2, 1));
+
546  lead_sprite->MoveTo(Point(width/2, height/2, 1));
+
547  aim_sprite->MoveTo(Point(width/2, height/2, 1));
+
548  tgt1_sprite->MoveTo(Point(width/2, height/2, 1));
+
549  tgt2_sprite->MoveTo(Point(width/2, height/2, 1));
+
550  tgt3_sprite->MoveTo(Point(width/2, height/2, 1));
+
551  tgt4_sprite->MoveTo(Point(width/2, height/2, 1));
+
552 
+
553  fpm_sprite->SetBlendMode(2);
+
554  hpm_sprite->SetBlendMode(2);
+
555  lead_sprite->SetBlendMode(2);
+
556  aim_sprite->SetBlendMode(2);
+
557  tgt1_sprite->SetBlendMode(2);
+
558  tgt2_sprite->SetBlendMode(2);
+
559  tgt3_sprite->SetBlendMode(2);
+
560  tgt4_sprite->SetBlendMode(2);
+
561  chase_sprite->SetBlendMode(2);
+
562 
+
563  fpm_sprite->SetFilter(0);
+
564  hpm_sprite->SetFilter(0);
+
565  lead_sprite->SetFilter(0);
+
566  aim_sprite->SetFilter(0);
+
567  tgt1_sprite->SetFilter(0);
+
568  tgt2_sprite->SetFilter(0);
+
569  tgt3_sprite->SetFilter(0);
+
570  tgt4_sprite->SetFilter(0);
+
571  chase_sprite->SetFilter(0);
+
572 
+
573  lead_sprite->Hide();
+
574  aim_sprite->Hide();
+
575  tgt1_sprite->Hide();
+
576  tgt2_sprite->Hide();
+
577  tgt3_sprite->Hide();
+
578  tgt4_sprite->Hide();
+
579  chase_sprite->Hide();
+
580 
+
581  aw = chase_left.Width() / 2;
+
582  ah = chase_left.Height() / 2;
+
583 
+ + + +
587 
+
588  hud_font = FontMgr::Find("HUD");
+
589  big_font = FontMgr::Find("GUI");
+
590 
+
591  for (i = 0; i < TXT_LAST; i++) {
+
592  hud_text[i].font = hud_font;
+
593  }
+
594 
+
595  hud_text[TXT_THREAT_WARN].font = big_font;
+
596  hud_text[TXT_SHOOT].font = big_font;
+
597  hud_text[TXT_AUTO].font = big_font;
+
598 
+ +
600  MFD::SetColor(standard_hud_colors[color]);
+
601 
+
602  DataLoader* loader = DataLoader::GetLoader();
+
603  loader->SetDataPath("HUD/");
+
604 
+
605  az_ring = new(__FILE__,__LINE__) Solid;
+
606  az_pointer = new(__FILE__,__LINE__) Solid;
+
607  el_ring = new(__FILE__,__LINE__) Solid;
+
608  el_pointer = new(__FILE__,__LINE__) Solid;
+
609 
+
610  az_ring->Load("CompassRing.mag", compass_scale);
+
611  az_pointer->Load("CompassPointer.mag", compass_scale);
+
612  el_ring->Load("PitchRing.mag", compass_scale);
+
613  el_pointer->Load("CompassPointer.mag", compass_scale);
+
614 
+
615  loader->SetDataPath("Sounds/");
+
616  loader->LoadSound("MissileLock.wav", missile_lock_sound, Sound::LOOP | Sound::LOCKED);
+
617 
+
618  loader->SetDataPath(0);
+
619 
+
620  for (i = 0; i < MAX_MSG; i++)
+
621  msg_time[i] = 0;
+
622 }
+
623 
+ +
625 {
+
626  HideCompass();
+
627 
+
628  if (missile_lock_sound) {
+
629  missile_lock_sound->Stop();
+
630  missile_lock_sound->Release();
+
631  missile_lock_sound = 0;
+
632  }
+
633 
+
634  for (int i = 0; i < 3; i++) {
+
635  delete mfd[i];
+
636  mfd[i] = 0;
+
637  }
+
638 
+
639  for (int i = 0; i < 32; i++) {
+ +
641  }
+
642 
+
643  fpm.ClearImage();
+
644  hpm.ClearImage();
+
645  lead.ClearImage();
+
646  cross.ClearImage();
+
647  cross1.ClearImage();
+
648  cross2.ClearImage();
+
649  cross3.ClearImage();
+
650  cross4.ClearImage();
+
651  hud_left_air.ClearImage();
+
652  hud_right_air.ClearImage();
+
653  hud_left_fighter.ClearImage();
+
654  hud_right_fighter.ClearImage();
+
655  hud_left_starship.ClearImage();
+
656  hud_right_starship.ClearImage();
+
657  instr_left.ClearImage();
+
658  instr_right.ClearImage();
+
659  warn_left.ClearImage();
+
660  warn_right.ClearImage();
+
661  icon_ship.ClearImage();
+
662  icon_target.ClearImage();
+
663  chase_left.ClearImage();
+
664  chase_right.ClearImage();
+
665  chase_top.ClearImage();
+
666  chase_bottom.ClearImage();
+
667  pitch_ladder_pos.ClearImage();
+
668  pitch_ladder_neg.ClearImage();
+
669 
+
670  delete [] fpm_shade;
+
671  delete [] hpm_shade;
+
672  delete [] lead_shade;
+
673  delete [] cross_shade;
+
674  delete [] cross1_shade;
+
675  delete [] cross2_shade;
+
676  delete [] cross3_shade;
+
677  delete [] cross4_shade;
+
678  delete [] hud_left_shade_air;
+
679  delete [] hud_right_shade_air;
+
680  delete [] hud_left_shade_fighter;
+
681  delete [] hud_right_shade_fighter;
+
682  delete [] hud_left_shade_starship;
+
683  delete [] hud_right_shade_starship;
+
684  delete [] instr_left_shade;
+
685  delete [] instr_right_shade;
+
686  delete [] warn_left_shade;
+
687  delete [] warn_right_shade;
+
688  delete [] icon_ship_shade;
+
689  delete [] icon_target_shade;
+
690  delete [] chase_left_shade;
+
691  delete [] chase_right_shade;
+
692  delete [] chase_top_shade;
+
693  delete [] chase_bottom_shade;
+
694  delete [] pitch_ladder_pos_shade;
+
695  delete [] pitch_ladder_neg_shade;
+
696 
+
697  delete az_ring;
+
698  delete az_pointer;
+
699  delete el_ring;
+
700  delete el_pointer;
+
701 
+
702  fpm_shade = 0;
+
703  hpm_shade = 0;
+
704  cross_shade = 0;
+
705  cross1_shade = 0;
+
706  cross2_shade = 0;
+
707  cross3_shade = 0;
+
708  cross4_shade = 0;
+
709  hud_left_shade_air = 0;
+
710  hud_right_shade_air = 0;
+
711  hud_left_shade_fighter = 0;
+
712  hud_right_shade_fighter = 0;
+
713  hud_left_shade_starship = 0;
+
714  hud_right_shade_starship = 0;
+
715  instr_left_shade = 0;
+
716  instr_right_shade = 0;
+
717  warn_left_shade = 0;
+
718  warn_right_shade = 0;
+
719  icon_ship_shade = 0;
+
720  icon_target_shade = 0;
+
721  chase_left_shade = 0;
+
722  chase_right_shade = 0;
+
723  chase_top_shade = 0;
+
724  chase_bottom_shade = 0;
+
725  pitch_ladder_pos_shade = 0;
+
726  pitch_ladder_neg_shade = 0;
+
727 
+
728  az_ring = 0;
+
729  az_pointer = 0;
+
730  el_ring = 0;
+
731  el_pointer = 0;
+
732 
+
733  hud_view = 0;
+
734 }
+
735 
+
736 void
+ +
738 {
+
739  width = window->Width();
+
740  height = window->Height();
+
741  xcenter = (width / 2.0) - 0.5;
+
742  ycenter = (height / 2.0) + 0.5;
+
743 
+
744  mfd[0]->SetRect(Rect( 8, height - 136, 128, 128));
+
745  mfd[1]->SetRect(Rect(width - 136, height - 136, 128, 128));
+
746  mfd[2]->SetRect(Rect( 8, 8, 128, 128));
+
747 
+
748  hud_left_sprite->MoveTo( Point(width/2-128, height/2, 1));
+
749  hud_right_sprite->MoveTo(Point(width/2+128, height/2, 1));
+
750 
+
751  instr_left_sprite->MoveTo( Point(width/2-128, height-128, 1));
+
752  instr_right_sprite->MoveTo(Point(width/2+128, height-128, 1));
+
753  warn_left_sprite->MoveTo( Point(width/2-128, height-128, 1));
+
754  warn_right_sprite->MoveTo(Point(width/2+128, height-128, 1));
+
755  icon_ship_sprite->MoveTo( Point( 184, height-72, 1));
+
756  icon_target_sprite->MoveTo(Point(width - 184, height-72, 1));
+
757 
+
758  for (int i = 0; i < TXT_LAST; i++) {
+
759  hud_text[i].font = hud_font;
+
760  hud_text[i].color = standard_txt_colors[color];
+
761  }
+
762 
+
763  if (big_font) {
+
764  hud_text[TXT_THREAT_WARN].font = big_font;
+
765  hud_text[TXT_SHOOT].font = big_font;
+
766  hud_text[TXT_AUTO].font = big_font;
+
767  }
+
768 
+
769  MFD::SetColor(standard_hud_colors[color]);
+
770 
+
771  int cx = width/2;
+
772  int cy = height/2;
+
773 }
+
774 
+
775 // +--------------------------------------------------------------------+
+
776 
+
777 void
+ +
779 {
+
780  if (tactical != mode) {
+
781  tactical = mode;
+
782 
+
783  if (tactical) {
+
784  hud_left_sprite->Hide();
+
785  hud_right_sprite->Hide();
+
786 
+
787  for (int i = 0; i < 31; i++)
+
788  pitch_ladder[i]->Hide();
+
789  }
+
790  else if (Game::MaxTexSize() > 128) {
+
791  hud_left_sprite->Show();
+
792  hud_right_sprite->Show();
+
793  }
+
794  }
+
795 }
+
796 
+
797 void
+ +
799 {
+
800  if (overlay != mode) {
+
801  overlay = mode;
+
802  }
+
803 }
+
804 
+
805 // +--------------------------------------------------------------------+
+
806 
+
807 bool
+ +
809 {
+
810  if (obj == ship) {
+
811  if (target)
+
812  SetTarget(0);
+
813 
+
814  ship = 0;
+
815 
+
816  for (int i = 0; i < 3; i++)
+
817  mfd[i]->SetShip(ship);
+
818  }
+
819 
+
820  if (obj == target) {
+
821  target = 0;
+
822  PrepareBitmap("hud_icon.pcx", icon_target, icon_target_shade);
+
823  ColorizeBitmap(icon_target, icon_target_shade, txt_color);
+
824  }
+
825 
+
826  return SimObserver::Update(obj);
+
827 }
+
828 
+
829 const char*
+ +
831 {
+
832  return "HUDView";
+
833 }
+
834 
+
835 // +--------------------------------------------------------------------+
+
836 
+
837 void
+ +
839 {
+
840  if (v && camview != v) {
+
841  camview = v;
+
842 
+
843  for (int i = 0; i < 3; i++)
+ +
845 
+ +
847  }
+
848 }
+
849 
+
850 // +--------------------------------------------------------------------+
+
851 
+
852 Color
+ +
854 {
+
855  Color c(80,80,80);
+
856 
+
857  if (contact) {
+
858  Sim* sim = Sim::GetSim();
+
859  Ship* ship = sim->GetPlayerShip();
+
860 
+
861  int c_iff = contact->GetIFF(ship);
+
862 
+
863  c = Ship::IFFColor(c_iff) * contact->Age();
+
864 
+
865  if (contact->GetShot() && contact->Threat(ship)) {
+
866  if ((Game::RealTime()/500) & 1)
+
867  c = c * 2;
+
868  else
+
869  c = c * 0.5;
+
870  }
+
871  }
+
872 
+
873  return c;
+
874 }
+
875 
+
876 // +--------------------------------------------------------------------+
+
877 
+
878 void
+ +
880 {
+
881  threat = 0;
+
882 
+
883  for (int i = 0; i < MAX_CONTACT; i++) {
+ + +
886  }
+
887 
+
888 
+
889  if (!ship)
+
890  return;
+
891 
+
892  int index = 0;
+
893  ListIter<Contact> contact = ship->ContactList();
+
894 
+
895  // draw own sensor contacts:
+
896  while (++contact) {
+
897  Contact* c = contact.value();
+
898 
+
899  // draw track ladder:
+
900  if (c->TrackLength() > 0 && c->GetShip() != ship) {
+
901  DrawTrack(c);
+
902  }
+
903 
+
904  DrawContact(c, index++);
+
905  }
+
906 
+
907  Color c = ship->MarkerColor();
+
908 
+
909  // draw own ship track ladder:
+ +
911  int ctl = ship->TrackLength();
+
912 
+
913  Point t1 = ship->Location();
+
914  Point t2 = ship->TrackPoint(0);
+
915 
+
916  if (t1 != t2)
+
917  DrawTrackSegment(t1, t2, c);
+
918 
+
919  for (int i = 0; i < ctl-1; i++) {
+
920  t1 = ship->TrackPoint(i);
+
921  t2 = ship->TrackPoint(i+1);
+
922 
+
923  if (t1 != t2)
+
924  DrawTrackSegment(t1, t2, c * ((double) (ctl-i)/ (double) ctl));
+
925  }
+
926  }
+
927 
+
928  // draw own ship marker:
+
929  Point mark_pt = ship->Location();
+
930  projector->Transform(mark_pt);
+
931 
+
932  // clip:
+
933  if (CameraDirector::GetCameraMode() == CameraDirector::MODE_ORBIT && mark_pt.z > 1.0) {
+
934  projector->Project(mark_pt);
+
935 
+
936  int x = (int) mark_pt.x;
+
937  int y = (int) mark_pt.y;
+
938 
+
939  if (x > 4 && x < width-4 &&
+
940  y > 4 && y < height-4) {
+
941 
+
942  DrawDiamond(x,y,5,c);
+
943 
+
944  if (tactical) {
+
945  Rect self_rect(x+8, y-4, 200, 12);
+
946  DrawHUDText(TXT_SELF, ship->Name(), self_rect, DT_LEFT, HUD_MIXED_CASE);
+
947 
+
948  if (NetGame::GetInstance()) {
+ +
950  if (p) {
+
951  Rect net_name_rect(x+8, y+6, 120, 12);
+
952  DrawHUDText(TXT_SELF_NAME, p->Name(), net_name_rect, DT_LEFT, HUD_MIXED_CASE);
+
953  }
+
954  }
+
955  }
+
956  }
+
957  }
+
958 
+
959  // draw life bars on targeted ship:
+
960  if (target && target->Type() == SimObject::SIM_SHIP && target->Rep()) {
+
961  Ship* tgt_ship = (Ship*) target;
+
962  Graphic* g = tgt_ship->Rep();
+
963  Rect r = g->ScreenRect();
+
964 
+
965  Point mark_pt;
+
966 
+
967  if (tgt_ship)
+
968  mark_pt = tgt_ship->Location();
+
969 
+
970  projector->Transform(mark_pt);
+
971 
+
972  // clip:
+
973  if (mark_pt.z > 1.0) {
+
974  projector->Project(mark_pt);
+
975 
+
976  int x = (int) mark_pt.x;
+
977  int y = r.y;
+
978 
+
979  if (y >= 2000)
+
980  y = (int) mark_pt.y;
+
981 
+
982  if (x > 4 && x < width-4 &&
+
983  y > 4 && y < height-4) {
+
984 
+
985  const int BAR_LENGTH = 40;
+
986 
+
987  // life bars:
+
988  int sx = x - BAR_LENGTH/2;
+
989  int sy = y - 8;
+
990 
+
991  double hull_strength = tgt_ship->Integrity() / tgt_ship->Design()->integrity;
+
992 
+
993  int hw = (int) (BAR_LENGTH * hull_strength);
+
994  int sw = (int) (BAR_LENGTH * (tgt_ship->ShieldStrength() / 100.0));
+
995 
+ +
997 
+
998  if (hull_strength < 0.30) s = System::CRITICAL;
+
999  else if (hull_strength < 0.60) s = System::DEGRADED;
+
1000 
+
1001  Color hc = GetStatusColor(s);
+
1002  Color sc = hud_color;
+
1003 
+
1004  window->FillRect(sx, sy, sx+hw, sy+1, hc);
+
1005  window->FillRect(sx, sy+3, sx+sw, sy+4, sc);
+
1006  }
+
1007  }
+
1008  }
+
1009 }
+
1010 
+
1011 // +--------------------------------------------------------------------+
+
1012 
+
1013 void
+
1014 HUDView::DrawContact(Contact* contact, int index)
+
1015 {
+
1016  if (index >= MAX_CONTACT) return;
+
1017 
+
1018  Color c = MarkerColor(contact);
+
1019  int c_iff = contact->GetIFF(ship);
+
1020  Ship* c_ship = contact->GetShip();
+
1021  Shot* c_shot = contact->GetShot();
+
1022  Point mark_pt = contact->Location();
+
1023  double distance = 0;
+
1024 
+
1025  if (!c_ship && !c_shot || c_ship == ship)
+
1026  return;
+
1027 
+
1028  if (c_ship && c_ship->GetFlightPhase() < Ship::ACTIVE)
+
1029  return;
+
1030 
+
1031  if (c_ship) {
+
1032  mark_pt = c_ship->Location();
+
1033 
+
1034  if (c_ship->IsGroundUnit())
+
1035  mark_pt += Point(0,150,0);
+
1036  }
+
1037  else {
+
1038  mark_pt = c_shot->Location();
+
1039  }
+
1040 
+
1041  projector->Transform(mark_pt);
+
1042 
+
1043  // clip:
+
1044  if (mark_pt.z > 1.0) {
+
1045  distance = mark_pt.length();
+
1046 
+
1047  projector->Project(mark_pt);
+
1048 
+
1049  int x = (int) mark_pt.x;
+
1050  int y = (int) mark_pt.y;
+
1051 
+
1052  if (x > 4 && x < width-4 &&
+
1053  y > 4 && y < height-4) {
+
1054 
+
1055  DrawDiamond(x,y,3,c);
+
1056 
+
1057  if (contact->Threat(ship)) {
+
1058  if (c_ship) {
+
1059  window->DrawEllipse(x-6, y-6, x+6, y+6, c);
+
1060  }
+
1061  else {
+
1062  DrawDiamond(x,y,7,c);
+
1063  }
+
1064  }
+
1065 
+
1066  bool name_crowded = false;
+
1067 
+
1068  if (x < width-8) {
+
1069  char code = *(Game::GetText("HUDView.symbol.fighter").data());
+
1070 
+
1071  if (c_ship) {
+
1072  if (c_ship->Class() > Ship::LCA)
+
1073  code = *(Game::GetText("HUDView.symbol.starship").data());
+
1074  }
+
1075 
+
1076  else if (c_shot) {
+
1077  code = *(Game::GetText("HUDView.symbol.torpedo").data());
+
1078  }
+
1079 
+
1080  Sensor* sensor = ship->GetSensor();
+
1081  double limit = 75e3;
+
1082 
+
1083  if (sensor)
+
1084  limit = sensor->GetBeamRange();
+
1085 
+
1086  double range = contact->Range(ship, limit);
+
1087 
+
1088  char contact_buf[256];
+
1089  Rect contact_rect(x+8, y-4, 120, 12);
+
1090 
+
1091  if (range == 0) {
+
1092  sprintf_s(contact_buf, "%c *", code);
+
1093  }
+
1094  else {
+
1095  bool mega = false;
+
1096 
+
1097  if (range > 999e3) {
+
1098  range /= 1e6;
+
1099  mega = true;
+
1100  }
+
1101  else if (range < 1e3)
+
1102  range = 1;
+
1103  else
+
1104  range /= 1000;
+
1105 
+
1106  if (arcade) {
+
1107  if (c_ship)
+
1108  strcpy_s(contact_buf, c_ship->Name());
+
1109  else if (!mega)
+
1110  sprintf_s(contact_buf, "%c %d", code, (int) range);
+
1111  else
+
1112  sprintf_s(contact_buf, "%c %.1f M", code, range);
+
1113  }
+
1114  else {
+
1115  char closing = '+';
+
1116  Point delta_v;
+
1117 
+
1118  if (c_ship)
+
1119  delta_v = ship->Velocity() - c_ship->Velocity();
+
1120  else if (c_shot)
+
1121  delta_v = ship->Velocity() - c_shot->Velocity();
+
1122 
+
1123  if (delta_v * ship->Velocity() < 0) // losing ground
+
1124  closing = '-';
+
1125 
+
1126  if (!mega)
+
1127  sprintf_s(contact_buf, "%c %d%c", code, (int) range, closing);
+
1128  else
+
1129  sprintf_s(contact_buf, "%c %.1f M", code, range);
+
1130  }
+
1131  }
+
1132 
+
1133  if (!IsNameCrowded(x, y)) {
+
1134  DrawHUDText(TXT_CONTACT_INFO+index, contact_buf, contact_rect, DT_LEFT, HUD_MIXED_CASE);
+
1135 
+
1136  if (c_shot || (c_ship && (c_ship->IsDropship() || c_ship->IsStatic())))
+
1137  name_crowded = distance > 50e3;
+
1138  }
+
1139  else {
+
1140  name_crowded = true;
+
1141  }
+
1142  }
+
1143 
+
1144  bool name_drawn = false;
+
1145  if (NetGame::GetInstance() && c_ship) {
+
1146  NetPlayer* netp = NetGame::GetInstance()->FindPlayerByObjID(c_ship->GetObjID());
+
1147  if (netp && strcmp(netp->Name(), "Server A.I. Ship")) {
+
1148  Rect contact_rect(x+8, y+6, 120, 12);
+
1149  DrawHUDText(TXT_CONTACT_NAME+index, netp->Name(), contact_rect, DT_LEFT, HUD_MIXED_CASE);
+
1150  name_drawn = true;
+
1151  }
+
1152  }
+
1153 
+
1154  if (!name_drawn && !name_crowded && c_ship && c_iff < 10 && !arcade) {
+
1155  Rect contact_rect(x+8, y+6, 120, 12);
+
1156  DrawHUDText(TXT_CONTACT_NAME+index, c_ship->Name(), contact_rect, DT_LEFT, HUD_MIXED_CASE);
+
1157  }
+
1158  }
+
1159  }
+
1160 
+
1161  if (contact->Threat(ship) && !ship->IsStarship()) {
+
1162  if (threat < 1 && c_ship && !c_ship->IsStarship())
+
1163  threat = 1;
+
1164 
+
1165  if (c_shot)
+
1166  threat = 2;
+
1167  }
+
1168 }
+
1169 
+
1170 // +--------------------------------------------------------------------+
+
1171 
+
1172 void
+ +
1174 {
+
1175  int x1, y1, x2, y2;
+
1176 
+
1177  projector->Transform(t1);
+
1178  projector->Transform(t2);
+
1179 
+
1180  const double CLIP_Z = 0.1;
+
1181 
+
1182  if (t1.z < CLIP_Z && t2.z < CLIP_Z)
+
1183  return;
+
1184 
+
1185  if (t1.z < CLIP_Z && t2.z >= CLIP_Z) {
+
1186  double dx = t2.x - t1.x;
+
1187  double dy = t2.y - t1.y;
+
1188  double s = (CLIP_Z - t1.z) / (t2.z - t1.z);
+
1189 
+
1190  t1.x += dx * s;
+
1191  t1.y += dy * s;
+
1192  t1.z = CLIP_Z;
+
1193  }
+
1194 
+
1195  else if (t2.z < CLIP_Z && t1.z >= CLIP_Z) {
+
1196  double dx = t1.x - t2.x;
+
1197  double dy = t1.y - t2.y;
+
1198  double s = (CLIP_Z - t2.z) / (t1.z - t2.z);
+
1199 
+
1200  t2.x += dx * s;
+
1201  t2.y += dy * s;
+
1202  t2.z = CLIP_Z;
+
1203  }
+
1204 
+
1205  if (t1.z >= CLIP_Z && t2.z >= CLIP_Z) {
+
1206  projector->Project(t1, false);
+
1207  projector->Project(t2, false);
+
1208 
+
1209  x1 = (int) t1.x;
+
1210  y1 = (int) t1.y;
+
1211  x2 = (int) t2.x;
+
1212  y2 = (int) t2.y;
+
1213 
+
1214  if (window->ClipLine(x1,y1,x2,y2))
+
1215  window->DrawLine(x1,y1,x2,y2,c);
+
1216  }
+
1217 }
+
1218 
+
1219 void
+ +
1221 {
+
1222  Ship* c_ship = contact->GetShip();
+
1223 
+
1224  if (c_ship && c_ship->GetFlightPhase() < Ship::ACTIVE)
+
1225  return;
+
1226 
+
1227  int ctl = contact->TrackLength();
+
1228  Color c = MarkerColor(contact);
+
1229 
+
1230  Point t1 = contact->Location();
+
1231  Point t2 = contact->TrackPoint(0);
+
1232 
+
1233  if (t1 != t2)
+
1234  DrawTrackSegment(t1, t2, c);
+
1235 
+
1236  for (int i = 0; i < ctl-1; i++) {
+
1237  t1 = contact->TrackPoint(i);
+
1238  t2 = contact->TrackPoint(i+1);
+
1239 
+
1240  if (t1 != t2)
+
1241  DrawTrackSegment(t1, t2, c * ((double) (ctl-i)/ (double) ctl));
+
1242  }
+
1243 }
+
1244 
+
1245 // +--------------------------------------------------------------------+
+
1246 
+
1247 void
+ +
1249 {
+
1250  Graphic* g = targ->Rep();
+
1251  Rect r = g->ScreenRect();
+
1252  Color c;
+
1253 
+
1254  if (targ->Type() == SimObject::SIM_SHIP)
+
1255  c = ((Ship*) targ)->MarkerColor();
+
1256  else
+
1257  c = ((Shot*) targ)->MarkerColor();
+
1258 
+
1259  if (r.w > 0 && r.h > 0) {
+
1260  if (r.w < 8) {
+
1261  r.x -= (8-r.w)/2;
+
1262  r.w = 8;
+
1263  }
+
1264 
+
1265  if (r.h < 8) {
+
1266  r.y -= (8-r.h)/2;
+
1267  r.h = 8;
+
1268  }
+
1269  }
+
1270 
+
1271  else {
+
1272  Point mark_pt = targ->Location();
+
1273  projector->Transform(mark_pt);
+
1274 
+
1275  // clip:
+
1276  if (mark_pt.z < 1.0)
+
1277  return;
+
1278 
+
1279  projector->Project(mark_pt);
+
1280 
+
1281  int x = (int) mark_pt.x;
+
1282  int y = (int) mark_pt.y;
+
1283 
+
1284  if (x < 4 || x > width-4 || y < 4 || y > height-4)
+
1285  return;
+
1286 
+
1287  r.x = x-4;
+
1288  r.y = y-4;
+
1289  r.w = 8;
+
1290  r.h = 8;
+
1291  }
+
1292 
+
1293  // horizontal
+
1294  window->DrawLine(r.x, r.y, r.x+8, r.y, c);
+
1295  window->DrawLine(r.x+r.w-8, r.y, r.x+r.w, r.y, c);
+
1296  window->DrawLine(r.x, r.y+r.h, r.x+8, r.y+r.h, c);
+
1297  window->DrawLine(r.x+r.w-8, r.y+r.h, r.x+r.w, r.y+r.h, c);
+
1298  // vertical
+
1299  window->DrawLine(r.x, r.y, r.x, r.y+8, c);
+
1300  window->DrawLine(r.x, r.y+r.h-8, r.x, r.y+r.h, c);
+
1301  window->DrawLine(r.x+r.w, r.y, r.x+r.w, r.y+8, c);
+
1302  window->DrawLine(r.x+r.w, r.y+r.h-8, r.x+r.w, r.y+r.h, c);
+
1303 }
+
1304 
+
1305 // +--------------------------------------------------------------------+
+
1306 
+
1307 void
+ +
1309 {
+
1310  fpm_sprite->Hide();
+
1311  hpm_sprite->Hide();
+
1312  lead_sprite->Hide();
+
1313  aim_sprite->Hide();
+
1314  tgt1_sprite->Hide();
+
1315  tgt2_sprite->Hide();
+
1316  tgt3_sprite->Hide();
+
1317  tgt4_sprite->Hide();
+
1318  chase_sprite->Hide();
+
1319 
+
1320  for (int i = 0; i < 31; i++)
+
1321  pitch_ladder[i]->Hide();
+
1322 
+
1323  const int bar_width = 256;
+
1324  const int bar_height = 192;
+
1325  const int box_width = 120;
+
1326 
+
1327  int cx = width/2;
+
1328  int cy = height/2;
+
1329  int l = cx - bar_width/2;
+
1330  int r = cx + bar_width/2;
+
1331  int t = cy - bar_height/2;
+
1332  int b = cy + bar_height/2;
+
1333  int align = DT_LEFT;
+
1334 
+
1335  if (Game::Paused())
+
1336  DrawHUDText(TXT_PAUSED, Game::GetText("HUDView.PAUSED"), Rect(cx-128, cy-60, 256, 12), DT_CENTER);
+
1337 
+
1338  if (ship) {
+ +
1340 
+
1341  char txt[256];
+
1342  double speed = ship->Velocity().length();
+
1343 
+
1344  if (ship->Velocity() * ship->Heading() < 0)
+
1345  speed = -speed;
+
1346 
+
1347  FormatNumber(txt, speed);
+
1348 
+
1349  if (tactical) {
+
1350  l = box_width + 16;
+
1351  r = width - box_width - 16;
+
1352  }
+
1353 
+
1354  Rect speed_rect(l-box_width-8, cy-5, box_width, 12);
+
1355 
+
1356  align = (tactical) ? DT_LEFT : DT_RIGHT;
+
1357  DrawHUDText(TXT_SPEED, txt, speed_rect, align);
+
1358 
+
1359  // upper left hud quadrant (airborne fighters)
+
1360  if (ship->IsAirborne()) {
+
1361  double alt_msl = ship->AltitudeMSL();
+
1362  double alt_agl = ship->AltitudeAGL();
+
1363 
+
1364  if (alt_agl <= 1000)
+
1365  sprintf_s(txt, "R %4d", (int) alt_agl);
+
1366  else
+
1367  FormatNumber(txt, alt_msl);
+
1368 
+
1369  speed_rect.y -= 20;
+
1370 
+
1371  if (arcade) {
+
1372  char arcade_txt[32];
+
1373  sprintf_s(arcade_txt, "%s %s", Game::GetText("HUDView.altitude").data(), txt);
+
1374  align = (tactical) ? DT_LEFT : DT_RIGHT;
+
1375  DrawHUDText(TXT_ALTITUDE, arcade_txt, speed_rect, align);
+
1376  }
+
1377  else {
+
1378  align = (tactical) ? DT_LEFT : DT_RIGHT;
+
1379  DrawHUDText(TXT_ALTITUDE, txt, speed_rect, align);
+
1380  }
+
1381 
+
1382  if (!arcade) {
+
1383  sprintf_s(txt, "%.1f G", ship->GForce());
+
1384  speed_rect.y -= 20;
+
1385 
+
1386  align = (tactical) ? DT_LEFT : DT_RIGHT;
+
1387  DrawHUDText(TXT_GFORCE, txt, speed_rect, align);
+
1388 
+
1389  speed_rect.y += 40;
+
1390  }
+
1391  }
+
1392 
+
1393  // upper left hud quadrant (starships)
+
1394  else if (ship->IsStarship() && ship->GetFLCSMode() == Ship::FLCS_HELM && !arcade) {
+
1395  sprintf_s(txt, "%s: %.1f", Game::GetText("HUDView.Pitch").data(), ship->GetHelmPitch()/DEGREES);
+
1396  speed_rect.y -= 50;
+
1397 
+
1398  align = (tactical) ? DT_LEFT : DT_RIGHT;
+
1399  DrawHUDText(TXT_PITCH, txt, speed_rect, align);
+
1400 
+
1401  speed_rect.y -= 10;
+
1402  int heading_degrees = (int) (ship->GetHelmHeading()/DEGREES);
+
1403  if (heading_degrees < 0) heading_degrees += 360;
+
1404  sprintf_s(txt, "%s: %03d", Game::GetText("HUDView.Heading").data(), heading_degrees);
+
1405  DrawHUDText(TXT_HEADING, txt, speed_rect, align);
+
1406 
+
1407  speed_rect.y += 60;
+
1408  }
+
1409 
+
1410  // per user request, all ships should show compass heading
+
1411  if (!tactical && !arcade) {
+
1412  Rect heading_rect(l, t+5, bar_width, 12);
+
1413  int heading_degrees = (int) (ship->CompassHeading()/DEGREES);
+
1414  if (heading_degrees < 0) heading_degrees += 360;
+
1415  sprintf_s(txt, "%d", heading_degrees);
+
1416  DrawHUDText(TXT_COMPASS, txt, heading_rect, DT_CENTER);
+
1417  }
+
1418 
+
1419  switch (mode) {
+
1420  case HUD_MODE_TAC: strcpy_s(txt, Game::GetText("HUDView.mode.tactical").data()); break;
+
1421  case HUD_MODE_NAV: strcpy_s(txt, Game::GetText("HUDView.mode.navigation").data()); break;
+
1422  case HUD_MODE_ILS: strcpy_s(txt, Game::GetText("HUDView.mode.landing").data()); break;
+
1423  }
+
1424 
+
1425  if (tactical) {
+
1426  speed_rect.y += 76;
+
1427  align = DT_LEFT;
+
1428  }
+
1429  else {
+
1430  speed_rect.y = cy+76;
+
1431  align = DT_RIGHT;
+
1432  }
+
1433 
+
1434  DrawHUDText(TXT_HUD_MODE, txt, speed_rect, align);
+
1435 
+
1436  // landing gear:
+
1437  if (ship->IsGearDown()) {
+
1438  const char* gear_down = Game::GetText("HUDView.gear-down");
+
1439 
+
1440  Rect gear_rect(l, b+20, box_width, 12);
+
1441  DrawHUDText(TXT_GEAR_DOWN, gear_down, gear_rect, DT_CENTER, HUD_UPPER_CASE, true);
+
1442  }
+
1443 
+
1444  // sensor/missile lock warnings and quantum drive countdown:
+
1445  QuantumDrive* quantum = ship->GetQuantumDrive();
+
1446 
+
1447  if (threat || (quantum && quantum->JumpTime() > 0)) {
+
1448  const char* threat_warn = Game::GetText("HUDView.threat-warn");
+
1449  bool show_msg = true;
+
1450 
+
1451  if (quantum && quantum->JumpTime() > 0) {
+
1452  static char buf[64];
+
1453  sprintf_s(buf, "%s: %d", Game::GetText("HUDView.quantum-jump").data(), (int) quantum->JumpTime());
+
1454  threat_warn = buf;
+
1455  }
+
1456 
+
1457  else if (threat > 1) {
+
1458  threat_warn = Game::GetText("HUDView.missile-warn");
+
1459  show_msg = ((Game::RealTime()/500) & 1) != 0;
+
1460  }
+
1461 
+
1462  if (show_msg) {
+
1463  Rect lock_rect(l, t-25, box_width, 12);
+
1464  DrawHUDText(TXT_THREAT_WARN, threat_warn, lock_rect, DT_CENTER, HUD_MIXED_CASE, true);
+
1465  }
+
1466  }
+
1467 
+
1468  if (ship->CanTimeSkip()) {
+
1469  Rect auto_rect(l, t-40, box_width, 12);
+
1470  DrawHUDText(TXT_AUTO, Game::GetText("HUDView.AUTO"), auto_rect, DT_CENTER, HUD_MIXED_CASE, true);
+
1471  }
+
1472 
+
1473  if (mode == HUD_MODE_NAV) {
+
1474  Instruction* next = ship->GetNextNavPoint();
+
1475 
+
1476  if (next) {
+
1477  double distance = ship->RangeToNavPoint(next);
+
1478  FormatNumber(txt, distance);
+
1479 
+
1480  Rect range_rect(r-20, cy-5, box_width, 12);
+
1481  DrawHUDText(TXT_RANGE, txt, range_rect, DT_RIGHT);
+
1482  range_rect.Inflate(2,2);
+
1483  }
+
1484  }
+
1485 
+
1486  // lower left hud quadrant
+
1487  else if (mode == HUD_MODE_TAC) {
+
1488  speed_rect.x = l-box_width-8;
+
1489  speed_rect.y = cy-5 +20;
+
1490  speed_rect.w = box_width;
+
1491  align = (tactical) ? DT_LEFT : DT_RIGHT;
+
1492 
+
1493  if (!arcade && ship->GetPrimary() && !ship->IsNetObserver())
+
1494  DrawHUDText(TXT_PRIMARY_WEP, ship->GetPrimary()->Abbreviation(), speed_rect, align);
+
1495 
+
1496  WeaponGroup* missile = ship->GetSecondaryGroup();
+
1497 
+
1498  if (missile && missile->Ammo() > 0 && !ship->IsNetObserver()) {
+
1499  if (!arcade) {
+
1500  speed_rect.y = cy-5 +30;
+
1501  sprintf_s(txt, "%s %d", missile->Name(), missile->Ammo());
+
1502  DrawHUDText(TXT_SECONDARY_WEP, txt, speed_rect, align);
+
1503  }
+
1504 
+
1505  // missile range indicator
+
1506  if (missile->GetSelected()->Locked()) {
+
1507  Rect shoot_rect(l, b+5, box_width, 12);
+
1508  DrawHUDText(TXT_SHOOT, Game::GetText("HUDView.SHOOT"), shoot_rect, DT_CENTER, HUD_MIXED_CASE, true);
+
1509  }
+
1510  }
+
1511 
+
1512  if (!arcade && !ship->IsNetObserver()) {
+
1513  if (ship->GetShield()) {
+
1514  speed_rect.y = cy-5+40;
+
1515  sprintf_s(txt, "%s - %03d +", Game::GetText("HUDView.SHIELD").data(), ship->ShieldStrength());
+
1516  DrawHUDText(TXT_SHIELD, txt, speed_rect, align);
+
1517  }
+
1518  else if (ship->GetDecoy()) {
+
1519  speed_rect.y = cy-5+40;
+
1520  sprintf_s(txt, "%s %d", Game::GetText("HUDView.DECOY").data(), ship->GetDecoy()->Ammo());
+
1521  DrawHUDText(TXT_DECOY, txt, speed_rect, align);
+
1522  }
+
1523 
+
1524 
+
1525  Rect eta_rect = speed_rect;
+
1526  eta_rect.y += 10;
+
1527 
+
1528  align = DT_RIGHT;
+
1529 
+
1530  if (tactical) {
+
1531  eta_rect.x = 8;
+
1532  align = DT_LEFT;
+
1533  }
+
1534 
+
1535  for (int i = 0; i < 2; i++) {
+
1536  int eta = ship->GetMissileEta(i);
+
1537  if (eta > 0) {
+
1538  int minutes = (eta/60) % 60;
+
1539  int seconds = (eta ) % 60;
+
1540 
+
1541  char eta_buf[16];
+
1542  sprintf_s(eta_buf, "T %d:%02d", minutes, seconds);
+
1543  DrawHUDText(TXT_MISSILE_T1+i, eta_buf, eta_rect, align);
+
1544  eta_rect.y += 10;
+
1545  }
+
1546  }
+
1547  }
+
1548 
+
1549  NetGame* netgame = NetGame::GetInstance();
+
1550  if (netgame && !netgame->IsActive()) {
+
1551  Rect shoot_rect(l, b+5, box_width, 12);
+
1552  DrawHUDText(TXT_SHOOT, Game::GetText("HUDView.NET-GAME-OVER"), shoot_rect, DT_CENTER, HUD_MIXED_CASE, true);
+
1553  }
+
1554 
+
1555  else if (ship->IsNetObserver()) {
+
1556  Rect shoot_rect(l, b+5, box_width, 12);
+
1557  DrawHUDText(TXT_SHOOT, Game::GetText("HUDView.OBSERVER"), shoot_rect, DT_CENTER, HUD_MIXED_CASE, true);
+
1558  }
+
1559 
+
1560  DrawTarget();
+
1561  }
+
1562 
+
1563  else if (mode == HUD_MODE_ILS) {
+
1564  DrawTarget();
+
1565  }
+
1566 
+
1567  DrawNavInfo();
+
1568  }
+
1569 }
+
1570 
+
1571 // +--------------------------------------------------------------------+
+
1572 
+
1573 void
+ +
1575 {
+
1576  fpm_sprite->Hide();
+
1577 
+
1578  if (ship->Velocity().length() > 50) {
+
1579  double xtarg = xcenter;
+
1580  double ytarg = ycenter;
+
1581 
+
1582  Point svel = ship->Velocity();
+
1583  svel.Normalize();
+
1584 
+
1585  Point tloc = ship->Location() + svel * 1e8;
+
1586  // Translate into camera relative:
+
1587  projector->Transform(tloc);
+
1588 
+
1589  int behind = tloc.z < 0;
+
1590 
+
1591  if (behind)
+
1592  return;
+
1593 
+
1594  // Project into screen coordinates:
+
1595  projector->Project(tloc);
+
1596 
+
1597  xtarg = tloc.x;
+
1598  ytarg = tloc.y;
+
1599 
+
1600  fpm_sprite->Show();
+
1601  fpm_sprite->MoveTo(Point(xtarg, ytarg, 1));
+
1602  }
+
1603 }
+
1604 
+
1605 // +--------------------------------------------------------------------+
+
1606 
+
1607 void
+ +
1609 {
+
1610  for (int i = 0; i < 31; i++)
+
1611  pitch_ladder[i]->Hide();
+
1612 
+
1613  if (ship->IsAirborne() && Game::MaxTexSize() > 128) {
+
1614  double xtarg = xcenter;
+
1615  double ytarg = ycenter;
+
1616 
+
1617  Point uvec = Point(0,1,0);
+
1618  Point svel = ship->Velocity();
+
1619 
+
1620  if (svel.length() == 0)
+
1621  svel = ship->Heading();
+
1622 
+
1623  if (svel.x == 0 && svel.z == 0)
+
1624  return;
+
1625 
+
1626  svel.y = 0;
+
1627  svel.Normalize();
+
1628 
+
1629  Point gloc = ship->Location();
+
1630  gloc.y = 0;
+
1631 
+
1632  const double baseline = 1e9;
+
1633  const double clip_angle = 20*DEGREES;
+
1634 
+
1635  Point tloc = gloc + svel * baseline;
+
1636 
+
1637  // Translate into camera relative:
+
1638  projector->Transform(tloc);
+
1639 
+
1640  // Project into screen coordinates:
+
1641  projector->Project(tloc);
+
1642 
+
1643  xtarg = tloc.x;
+
1644  ytarg = tloc.y;
+
1645 
+
1646  // compute roll angle:
+
1647  double roll_angle = 0;
+
1648  double pitch_angle = 0;
+
1649 
+
1650  Point heading = ship->Heading();
+
1651  heading.Normalize();
+
1652 
+
1653  if (heading.x != 0 || heading.z != 0) {
+
1654  Point gheading = heading;
+
1655  gheading.y = 0;
+
1656  gheading.Normalize();
+
1657 
+
1658  double dot = gheading * heading;
+
1659 
+
1660  if (heading.y < 0) dot = -dot;
+
1661 
+
1662  pitch_angle = acos(dot);
+
1663 
+
1664  if (pitch_angle > PI/2)
+
1665  pitch_angle -= PI;
+
1666 
+
1667  double s0 = sin(pitch_angle);
+
1668  double c0 = cos(pitch_angle);
+
1669  double s1 = sin(pitch_angle + 10*DEGREES);
+
1670  double c1 = cos(pitch_angle + 10*DEGREES);
+
1671 
+
1672  tloc = gloc + (svel * baseline * c0) + (uvec * baseline * s0);
+
1673  projector->Transform(tloc);
+
1674 
+
1675  double x0 = tloc.x;
+
1676  double y0 = tloc.y;
+
1677 
+
1678  tloc = gloc + (svel * baseline * c1) + (uvec * baseline * s1);
+
1679  projector->Transform(tloc);
+
1680 
+
1681  double x1 = tloc.x;
+
1682  double y1 = tloc.y;
+
1683 
+
1684  double dx = x1-x0;
+
1685  double dy = y1-y0;
+
1686 
+
1687  roll_angle = atan2(-dy,dx) + PI/2;
+
1688  }
+
1689 
+
1690  const double alias_limit = 0.1*DEGREES;
+
1691 
+
1692  if (fabs(roll_angle) <= alias_limit) {
+
1693  if (roll_angle > 0)
+
1694  roll_angle = alias_limit;
+
1695  else
+
1696  roll_angle = -alias_limit;
+
1697  }
+
1698 
+
1699  else if (fabs(roll_angle-PI) <= alias_limit) {
+
1700  roll_angle = PI - alias_limit;
+
1701  }
+
1702 
+
1703  if (fabs(pitch_angle) <= clip_angle) {
+
1704  pitch_ladder[15]->Show();
+
1705  pitch_ladder[15]->MoveTo(Point(xtarg, ytarg, 1));
+
1706  pitch_ladder[15]->SetAngle(roll_angle);
+
1707  }
+
1708 
+
1709  for (int i = 1; i <= 15; i++) {
+
1710  double angle = i * 5 * DEGREES;
+
1711 
+
1712  if (i > 12)
+
1713  angle = (60 + (i-12)*10) * DEGREES;
+
1714 
+
1715  double s = sin(angle);
+
1716  double c = cos(angle);
+
1717 
+
1718  if (fabs(pitch_angle - angle) <= clip_angle) {
+
1719  // positive angle:
+
1720  tloc = gloc + (svel * baseline * c) + (uvec * baseline * s);
+
1721  projector->Transform(tloc);
+
1722 
+
1723  if (tloc.z > 0) {
+
1724  projector->Project(tloc);
+
1725  pitch_ladder[15-i]->Show();
+
1726  pitch_ladder[15-i]->MoveTo(Point(tloc.x, tloc.y, 1));
+
1727  pitch_ladder[15-i]->SetAngle(roll_angle);
+
1728  }
+
1729  }
+
1730 
+
1731  if (fabs(pitch_angle + angle) <= clip_angle) {
+
1732  // negative angle:
+
1733  tloc = gloc + (svel * baseline * c) + (uvec * -baseline * s);
+
1734  projector->Transform(tloc);
+
1735 
+
1736  if (tloc.z > 0) {
+
1737  projector->Project(tloc);
+
1738  pitch_ladder[15+i]->Show();
+
1739  pitch_ladder[15+i]->MoveTo(Point(tloc.x, tloc.y, 1));
+
1740  pitch_ladder[15+i]->SetAngle(roll_angle);
+
1741  }
+
1742  }
+
1743  }
+
1744  }
+
1745 }
+
1746 
+
1747 // +--------------------------------------------------------------------+
+
1748 
+
1749 void
+ +
1751 {
+
1752  hpm_sprite->Hide();
+
1753 
+
1754  if (!ship)
+
1755  return;
+
1756 
+
1757  double xtarg = xcenter;
+
1758  double ytarg = ycenter;
+
1759 
+
1760  double az = ship->GetHelmHeading() - PI;
+
1761  double el = ship->GetHelmPitch();
+
1762 
+
1763  Point hvec = Point(sin(az), sin(el), cos(az));
+
1764  hvec.Normalize();
+
1765 
+
1766  Point tloc = ship->Location() + hvec * 1e8;
+
1767  // Translate into camera relative:
+
1768  projector->Transform(tloc);
+
1769 
+
1770  int behind = tloc.z < 0;
+
1771 
+
1772  if (behind)
+
1773  return;
+
1774 
+
1775  // Project into screen coordinates:
+
1776  projector->Project(tloc);
+
1777 
+
1778  xtarg = tloc.x;
+
1779  ytarg = tloc.y;
+
1780 
+
1781  hpm_sprite->Show();
+
1782  hpm_sprite->MoveTo(Point(xtarg, ytarg, 1));
+
1783 }
+
1784 
+
1785 // +--------------------------------------------------------------------+
+
1786 
+
1787 void
+ +
1789 {
+
1790  az_ring->Hide();
+
1791  az_pointer->Hide();
+
1792  el_ring->Hide();
+
1793  el_pointer->Hide();
+
1794 
+
1795  Scene* scene = az_ring->GetScene();
+
1796  if (scene) {
+
1797  scene->DelGraphic(az_ring);
+
1798  scene->DelGraphic(az_pointer);
+
1799  scene->DelGraphic(el_ring);
+
1800  scene->DelGraphic(el_pointer);
+
1801  }
+
1802 }
+
1803 
+
1804 // +--------------------------------------------------------------------+
+
1805 
+
1806 void
+ +
1808 {
+
1809  if (!ship || !ship->Rep())
+
1810  return;
+
1811 
+
1812  Solid* solid = (Solid*) ship->Rep();
+
1813  Point loc = solid->Location();
+
1814 
+
1815  az_ring->MoveTo(loc);
+
1816  az_pointer->MoveTo(loc);
+
1817  el_ring->MoveTo(loc);
+
1818  el_pointer->MoveTo(loc);
+
1819 
+
1820  double helm_heading = ship->GetHelmHeading();
+
1821  double helm_pitch = ship->GetHelmPitch();
+
1822  double curr_heading = ship->CompassHeading();
+
1823  double curr_pitch = ship->CompassPitch();
+
1824 
+
1825  bool show_az = fabs(helm_heading - curr_heading) > 5*DEGREES;
+
1826  bool show_el = fabs(helm_pitch - curr_pitch) > 5*DEGREES;
+
1827 
+
1828  Scene* scene = camview->GetScene();
+
1829 
+
1830  if (show_az || show_el) {
+
1831  scene->AddGraphic(az_ring);
+
1832  az_ring->Show();
+
1833 
+
1834  if (show_el || fabs(helm_pitch) > 5 * DEGREES) {
+
1835  scene->AddGraphic(el_ring);
+
1836  Matrix ring_orient;
+
1837  ring_orient.Yaw(helm_heading + PI);
+
1838  el_ring->SetOrientation(ring_orient);
+
1839  el_ring->Show();
+
1840 
+
1841  scene->AddGraphic(el_pointer);
+
1842  Matrix pointer_orient;
+
1843  pointer_orient.Yaw(helm_heading + PI);
+
1844  pointer_orient.Pitch(-helm_pitch);
+
1845  pointer_orient.Roll(PI/2);
+
1846  el_pointer->SetOrientation(pointer_orient);
+
1847  el_pointer->Show();
+
1848  }
+
1849  else {
+
1850  scene->AddGraphic(az_pointer);
+
1851  Matrix pointer_orient;
+
1852  pointer_orient.Yaw(helm_heading + PI);
+
1853 
+
1854  az_pointer->SetOrientation(pointer_orient);
+
1855  az_pointer->Show();
+
1856  }
+
1857  }
+
1858 }
+
1859 
+
1860 // +--------------------------------------------------------------------+
+
1861 
+
1862 void
+
1863 HUDView::DrawLCOS(SimObject* targ, double dist)
+
1864 {
+
1865  lead_sprite->Hide();
+
1866  aim_sprite->Hide();
+
1867  chase_sprite->Hide();
+
1868 
+
1869  double xtarg = xcenter;
+
1870  double ytarg = ycenter;
+
1871 
+
1872  Weapon* prim = ship->GetPrimary();
+
1873  if (!prim) return;
+
1874 
+
1875  Point tloc = targ->Location();
+
1876  // Translate into camera relative:
+
1877  projector->Transform(tloc);
+
1878 
+
1879  int behind = tloc.z < 0;
+
1880 
+
1881  if (behind)
+
1882  tloc.z = -tloc.z;
+
1883 
+
1884  // Project into screen coordinates:
+
1885  projector->Project(tloc);
+
1886 
+
1887  // DRAW THE OFFSCREEN CHASE INDICATOR:
+
1888  if (behind ||
+
1889  tloc.x <= 0 || tloc.x >= width-1 ||
+
1890  tloc.y <= 0 || tloc.y >= height-1) {
+
1891 
+
1892  // Left side:
+
1893  if (tloc.x <= 0 || (behind && tloc.x < width/2)) {
+
1894  if (tloc.y < ah) tloc.y = ah;
+
1895  else if (tloc.y >= height-ah) tloc.y = height-1-ah;
+
1896 
+
1897  chase_sprite->Show();
+
1898  chase_sprite->SetAnimation(&chase_left);
+
1899  chase_sprite->MoveTo(Point(aw, tloc.y, 1));
+
1900  }
+
1901 
+
1902  // Right side:
+
1903  else if (tloc.x >= width-1 || behind) {
+
1904  if (tloc.y < ah) tloc.y = ah;
+
1905  else if (tloc.y >= height-ah) tloc.y = height-1-ah;
+
1906 
+
1907  chase_sprite->Show();
+
1908  chase_sprite->SetAnimation(&chase_right);
+
1909  chase_sprite->MoveTo(Point(width-1-aw, tloc.y, 1));
+
1910  }
+
1911  else {
+
1912  if (tloc.x < aw) tloc.x = aw;
+
1913  else if (tloc.x >= width-aw) tloc.x = width-1-aw;
+
1914 
+
1915  // Top edge:
+
1916  if (tloc.y <= 0) {
+
1917  chase_sprite->Show();
+
1918  chase_sprite->SetAnimation(&chase_top);
+
1919  chase_sprite->MoveTo(Point(tloc.x, ah, 1));
+
1920  }
+
1921 
+
1922  // Bottom edge:
+
1923  else if (tloc.y >= height-1) {
+
1924  chase_sprite->Show();
+
1925  chase_sprite->SetAnimation(&chase_bottom);
+
1926  chase_sprite->MoveTo(Point(tloc.x, height-1-ah, 1));
+
1927  }
+
1928  }
+
1929  }
+
1930 
+
1931  // DRAW THE LCOS:
+
1932  else {
+
1933  if (!ship->IsStarship()) {
+
1934  Point aim_vec = ship->Heading();
+
1935  aim_vec.Normalize();
+
1936 
+
1937  // shot speed is relative to ship speed:
+
1938  Point shot_vel = ship->Velocity() + aim_vec * prim->Design()->speed;
+
1939  double shot_speed = shot_vel.length();
+
1940 
+
1941  // time for shot to reach target
+
1942  double time = dist / shot_speed;
+
1943 
+
1944  // LCOS (Lead Computing Optical Sight)
+
1945  if (gunsight == 0) {
+
1946  // where the shot will be when it is the same distance
+
1947  // away from the ship as the target:
+
1948  Point impact = ship->Location() + (shot_vel * time);
+
1949 
+
1950  // where the target will be when the shot reaches it:
+
1951  Point targ_vel = targ->Velocity();
+
1952  Point dest = targ->Location() + (targ_vel * time);
+
1953  Point delta = impact - dest;
+
1954 
+
1955  // draw the gun sight here in 3d world coordinates:
+
1956  Point sight = targ->Location() + delta;
+
1957 
+
1958  // Project into screen coordinates:
+
1959  projector->Transform(sight);
+
1960  projector->Project(sight);
+
1961 
+
1962  xtarg = sight.x;
+
1963  ytarg = sight.y;
+
1964 
+
1965  aim_sprite->Show();
+
1966  aim_sprite->MoveTo(Point(xtarg, ytarg, 1));
+
1967  }
+
1968 
+
1969  // Wing Commander style lead indicator
+
1970  else {
+
1971  // where the target will be when the shot reaches it:
+
1972  Point targ_vel = targ->Velocity() - ship->Velocity();
+
1973  Point dest = targ->Location() + (targ_vel * time);
+
1974 
+
1975  // Translate into camera relative:
+
1976  projector->Transform(dest);
+
1977  projector->Project(dest);
+
1978 
+
1979  xtarg = dest.x;
+
1980  ytarg = dest.y;
+
1981 
+
1982  lead_sprite->Show();
+
1983  lead_sprite->MoveTo(Point(xtarg, ytarg, 1));
+
1984  }
+
1985  }
+
1986  }
+
1987 }
+
1988 
+
1989 // +--------------------------------------------------------------------+
+
1990 
+
1991 void
+ +
1993 {
+
1994  const int bar_width = 256;
+
1995  const int bar_height = 192;
+
1996  const int box_width = 120;
+
1997 
+
1998  SimObject* old_target = target;
+
1999 
+
2000  if (mode == HUD_MODE_ILS) {
+
2001  Ship* controller = ship->GetController();
+
2002  if (controller && !target)
+
2003  target = controller;
+
2004  }
+
2005 
+
2006  if (target && target->Rep()) {
+
2007  Sensor* sensor = ship->GetSensor();
+
2008  Contact* contact = 0;
+
2009 
+
2010  if (sensor && target->Type() == SimObject::SIM_SHIP) {
+
2011  contact = sensor->FindContact((Ship*) target);
+
2012  }
+
2013 
+
2014  int cx = width/2;
+
2015  int cy = height/2;
+
2016  int l = cx - bar_width/2;
+
2017  int r = cx + bar_width/2;
+
2018  int t = cy - bar_height/2;
+
2019  int b = cy + bar_height/2;
+
2020  Point delta = target->Location() - ship->Location();
+
2021  double distance = delta.length();
+
2022  Point delta_v = ship->Velocity() - target->Velocity();
+
2023  double speed = delta_v.length();
+
2024  char txt[256];
+
2025 
+
2026  if (mode == HUD_MODE_ILS && ship->GetInbound() && ship->GetInbound()->GetDeck()) {
+
2027  delta = ship->GetInbound()->GetDeck()->EndPoint() - ship->Location();
+
2028  distance = delta.length();
+
2029  }
+
2030 
+
2031  if (delta * ship->Velocity() > 0) { // in front
+
2032  if (delta_v * ship->Velocity() < 0) // losing ground
+
2033  speed = -speed;
+
2034  }
+
2035  else { // behind
+
2036  if (delta_v * ship->Velocity() > 0) // passing
+
2037  speed = -speed;
+
2038  }
+
2039 
+
2040  Rect range_rect(r-20, cy-5, box_width, 12);
+
2041 
+
2042  if (tactical)
+
2043  range_rect.x = width - range_rect.w - 8;
+
2044 
+
2045  if (contact) {
+
2046  Sensor* sensor = ship->GetSensor();
+
2047  double limit = 75e3;
+
2048 
+
2049  if (sensor)
+
2050  limit = sensor->GetBeamRange();
+
2051 
+
2052  distance = contact->Range(ship, limit);
+
2053 
+
2054  if (!contact->ActLock() && !contact->PasLock()) {
+
2055  strcpy_s(txt, Game::GetText("HUDView.No-Range").data());
+
2056  speed = 0;
+
2057  }
+
2058  else {
+
2059  FormatNumber(txt, distance);
+
2060  }
+
2061  }
+
2062 
+
2063  else {
+
2064  FormatNumber(txt, distance);
+
2065  }
+
2066 
+
2067  DrawHUDText(TXT_RANGE, txt, range_rect, DT_RIGHT);
+
2068 
+
2069  if (arcade) {
+
2070  target = old_target;
+
2071  return;
+
2072  }
+
2073 
+
2074  range_rect.y += 18;
+
2075  FormatNumber(txt, speed);
+
2076  DrawHUDText(TXT_CLOSING_SPEED, txt, range_rect, DT_RIGHT);
+
2077 
+
2078  // target info:
+
2079  if (!tactical) {
+
2080  range_rect.y = cy-76;
+
2081  }
+
2082 
+
2083  else {
+
2084  range_rect.x = width - 2*box_width - 8;
+
2085  range_rect.y = cy-76;
+
2086  range_rect.w = 2*box_width;
+
2087  }
+
2088 
+
2089  DrawHUDText(TXT_TARGET_NAME, target->Name(), range_rect, DT_RIGHT);
+
2090 
+
2091  if (target->Type() == SimObject::SIM_SHIP) {
+
2092  Ship* tgt_ship = (Ship*) target;
+
2093 
+
2094  range_rect.y += 10;
+
2095  DrawHUDText(TXT_TARGET_DESIGN, tgt_ship->Design()->display_name, range_rect, DT_RIGHT);
+
2096 
+
2097  if (mode != HUD_MODE_ILS) {
+
2098  if (tgt_ship->IsStarship()) {
+
2099  range_rect.y += 10;
+
2100  sprintf_s(txt, "%s %03d", Game::GetText("HUDView.symbol.shield").data(), (int) tgt_ship->ShieldStrength());
+
2101  DrawHUDText(TXT_TARGET_SHIELD, txt, range_rect, DT_RIGHT);
+
2102  }
+
2103 
+
2104  range_rect.y += 10;
+
2105  sprintf_s(txt, "%s %03d", Game::GetText("HUDView.symbol.hull").data(), (int) (tgt_ship->Integrity() / tgt_ship->Design()->integrity * 100));
+
2106  DrawHUDText(TXT_TARGET_HULL, txt, range_rect, DT_RIGHT);
+
2107 
+
2108  System* sys = ship->GetSubTarget();
+
2109  if (sys) {
+
2110  Color stat = hud_color;
+
2111  static DWORD blink = Game::RealTime();
+
2112 
+
2113  int blink_delta = Game::RealTime() - blink;
+
2114  sprintf_s(txt, "%s %03d", sys->Abbreviation(), (int) sys->Availability());
+
2115 
+
2116  switch (sys->Status()) {
+
2117  case System::DEGRADED: stat = Color(255,255, 0); break;
+
2118  case System::CRITICAL:
+
2119  case System::DESTROYED: stat = Color(255, 0, 0); break;
+
2120  case System::MAINT:
+
2121  if (blink_delta < 250)
+
2122  stat = Color(8,8,8);
+
2123  break;
+
2124  }
+
2125 
+
2126  if (blink_delta > 500)
+
2127  blink = Game::RealTime();
+
2128 
+
2129  range_rect.y += 10;
+
2130  DrawHUDText(TXT_TARGET_SUB, txt, range_rect, DT_RIGHT);
+
2131  }
+
2132  }
+
2133  }
+
2134 
+
2135  else if (target->Type() == SimObject::SIM_DRONE) {
+
2136  Drone* tgt_drone = (Drone*) target;
+
2137 
+
2138  range_rect.y += 10;
+
2139  DrawHUDText(TXT_TARGET_DESIGN, tgt_drone->DesignName(), range_rect, DT_RIGHT);
+
2140 
+
2141  range_rect.y += 10;
+
2142  int eta = tgt_drone->GetEta();
+
2143 
+
2144  if (eta > 0) {
+
2145  int minutes = (eta/60) % 60;
+
2146  int seconds = (eta ) % 60;
+
2147 
+
2148  char eta_buf[16];
+
2149  sprintf_s(eta_buf, "T %d:%02d", minutes, seconds);
+
2150  DrawHUDText(TXT_TARGET_ETA, eta_buf, range_rect, DT_RIGHT);
+
2151  }
+
2152  }
+
2153  }
+
2154 
+
2155  target = old_target;
+
2156 }
+
2157 
+
2158 // +--------------------------------------------------------------------+
+
2159 
+
2160 void
+ +
2162 {
+
2163  const int bar_width = 256;
+
2164  const int bar_height = 192;
+
2165  const int box_width = 120;
+
2166 
+
2167  if (arcade) {
+
2168  if (ship->IsAutoNavEngaged()) {
+
2169  Rect info_rect(width/2-box_width, height/2+bar_height, box_width*2, 12);
+
2170 
+
2171  if (big_font)
+
2172  hud_text[TXT_NAV_INDEX].font = big_font;
+
2173 
+
2174  DrawHUDText(TXT_NAV_INDEX, Game::GetText("HUDView.Auto-Nav"), info_rect, DT_CENTER);
+
2175  }
+
2176 
+
2177  return;
+
2178  }
+
2179 
+
2180  hud_text[TXT_NAV_INDEX].font = hud_font;
+
2181 
+
2182  Instruction* navpt = ship->GetNextNavPoint();
+
2183 
+
2184  if (navpt) {
+
2185  int cx = width/2;
+
2186  int cy = height/2;
+
2187  int l = cx - bar_width/2;
+
2188  int r = cx + bar_width/2;
+
2189  int t = cy - bar_height/2;
+
2190  int b = cy + bar_height/2;
+
2191 
+
2192  int index = ship->GetNavIndex(navpt);
+
2193  double distance = ship->RangeToNavPoint(navpt);
+
2194  double speed = ship->Velocity().length();
+
2195  int etr = 0;
+
2196  char txt[256];
+
2197 
+
2198  if (speed > 10)
+
2199  etr = (int) (distance/speed);
+
2200 
+
2201  Rect info_rect(r-20, cy+32, box_width, 12);
+
2202 
+
2203  if (tactical)
+
2204  info_rect.x = width - info_rect.w - 8;
+
2205 
+
2206  if (ship->IsAutoNavEngaged())
+
2207  sprintf_s(txt, "%s %d", Game::GetText("HUDView.Auto-Nav").data(), index);
+
2208  else
+
2209  sprintf_s(txt, "%s %d", Game::GetText("HUDView.Nav").data(), index);
+
2210  DrawHUDText(TXT_NAV_INDEX, txt, info_rect, DT_RIGHT);
+
2211 
+
2212  info_rect.y += 10;
+
2213  if (navpt->Action())
+
2214  DrawHUDText(TXT_NAV_ACTION, Instruction::ActionName(navpt->Action()), info_rect, DT_RIGHT);
+
2215 
+
2216  info_rect.y += 10;
+
2217  FormatNumber(txt, navpt->Speed());
+
2218  DrawHUDText(TXT_NAV_SPEED, txt, info_rect, DT_RIGHT);
+
2219 
+
2220  if (etr > 3600) {
+
2221  info_rect.y += 10;
+
2222  sprintf_s(txt, "%s XX:XX", Game::GetText("HUDView.time-enroute").data());
+
2223  DrawHUDText(TXT_NAV_ETR, txt, info_rect, DT_RIGHT);
+
2224  }
+
2225  else if (etr > 0) {
+
2226  info_rect.y += 10;
+
2227 
+
2228  int minutes = (etr/60) % 60;
+
2229  int seconds = (etr ) % 60;
+
2230  sprintf_s(txt, "%s %2d:%02d", Game::GetText("HUDView.time-enroute").data(), minutes, seconds);
+
2231  DrawHUDText(TXT_NAV_ETR, txt, info_rect, DT_RIGHT);
+
2232  }
+
2233 
+
2234  if (navpt->HoldTime() > 0) {
+
2235  info_rect.y += 10;
+
2236 
+
2237  int hold = (int) navpt->HoldTime();
+
2238  int minutes = (hold/60) % 60;
+
2239  int seconds = (hold ) % 60;
+
2240  sprintf_s(txt, "%s %2d:%02d", Game::GetText("HUDView.HOLD").data(), minutes, seconds);
+
2241  DrawHUDText(TXT_NAV_HOLD, txt, info_rect, DT_RIGHT);
+
2242  }
+
2243  }
+
2244 }
+
2245 
+
2246 // +--------------------------------------------------------------------+
+
2247 
+
2248 void
+ +
2250 {
+
2251  if (target && target->Rep()) {
+
2252  Point delta = target->Location() - ship->Location();
+
2253  double distance = delta.length();
+
2254 
+
2255  // draw LCOS on target:
+
2256  if (!tactical)
+
2257  DrawLCOS(target, distance);
+
2258  }
+
2259 }
+
2260 
+
2261 // +--------------------------------------------------------------------+
+
2262 
+
2263 void
+ +
2265 {
+
2266  double xtarg = xcenter;
+
2267  double ytarg = ycenter;
+
2268  SimObject* t1 = 0;
+
2269  SimObject* t2 = 0;
+
2270  SimObject* t3 = 0;
+
2271  Sprite* sprite = 0;
+
2272 
+
2273  tgt1_sprite->Hide();
+
2274  tgt2_sprite->Hide();
+
2275  tgt3_sprite->Hide();
+
2276  tgt4_sprite->Hide();
+
2277 
+
2278  // fighters just show primary target:
+
2279  if (ship->IsDropship()) {
+
2280  SimObject* t = ship->GetTarget();
+
2281  System* s = ship->GetSubTarget();
+
2282 
+
2283  if (t) {
+
2284  Point tloc = t->Location();
+
2285  if (s) {
+
2286  tloc = s->MountLocation();
+
2287  }
+
2288  else if (t->Type() == SimObject::SIM_SHIP) {
+
2289  Ship* tgt_ship = (Ship*) t;
+
2290 
+
2291  if (tgt_ship->IsGroundUnit())
+
2292  tloc += Point(0,150,0);
+
2293  }
+
2294 
+
2295  projector->Transform(tloc);
+
2296 
+
2297  if (tloc.z > 0) {
+
2298  projector->Project(tloc);
+
2299 
+
2300  xtarg = tloc.x;
+
2301  ytarg = tloc.y;
+
2302 
+
2303  if (xtarg>0 && xtarg<width-1 && ytarg>0 && ytarg<height-1) {
+
2304  double range = Point(t->Location() - ship->Location()).length();
+
2305 
+
2306  // use out-of-range crosshair if out of range:
+
2307  if (!ship->GetPrimaryDesign() || ship->GetPrimaryDesign()->max_range < range) {
+
2308  tgt4_sprite->Show();
+
2309  tgt4_sprite->MoveTo(Point(xtarg, ytarg, 1));
+
2310  }
+
2311 
+
2312  // else, use in-range primary crosshair:
+
2313  else {
+
2314  tgt1_sprite->Show();
+
2315  tgt1_sprite->MoveTo(Point(xtarg, ytarg, 1));
+
2316  }
+
2317  }
+
2318  }
+
2319  }
+
2320  }
+
2321 
+
2322  // starships show up to three targets:
+
2323  else {
+ +
2325  while (!t3 && ++w) {
+
2326  SimObject* t = w->GetTarget();
+
2327  System* s = w->GetSubTarget();
+
2328 
+
2329  if (w->Contains(ship->GetPrimary())) {
+
2330  if (t == 0) t = ship->GetTarget();
+
2331  t1 = t;
+
2332  sprite = tgt1_sprite;
+
2333  }
+
2334 
+
2335  else if (t && w->Contains(ship->GetSecondary())) {
+
2336  t2 = t;
+
2337  sprite = tgt2_sprite;
+
2338 
+
2339  if (t2 == t1)
+
2340  continue; // don't overlap target designators
+
2341  }
+
2342 
+
2343  else if (t) {
+
2344  t3 = t;
+
2345  sprite = tgt3_sprite;
+
2346 
+
2347  if (t3 == t1 || t3 == t2)
+
2348  continue; // don't overlap target designators
+
2349  }
+
2350 
+
2351  if (t) {
+
2352  Point tloc = t->Location();
+
2353 
+
2354  if (s)
+
2355  tloc = s->MountLocation();
+
2356 
+
2357  projector->Transform(tloc);
+
2358 
+
2359  if (tloc.z > 0) {
+
2360  projector->Project(tloc);
+
2361 
+
2362  xtarg = tloc.x;
+
2363  ytarg = tloc.y;
+
2364 
+
2365  if (xtarg>0 && xtarg<width-1 && ytarg>0 && ytarg<height-1) {
+
2366  double range = Point(t->Location() - ship->Location()).length();
+
2367 
+
2368  // flip to out-of-range crosshair
+
2369  if (sprite == tgt1_sprite) {
+
2370  if (!ship->GetPrimaryDesign() || ship->GetPrimaryDesign()->max_range < range) {
+
2371  sprite = tgt4_sprite;
+
2372  }
+
2373  }
+
2374 
+
2375  sprite->Show();
+
2376  sprite->MoveTo(Point(xtarg, ytarg, 1));
+
2377  }
+
2378  }
+
2379  }
+
2380  }
+
2381  }
+
2382 }
+
2383 
+
2384 // +--------------------------------------------------------------------+
+
2385 
+
2386 Color
+ +
2388 {
+
2389  Color sc;
+
2390 
+
2391  switch (status) {
+
2392  default:
+
2393  case System::NOMINAL: sc = Color( 32,192, 32); break;
+
2394  case System::DEGRADED: sc = Color(255,255, 0); break;
+
2395  case System::CRITICAL: sc = Color(255, 0, 0); break;
+
2396  case System::DESTROYED: sc = Color( 0, 0, 0); break;
+
2397  }
+
2398 
+
2399  return sc;
+
2400 }
+
2401 
+
2402 void
+ +
2404 {
+
2405  switch (status) {
+
2406  default:
+
2407  case System::NOMINAL: status_color = txt_color; break;
+
2408  case System::DEGRADED: status_color = Color(255,255, 0); break;
+
2409  case System::CRITICAL: status_color = Color(255, 0, 0); break;
+
2410  case System::DESTROYED: status_color = Color( 0, 0, 0); break;
+
2411  }
+
2412 }
+
2413 
+
2414 // +--------------------------------------------------------------------+
+
2415 
+
2416 static int GetReactorStatus(Ship* ship)
+
2417 {
+
2418  if (!ship || ship->Reactors().size() < 1)
+
2419  return -1;
+
2420 
+
2421  int status = System::NOMINAL;
+
2422  bool maint = false;
+
2423 
+
2424  ListIter<PowerSource> iter = ship->Reactors();
+
2425  while (++iter) {
+
2426  PowerSource* s = iter.value();
+
2427 
+
2428  if (s->Status() < status)
+
2429  status = s->Status();
+
2430  }
+
2431 
+
2432  if (maint && status == System::NOMINAL)
+
2433  status = System::MAINT;
+
2434 
+
2435  return status;
+
2436 }
+
2437 
+
2438 static int GetDriveStatus(Ship* ship)
+
2439 {
+
2440  if (!ship || ship->Drives().size() < 1)
+
2441  return -1;
+
2442 
+
2443  int status = System::NOMINAL;
+
2444  bool maint = false;
+
2445 
+
2446  ListIter<Drive> iter = ship->Drives();
+
2447  while (++iter) {
+
2448  Drive* s = iter.value();
+
2449 
+
2450  if (s->Status() < status)
+
2451  status = s->Status();
+
2452 
+
2453  else if (s->Status() == System::MAINT)
+
2454  maint = true;
+
2455  }
+
2456 
+
2457  if (maint && status == System::NOMINAL)
+
2458  status = System::MAINT;
+
2459 
+
2460  return status;
+
2461 }
+
2462 
+
2463 static int GetQuantumStatus(Ship* ship)
+
2464 {
+
2465  if (!ship || ship->GetQuantumDrive() == 0)
+
2466  return -1;
+
2467 
+
2468  QuantumDrive* s = ship->GetQuantumDrive();
+
2469  return s->Status();
+
2470 }
+
2471 
+
2472 static int GetThrusterStatus(Ship* ship)
+
2473 {
+
2474  if (!ship || ship->GetThruster() == 0)
+
2475  return -1;
+
2476 
+
2477  Thruster* s = ship->GetThruster();
+
2478  return s->Status();
+
2479 }
+
2480 
+
2481 static int GetShieldStatus(Ship* ship)
+
2482 {
+
2483  if (!ship)
+
2484  return -1;
+
2485 
+
2486  Shield* s = ship->GetShield();
+
2487  Weapon* d = ship->GetDecoy();
+
2488 
+
2489  if (!s && !d)
+
2490  return -1;
+
2491 
+
2492  int status = System::NOMINAL;
+
2493  bool maint = false;
+
2494 
+
2495  if (s) {
+
2496  if (s->Status() < status)
+
2497  status = s->Status();
+
2498 
+
2499  else if (s->Status() == System::MAINT)
+
2500  maint = true;
+
2501  }
+
2502 
+
2503  if (d) {
+
2504  if (d->Status() < status)
+
2505  status = d->Status();
+
2506 
+
2507  else if (d->Status() == System::MAINT)
+
2508  maint = true;
+
2509  }
+
2510 
+
2511  if (maint && status == System::NOMINAL)
+
2512  status = System::MAINT;
+
2513 
+
2514  return status;
+
2515 }
+
2516 
+
2517 static int GetWeaponStatus(Ship* ship, int index)
+
2518 {
+
2519  if (!ship || ship->Weapons().size() <= index)
+
2520  return -1;
+
2521 
+
2522  WeaponGroup* group = ship->Weapons().at(index);
+
2523 
+
2524  int status = System::NOMINAL;
+
2525  bool maint = false;
+
2526 
+
2527  ListIter<Weapon> iter = group->GetWeapons();
+
2528  while (++iter) {
+
2529  Weapon* s = iter.value();
+
2530 
+
2531  if (s->Status() < status)
+
2532  status = s->Status();
+
2533 
+
2534  else if (s->Status() == System::MAINT)
+
2535  maint = true;
+
2536  }
+
2537 
+
2538  if (maint && status == System::NOMINAL)
+
2539  status = System::MAINT;
+
2540 
+
2541  return status;
+
2542 }
+
2543 
+
2544 static int GetSensorStatus(Ship* ship)
+
2545 {
+
2546  if (!ship || ship->GetSensor() == 0)
+
2547  return -1;
+
2548 
+
2549  Sensor* s = ship->GetSensor();
+
2550  Weapon* p = ship->GetProbeLauncher();
+
2551 
+
2552  int status = s->Status();
+
2553  bool maint = s->Status() == System::MAINT;
+
2554 
+
2555  if (p) {
+
2556  if (p->Status() < status)
+
2557  status = p->Status();
+
2558 
+
2559  else if (p->Status() == System::MAINT)
+
2560  maint = true;
+
2561  }
+
2562 
+
2563  if (maint && status == System::NOMINAL)
+
2564  status = System::MAINT;
+
2565 
+
2566  return status;
+
2567 }
+
2568 
+
2569 static int GetComputerStatus(Ship* ship)
+
2570 {
+
2571  if (!ship || ship->Computers().size() < 1)
+
2572  return -1;
+
2573 
+
2574  int status = System::NOMINAL;
+
2575  bool maint = false;
+
2576 
+
2577  ListIter<Computer> iter = ship->Computers();
+
2578  while (++iter) {
+
2579  Computer* s = iter.value();
+
2580 
+
2581  if (s->Status() < status)
+
2582  status = s->Status();
+
2583 
+
2584  else if (s->Status() == System::MAINT)
+
2585  maint = true;
+
2586  }
+
2587 
+
2588  if (ship->GetNavSystem()) {
+
2589  NavSystem* s = ship->GetNavSystem();
+
2590 
+
2591  if (s->Status() < status)
+
2592  status = s->Status();
+
2593 
+
2594  else if (s->Status() == System::MAINT)
+
2595  maint = true;
+
2596  }
+
2597 
+
2598  if (maint && status == System::NOMINAL)
+
2599  status = System::MAINT;
+
2600 
+
2601  return status;
+
2602 }
+
2603 
+
2604 static int GetFlightDeckStatus(Ship* ship)
+
2605 {
+
2606  if (!ship || ship->FlightDecks().size() < 1)
+
2607  return -1;
+
2608 
+
2609  int status = System::NOMINAL;
+
2610  bool maint = false;
+
2611 
+
2612  ListIter<FlightDeck> iter = ship->FlightDecks();
+
2613  while (++iter) {
+
2614  FlightDeck* s = iter.value();
+
2615 
+
2616  if (s->Status() < status)
+
2617  status = s->Status();
+
2618 
+
2619  else if (s->Status() == System::MAINT)
+
2620  maint = true;
+
2621  }
+
2622 
+
2623  if (maint && status == System::NOMINAL)
+
2624  status = System::MAINT;
+
2625 
+
2626  return status;
+
2627 }
+
2628 
+
2629 void
+ +
2631 {
+
2632  int box_width = 75;
+
2633  int box_height = 17;
+
2634  int row_height = 28;
+
2635  int box_left = width/2 - box_width*2;
+
2636 
+
2637  if (cockpit_hud_texture) {
+
2638  box_left = 275;
+
2639  box_height = 18;
+
2640  row_height = 18;
+
2641  }
+
2642 
+
2643  if (ship) {
+
2644  if (Game::MaxTexSize() > 128) {
+
2645  warn_left_sprite->Show();
+
2646  warn_right_sprite->Show();
+
2647  }
+
2648 
+
2649  int x = box_left;
+
2650  int y = cockpit_hud_texture ? 410 : height-97;
+
2651  int c = cockpit_hud_texture ? 3 : 4;
+
2652 
+
2653  static DWORD blink = Game::RealTime();
+
2654 
+
2655  for (int index = 0; index < 12; index++) {
+
2656  int stat = -1;
+
2657  Text abrv = Game::GetText("HUDView.UNKNOWN");
+
2658 
+
2659  switch (index) {
+
2660  case 0: stat = GetReactorStatus(ship); abrv = Game::GetText("HUDView.REACTOR"); break;
+
2661  case 1: stat = GetDriveStatus(ship); abrv = Game::GetText("HUDView.DRIVE"); break;
+
2662  case 2: stat = GetQuantumStatus(ship); abrv = Game::GetText("HUDView.QUANTUM"); break;
+
2663  case 3: stat = GetShieldStatus(ship); abrv = Game::GetText("HUDView.SHIELD");
+
2664  if (ship->GetShield() == 0 && ship->GetDecoy())
+
2665  abrv = Game::GetText("HUDView.DECOY");
+
2666  break;
+
2667 
+
2668  case 4:
+
2669  case 5:
+
2670  case 6:
+
2671  case 7: stat = GetWeaponStatus(ship, index-4);
+
2672  if (stat >= 0) {
+
2673  WeaponGroup* g = ship->Weapons().at(index-4);
+
2674  abrv = g->Name();
+
2675  }
+
2676  break;
+
2677 
+
2678  case 8: stat = GetSensorStatus(ship); abrv = Game::GetText("HUDView.SENSOR"); break;
+
2679  case 9: stat = GetComputerStatus(ship); abrv = Game::GetText("HUDView.COMPUTER"); break;
+
2680  case 10: stat = GetThrusterStatus(ship); abrv = Game::GetText("HUDView.THRUSTER"); break;
+
2681  case 11: stat = GetFlightDeckStatus(ship);abrv = Game::GetText("HUDView.FLTDECK"); break;
+
2682  }
+
2683 
+
2684  Rect warn_rect(x, y, box_width, box_height);
+
2685 
+
2686  if (cockpit_hud_texture)
+ +
2688 
+
2689  if (stat >= 0) {
+ +
2691  Color tc = status_color;
+
2692 
+
2693  if (stat != System::NOMINAL) {
+
2694  if (Game::RealTime() - blink < 250) {
+
2695  tc = cockpit_hud_texture ? txt_color : Color(8,8,8);
+
2696  }
+
2697  }
+
2698 
+
2699  if (cockpit_hud_texture) {
+
2700  if (tc != txt_color) {
+
2701  Rect r2 = warn_rect;
+
2702  r2.Inset(1,1,1,1);
+
2703  cockpit_hud_texture->FillRect(r2, tc);
+
2704  tc = Color::Black;
+
2705  }
+
2706 
+
2707  warn_rect.y += 4;
+
2708 
+
2709  hud_font->SetColor(tc);
+
2710  hud_font->DrawText(abrv, -1,
+
2711  warn_rect,
+
2712  DT_CENTER | DT_SINGLELINE,
+ +
2714 
+
2715  warn_rect.y -= 4;
+
2716  }
+
2717  else {
+
2718  DrawHUDText(TXT_CAUTION_TXT + index,
+
2719  abrv,
+
2720  warn_rect,
+
2721  DT_CENTER);
+
2722 
+
2723  hud_text[TXT_CAUTION_TXT + index].color = tc;
+
2724  }
+
2725  }
+
2726 
+
2727  x += box_width;
+
2728 
+
2729  if (--c <= 0) {
+
2730  c = cockpit_hud_texture ? 3 : 4;
+
2731  x = box_left;
+
2732  y += row_height;
+
2733  }
+
2734  }
+
2735 
+
2736  if (Game::RealTime() - blink > 500)
+
2737  blink = Game::RealTime();
+
2738 
+
2739  // reset for next time
+ +
2741  }
+
2742 }
+
2743 
+
2744 // +--------------------------------------------------------------------+
+
2745 
+
2746 void
+ +
2748 {
+
2749  if (!ship) return;
+
2750 
+
2751  if (Game::MaxTexSize() > 128) {
+
2752  instr_left_sprite->Show();
+
2753  instr_right_sprite->Show();
+
2754  }
+
2755 
+
2756  int ninst = 0;
+
2757  int nobj = 0;
+
2758  Element* elem = ship->GetElement();
+
2759 
+
2760  if (elem) {
+
2761  ninst = elem->NumInstructions();
+
2762  nobj = elem->NumObjectives();
+
2763  }
+
2764 
+
2765  Rect r = Rect(width/2 - 143, height - 105, 290, 17);
+
2766 
+
2767  if (ninst) {
+
2768  int npages = ninst/6 + (ninst%6 ? 1 : 0);
+
2769 
+
2770  if (inst_page >= npages)
+
2771  inst_page = npages-1;
+
2772  else if (inst_page < 0)
+
2773  inst_page = 0;
+
2774 
+
2775  int first = inst_page * 6;
+
2776  int last = first + 6;
+
2777  if (last > ninst) last = ninst;
+
2778 
+
2779  int n = TXT_CAUTION_TXT;
+
2780 
+
2781  for (int i = first; i < last; i++) {
+
2782  hud_text[n].color = standard_txt_colors[color];
+
2783  DrawHUDText(n++, FormatInstruction(elem->GetInstruction(i)), r, DT_LEFT, HUD_MIXED_CASE);
+
2784  r.y += 14;
+
2785  }
+
2786 
+
2787  char page[32];
+
2788  sprintf_s(page, "%d / %d", inst_page+1, npages);
+
2789  r = Rect(width/2 + 40, height-16, 110, 16);
+
2790  DrawHUDText(TXT_INSTR_PAGE, page, r, DT_CENTER, HUD_MIXED_CASE);
+
2791  }
+
2792 
+
2793  else if (nobj) {
+
2794  int n = TXT_CAUTION_TXT;
+
2795 
+
2796  for (int i = 0; i < nobj; i++) {
+
2797  char desc[256];
+
2798  sprintf_s(desc, "* %s", elem->GetObjective(i)->GetShortDescription());
+
2799  hud_text[n].color = standard_txt_colors[color];
+
2800  DrawHUDText(n++, desc, r, DT_LEFT, HUD_MIXED_CASE);
+
2801  r.y += 14;
+
2802  }
+
2803  }
+
2804 
+
2805  else {
+
2806  hud_text[TXT_CAUTION_TXT].color = standard_txt_colors[color];
+
2807  DrawHUDText(TXT_CAUTION_TXT, Game::GetText("HUDView.No-Instructions"), r, DT_LEFT, HUD_MIXED_CASE);
+
2808  }
+
2809 }
+
2810 
+
2811 // +--------------------------------------------------------------------+
+
2812 
+
2813 const char*
+ +
2815 {
+
2816  if (!instr.contains('$'))
+
2817  return (const char*) instr;
+
2818 
+
2819  static char result[256];
+
2820 
+
2821  const char* s = (const char*) instr;
+
2822  char* d = result;
+
2823 
+
2824  KeyMap& keymap = Starshatter::GetInstance()->GetKeyMap();
+
2825 
+
2826  while (*s) {
+
2827  if (*s == '$') {
+
2828  s++;
+
2829  char action[32];
+
2830  char* a = action;
+
2831  while (*s && (isupper(*s) || isdigit(*s) || *s == '_')) *a++ = *s++;
+
2832  *a = 0;
+
2833 
+
2834  int act = KeyMap::GetKeyAction(action);
+
2835  int key = keymap.FindMapIndex(act);
+
2836  const char* s2 = keymap.DescribeKey(key);
+
2837 
+
2838  if (!s2) s2 = action;
+
2839  while (*s2) *d++ = *s2++;
+
2840  }
+
2841  else {
+
2842  *d++ = *s++;
+
2843  }
+
2844  }
+
2845 
+
2846  *d = 0;
+
2847 
+
2848  return result;
+
2849 }
+
2850 
+
2851 // +--------------------------------------------------------------------+
+
2852 
+
2853 void
+ +
2855 {
+
2856  if (direction > 0)
+
2857  inst_page++;
+
2858  else
+
2859  inst_page--;
+
2860 }
+
2861 
+
2862 // +--------------------------------------------------------------------+
+
2863 
+
2864 void
+ +
2866 {
+
2867  int message_queue_empty = true;
+
2868 
+
2869  // age messages:
+
2870  for (int i = 0; i < MAX_MSG; i++) {
+
2871  if (msg_time[i] > 0) {
+
2872  msg_time[i] -= Game::GUITime();
+
2873 
+
2874  if (msg_time[i] <= 0) {
+
2875  msg_time[i] = 0;
+
2876  msg_text[i] = "";
+
2877  }
+
2878 
+
2879  message_queue_empty = false;
+
2880  }
+
2881  }
+
2882 
+
2883  if (!message_queue_empty) {
+
2884  // advance message pipeline:
+
2885  for (int i = 0; i < MAX_MSG; i++) {
+
2886  if (msg_time[0] == 0) {
+
2887  for (int j = 0; j < MAX_MSG-1; j++) {
+
2888  msg_time[j] = msg_time[j+1];
+
2889  msg_text[j] = msg_text[j+1];
+
2890  }
+
2891 
+
2892  msg_time[MAX_MSG-1] = 0;
+
2893  msg_text[MAX_MSG-1] = "";
+
2894  }
+
2895  }
+
2896 
+
2897  // draw messages:
+
2898  for (int i = 0; i < MAX_MSG; i++) {
+
2899  int index = TXT_MSG_1 + i;
+
2900 
+
2901  if (msg_time[i] > 0) {
+
2902  Rect msg_rect(10, 95 + i*10, width-20, 12);
+
2903  DrawHUDText(index, msg_text[i], msg_rect, DT_LEFT, HUD_MIXED_CASE);
+
2904  if (msg_time[i] > 1)
+
2905  hud_text[index].color = txt_color;
+
2906  else
+
2907  hud_text[index].color = txt_color.dim(0.5 + 0.5*msg_time[i]);
+
2908  }
+
2909  }
+
2910  }
+
2911 }
+
2912 
+
2913 // +--------------------------------------------------------------------+
+
2914 
+
2915 void
+ +
2917 {
+
2918  if (!sim)
+
2919  return;
+
2920 
+ +
2922 
+
2923  if (ship) {
+
2924  int nav_index = 1;
+
2925  Instruction* next = ship->GetNextNavPoint();
+
2926 
+
2927  if (mode == HUD_MODE_NAV) {
+
2928  if (next && next->Action() == Instruction::LAUNCH)
+
2929  DrawNavPoint(*next, 0, true);
+
2930 
+
2931  ListIter<Instruction> navpt = ship->GetFlightPlan();
+
2932  while (++navpt) {
+
2933  DrawNavPoint(*navpt.value(), nav_index++, (navpt.value() == next));
+
2934  }
+
2935  }
+
2936  else if (next) {
+
2937  DrawNavPoint(*next, 0, true);
+
2938  }
+
2939  }
+
2940 }
+
2941 
+
2942 void
+ +
2944 {
+
2945  if (ship) {
+
2946  bool hoops_drawn = false;
+
2947  bool same_sector = false;
+
2948 
+
2949  InboundSlot* inbound = ship->GetInbound();
+
2950  if (inbound) {
+
2951  FlightDeck* fd = inbound->GetDeck();
+
2952 
+
2953  if (fd && fd->IsRecoveryDeck() && fd->GetCarrier()) {
+
2954  if (fd->GetCarrier()->GetRegion() == ship->GetRegion())
+
2955  same_sector = true;
+
2956 
+
2957  if (same_sector && mode == HUD_MODE_ILS && !transition && !docking) {
+
2958  Point dst = fd->MountLocation();
+
2959  projector->Transform(dst);
+
2960 
+
2961  if (dst.z > 1.0) {
+
2962  projector->Project(dst);
+
2963 
+
2964  int x = (int) dst.x;
+
2965  int y = (int) dst.y;
+
2966 
+
2967  if (x > 4 && x < width-4 &&
+
2968  y > 4 && y < height-4) {
+
2969 
+
2970  window->DrawLine(x-6, y-6, x+6, y+6, hud_color);
+
2971  window->DrawLine(x+6, y-6, x-6, y+6, hud_color);
+
2972  }
+
2973  }
+
2974  }
+
2975 
+
2976  // draw the hoops for this flight deck:
+
2977  Scene* scene = camview->GetScene();
+
2978  for (int h = 0; h < fd->NumHoops(); h++) {
+
2979  Hoop* hoop = fd->GetHoops() + h;
+
2980  if (hoop && scene) {
+
2981  if (same_sector && mode == HUD_MODE_ILS && !transition && !docking) {
+
2982  scene->AddGraphic(hoop);
+
2983  hoop->Show();
+
2984 
+
2985  hoops_drawn = true;
+
2986  }
+
2987  else {
+
2988  hoop->Hide();
+
2989  scene->DelGraphic(hoop);
+
2990  }
+
2991  }
+
2992  }
+
2993  }
+
2994  }
+
2995 
+
2996  if (!hoops_drawn) {
+
2997  ListIter<Ship> iter = ship->GetRegion()->Carriers();
+
2998  while (++iter) {
+
2999  Ship* carrier = iter.value();
+
3000 
+
3001  bool ours = (carrier->GetIFF() == ship->GetIFF()) ||
+
3002  (carrier->GetIFF() == 0);
+
3003 
+
3004  for (int i = 0; i < carrier->NumFlightDecks(); i++) {
+
3005  FlightDeck* fd = carrier->GetFlightDeck(i);
+
3006 
+
3007  if (fd && fd->IsRecoveryDeck()) {
+
3008  if (mode == HUD_MODE_ILS && ours && !transition && !docking) {
+
3009  Point dst = fd->MountLocation();
+
3010  projector->Transform(dst);
+
3011 
+
3012  if (dst.z > 1.0) {
+
3013  projector->Project(dst);
+
3014 
+
3015  int x = (int) dst.x;
+
3016  int y = (int) dst.y;
+
3017 
+
3018  if (x > 4 && x < width-4 &&
+
3019  y > 4 && y < height-4) {
+
3020 
+
3021  window->DrawLine(x-6, y-6, x+6, y+6, hud_color);
+
3022  window->DrawLine(x+6, y-6, x-6, y+6, hud_color);
+
3023  }
+
3024  }
+
3025  }
+
3026 
+
3027  // draw the hoops for this flight deck:
+
3028  Scene* scene = camview->GetScene();
+
3029  for (int h = 0; h < fd->NumHoops(); h++) {
+
3030  Hoop* hoop = fd->GetHoops() + h;
+
3031  if (hoop && scene) {
+
3032  if (mode == HUD_MODE_ILS && ours && !transition && !docking) {
+
3033  hoop->Show();
+
3034  if (!hoop->GetScene())
+
3035  scene->AddGraphic(hoop);
+
3036  }
+
3037  else {
+
3038  hoop->Hide();
+
3039  if (hoop->GetScene())
+
3040  scene->DelGraphic(hoop);
+
3041  }
+
3042  }
+
3043  }
+
3044  }
+
3045  }
+
3046  }
+
3047  }
+
3048  }
+
3049 }
+
3050 
+
3051 void
+ +
3053 {
+
3054  if (ship && ship->GetDirector() && ship->GetDirector()->Type() >= SteerAI::SEEKER) {
+
3055  SteerAI* steer = (SteerAI*) ship->GetDirector();
+
3056  Point obj = steer->GetObjective();
+
3057  projector->Transform(obj);
+
3058 
+
3059  if (obj.z > 1.0) {
+
3060  projector->Project(obj);
+
3061 
+
3062  int x = (int) obj.x;
+
3063  int y = (int) obj.y;
+
3064 
+
3065  if (x > 4 && x < width-4 &&
+
3066  y > 4 && y < height-4) {
+
3067 
+
3068  Color c = Color::Cyan;
+
3069  window->DrawRect(x-6, y-6, x+6, y+6, c);
+
3070  window->DrawLine(x-6, y-6, x+6, y+6, c);
+
3071  window->DrawLine(x+6, y-6, x-6, y+6, c);
+
3072  }
+
3073  }
+
3074 
+
3075  if (steer->GetOther()) {
+
3076  obj = steer->GetOther()->Location();
+
3077  projector->Transform(obj);
+
3078 
+
3079  if (obj.z > 1.0) {
+
3080  projector->Project(obj);
+
3081 
+
3082  int x = (int) obj.x;
+
3083  int y = (int) obj.y;
+
3084 
+
3085  if (x > 4 && x < width-4 &&
+
3086  y > 4 && y < height-4) {
+
3087 
+
3088  Color c = Color::Orange;
+
3089  window->DrawRect(x-6, y-6, x+6, y+6, c);
+
3090  window->DrawLine(x-6, y-6, x+6, y+6, c);
+
3091  window->DrawLine(x+6, y-6, x-6, y+6, c);
+
3092  }
+
3093  }
+
3094  }
+
3095  }
+
3096  /***/
+
3097 }
+
3098 
+
3099 void
+
3100 HUDView::DrawNavPoint(Instruction& navpt, int index, int next)
+
3101 {
+
3102  if (index >= 15 || !navpt.Region()) return;
+
3103 
+
3104  // transform from starsystem to world coordinates:
+
3105  Point npt = navpt.Region()->Location() + navpt.Location();
+
3106 
+
3107  if (active_region)
+
3108  npt -= active_region->Location();
+
3109 
+
3110  npt = npt.OtherHand();
+
3111 
+
3112  // transform from world to camera:
+
3113  projector->Transform(npt);
+
3114 
+
3115  // clip:
+
3116  if (npt.z > 1.0) {
+
3117 
+
3118  // project:
+
3119  projector->Project(npt);
+
3120 
+
3121  int x = (int) npt.x;
+
3122  int y = (int) npt.y;
+
3123 
+
3124  // clip:
+
3125  if (x > 4 && x < width-4 &&
+
3126  y > 4 && y < height-4) {
+
3127 
+
3128  Color c = Color::White;
+
3129  if (navpt.Status() > Instruction::ACTIVE && navpt.HoldTime() <= 0)
+
3130  c = Color::DarkGray;
+
3131 
+
3132  // draw:
+
3133  if (next)
+
3134  window->DrawEllipse(x-6, y-6, x+5, y+5, c);
+
3135 
+
3136  window->DrawLine(x-6, y-6, x+6, y+6, c);
+
3137  window->DrawLine(x+6, y-6, x-6, y+6, c);
+
3138 
+
3139  if (index > 0) {
+
3140  char npt_buf[32];
+
3141  Rect npt_rect(x+10, y-4, 200, 12);
+
3142 
+
3143  if (navpt.Status() == Instruction::COMPLETE && navpt.HoldTime() > 0) {
+
3144  char hold_time[32];
+
3145  FormatTime(hold_time, navpt.HoldTime());
+
3146  sprintf_s(npt_buf, "%d %s", index, hold_time);
+
3147  }
+
3148  else {
+
3149  sprintf_s(npt_buf, "%d", index);
+
3150  }
+
3151 
+
3152  DrawHUDText(TXT_NAV_PT + index, npt_buf, npt_rect, DT_LEFT);
+
3153  }
+
3154  }
+
3155  }
+
3156 
+
3157  if (next && mode == HUD_MODE_NAV && navpt.Region() == ship->GetRegion()) {
+
3158 
+
3159  // Translate into camera relative:
+
3160  Point tloc = navpt.Location().OtherHand();
+
3161  projector->Transform(tloc);
+
3162 
+
3163  int behind = tloc.z < 0;
+
3164 
+
3165  if (behind)
+
3166  tloc.z = -tloc.z;
+
3167 
+
3168  // Project into screen coordinates:
+
3169  projector->Project(tloc);
+
3170 
+
3171  // DRAW THE OFFSCREEN CHASE INDICATOR:
+
3172  if (behind ||
+
3173  tloc.x <= 0 || tloc.x >= width-1 ||
+
3174  tloc.y <= 0 || tloc.y >= height-1) {
+
3175 
+
3176  // Left side:
+
3177  if (tloc.x <= 0 || (behind && tloc.x < width/2)) {
+
3178  if (tloc.y < ah) tloc.y = ah;
+
3179  else if (tloc.y >= height-ah) tloc.y = height-1-ah;
+
3180 
+
3181  chase_sprite->Show();
+
3182  chase_sprite->SetAnimation(&chase_left);
+
3183  chase_sprite->MoveTo(Point(aw, tloc.y, 1));
+
3184  }
+
3185 
+
3186  // Right side:
+
3187  else if (tloc.x >= width-1 || behind) {
+
3188  if (tloc.y < ah) tloc.y = ah;
+
3189  else if (tloc.y >= height-ah) tloc.y = height-1-ah;
+
3190 
+
3191  chase_sprite->Show();
+
3192  chase_sprite->SetAnimation(&chase_right);
+
3193  chase_sprite->MoveTo(Point(width-1-aw, tloc.y, 1));
+
3194  }
+
3195  else {
+
3196  if (tloc.x < aw) tloc.x = aw;
+
3197  else if (tloc.x >= width-aw) tloc.x = width-1-aw;
+
3198 
+
3199  // Top edge:
+
3200  if (tloc.y <= 0) {
+
3201  chase_sprite->Show();
+
3202  chase_sprite->SetAnimation(&chase_top);
+
3203  chase_sprite->MoveTo(Point(tloc.x, ah, 1));
+
3204  }
+
3205 
+
3206  // Bottom edge:
+
3207  else if (tloc.y >= height-1) {
+
3208  chase_sprite->Show();
+
3209  chase_sprite->SetAnimation(&chase_bottom);
+
3210  chase_sprite->MoveTo(Point(tloc.x, height-1-ah, 1));
+
3211  }
+
3212  }
+
3213  }
+
3214  }
+
3215 }
+
3216 
+
3217 // +--------------------------------------------------------------------+
+
3218 
+
3219 void
+ +
3221 {
+
3222  if (ship != s) {
+
3223  double new_scale = 1;
+
3224 
+
3225  ship_status = -1;
+
3226  ship = s;
+
3227 
+
3228  if (ship) {
+
3229  if (ship->Life() == 0 || ship->IsDying() || ship->IsDead()) {
+
3230  ship = 0;
+
3231  }
+
3232  else {
+
3233  Observe(ship);
+
3234  new_scale = 1.1 * ship->Radius() / 64;
+
3235 
+
3236  if (ship->Design()->hud_icon.Width()) {
+
3237  TransferBitmap(ship->Design()->hud_icon, icon_ship, icon_ship_shade);
+
3238  ColorizeBitmap(icon_ship, icon_ship_shade, txt_color);
+
3239  }
+
3240  }
+
3241  }
+
3242 
+
3243  if (az_ring) {
+ +
3245  az_ring->Rescale(new_scale);
+
3246  }
+
3247 
+
3248  if (az_pointer) {
+ +
3250  az_pointer->Rescale(new_scale);
+
3251  }
+
3252 
+
3253  if (el_ring) {
+ +
3255  el_ring->Rescale(new_scale);
+
3256  }
+
3257 
+
3258  if (el_pointer) {
+ +
3260  el_pointer->Rescale(new_scale);
+
3261  }
+
3262 
+
3263  compass_scale = new_scale;
+
3264  inst_page = 0;
+
3265 
+
3266  if (ship && ship->GetElement() && ship->GetElement()->NumInstructions() > 0)
+
3267  if (!show_inst)
+
3268  CycleHUDInst();
+
3269  }
+
3270 
+
3271  else if (ship && ship->Design()->hud_icon.Width()) {
+
3272  bool update = false;
+ +
3274  int integrity = (int) (ship->Integrity() / ship->Design()->integrity * 100);
+
3275 
+
3276  if (integrity < 30) s = System::CRITICAL;
+
3277  else if (integrity < 60) s = System::DEGRADED;
+
3278 
+
3279  if (s != ship_status) {
+
3280  ship_status = s;
+
3281  update = true;
+
3282  }
+
3283 
+
3284  if (update) {
+
3285  SetStatusColor((System::STATUS) ship_status);
+
3286  ColorizeBitmap(icon_ship, icon_ship_shade, status_color);
+
3287  }
+
3288  }
+
3289 
+
3290  if (ship && ship->Cockpit()) {
+
3291  Solid* cockpit = (Solid*) ship->Cockpit();
+
3292 
+
3293  bool change = false;
+
3294 
+
3295  if (cockpit->Hidden()) {
+
3296  if (cockpit_hud_texture)
+
3297  change = true;
+
3298 
+
3299  cockpit_hud_texture = 0;
+
3300  }
+
3301  else {
+
3302  if (!cockpit_hud_texture)
+
3303  change = true;
+
3304 
+
3305  Model* cockpit_model = cockpit->GetModel();
+
3306  Material* hud_material = 0;
+
3307 
+
3308  if (cockpit_model) {
+
3309  hud_material = (Material*) cockpit_model->FindMaterial("HUD");
+
3310  if (hud_material) {
+
3311  cockpit_hud_texture = hud_material->tex_emissive;
+
3312  }
+
3313  }
+
3314  }
+
3315 
+
3316  if (change) {
+ +
3318  }
+
3319  }
+
3320 }
+
3321 
+
3322 void
+ +
3324 {
+
3325  bool update = false;
+
3326 
+
3327  if (target != t) {
+
3328  tgt_status = -1;
+
3329  target = t;
+
3330  if (target) Observe(target);
+
3331  update = true;
+
3332  }
+
3333 
+
3334  if (target && target->Type() == SimObject::SIM_SHIP) {
+ +
3336  Ship* tship = (Ship*) target;
+
3337  int integrity = (int) (tship->Integrity() / tship->Design()->integrity * 100);
+
3338 
+
3339  if (integrity < 30) s = System::CRITICAL;
+
3340  else if (integrity < 60) s = System::DEGRADED;
+
3341 
+
3342  if (s != tgt_status) {
+
3343  tgt_status = s;
+
3344  update = true;
+
3345  }
+
3346  }
+
3347 
+
3348  if (update) {
+
3349  if (target && target->Type() == SimObject::SIM_SHIP) {
+
3350  Ship* tship = (Ship*) target;
+
3351  TransferBitmap(tship->Design()->hud_icon, icon_target, icon_target_shade);
+
3352  }
+
3353  else {
+
3354  PrepareBitmap("hud_icon.pcx", icon_target, icon_target_shade);
+
3355  }
+
3356 
+
3357  SetStatusColor((System::STATUS) tgt_status);
+
3358  ColorizeBitmap(icon_target, icon_target_shade, status_color);
+
3359  }
+
3360 }
+
3361 
+
3362 // +--------------------------------------------------------------------+
+
3363 
+
3364 MFD*
+
3365 HUDView::GetMFD(int n) const
+
3366 {
+
3367  if (n >= 0 && n < 3)
+
3368  return mfd[n];
+
3369 
+
3370  return 0;
+
3371 }
+
3372 
+
3373 // +--------------------------------------------------------------------+
+
3374 
+
3375 void
+ +
3377 {
+
3378  sim = Sim::GetSim();
+
3379  mouse_in = false;
+
3380 
+
3381  if (!sim || !camview || !projector) {
+
3382  return;
+
3383  }
+
3384 
+
3385  if (Mouse::LButton() == 0) {
+
3386  mouse_latch = 0;
+
3387  mouse_index = -1;
+
3388  }
+
3389 
+
3390  int mouse_index_old = mouse_index;
+
3391 
+ +
3393 
+
3394  if (mode == HUD_MODE_OFF) {
+
3395  if (cockpit_hud_texture) {
+ +
3397  }
+
3398 
+
3399  sim->ShowGrid(false);
+
3400  return;
+
3401  }
+
3402 
+
3403  if (cockpit_hud_texture && cockpit_hud_texture->Width() == 512) {
+
3404  Bitmap* hud_bmp = 0;
+
3405 
+
3406  if (hud_sprite[0]) {
+
3407  hud_bmp = hud_sprite[0]->Frame();
+
3408  int bmp_w = hud_bmp->Width();
+
3409  int bmp_h = hud_bmp->Height();
+
3410 
+
3411  cockpit_hud_texture->BitBlt( 0, 0, *hud_bmp, 0, 0, bmp_w, bmp_h);
+
3412  }
+
3413 
+
3414  if (hud_sprite[1]) {
+
3415  hud_bmp = hud_sprite[1]->Frame();
+
3416  int bmp_w = hud_bmp->Width();
+
3417  int bmp_h = hud_bmp->Height();
+
3418 
+
3419  cockpit_hud_texture->BitBlt(256, 0, *hud_bmp, 0, 0, bmp_w, bmp_h);
+
3420  }
+
3421 
+
3422  if (hud_sprite[6]) {
+
3423  if (hud_sprite[6]->Hidden()) {
+
3424  cockpit_hud_texture->FillRect(0,384,128,512,Color::Black);
+
3425  }
+
3426  else {
+
3427  hud_bmp = hud_sprite[6]->Frame();
+
3428  int bmp_w = hud_bmp->Width();
+
3429  int bmp_h = hud_bmp->Height();
+
3430 
+
3431  cockpit_hud_texture->BitBlt(0,384, *hud_bmp, 0, 0, bmp_w, bmp_h);
+
3432  }
+
3433  }
+
3434 
+
3435  if (hud_sprite[7]) {
+
3436  if (hud_sprite[7]->Hidden()) {
+
3437  cockpit_hud_texture->FillRect(128,384,256,512,Color::Black);
+
3438  }
+
3439  else {
+
3440  hud_bmp = hud_sprite[7]->Frame();
+
3441  int bmp_w = hud_bmp->Width();
+
3442  int bmp_h = hud_bmp->Height();
+
3443 
+
3444  cockpit_hud_texture->BitBlt(128,384, *hud_bmp, 0, 0, bmp_w, bmp_h);
+
3445  }
+
3446  }
+
3447 
+
3448  for (int i = 8; i < 32; i++) {
+
3449  if (hud_sprite[i] && !hud_sprite[i]->Hidden()) {
+
3450  Sprite* s = hud_sprite[i];
+
3451 
+
3452  int cx = (int) s->Location().x;
+
3453  int cy = (int) s->Location().y;
+
3454  int w2 = s->Width() / 2;
+
3455  int h2 = s->Height() / 2;
+
3456 
+
3457  window->DrawBitmap(cx-w2, cy-h2, cx+w2, cy+h2, s->Frame(), Video::BLEND_ALPHA);
+
3458  }
+
3459  }
+
3460  }
+
3461  else {
+
3462  for (int i = 0; i < 32; i++) {
+
3463  if (hud_sprite[i] && !hud_sprite[i]->Hidden()) {
+
3464  Sprite* s = hud_sprite[i];
+
3465 
+
3466  int cx = (int) s->Location().x;
+
3467  int cy = (int) s->Location().y;
+
3468  int w2 = s->Width() / 2;
+
3469  int h2 = s->Height() / 2;
+
3470 
+
3471  window->DrawBitmap(cx-w2, cy-h2, cx+w2, cy+h2, s->Frame(), Video::BLEND_ALPHA);
+
3472  }
+
3473  }
+
3474 
+
3475  Video* video = Video::GetInstance();
+
3476 
+
3477  for (int i = 0; i < 31; i++) {
+
3478  Sprite* s = pitch_ladder[i];
+
3479 
+
3480  if (s && !s->Hidden()) {
+
3481  s->Render2D(video);
+
3482  }
+
3483  }
+
3484  }
+
3485 
+
3486  //DrawStarSystem();
+
3487  DrawMessages();
+
3488 
+
3489  if (ship) {
+
3490  // no hud in transition:
+
3491  if (ship->InTransition()) {
+
3492  transition = true;
+
3493  HideAll();
+
3494  return;
+
3495  }
+
3496 
+
3497  else if (transition) {
+
3498  transition = false;
+
3499  RestoreHUD();
+
3500  }
+
3501 
+ +
3503 
+
3504  // everything is off during docking, except the final message:
+
3505  if (cam_dir && cam_dir->GetMode() == CameraDirector::MODE_DOCKING) {
+
3506  docking = true;
+
3507  HideAll();
+
3508 
+
3509  if (ship->GetFlightPhase() == Ship::DOCKING) {
+
3510  Rect dock_rect(width/2-100, height/6, 200, 20);
+
3511 
+
3512  if (ship->IsAirborne())
+
3513  DrawHUDText(TXT_AUTO, Game::GetText("HUDView.SUCCESSFUL-LANDING"), dock_rect, DT_CENTER);
+
3514  else
+
3515  DrawHUDText(TXT_AUTO, Game::GetText("HUDView.DOCKING-COMPLETE"), dock_rect, DT_CENTER);
+
3516  }
+
3517  return;
+
3518  }
+
3519  else if (docking) {
+
3520  docking = false;
+
3521  RestoreHUD();
+
3522  }
+
3523 
+
3524  // go to NAV mode during autopilot:
+
3525  if (ship->GetNavSystem() && ship->GetNavSystem()->AutoNavEngaged() && !arcade)
+
3526  mode = HUD_MODE_NAV;
+
3527 
+
3528  SetTarget(ship->GetTarget());
+
3529 
+
3530  // internal view of HUD reticule
+ +
3532  SetTacticalMode(0);
+
3533 
+
3534  // external view
+
3535  else
+ +
3537 
+
3538  sim->ShowGrid(tactical &&
+
3539  !ship->IsAirborne() &&
+ +
3541 
+
3542  // draw HUD bars:
+
3543  DrawBars();
+
3544 
+
3545  if (missile_lock_sound) {
+
3546  if (threat > 1) {
+
3547  long max_vol = AudioConfig::WrnVolume();
+
3548  long volume = -1500;
+
3549 
+
3550  if (volume > max_vol)
+
3551  volume = max_vol;
+
3552 
+
3553  missile_lock_sound->SetVolume(volume);
+
3554  missile_lock_sound->Play();
+
3555  }
+
3556  else {
+
3557  missile_lock_sound->Stop();
+
3558  }
+
3559  }
+
3560 
+
3561  DrawNav();
+
3562  DrawILS();
+
3563 
+
3564  // FOR DEBUG PURPOSES ONLY:
+
3565  // DrawObjective();
+
3566 
+
3567  if (!overlay) {
+
3568  Rect fov_rect(0, 10, width, 10);
+
3569  int fov_degrees = 180 - 2 * (int)(projector->XAngle()*180/PI);
+
3570 
+
3571  if (fov_degrees > 90)
+
3572  DrawHUDText(TXT_CAM_ANGLE, Game::GetText("HUDView.Wide-Angle"), fov_rect, DT_CENTER);
+
3573 
+
3574  fov_rect.y = 20;
+
3575  DrawHUDText(TXT_CAM_MODE, CameraDirector::GetModeName(), fov_rect, DT_CENTER);
+
3576  }
+
3577 
+
3578  DrawMFDs();
+
3579 
+
3580  instr_left_sprite->Hide();
+
3581  instr_right_sprite->Hide();
+
3582  warn_left_sprite->Hide();
+
3583  warn_right_sprite->Hide();
+
3584 
+
3585  if (cockpit_hud_texture)
+
3586  cockpit_hud_texture->FillRect(256,384,512,512,Color::Black);
+
3587 
+
3588  if (show_inst) {
+
3589  DrawInstructions();
+
3590  }
+
3591 
+
3592  else if (!arcade) {
+
3593  if (ship->MasterCaution() && !show_warn)
+
3594  ShowHUDWarn();
+
3595 
+
3596  if (show_warn)
+
3597  DrawWarningPanel();
+
3598  }
+
3599 
+
3600  if (width > 640 || (!show_inst && !show_warn)) {
+
3601  Rect icon_rect(120, height-24, 128, 16);
+
3602 
+
3603  if (ship)
+
3604  DrawHUDText(TXT_ICON_SHIP_TYPE, ship->DesignName(), icon_rect, DT_CENTER);
+
3605 
+
3606  icon_rect.x = width - 248;
+
3607 
+
3608  if (target && target->Type() == SimObject::SIM_SHIP) {
+
3609  Ship* tship = (Ship*) target;
+
3610  DrawHUDText(TXT_ICON_TARGET_TYPE, tship->DesignName(), icon_rect, DT_CENTER);
+
3611  }
+
3612  }
+
3613  }
+
3614  else {
+
3615  if (target) {
+
3616  SetTarget(0);
+
3617  }
+
3618  }
+
3619 
+
3620  // latch mouse down to prevent dragging into a control:
+
3621  if (Mouse::LButton() == 1)
+
3622  mouse_latch = 1;
+
3623 
+
3624  if (mouse_index > -1 && mouse_index_old != mouse_index)
+
3625  MouseFrame();
+
3626 }
+
3627 
+
3628 void
+ +
3630 {
+
3631  for (int i = 0; i < 3; i++) {
+
3632  mfd[i]->Show();
+
3633  mfd[i]->SetShip(ship);
+ +
3635  mfd[i]->Draw();
+
3636  }
+
3637 }
+
3638 
+
3639 // +--------------------------------------------------------------------+
+
3640 
+
3641 void
+ +
3643 {
+
3644  if (sim && sim->GetStarSystem()) {
+
3645  StarSystem* sys = sim->GetStarSystem();
+
3646 
+
3647  ListIter<OrbitalBody> iter = sys->Bodies();
+
3648  while (++iter) {
+
3649  OrbitalBody* body = iter.value();
+
3650  DrawOrbitalBody(body);
+
3651  }
+
3652  }
+
3653 }
+
3654 
+
3655 void
+ +
3657 {
+
3658  if (body) {
+
3659  Point p = body->Rep()->Location();
+
3660 
+
3661  projector->Transform(p);
+
3662 
+
3663  if (p.z > 100) {
+
3664  float r = (float) body->Radius();
+
3665  r = projector->ProjectRadius(p, r);
+
3666  projector->Project(p, false);
+
3667 
+
3668  window->DrawEllipse((int) (p.x-r),
+
3669  (int) (p.y-r),
+
3670  (int) (p.x+r),
+
3671  (int) (p.y+r),
+
3672  Color::Cyan);
+
3673  }
+
3674 
+
3675  ListIter<OrbitalBody> iter = body->Satellites();
+
3676  while (++iter) {
+
3677  OrbitalBody* body = iter.value();
+
3678  DrawOrbitalBody(body);
+
3679  }
+
3680  }
+
3681 }
+
3682 
+
3683 // +--------------------------------------------------------------------+
+
3684 
+
3685 void
+ +
3687 {
+
3688  // update the position of HUD elements that are
+
3689  // part of the 3D scene (like fpm and lcos sprites)
+
3690  HideCompass();
+
3691 
+
3692  if (ship && !transition && !docking && mode != HUD_MODE_OFF) {
+ +
3694  gunsight = p->Gunsight();
+
3695 
+
3696  if (ship->IsStarship()) {
+
3697  if (tactical) {
+
3698  hud_left_sprite->Hide();
+
3699  hud_right_sprite->Hide();
+
3700  }
+
3701 
+
3702  else if (hud_left_sprite->Frame() != &hud_left_starship) {
+
3703  hud_left_sprite->SetAnimation(&hud_left_starship);
+
3704  hud_right_sprite->SetAnimation(&hud_right_starship);
+
3705 
+
3706  hud_left_sprite->MoveTo( Point(width/2-128, height/2, 1));
+
3707  hud_right_sprite->MoveTo(Point(width/2+128, height/2, 1));
+
3708  }
+
3709  }
+
3710 
+
3711  else if (!ship->IsStarship()) {
+
3712  if (ship->IsAirborne() && hud_left_sprite->Frame() != &hud_left_air) {
+
3713  hud_left_sprite->SetAnimation(&hud_left_air);
+
3714  hud_right_sprite->SetAnimation(&hud_right_air);
+
3715  }
+
3716 
+
3717  else if (!ship->IsAirborne() && hud_left_sprite->Frame() != &hud_left_fighter) {
+
3718  hud_left_sprite->SetAnimation(&hud_left_fighter);
+
3719  hud_right_sprite->SetAnimation(&hud_right_fighter);
+
3720  }
+
3721  }
+
3722 
+
3723  if (!tactical) {
+
3724  if (Game::MaxTexSize() > 128) {
+
3725  hud_left_sprite->Show();
+
3726  hud_right_sprite->Show();
+
3727  }
+
3728 
+
3729  if (!arcade)
+
3730  DrawFPM();
+
3731 
+
3732  if (ship->IsStarship() && ship->GetFLCSMode() == Ship::FLCS_HELM)
+
3733  DrawHPM();
+
3734  else if (!arcade)
+
3735  DrawPitchLadder();
+
3736  }
+
3737 
+
3738  else {
+
3739  if (ship->IsStarship() && ship->GetFLCSMode() == Ship::FLCS_HELM)
+
3740  DrawCompass();
+
3741  }
+
3742 
+
3743  if (mode == HUD_MODE_TAC) {
+
3744  DrawSight();
+
3745  DrawDesignators();
+
3746  }
+
3747 
+
3748  if (width > 640 || (!show_inst && !show_warn)) {
+
3749  icon_ship_sprite->Show();
+
3750  icon_target_sprite->Show();
+
3751  }
+
3752  else {
+
3753  icon_ship_sprite->Hide();
+
3754  icon_target_sprite->Hide();
+
3755  }
+
3756  }
+
3757 
+
3758  // if the hud is off or prohibited,
+
3759  // hide all of the sprites:
+
3760 
+
3761  else {
+
3762  hud_left_sprite->Hide();
+
3763  hud_right_sprite->Hide();
+
3764  instr_left_sprite->Hide();
+
3765  instr_right_sprite->Hide();
+
3766  warn_left_sprite->Hide();
+
3767  warn_right_sprite->Hide();
+
3768  icon_ship_sprite->Hide();
+
3769  icon_target_sprite->Hide();
+
3770  fpm_sprite->Hide();
+
3771  hpm_sprite->Hide();
+
3772  lead_sprite->Hide();
+
3773  aim_sprite->Hide();
+
3774  tgt1_sprite->Hide();
+
3775  tgt2_sprite->Hide();
+
3776  tgt3_sprite->Hide();
+
3777  tgt4_sprite->Hide();
+
3778  chase_sprite->Hide();
+
3779 
+
3780  for (int i = 0; i < 3; i++)
+
3781  mfd[i]->Hide();
+
3782 
+
3783  for (int i = 0; i < 31; i++)
+
3784  pitch_ladder[i]->Hide();
+
3785 
+
3786  DrawILS();
+
3787  }
+
3788 }
+
3789 
+
3790 // +--------------------------------------------------------------------+
+
3791 
+
3792 void
+ +
3794 {
+
3795  if (mfd_index < 0 || mfd_index > 2) return;
+
3796 
+
3797  int m = mfd[mfd_index]->GetMode();
+
3798  m++;
+
3799 
+
3800  if (mfd_index == 2) {
+
3801  if (m > MFD::MFD_MODE_SHIP)
+
3802  m = MFD::MFD_MODE_OFF;
+
3803  }
+
3804  else {
+
3805  if (m > MFD::MFD_MODE_3D)
+
3806  m = MFD::MFD_MODE_OFF;
+
3807 
+
3808  if (m == MFD::MFD_MODE_GAME)
+
3809  m++;
+
3810 
+
3811  if (mfd_index != 0 && m == MFD::MFD_MODE_SHIP)
+
3812  m++;
+
3813  }
+
3814 
+
3815  mfd[mfd_index]->SetMode(m);
+ +
3817 }
+
3818 
+
3819 // +--------------------------------------------------------------------+
+
3820 
+
3821 void
+ +
3823 {
+
3824  if (!show_warn) {
+
3825  show_warn = true;
+
3826 
+
3827  if (ship && ship->HullStrength() <= 40) {
+
3828  // TOO OBNOXIOUS!!
+ +
3830  }
+
3831  }
+
3832 }
+
3833 
+
3834 void
+ +
3836 {
+
3837  show_inst = true;
+
3838 }
+
3839 
+
3840 // +--------------------------------------------------------------------+
+
3841 
+
3842 void
+ +
3844 {
+
3845  show_warn = false;
+
3846 
+
3847  if (ship) {
+
3848  ship->ClearCaution();
+ +
3850  }
+
3851 }
+
3852 
+
3853 void
+ +
3855 {
+
3856  show_inst = false;
+
3857 }
+
3858 
+
3859 // +--------------------------------------------------------------------+
+
3860 
+
3861 void
+ +
3863 {
+ +
3865  show_warn = !show_warn;
+
3866 
+
3867  if (ship && !show_warn) {
+
3868  ship->ClearCaution();
+ +
3870  }
+
3871 }
+
3872 
+
3873 void
+ +
3875 {
+
3876  show_inst = !show_inst;
+ +
3878 }
+
3879 
+
3880 // +--------------------------------------------------------------------+
+
3881 
+
3882 void
+ +
3884 {
+
3885  if (mode != m) {
+
3886  mode = m;
+
3887 
+
3888  if (mode > HUD_MODE_ILS || mode < HUD_MODE_OFF)
+
3889  mode = HUD_MODE_OFF;
+
3890 
+
3891  if (ship && !ship->IsDropship() && mode == HUD_MODE_ILS)
+
3892  mode = HUD_MODE_OFF;
+
3893 
+
3894  RestoreHUD();
+
3895  }
+
3896 }
+
3897 
+
3898 void
+ +
3900 {
+
3901  mode++;
+
3902 
+
3903  if (arcade && mode != HUD_MODE_TAC)
+
3904  mode = HUD_MODE_OFF;
+
3905 
+
3906  else if (mode > HUD_MODE_ILS || mode < HUD_MODE_OFF)
+
3907  mode = HUD_MODE_OFF;
+
3908 
+
3909  else if (!ship->IsDropship() && mode == HUD_MODE_ILS)
+
3910  mode = HUD_MODE_OFF;
+
3911 
+
3912  RestoreHUD();
+ +
3914 }
+
3915 
+
3916 void
+ +
3918 {
+
3919  if (mode == HUD_MODE_OFF) {
+
3920  HideAll();
+
3921  }
+
3922  else {
+
3923  for (int i = 0; i < 3; i++)
+
3924  mfd[i]->Show();
+
3925 
+
3926  if (width > 640 || (!show_inst && !show_warn)) {
+
3927  icon_ship_sprite->Show();
+
3928  icon_target_sprite->Show();
+
3929  }
+
3930  else {
+
3931  icon_ship_sprite->Hide();
+
3932  icon_target_sprite->Hide();
+
3933  }
+
3934 
+
3935  if (!tactical && Game::MaxTexSize() > 128) {
+
3936  hud_left_sprite->Show();
+
3937  hud_right_sprite->Show();
+
3938  }
+
3939 
+
3940  fpm_sprite->Show();
+
3941 
+
3942  if (ship && ship->IsStarship())
+
3943  hpm_sprite->Show();
+
3944 
+
3945  if (gunsight == 0)
+
3946  aim_sprite->Show();
+
3947  else
+
3948  lead_sprite->Show();
+
3949  }
+
3950 }
+
3951 
+
3952 void
+ +
3954 {
+
3955  for (int i = 0; i < 3; i++)
+
3956  mfd[i]->Hide();
+
3957 
+
3958  hud_left_sprite->Hide();
+
3959  hud_right_sprite->Hide();
+
3960  instr_left_sprite->Hide();
+
3961  instr_right_sprite->Hide();
+
3962  warn_left_sprite->Hide();
+
3963  warn_right_sprite->Hide();
+
3964  icon_ship_sprite->Hide();
+
3965  icon_target_sprite->Hide();
+
3966  fpm_sprite->Hide();
+
3967  hpm_sprite->Hide();
+
3968  lead_sprite->Hide();
+
3969  aim_sprite->Hide();
+
3970  tgt1_sprite->Hide();
+
3971  tgt2_sprite->Hide();
+
3972  tgt3_sprite->Hide();
+
3973  tgt4_sprite->Hide();
+
3974  chase_sprite->Hide();
+
3975 
+
3976  sim->ShowGrid(false);
+
3977 
+
3978  for (int i = 0; i < 31; i++)
+
3979  pitch_ladder[i]->Hide();
+
3980 
+
3981  if (missile_lock_sound)
+
3982  missile_lock_sound->Stop();
+
3983 
+
3984  HideCompass();
+
3985  DrawILS();
+
3986  Mouse::Show(false);
+
3987 }
+
3988 
+
3989 // +--------------------------------------------------------------------+
+
3990 
+
3991 Color
+ +
3993 {
+
3994  if (!sim || !ship || mode == HUD_MODE_OFF)
+
3995  return Color::Black;
+
3996 
+
3997  SimRegion* rgn = sim->GetActiveRegion();
+
3998 
+
3999  if (!rgn || !rgn->IsAirSpace())
+
4000  return Color::Black;
+
4001 
+
4002  Color c = sim->GetStarSystem()->Ambient();
+
4003 
+
4004  if (c.Red() > 32 || c.Green() > 32 || c.Blue() > 32)
+
4005  return Color::Black;
+
4006 
+
4007  // if we get this far, the night-vision aid is on
+
4008  return night_vision_colors[color];
+
4009 }
+
4010 
+
4011 Color
+ +
4013 {
+ +
4015  SetHUDColorSet(color+1);
+
4016  return hud_color;
+
4017 }
+
4018 
+
4019 void
+ +
4021 {
+
4022  color = c;
+
4023  if (color > NUM_HUD_COLORS-1) color = 0;
+
4024  hud_color = standard_hud_colors[color];
+
4025  txt_color = standard_txt_colors[color];
+
4026 
+
4027  ColorizeBitmap(fpm, fpm_shade, hud_color, true);
+
4028  ColorizeBitmap(hpm, hpm_shade, hud_color, true);
+
4029  ColorizeBitmap(lead, lead_shade, txt_color * 1.25, true);
+
4030  ColorizeBitmap(cross, cross_shade, hud_color, true);
+
4031  ColorizeBitmap(cross1, cross1_shade, hud_color, true);
+
4032  ColorizeBitmap(cross2, cross2_shade, hud_color, true);
+
4033  ColorizeBitmap(cross3, cross3_shade, hud_color, true);
+
4034  ColorizeBitmap(cross4, cross4_shade, hud_color, true);
+
4035 
+
4036  if (Game::MaxTexSize() > 128) {
+
4037  ColorizeBitmap(hud_left_air, hud_left_shade_air, hud_color);
+
4038  ColorizeBitmap(hud_right_air, hud_right_shade_air, hud_color);
+
4039  ColorizeBitmap(hud_left_fighter, hud_left_shade_fighter, hud_color);
+
4040  ColorizeBitmap(hud_right_fighter, hud_right_shade_fighter, hud_color);
+
4041  ColorizeBitmap(hud_left_starship, hud_left_shade_starship, hud_color);
+
4042  ColorizeBitmap(hud_right_starship, hud_right_shade_starship, hud_color);
+
4043 
+
4044  ColorizeBitmap(instr_left, instr_left_shade, hud_color);
+
4045  ColorizeBitmap(instr_right, instr_right_shade, hud_color);
+
4046  ColorizeBitmap(warn_left, warn_left_shade, hud_color);
+
4047  ColorizeBitmap(warn_right, warn_right_shade, hud_color);
+
4048 
+
4049  ColorizeBitmap(pitch_ladder_pos, pitch_ladder_pos_shade, hud_color);
+
4050  ColorizeBitmap(pitch_ladder_neg, pitch_ladder_neg_shade, hud_color);
+
4051  }
+
4052 
+
4053  ColorizeBitmap(icon_ship, icon_ship_shade, txt_color);
+
4054  ColorizeBitmap(icon_target, icon_target_shade, txt_color);
+
4055 
+
4056  ColorizeBitmap(chase_left, chase_left_shade, hud_color, true);
+
4057  ColorizeBitmap(chase_right, chase_right_shade, hud_color, true);
+
4058  ColorizeBitmap(chase_top, chase_top_shade, hud_color, true);
+
4059  ColorizeBitmap(chase_bottom, chase_bottom_shade, hud_color, true);
+
4060 
+ + +
4063 
+
4064  for (int i = 0; i < 3; i++)
+
4065  mfd[i]->SetText3DColor(txt_color);
+
4066 
+
4067  Font* font = FontMgr::Find("HUD");
+
4068  if (font)
+
4069  font->SetColor(txt_color);
+
4070 
+
4071  for (int i = 0; i < TXT_LAST; i++)
+
4072  hud_text[i].color = txt_color;
+
4073 }
+
4074 
+
4075 // +--------------------------------------------------------------------+
+
4076 
+
4077 void
+
4078 HUDView::Message(const char* fmt, ...)
+
4079 {
+
4080  if (fmt) {
+
4081  char msg[512];
+
4082  vsprintf(msg, fmt, (char *)(&fmt+1));
+
4083 
+
4084  char* newline = strchr(msg, '\n');
+
4085  if (newline)
+
4086  *newline = 0;
+
4087 
+
4088  Print("%s\n", msg);
+
4089 
+
4090  if (hud_view) {
+
4091  int index = -1;
+
4092 
+
4093  for (int i = 0; i < MAX_MSG; i++) {
+
4094  if (hud_view->msg_time[i] <= 0) {
+
4095  index = i;
+
4096  break;
+
4097  }
+
4098  }
+
4099 
+
4100  // no space; advance pipeline:
+
4101  if (index < 0) {
+
4102  for (int i = 0; i < MAX_MSG-1; i++) {
+
4103  hud_view->msg_text[i] = hud_view->msg_text[i+1];
+
4104  hud_view->msg_time[i] = hud_view->msg_time[i+1];
+
4105  }
+
4106 
+
4107  index = MAX_MSG-1;
+
4108  }
+
4109 
+
4110  hud_view->msg_text[index] = msg;
+
4111  hud_view->msg_time[index] = 10;
+
4112  }
+
4113  }
+
4114 }
+
4115 
+
4116 // +--------------------------------------------------------------------+
+
4117 
+
4118 void
+ +
4120 {
+
4121  if (hud_view) {
+
4122  for (int i = 0; i < MAX_MSG-1; i++) {
+
4123  hud_view->msg_text[i] = Text();
+
4124  hud_view->msg_time[i] = 0;
+
4125  }
+
4126  }
+
4127 }
+
4128 
+
4129 // +--------------------------------------------------------------------+
+
4130 
+
4131 void
+
4132 HUDView::PrepareBitmap(const char* name, Bitmap& img, BYTE*& shades)
+
4133 {
+
4134  delete [] shades;
+
4135  shades = 0;
+
4136 
+
4137  DataLoader* loader = DataLoader::GetLoader();
+
4138 
+
4139  loader->SetDataPath("HUD/");
+
4140  int loaded = loader->LoadBitmap(name, img, Bitmap::BMP_TRANSPARENT);
+
4141  loader->SetDataPath(0);
+
4142 
+
4143  if (!loaded)
+
4144  return;
+
4145 
+
4146  int w = img.Width();
+
4147  int h = img.Height();
+
4148 
+
4149  shades = new(__FILE__,__LINE__) BYTE[w*h];
+
4150 
+
4151  for (int y = 0; y < h; y++)
+
4152  for (int x = 0; x < w; x++)
+
4153  shades[y*w+x] = (BYTE) (img.GetColor(x,y).Red() * 0.66);
+
4154 }
+
4155 
+
4156 void
+
4157 HUDView::TransferBitmap(const Bitmap& src, Bitmap& img, BYTE*& shades)
+
4158 {
+
4159  delete [] shades;
+
4160  shades = 0;
+
4161 
+
4162  if (src.Width() != img.Width() || src.Height() != img.Height())
+
4163  return;
+
4164 
+
4165  img.CopyBitmap(src);
+ +
4167 
+
4168  int w = img.Width();
+
4169  int h = img.Height();
+
4170 
+
4171  shades = new(__FILE__,__LINE__) BYTE[w*h];
+
4172 
+
4173  for (int y = 0; y < h; y++)
+
4174  for (int x = 0; x < w; x++)
+
4175  shades[y*w+x] = (BYTE) (img.GetColor(x,y).Red() * 0.5);
+
4176 }
+
4177 
+
4178 void
+
4179 HUDView::ColorizeBitmap(Bitmap& img, BYTE* shades, Color color, bool force_alpha)
+
4180 {
+
4181  if (!shades) return;
+
4182 
+
4183  int max_tex_size = Game::MaxTexSize();
+
4184 
+
4185  if (max_tex_size < 128)
+
4186  Game::SetMaxTexSize(128);
+
4187 
+
4188  if (hud_view && hud_view->cockpit_hud_texture && !force_alpha) {
+
4189  img.FillColor(Color::Black);
+
4190  Color* dst = img.HiPixels();
+
4191  BYTE* src = shades;
+
4192 
+
4193  for (int y = 0; y < img.Height(); y++) {
+
4194  for (int x = 0; x < img.Width(); x++) {
+
4195  if (*src)
+
4196  *dst = color.dim(*src/200.0);
+
4197  else
+
4198  *dst = Color::Black;
+
4199 
+
4200  dst++;
+
4201  src++;
+
4202  }
+
4203  }
+
4204  img.MakeTexture();
+
4205  }
+
4206  else {
+
4207  img.FillColor(color);
+
4208  img.CopyAlphaImage(img.Width(), img.Height(), shades);
+
4209  img.MakeTexture();
+
4210  }
+
4211 
+
4212  if (max_tex_size < 128)
+
4213  Game::SetMaxTexSize(max_tex_size);
+
4214 }
+
4215 
+
4216 // +--------------------------------------------------------------------+
+
4217 
+
4218 void
+ +
4220 {
+ +
4222  if (ctrl && ctrl->Active())
+
4223  return;
+
4224 
+
4225  if (mouse_index >= TXT_CAUTION_TXT && mouse_index <= TXT_LAST_CAUTION) {
+
4226  if (show_inst) {
+
4227  if (mouse_index == TXT_INSTR_PAGE) {
+
4228  if (Mouse::X() > width/2 + 125)
+
4229  CycleInstructions(1);
+
4230  else if (Mouse::X() < width/2 + 65)
+
4231  CycleInstructions(-1);
+
4232  }
+
4233  else
+
4234  show_inst = false;
+
4235  }
+
4236  else {
+
4237  CycleHUDWarn();
+
4238  }
+
4239  return;
+
4240  }
+
4241 
+ +
4243  if (mouse_index == TXT_PAUSED)
+
4244  stars->Pause(!Game::Paused());
+
4245 
+
4246  if (mouse_index == TXT_GEAR_DOWN)
+
4247  ship->ToggleGear();
+
4248 
+
4249  if (mouse_index == TXT_HUD_MODE) {
+
4250  CycleHUDMode();
+
4251 
+
4252  if (mode == HUD_MODE_OFF)
+
4253  CycleHUDMode();
+
4254  }
+
4255 
+
4256  if (mouse_index == TXT_PRIMARY_WEP) {
+ +
4258  ship->CyclePrimary();
+
4259  }
+
4260 
+
4261  if (mouse_index == TXT_SECONDARY_WEP) {
+ +
4263  ship->CycleSecondary();
+
4264  }
+
4265 
+
4266  if (mouse_index == TXT_DECOY)
+
4267  ship->FireDecoy();
+
4268 
+
4269  if (mouse_index == TXT_SHIELD) {
+
4270  Shield* shield = ship->GetShield();
+
4271 
+
4272  if (shield) {
+
4273  double level = shield->GetPowerLevel();
+
4274 
+
4275  const Rect& r = hud_text[TXT_SHIELD].rect;
+
4276  if (Mouse::X() < r.x + r.w * 0.75)
+
4277  shield->SetPowerLevel(level - 10);
+
4278  else
+
4279  shield->SetPowerLevel(level + 10);
+
4280 
+ +
4282  }
+
4283  }
+
4284 
+
4285  if (mouse_index == TXT_AUTO)
+
4286  ship->TimeSkip();
+
4287 
+
4288  if (mouse_index >= TXT_NAV_INDEX && mouse_index <= TXT_NAV_ETR) {
+
4289  ship->SetAutoNav(!ship->IsAutoNavEngaged());
+ +
4291  }
+
4292 }
+
4293 
+
4294 // +--------------------------------------------------------------------+
+
4295 
+
4296 bool
+ +
4298 {
+
4299  bool result = mouse_in;
+
4300 
+
4301  if (!result) {
+
4302  HUDView* hud = HUDView::GetInstance();
+
4303 
+
4304  for (int i = 0; i < 3; i++)
+
4305  result = result || hud->mfd[i]->IsMouseLatched();
+
4306  }
+
4307 
+
4308  return result;
+
4309 }
+
4310 
+
4311 // +--------------------------------------------------------------------+
+
4312 
+
4313 bool
+ +
4315 {
+
4316  for (int i = 0; i < MAX_CONTACT; i++) {
+
4317  HUDText& test = hud_text[TXT_CONTACT_NAME + i];
+
4318 
+
4319  if (!test.hidden) {
+
4320  Rect r = test.rect;
+
4321 
+
4322  int dx = r.x - x;
+
4323  int dy = r.y - y;
+
4324  int d = dx*dx + dy*dy;
+
4325 
+
4326  if (d <= 400)
+
4327  return true;
+
4328  }
+
4329 
+
4330  test = hud_text[TXT_CONTACT_INFO + i];
+
4331 
+
4332  if (!test.hidden) {
+
4333  Rect r = test.rect;
+
4334 
+
4335  int dx = r.x - x;
+
4336  int dy = r.y - y;
+
4337  int d = dx*dx + dy*dy;
+
4338 
+
4339  if (d <= 400)
+
4340  return true;
+
4341  }
+
4342  }
+
4343 
+
4344  return false;
+
4345 }
+
4346 
+
4347 void
+
4348 HUDView::DrawDiamond(int x, int y, int r, Color c)
+
4349 {
+
4350  POINT diamond[4];
+
4351 
+
4352  diamond[0].x = x;
+
4353  diamond[0].y = y-r;
+
4354 
+
4355  diamond[1].x = x+r;
+
4356  diamond[1].y = y;
+
4357 
+
4358  diamond[2].x = x;
+
4359  diamond[2].y = y+r;
+
4360 
+
4361  diamond[3].x = x-r;
+
4362  diamond[3].y = y;
+
4363 
+
4364  window->DrawPoly(4, diamond, c);
+
4365 }
+
+
+ + + + -- cgit v1.1