]> icculus.org git repositories - taylor/freespace2.git/blob - src/hud/hudbrackets.cpp
try to prevent random crashing from wing ai
[taylor/freespace2.git] / src / hud / hudbrackets.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/HUDbrackets.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C file that contains functions for drawing target brackets on the HUD
16  *
17  * $Log$
18  * Revision 1.3  2002/06/09 04:41:21  relnev
19  * added copyright header
20  *
21  * Revision 1.2  2002/05/07 03:16:45  theoddone33
22  * The Great Newline Fix
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:09  root
25  * Initial import.
26  *
27  * 
28  * 6     8/03/99 5:35p Andsager
29  * Dont draw target dot for instructor in training mission
30  * 
31  * 5     6/07/99 4:20p Andsager
32  * Add HUD color for tagged object.  Apply to target and radar.
33  * 
34  * 4     12/28/98 3:17p Dave
35  * Support for multiple hud bitmap filenames for hi-res mode.
36  * 
37  * 3     12/21/98 5:02p Dave
38  * Modified all hud elements to be multi-resolution friendly.
39  * 
40  * 2     10/07/98 10:53a Dave
41  * Initial checkin.
42  * 
43  * 1     10/07/98 10:49a Dave
44  * 
45  * 54    8/25/98 1:48p Dave
46  * First rev of EMP effect. Player side stuff basically done. Next comes
47  * AI code.
48  * 
49  * 53    6/01/98 11:43a John
50  * JAS & MK:  Classified all strings for localization.
51  * 
52  * 52    5/27/98 1:22p Allender
53  * make targeting dots work in multiplayer -- as well as many other minor
54  * targeting problems
55  * 
56  * 51    5/23/98 2:26a Lawrance
57  * Tweak brackets
58  * 
59  * 50    5/14/98 11:26a Lawrance
60  * ensure fighter bays are drawn with correct bracket color
61  * 
62  * 49    5/12/98 9:27a Mike
63  * num-ships-attacking: always showed an additional ship attacking
64  * asteroid or debris.  Fixed.
65  * 
66  * 48    5/08/98 10:16a Lawrance
67  * Add new "ship attacking count" gauge
68  * 
69  * 47    5/07/98 4:07p Mike
70  * Use smaller num-ships-attacking blip.
71  * 
72  * 46    5/06/98 5:30p John
73  * Removed unused cfilearchiver.  Removed/replaced some unused/little used
74  * graphics functions, namely gradient_h and _v and pixel_sp.   Put in new
75  * DirectX header files and libs that fixed the Direct3D alpha blending
76  * problems.
77  * 
78  * 45    5/06/98 2:46p Mike
79  * Modify num-ships-attacking system.
80  * 
81  * 44    5/03/98 1:07a Mike
82  * Show + for ships attacking your target, whether hostile or friendly.
83  * 
84  * 43    4/05/98 7:42p Lawrance
85  * fix inconsistent distance display on the HUD
86  * 
87  * 42    4/01/98 9:21p John
88  * Made NDEBUG, optimized build with no warnings or errors.
89  * 
90  * 41    3/30/98 12:20a Lawrance
91  * Draw subsystem targeting brackets gray if subsystem is destroyed.
92  * 
93  * 40    3/18/98 6:04p Lawrance
94  * Improve when brackets get drawn for large objects
95  * 
96  * 39    3/10/98 6:03p Lawrance
97  * Ensure proper bracket color gets drawn for traitors
98  * 
99  * 38    3/06/98 5:13p Johnson
100  * Put in a check for team traitor in hud_brackets_get_iff_color()
101  * 
102  * 37    3/02/98 11:32p Lawrance
103  * Allow asteroids about to impact ships to be bracketed
104  * 
105  * 36    2/21/98 2:49p Lawrance
106  * Don't do facing check for subsystems when deciding whether to draw
107  * brackets
108  * 
109  * 35    2/19/98 12:48a Lawrance
110  * Ensure subsystem brackets remain between HUD and target monitor
111  * 
112  * 34    2/09/98 8:05p Lawrance
113  * Add new gauges: cmeasure success, warp-out, and missiontime
114  * 
115  * 33    2/07/98 5:46p Lawrance
116  * Show target distance on brackets
117  * 
118  * 32    1/19/98 11:37p Lawrance
119  * Fixing Optimization build warnings
120  * 
121  * 31    1/18/98 5:09p Lawrance
122  * Added support for TEAM_TRAITOR
123  * 
124  * 30    1/02/98 10:01p Lawrance
125  * Ensure correct subsystem bracket color gets drawn once player goes
126  * traitor.
127  * 
128  * 29    1/02/98 9:10p Lawrance
129  * Big changes to how colors get set on the HUD.
130  * 
131  * 28    12/28/97 5:54p Lawrance
132  * Draw HUD brackets the correct IFF color.. taking into account that the
133  * player may be TEAM_NEUTRAL
134  * 
135  * 27    12/18/97 8:46p Lawrance
136  * Move IFF_color definitions from HUD->ship, so FRED can use them.
137  * 
138  * 26    12/17/97 11:14p Mike
139  * Change radar and hud color to red for all neutral.
140  * 
141  * 25    11/27/97 4:24p Lawrance
142  * change appearance of subsystem targeting brackets
143  * 
144  * 24    10/22/97 5:53p Lawrance
145  * change name of subsystem_in_sight() function
146  * 
147  * 23    9/06/97 2:13p Mike
148  * Replace support for TEAM_NEUTRAL
149  * 
150  * 22    7/24/97 10:45a Mike
151  * Fix hole in Unknown team support.
152  * 
153  * 21    7/24/97 10:24a Mike
154  * Restore support for Unknown team
155  * 
156  * 20    6/11/97 1:12p John
157  * Started fixing all the text colors in the game.
158  * 
159  * 19    5/21/97 11:12a Mike
160  * Move more stuff out of player struct, mainly subsys stuff.
161  * 
162  * 18    5/20/97 2:45p Mike
163  * Move current_target and a bunch of other stuff out of player struct.
164  * 
165  * 17    4/09/97 3:30p Lawrance
166  * let target brackets grow to bracket ship entirely
167  * 
168  * 16    4/08/97 1:28p Lawrance
169  * get brackets for targeting and messaging drawing right
170  * 
171  * 15    4/08/97 11:44a Lawrance
172  * get selection and target brackets drawing right at close and far
173  * distances
174  * 
175  * 14    4/08/97 10:55a Allender
176  * draw purple brackets on ship sending a message
177  * 
178  * 13    4/08/97 9:58a Lawrance
179  * center bracket on target center.  Give min and max dimensions to
180  * subsystem target brackets.
181  * 
182  * 12    4/07/97 6:03p Lawrance
183  * draw diamond brackets instead of dashed boxes
184  * 
185  * 11    4/07/97 3:50p Allender
186  * ability to assign > 1 ship to a hotkey.  Enabled use of hotkeys in
187  * squadmate messaging
188  * 
189  * 10    4/02/97 10:08a Lawrance
190  * fixed bracket drawing glitches 
191  * 
192  * 9     3/28/97 2:46p John
193  * added code to make debris chunks target properly.
194  * 
195  * 8     3/27/97 5:44p Lawrance
196  * drawing dashed lines for sub-object targeting box that is not in line
197  * of sight
198  * 
199  * 7     3/27/97 3:59p Lawrance
200  * made brackets draw even if center of target is offscreen
201  * 
202  * 6     3/27/97 9:29a Lawrance
203  * If reach maximum bounding box size, use radius targeting box method
204  * 
205  * 5     3/25/97 3:55p Lawrance
206  * allowing debris to be targeted and shown on radar
207  * 
208  * 4     3/23/97 11:55p Lawrance
209  * made max targeting bracket size of 200x200
210  * 
211  * 3     3/07/97 4:37p Mike
212  * Make rockeye missile home.
213  * Remove UNKNOWN and NEUTRAL teams.
214  * 
215  * 2     12/24/96 4:30p Lawrance
216  * Target bracket drawing code moved to separate files
217  *
218  * $NoKeywords: $
219  */
220
221 #include "hudbrackets.h"
222 #include "hud.h"
223 #include "player.h"
224 #include "hudtarget.h"
225 #include "3d.h"
226 #include "debris.h"
227 #include "ai.h"
228 #include "freespace.h"
229 #include "bmpman.h"
230 #include "linklist.h"
231 #include "emp.h"
232
233 #define FADE_FACTOR     2                       // how much the bounding brackets get faded
234 #define LOWEST_RED      50                      // lowest r value for bounding bracket
235 #define LOWEST_GREEN    50                      // lowest g value for bounding bracket
236 #define LOWEST_BLUE     50                      // lowest b value for bounding bracket
237
238 char Ships_attack_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
239         "attacker",
240         "attacker"
241 };
242
243 // resolution adjust factors for the above defines
244 int Min_target_box_width[GR_NUM_RESOLUTIONS] = { 20, 30 };
245 int Min_target_box_height[GR_NUM_RESOLUTIONS] = { 20, 30 };
246 int Min_subtarget_box_width[GR_NUM_RESOLUTIONS] = { 12, 24 };
247 int Min_subtarget_box_height[GR_NUM_RESOLUTIONS] = { 12, 24 };
248
249 void hud_init_brackets()
250 {
251 }
252
253 // find IFF color index for brackets based on team
254 int hud_brackets_get_iff_color(int team)
255 {
256         int color=IFF_COLOR_FRIENDLY;
257
258         switch ( team ) {
259         case TEAM_FRIENDLY:
260         case TEAM_HOSTILE:
261         case TEAM_NEUTRAL:
262         case TEAM_TRAITOR:
263         case TEAM_UNKNOWN:
264                 if ( (team == Player_ship->team) && (team != TEAM_TRAITOR) ) {
265                         color = IFF_COLOR_FRIENDLY;
266                 } else {
267                         switch (team) {
268                         case TEAM_NEUTRAL:
269                                 color = IFF_COLOR_NEUTRAL;
270                                 break;
271                         case TEAM_UNKNOWN:
272                                 color = IFF_COLOR_UNKNOWN;
273                                 break;
274                         case TEAM_HOSTILE:
275                         case TEAM_FRIENDLY:
276                         case TEAM_TRAITOR:
277                                 color = IFF_COLOR_HOSTILE;
278                                 break;
279                         }
280                 }
281                 break;
282         case SELECTION_SET:
283                 color = IFF_COLOR_SELECTION;
284                 break;
285                 
286         case MESSAGE_SENDER:
287                 color = IFF_COLOR_MESSAGE;
288                 break;
289
290         default:
291                 color = IFF_COLOR_UNKNOWN;
292                 Int3();
293         } // end switch
294
295         return color;
296 }
297
298
299 //      Called by draw_bounding_brackets.  
300 void draw_brackets_square(int x1, int y1, int x2, int y2)
301 {
302         int     width, height;
303         
304         width = x2 - x1;
305         SDL_assert( width > 0);
306         height = y2 - y1;
307         SDL_assert( height > 0);
308
309         // make the brackets extend 25% of the way along the width or height
310         int bracket_width = width/4;
311         int bracket_height = height/4;
312
313         // horizontal lines
314         if ( (x1 + bracket_width > 0) && (x1 < gr_screen.clip_width) ){
315                 gr_gradient(x1,y1,x1+bracket_width-1,y1);       // top left
316                 gr_gradient(x1,y2,x1+bracket_width-1,y2);       // bottom left
317         }
318
319         if ( (x2 - bracket_width < gr_screen.clip_width) && (x2 > 0) )  {
320                 gr_gradient(x2, y1, x2-bracket_width+1,y1);     // top right
321                 gr_gradient(x2, y2, x2-bracket_width+1,y2);     // bottom right
322         }
323
324         // vertical lines
325         if ( (y1 + bracket_height > 0) && (y1 < gr_screen.clip_height) ) {
326                 gr_gradient(x1,y1,x1,y1+bracket_height-1);              // top left
327                 gr_gradient(x2,y1,x2,y1+bracket_height-1);              // top right
328         }
329
330         if ( (y2 - bracket_height < gr_screen.clip_height) && (y2 > 0) )        {
331                 gr_gradient(x1,y2,x1,y2-bracket_height+1);      // bottom left
332                 gr_gradient(x2,y2,x2,y2-bracket_height+1);      // bottom right
333         }
334 }
335
336 void draw_brackets_square_quick(int x1, int y1, int x2, int y2, int thick)
337 {
338         int     width, height;
339
340         width = x2 - x1;
341         height = y2 - y1;
342
343         // make the brackets extend 25% of the way along the width or height
344         int bracket_width = width/4;
345         int bracket_height = height/4;
346
347         // top line
348         gr_line(x1,y1,x1+bracket_width,y1);
349         gr_line(x2,y1,x2-bracket_width,y1);
350         if ( thick ) {
351                 gr_line(x1,y1+1,x1+bracket_width,y1+1);
352                 gr_line(x2,y1+1,x2-bracket_width,y1+1);
353         }
354
355         // bottom line
356         gr_line(x1,y2,x1+bracket_width,y2);
357         gr_line(x2,y2,x2-bracket_width,y2);
358         if ( thick ) {
359                 gr_line(x1,y2-1,x1+bracket_width,y2-1);
360                 gr_line(x2,y2-1,x2-bracket_width,y2-1);
361         }
362
363         // left line
364         if ( thick ) {
365                 gr_line(x1,y1+2,x1,y1+bracket_height);
366                 gr_line(x1,y2-2,x1,y2-bracket_height);
367                 gr_line(x1+1,y1+2,x1+1,y1+bracket_height);
368                 gr_line(x1+1,y2-2,x1+1,y2-bracket_height);
369         } else {
370                 gr_line(x1,y1+1,x1,y1+bracket_height);
371                 gr_line(x1,y2-1,x1,y2-bracket_height);
372         }
373
374         // right line
375         if ( thick ) {
376                 gr_line(x2,y1+2,x2,y1+bracket_height);
377                 gr_line(x2,y2-2,x2,y2-bracket_height);
378                 gr_line(x2-1,y1+2,x2-1,y1+bracket_height);
379                 gr_line(x2-1,y2-2,x2-1,y2-bracket_height);
380         } else {
381                 gr_line(x2,y1+1,x2,y1+bracket_height);
382                 gr_line(x2,y2-1,x2,y2-bracket_height);
383         }
384 }
385
386
387 #define NUM_DASHES      2
388 void draw_brackets_dashed_square_quick(int x1, int y1, int x2, int y2)
389 {
390         int     width, height, i;
391
392         width = x2 - x1;
393         height = y2 - y1;
394
395         // make the brackets extend 25% of the way along the width or height
396         float bracket_width = width/4.0f;
397         float bracket_height = height/4.0f;
398
399         int dash_width;
400         dash_width = fl2i(bracket_width / ( NUM_DASHES*2 - 1 ) + 0.5f);
401
402         if ( dash_width < 1 ) {
403                 draw_brackets_square_quick(x1, y1, x2, y2);
404                 return;
405         }
406
407         int dash_height;
408         dash_height = fl2i(bracket_height / ( NUM_DASHES*2 - 1 ) + 0.5f);
409
410         if ( dash_height < 1 ) {
411                 draw_brackets_square_quick(x1, y1, x2, y2);
412                 return;
413         }
414         
415         int dash_x1, dash_x2, dash_y1, dash_y2;
416
417         dash_x1 = x1;
418         dash_x2 = x2;
419         dash_y1 = y1;
420         dash_y2 = y2;
421
422         for ( i = 0; i < NUM_DASHES; i++ ) {
423                 // top line
424                 gr_line(dash_x1, y1, dash_x1+(dash_width-1), y1);
425                 gr_line(dash_x2, y1, dash_x2-(dash_width-1), y1);
426
427                 // bottom line
428                 gr_line(dash_x1, y2, dash_x1+(dash_width-1), y2);
429                 gr_line(dash_x2, y2, dash_x2-(dash_width-1), y2);
430                 
431                 dash_x1 += dash_width*2;
432                 dash_x2 -= dash_width*2;
433
434                 // left line
435                 gr_line(x1, dash_y1, x1, dash_y1+(dash_height-1));
436                 gr_line(x1, dash_y2, x1, dash_y2-(dash_height-1));
437
438                 // right line
439                 gr_line(x2, dash_y1, x2, dash_y1+(dash_height-1));
440                 gr_line(x2, dash_y2, x2, dash_y2-(dash_height-1));
441
442                 dash_y1 += dash_height*2;
443                 dash_y2 -= dash_height*2;
444         }
445
446 }
447
448
449
450 // draw_brackets_diamond()
451 //      Called by draw_bounding_brackets.  
452
453 void draw_brackets_diamond(int x1, int y1, int x2, int y2)
454 {
455         int width, height, half_width, half_height;
456         int center_x, center_y;
457         int x_delta, y_delta;
458
459         float side_len, bracket_len;
460
461         width = x2 - x1;
462         height = y2 - y1;
463
464         half_width = fl2i( width/2.0f + 0.5f );
465         half_height = fl2i( height/2.0f +0.5f );
466
467         side_len = hypotf(i2fl(half_width), i2fl(half_height));
468         bracket_len = side_len / 8.0f;
469         
470         x_delta = fl2i(bracket_len * width / side_len + 0.5f);
471         y_delta = fl2i(bracket_len * height / side_len + 0.5f);
472
473
474         center_x = x1 + half_width;
475         center_y = y1 + half_height;
476
477         // top left line
478         gr_gradient(center_x - x_delta, y1 + y_delta,center_x, y1);
479         gr_gradient(x1 + x_delta, center_y - y_delta, x1, center_y);
480
481         // top right line
482         gr_gradient(center_x + x_delta, y1 + y_delta,center_x, y1);
483         gr_gradient(x2 - x_delta, center_y - y_delta, x2, center_y);
484
485         // bottom left line
486         gr_gradient(x1 + x_delta, center_y + y_delta, x1, center_y);
487         gr_gradient(center_x - x_delta, y2 - y_delta, center_x, y2);
488
489         // bottom right line
490         gr_gradient(x2 - x_delta, center_y + y_delta, x2, center_y);
491         gr_gradient(center_x + x_delta, y2 - y_delta, center_x, y2);
492 }
493
494 void draw_brackets_diamond_quick(int x1, int y1, int x2, int y2, int thick)
495 {
496         int width, height, half_width, half_height;
497         int center_x, center_y;
498         int x_delta, y_delta;
499
500         float side_len, bracket_len;
501
502         width = x2 - x1;
503         height = y2 - y1;
504
505         half_width = fl2i( width/2.0f + 0.5f);
506         half_height = fl2i( height/2.0f + 0.5f);
507
508         side_len = hypotf(i2fl(half_width), i2fl(half_height));
509         bracket_len = side_len / 8.0f;
510         
511         x_delta = fl2i(bracket_len * width / side_len + 0.5f);
512         y_delta = fl2i(bracket_len * height / side_len + 0.5f);
513
514         center_x = x1 + half_width;
515         center_y = y1 + half_height;
516
517         // top left line
518         gr_line(center_x - x_delta, y1 + y_delta,center_x, y1);
519         gr_line(x1 + x_delta, center_y - y_delta, x1, center_y);
520
521         // top right line
522         gr_line(center_x + x_delta, y1 + y_delta,center_x, y1);
523         gr_line(x2 - x_delta, center_y - y_delta, x2, center_y);
524
525         // bottom left line
526         gr_line(x1 + x_delta, center_y + y_delta, x1, center_y);
527         gr_line(center_x - x_delta, y2 - y_delta, center_x, y2);
528
529         // bottom right line
530         gr_line(x2 - x_delta, center_y + y_delta, x2, center_y);
531         gr_line(center_x + x_delta, y2 - y_delta, center_x, y2);
532
533         // draw an 'X' in the middle of the brackets
534         gr_line(center_x-x_delta, center_y-y_delta, center_x+x_delta, center_y+y_delta);
535         gr_line(center_x-x_delta, center_y+y_delta, center_x+x_delta, center_y-y_delta);
536 }
537
538
539 int subsys_is_fighterbay(ship_subsys *ss)
540 {
541         if ( !SDL_strncasecmp(NOX("fighter"), ss->system_info->name, 7) ) {
542                 return 1;
543         }
544
545         return 0;
546 }
547
548 //      Draw bounding brackets for a subobject.
549 void draw_bounding_brackets_subobject()
550 {
551         if (Player_ai->targeted_subsys_parent == Player_ai->target_objnum)
552                 if (Player_ai->targeted_subsys != NULL) {
553                         ship_subsys     *subsys;
554                         int             target_objnum;
555                         object* targetp;
556                         vertex subobj_vertex;
557                         vector  subobj_pos;
558                         int x1,x2,y1,y2;
559
560                         subsys = Player_ai->targeted_subsys;
561                         target_objnum = Player_ai->target_objnum;
562                         SDL_assert(target_objnum != -1);
563                         targetp = &Objects[target_objnum];
564                         SDL_assert( targetp->type == OBJ_SHIP );
565
566                         get_subsystem_world_pos(targetp, subsys, &subobj_pos);
567
568                         g3_rotate_vertex(&subobj_vertex,&subobj_pos);
569
570                         g3_project_vertex(&subobj_vertex);
571                         if (subobj_vertex.flags & PF_OVERFLOW)  // if overflow, no point in drawing brackets
572                                 return;
573
574                         int subobj_x = fl2i(subobj_vertex.sx + 0.5f);
575                         int subobj_y = fl2i(subobj_vertex.sy + 0.5f);
576                         int hud_subtarget_w, hud_subtarget_h, bound_rc;
577
578                         bound_rc = subobj_find_2d_bound(subsys->system_info->radius, &targetp->orient, &subobj_pos, &x1,&y1,&x2,&y2);
579                         if ( bound_rc != 0 )
580                                 return;
581
582                         hud_subtarget_w = x2-x1+1;
583                         if ( hud_subtarget_w > gr_screen.clip_width ) {
584                                 hud_subtarget_w = gr_screen.clip_width;
585                         }
586
587                         hud_subtarget_h = y2-y1+1;
588                         if ( hud_subtarget_h > gr_screen.clip_height ) {
589                                 hud_subtarget_h = gr_screen.clip_height;
590                         }
591
592                         if ( hud_subtarget_w > gr_screen.max_w ) {
593                                 x1 = subobj_x - (gr_screen.max_w>>1);
594                                 x2 = subobj_x + (gr_screen.max_w>>1);
595                         }
596                         if ( hud_subtarget_h > gr_screen.max_h ) {
597                                 y1 = subobj_y - (gr_screen.max_h>>1);
598                                 y2 = subobj_y + (gr_screen.max_h>>1);
599                         }
600
601                         if ( hud_subtarget_w < Min_subtarget_box_width[gr_screen.res] ) {
602                                 x1 = subobj_x - (Min_subtarget_box_width[gr_screen.res]>>1);
603                                 x2 = subobj_x + (Min_subtarget_box_width[gr_screen.res]>>1);
604                         }
605                         if ( hud_subtarget_h < Min_subtarget_box_height[gr_screen.res] ) {
606                                 y1 = subobj_y - (Min_subtarget_box_height[gr_screen.res]>>1);
607                                 y2 = subobj_y + (Min_subtarget_box_height[gr_screen.res]>>1);
608                         }
609
610                         // determine if subsystem is on far or near side of the ship
611                         Player->subsys_in_view = ship_subsystem_in_sight(targetp, subsys, &View_position, &subobj_pos, 0);
612
613                         // AL 29-3-98: If subsystem is destroyed, draw gray brackets                                    
614                         if ( (Player_ai->targeted_subsys->current_hits <= 0) && (!subsys_is_fighterbay(Player_ai->targeted_subsys)) ) {
615                                 gr_set_color_fast(&IFF_colors[IFF_COLOR_MESSAGE][1]);
616                         } else {
617                                 hud_set_iff_color( targetp, 1 );
618                         }
619
620                         if ( Player->subsys_in_view ) {
621                                 draw_brackets_square_quick(x1, y1, x2, y2);
622                         } else {
623                                 draw_brackets_diamond_quick(x1, y1, x2, y2);
624                         }
625                         // mprintf(("Drawing subobject brackets at %4i, %4i\n", sx, sy));
626                 }
627 }
628
629 extern int HUD_drew_selection_bracket_on_target;
630
631 // Display the current target distance, right justified at (x,y)
632 void hud_target_show_dist_on_bracket(int x, int y, float distance)
633 {
634         char    text_dist[64];
635         int     w,h;
636
637         if ( y < 0 || y > gr_screen.clip_height ) {
638                 return;
639         }
640
641         if ( x < 0 || x > gr_screen.clip_width ) {
642                 return;
643         }
644
645         SDL_snprintf(text_dist, SDL_arraysize(text_dist), "%d", fl2i(distance+0.5f));
646         hud_num_make_mono(text_dist);
647         gr_get_string_size(&w,&h,text_dist);
648
649         int y_delta = 4;
650         if ( HUD_drew_selection_bracket_on_target ) {
651                 y += 4;
652         }
653
654         gr_string(x - w+2, y+y_delta, text_dist);
655 }
656
657
658 // !!!!!!!!!!!!!!!
659 //      Given an object number, return the number of ships attacking it.
660 // MWA 5/26/98 -- copied from aicode num_attacking_ships()!!!
661 // !!!!!!!!!!!!!!!
662 int hud_bracket_num_ships_attacking(int objnum)
663 {
664         object  *objp;
665         ship_obj        *so;
666         int             count = 0;
667
668         for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
669                 objp = &Objects[so->objnum];
670                 if (objp->instance != -1) {
671                         ai_info *aip;
672                         aip = &Ai_info[Ships[objp->instance].ai_index];
673
674                         // don't count instructor
675                         extern int is_training_mission();
676                         if ( is_training_mission() && SDL_strcasecmp(Ships[objp->instance].ship_name, "Instructor") == 0) {
677                                 break;
678                         }
679
680                         if ( ((Game_mode & GM_MULTIPLAYER) || (aip->mode == AIM_CHASE)) && (aip->target_objnum == objnum))
681                                 if (Ships[objp->instance].team != Ships[Objects[objnum].instance].team)
682                                         count++;
683                 }
684         }
685
686         return count;
687 }
688
689
690 int     Ships_attacking_bitmap = -1;
691
692 // draw_bounding_brackets() will draw the faded brackets that surround the current target
693 void draw_bounding_brackets(int x1, int y1, int x2, int y2, int w_correction, int h_correction, float distance, int target_objnum)
694 {
695         int width, height;
696
697         if ( ( x1 < 0 && x2 < 0 ) || ( y1 < 0 && y2 < 0 ) )
698                 return;
699
700         if ( ( x1 > gr_screen.clip_width && x2 > gr_screen.clip_width ) ||
701                   ( y1 > gr_screen.clip_height && y2 > gr_screen.clip_height ) )
702                 return;
703
704         width = x2-x1;
705         SDL_assert(width>=0);
706
707         height = y2-y1;
708         SDL_assert(height>=0);
709
710         if ( (width>(gr_screen.max_w - 1)) && (height>(gr_screen.max_h - 1)) ) {
711                 return;
712         }
713         if ( width > 1200 ) {
714                 return;
715
716         }
717         if ( height > 1200) {
718                 return;
719         }
720
721         if (width < Min_target_box_width[gr_screen.res]) {
722                 x1 = x1 - (Min_target_box_width[gr_screen.res]-width)/2;
723                 x2 = x2 + (Min_target_box_width[gr_screen.res]-width)/2;
724         }
725
726         if (height < Min_target_box_height[gr_screen.res]) {
727                 y1 = y1 - (Min_target_box_height[gr_screen.res]-height)/2;
728                 y2 = y2 + (Min_target_box_height[gr_screen.res]-height)/2;
729         }
730                 
731         draw_brackets_square(x1-w_correction, y1-h_correction, x2+w_correction, y2+h_correction);
732
733         // draw distance to target in lower right corner of box
734         if ( distance > 0 ) {
735                 hud_target_show_dist_on_bracket(x2+w_correction,y2+h_correction,distance);
736         }
737
738         //      Maybe show + for each additional fighter or bomber attacking target.
739         if ( (target_objnum != -1) && hud_gauge_active(HUD_ATTACKING_TARGET_COUNT) ) {
740                 int num_attacking = hud_bracket_num_ships_attacking(target_objnum);
741
742                 if (Ships_attacking_bitmap == -1){
743                         Ships_attacking_bitmap = bm_load(Ships_attack_fname[gr_screen.res]);
744                 }
745
746                 if (Ships_attacking_bitmap == -1) {
747                         Int3();
748                         return;
749                 }
750
751                 //      If a ship not on player's team, show one fewer plus since it is targeted and attacked by player.
752                 int     k=0;
753                 if (Objects[target_objnum].type == OBJ_SHIP) {
754                         if (Ships[Objects[target_objnum].instance].team != Player_ship->team){
755                                 k = 1;
756                         }
757                 } else {
758                         k = 1;
759                 }
760
761                 if (num_attacking > k) {
762                         int     i, num_blips;
763                         
764                         num_blips = num_attacking-k;
765                         if (num_blips > 4){
766                                 num_blips = 4;
767                         }
768
769                         //int   bitmap = get_blip_bitmap();
770
771                         if (Ships_attacking_bitmap > -1) {
772                                 if (num_blips > 3)
773                                         y1 -= 3;
774
775                                 for (i=0; i<num_blips; i++) {
776                                         GR_AABITMAP(Ships_attacking_bitmap, x2+3, y1+i*7);                                      
777                                 }
778                         }
779                 }
780         }
781 }
782