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