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