]> icculus.org git repositories - taylor/freespace2.git/blob - src/hud/hudtargetbox.cpp
Speed up the renderer a tad
[taylor/freespace2.git] / src / hud / hudtargetbox.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Hud/HUDtargetbox.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module for drawing the target monitor box on the HUD
16  *
17  * $Log$
18  * Revision 1.5  2002/06/18 08:58:53  relnev
19  * last few struct changes
20  *
21  * Revision 1.4  2002/06/17 06:33:09  relnev
22  * ryan's struct patch for gcc 2.95
23  *
24  * Revision 1.3  2002/06/09 04:41:21  relnev
25  * added copyright header
26  *
27  * Revision 1.2  2002/05/07 03:16:45  theoddone33
28  * The Great Newline Fix
29  *
30  * Revision 1.1.1.1  2002/05/03 03:28:09  root
31  * Initial import.
32  *
33  * 
34  * 31    11/02/99 3:22p Jefff
35  * translation of targetbox text
36  * 
37  * 30    10/29/99 10:41p Jefff
38  * more subsystem fixes
39  * 
40  * 29    10/28/99 11:17p Jefff
41  * used escape seqs for some special German chars
42  * 
43  * 28    10/28/99 2:02a Jefff
44  * revised the subsystem localization
45  * 
46  * 27    9/14/99 11:03p Jefff
47  * dont draw target names from # on (weapons case)
48  * 
49  * 26    9/04/99 5:17p Andsager
50  * Make event log record name of destroyed subsytem, and use this name for
51  * different types of turrets
52  * 
53  * 25    8/25/99 11:35a Andsager
54  * Move hud render ship subsystem target box for ships with Autocenter
55  * 
56  * 24    8/17/99 7:32p Jefff
57  * models use autocenter in target view
58  * 
59  * 23    8/01/99 12:39p Dave
60  * Added HUD contrast control key (for nebula).
61  * 
62  * 22    7/31/99 4:15p Dave
63  * Fixed supernova particle velocities. Handle OBJ_NONE in target
64  * monitoring view. Properly use objectives notify gauge colors.
65  * 
66  * 21    7/28/99 2:49p Andsager
67  * Make hud target speed use vm_vec_mag (not vm_vec_mag_quick)
68  * 
69  * 20    7/15/99 9:20a Andsager
70  * FS2_DEMO initial checkin
71  * 
72  * 19    7/02/99 10:56a Andsager
73  * Put in big ship - big ship attack mode.  Modify stealth sweep ai.
74  * 
75  * 18    6/29/99 3:16p Andsager
76  * Debug stuff.
77  * 
78  * 17    6/10/99 3:43p Dave
79  * Do a better job of syncing text colors to HUD gauges.
80  * 
81  * 16    6/09/99 2:55p Andsager
82  * Allow multiple asteroid subtypes (of large, medium, small) and follow
83  * family.
84  * 
85  * 15    6/07/99 4:20p Andsager
86  * Add HUD color for tagged object.  Apply to target and radar.
87  * 
88  * 14    6/03/99 11:43a Dave
89  * Added the ability to use a different model when rendering to the HUD
90  * target box.
91  * 
92  * 13    5/24/99 9:02a Andsager
93  * Remove Int3() in turret subsys name code when turret has no weapon.
94  * 
95  * 12    5/21/99 1:42p Andsager
96  * Added error checking for HUD turret name
97  * 
98  * 11    5/20/99 7:00p Dave
99  * Added alternate type names for ships. Changed swarm missile table
100  * entries.
101  * 
102  * 10    5/19/99 3:50p Andsager
103  * Show type of debris is debris field (species debris or asteroid).  Show
104  * type of subsystem turret targeted (laser, missile, flak, beam).
105  * 
106  * 9     5/14/99 4:22p Andsager
107  * Modify hud_render_target_ship to show damaged subsystems in their
108  * actual state.  Now also shows rotation of subsystems.
109  * 
110  * 8     4/16/99 5:54p Dave
111  * Support for on/off style "stream" weapons. Real early support for
112  * target-painting lasers.
113  * 
114  * 7     1/07/99 9:08a Jasen
115  * HUD coords
116  * 
117  * 6     12/28/98 3:17p Dave
118  * Support for multiple hud bitmap filenames for hi-res mode.
119  * 
120  * 5     12/21/98 5:03p Dave
121  * Modified all hud elements to be multi-resolution friendly.
122  * 
123  * 4     11/05/98 4:18p Dave
124  * First run nebula support. Beefed up localization a bit. Removed all
125  * conditional compiles for foreign versions. Modified mission file
126  * format.
127  * 
128  * 3     10/13/98 9:28a Dave
129  * Started neatening up freespace.h. Many variables renamed and
130  * reorganized. Added AlphaColors.[h,cpp]
131  * 
132  * 2     10/07/98 10:53a Dave
133  * Initial checkin.
134  * 
135  * 1     10/07/98 10:49a Dave
136  * 
137  * 108   8/28/98 3:28p Dave
138  * EMP effect done. AI effects may need some tweaking as required.
139  * 
140  * 107   8/25/98 1:48p Dave
141  * First rev of EMP effect. Player side stuff basically done. Next comes
142  * AI code.
143  * 
144  * 106   6/19/98 3:49p Lawrance
145  * localization tweaks
146  * 
147  * 105   6/17/98 11:04a Lawrance
148  * localize subsystem names that appear on the HUD
149  * 
150  * 104   6/09/98 5:18p Lawrance
151  * French/German localization
152  * 
153  * 103   6/09/98 10:31a Hoffoss
154  * Created index numbers for all xstr() references.  Any new xstr() stuff
155  * added from here on out should be added to the end if the list.  The
156  * current list count can be found in FreeSpace.cpp (search for
157  * XSTR_SIZE).
158  * 
159  * 102   6/01/98 11:43a John
160  * JAS & MK:  Classified all strings for localization.
161  * 
162  * 101   5/20/98 3:52p Allender
163  * fixed compiler warnings
164  * 
165  * 100   5/20/98 12:59p John
166  * Turned optimizations on for debug builds.   Also turning on automatic
167  * function inlining.  Turned off the unreachable code warning.
168  * 
169  * 99    5/15/98 8:36p Lawrance
170  * Add 'target ship that last sent transmission' target key
171  * 
172  * 98    5/14/98 11:26a Lawrance
173  * ensure fighter bays are drawn with correct bracket color
174  * 
175  * 97    5/08/98 5:32p Lawrance
176  * Allow cargo scanning even if target gauge is disabled
177  * 
178  * 96    5/04/98 10:51p Lawrance
179  * remove unused local 
180  * 
181  * 95    5/04/98 9:17p Lawrance
182  * Truncate ship class names at # char when displaying debris on target
183  * moniter
184  * 
185  * 94    5/04/98 6:12p Lawrance
186  * Write generic function hud_end_string_at_first_hash_symbol(), to use in
187  * various spots on the HUD
188  * 
189  * 93    4/15/98 12:55a Lawrance
190  * Show time to impact for bombs
191  * 
192  * 92    4/02/98 6:31p Lawrance
193  * remove asteroid references if DEMO defined
194  * 
195  * 91    3/31/98 5:18p John
196  * Removed demo/save/restore.  Made NDEBUG defined compile.  Removed a
197  * bunch of debug stuff out of player file.  Made model code be able to
198  * unload models and malloc out only however many models are needed.
199  *  
200  * 
201  * 90    3/30/98 1:08a Lawrance
202  * Implement "blast" icon.  Blink HUD icon when player ship is hit by a
203  * blast.
204  *
205  * $NoKeywords: $
206  */
207
208 #include "2d.h"
209 #include "3d.h"
210 #include "3dinternal.h"
211 #include "object.h"
212 #include "hud.h"
213 #include "hudtarget.h"
214 #include "hudbrackets.h"
215 #include "hudets.h"
216 #include "model.h"
217 #include "missionparse.h"
218 #include "debris.h"
219 #include "weapon.h"
220 #include "player.h"
221 #include "gamesnd.h"
222 #include "freespace.h"
223 #include "bmpman.h"
224 #include "timer.h"
225 #include "subsysdamage.h"
226 #include "hudtargetbox.h"
227 #include "font.h"
228 #include "asteroid.h"
229 #include "jumpnode.h"
230 #include "multi.h"
231 #include "emp.h"
232 #include "localize.h"
233
234 int Target_window_coords[GR_NUM_RESOLUTIONS][4] =
235 {
236         { // GR_640
237                 8, 362, 131, 112
238         },
239         { // GR_1024
240                 8, 629, 131, 112
241         }
242 };
243
244 object *Enemy_attacker = NULL;
245
246 static int Target_static_next;
247 static int Target_static_playing;
248 int Target_static_looping;
249
250 #ifndef NDEBUG
251 extern int Show_target_debug_info;
252 extern int Show_target_weapons;
253 #endif
254
255 // used to print out + or - after target distance and speed
256 char* modifiers[] = {
257 //XSTR:OFF
258 "+",
259 "-",
260 ""
261 //XSTR:ON
262 };
263
264 char Target_view_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
265         "targetview1",
266         "targetview1"
267 };
268 char Target_integ_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
269         "targetview2",
270         "targetview2"
271 };
272 char Target_extra_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
273         "targetview3",
274         "targetview3"
275 };
276
277 // animation frames for the target view monitor
278 // frames:      0       =>              background of target monitor
279 //                              1       =>              foreground of target monitor
280 hud_frames Target_view_gauge;
281 int Target_view_gauge_loaded = 0;
282
283 // animation frames for the extended target information
284 // frames:      0       =>              normal gague
285 hud_frames Target_view_extra;
286 int Target_view_extra_loaded = 0;
287
288 // animation frames for the target view monitor integrity bar
289 // frames:      0       =>              dark bar
290 //                              1       =>              bright bar
291 hud_frames Target_view_integrity_gauge;
292 int Target_view_integrity_gauge_loaded = 0;
293
294 #define NUM_TBOX_COORDS                 11      // keep up to date
295 #define TBOX_BACKGROUND                 0
296 #define TBOX_NAME                                       1
297 #define TBOX_CLASS                              2
298 #define TBOX_DIST                                       3
299 #define TBOX_SPEED                              4
300 #define TBOX_CARGO                              5
301 #define TBOX_HULL                                       6
302 #define TBOX_EXTRA                              7
303 #define TBOX_EXTRA_ORDERS               8
304 #define TBOX_EXTRA_TIME                 9
305 #define TBOX_EXTRA_DOCK                 10
306
307 int Targetbox_coords[GR_NUM_RESOLUTIONS][NUM_TBOX_COORDS][2] = 
308 {
309         { // GR_640
310                 {5,319},
311                 {13,316},
312                 {13,325},
313                 {13,337},
314                 {90,337},
315                 {13,349},
316                 {139,361},
317                 {5,283},
318                 {13,280},
319                 {13,290},
320                 {13,299}
321         }, 
322         { // GR_1024
323                 {5,590},
324                 {13,587},
325                 {13,597},
326                 {13,608},
327                 {90,608},
328                 {13,620},
329                 {139,632},
330                 {5,555},
331                 {13,552},
332                 {13,561},
333                 {13,570}
334         }
335 };
336
337 int Integrity_bar_coords[GR_NUM_RESOLUTIONS][4] = {
338         { // GR_640
339                 138, 371, 4, 88
340         },
341         { // GR_1024
342                 138, 642, 4, 88
343         }
344 };
345 int Integrity_string_coords[GR_NUM_RESOLUTIONS][2] = {
346         { // GR_640
347                 112, 372
348         },
349         { // GR_1024
350                 112, 643
351         }
352 };
353
354 // cargo scanning extents
355 int Cargo_scan_coords[GR_NUM_RESOLUTIONS][4] = {
356         { // GR_640
357                 7, 364, 130, 109
358         },
359         { // GR_1024
360                 7, 635, 130, 109
361         }
362 };
363
364 // first element is time flashing expires, second element is time of next flash
365 int Targetbox_flash_timers[NUM_TBOX_FLASH_TIMERS][2];
366 int Targetbox_flash_flags;
367
368 // flag to indicate whether to show the extra information about a target 
369 // The HUD_config controls whether this can be shown... but the player can still toggle it on/off
370 // during the game.
371 int Targetbox_show_extra_info = 1;
372
373 // Different target states.  This drives the text display right below the hull integrity on the targetbox.
374 #define TS_DIS          0
375 #define TS_OK           1
376 #define TS_DMG          2
377 #define TS_CRT          3
378
379 static int Last_ts;     // holds last target status.
380
381 void hud_blit_target_integrity(int disabled,int force_obj_num = -1);
382
383 // cut down long subsystem names to a more manageable length
384 char *hud_targetbox_truncate_subsys_name(char *outstr)
385 {       
386         if(Lcl_gr){
387                 if ( strstr(outstr, "communication") )  {
388                         strcpy(outstr, "Komm");
389                 } else if ( !stricmp(outstr, "weapons") ) {
390                         strcpy(outstr, "Waffen");
391                 } else if ( strstr(outstr, "engine") || strstr(outstr, "Engine")) {
392                         strcpy(outstr, "Antrieb");
393                 } else if ( !stricmp(outstr, "sensors") ) {
394                         strcpy(outstr, "Sensoren");
395                 } else if ( strstr(outstr, "navigat") ) {
396                         strcpy(outstr, "Nav");
397                 } else if ( strstr(outstr, "fighterbay") || strstr(outstr, "Fighterbay") ) {
398                         strcpy(outstr, "J\x84gerhangar");
399                 } else if ( strstr(outstr, "missile") ) {
400                         strcpy(outstr, "Raketenwerfer");
401                 } else if ( strstr(outstr, "laser") || strstr(outstr, "turret") ) {
402                         strcpy(outstr, "Gesch\x81tzturm");
403                 } else if ( strstr(outstr, "Command Tower") || strstr(outstr, "Bridge") ) {
404                         strcpy(outstr, "Br\x81""cke");
405                 } else if ( strstr(outstr, "Barracks") ) {
406                         strcpy(outstr, "Quartiere");
407                 } else if ( strstr(outstr, "Reactor") ) {
408                         strcpy(outstr, "Reaktor");
409                 } else if ( strstr(outstr, "RadarDish") ) {
410                         strcpy(outstr, "Radarantenne");
411                 } else if (!stricmp(outstr, "Gas Collector")) {
412                         strcpy(outstr, "Sammler");
413                 } 
414         } else if(Lcl_fr){      
415                 if ( strstr(outstr, "communication") )  {
416                         strcpy(outstr, "comm");
417                 } else if ( !stricmp(outstr, "weapons") ) {
418                         strcpy(outstr, "armes");
419                 } else if ( strstr(outstr, "engine") ) {
420                         strcpy(outstr, "moteur");
421                 } else if ( !stricmp(outstr, "sensors") ) {
422                         strcpy(outstr, "detecteurs");
423                 } else if ( strstr(outstr, "navi") ) {
424                         strcpy(outstr, "nav");
425                 } else if ( strstr(outstr, "missile") ) {
426                         strcpy(outstr, "lanceur de missiles");
427                 } else if ( strstr(outstr, "fighter") ) {
428                         strcpy(outstr, "baie de chasse");
429                 } else if ( strstr(outstr, "laser") || strstr(outstr, "turret") || strstr(outstr, "missile") ) {
430                         strcpy(outstr, "tourelle");
431                 } 
432         } else {        
433                 if (!strnicmp(outstr, XSTR( "communication", 333), 3))  {
434                         strcpy( outstr, XSTR( "comm", 334) );
435                 } else if (!strnicmp(outstr, XSTR( "navigation", 335), 3))      {
436                         strcpy( outstr, XSTR( "nav", 336) );
437                 } else if (!stricmp(outstr, "Gas Collector")) {
438                         strcpy(outstr, "Collector");
439                 }
440         }
441
442         return outstr;
443 }
444
445 // init a specific targetbox timer
446 void hud_targetbox_init_flash_timer(int index)
447 {
448         Targetbox_flash_timers[index][0] = 1;
449         Targetbox_flash_timers[index][1] = 1;
450         Targetbox_flash_flags &= ~(1<<index);
451 }
452
453 // init the timers used to flash different parts of the targetbox.  This needs to get called whenever
454 // the current target changes.
455 void hud_targetbox_init_flash()
456 {
457         hud_targetbox_init_flash_timer(TBOX_FLASH_NAME);
458         hud_targetbox_init_flash_timer(TBOX_FLASH_CARGO);
459         hud_targetbox_init_flash_timer(TBOX_FLASH_HULL);
460         hud_targetbox_init_flash_timer(TBOX_FLASH_STATUS);
461         hud_targetbox_init_flash_timer(TBOX_FLASH_SUBSYS);
462         hud_targetbox_init_flash_timer(TBOX_FLASH_DOCKED);
463
464         Last_ts = -1;
465 }
466
467 // set the color for flashing text
468 // input:       index   =>      item to flash
469 //                              flash_fast      =>      optional param (default value 0), flash twice as fast
470 // exit:        1 =>    set bright color
471 //                      0 =>    set default color
472 int hud_targetbox_maybe_flash(int index, int flash_fast)
473 {
474         int draw_bright=0;
475
476         // hud_set_default_color();
477         hud_set_gauge_color(HUD_TARGET_MONITOR);
478         if ( !timestamp_elapsed(Targetbox_flash_timers[index][0]) ) {
479                 if ( timestamp_elapsed(Targetbox_flash_timers[index][1]) ) {
480                         if ( flash_fast ) {
481                                 Targetbox_flash_timers[index][1] = timestamp(fl2i(TBOX_FLASH_INTERVAL/2.0f));
482                         } else {
483                                 Targetbox_flash_timers[index][1] = timestamp(TBOX_FLASH_INTERVAL);
484                         }
485                         Targetbox_flash_flags ^= (1<<index);    // toggle between default and bright frames
486                 }
487
488                 if ( Targetbox_flash_flags & (1<<index) ) {
489                         // hud_set_bright_color();
490                         hud_set_gauge_color(HUD_TARGET_MONITOR, HUD_C_BRIGHT);
491                         draw_bright=1;
492                 } else {                        
493                         // hud_set_dim_color();
494                         hud_set_gauge_color(HUD_TARGET_MONITOR, HUD_C_DIM);
495                 }
496         }
497
498         return draw_bright;
499 }
500
501 // init all targetbox flash timers
502 void hud_targetbox_init_all_timers()
503 {
504         int i;
505         for ( i = 0; i < NUM_TBOX_FLASH_TIMERS; i++ ) {
506                 hud_targetbox_init_flash_timer(i);
507         }
508
509         Last_ts = -1;
510 }
511
512 // Initialize the data needed for the target view.  This is called from HUD_init() once per mission
513 void hud_targetbox_init()
514 {
515         if (!Target_view_gauge_loaded) {
516                 Target_view_gauge.first_frame = bm_load_animation(Target_view_fname[gr_screen.res], &Target_view_gauge.num_frames);
517                 if ( Target_view_gauge.first_frame < 0 ) {
518                         Warning(LOCATION,"Cannot load hud ani: %s\n", Target_view_fname[gr_screen.res]);
519                 }
520                 Target_view_gauge_loaded = 1;
521         }
522
523         if (!Target_view_integrity_gauge_loaded) {
524                 Target_view_integrity_gauge.first_frame = bm_load_animation(Target_integ_fname[gr_screen.res], &Target_view_integrity_gauge.num_frames);
525                 if ( Target_view_integrity_gauge.first_frame < 0 ) {
526                         Warning(LOCATION,"Cannot load hud ani: %s\n", Target_integ_fname[gr_screen.res]);
527                 }
528                 Target_view_integrity_gauge_loaded = 1;
529         }
530
531         if (!Target_view_extra_loaded) {
532                 Target_view_extra.first_frame = bm_load_animation(Target_extra_fname[gr_screen.res], &Target_view_extra.num_frames);
533                 if ( Target_view_extra.first_frame < 0 ) {
534                         Warning(LOCATION,"Cannot load hud ani: %s\n", Target_extra_fname[gr_screen.res]);
535                 }
536                 Target_view_extra_loaded = 1;
537         }
538
539         hud_targetbox_init_all_timers();
540 }
541
542 // -------------------------------------------------------------------------------------
543 // hud_save_restore_camera_data()
544 //
545 //      Called to save and restore the 3D camera settings.
546 //
547 void hud_save_restore_camera_data(int save)
548 {
549         static vector   save_view_position;
550         static float    save_view_zoom;
551         static matrix   save_view_matrix;
552         static matrix   save_eye_matrix;
553         static vector   save_eye_position;
554
555         // save global view variables, so we can restore them
556         if ( save ) {
557                 save_view_position      = View_position;
558                 save_view_zoom                  = View_zoom;
559                 save_view_matrix                = View_matrix;
560                 save_eye_matrix         = Eye_matrix;
561                 save_eye_position               = Eye_position;
562         }
563         else {
564                 // restore global view variables
565                 View_position   = save_view_position;
566                 View_zoom               = save_view_zoom;
567                 View_matrix             = save_view_matrix;
568                 Eye_matrix              = save_eye_matrix;
569                 Eye_position    = save_eye_position;
570         }
571 }
572
573 // -------------------------------------------------------------------------------------
574 // hud_render_target_background()
575 //
576 // Common set up for drawing the background of the target monitor, for ships/debris/missiles
577 //
578 void hud_render_target_background()
579 {
580         // blit the background frame
581         hud_set_gauge_color(HUD_TARGET_MONITOR);
582
583         GR_AABITMAP(Target_view_gauge.first_frame, Targetbox_coords[gr_screen.res][TBOX_BACKGROUND][0],Targetbox_coords[gr_screen.res][TBOX_BACKGROUND][1]);
584
585         // blit the extra targeting info frame
586         hud_set_gauge_color(HUD_TARGET_MONITOR_EXTRA_DATA);
587 }
588
589
590 // -------------------------------------------------------------------------------------
591 // hud_render_target_setup()
592 //
593 // Common set up for the 3d code for drawing the target monitor, for ships/debris/missiles
594 //
595 void hud_render_target_setup(vector *camera_eye, matrix *camera_orient, float zoom)
596 {
597         // JAS: g3_start_frame uses clip_width and clip_height to determine the
598         // size to render to.  Normally, you would set this by using gr_set_clip,
599         // but because of the hacked in hud jittering, I couldn't.  So come talk
600         // to me before modifying or reusing the following code. Thanks.
601         
602         gr_screen.clip_width = Target_window_coords[gr_screen.res][2];
603         gr_screen.clip_height = Target_window_coords[gr_screen.res][3];
604         g3_start_frame(1);              // Turn on zbuffering
605         hud_save_restore_camera_data(1);
606         g3_set_view_matrix( camera_eye, camera_orient, zoom);   
607         model_set_detail_level(1);              // use medium detail level
608
609         HUD_set_clip(Target_window_coords[gr_screen.res][0],Target_window_coords[gr_screen.res][1],Target_window_coords[gr_screen.res][2],Target_window_coords[gr_screen.res][3]);
610
611 }
612
613 // -------------------------------------------------------------------------------------
614 // hud_render_target_close()
615 //
616 // Common clean-up after drawing the target monitor, for ships/debris/missiles
617 //
618 void hud_render_target_close()
619 {
620         g3_end_frame();
621         hud_save_restore_camera_data(0);
622 }
623
624 // -------------------------------------------------------------------------------------
625 // hud_blit_target_foreground()
626 //
627 void hud_blit_target_foreground()
628 {
629         hud_set_gauge_color(HUD_TARGET_MONITOR);
630
631         GR_AABITMAP(Target_view_gauge.first_frame+1, Targetbox_coords[gr_screen.res][TBOX_BACKGROUND][0],Targetbox_coords[gr_screen.res][TBOX_BACKGROUND][1]);  
632 }
633
634 // -------------------------------------------------------------------------------------
635 // hud_get_target_strength()
636 //
637 // Get the shield and hull percentages for a given ship object
638 //
639 // input:       *objp           =>              pointer to ship object that you want strength values for
640 //                              shields =>              OUTPUT parameter:       percentage value of shields (0->1.0)
641 //                              integrity =>    OUTPUT parameter: percentage value of integrity (0->1.0)
642 //
643 void hud_get_target_strength(object *objp, float *shields, float *integrity)
644 {
645         ship_info       *sip;
646         
647         if ( objp->type != OBJ_SHIP ) {
648                 Int3();
649                 return;
650         }
651
652         sip = &Ship_info[Ships[objp->instance].ship_info_index];
653
654         if (!( sip->shields == 0.0f )){
655                 *shields = get_shield_strength(objp) / sip->shields;
656         } else {
657                 *shields = 0.0f;
658         }
659
660         if (*shields < 0.0f){
661                 *shields = 0.0f;
662         }
663
664         if ( sip->initial_hull_strength == 0 ) {
665                 Int3(); // illegal initial hull strength
666                 *integrity = 0.0f;
667                 return;
668         }
669
670         *integrity = objp->hull_strength / sip->initial_hull_strength;
671         if (*integrity < 0)
672                 *integrity = 0.0f;
673 }
674
675 // maybe draw the extra targeted ship information above the target monitor
676 void hud_targetbox_show_extra_ship_info(ship *target_shipp, ai_info *target_aip)
677 {
678         char outstr[256], tmpbuf[256];
679         int has_orders = 0;
680         int not_training;
681         int extra_data_shown=0;
682
683         hud_set_gauge_color(HUD_TARGET_MONITOR_EXTRA_DATA);
684
685         not_training = !(The_mission.game_type & MISSION_TYPE_TRAINING);
686         if ( not_training && (hud_gauge_active(HUD_TARGET_MONITOR_EXTRA_DATA)) && (Targetbox_show_extra_info) ) {
687                 // Print out current orders if the targeted ship is friendly
688                 // AL 12-26-97: only show orders and time to target for friendly ships
689                 if ( (Player_ship->team == target_shipp->team) && !(ship_get_SIF(target_shipp) & SIF_NOT_FLYABLE) ) {
690                         extra_data_shown=1;
691                         if ( ship_return_orders(outstr, target_shipp) ) {
692                                 gr_force_fit_string(outstr, 255, 162);
693                                 has_orders = 1;
694                         } else {
695                                 strcpy(outstr, XSTR( "no orders", 337));
696                         }
697                         
698                         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_EXTRA_ORDERS][0], Targetbox_coords[gr_screen.res][TBOX_EXTRA_ORDERS][1], EG_TBOX_EXTRA1, outstr);                   
699                 }
700
701                 if ( has_orders ) {
702                         sprintf(outstr, XSTR( "time to: ", 338));
703                         if ( ship_return_time_to_goal(tmpbuf, target_shipp) ) {
704                                 strcat(outstr, tmpbuf);
705                                 
706                                 emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_EXTRA_TIME][0], Targetbox_coords[gr_screen.res][TBOX_EXTRA_TIME][1], EG_TBOX_EXTRA2, outstr);                               
707                         }
708                 }
709         }
710
711         // Print out dock status
712         if ( target_aip->ai_flags & AIF_DOCKED ) {
713                 if ( target_aip->dock_objnum >= 0 ) {
714                         sprintf(outstr, XSTR( "Docked: %s", 339), Ships[Objects[target_aip->dock_objnum].instance].ship_name);
715                         gr_force_fit_string(outstr, 255, 173);
716                         hud_targetbox_maybe_flash(TBOX_FLASH_DOCKED);
717                         
718                         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_EXTRA_DOCK][0], Targetbox_coords[gr_screen.res][TBOX_EXTRA_DOCK][1], EG_TBOX_EXTRA3, outstr);                       
719                         extra_data_shown=1;
720                 }
721         }
722
723         if ( extra_data_shown ) {
724                 // hud_set_default_color();             
725
726                 GR_AABITMAP(Target_view_extra.first_frame, Targetbox_coords[gr_screen.res][TBOX_EXTRA][0],Targetbox_coords[gr_screen.res][TBOX_EXTRA][1]);              
727         }
728 }
729
730 // Render a jump node on the target monitor
731 void hud_render_target_jump_node(object *target_objp)
732 {
733         char                    outstr[256];
734         vector          obj_pos = {0.0f,0.0f,0.0f};
735         vector          camera_eye = {0.0f,0.0f,0.0f};
736         matrix          camera_orient = IDENTITY_MATRIX;
737         vector          orient_vec, up_vector;
738         float                   factor, dist;
739         int                     hx, hy, w, h;
740
741         if ( Detail.targetview_model )  {
742                 // take the forward orientation to be the vector from the player to the current target
743                 vm_vec_sub(&orient_vec, &target_objp->pos, &Player_obj->pos);
744                 vm_vec_normalize(&orient_vec);
745
746                 factor = target_objp->radius*4.0f;
747
748                 // use the player's up vector, and construct the viewers orientation matrix
749                 up_vector = Player_obj->orient.v.uvec;
750                 vm_vector_2_matrix(&camera_orient,&orient_vec,&up_vector,NULL);
751
752                 // normalize the vector from the player to the current target, and scale by a factor to calculate
753                 // the objects position
754                 vm_vec_copy_scale(&obj_pos,&orient_vec,factor);
755
756                 hud_render_target_setup(&camera_eye, &camera_orient, 0.5f);
757                 jumpnode_render( target_objp, &obj_pos );
758                 hud_render_target_close();
759         }
760         
761         HUD_reset_clip();
762         hud_blit_target_foreground();
763         hud_blit_target_integrity(1);
764         // hud_set_default_color();
765         hud_set_gauge_color(HUD_TARGET_MONITOR);
766
767         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_NAME][0], Targetbox_coords[gr_screen.res][TBOX_NAME][1], EG_TBOX_NAME, Jump_nodes[target_objp->instance].name);     
768
769         dist = vm_vec_dist_quick(&target_objp->pos, &Player_obj->pos);
770
771         // account for hud shaking
772         hx = fl2i(HUD_offset_x);
773         hy = fl2i(HUD_offset_y);
774
775         sprintf(outstr,XSTR( "d: %.0f", 340), dist);
776         hud_num_make_mono(outstr);
777         gr_get_string_size(&w,&h,outstr);
778         
779         emp_hud_printf(Targetbox_coords[gr_screen.res][TBOX_DIST][0]+hx, Targetbox_coords[gr_screen.res][TBOX_DIST][1]+hy, EG_TBOX_DIST, outstr);       
780 }
781
782 // -------------------------------------------------------------------------------------
783 // hud_render_target_asteroid()
784 //
785 // Render a piece of asteroid on the target monitor
786 //
787 void hud_render_target_asteroid(object *target_objp)
788 {
789 #ifndef FS2_DEMO
790         vector          obj_pos = {0.0f,0.0f,0.0f};
791         vector          camera_eye = {0.0f,0.0f,0.0f};
792         matrix          camera_orient = IDENTITY_MATRIX;
793         asteroid                *asteroidp;
794         vector          orient_vec, up_vector;
795         int                     target_team;
796         float                   time_to_impact, factor; 
797         int                     subtype;
798
799         asteroidp = &Asteroids[target_objp->instance];
800
801         target_team = obj_team(target_objp);
802
803         subtype = asteroidp->asteroid_subtype;
804
805         if ( Detail.targetview_model )  {
806                 // take the forward orientation to be the vector from the player to the current target
807                 vm_vec_sub(&orient_vec, &target_objp->pos, &Player_obj->pos);
808                 vm_vec_normalize(&orient_vec);
809
810                 factor = 2*target_objp->radius;
811
812                 // use the player's up vector, and construct the viewers orientation matrix
813                 up_vector = Player_obj->orient.v.uvec;
814                 vm_vector_2_matrix(&camera_orient,&orient_vec,&up_vector,NULL);
815
816                 // normalize the vector from the player to the current target, and scale by a factor to calculate
817                 // the objects position
818                 vm_vec_copy_scale(&obj_pos,&orient_vec,factor);
819
820                 hud_render_target_setup(&camera_eye, &camera_orient, 0.5f);
821                 model_clear_instance(Asteroid_info[asteroidp->type].model_num[subtype]);
822                 model_render(Asteroid_info[asteroidp->type].model_num[subtype], &target_objp->orient, &obj_pos, MR_NO_LIGHTING | MR_LOCK_DETAIL );
823                 hud_render_target_close();
824         }
825
826         HUD_reset_clip();
827         hud_blit_target_foreground();
828         hud_blit_target_integrity(1);
829         // hud_set_default_color();
830         hud_set_gauge_color(HUD_TARGET_MONITOR);
831
832         // hud print type of Asteroid (debris)
833         char hud_name[64];
834         switch (asteroidp->type) {
835         case ASTEROID_TYPE_SMALL:
836         case ASTEROID_TYPE_MEDIUM:
837         case ASTEROID_TYPE_BIG:
838                 strcpy(hud_name, NOX("asteroid"));
839                 break;
840
841         case DEBRIS_TERRAN_SMALL:
842         case DEBRIS_TERRAN_MEDIUM:
843         case DEBRIS_TERRAN_LARGE:
844                 strcpy(hud_name, NOX("terran debris"));
845                 break;
846
847         case DEBRIS_VASUDAN_SMALL:
848         case DEBRIS_VASUDAN_MEDIUM:
849         case DEBRIS_VASUDAN_LARGE:
850                 strcpy(hud_name, NOX("vasudan debris"));
851                 break;
852
853         case DEBRIS_SHIVAN_SMALL:
854         case DEBRIS_SHIVAN_MEDIUM:
855         case DEBRIS_SHIVAN_LARGE:
856                 strcpy(hud_name, NOX("shivan debris"));
857                 break;
858
859         default:
860                 Int3();
861         }
862
863         emp_hud_printf(Targetbox_coords[gr_screen.res][TBOX_NAME][0], Targetbox_coords[gr_screen.res][TBOX_NAME][1], EG_TBOX_NAME, hud_name);   
864         
865         time_to_impact = asteroid_time_to_impact(target_objp);
866         if ( time_to_impact >= 0 ) {
867                 emp_hud_printf(Targetbox_coords[gr_screen.res][TBOX_CLASS][0], Targetbox_coords[gr_screen.res][TBOX_CLASS][1], EG_TBOX_CLASS, NOX("impact: %.1f sec"), time_to_impact); 
868         }
869 #endif
870 }
871
872 void get_turret_subsys_name(model_subsystem *system_info, char *outstr)
873 {
874         Assert(system_info->type == SUBSYSTEM_TURRET);
875
876         if (system_info->turret_weapon_type >= 0) {
877                 // check if beam or flak using weapon flags
878                 if (Weapon_info[system_info->turret_weapon_type].wi_flags & WIF_FLAK) {
879                         sprintf(outstr, "%s", XSTR("Flak turret", 1566));
880                 } else if (Weapon_info[system_info->turret_weapon_type].wi_flags & WIF_BEAM) {
881                         sprintf(outstr, "%s", XSTR("Beam turret", 1567));
882                 } else {
883
884                         if (Weapon_info[system_info->turret_weapon_type].subtype == WP_LASER) {
885                                 sprintf(outstr, "%s", XSTR("Laser turret", 1568));
886                         } else if (Weapon_info[system_info->turret_weapon_type].subtype == WP_MISSILE) {
887                                 sprintf(outstr, "%s", XSTR("Missile lnchr", 1569));
888                         } else {
889                                 // Illegal subtype
890                                 Int3();
891                                 sprintf(outstr, "%s", NOX("Turret"));
892                         }
893                 }
894         } else {
895                 // This should not happen
896                 sprintf(outstr, "%s", NOX("Unused"));
897         }
898 }
899
900 // -------------------------------------------------------------------------------------
901 // hud_render_target_ship_info()
902 //
903 // Render the data for a ship on the target monitor.  Called by hud_render_target_ship().
904 //
905 void hud_render_target_ship_info(object *target_objp)
906 {
907         ship                    *target_shipp;
908         ship_info       *target_sip;
909         ai_info         *target_aip;
910         int                     w,h,screen_integrity=1, base_index;
911         char                    outstr[256];
912         float                   ship_integrity, shield_strength;
913
914         Assert(target_objp->type == OBJ_SHIP);
915         target_shipp = &Ships[target_objp->instance];
916         target_sip = &Ship_info[target_shipp->ship_info_index];
917         target_aip = &Ai_info[target_shipp->ai_index];
918
919         strcpy( outstr, target_shipp->ship_name );
920
921         if ( hud_gauge_maybe_flash(HUD_TARGET_MONITOR) == 1 ) {
922                 hud_set_iff_color(target_objp, 1);
923         } else {
924                 // Print out ship name, with wing name if it exists
925                 if ( hud_targetbox_maybe_flash(TBOX_FLASH_NAME) ) {
926                         hud_set_iff_color(target_objp, 1);
927                 } else {
928                         hud_set_iff_color(target_objp);
929                 }
930         }
931
932         // take ship "copies" into account before printing ship class name.
933         base_index = target_shipp->ship_info_index;
934         if ( target_sip->flags & SIF_SHIP_COPY )
935                 base_index = ship_info_base_lookup( target_shipp->ship_info_index );
936
937         // maybe do some translation
938         if (Lcl_gr) {
939                 lcl_translate_targetbox_name(outstr);
940         }
941         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_NAME][0], Targetbox_coords[gr_screen.res][TBOX_NAME][1], EG_TBOX_NAME, outstr);     
942
943         // print out ship class
944         char temp_name[NAME_LENGTH+2] = "";
945
946         // if this ship has an alternate type name
947         if(target_shipp->alt_type_index >= 0){
948                 mission_parse_lookup_alt_index(target_shipp->alt_type_index, temp_name);
949         } else {
950                 strcpy(temp_name, Ship_info[base_index].name);  
951                 if ( strstr(Ship_info[base_index].name, NOX("#")) ) {                   
952                         strcpy(temp_name, Ship_info[base_index].name);
953                         hud_end_string_at_first_hash_symbol(temp_name);                 
954                 }       
955         }
956
957         if (Lcl_gr) {
958                 lcl_translate_targetbox_name(temp_name);
959         }
960         emp_hud_printf(Targetbox_coords[gr_screen.res][TBOX_CLASS][0], Targetbox_coords[gr_screen.res][TBOX_CLASS][1], EG_TBOX_CLASS, temp_name);
961
962         ship_integrity = 1.0f;
963         hud_get_target_strength(target_objp, &shield_strength, &ship_integrity);
964
965         // convert to values of 0->100
966         shield_strength *= 100.0f;
967         ship_integrity *= 100.0f;
968
969         screen_integrity = fl2i(ship_integrity+0.5f);
970         if ( screen_integrity == 0 ) {
971                 if ( ship_integrity > 0 ) {
972                         screen_integrity = 1;
973                 }
974         }
975         // Print out right-justified integrity
976         sprintf(outstr,XSTR( "%d%%", 341), screen_integrity);
977         gr_get_string_size(&w,&h,outstr);
978
979         if ( hud_gauge_maybe_flash(HUD_TARGET_MONITOR) == 1 ) {
980                 // hud_set_bright_color();
981                 hud_set_gauge_color(HUD_TARGET_MONITOR, HUD_C_BRIGHT);
982         } else {
983                 hud_targetbox_maybe_flash(TBOX_FLASH_HULL);
984         }
985
986         emp_hud_printf(Targetbox_coords[gr_screen.res][TBOX_HULL][0]-w, Targetbox_coords[gr_screen.res][TBOX_HULL][1], EG_TBOX_HULL, "%s", outstr);     
987         hud_set_gauge_color(HUD_TARGET_MONITOR);
988
989         // print out the targeted sub-system and % integrity
990         if (Player_ai->targeted_subsys != NULL) {
991                 shield_strength = Player_ai->targeted_subsys->current_hits/Player_ai->targeted_subsys->system_info->max_hits *100.0f;
992                 screen_integrity = fl2i(shield_strength+0.5f);
993
994                 if ( screen_integrity < 0 ) {
995                         screen_integrity = 0;
996                 }
997
998                 if ( screen_integrity == 0 ) {
999                         if ( shield_strength > 0 ) {
1000                                 screen_integrity = 1;
1001                         }
1002                 }
1003
1004                 if ( screen_integrity <= 0 ){
1005                         hud_targetbox_start_flash(TBOX_FLASH_SUBSYS);   // need to flash 0% continuously
1006                         hud_targetbox_maybe_flash(TBOX_FLASH_SUBSYS);
1007                 }
1008
1009                 // PRINT SUBSYS NAME
1010                 // hud_set_default_color();
1011                 // get turret subsys name
1012                 if (Player_ai->targeted_subsys->system_info->type == SUBSYSTEM_TURRET) {
1013                         get_turret_subsys_name(Player_ai->targeted_subsys->system_info, outstr);
1014                 } else {
1015                         sprintf(outstr, "%s", Player_ai->targeted_subsys->system_info->name);
1016                 }
1017                 hud_targetbox_truncate_subsys_name(outstr);
1018                 gr_printf(Target_window_coords[gr_screen.res][0]+2, Target_window_coords[gr_screen.res][1]+Target_window_coords[gr_screen.res][3]-h, outstr);
1019
1020                 // AL 23-3-98: Fighter bays are a special case.  Player cannot destroy them, so don't
1021                 //                                      show the subsystem strength
1022                 if ( strnicmp(NOX("fighter"), Player_ai->targeted_subsys->system_info->name, 7) ) {
1023                         sprintf(outstr,XSTR( "%d%%", 341),screen_integrity);
1024                         gr_get_string_size(&w,&h,outstr);
1025                         gr_printf(Target_window_coords[gr_screen.res][0]+Target_window_coords[gr_screen.res][2]-w-1, Target_window_coords[gr_screen.res][1]+Target_window_coords[gr_screen.res][3] - h, "%s", outstr);
1026                 }
1027
1028                 hud_set_gauge_color(HUD_TARGET_MONITOR);
1029         }
1030
1031         // print out 'disabled' on the monitor if the target is disabled
1032         if ( (target_shipp->flags & SF_DISABLED) || (ship_subsys_disrupted(target_shipp, SUBSYSTEM_ENGINE)) ) {
1033                 if ( target_shipp->flags & SF_DISABLED ) {
1034                         sprintf(outstr, XSTR( "DISABLED", 342));
1035                 } else {
1036                         sprintf(outstr, XSTR( "DISRUPTED", 343));
1037                 }
1038                 gr_get_string_size(&w,&h,outstr);
1039                 gr_printf(Target_window_coords[gr_screen.res][0]+Target_window_coords[gr_screen.res][2]/2 - w/2 - 1, Target_window_coords[gr_screen.res][1]+Target_window_coords[gr_screen.res][3] - 2*h, "%s", outstr);
1040         }
1041
1042         hud_targetbox_show_extra_ship_info(target_shipp, target_aip);
1043 }
1044
1045 // call to draw the integrity bar that is on the right of the target monitor
1046 void hud_blit_target_integrity(int disabled,int force_obj_num)
1047 {
1048         object  *objp;
1049         int             clip_h,w,h;
1050         char            buf[16];
1051         int             current_ts;
1052
1053         if ( Target_view_integrity_gauge.first_frame == -1 ) 
1054                 return;
1055
1056         if ( disabled ) {
1057                 GR_AABITMAP(Target_view_integrity_gauge.first_frame, Integrity_bar_coords[gr_screen.res][0], Integrity_bar_coords[gr_screen.res][1]);
1058                 return;
1059         }
1060
1061         if(force_obj_num == -1){
1062                 Assert(Player_ai->target_objnum >= 0 );
1063                 objp = &Objects[Player_ai->target_objnum];
1064         } else {
1065                 objp = &Objects[Player_ai->target_objnum];
1066         }
1067
1068         clip_h = fl2i( (1 - Pl_target_integrity) * Integrity_bar_coords[gr_screen.res][3] );
1069
1070         // print out status of ship
1071         if ( (Ships[objp->instance].flags & SF_DISABLED) || (ship_subsys_disrupted(&Ships[objp->instance], SUBSYSTEM_ENGINE)) ) {
1072                 sprintf(buf,XSTR( "dis", 344));
1073                 current_ts = TS_DIS;
1074         } else {
1075                 if ( Pl_target_integrity > 0.9 ) {
1076                         sprintf(buf,XSTR( "ok", 345));
1077                         current_ts = TS_OK;
1078                 } else if ( Pl_target_integrity > 0.2 ) {
1079                         sprintf(buf,XSTR( "dmg", 346));
1080                         current_ts = TS_DMG;
1081                 } else {
1082                         sprintf(buf,XSTR( "crt", 347));
1083                         current_ts = TS_CRT;
1084                 }
1085         }
1086
1087         if ( Last_ts != -1 && current_ts != Last_ts ) {
1088                 hud_targetbox_start_flash(TBOX_FLASH_STATUS);
1089         }
1090         Last_ts = current_ts;
1091
1092         hud_targetbox_maybe_flash(TBOX_FLASH_STATUS);
1093         
1094         emp_hud_string(Integrity_string_coords[gr_screen.res][0], Integrity_string_coords[gr_screen.res][1], EG_TBOX_INTEG, buf);       
1095
1096         hud_set_gauge_color(HUD_TARGET_MONITOR);
1097
1098         bm_get_info(Target_view_integrity_gauge.first_frame,&w,&h);
1099         
1100         if ( clip_h > 0 ) {
1101                 // draw the dark portion
1102                 GR_AABITMAP_EX(Target_view_integrity_gauge.first_frame, Integrity_bar_coords[gr_screen.res][0], Integrity_bar_coords[gr_screen.res][1], w, clip_h,0,0);         
1103         }
1104
1105         if ( clip_h <= Integrity_bar_coords[gr_screen.res][3] ) {
1106                 // draw the bright portion
1107                 GR_AABITMAP_EX(Target_view_integrity_gauge.first_frame+1, Integrity_bar_coords[gr_screen.res][0], Integrity_bar_coords[gr_screen.res][1]+clip_h,w,h-clip_h,0,clip_h);           
1108         }
1109 }
1110
1111 // determine if the subsystem is in line-of sight, without taking into accout whether the player ship is
1112 // facing the subsystem
1113 int hud_targetbox_subsystem_in_view(object *target_objp, int *sx, int *sy)
1114 {
1115         ship_subsys     *subsys;
1116         vector          subobj_pos;
1117         vertex          subobj_vertex;
1118         int                     rval = -1;
1119         polymodel       *pm;
1120
1121         subsys = Player_ai->targeted_subsys;
1122         if (subsys != NULL ) {
1123                 vm_vec_unrotate(&subobj_pos, &subsys->system_info->pnt, &target_objp->orient);
1124                 vm_vec_add2(&subobj_pos, &target_objp->pos);
1125
1126                 // is it subsystem in view
1127                 if ( Player->subsys_in_view == -1 ) {
1128                         rval = ship_subsystem_in_sight(target_objp, subsys, &View_position, &subobj_pos, 0);
1129                 } else {
1130                         rval =  Player->subsys_in_view;
1131                 }
1132
1133                 // get screen coords, adjusting for autocenter
1134                 Assert(target_objp->type == OBJ_SHIP);
1135                 if (target_objp->type == OBJ_SHIP) {
1136                         pm = model_get(Ships[target_objp->instance].modelnum);
1137                         if (pm->flags & PM_FLAG_AUTOCEN) {
1138                                 vector temp, delta;
1139                                 vm_vec_copy_scale(&temp, &pm->autocenter, -1.0f);
1140                                 vm_vec_unrotate(&delta, &temp, &target_objp->orient);
1141                                 vm_vec_add2(&subobj_pos, &delta);
1142                         }
1143                 }
1144
1145                 g3_rotate_vertex(&subobj_vertex, &subobj_pos);
1146                 g3_project_vertex(&subobj_vertex);
1147                 *sx = (int) subobj_vertex.sx;
1148                 *sy = (int) subobj_vertex.sy;
1149         }
1150
1151         return rval;
1152 }
1153
1154 void hud_update_cargo_scan_sound()
1155 {
1156         if ( Player->cargo_inspect_time <= 0  ) {
1157                 player_stop_cargo_scan_sound();
1158                 return;
1159         }
1160         player_maybe_start_cargo_scan_sound();
1161
1162 }
1163
1164 // If the player is scanning for cargo, draw some cool scanning lines on the target monitor
1165 void hud_maybe_render_cargo_scan(ship_info *target_sip)
1166 {
1167         int x1, y1, x2, y2;
1168         int scan_time;                          // time required to scan ship
1169
1170         if ( Player->cargo_inspect_time <= 0  ) {
1171                 return;
1172         }
1173
1174         scan_time = target_sip->scan_time;
1175         // hud_set_default_color();
1176         hud_set_gauge_color(HUD_TARGET_MONITOR, HUD_C_BRIGHT);
1177
1178         // draw horizontal scan line
1179         x1 = Cargo_scan_coords[gr_screen.res][0];
1180         y1 = fl2i(0.5f + Cargo_scan_coords[gr_screen.res][1] + ( (i2fl(Player->cargo_inspect_time) / scan_time) * Cargo_scan_coords[gr_screen.res][3] ));
1181         x2 = x1 + Cargo_scan_coords[gr_screen.res][2];
1182
1183         gr_line(x1, y1, x2, y1);
1184
1185         // draw vertical scan line
1186         x1 = fl2i(0.5f + Cargo_scan_coords[gr_screen.res][0] + ( (i2fl(Player->cargo_inspect_time) / scan_time) * Cargo_scan_coords[gr_screen.res][2] ));
1187         y1 = Cargo_scan_coords[gr_screen.res][1];
1188         y2 = y1 + Cargo_scan_coords[gr_screen.res][3];
1189
1190         gr_line(x1, y1-3, x1, y2-1);
1191 }
1192
1193 // Get the eye position for an object at the origin, called from hud_render_target_ship()
1194 // input:       eye_pos         =>      Global pos for eye (output parameter)
1195 //                      orient          =>      Orientation of object at the origin
1196 void hud_targetbox_get_eye(vector *eye_pos, matrix *orient, int ship_num)
1197 {
1198         ship            *shipp;
1199         polymodel       *pm;
1200         eye                     *ep;
1201         vector          origin = {0.0f, 0.0f, 0.0f};
1202
1203         shipp = &Ships[ship_num];
1204         pm = model_get( shipp->modelnum );
1205
1206         // If there is no eye, don't do anything
1207         if ( pm->n_view_positions == 0 ) {
1208                 return;
1209         }
1210
1211         ep = &(pm->view_positions[0] );
1212
1213         model_find_world_point( eye_pos, &ep->pnt, shipp->modelnum, ep->parent, orient, &origin );
1214 }
1215
1216 // -------------------------------------------------------------------------------------
1217 // hud_render_target_ship()
1218 //
1219 // Render a ship to the target monitor
1220 //
1221 void hud_render_target_ship(object *target_objp)
1222 {
1223         vector          obj_pos = {0.0f,0.0f,0.0f};
1224         vector          camera_eye = {0.0f,0.0f,0.0f};
1225         matrix          camera_orient = IDENTITY_MATRIX;
1226         ship            *target_shipp;
1227         ship_info       *target_sip;
1228         vector          orient_vec, up_vector;
1229         int                     sx, sy;
1230         int                     subsys_in_view;
1231         float           factor;
1232         
1233         target_shipp    = &Ships[target_objp->instance];
1234         target_sip              = &Ship_info[target_shipp->ship_info_index];
1235
1236         if ( Detail.targetview_model )  {
1237                 // take the forward orientation to be the vector from the player to the current target
1238                 vm_vec_sub(&orient_vec, &target_objp->pos, &Player_obj->pos);
1239                 vm_vec_normalize(&orient_vec);
1240
1241                 factor = -target_sip->closeup_pos.xyz.z;
1242
1243                 // use the player's up vector, and construct the viewers orientation matrix
1244                 up_vector = Player_obj->orient.v.uvec;
1245                 vm_vector_2_matrix(&camera_orient,&orient_vec,&up_vector,NULL);
1246
1247                 // normalize the vector from the player to the current target, and scale by a factor to calculate
1248                 // the objects position
1249                 vm_vec_copy_scale(&obj_pos,&orient_vec,factor);
1250
1251                 // set camera eye to eye of ship relative to origin
1252         //      hud_targetbox_get_eye(&camera_eye, &camera_orient, Player_obj->instance);
1253
1254                 hud_render_target_setup(&camera_eye, &camera_orient, target_sip->closeup_zoom);
1255                 // model_clear_instance(target_sip->modelnum);
1256                 ship_model_start( target_objp );
1257
1258                 // maybe render a special hud-target-only model
1259                 if(target_sip->modelnum_hud >= 0){
1260                         model_render( target_sip->modelnum_hud, &target_objp->orient, &obj_pos, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER);
1261                 } else {
1262                         model_render( target_sip->modelnum, &target_objp->orient, &obj_pos, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER);
1263                 }
1264                 ship_model_stop( target_objp );
1265
1266                 sx = 0;
1267                 sy = 0;
1268                 // check if subsystem target has changed
1269                 if ( Player_ai->targeted_subsys == Player_ai->last_subsys_target ) {
1270                         vector save_pos;
1271                         save_pos = target_objp->pos;
1272                         target_objp->pos = obj_pos;
1273                         subsys_in_view = hud_targetbox_subsystem_in_view(target_objp, &sx, &sy);
1274                         target_objp->pos = save_pos;
1275
1276                         if ( subsys_in_view != -1 ) {
1277
1278                                 // AL 29-3-98: If subsystem is destroyed, draw gray brackets                                    
1279                                 if ( (Player_ai->targeted_subsys->current_hits <= 0) && (strnicmp(NOX("fighter"), Player_ai->targeted_subsys->system_info->name, 7)) ) {
1280                                         gr_set_color_fast(&IFF_colors[IFF_COLOR_MESSAGE][1]);
1281                                 } else {
1282                                         hud_set_iff_color( target_objp, 1 );
1283                                 }
1284
1285                                 if ( subsys_in_view ) {
1286                                         draw_brackets_square_quick(sx - 10, sy - 10, sx + 10, sy + 10);
1287                                 } else {
1288                                         draw_brackets_diamond_quick(sx - 10, sy - 10, sx + 10, sy + 10);
1289                                 }
1290                         }
1291                 }
1292                 hud_render_target_close();
1293         }
1294         HUD_reset_clip();
1295         hud_blit_target_foreground();
1296         hud_blit_target_integrity(0,OBJ_INDEX(target_objp));
1297
1298         hud_render_target_ship_info(target_objp);
1299         hud_maybe_render_cargo_scan(target_sip);
1300 }
1301
1302 // -------------------------------------------------------------------------------------
1303 // hud_render_target_debris()
1304 //
1305 // Render a piece of debris on the target monitor
1306 //
1307 void hud_render_target_debris(object *target_objp)
1308 {
1309         vector  obj_pos = {0.0f,0.0f,0.0f};
1310         vector  camera_eye = {0.0f,0.0f,0.0f};
1311         matrix  camera_orient = IDENTITY_MATRIX;
1312         debris  *debrisp;
1313         vector  orient_vec, up_vector;
1314         int             target_team, base_index;
1315         float           factor; 
1316
1317         debrisp = &Debris[target_objp->instance];
1318
1319         //target_sip = &Ship_info[debrisp->ship_info_index];
1320         target_team = obj_team(target_objp);
1321
1322
1323         if ( Detail.targetview_model )  {
1324                 // take the forward orientation to be the vector from the player to the current target
1325                 vm_vec_sub(&orient_vec, &target_objp->pos, &Player_obj->pos);
1326                 vm_vec_normalize(&orient_vec);
1327
1328                 factor = 2*target_objp->radius;
1329
1330                 // use the player's up vector, and construct the viewers orientation matrix
1331                 up_vector = Player_obj->orient.v.uvec;
1332                 vm_vector_2_matrix(&camera_orient,&orient_vec,&up_vector,NULL);
1333
1334                 // normalize the vector from the player to the current target, and scale by a factor to calculate
1335                 // the objects position
1336                 vm_vec_copy_scale(&obj_pos,&orient_vec,factor);
1337
1338                 hud_render_target_setup(&camera_eye, &camera_orient, 0.5f);
1339                 model_clear_instance(debrisp->model_num);
1340                 submodel_render( debrisp->model_num, debrisp->submodel_num, &target_objp->orient, &obj_pos, MR_NO_LIGHTING | MR_LOCK_DETAIL );
1341                 hud_render_target_close();
1342         }
1343
1344         HUD_reset_clip();
1345         hud_blit_target_foreground();
1346         hud_blit_target_integrity(1);
1347         // hud_set_default_color();
1348         hud_set_gauge_color(HUD_TARGET_MONITOR);
1349
1350         // take ship "copies" into account before printing out ship class information
1351         base_index = debrisp->ship_info_index;
1352         if ( Ship_info[base_index].flags & SIF_SHIP_COPY )
1353                 base_index = ship_info_base_lookup( debrisp->ship_info_index );
1354
1355         // print out ship class that debris came from
1356         char *printable_ship_class = Ship_info[base_index].name;
1357         if ( strstr(Ship_info[base_index].name, NOX("#")) ) {
1358                 char temp_name[NAME_LENGTH];
1359                 strcpy(temp_name, Ship_info[base_index].name);
1360                 hud_end_string_at_first_hash_symbol(temp_name);
1361                 printable_ship_class = temp_name;
1362         }
1363
1364         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_CLASS][0], Targetbox_coords[gr_screen.res][TBOX_CLASS][1], EG_TBOX_CLASS, printable_ship_class);    
1365         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_NAME][0], Targetbox_coords[gr_screen.res][TBOX_NAME][1], EG_TBOX_NAME, XSTR( "debris", 348));       
1366 }
1367
1368 // -------------------------------------------------------------------------------------
1369 // hud_render_target_weapon()
1370 //
1371 // Render a missile or a missile view to the target monitor
1372 //
1373 void hud_render_target_weapon(object *target_objp)
1374 {
1375         vector          obj_pos = {0.0f,0.0f,0.0f};
1376         vector          camera_eye = {0.0f,0.0f,0.0f};
1377         matrix          camera_orient = IDENTITY_MATRIX;
1378         vector          orient_vec, up_vector;
1379         weapon_info     *target_wip = NULL;
1380         weapon          *wp = NULL;
1381         object          *viewer_obj, *viewed_obj;
1382         int                     target_team, is_homing, is_player_missile, missile_view, viewed_model_num, w, h;
1383         float                   factor;
1384         char                    outstr[100];                            // temp buffer
1385
1386         target_team = obj_team(target_objp);
1387
1388         wp = &Weapons[target_objp->instance];
1389         target_wip = &Weapon_info[wp->weapon_info_index];
1390
1391         is_homing = FALSE;
1392         if ( target_wip->wi_flags & WIF_HOMING && wp->homing_object != &obj_used_list )
1393                 is_homing = TRUE;
1394
1395         is_player_missile = FALSE;
1396         if ( target_objp->parent_sig == Player_obj->signature ) {
1397                 is_player_missile = TRUE;
1398         }
1399
1400         if ( Detail.targetview_model )  {
1401
1402                 viewer_obj                      = Player_obj;
1403                 viewed_obj                      = target_objp;
1404                 missile_view            = FALSE;
1405                 viewed_model_num        = target_wip->model_num;
1406                 if ( is_homing && is_player_missile ) {
1407                         viewer_obj                      = target_objp;
1408                         viewed_obj                      = wp->homing_object;
1409                         missile_view            = TRUE;
1410                         viewed_model_num        = Ships[wp->homing_object->instance].modelnum;
1411                 }
1412
1413                 // take the forward orientation to be the vector from the player to the current target
1414                 vm_vec_sub(&orient_vec, &viewed_obj->pos, &viewer_obj->pos);
1415                 vm_vec_normalize(&orient_vec);
1416
1417                 if ( missile_view == FALSE )
1418                         factor = 2*target_objp->radius;
1419                 else
1420                         factor = vm_vec_dist_quick(&viewer_obj->pos, &viewed_obj->pos);
1421
1422                 // use the viewer's up vector, and construct the viewers orientation matrix
1423                 up_vector = viewer_obj->orient.v.uvec;
1424                 vm_vector_2_matrix(&camera_orient,&orient_vec,&up_vector,NULL);
1425
1426                 // normalize the vector from the viewer to the viwed target, and scale by a factor to calculate
1427                 // the objects position
1428                 vm_vec_copy_scale(&obj_pos,&orient_vec,factor);
1429
1430                 hud_render_target_setup(&camera_eye, &camera_orient, View_zoom/3);
1431                 model_clear_instance(viewed_model_num);
1432                 model_render( viewed_model_num, &viewed_obj->orient, &obj_pos, MR_NO_LIGHTING | MR_LOCK_DETAIL );
1433                 hud_render_target_close();
1434         }
1435
1436         HUD_reset_clip();
1437         if ( is_homing == TRUE ) {
1438                 hud_blit_target_foreground();
1439         } else {
1440                 hud_blit_target_foreground();
1441         }
1442
1443         hud_blit_target_integrity(1);
1444         // hud_set_default_color();
1445         hud_set_gauge_color(HUD_TARGET_MONITOR);
1446
1447         // print out the weapon class name
1448         sprintf( outstr,"%s", target_wip->name );
1449         gr_get_string_size(&w,&h,outstr);
1450
1451         // drop name past the # sign
1452         if ( strstr(outstr, NOX("#")) ) {                       
1453                 hud_end_string_at_first_hash_symbol(outstr);                    
1454         }
1455         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_NAME][0], Targetbox_coords[gr_screen.res][TBOX_NAME][1], EG_TBOX_NAME, outstr);     
1456
1457         // If a homing weapon, show time to impact
1458         if ( is_homing ) {
1459                 float dist, speed;
1460
1461                 dist = vm_vec_dist(&target_objp->pos, &wp->homing_object->pos);
1462                 speed = vm_vec_mag(&target_objp->phys_info.vel);
1463                 if ( speed > 0 ) {
1464                         sprintf(outstr, NOX("impact: %.1f sec"), dist/speed);
1465                 } else {
1466                         sprintf(outstr, XSTR( "unknown", 349));
1467                 }
1468
1469                 emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_CLASS][0], Targetbox_coords[gr_screen.res][TBOX_CLASS][1], EG_TBOX_CLASS, outstr);          
1470         }
1471 }
1472
1473 // -------------------------------------------------------------------------------------
1474 // hud_render_target_model() will render the target in the small targetting box.  The box
1475 // is then shaded to give a monochrome effect
1476 //
1477 void hud_render_target_model()
1478 {
1479         object  *target_objp;
1480
1481         if ( !hud_gauge_active(HUD_TARGET_MONITOR) )
1482                 return;
1483
1484         if ( Player_ai->target_objnum == -1)
1485                 return;
1486
1487         if ( Target_static_playing ) 
1488                 return;
1489
1490         target_objp = &Objects[Player_ai->target_objnum];
1491
1492         // Draw the background frame
1493         hud_render_target_background();
1494
1495         switch ( target_objp->type ) {
1496                 case OBJ_SHIP:
1497                         hud_render_target_ship(target_objp);
1498                         break;
1499         
1500                 case OBJ_DEBRIS:
1501                         hud_render_target_debris(target_objp);
1502                         break;
1503
1504                 case OBJ_WEAPON:
1505                         hud_render_target_weapon(target_objp);
1506                         break;
1507
1508                 case OBJ_ASTEROID:
1509                         hud_render_target_asteroid(target_objp);
1510                         break;
1511
1512                 case OBJ_JUMP_NODE:
1513                         hud_render_target_jump_node(target_objp);
1514                         break;
1515
1516                 default:
1517                         // Error(LOCATION, "Trying to show object type %d on target monitor\n", target_objp->type);
1518                         hud_cease_targeting();
1519                         break;
1520         } // end switch
1521 }
1522
1523 void hud_cargo_scan_update(object *targetp, float frametime)
1524 {
1525         char outstr[256];                                               // temp buffer for sprintf'ing hud output
1526         int hx, hy;
1527
1528         // Account for HUD shaking
1529         hx = fl2i(HUD_offset_x);
1530         hy = fl2i(HUD_offset_y);
1531
1532         // display cargo inspection status
1533         if ( targetp->type == OBJ_SHIP ) {
1534                 if ( player_inspect_cargo(frametime, outstr) ) {
1535                         if ( hud_gauge_active(HUD_TARGET_MONITOR) ) {
1536                                 if ( Player->cargo_inspect_time > 0 ) {
1537                                         hud_targetbox_start_flash(TBOX_FLASH_CARGO);
1538                                 }
1539
1540                                 // Print out what the cargo is
1541                                 if ( hud_gauge_maybe_flash(HUD_TARGET_MONITOR) == 1 ) {
1542                                         // hud_set_bright_color();
1543                                         hud_set_gauge_color(HUD_TARGET_MONITOR, HUD_C_BRIGHT);
1544                                 } else {
1545                                         hud_targetbox_maybe_flash(TBOX_FLASH_CARGO);
1546                                 }
1547
1548                                 emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_CARGO][0]+hx, Targetbox_coords[gr_screen.res][TBOX_CARGO][1]+hy, EG_TBOX_CARGO, outstr);                            
1549                                 hud_set_gauge_color(HUD_TARGET_MONITOR);
1550                         }
1551                 }
1552         }       // end if (is_ship)
1553
1554 }
1555
1556 // -----------------------------------------------------------------------------------
1557 // hud_show_target_data() will display the data about the target in and
1558 // around the targetting window
1559 //
1560 void hud_show_target_data(float frametime)
1561 {
1562         char outstr[256];                                               // temp buffer for sprintf'ing hud output
1563         int w,h;                                                                        // width and height of string about to print
1564         object          *target_objp;
1565         ship                    *shipp = NULL;
1566         debris          *debrisp = NULL;
1567         ship_info       *sip = NULL;
1568         int is_ship = 0;
1569
1570         hud_set_gauge_color(HUD_TARGET_MONITOR);
1571
1572         target_objp = &Objects[Player_ai->target_objnum];
1573
1574         switch( Objects[Player_ai->target_objnum].type ) {
1575                 case OBJ_SHIP:
1576                         shipp = &Ships[target_objp->instance];
1577                         sip = &Ship_info[shipp->ship_info_index];
1578                         is_ship = 1;
1579                         break;
1580
1581                 case OBJ_DEBRIS:
1582                         debrisp = &Debris[target_objp->instance]; 
1583                         sip = &Ship_info[debrisp->ship_info_index];
1584                         break;
1585
1586                 case OBJ_WEAPON:
1587                         sip = NULL;
1588                         break;
1589
1590                 case OBJ_ASTEROID:
1591                         sip = NULL;
1592                         break;
1593
1594                 case OBJ_JUMP_NODE:
1595                         return;
1596
1597                 default:
1598                         Int3(); // can't happen
1599                         break;
1600         }
1601
1602         int hx, hy;
1603
1604         // Account for HUD shaking
1605         hx = fl2i(HUD_offset_x);
1606         hy = fl2i(HUD_offset_y);
1607
1608         // print out the target distance and speed
1609         sprintf(outstr,XSTR( "d: %.0f%s", 350), Player_ai->current_target_distance, modifiers[Player_ai->current_target_dist_trend]);
1610
1611         hud_num_make_mono(outstr);
1612         gr_get_string_size(&w,&h,outstr);
1613
1614         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_DIST][0]+hx, Targetbox_coords[gr_screen.res][TBOX_DIST][1]+hy, EG_TBOX_DIST, outstr);       
1615
1616         float spd;
1617 #if 0
1618         spd = vm_vec_dist(&target_objp->pos, &target_objp->last_pos) / frametime;
1619 #endif
1620         // 7/28/99 DKA: Do not use vec_mag_quick -- the error is too big
1621         spd = vm_vec_mag(&target_objp->phys_info.vel);
1622 //      spd = target_objp->phys_info.fspeed;
1623         if ( spd < 0.1 ) {
1624                 spd = 0.0f;
1625         }
1626         // if the speed is 0, determine if we are docked with something -- if so, get the velocity from
1627         // our docked object instead
1628         if ( (spd == 0.0f) && is_ship ) {
1629                 ai_info *aip;
1630                 object *other_objp;
1631
1632                 aip = &Ai_info[shipp->ai_index];
1633                 if ( aip->ai_flags & AIF_DOCKED ) {
1634                         Assert( aip->dock_objnum != -1 );
1635                         other_objp = &Objects[aip->dock_objnum];
1636                         spd = other_objp->phys_info.fspeed;
1637                         if ( spd < 0.1 )
1638                                 spd = 0.0f;
1639                 }
1640         }
1641
1642         sprintf(outstr, XSTR( "s: %.0f%s", 351), spd, (spd>1)?modifiers[Player_ai->current_target_speed_trend]:"");
1643         hud_num_make_mono(outstr);
1644
1645         emp_hud_string(Targetbox_coords[gr_screen.res][TBOX_SPEED][0]+hx, Targetbox_coords[gr_screen.res][TBOX_SPEED][1]+hy, EG_TBOX_SPEED, outstr);    
1646
1647         //
1648         // output target info for debug purposes only, this will be removed later
1649         //
1650
1651 #ifndef NDEBUG
1652         //XSTR:OFF
1653         char outstr2[256];      
1654         if ( Show_target_debug_info && (is_ship == 1) ) {
1655                 int sx, sy, dy;
1656                 sx = 5;
1657                 dy = gr_get_font_height() + 1;
1658                 sy = 300 - 7*dy;
1659
1660                 gr_set_color_fast(&HUD_color_debug);
1661
1662                 if ( shipp->ai_index >= 0 ) {
1663                         ai_info *aip = &Ai_info[shipp->ai_index];
1664
1665                         sprintf(outstr,"AI: %s",Ai_behavior_names[aip->mode]);
1666
1667                         switch (aip->mode) {
1668                         case AIM_CHASE:
1669                                 Assert(aip->submode <= SM_BIG_PARALLEL);        //      Must be <= largest chase submode value.
1670 //                              sprintf(outstr,"AI: %s",Submode_text[aip->submode]);
1671                                 sprintf(outstr2," / %s",Submode_text[aip->submode]);
1672                                 strcat(outstr,outstr2);
1673                                 break;
1674                         case AIM_STRAFE:
1675                                 Assert(aip->submode <= AIS_STRAFE_POSITION);    //      Must be <= largest chase submode value.
1676 //                              sprintf(outstr,"AI: %s",Strafe_submode_text[aip->submode-AIS_STRAFE_ATTACK]);
1677                                 sprintf(outstr2," / %s",Strafe_submode_text[aip->submode-AIS_STRAFE_ATTACK]);
1678                                 strcat(outstr,outstr2);
1679                                 break;
1680                         case AIM_WAYPOINTS:
1681 //                              gr_printf(sx, sy, "Wpnum: %i",aip->wp_index);
1682                                 sprintf(outstr2," / Wpnum: %i",aip->wp_index);
1683                                 strcat(outstr,outstr2);
1684                                 break;
1685                         default:
1686                                 break;
1687                         }
1688
1689                         gr_printf(sx, sy, outstr);
1690                         sy += dy;
1691
1692                         gr_printf(sx, sy, "Max speed = %d, (%d%%)", (int) shipp->current_max_speed, (int) (100.0f * vm_vec_mag(&target_objp->phys_info.vel)/shipp->current_max_speed));
1693                         sy += dy;
1694                         
1695                         // data can be found in target montior
1696                         // gr_printf(TARGET_WINDOW_X1+TARGET_WINDOW_WIDTH+3, TARGET_WINDOW_Y1+5*h, "Shields: %d", (int) Players[Player_num].current_target->shields);
1697                         if (aip->target_objnum != -1) {
1698                                 char    target_str[32];
1699                                 float   dot, dist;
1700                                 vector  v2t;
1701
1702                                 if (aip->target_objnum == Player_obj-Objects)
1703                                         strcpy(target_str, "Player!");
1704                                 else
1705                                         sprintf(target_str, "%s", Ships[Objects[aip->target_objnum].instance].ship_name);
1706
1707 //              gr_printf(TARGET_WINDOW_X1+TARGET_WINDOW_WIDTH+2, TARGET_WINDOW_Y1+4*h, "Target: %s", target_str);
1708                                 gr_printf(sx, sy, "Targ: %s", target_str);
1709                                 sy += dy;
1710
1711                                 dist = vm_vec_dist_quick(&Objects[Player_ai->target_objnum].pos, &Objects[aip->target_objnum].pos);
1712                                 vm_vec_normalized_dir(&v2t,&Objects[aip->target_objnum].pos, &Objects[Player_ai->target_objnum].pos);
1713
1714                                 dot = vm_vec_dot(&v2t, &Objects[Player_ai->target_objnum].orient.v.fvec);
1715
1716                                 // data can be found in target montior
1717                                 // gr_printf(TARGET_WINDOW_X1+TARGET_WINDOW_WIDTH+3, TARGET_WINDOW_Y1+6*h, "Targ dist: %5.1f", dist);
1718 //              gr_printf(TARGET_WINDOW_X1+TARGET_WINDOW_WIDTH+2, TARGET_WINDOW_Y1+5*h, "Targ dot: %3.2f", dot);
1719                                 gr_printf(sx, sy, "Targ dot: %3.2f", dot);
1720                                 sy += dy;
1721 //              gr_printf(TARGET_WINDOW_X1+TARGET_WINDOW_WIDTH+2, TARGET_WINDOW_Y1+6*h, "Targ dst: %3.2f", dist);
1722                                 gr_printf(sx, sy, "Targ dst: %3.2f", dist);
1723                                 sy += dy;
1724
1725                                 if ( aip->targeted_subsys != NULL ) {
1726                                         sprintf(outstr, "Subsys: %s", aip->targeted_subsys->system_info->name);
1727                                         gr_printf(sx, sy, outstr);
1728                                 }
1729                                 sy += dy;
1730                         }
1731
1732                         // print out energy transfer information on the ship
1733                         sy = 70;
1734
1735                         sprintf(outstr,"MAX G/E: %.0f/%.0f",shipp->weapon_energy,shipp->current_max_speed);
1736                         gr_printf(sx, sy, outstr);
1737                         sy += dy;
1738                          
1739                         sprintf(outstr,"G/S/E: %.2f/%.2f/%.2f",Energy_levels[shipp->weapon_recharge_index],Energy_levels[shipp->shield_recharge_index],Energy_levels[shipp->engine_recharge_index]);
1740                         gr_printf(sx, sy, outstr);
1741                         sy += dy;
1742
1743                         //      Show information about attacker.
1744                         {
1745                                 int     found = 0;
1746
1747                                 if (Enemy_attacker != NULL)
1748                                         if (Enemy_attacker->type == OBJ_SHIP) {
1749                                                 ship            *eshipp;
1750                                                 ai_info *eaip;
1751                                                 float           dot, dist;
1752                                                 vector  v2t;
1753
1754                                                 eshipp = &Ships[Enemy_attacker->instance];
1755                                                 eaip = &Ai_info[eshipp->ai_index];
1756
1757                                                 if (eaip->target_objnum == Player_obj-Objects) {
1758                                                         found = 1;
1759                                                         dist = vm_vec_dist_quick(&Enemy_attacker->pos, &Player_obj->pos);
1760                                                         vm_vec_normalized_dir(&v2t,&Objects[eaip->target_objnum].pos, &Enemy_attacker->pos);
1761
1762                                                         dot = vm_vec_dot(&v2t, &Enemy_attacker->orient.v.fvec);
1763
1764                                                         gr_printf(sx, sy, "#%i: %s", Enemy_attacker-Objects, Ships[Enemy_attacker->instance].ship_name);
1765                                                         sy += dy;
1766                                                         gr_printf(sx, sy, "Targ dist: %5.1f", dist);
1767                                                         sy += dy;
1768                                                         gr_printf(sx, sy, "Targ dot: %3.2f", dot);
1769                                                         sy += dy;
1770                                                 }
1771                                         }
1772
1773                                 if (Player_ai->target_objnum == Enemy_attacker - Objects)
1774                                         found = 0;
1775
1776                                 if (!found) {
1777                                         int     i;
1778
1779                                         Enemy_attacker = NULL;
1780                                         for (i=0; i<MAX_OBJECTS; i++)
1781                                                 if (Objects[i].type == OBJ_SHIP) {
1782                                                         int     enemy;
1783
1784                                                         if (i != Player_ai->target_objnum) {
1785                                                                 enemy = Ai_info[Ships[Objects[i].instance].ai_index].target_objnum;
1786
1787                                                                 if (enemy == Player_obj-Objects) {
1788                                                                         Enemy_attacker = &Objects[i];
1789                                                                         break;
1790                                                                 }
1791                                                         }
1792                                                 }
1793                                 }
1794                         }
1795
1796                         // Show target size
1797                         // hud_target_w
1798                         gr_printf(sx, sy, "Targ size: %dx%d", Hud_target_w, Hud_target_h );
1799                         sy += dy;
1800
1801                         polymodel *pm = model_get( shipp->modelnum );
1802                         gr_printf(sx, sy, "POF:%s", pm->filename );
1803                         sy += dy;
1804
1805                         gr_printf(sx, sy, "Mass: %.2f\n", pm->mass);
1806                         sy += dy;
1807                 }
1808         }
1809
1810         // display the weapons for the target on the HUD.  Include ammo counts.
1811         if ( Show_target_weapons && (is_ship == 1) ) {
1812                 int sx, sy, dy, i;
1813                 ship_weapon *swp;
1814
1815                 swp = &shipp->weapons;
1816                 sx = 400;
1817                 sy = 100;
1818                 dy = gr_get_font_height();
1819
1820                 sprintf(outstr,"Num primaries: %d", swp->num_primary_banks);
1821                 gr_printf(sx,sy,outstr);
1822                 sy += dy;
1823                 for ( i = 0; i < swp->num_primary_banks; i++ ) {
1824                         sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->primary_bank_weapons[i]].name);
1825                         gr_printf(sx,sy,outstr);
1826                         sy += dy;
1827                 }
1828
1829                 sy += dy;
1830                 sprintf(outstr,"Num secondaries: %d", swp->num_secondary_banks);
1831                 gr_printf(sx,sy,outstr);
1832                 sy += dy;
1833                 for ( i = 0; i < swp->num_secondary_banks; i++ ) {
1834                         sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->secondary_bank_weapons[i]].name);
1835                         gr_printf(sx,sy,outstr);
1836                         sy += dy;
1837                 }
1838         }
1839         //XSTR:ON
1840
1841 #endif
1842 }
1843
1844 // called at the start of each level
1845 void hud_targetbox_static_init()
1846 {
1847         Target_static_next = 0;;
1848         Target_static_playing = 0;
1849 }
1850
1851 // determine if we should draw static on top of the target box
1852 int hud_targetbox_static_maybe_blit(float frametime)
1853 {
1854         float   sensors_str;
1855
1856         // on lowest skill level, don't show static on target monitor
1857         if ( Game_skill_level == 0 )
1858                 return 0;
1859
1860         // if multiplayer observer, don't show static
1861         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
1862                 return 0;
1863         }
1864
1865         sensors_str = ship_get_subsystem_strength( Player_ship, SUBSYSTEM_SENSORS );
1866
1867         if ( ship_subsys_disrupted(Player_ship, SUBSYSTEM_SENSORS) ) {
1868                 sensors_str = SENSOR_STR_TARGET_NO_EFFECTS-1;
1869         }
1870
1871         if ( sensors_str > SENSOR_STR_TARGET_NO_EFFECTS ) {
1872                 Target_static_playing = 0;
1873                 Target_static_next = 0;
1874         } else {
1875                 if ( Target_static_next == 0 )
1876                         Target_static_next = 1;
1877         }
1878
1879         if ( timestamp_elapsed(Target_static_next) ) {
1880                 Target_static_playing ^= 1;
1881                 Target_static_next = timestamp_rand(50, 750);
1882         }
1883
1884         if ( Target_static_playing ) {
1885                 // hud_set_default_color();
1886                 hud_set_gauge_color(HUD_TARGET_MONITOR);
1887                 hud_anim_render(&Target_static, frametime, 1);
1888                 if ( Target_static_looping == -1 ) {
1889                         Target_static_looping = snd_play_looping(&Snds[SND_STATIC]);
1890                 }
1891         } else {
1892                 if ( Target_static_looping != -1 ) {
1893                         snd_stop(Target_static_looping);
1894                         Target_static_looping = -1;
1895                 }
1896         }
1897
1898         return Target_static_playing;
1899 }
1900
1901 // start the targetbox item flashing for duration ms
1902 // input:       index   =>      TBOX_FLASH_ #define
1903 //                              duration        =>      optional param (default value TBOX_FLASH_DURATION), how long to flash in ms
1904 void hud_targetbox_start_flash(int index, int duration)
1905 {
1906         Targetbox_flash_timers[index][0] = timestamp(duration);
1907 }
1908
1909 // stop flashing a specific targetbox item 
1910 void hud_targetbox_end_flash(int index)
1911 {
1912         Targetbox_flash_timers[index][0] = 1;
1913 }
1914
1915 // determine if a given flashing index is bright or not
1916 int hud_targetbox_is_bright(int index)
1917 {
1918         return (Targetbox_flash_flags & (1<<index));
1919 }
1920
1921 // determine if the flashing has expired
1922 int hud_targetbox_flash_expired(int index)
1923 {
1924         if ( timestamp_elapsed(Targetbox_flash_timers[index][0]) ) {
1925                 return 1;
1926         }
1927                                                                                                                                                 
1928         return 0;
1929
1930
1931
1932 void hudtargetbox_page_in()
1933 {
1934         bm_page_in_aabitmap( Target_view_gauge.first_frame, Target_view_gauge.num_frames);
1935
1936         bm_page_in_aabitmap( Target_view_integrity_gauge.first_frame, Target_view_integrity_gauge.num_frames );
1937
1938         bm_page_in_aabitmap( Target_view_extra.first_frame, Target_view_extra.num_frames );
1939 }