]> icculus.org git repositories - taylor/freespace2.git/blob - src/hud/hudshield.cpp
missing braces warning fixes
[taylor/freespace2.git] / src / hud / hudshield.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/HUDshield.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C file for the display and management of the HUD shield
16  *
17  * $Log$
18  * Revision 1.5  2005/10/01 22:04:58  taylor
19  * fix FS1 (de)briefing voices, the directory names are different in FS1
20  * hard code the table values so that the fs1.vp file isn't needed
21  * hard code a mission fix for sm2-08a since a have no idea how to fix it otherwise
22  * generally cleanup some FS1 code
23  * fix volume sliders in the options screen that never went all the way up
24  *
25  * Revision 1.4  2002/07/13 06:46:48  theoddone33
26  * Warning cleanups
27  *
28  * Revision 1.3  2002/06/09 04:41:21  relnev
29  * added copyright header
30  *
31  * Revision 1.2  2002/05/07 03:16:45  theoddone33
32  * The Great Newline Fix
33  *
34  * Revision 1.1.1.1  2002/05/03 03:28:09  root
35  * Initial import.
36  *
37  * 
38  * 12    8/27/99 10:36a Dave
39  * Impose a 2% penalty for hitting the shield balance key.
40  * 
41  * 11    8/23/99 11:34a Dave
42  * Fixed shield intensity rendering problems.
43  * 
44  * 10    8/01/99 12:39p Dave
45  * Added HUD contrast control key (for nebula).
46  * 
47  * 9     7/22/99 4:00p Dave
48  * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
49  * 
50  * 8     6/10/99 3:43p Dave
51  * Do a better job of syncing text colors to HUD gauges.
52  * 
53  * 7     1/07/99 9:06a Jasen
54  * coords...
55  * 
56  * 6     12/30/98 8:57a Jasen
57  * updated coords for hi res
58  * 
59  * 5     12/28/98 3:17p Dave
60  * Support for multiple hud bitmap filenames for hi-res mode.
61  * 
62  * 4     12/21/98 5:02p Dave
63  * Modified all hud elements to be multi-resolution friendly.
64  * 
65  * 3     12/14/98 1:15p Jasen
66  * added new HUD shield gauges
67  * 
68  * 2     10/07/98 10:53a Dave
69  * Initial checkin.
70  * 
71  * 1     10/07/98 10:49a Dave
72  * 
73  * 35    9/19/98 3:11p Adam
74  * Added new hardcoded values for Hud_shield_filenames
75  * 
76  * 34    8/25/98 1:48p Dave
77  * First rev of EMP effect. Player side stuff basically done. Next comes
78  * AI code.
79  * 
80  * 33    5/17/98 3:32p Lawrance
81  * Make shield gauge more readable when flashing
82  * 
83  * 32    4/25/98 5:39p Dave
84  * Removed an unneeded assert.
85  * 
86  * 31    4/25/98 3:56p Mike
87  * Make player's shield icon flash when Fred tells it to.
88  * 
89  * 30    4/25/98 2:00p Dave
90  * Installed a bunch of multiplayer context help screens. Reworked ingame
91  * join ship select screen. Fix places where network timestamps get hosed.
92  * 
93  * 29    4/21/98 12:19a Allender
94  * only play equalize shield sound if player equalizes shields
95  * 
96  * 28    3/26/98 5:26p John
97  * added new paging code. nonfunctional.
98  * 
99  * 27    3/21/98 3:35p Lawrance
100  * Tweak position of numeric integrity for target
101  * 
102  * 26    3/14/98 4:59p Lawrance
103  * Flash shield/ship icons when ships are hit
104  * 
105  * 25    3/02/98 5:42p John
106  * Removed WinAVI stuff from Freespace.  Made all HUD gauges wriggle from
107  * afterburner.  Made gr_set_clip work good with negative x &y.  Made
108  * model_caching be on by default.  Made each cached model have it's own
109  * bitmap id.  Made asteroids not rotate when model_caching is on.  
110  * 
111  * 24    2/22/98 12:19p John
112  * Externalized some strings
113  * 
114  * 23    2/12/98 4:58p Lawrance
115  * Change to new flashing method.
116  * 
117  * 22    1/12/98 11:16p Lawrance
118  * Wonderful HUD config.
119  * 
120  * 21    1/08/98 4:36p Lawrance
121  * Fix bug in shield drawing code.
122  * 
123  * 20    1/05/98 9:38p Lawrance
124  * Implement flashing HUD gauges.
125  * 
126  * 19    1/02/98 9:10p Lawrance
127  * Big changes to how colors get set on the HUD.
128  * 
129  * 18    12/29/97 9:48p Mike
130  * Prevent indexing before array start when quadrant_num = -1.
131  * 
132  * 17    12/01/97 12:27a Lawrance
133  * redo default alpha color for HUD, make it easy to modify in the future
134  * 
135  * 16    11/18/97 5:58p Lawrance
136  * flash escort view info when that ship is taking hits
137  * 
138  * 15    11/18/97 1:21p Mitri
139  * ALAN: be sure to only draw shield icons for targets that are ships
140  * 
141  * 14    11/17/97 6:37p Lawrance
142  * new gauges: extended target view, new lock triangles, support ship view
143  * 
144  * 13    11/13/97 10:46p Lawrance
145  * implemented new escort view, damage view and weapons
146  * 
147  * 12    11/12/97 9:42a Lawrance
148  * show player ship integrity above shield icon
149  * 
150  * 11    11/11/97 5:06p Lawrance
151  * fix bug with flashing frequency of hull
152  * 
153  * 10    11/09/97 11:27p Lawrance
154  * move target shield icon closer to center
155  * 
156  * 9     11/09/97 4:39p Lawrance
157  * don't draw mini ship icon anymore
158  * 
159  * 8     11/08/97 11:08p Lawrance
160  * implement new "mini-shield" view that sits near bottom of reticle
161  * 
162  * 7     11/05/97 11:21p Lawrance
163  * implement dynamic alpha on the shields
164  * 
165  * 6     11/04/97 8:34p Lawrance
166  * fix warning: remove unused variable
167  * 
168  * 5     11/04/97 7:49p Lawrance
169  * integrating new HUD reticle and shield icons
170  * 
171  * 4     10/24/97 5:51p Lawrance
172  * don't show shield % if ship has no shields
173  * 
174  * 3     9/03/97 4:32p John
175  * changed bmpman to only accept ani and pcx's.  made passing .pcx or .ani
176  * to bm_load functions not needed.   Made bmpman keep track of palettes
177  * for bitmaps not mapped into game palettes.
178  * 
179  * 2     8/25/97 12:24a Lawrance
180  * implemented HUD shield management
181  * 
182  * 1     8/24/97 10:31p Lawrance
183  *
184  * $NoKeywords: $
185  */
186
187 #include "2d.h"
188 #include "object.h"
189 #include "hud.h"
190 #include "hudtarget.h"
191 #include "hudtargetbox.h"
192 #include "hudets.h"
193 #include "player.h"
194 #include "gamesnd.h"
195 #include "freespace.h"
196 #include "bmpman.h"
197 #include "timer.h"
198 #include "hudshield.h"
199 #include "hudescort.h"
200 #include "emp.h"
201 #include "multi.h"
202
203 #define NUM_SHIELD_LEVELS               8
204
205 #define SHIELD_TRANSFER_PERCENT 0.083f          // 1/12 total shield strength
206
207 #define SHIELD_HIT_DURATION_SHORT       300     // time a shield quadrant flashes after being hit
208 #define SHIELD_FLASH_INTERVAL_FAST      200     // time between shield quadrant flashes
209
210 // now read in from hud.tbl
211 #define MAX_SHIELD_ICONS                40
212 int Hud_shield_filename_count = 0;
213 char Hud_shield_filenames[MAX_SHIELD_ICONS][MAX_FILENAME_LEN];
214
215 char Shield_mini_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
216         "targhit1",
217         "targhit1"
218 };
219
220 hud_frames Shield_gauges[MAX_SHIELD_ICONS];
221
222 static int Player_shield_coords[GR_NUM_RESOLUTIONS][2] = 
223 {
224         { // GR_640
225                 396, 379
226         },
227         { // GR_1024
228                 634, 670
229         }
230 };
231
232 static int Target_shield_coords[GR_NUM_RESOLUTIONS][2] = 
233 {
234         { // GR_640
235                 142, 379
236         },
237         { // GR_1024
238                 292, 670
239         }
240 };
241
242 static int Hud_shield_inited = 0;
243
244 int Shield_mini_coords[GR_NUM_RESOLUTIONS][2] = {
245         { // GR_640
246                 305, 291
247         },
248         { // GR_1024
249                 497, 470
250         }
251 };
252
253 // draw on the mini shield icon what the ship integrity is
254 int Hud_mini_3digit[GR_NUM_RESOLUTIONS][3] = {
255         { // GR_640
256                 310, 298, 0
257         },
258         { // GR_1024
259                 502, 477, 0
260         }
261 };
262 int Hud_mini_2digit[GR_NUM_RESOLUTIONS][3] = {
263         { // GR_640
264                 213, 298, 2
265         },
266         { // GR_1024
267                 346, 477, 2
268         }
269 };
270 int Hud_mini_1digit[GR_NUM_RESOLUTIONS][3] = {
271         { // GR_640
272                 316, 298, 6
273         },
274         { // GR_1024
275                 511, 477, 6
276         }
277 };
278 int Hud_mini_base[GR_NUM_RESOLUTIONS][2] = {
279         { // GR_640
280                 310, 298
281         },
282         { // GR_1024
283                 502, 477
284         }
285 };
286         
287 int Shield_mini_loaded = 0;
288 hud_frames Shield_mini_gauge;
289
290 #define SHIELD_HIT_PLAYER               0
291 #define SHIELD_HIT_TARGET               1
292 static shield_hit_info  Shield_hit_data[2];
293
294 // translate between clockwise-from-top shield quadrant ordering to way quadrants are numbered in the game
295 ubyte Quadrant_xlate[4] = {1,0,2,3};
296
297 void hud_shield_game_init()
298 {
299 #ifndef MAKE_FS1
300         char name[MAX_FILENAME_LEN+1] = "";
301
302         // read in hud.tbl
303         read_file_text("hud.tbl");
304         reset_parse();
305
306         Hud_shield_filename_count = 0;
307         required_string("#Shield Icons Begin");
308         while(!optional_string("#End")){
309                 required_string("$Shield:");
310
311                 stuff_string(name, F_NAME, NULL);
312
313                 // maybe store
314                 Assert(Hud_shield_filename_count < MAX_SHIELD_ICONS);
315                 if(Hud_shield_filename_count < MAX_SHIELD_ICONS){
316                         strcpy(Hud_shield_filenames[Hud_shield_filename_count++], name);
317                 }
318         }
319 #else
320         // hardcoded FS1 table values
321         int i;
322
323         Hud_shield_filename_count = 0;
324
325         // for fighters
326         for (i = 1; i < 14; i++) {
327                 snprintf(Hud_shield_filenames[Hud_shield_filename_count++], MAX_FILENAME_LEN, "shield-f%02d", i);
328                 Assert(Hud_shield_filename_count < MAX_SHIELD_ICONS);
329         }
330
331         // for bombers
332         for (i = 1; i < 11; i++) {
333                 snprintf(Hud_shield_filenames[Hud_shield_filename_count++], MAX_FILENAME_LEN, "shield-b%02d", i);
334                 Assert(Hud_shield_filename_count < MAX_SHIELD_ICONS);
335         }
336 #endif
337 }
338
339 // called at the start of each level from HUD_init.  Use Hud_shield_init so we only init Shield_gauges[] once.
340 void hud_shield_level_init()
341 {
342         int i;  
343
344         hud_shield_hit_reset(1);        // reset for the player
345
346         if ( Hud_shield_inited ) {
347                 return;
348         }       
349
350         for ( i = 0; i < MAX_SHIELD_ICONS; i++ ) {
351                 Shield_gauges[i].first_frame = -1;
352                 Shield_gauges[i].num_frames  = 0;
353         }
354
355         Hud_shield_inited = 1;
356
357         if ( !Shield_mini_loaded ) {
358                 Shield_mini_gauge.first_frame = bm_load_animation(Shield_mini_fname[gr_screen.res], &Shield_mini_gauge.num_frames);
359                 if ( Shield_mini_gauge.first_frame == -1 ) {
360                         Warning(LOCATION, "Could not load in the HUD shield ani: Shield_mini_fname[gr_screen.res]\n");
361                         return;
362                 }
363                 Shield_mini_loaded = 1;
364         }
365 }
366
367 int hud_shield_maybe_flash(int gauge, int target_index, int shield_offset)
368 {
369         int                                     flashed = 0;
370         shield_hit_info *shi;
371
372         shi = &Shield_hit_data[target_index];
373
374         if ( !timestamp_elapsed(shi->shield_hit_timers[shield_offset]) ) {
375                 if ( timestamp_elapsed(shi->shield_hit_next_flash[shield_offset]) ) {
376                         shi->shield_hit_next_flash[shield_offset] = timestamp(SHIELD_FLASH_INTERVAL_FAST);
377                         shi->shield_show_bright ^= (1<<shield_offset);  // toggle between default and bright frames
378                 }
379
380                 if ( shi->shield_show_bright & (1<<shield_offset) ) {
381                         // hud_set_bright_color();
382                         hud_set_gauge_color(gauge, HUD_C_BRIGHT);
383                         flashed = 1;
384                 } else {
385                         hud_set_gauge_color(gauge, HUD_C_NORMAL);
386                         // hud_set_default_color();
387                 }
388         }
389
390         return flashed;
391 }
392
393 // ------------------------------------------------------------------
394 // hud_shield_show()
395 //
396 // Show the players shield strength and integrity
397 //
398 void hud_shield_show(object *objp)
399 {
400         float                   max_shield;
401         int                     hud_color_index, range;
402         int                     sx, sy, i;
403         ship                    *sp;
404         ship_info       *sip;
405         hud_frames      *sgp;
406
407         if ( objp->type != OBJ_SHIP )
408                 return;
409
410         sp = &Ships[objp->instance];
411         sip = &Ship_info[sp->ship_info_index];
412
413         if ( sip->shield_icon_index == 255 ) {
414                 return;
415         }
416
417         if (objp == Player_obj) {
418                 hud_set_gauge_color(HUD_PLAYER_SHIELD_ICON);
419         } else {
420                 hud_set_gauge_color(HUD_TARGET_SHIELD_ICON);
421         }
422
423         // load in shield frames if not already loaded
424         // DDOI - shield_icon_index is unsigned
425         // Assert(sip->shield_icon_index >= 0 && sip->shield_icon_index < Hud_shield_filename_count);
426         Assert(sip->shield_icon_index < Hud_shield_filename_count);
427         
428         sgp = &Shield_gauges[sip->shield_icon_index];
429
430         if ( sgp->first_frame == -1 ) {
431                 sgp->first_frame = bm_load_animation(Hud_shield_filenames[sip->shield_icon_index], &sgp->num_frames);
432                 if ( sgp->first_frame == -1 ) {
433                         Warning(LOCATION, "Could not load in the HUD shield ani: %s\n", Hud_shield_filenames[sip->shield_icon_index]);
434                         return;
435                 }
436         }
437
438         if ( objp == Player_obj ) {
439                 sx = Player_shield_coords[gr_screen.res][0];
440                 sy = Player_shield_coords[gr_screen.res][1];
441         } else {
442                 sx = Target_shield_coords[gr_screen.res][0];
443                 sy = Target_shield_coords[gr_screen.res][1];
444         }
445
446         sx += fl2i(HUD_offset_x);
447         sy += fl2i(HUD_offset_y);
448
449         // draw the ship first
450         if ( objp == Player_obj ) {
451                 hud_shield_maybe_flash(HUD_PLAYER_SHIELD_ICON, SHIELD_HIT_PLAYER, HULL_HIT_OFFSET);
452         } else {
453                 hud_shield_maybe_flash(HUD_TARGET_SHIELD_ICON, SHIELD_HIT_TARGET, HULL_HIT_OFFSET);
454         }
455
456         GR_AABITMAP(sgp->first_frame, sx, sy);  
457
458         // draw the four quadrants
459         //
460         // Draw shield quadrants at one of NUM_SHIELD_LEVELS
461         max_shield = sip->shields/4.0f;
462
463         for ( i = 0; i < 4; i++ ) {
464
465                 if ( objp->flags & OF_NO_SHIELDS ) {
466                         break;
467                 }
468
469                 if ( objp->shields[Quadrant_xlate[i]] < 0.1f ) {
470                         continue;
471                 }
472
473                 range = max(HUD_COLOR_ALPHA_MAX, HUD_color_alpha + 4);
474                 hud_color_index = fl2i( (objp->shields[Quadrant_xlate[i]] / max_shield) * range + 0.5);
475                 Assert(hud_color_index >= 0 && hud_color_index <= range);
476
477                 if ( hud_color_index < 0 ) {
478                         hud_color_index = 0;
479                 }
480                 if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) {
481                         hud_color_index = HUD_NUM_COLOR_LEVELS - 1;
482                 }
483
484                 int flash=0;
485                 if ( objp == Player_obj ) {
486                         flash = hud_shield_maybe_flash(HUD_PLAYER_SHIELD_ICON, SHIELD_HIT_PLAYER, i);
487                 } else {
488                         flash = hud_shield_maybe_flash(HUD_TARGET_SHIELD_ICON, SHIELD_HIT_TARGET, i);
489                 }
490                                 
491                 if ( !flash ) {
492                         // gr_set_color_fast(&HUD_color_defaults[hud_color_index]);
493                         if ( objp == Player_obj ) {
494                                 hud_set_gauge_color(HUD_PLAYER_SHIELD_ICON, hud_color_index);
495                         } else {
496                                 hud_set_gauge_color(HUD_TARGET_SHIELD_ICON, hud_color_index);
497                         }
498
499                         GR_AABITMAP(sgp->first_frame+i+1, sx, sy);                      
500                 }
501         }
502
503         // hud_set_default_color();
504 }
505
506 // called at beginning of level to page in all ship icons
507 // used in this level
508 void hud_ship_icon_page_in(ship_info *sip)
509 {
510         hud_frames      *sgp;
511
512         if ( sip->shield_icon_index == 255 ) {
513                 return;
514         }
515
516         // load in shield frames if not already loaded
517         // DDOI - shield_icon_index is unsigned
518         // Assert(sip->shield_icon_index >= 0 && sip->shield_icon_index < Hud_shield_filename_count);
519         Assert(sip->shield_icon_index < Hud_shield_filename_count);
520         sgp = &Shield_gauges[sip->shield_icon_index];
521
522         if ( sgp->first_frame == -1 ) {
523                 sgp->first_frame = bm_load_animation(Hud_shield_filenames[sip->shield_icon_index], &sgp->num_frames);
524                 if ( sgp->first_frame == -1 ) {
525                         Warning(LOCATION, "Could not load in the HUD shield ani: %s\n", Hud_shield_filenames[sip->shield_icon_index]);
526                         return;
527                 }
528         }
529
530         int i;
531         for (i=0; i<sgp->num_frames; i++ )      {
532                 bm_page_in_aabitmap(sgp->first_frame+i);
533         }
534
535 }
536
537 // ------------------------------------------------------------------
538 // hud_shield_equalize()
539 //
540 // Equalize the four shield quadrants for an object
541 //
542 void hud_shield_equalize(object *objp, player *pl)
543 {
544         float   strength;
545         int idx;
546         int all_equal = 1;
547
548         Assert(objp != NULL);
549         if(objp == NULL){
550                 return;
551         }
552         Assert(pl != NULL);
553         if(pl == NULL){
554                 return;
555         }
556         Assert(objp->type == OBJ_SHIP);
557         if(objp->type != OBJ_SHIP){
558                 return;
559         }
560
561         // are all quadrants equal?
562         for(idx=0; idx<MAX_SHIELD_SECTIONS-1; idx++){
563                 if(objp->shields[idx] != objp->shields[idx+1]){
564                         all_equal = 0;
565                         break;
566                 }
567         }
568
569         // not all equal
570         if(!all_equal){
571                 strength = get_shield_strength(objp);
572                 if ( strength != 0 ) {
573                         // maybe impose a 2% penalty - server side and single player only
574                         if(!MULTIPLAYER_CLIENT &&  (pl->shield_penalty_stamp < 0) || timestamp_elapsed_safe(pl->shield_penalty_stamp, 1000) ){
575                                 strength *= 0.98f;
576
577                                 // reset the penalty timestamp
578                                 pl->shield_penalty_stamp = timestamp(1000);
579                         }
580                         
581                         set_shield_strength(objp, strength);                                    
582                 }
583         }
584
585         // beep
586         if ( objp == Player_obj ){
587                 snd_play( &Snds[SND_SHIELD_XFER_OK] );
588         }
589 }
590
591 // ------------------------------------------------------------------
592 // hud_augment_shield_quadrant()
593 //
594 // Transfer shield energy to a shield quadrant from the three other
595 //      quadrants.  Works by trying to transfer a fixed amount of shield
596 //      energy from the other three quadrants, taking the same percentage
597 // from each quadrant.
598 //
599 //      input:  objp                    =>              object to perform shield transfer on
600 //                              direction       =>              which quadrant to augment:
601 //                                                                              0 - right
602 //                                                                              1 - top
603 //                                                                              2 - bottom
604 //                                                                              3 - left
605 //
606 void hud_augment_shield_quadrant(object *objp, int direction)
607 {
608         float   full_shields, xfer_amount, energy_avail, percent_to_take, delta;
609         float   max_quadrant_val;
610         int     i;
611
612         Assert(direction >= 0 && direction < 4);
613         Assert(objp->type == OBJ_SHIP);
614         full_shields = Ship_info[Ships[objp->instance].ship_info_index].shields;
615         
616         xfer_amount = full_shields * SHIELD_TRANSFER_PERCENT;
617         max_quadrant_val = full_shields/4.0f;
618
619         if ( (objp->shields[direction] + xfer_amount) > max_quadrant_val )
620                 xfer_amount = max_quadrant_val - objp->shields[direction];
621
622         Assert(xfer_amount >= 0);
623         if ( xfer_amount == 0 ) {
624                 // TODO: provide a feedback sound
625                 return;
626         }
627         else {
628                 snd_play( &Snds[SND_SHIELD_XFER_OK] );
629         }
630
631         energy_avail = 0.0f;
632         for ( i = 0; i < MAX_SHIELD_SECTIONS; i++ ) {
633                 if ( i == direction )
634                         continue;
635                 energy_avail += objp->shields[i];
636         }
637
638         percent_to_take = xfer_amount/energy_avail;
639         if ( percent_to_take > 1.0f )
640                 percent_to_take = 1.0f;
641
642         for ( i = 0; i < MAX_SHIELD_SECTIONS; i++ ) {
643                 if ( i == direction )
644                         continue;
645                 delta = percent_to_take * objp->shields[i];
646                 objp->shields[i] -= delta;
647                 Assert(objp->shields[i] >= 0 );
648                 objp->shields[direction] += delta;
649                 if ( objp->shields[direction] > max_quadrant_val )
650                         objp->shields[direction] = max_quadrant_val;
651         }
652 }
653
654 // Try to find a match between filename and the names inside
655 // of Hud_shield_filenames.  This will provide us with an 
656 // association of ship class to shield icon information.
657 void hud_shield_assign_info(ship_info *sip, char *filename)
658 {
659         ubyte i;
660
661         for ( i = 0; i < Hud_shield_filename_count; i++ ) {
662                 if ( !stricmp(filename, Hud_shield_filenames[i]) ) {
663                         sip->shield_icon_index = i;
664                 }
665         }               
666 }
667
668 void hud_show_mini_ship_integrity(object *objp, int x_force, int y_force)
669 {
670         char    text_integrity[64];
671         int     numeric_integrity;
672         float p_target_integrity,initial_hull;
673         int     nx, ny;
674
675         initial_hull = Ship_info[Ships[objp->instance].ship_info_index].initial_hull_strength;
676         if (  initial_hull <= 0 ) {
677                 Int3(); // illegal initial hull strength
678                 p_target_integrity = 0.0f;
679         } else {
680                 p_target_integrity = objp->hull_strength / initial_hull;
681                 if (p_target_integrity < 0){
682                         p_target_integrity = 0.0f;
683                 }
684         }
685
686         numeric_integrity = fl2i(p_target_integrity*100 + 0.5f);
687         if(numeric_integrity > 100){
688                 numeric_integrity = 100;
689         }
690         // Assert(numeric_integrity <= 100);
691
692         // base coords
693         nx = (x_force == -1) ? Hud_mini_base[gr_screen.res][0] : x_force;
694         ny = (y_force == -1) ? Hud_mini_base[gr_screen.res][1] : y_force;
695
696         // 3 digit hull strength
697         if ( numeric_integrity == 100 ) {
698                 nx += Hud_mini_3digit[gr_screen.res][2];
699         } 
700         // 2 digit hull strength
701         else if ( numeric_integrity < 10 ) {
702                 nx += Hud_mini_1digit[gr_screen.res][2];                
703         }
704         // 1 digit hull strength
705         else {
706                 nx += Hud_mini_2digit[gr_screen.res][2];                
707         }       
708
709         if ( numeric_integrity == 0 ) {
710                 if ( p_target_integrity > 0 ) {
711                         numeric_integrity = 1;
712                 }
713         }
714
715         nx += fl2i( HUD_offset_x );
716         ny += fl2i( HUD_offset_y );
717
718         sprintf(text_integrity, "%d", numeric_integrity);
719         if ( numeric_integrity < 100 ) {
720                 hud_num_make_mono(text_integrity);
721         }       
722
723         gr_string(nx, ny, text_integrity);
724 }
725
726 // Draw the miniature shield icon that is drawn near the reticle
727 void hud_shield_show_mini(object *objp, int x_force, int y_force, int x_hull_offset, int y_hull_offset)
728 {
729         float                   max_shield;
730         int                     hud_color_index, range, frame_offset;
731         int                     sx, sy, i;
732         ship                    *sp;
733         ship_info       *sip;
734         shield_hit_info *shi;
735
736         shi = &Shield_hit_data[SHIELD_HIT_TARGET];
737
738         if ( objp->type != OBJ_SHIP ) {
739                 return;
740         }
741
742         sp = &Ships[objp->instance];
743         sip = &Ship_info[sp->ship_info_index];
744
745         hud_set_gauge_color(HUD_TARGET_MINI_ICON);
746
747         if (!Shield_mini_loaded)
748                 return;
749
750         sx = (x_force == -1) ? Shield_mini_coords[gr_screen.res][0]+fl2i(HUD_offset_x) : x_force;
751         sy = (y_force == -1) ? Shield_mini_coords[gr_screen.res][1]+fl2i(HUD_offset_y) : y_force;
752
753         // draw the ship first
754         hud_shield_maybe_flash(HUD_TARGET_MINI_ICON, SHIELD_HIT_TARGET, HULL_HIT_OFFSET);
755         hud_show_mini_ship_integrity(objp,x_force + x_hull_offset,y_force + y_hull_offset);
756
757         // draw the four quadrants
758         // Draw shield quadrants at one of NUM_SHIELD_LEVELS
759         max_shield = sip->shields/4.0f;
760
761         for ( i = 0; i < 4; i++ ) {
762
763                 if ( objp->flags & OF_NO_SHIELDS ) {
764                         break;
765                 }
766
767                 if ( objp->shields[Quadrant_xlate[i]] < 0.1f ) {
768                         continue;
769                 }
770
771                 if ( hud_shield_maybe_flash(HUD_TARGET_MINI_ICON, SHIELD_HIT_TARGET, i) ) {
772                         frame_offset = i+4;
773                 } else {
774                         frame_offset = i;
775                 }
776                                 
777                 range = HUD_color_alpha;
778                 hud_color_index = fl2i( (objp->shields[Quadrant_xlate[i]] / max_shield) * range + 0.5);
779                 Assert(hud_color_index >= 0 && hud_color_index <= range);
780         
781                 if ( hud_color_index < 0 ) {
782                         hud_color_index = 0;
783                 }
784                 if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) {
785                         hud_color_index = HUD_NUM_COLOR_LEVELS - 1;
786                 }
787
788                 if ( hud_gauge_maybe_flash(HUD_TARGET_MINI_ICON) == 1) {
789                         // hud_set_bright_color();
790                         hud_set_gauge_color(HUD_TARGET_MINI_ICON, HUD_C_BRIGHT);
791                 } else {
792                         // gr_set_color_fast(&HUD_color_defaults[hud_color_index]);
793                         hud_set_gauge_color(HUD_TARGET_MINI_ICON, hud_color_index);
794                 }                                        
795
796                 GR_AABITMAP(Shield_mini_gauge.first_frame + frame_offset, sx, sy);              
797         }
798         
799         // hud_set_default_color();
800 }
801
802 // reset the shield_hit_info data structure
803 void shield_info_reset(shield_hit_info *shi)
804 {
805         int i;
806
807         shi->shield_hit_status = 0;
808         shi->shield_show_bright = 0;
809         for ( i = 0; i < NUM_SHIELD_HIT_MEMBERS; i++ ) {
810                 shi->shield_hit_timers[i] = 1;
811                 shi->shield_hit_next_flash[i] = 1;
812         }
813 }
814
815 // reset the timers and hit flags for the shield gauges
816 //
817 // This needs to be called whenever the player selects a new target
818 //
819 // input:       player  =>      optional parameter (default value 0).  This is to indicate that player shield hit
820 //                                                              info should be reset.  This is normally not the case.
821 //                                                              is for the player's current target
822 void hud_shield_hit_reset(int player)
823 {
824         shield_hit_info *shi;
825
826         if (player) {
827                 shi = &Shield_hit_data[SHIELD_HIT_PLAYER];
828         } else {
829                 shi = &Shield_hit_data[SHIELD_HIT_TARGET];
830         }
831
832         shield_info_reset(shi);
833 }
834
835 // called once per frame to update the state of Shield_hit_status based on the Shield_hit_timers[]
836 void hud_shield_hit_update()
837 {
838         int i, j, limit;                
839
840         limit = 1;
841         if ( Player_ai->target_objnum >= 0 ) {
842                 limit = 2;
843         }
844
845         for ( i = 0; i < limit; i++ ) {
846                 for ( j = 0; j < NUM_SHIELD_HIT_MEMBERS; j++ ) {
847                         if ( timestamp_elapsed(Shield_hit_data[i].shield_hit_timers[j]) ) {
848                                 Shield_hit_data[i].shield_hit_status &= ~(1<<j);
849                                 Shield_hit_data[i].shield_show_bright &= ~(1<<j);
850                         }
851                 }
852         }
853 }
854
855 // called when a shield quadrant is struct, so we can update the timer that will draw the quadrant
856 // as flashing
857 //
858 // input:
859 //                              objp            =>      object pointer for ship that has been hit
860 //                              quadrant        => quadrant of shield getting hit (-1 if no shield is present)
861 void hud_shield_quadrant_hit(object *objp, int quadrant)
862 {
863         shield_hit_info *shi;
864         int                                     num;
865
866         if ( objp->type != OBJ_SHIP )
867                 return;
868
869         hud_escort_ship_hit(objp, quadrant);
870         hud_gauge_popup_start(HUD_TARGET_MINI_ICON);
871
872         if ( OBJ_INDEX(objp) == Player_ai->target_objnum ) {
873                 shi = &Shield_hit_data[SHIELD_HIT_TARGET];
874         } else if ( objp == Player_obj ) {
875                 shi = &Shield_hit_data[SHIELD_HIT_PLAYER];
876         } else {
877                 return;
878         }
879
880         if ( quadrant >= 0 ) {
881                 num = Quadrant_xlate[quadrant];
882                 shi->shield_hit_timers[num] = timestamp(300);
883         } else {
884                 shi->shield_hit_timers[HULL_HIT_OFFSET] = timestamp(SHIELD_HIT_DURATION_SHORT);
885                 hud_targetbox_start_flash(TBOX_FLASH_HULL);
886         }
887 }
888
889
890 void hudshield_page_in()
891 {
892         bm_page_in_aabitmap( Shield_mini_gauge.first_frame, Shield_mini_gauge.num_frames );
893 }
894