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