FS2_Open
Open source remastering of the Freespace 2 engine
hudtarget.cpp
Go to the documentation of this file.
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 the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "asteroid/asteroid.h"
14 #include "cmdline/cmdline.h"
15 #include "debris/debris.h"
16 #include "freespace2/freespace.h" // for flFrametime
17 #include "gamesnd/gamesnd.h"
18 #include "globalincs/alphacolors.h"
19 #include "globalincs/linklist.h"
20 #include "hud/hudartillery.h"
21 #include "hud/hudbrackets.h"
22 #include "hud/hudlock.h"
23 #include "hud/hudmessage.h"
24 #include "hud/hudparse.h"
25 #include "hud/hudreticle.h"
26 #include "hud/hudshield.h"
27 #include "hud/hudtarget.h"
28 #include "hud/hudtargetbox.h"
29 #include "iff_defs/iff_defs.h"
30 #include "io/timer.h"
31 #include "jumpnode/jumpnode.h"
32 #include "localization/localize.h"
33 #include "mission/missionhotkey.h"
34 #include "mission/missionmessage.h"
35 #include "model/model.h"
36 #include "network/multi.h"
37 #include "network/multiutil.h"
38 #include "object/object.h"
39 #include "parse/parselo.h"
40 #include "playerman/player.h"
41 #include "render/3dinternal.h"
42 #include "ship/awacs.h"
43 #include "ship/ship.h"
44 #include "ship/subsysdamage.h"
45 #include "weapon/emp.h"
46 #include "weapon/weapon.h"
47 
48 // If any of these bits in the ship->flags are set, ignore this ship when targeting
50 
51 // Global values for the target bracket width and height, used for debugging
53 
54 // offscreen triangle that point the the off-screen target
56  6.0f,
57  9.5f
58 };
60  7.0f,
61  11.0f
62 };
64  10.0f,
65  16.0f
66 };
68  10.0f,
69  16.0f
70 };
71 
73 
74 // The following variables are global to this file, and do not need to be persistent from frame-to-frame
75 // This means the variables are not player-specific
76 object* hostile_obj = NULL;
77 
78 static int ballistic_hud_index = 0; // Goober5000
79 
80 extern object obj_used_list; // dummy node in linked list of active objects
81 extern char *Cargo_names[];
82 
83 // shader is used to shade the target box
85 
86 // the target triangle (that orbits the reticle) dimensions
88  6.0f,
89  9.5f
90 };
92  7.0f,
93  11.0f
94 };
95 
96 // stuff for hotkey targeting lists
99 
100 /*
101 // coordinates and widths used to render the HUD afterburner energy gauge
102 int current_hud->Aburn_coords[GR_NUM_RESOLUTIONS][4] = {
103  { // GR_640
104  171, 265, 60, 60
105  },
106  { // GR_1024
107  274, 424, 86, 96
108  }
109 };
110 
111 // coordinates and widths used to render the HUD weapons energy gauge
112 int current_hud->Wenergy_coords[GR_NUM_RESOLUTIONS][4] = {
113  { // GR_640
114  416, 265, 60, 60
115  },
116  { // GR_1024
117  666, 424, 86, 96
118  }
119 };*/
120 
121 #define MIN_DISTANCE_TO_CONSIDER_THREAT 1500 // min distance to show hostile warning triangle
122 
124 // lists for target in reticle cycling
126 #define RL_USED (1<<0)
127 #define RL_USE_DOT (1<<1) // use dot product result, not distance
128 
129 typedef struct _reticle_list {
131  object *objp;
132  float dist, dot;
133  int flags;
134 } reticle_list;
135 
136 #define RESET_TARGET_IN_RETICLE 750
140 #define MAX_RETICLE_TARGETS 50
142 
144 // used for closest target cycling
146 #define TL_RESET 1500
147 #define TURRET_RESET 1000
148 static int Tl_hostile_reset_timestamp;
149 static int Tl_friendly_reset_timestamp;
150 static int Target_next_uninspected_object_timestamp;
151 static int Target_newest_ship_timestamp;
152 static int Target_next_turret_timestamp;
153 
154 // animation frames for the hud targeting gauges
155 // frames: 0 => out of range lead
156 // 1 => in range lead
158 {
159  {
160  { // GR_640
161  12.5f, // half-width
162  12.5f // half-height
163  },
164  { // GR_1024
165  20.0f, // half-width
166  20.0f // half-height
167  }
168  },
169  {
170  { // GR_640
171  8.0f, // half-width
172  8.0f // half-height
173  },
174  { // GR_1024
175  13.0f, // half-width
176  13.0f // half-height
177  }
178  }
179 };
183 {
184  { "lead1_fs1", "2_lead1_fs1" },
185  { "lead1", "2_lead1" }
186 };
187 
188 // animation frames for the countermeasures gauge
189 // frames: 0 => background
193  { // GR_640
194  497, 343
195  },
196  { // GR_1024
197  880, 602
198  }
199 };
201  { // GR_640
202  533, 347
203  },
204  { // GR_1024
205  916, 606
206  }
207 };
209  { // GR_640
210  506, 347
211  },
212  { // GR_1024
213  889, 606
214  }
215 };
217  "countermeasure1",
218  "countermeasure1"
219 };
220 
221 #define TOGGLE_TEXT_AUTOT 0
222 #define TOGGLE_TEXT_TARGET 1
223 #define TOGGLE_TEXT_AUTOS 2
224 #define TOGGLE_TEXT_SPEED 3
225 
227 
228 
229 // animation files for the weapons gauge
230 #define NUM_WEAPON_GAUGES 5
234 // for primaries
236 {
237  { // normal HUD
238  { // GR_640
239  // based on the # of primaries
240  {509, 273}, // top of weapon gauge, first frame, always
241  {497, 293}, // for the first primary
242  {497, 305} // for the second primary
243  },
244  { // GR_1024
245  // based on the # of primaries
246  {892, 525}, // top of weapon gauge, first frame, always
247  {880, 545}, // for the first primary
248  {880, 557} // for the second primary
249  }
250  },
251  { // ballistic HUD - slightly different alignment
252  { // GR_640
253  // based on the # of primaries
254  {485, 273}, // top of weapon gauge, first frame, always
255  {485, 293}, // for the first primary
256  {485, 305} // for the second primary
257  },
258  { // GR_1024
259  // based on the # of primaries
260  {868, 525}, // top of weapon gauge, first frame, always
261  {868, 545}, // for the first primary
262  {868, 557} // for the second primary
263  }
264  }
265 };
267 {
268  { // normal HUD
269  { // GR_640
270  // based on the # of secondaries
271  {497, 318}, // bottom of gauge, 0 secondaries
272  {497, 318}, // bottom of gauge, 1 secondaries
273  {497, 317}, // middle of gauge, 2 secondaries AND middle of gauge, 3 secondaries
274  {497, 326}, // bottom of gauge, 2 secondaries AND middle of gauge, 3 secondaries
275  {497, 335} // bottom of gauge, 3 secondaries
276  },
277  { // GR_1024
278  // based on the # of secondaries
279  {880, 570}, // bottom of gauge, 0 secondaries
280  {880, 570}, // bottom of gauge, 1 secondaries
281  {880, 569}, // middle of gauge, 2 secondaries AND middle of gauge, 3 secondaries
282  {880, 578}, // bottom of gauge, 2 secondaries AND middle of gauge, 3 secondaries
283  {880, 587} // bottom of gauge, 3 secondaries
284  }
285  },
286  { // ballistic HUD - slightly different alignment
287  { // GR_640
288  // based on the # of secondaries
289  {485, 318}, // bottom of gauge, 0 secondaries
290  {485, 318}, // bottom of gauge, 1 secondaries
291  {485, 317}, // middle of gauge, 2 secondaries AND middle of gauge, 3 secondaries
292  {485, 326}, // bottom of gauge, 2 secondaries AND middle of gauge, 3 secondaries
293  {485, 335} // bottom of gauge, 3 secondaries
294  },
295  { // GR_1024
296  // based on the # of secondaries
297  {868, 570}, // bottom of gauge, 0 secondaries
298  {868, 570}, // bottom of gauge, 1 secondaries
299  {868, 569}, // middle of gauge, 2 secondaries AND middle of gauge, 3 secondaries
300  {868, 578}, // bottom of gauge, 2 secondaries AND middle of gauge, 3 secondaries
301  {868, 587} // bottom of gauge, 3 secondaries
302  }
303  }
304 };
306 {
307  { // normal HUD
308  { // GR_640
309  518, 274
310  },
311  { // GR_1024
312  901, 527
313  }
314  },
315  { // ballistic HUD - slightly different alignment
316  { // GR_640
317  487, 274
318  },
319  { // GR_1024
320  870, 527
321  }
322  }
323 };
325  { // GR_640
326  {530, 285}, // fire-linked thingie, for the first primary
327  {530, 295} // fire-linked thingie, for the second primary
328  },
329  { // GR_1024
330  {913, 537}, // fire-linked thingie, for the first primary
331  {913, 547} // fire-linked thingie, for the second primary
332  }
333 };
335  { // GR_640
336  {536, 285}, // weapon name, first primary
337  {536, 295} // weapon name, second primary
338  },
339  { // GR_1024
340  {919, 537}, // weapon name, first primary
341  {919, 547} // weapon name, second primary
342  }
343 };
345  525, // where to draw the second thingie if this weapon is fire-linked
346  908
347 };
349  530, // where to draw the first thingie if this weapon is selected at all (fire-linked or not)
350  913
351 };
353  { // GR_640
354  309, // y location of where to draw text for the first secondary
355  318, // y location of where to draw text for the second secondary
356  327 // y location of where to draw text for the third secondary
357  },
358  { // GR_1024
359  561, // y location of where to draw text for the third secondary
360  570, // y location of where to draw text for the third secondary
361  579 // y location of where to draw text for the third secondary
362  }
363 };
365  { // GR_640
366  285, // y location of where to draw text for the first primary
367  295 // y location of where to draw text for the second primary
368  },
369  { // GR_1024
370  537, // y location of where to draw text for the first primary
371  547 // y location of where to draw text for the second primary
372  }
373 };
375  536, // x location of where to draw weapon name
376  919
377 };
379  525, // x location of where to draw weapon ammo count
380  908
381 };
383  525, // x location of where to draw primary weapon ammo count
384  908
385 };
387  615, // x location of where to draw the weapon reload time
388  998
389 };
391 {
392 //XSTR:OFF
393  { // normal HUD
394  { // GR_640
395  "weapons1",
396  "weapons2",
397  "weapons3",
398  "weapons4",
399  "weapons5"
400  },
401  { // GR_1024
402  "weapons1",
403  "weapons2",
404  "weapons3",
405  "weapons4",
406  "weapons5"
407  }
408  },
409  { // ballistic HUD - slightly different alignment
410  { // GR_640
411  "weapons1_b",
412  "weapons2_b",
413  "weapons3_b",
414  "weapons4_b",
415  "weapons5_b"
416  },
417  { // GR_1024
418  "weapons1_b",
419  "weapons2_b",
420  "weapons3_b",
421  "weapons4_b",
422  "weapons5_b"
423  }
424  }
425 //XSTR:ON
426 };
427 
428 // Flash the line for a weapon. This normally occurs when the player tries to fire that
429 // weapon, but the firing fails (due to lack of energy or damaged weapons subsystem).
430 #define MAX_WEAPON_FLASH_LINES 7 // 3 primary and 4 secondary
431 typedef struct weapon_flash
432 {
436 } weapon_flash;
438 
439 // Data used for the proximity warning
440 typedef struct homing_beep_info
441 {
442  int snd_handle; // sound handle for last played beep
443  fix last_time_played; // time beep was last played
444  int min_cycle_time; // time (in ms) for fastest cycling of the sound
445  int max_cycle_time; // time (in ms) for slowest cycling of the sound
446  float min_cycle_dist; // distance at which fastest cycling occurs
447  float max_cycle_dist; // distance at which slowest cycling occurs
448  float precalced_interp; // a precalculated value used in a linear interpretation
450 
451 homing_beep_info Homing_beep = { -1, 0, 150, 1000, 30.0f, 1500.0f, 1.729412f };
452 
453 // Set at the start of a mission, used to decide how to draw the separation for the warning missile indicators
456 
457 void hud_maybe_flash_weapon(int index);
458 
459 // if a given object should be ignored because of AWACS effects
461 {
462  // if objp is ship object, first check if can be targeted with team info
463  if (objp->type == OBJ_SHIP) {
464  if (Player_ship != NULL) {
466  return 0;
467  }
468  }
469  }
470 
471  // check for invalid status
472  if((Player_ship != NULL) && (awacs_get_level(objp, Player_ship) < 1.0f)){
473  return 1;
474  }
475 
476  // valid
477  return 0;
478 }
479 
481 {
482  if (next_flag) {
483  return GET_NEXT(cur);
484  } else {
485  return GET_LAST(cur);
486  }
487 }
488 
489 // select a sorted turret subsystem on a ship if no other subsys has been selected
491 {
493  if (!((Player_ai->target_objnum >= 0) && (Player_ai->target_objnum < MAX_OBJECTS))) {
494  return;
495  }
498  return;
499  }
500 
501  if (Ship_info[shipp->ship_info_index].flags & (SIF_BIG_SHIP|SIF_HUGE_SHIP)) {
502  if (shipp->last_targeted_subobject[Player_num] == NULL) {
504  }
505  }
506 
507 }
508 
509 // -----------------------------------------------------------------------
510 // clear out the linked list of targets in the reticle
512 {
513  reticle_list *cur;
514  for ( cur = GET_FIRST(rlist); cur != END_OF_LIST(rlist); cur = GET_NEXT(cur) ) {
515  cur->flags = 0;
516  }
517  list_init(rlist);
518 }
519 
520 // --------------------------------------------------------------------------------------
521 // hud_reticle_list_init()
523 {
524  int i;
525 
526  for ( i = 0; i < MAX_RETICLE_TARGETS; i++ ) {
527  Reticle_list[i].flags = 0;
528  }
529 
531  list_init(&Reticle_save_list);
532  list_init(&Reticle_cur_list);
533 }
534 
535 // --------------------------------------------------------------------------------------
536 // hud_check_reticle_list()
537 //
538 //
540 {
541  reticle_list *rl, *temp;
542 
543  // cull dying objects from reticle list
544  rl = GET_FIRST(&Reticle_cur_list);
545  while( rl !=END_OF_LIST(&Reticle_cur_list) ) {
546  temp = GET_NEXT(rl);
547  if ( rl->objp->flags & OF_SHOULD_BE_DEAD ) {
548  list_remove( &Reticle_cur_list, rl );
549  rl->flags = 0;
550  }
551  rl = temp;
552  }
553 
555  hud_reticle_clear_list(&Reticle_save_list);
557  }
558 }
559 
560 // --------------------------------------------------------------------------------------
561 // hud_reticle_list_find_free()
562 //
563 //
565 {
566  int i;
567 
568  // find a free reticle_list element
569  for ( i = 0; i < MAX_RETICLE_TARGETS; i++ ) {
570  if ( !(Reticle_list[i].flags & RL_USED) ) {
571  break;
572  }
573  }
574 
575  if ( i == MAX_RETICLE_TARGETS ) {
576 // nprintf(("Warning","Warning ==> Ran out of reticle target elements...\n"));
577  return -1;
578  }
579 
580  return i;
581 }
582 
583 // --------------------------------------------------------------------------------------
584 // hud_stuff_reticle_list()
585 //
586 //
587 #define RETICLE_DEFAULT_DIST 100000.0f
588 #define RETICLE_DEFAULT_DOT 1.0f
589 void hud_stuff_reticle_list(reticle_list *rl, object *objp, float measure, int dot_flag)
590 {
591  if ( dot_flag ) {
592  rl->dot = measure;
594  rl->flags |= RL_USE_DOT;
595  }
596  else {
597  rl->dist = measure;
598  rl->dot = RETICLE_DEFAULT_DOT;
599  }
600  rl->objp = objp;
601 }
602 
603 // --------------------------------------------------------------------------------------
604 // hud_reticle_list_update()
605 //
606 // Update Reticle_cur_list with an object that lies in the reticle
607 //
608 // parmeters: objp => object pointer to target
609 // measure => distance or dot product, depending on dot_flag
610 // dot_flag => if 0, measure is distance, if 1 measure is dot
611 //
612 void hud_reticle_list_update(object *objp, float measure, int dot_flag)
613 {
614  reticle_list *rl, *new_rl;
615  int i;
617 
618  if (objp->type == OBJ_JUMP_NODE) {
619  for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
620  if( jnp->GetSCPObject() != objp )
621  continue;
622 
623  if( jnp->IsHidden() )
624  return;
625  }
626  }
627 
628  for ( rl = GET_FIRST(&Reticle_cur_list); rl != END_OF_LIST(&Reticle_cur_list); rl = GET_NEXT(rl) ) {
629  if ( rl->objp == objp )
630  return;
631  }
632 
634  if ( i == -1 )
635  return;
636 
637  new_rl = &Reticle_list[i];
638  new_rl->flags |= RL_USED;
639  hud_stuff_reticle_list(new_rl, objp, measure, dot_flag);
640 
641  int was_inserted = 0;
642 
643  if ( EMPTY(&Reticle_cur_list) ) {
644  list_insert(&Reticle_cur_list, new_rl);
645  was_inserted = 1;
646  }
647  else {
648  for ( rl = GET_FIRST(&Reticle_cur_list); rl != END_OF_LIST(&Reticle_cur_list); rl = GET_NEXT(rl) ) {
649  if ( !dot_flag ) {
650  // compare based on distance
651  if ( measure < rl->dist ) {
652  list_insert_before(rl, new_rl);
653  was_inserted = 1;
654  break;
655  }
656  }
657  else {
658  // compare based on dot
659  if ( measure > rl->dot ) {
660  list_insert_before(rl, new_rl);
661  was_inserted = 1;
662  break;
663  }
664  }
665  } // end for
666  }
667 
668  if ( !was_inserted ) {
669  list_append(&Reticle_cur_list, new_rl);
670  }
671 }
672 
673 // --------------------------------------------------------------------------------------
674 // hud_reticle_pick_target()
675 //
676 // Pick a target from Reticle_cur_list, based on what is in Reticle_save_list
677 //
678 //
680 {
681  reticle_list *cur_rl, *save_rl, *new_rl;
682  object *return_objp;
683  int in_save_list, i;
684 
685  return_objp = NULL;
686 
687  // As a first step, see if both ships and debris are in the list. If so, cull the debris.
688  int debris_in_list = 0;
689  int ship_in_list = 0;
690  for ( cur_rl = GET_FIRST(&Reticle_cur_list); cur_rl != END_OF_LIST(&Reticle_cur_list); cur_rl = GET_NEXT(cur_rl) ) {
691  if ( (cur_rl->objp->type == OBJ_SHIP) || (cur_rl->objp->type == OBJ_JUMP_NODE) ) {
692  ship_in_list = 1;
693  continue;
694  }
695 
696  if ( cur_rl->objp->type == OBJ_WEAPON ) {
698  ship_in_list = 1;
699  continue;
700  }
701  }
702 
703  if ( (cur_rl->objp->type == OBJ_DEBRIS) || (cur_rl->objp->type == OBJ_ASTEROID) ) {
704  debris_in_list = 1;
705  continue;
706  }
707  }
708 
709  if ( ship_in_list && debris_in_list ) {
710  // cull debris
711  reticle_list *rl, *next;
712 
713  rl = GET_FIRST(&Reticle_cur_list);
714  while ( rl != &Reticle_cur_list ) {
715  next = rl->next;
716  if ( (rl->objp->type == OBJ_DEBRIS) || (rl->objp->type == OBJ_ASTEROID) ){
717  list_remove(&Reticle_cur_list,rl);
718  rl->flags = 0;
719  }
720  rl = next;
721  }
722  }
723 
724  for ( cur_rl = GET_FIRST(&Reticle_cur_list); cur_rl != END_OF_LIST(&Reticle_cur_list); cur_rl = GET_NEXT(cur_rl) ) {
725  in_save_list = 0;
726  for ( save_rl = GET_FIRST(&Reticle_save_list); save_rl != END_OF_LIST(&Reticle_save_list); save_rl = GET_NEXT(save_rl) ) {
727  if ( cur_rl->objp == save_rl->objp ) {
728  in_save_list = 1;
729  break;
730  }
731  }
732 
733  if ( !in_save_list ) {
734  return_objp = cur_rl->objp;
736  if ( i == -1 )
737  break;
738 
739  new_rl = &Reticle_list[i];
740  new_rl->flags |= RL_USED;
741  if ( cur_rl->flags & RL_USE_DOT ) {
742  hud_stuff_reticle_list(new_rl, cur_rl->objp, cur_rl->dot, 1);
743  }
744  else {
745  hud_stuff_reticle_list(new_rl, cur_rl->objp, cur_rl->dist, 0);
746  }
747 
748  list_append(&Reticle_save_list, new_rl);
749  break;
750  }
751  } // end for
752 
753  if ( return_objp == NULL && !EMPTY(&Reticle_cur_list) ) {
755  if ( i == -1 )
756  return NULL;
757  new_rl = &Reticle_list[i];
758  cur_rl = GET_FIRST(&Reticle_cur_list);
759  *new_rl = *cur_rl;
760  return_objp = cur_rl->objp;
761  hud_reticle_clear_list(&Reticle_save_list);
762  list_append(&Reticle_save_list, new_rl);
763  }
764 
765  return return_objp;
766 }
767 
768 // hud_target_hotkey_add_remove takes as its parameter which hotkey (1-0) to add/remove the current
769 // target from. This function behaves like the Shift-<selection> does in Windows -- using shift # will toggle
770 // the current target in and out of the selection set.
771 void hud_target_hotkey_add_remove( int k, object *ctarget, int how_to_add )
772 {
773  htarget_list *hitem, *plist;
774 
775  // don't do anything if a standalone multiplayer server
777  return;
778 
779  if ( (k < 0) || (k >= MAX_KEYED_TARGETS) ) {
780  nprintf(("Warning", "Bogus hotkey %d sent to hud_target_hotkey_add_remove\n", k));
781  return;
782  }
783 
784  plist = &(Players[Player_num].keyed_targets[k]);
785 
786  // we must operate only on ships
787  if ( ctarget->type != OBJ_SHIP )
788  return;
789 
790  // don't allow player into hotkey set
791  if ( ctarget == Player_obj )
792  return;
793 
794  // don't put dying or departing
795  if ( Ships[ctarget->instance].flags & (SF_DYING|SF_DEPARTING) )
796  return;
797 
798  // don't add mission file added hotkey assignments if there are player added assignments
799  // already in the list
800  if ( (how_to_add == HOTKEY_MISSION_FILE_ADDED) && NOT_EMPTY(plist) ) {
801  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
802  if ( hitem->how_added == HOTKEY_USER_ADDED )
803  return;
804  }
805  }
806 
807  // determine if the current target is currently in the set or not
808  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
809  if ( hitem->objp == ctarget )
810  break;
811  }
812 
813  // if hitem == end of the list, then the target should be added, else it should be removed
814  if ( hitem == END_OF_LIST(plist) ) {
815  if ( EMPTY(&htarget_free_list) ) {
816  Int3(); // get Allender -- no more free hotkey target items
817  return;
818  }
819 
820  nprintf(("network", "Hotkey: Adding %s\n", Ships[ctarget->instance].ship_name));
821  hitem = GET_FIRST( &htarget_free_list );
822  list_remove( &htarget_free_list, hitem );
823  list_append( plist, hitem );
824  hitem->objp = ctarget;
825  hitem->how_added = how_to_add;
826  } else {
827  nprintf(("network", "Hotkey: Removing %s\n", Ships[ctarget->instance].ship_name));
828  list_remove( plist, hitem );
829  list_append( &htarget_free_list, hitem );
830  hitem->objp = NULL; // for safety
831  }
832 }
833 
834 // the following function clears the hotkey set given by parameter passed in
836 {
837  htarget_list *hitem, *plist, *temp;
838 
839  plist = &(Players[Player_num].keyed_targets[k]);
840  hitem = GET_FIRST(plist);
841  while ( hitem != END_OF_LIST(plist) ) {
842  temp = GET_NEXT(hitem);
843  list_remove( plist, hitem );
844  list_append( &htarget_free_list, hitem );
845  hitem->objp = NULL;
846  hitem = temp;
847  }
848  if ( Players[Player_num].current_hotkey_set == k ) // clear this variable if we removed the bindings
850 }
851 
852 // the next function sets the current selected set to be N. If there is just one ship in the selection
853 // set, this ship will become the new target. If there is more than one ship in the selection set,
854 // then the current_target will remain what it was.
856 {
857  int visible_count = 0;
858  htarget_list *hitem, *plist, *target, *next_target, *first_target;
859  int target_objnum;
860 
861  plist = &(Players[Player_num].keyed_targets[k]);
862 
863  if ( EMPTY( plist ) ) // no items in list, then do nothing
864  return;
865 
866  // a simple walk of the list to get the count
867  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ){
868  if (awacs_get_level(hitem->objp, Player_ship, 1) > 1) {
869  visible_count++;
870  }
871  }
872 
873  // no visible ships in list
874  if (visible_count == 0) {
875  return;
876  }
877 
878  // set the current target to be the "next" ship in the list. Scan the list to see if our
879  // current target is in the set. If so, target the next ship in the list, otherwise target
880  // the first
881  // set first_target - first visible item in list
882  // target - item in list that is the player's currently selected target
883  // next_target - next visible item in list following target
884  target_objnum = Player_ai->target_objnum;
885  target = NULL;
886  next_target = NULL;
887  first_target = NULL;
888  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
889 
890  if (awacs_get_level(hitem->objp, Player_ship, 1) > 1) {
891  // get the first valid target
892  if (first_target == NULL) {
893  first_target = hitem;
894  }
895 
896  // get the next target in the list following the player currently selected target
897  if (target != NULL) {
898  next_target = hitem;
899  break;
900  }
901  }
902 
903  // mark the player currently selected target
904  if ( OBJ_INDEX(hitem->objp) == target_objnum ) {
905  target = hitem;
906  }
907  }
908 
909  // if current target is not in list, then target and next_target will be NULL
910  // so we use the first found target
911  if (target == NULL) {
912  Assert(first_target != NULL);
913  if (first_target != NULL) {
914  target = first_target;
915  next_target = first_target;
916  } else {
917  // this should not happen
918  return;
919  }
920  // if current target is in the list but this is not our current selection set,
921  // then we don't want to change target.
922  } else if (Players[Player_num].current_hotkey_set != k) {
923  next_target = target;
924  }
925 
926  // update target if more than 1 is visible
927  if (visible_count > 1) {
928  // next already found (after current target in list)
929  if (next_target != NULL) {
930  target = next_target;
931  } else {
932 
933  // next is before current target, so search from start of list
934  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
935  if (awacs_get_level(hitem->objp, Player_ship, 1) > 1) {
936  target = hitem;
937  break;
938  }
939  }
940  }
941  }
942 
943  Assert( target != END_OF_LIST(plist) );
944 
945  if ( Player_obj != target->objp ){
947  hud_shield_hit_reset(target->objp);
948  }
949 
951 }
952 
953 // hud_init_targeting_colors() will initialize the shader and gradient objects used
954 // on the HUD
955 //
956 
958 
959 void hud_make_shader(shader *sh, ubyte r, ubyte g, ubyte b, float dimmer = 1000.0f)
960 {
961  // The m matrix converts all colors to shades of green
962  //float tmp = 16.0f*(0.0015625f * i2fl(HUD_color_alpha+1.0f));
963  float tmp = 0.025f * i2fl(HUD_color_alpha+1.0f);
964 
965  ubyte R = ubyte(r * tmp);
966  ubyte G = ubyte(r * tmp);
967  ubyte B = ubyte(r * tmp);
968  ubyte A = ubyte((float(r) / dimmer)*(i2fl(HUD_color_alpha) / 15.0f) * 255.0f);
969 
970  gr_create_shader( sh, R, G, B, A );
971 }
972 
974 {
975  gr_init_color( &HUD_color_homing_indicator, 0x7f, 0x7f, 0 ); // yellow
976 
977  hud_make_shader(&Training_msg_glass, 61, 61, 85, 500.0f);
978 
980 }
981 
983 {
984  int i;
985 
986  // clear out the keyed target list
987  for (i = 0; i < MAX_KEYED_TARGETS; i++ )
988  list_init( &(Players[Player_num].keyed_targets[i]) );
989 
991 
992  // place all of the hoykey target items back onto the free list
993  list_init( &htarget_free_list );
994  for ( i = 0; i < MAX_HOTKEY_TARGET_ITEMS; i++ )
995  list_append( &htarget_free_list, &htarget_items[i] );
996 }
997 
998 // Init data used for the weapons display on the HUD
1000 {
1001  Weapon_flash_info.is_bright = 0;
1002  for ( int i = 0; i < MAX_WEAPON_FLASH_LINES; i++ ) {
1003  Weapon_flash_info.flash_duration[i] = 1;
1004  Weapon_flash_info.flash_next[i] = 1;
1005  }
1006 
1007  // The E: There used to be a number of checks here. They are no longer needed, as the new HUD code handles it on its own.
1009 }
1010 
1011 // init data used to play the homing "proximity warning" sound
1013 {
1014  Homing_beep.snd_handle = -1;
1015  Homing_beep.last_time_played = 0;
1016  Homing_beep.precalced_interp = (Homing_beep.max_cycle_dist-Homing_beep.min_cycle_dist) / (Homing_beep.max_cycle_time - Homing_beep.min_cycle_time );
1017 }
1018 
1020 {
1021  int i;
1022 
1023  // decide whether to realign HUD for ballistic primaries
1024  ballistic_hud_index = 0;
1025  for (i = 0; i < Player_ship->weapons.num_primary_banks; i++)
1026  {
1028  {
1029  ballistic_hud_index = 1;
1030  break;
1031  }
1032  }
1033 }
1034 
1035 // hud_init_targeting() will set the current target to point to the dummy node
1036 // in the object used list
1037 //
1039 {
1040  Assert(Player_ai != NULL);
1041 
1042  // make sure there is no current target
1044  Player_ai->last_target = -1;
1045  Player_ai->last_subsys_target = NULL;
1046  Player_ai->last_dist = 0.0f;
1047  Player_ai->last_speed = 0.0f;
1048 
1052 
1053  // Init the lists that hold targets in reticle (to allow cycling of targets in reticle)
1056 
1057  hud_weapons_init();
1058 
1060  Max_warning_missile_dist = 1500.0f;
1061 
1062  Tl_hostile_reset_timestamp = timestamp(0);
1063  Tl_friendly_reset_timestamp = timestamp(0);
1064  Target_next_uninspected_object_timestamp = timestamp(0);
1065  Target_newest_ship_timestamp = timestamp(0);
1066  Target_next_turret_timestamp = timestamp(0);
1067 
1070  } else {
1072  }
1073 }
1074 
1075 // Target the next or previous subobject on the currently selected ship, based on next_flag.
1076 void hud_target_subobject_common(int next_flag)
1077 {
1078  if (Player_ai->target_objnum == -1) {
1079  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "No target selected.", 322));
1081  return;
1082  }
1083 
1086  return;
1087  }
1088 
1089  ship_subsys *start, *start2, *A;
1090  ship_subsys *subsys_to_target=NULL;
1091  ship *target_shipp;
1092 
1093  target_shipp = &Ships[Objects[Player_ai->target_objnum].instance];
1094 
1095  if (!Player_ai->targeted_subsys) {
1096  start = END_OF_LIST(&target_shipp->subsys_list);
1097  } else {
1098  start = Player_ai->targeted_subsys;
1099  }
1100 
1101  start2 = advance_subsys(start, next_flag);
1102 
1103  for ( A = start2; A != start; A = advance_subsys(A, next_flag) ) {
1104 
1105  if ( A == &target_shipp->subsys_list ) {
1106  continue;
1107  }
1108 
1109  // ignore turrets
1110  if ( A->system_info->type == SUBSYSTEM_TURRET ) {
1111  continue;
1112  }
1113 
1114  if ( A->flags & SSF_UNTARGETABLE ) {
1115  continue;
1116  }
1117 
1118  subsys_to_target = A;
1119  break;
1120 
1121  } // end for
1122 
1123  if ( subsys_to_target == NULL ) {
1125  } else {
1128  }
1129 }
1130 
1131 object *advance_fb(object *objp, int next_flag)
1132 {
1133  if (next_flag)
1134  return GET_NEXT(objp);
1135  else
1136  return GET_LAST(objp);
1137 }
1138 
1139 // Target the previous subobject on the currently selected ship.
1140 //
1141 
1143 {
1145 }
1146 
1148 {
1150 }
1151 
1152 // hud_target_next() will set the Players[Player_num].current_target to the next target in the object
1153 // used list whose team matches the team parameter. The player is NOT included in the target list.
1154 //
1155 // parameters: team_mask => team(s) of ship to target next
1156 //
1157 
1158 void hud_target_common(int team_mask, int next_flag)
1159 {
1160  object *A, *start, *start2;
1161  ship *shipp;
1162  int is_ship, target_found = FALSE;
1164 
1165  if (Player_ai->target_objnum == -1)
1166  start = &obj_used_list;
1167  else
1168  start = &Objects[Player_ai->target_objnum];
1169 
1170  start2 = advance_fb(start, next_flag);
1171 
1172  for ( A = start2; A != start; A = advance_fb(A, next_flag) ) {
1173  is_ship = 0;
1174 
1175  if (A == &obj_used_list)
1176  continue;
1177 
1178  if ( (A == Player_obj) || ((A->type != OBJ_SHIP) && (A->type != OBJ_WEAPON) && (A->type != OBJ_JUMP_NODE)) )
1179  continue;
1180 
1181  if ( hud_target_invalid_awacs(A) )
1182  continue;
1183 
1184  if (A->type == OBJ_WEAPON) {
1187  continue;
1188 
1189  if (Weapons[A->instance].lssm_stage == 3)
1190  continue;
1191  }
1192 
1193  if (A->type == OBJ_SHIP) {
1195  continue;
1196 
1197  is_ship = 1;
1198  }
1199 
1200  if (A->type == OBJ_JUMP_NODE) {
1201  for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
1202  if( jnp->GetSCPObject() == A )
1203  break;
1204  }
1205 
1206  if( jnp->IsHidden() )
1207  continue;
1208  }
1209 
1210  if ( vm_vec_same(&A->pos, &Eye_position) )
1211  continue;
1212 
1213  if ( is_ship ) {
1214  shipp = &Ships[A->instance]; // get a pointer to the ship information
1215 
1216  if (!iff_matches_mask(shipp->team, team_mask)) {
1217  continue;
1218  }
1219 
1220  if ( A == Player_obj || (shipp->flags & TARGET_SHIP_IGNORE_FLAGS) ){
1221  continue;
1222  }
1223 
1224  // if we've reached here, it is a valid next target
1225  if ( Player_ai->target_objnum != A-Objects ) {
1226  target_found = TRUE;
1229  // if ship is BIG|HUGE and last subsys is NULL, get turret
1232  }
1233  } else {
1234  target_found = TRUE;
1237  }
1238 
1239  break;
1240  }
1241 
1242  if ( target_found == FALSE ) {
1244  }
1245 }
1246 
1247 void hud_target_next(int team_mask)
1248 {
1249  hud_target_common(team_mask, 1);
1250 }
1251 
1252 void hud_target_prev(int team_mask)
1253 {
1254  hud_target_common(team_mask, 0);
1255 }
1256 
1257 // -------------------------------------------------------------------
1258 // advance_missile_obj()
1259 //
1261 {
1262  if (next_flag){
1263  return GET_NEXT(mo);
1264  }
1265 
1266  return GET_LAST(mo);
1267 }
1268 
1269 ship_obj *advance_ship(ship_obj *so, int next_flag)
1270 {
1271  if (next_flag){
1272  return GET_NEXT(so);
1273  }
1274 
1275  return GET_LAST(so);
1276 }
1277 
1296 static object* select_next_target_by_distance( const bool targeting_from_closest_to_farthest, const int valid_team_mask, const int attacked_object_number = -1, const int target_filters = (SIF_CARGO | SIF_NAVBUOY)) {
1297  object *minimum_object_ptr, *maximum_object_ptr, *nearest_object_ptr;
1298  minimum_object_ptr = maximum_object_ptr = nearest_object_ptr = NULL;
1299  float current_distance = hud_find_target_distance(&Objects[Player_ai->target_objnum], Player_obj);
1300  float minimum_distance = 1e20f;
1301  float maximum_distance = 0.0f;
1302  int player_object_index = OBJ_INDEX(Player_obj);
1303 
1304  float nearest_distance;
1305  if ( targeting_from_closest_to_farthest ) {
1306  nearest_distance = 1e20f;
1307  } else {
1308  nearest_distance = 0.0f;
1309  }
1310 
1311  ship_obj *ship_object_ptr;
1312  object *prospective_victim_ptr;
1313  ship *prospective_victim_ship_ptr;
1314  for ( ship_object_ptr = GET_FIRST(&Ship_obj_list); ship_object_ptr != END_OF_LIST(&Ship_obj_list); ship_object_ptr = GET_NEXT( ship_object_ptr) ) {
1315  prospective_victim_ptr = &Objects[ ship_object_ptr->objnum];
1316  // get a pointer to the ship information
1317  prospective_victim_ship_ptr = &Ships[prospective_victim_ptr->instance];
1318 
1319  float new_distance;
1320  if ( (prospective_victim_ptr == Player_obj) || (prospective_victim_ship_ptr->flags & TARGET_SHIP_IGNORE_FLAGS) ) {
1321  continue;
1322  }
1323 
1324  // choose from the correct team
1325  if ( !iff_matches_mask(prospective_victim_ship_ptr->team, valid_team_mask) ) {
1326  continue;
1327  }
1328 
1329  // don't use object if it is already a target
1330  if ( OBJ_INDEX(prospective_victim_ptr) == Player_ai->target_objnum ) {
1331  continue;
1332  }
1333 
1334 
1335  if( attacked_object_number == -1 ) {
1336  // always ignore navbuoys and cargo
1337  if ( Ship_info[prospective_victim_ship_ptr->ship_info_index].flags & target_filters ) {
1338  continue;
1339  }
1340 
1341  if(hud_target_invalid_awacs(prospective_victim_ptr)){
1342  continue;
1343  }
1344 
1345  new_distance = hud_find_target_distance(prospective_victim_ptr,Player_obj);
1346  } else {
1347  // Filter out any target that is not targeting the player --Mastadon
1348  if ( (attacked_object_number == player_object_index) && (Ai_info[prospective_victim_ship_ptr->ai_index].target_objnum != player_object_index) ) {
1349  continue;
1350  }
1351  esct eval_ship_as_closest_target_args;
1352  eval_ship_as_closest_target_args.attacked_objnum = attacked_object_number;
1353  eval_ship_as_closest_target_args.check_all_turrets = (attacked_object_number == player_object_index);
1354  eval_ship_as_closest_target_args.check_nearest_turret = FALSE;
1355  // We don't ever filter our target selection to just bombers or fighters
1356  // because the select next attacker logic doesn't. --Mastadon
1357  eval_ship_as_closest_target_args.filter = 0;
1358  eval_ship_as_closest_target_args.team_mask = valid_team_mask;
1359  // We always get the turret attacking, since that's how the select next
1360  // attacker logic does it. --Mastadon
1361  eval_ship_as_closest_target_args.turret_attacking_target = 1;
1362  eval_ship_as_closest_target_args.shipp = prospective_victim_ship_ptr;
1363  evaluate_ship_as_closest_target( &eval_ship_as_closest_target_args );
1364 
1365  new_distance = eval_ship_as_closest_target_args.min_distance;
1366  }
1367 
1368 
1369  if (new_distance <= minimum_distance) {
1370  minimum_distance = new_distance;
1371  minimum_object_ptr = prospective_victim_ptr;
1372  }
1373 
1374  if (new_distance >= maximum_distance) {
1375  maximum_distance = new_distance;
1376  maximum_object_ptr = prospective_victim_ptr;
1377  }
1378 
1379  float diff = 0.0f;
1380  if ( targeting_from_closest_to_farthest ) {
1381  diff = new_distance - current_distance;
1382  if ( diff > 0.0f ) {
1383  if ( diff < ( nearest_distance - current_distance ) ) {
1384  nearest_distance = new_distance;
1385  nearest_object_ptr = prospective_victim_ptr;
1386  }
1387  }
1388  } else {
1389  diff = current_distance - new_distance;
1390  if ( diff > 0.0f ) {
1391  if ( diff < ( current_distance - nearest_distance ) ) {
1392  nearest_distance = new_distance;
1393  nearest_object_ptr = prospective_victim_ptr;
1394  }
1395  }
1396  }
1397  }
1398 
1399  if ( nearest_object_ptr == NULL ) {
1400 
1401  if ( targeting_from_closest_to_farthest ) {
1402  if ( minimum_object_ptr != NULL ) {
1403  nearest_object_ptr = minimum_object_ptr;
1404  }
1405  } else {
1406  if ( maximum_object_ptr != NULL ) {
1407  nearest_object_ptr = maximum_object_ptr;
1408  }
1409  }
1410  }
1411 
1412  return nearest_object_ptr;
1413 }
1414 
1416 // -------------------------------------------------------------------
1417 // hud_target_missile()
1418 //
1419 // Target the closest locked missile that is locked on locked_obj
1420 //
1421 // input: source_obj => pointer to object that fired weapon
1422 // next_flag => 0 -> previous 1 -> next
1423 //
1424 // NOTE: this function is only allows targeting bombs
1425 void hud_target_missile(object *source_obj, int next_flag)
1426 {
1427  missile_obj *end, *start, *mo;
1428  object *A, *target_objp;
1429  ai_info *aip;
1430  weapon *wp;
1431  weapon_info *wip;
1432  int target_found = 0;
1433 
1434  if ( source_obj->type != OBJ_SHIP )
1435  return;
1436 
1437  Assert( Ships[source_obj->instance].ai_index != -1 );
1438  aip = &Ai_info[Ships[source_obj->instance].ai_index];
1439 
1440  end = &Missile_obj_list;
1441  if (aip->target_objnum != -1) {
1442  target_objp = &Objects[aip->target_objnum];
1443  if ( target_objp->type == OBJ_WEAPON && Weapon_info[Weapons[target_objp->instance].weapon_info_index].subtype == WP_MISSILE ) { // must be a missile
1445  }
1446  }
1447 
1448  start = advance_missile_obj(end, next_flag);
1449 
1450  for ( mo = start; mo != end; mo = advance_missile_obj(mo, next_flag) ) {
1451  if ( mo == &Missile_obj_list ){
1452  continue;
1453  }
1454 
1455  Assert(mo->objnum >= 0 && mo->objnum < MAX_OBJECTS);
1456  A = &Objects[mo->objnum];
1457 
1458  Assert(A->type == OBJ_WEAPON);
1459  Assert((A->instance >= 0) && (A->instance < MAX_WEAPONS));
1460  wp = &Weapons[A->instance];
1461  wip = &Weapon_info[wp->weapon_info_index];
1462 
1463  // only allow targeting of bombs
1464  if ( !(wip->wi_flags2 & WIF2_CAN_BE_TARGETED) ) {
1465  if ( !(wip->wi_flags & WIF_BOMB) ) {
1466  continue;
1467  }
1468  }
1469 
1470  if (wp->lssm_stage==3){
1471  continue;
1472  }
1473 
1474  // only allow targeting of hostile bombs
1476  continue;
1477  }
1478 
1479  if(hud_target_invalid_awacs(A)){
1480  continue;
1481  }
1482 
1483  // if we've reached here, got a new target
1484  target_found = TRUE;
1485  set_target_objnum( aip, OBJ_INDEX(A) );
1487  break;
1488  } // end for
1489 
1490  if ( !target_found ) {
1491  // if no bomb is found, search for bombers
1492  ship_obj *startShip, *so;
1493 
1494  if ( (aip->target_objnum != -1)
1495  && (Objects[aip->target_objnum].type == OBJ_SHIP)
1496  && ((Ship_info[Ships[Objects[aip->target_objnum].instance].ship_info_index].flags & SIF_BOMBER)
1498  int index = Ships[Objects[aip->target_objnum].instance].ship_list_index;
1499  startShip = get_ship_obj_ptr_from_index(index);
1500  } else {
1501  startShip = GET_FIRST(&Ship_obj_list);
1502  }
1503 
1504  for (so=advance_ship(startShip, next_flag); so!=startShip; so=advance_ship(so, next_flag)) {
1505  A = &Objects[so->objnum];
1506 
1507  // don't look at header
1508  if (so == &Ship_obj_list) {
1509  continue;
1510  }
1511 
1512  // only allow targeting of hostile bombs
1514  continue;
1515  }
1516 
1517  if(hud_target_invalid_awacs(A)){
1518  continue;
1519  }
1520 
1521  // check if ship type is bomber
1522  if ( !(Ship_info[Ships[A->instance].ship_info_index].flags & SIF_BOMBER) && !(A->flags & OF_TARGETABLE_AS_BOMB) ) {
1523  continue;
1524  }
1525 
1526  // check if ignore
1527  if ( Ships[A->instance].flags & TARGET_SHIP_IGNORE_FLAGS ){
1528  continue;
1529  }
1530 
1531  // found a good one
1532  target_found = TRUE;
1533  set_target_objnum( aip, OBJ_INDEX(A) );
1535  break;
1536  }
1537  }
1538 
1539  if ( !target_found ) {
1540  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
1541  }
1542 }
1543 
1544 // Return !0 if shipp can be scanned, otherwise return 0
1546 {
1547  ship_info *sip;
1548 
1549  sip = &Ship_info[shipp->ship_info_index];
1550 
1551  // ignore cargo that has already been scanned
1552  if (shipp->flags & SF_CARGO_REVEALED)
1553  return 0;
1554 
1555  // allow ships with scannable flag set
1556  if (shipp->flags & SF_SCANNABLE)
1557  return 1;
1558 
1559  // ignore ships that don't carry cargo
1560  if ((sip->class_type < 0) || !(Ship_types[sip->class_type].ship_bools & STI_SHIP_SCANNABLE))
1561  return 0;
1562 
1563  return 1;
1564 }
1565 
1566 // target the next/prev uninspected cargo container
1567 void hud_target_uninspected_cargo(int next_flag)
1568 {
1569  object *A, *start, *start2;
1570  ship *shipp;
1571  int target_found = 0;
1572 
1573  if (Player_ai->target_objnum == -1) {
1574  start = &obj_used_list;
1575  } else {
1576  start = &Objects[Player_ai->target_objnum];
1577  }
1578 
1579  start2 = advance_fb(start, next_flag);
1580 
1581  for ( A = start2; A != start; A = advance_fb(A, next_flag) ) {
1582  if ( A == &obj_used_list ) {
1583  continue;
1584  }
1585 
1586  if (A == Player_obj || (A->type != OBJ_SHIP) ) {
1587  continue;
1588  }
1589 
1590  shipp = &Ships[A->instance]; // get a pointer to the ship information
1591 
1592  if ( shipp->flags & TARGET_SHIP_IGNORE_FLAGS ) {
1593  continue;
1594  }
1595 
1596  // ignore all non-cargo carrying craft
1597  if ( !hud_target_ship_can_be_scanned(shipp) ) {
1598  continue;
1599  }
1600 
1601  if(hud_target_invalid_awacs(A)){
1602  continue;
1603  }
1604 
1605  // if we've reached here, it is a valid next target
1606  if ( Player_ai->target_objnum != OBJ_INDEX(A) ) {
1607  target_found = TRUE;
1610  }
1611  }
1612 
1613  if ( target_found == FALSE ) {
1615  }
1616 }
1617 
1618 // target the newest ship in the area
1620 {
1621  object *A, *player_target_objp;
1622  object *newest_obj=NULL;
1623  ship *shipp;
1624  ship_obj *so;
1625  uint current_target_arrived_time = 0xffffffff, newest_time = 0;
1626 
1627  if ( Player_ai->target_objnum >= 0 ) {
1628  player_target_objp = &Objects[Player_ai->target_objnum];
1629  if ( player_target_objp->type == OBJ_SHIP ) {
1630  current_target_arrived_time = Ships[player_target_objp->instance].create_time;
1631  }
1632  } else {
1633  player_target_objp = NULL;
1634  }
1635 
1636  // If no target is selected, then simply target the closest uninspected cargo
1637  if ( Player_ai->target_objnum == -1 || timestamp_elapsed(Target_newest_ship_timestamp) ) {
1638  current_target_arrived_time = 0xffffffff;
1639  }
1640 
1641  Target_newest_ship_timestamp = timestamp(TL_RESET);
1642 
1643  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
1644  A = &Objects[so->objnum];
1645  shipp = &Ships[A->instance]; // get a pointer to the ship information
1646 
1647  if ( (A == Player_obj) || (shipp->flags & TARGET_SHIP_IGNORE_FLAGS) )
1648  continue;
1649 
1650  // ignore navbuoys
1651  if ( Ship_info[shipp->ship_info_index].flags & SIF_NAVBUOY ) {
1652  continue;
1653  }
1654 
1655  if ( A == player_target_objp ) {
1656  continue;
1657  }
1658 
1659  if(hud_target_invalid_awacs(A)){
1660  continue;
1661  }
1662 
1663  if ( (shipp->create_time >= newest_time) && (shipp->create_time <= current_target_arrived_time) ) {
1664  newest_time = shipp->create_time;
1665  newest_obj = A;
1666  }
1667  }
1668 
1669  if (newest_obj) {
1670  set_target_objnum( Player_ai, OBJ_INDEX(newest_obj) );
1671  hud_shield_hit_reset(newest_obj);
1672  // if BIG|HUGE and no selected subsystem, get sorted turret
1675  }
1676  else {
1678  }
1679 }
1680 
1681 #define TYPE_NONE 0
1682 #define TYPE_FACING_BEAM 1
1683 #define TYPE_FACING_FLAK 2
1684 #define TYPE_FACING_MISSILE 3
1685 #define TYPE_FACING_LASER 4
1686 #define TYPE_NONFACING_BEAM 5
1687 #define TYPE_NONFACING_FLAK 6
1688 #define TYPE_NONFACING_MISSILE 7
1689 #define TYPE_NONFACING_LASER 8
1690 #define TYPE_NONFACING_INC 4
1691 
1692 typedef struct eval_next_turret {
1694  int type;
1695  float dist;
1697 
1698 int turret_compare_func(const void *e1, const void *e2)
1699 {
1702 
1703  Assert(p1->type != TYPE_NONE);
1704  Assert(p2->type != TYPE_NONE);
1705 
1706  if (p1->type != p2->type) {
1707  return (p1->type - p2->type);
1708  } else {
1709  float delta_dist = p1->dist - p2->dist;
1710  if (delta_dist < 0) {
1711  return -1;
1712  } else if (delta_dist > 0) {
1713  return 1;
1714  } else {
1715  return 0;
1716  }
1717  }
1718 }
1719 
1720 extern bool turret_weapon_has_flags(ship_weapon *swp, int flags);
1721 extern bool turret_weapon_has_subtype(ship_weapon *swp, int subtype);
1722 // target the next/prev live turret on the current target
1723 // auto_advance from hud_update_closest_turret
1724 void hud_target_live_turret(int next_flag, int auto_advance, int only_player_target)
1725 {
1726  ship_subsys *A;
1727  ship_subsys *live_turret=NULL;
1728  ship *target_shipp;
1729  object *objp;
1731  int num_live_turrets = 0;
1732 
1733  // make sure we're targeting a ship
1734  if (Player_ai->target_objnum == -1 && !auto_advance) {
1736  return;
1737  }
1738 
1739  // only targeting subsystems on ship
1740  if ((Objects[Player_ai->target_objnum].type != OBJ_SHIP) && (!auto_advance)) {
1742  return;
1743  }
1744 
1745  // set some pointers
1746  objp = &Objects[Player_ai->target_objnum];
1747  target_shipp = &Ships[objp->instance];
1748 
1749  // set timestamp
1750  int timestamp_val = 0;
1751  if (!auto_advance) {
1752  timestamp_val = Target_next_turret_timestamp;
1753  Target_next_turret_timestamp = timestamp(TURRET_RESET);
1754  }
1755 
1756  // If no target is selected, then simply target the closest (or facing) turret
1757  int last_subsys_turret = FALSE;
1758  if (Player_ai->targeted_subsys != NULL) {
1761  last_subsys_turret = TRUE;
1762  }
1763  }
1764  }
1765 
1766  // do we want the closest turret (or the one our ship is pointing at)
1767  int get_closest_turret = (auto_advance || !last_subsys_turret || timestamp_elapsed(timestamp_val));
1768 
1769  // initialize eval struct
1770  memset(ent,0, sizeof(ent));
1771  int use_straight_ahead_turret = FALSE;
1772 
1773  // go through list of turrets
1774  for (A=GET_FIRST(&target_shipp->subsys_list); A!=END_OF_LIST(&target_shipp->subsys_list); A=GET_NEXT(A)) {
1775  // get a turret
1776  if (A->system_info->type == SUBSYSTEM_TURRET) {
1777  // niffiwan: ignore untargetable turrets
1778  if ( A->flags & SSF_UNTARGETABLE ) {
1779  continue;
1780  }
1781  // check turret has hit points and has a weapon
1782  if ( (A->current_hits > 0) && (A->weapons.num_primary_banks > 0 || A->weapons.num_secondary_banks > 0) ) {
1783  if ( !only_player_target || (A->turret_enemy_objnum == OBJ_INDEX(Player_obj)) ) {
1784  vec3d gsubpos, vec_to_subsys;
1785  float distance, dot;
1786  // get world pos of subsystem and its distance
1787  get_subsystem_world_pos(objp, A, &gsubpos);
1788  distance = vm_vec_normalized_dir(&vec_to_subsys, &gsubpos, &View_position);
1789 
1790  // check if facing and in view
1791  int facing = ship_subsystem_in_sight(objp, A, &View_position, &gsubpos, 0);
1792 
1793  if (!auto_advance && get_closest_turret && !only_player_target) {
1794  // if within 3 degrees and not previous subsys, use subsys in front
1795  dot = vm_vec_dot(&vec_to_subsys, &Player_obj->orient.vec.fvec);
1796  if ((dot > 0.9986) && facing) {
1797  use_straight_ahead_turret = TRUE;
1798  break;
1799  }
1800  }
1801 
1802  // set weapon_type to allow sort of ent on type
1804  ent[num_live_turrets].type = TYPE_FACING_BEAM;
1805  } else if (turret_weapon_has_flags(&A->weapons, WIF_FLAK)) {
1806  ent[num_live_turrets].type = TYPE_FACING_FLAK;
1807  } else {
1809  ent[num_live_turrets].type = TYPE_FACING_MISSILE;
1810  } else if (turret_weapon_has_subtype(&A->weapons, WP_LASER)) {
1811  ent[num_live_turrets].type = TYPE_FACING_LASER;
1812  } else {
1813  //Turret not live, bail
1814  continue;
1815  }
1816  }
1817 
1818  // fill out ent struct
1819  ent[num_live_turrets].ss = A;
1820  ent[num_live_turrets].dist = distance;
1821  if (!facing) {
1822  ent[num_live_turrets].type += TYPE_NONFACING_INC;
1823  }
1824  num_live_turrets++;
1825  }
1826  }
1827  }
1828  }
1829 
1830  // sort the list if we're not using turret straight ahead of us
1831  if (!use_straight_ahead_turret) {
1832  insertion_sort(ent, num_live_turrets, sizeof(eval_next_turret), turret_compare_func);
1833  }
1834 
1835  if (use_straight_ahead_turret) {
1836  // use the straight ahead turret
1837  live_turret = A;
1838  } else {
1839  // check if we have a currently targeted turret and find its position after the sort
1840  int i, start_index, next_index;
1841  if (get_closest_turret) {
1842  start_index = 0;
1843  } else {
1844  start_index = -1;
1845  for (i=0; i<num_live_turrets; i++) {
1846  if (ent[i].ss == Player_ai->targeted_subsys) {
1847  start_index = i;
1848  break;
1849  }
1850  }
1851  // check that we started with a turret
1852  if (start_index == -1) {
1853  start_index = 0;
1854  }
1855  }
1856 
1857  // set next live turret
1858  if (num_live_turrets == 0) {
1859  // no live turrets
1860  live_turret = NULL;
1861  } else if (num_live_turrets == 1 || get_closest_turret) {
1862  // only 1 live turret, so set it
1863  live_turret = ent[0].ss;
1864  } else {
1865  if (next_flag) {
1866  // advance to next closest turret
1867  next_index = start_index + 1;
1868  if (next_index == num_live_turrets) {
1869  next_index = 0;
1870  }
1871  } else {
1872  // go to next farther turret
1873  next_index = start_index - 1;
1874  if (next_index == -1) {
1875  next_index = num_live_turrets - 1;
1876  }
1877  }
1878 
1879  // set the next turret to be targeted based on next_index
1880  live_turret = ent[next_index].ss;
1881  }
1882 
1883  //if (live_turret) {
1884  // debug info
1885  // mprintf(("name %s, index: %d, type: %d\n", live_turret->system_info->subobj_name, next_index, ent[next_index].type));
1886  //}
1887  }
1888 
1889  if ( live_turret != NULL ) {
1892  } else {
1893  if (!auto_advance) {
1895  }
1896  }
1897 }
1898 
1899 
1900 // -------------------------------------------------------------------
1901 // hud_target_closest_locked_missile()
1902 //
1903 // Target the closest locked missile that is locked on locked_obj
1904 //
1905 // input: locked_obj => pointer to object that you want to find
1906 // closest missile to
1907 //
1908 void hud_target_closest_locked_missile(object *locked_obj)
1909 {
1910  object *A, *nearest_obj=NULL;
1911  weapon *wp;
1912  weapon_info *wip;
1913  float nearest_dist, dist;
1914  int target_found = FALSE;
1915  missile_obj *mo;
1916 
1917  nearest_dist = 10000.0f;
1918 
1919  for ( mo = GET_NEXT(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) {
1920  Assert(mo->objnum >= 0 && mo->objnum < MAX_OBJECTS);
1921  A = &Objects[mo->objnum];
1922 
1923  if (A->type != OBJ_WEAPON){
1924  continue;
1925  }
1926 
1927  Assert((A->instance >= 0) && (A->instance < MAX_WEAPONS));
1928  wp = &Weapons[A->instance];
1929  wip = &Weapon_info[wp->weapon_info_index];
1930 
1931  if ( wip->subtype != WP_MISSILE ){
1932  continue;
1933  }
1934 
1935  if ( !(wip->wi_flags & WIF_HOMING ) ){
1936  continue;
1937  }
1938 
1939  if (wp->lssm_stage==3){
1940  continue;
1941  }
1942 
1943  if(hud_target_invalid_awacs(A)){
1944  continue;
1945  }
1946 
1947 
1948  if (wp->homing_object == locked_obj) {
1949  dist = vm_vec_dist_quick(&A->pos, &locked_obj->pos); // Find distance!
1950 
1951  if (dist < nearest_dist) {
1952  nearest_obj = A;
1953  nearest_dist = dist;
1954  }
1955  }
1956  } // end for
1957 
1958  if (nearest_dist < 10000.0f) {
1959  Assert(nearest_obj);
1960  set_target_objnum( Player_ai, OBJ_INDEX(nearest_obj) );
1961  hud_shield_hit_reset(nearest_obj);
1962  target_found = TRUE;
1963  }
1964 
1965  if ( !target_found ){
1966  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
1967  }
1968 }
1969 
1970 // select a new target, by auto-targeting
1972 {
1973  if ( Framecount < 2 ) {
1974  return;
1975  }
1976 
1977  // No auto-targeting after dead.
1978  if (Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))
1979  return;
1980 
1981  // try target next ship in hotkey set, if any -- Backslash
1982  if ( Player->current_hotkey_set != -1 ) {
1984  }
1985 
1986  int valid_team_mask = iff_get_attackee_mask(Player_ship->team);
1987 
1988  // if none, try targeting closest hostile fighter/bomber
1989  if ( Player_ai->target_objnum == -1 ) { //-V581
1990  hud_target_closest(valid_team_mask, -1, FALSE, TRUE);
1991  }
1992 
1993  // No fighter/bombers exists, so go ahead an target the closest hostile
1994  if ( Player_ai->target_objnum == -1 ) { //-V581
1995  hud_target_closest(valid_team_mask, -1, FALSE);
1996  }
1997 
1998  // um, ok. Try targeting asteroids that are on a collision course for an escort ship
1999  if ( Player_ai->target_objnum == -1 ) { //-V581
2001  }
2002 }
2003 
2004 
2005 // Given that object 'targeter' is targeting object 'targetee',
2006 // how far are they? This uses the point closest to the targeter
2007 // object on the targetee's bounding box. So if targeter is inside
2008 // targtee's bounding box, the distance is 0.
2009 float hud_find_target_distance( object *targetee, object *targeter )
2010 {
2011  vec3d tmp_pnt;
2012 
2013  int model_num = -1;
2014 
2015  // Which model is it?
2016  switch( targetee->type ) {
2017  case OBJ_SHIP:
2018  model_num = Ship_info[Ships[targetee->instance].ship_info_index].model_num;
2019  break;
2020  case OBJ_DEBRIS:
2021 // model_num = Debris[targetee->instance].model_num;
2022  break;
2023  case OBJ_WEAPON:
2024  // Don't find model_num since circles would work better
2025  //model_num = Weapon_info[Weapons[targetee->instance].weapon_info_index].model_num;
2026  break;
2027  case OBJ_ASTEROID:
2028  // Don't find model_num since circles would work better
2029  //model_num = Asteroid_info[Asteroids[targetee->instance].type].model_num;
2030  break;
2031  case OBJ_JUMP_NODE:
2032  // Don't find model_num since circles would work better
2033  //model_num = Jump_nodes[targetee->instance].modelnum;
2034  break;
2035  }
2036 
2037  float dist = 0.0f;
2038 
2039  // New way, that uses bounding box.
2040  if ( model_num > -1 ) {
2041  dist = model_find_closest_point( &tmp_pnt, model_num, -1, &targetee->orient, &targetee->pos, &targeter->pos );
2042  } else {
2043  // Old way, that uses radius.
2044  dist = vm_vec_dist_quick(&targetee->pos, &targeter->pos) - targetee->radius;
2045  if ( dist < 0.0f ) {
2046  dist = 0.0f;
2047  }
2048  }
2049  return dist;
2050 }
2051 
2052 //
2053 
2070 {
2071  int targeting_player, turret_is_attacking;
2072  ship_subsys *ss;
2073  float new_distance;
2074 
2075  // initialize
2076  esct_p->min_distance = FLT_MAX;
2077  esct_p->check_nearest_turret = FALSE;
2078  turret_is_attacking = FALSE;
2079 
2080 
2081  object *objp = &Objects[esct_p->shipp->objnum];
2082  Assert(objp->type == OBJ_SHIP);
2083  if (objp->type != OBJ_SHIP) {
2084  return false;
2085  }
2086 
2087  // player being targeted, so we will want closest distance from player
2088  targeting_player = (esct_p->attacked_objnum == OBJ_INDEX(Player_obj));
2089 
2090  // filter on team
2091  if ( !iff_matches_mask(esct_p->shipp->team, esct_p->team_mask) ) {
2092  return false;
2093  }
2094 
2095  // check if player or ignore ship
2096  if ( (esct_p->shipp->objnum == OBJ_INDEX(Player_obj)) || (esct_p->shipp->flags & TARGET_SHIP_IGNORE_FLAGS) ) {
2097  return false;
2098  }
2099 
2100  // bail if harmless
2101  if ( Ship_info[esct_p->shipp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[esct_p->shipp->ship_info_index].class_type].hud_bools & STI_HUD_TARGET_AS_THREAT)) {
2102  return false;
2103  }
2104 
2105  // only look at targets that are AWACS valid
2106  if (hud_target_invalid_awacs(&Objects[esct_p->shipp->objnum])) {
2107  return false;
2108  }
2109 
2110  // If filter is set, only target fighters and bombers
2111  if ( esct_p->filter ) {
2112  if ( !(Ship_info[esct_p->shipp->ship_info_index].flags & (SIF_FIGHTER | SIF_BOMBER)) ) {
2113  return false;
2114  }
2115  }
2116 
2117  // find closest turret to player if BIG or HUGE ship
2118  if (Ship_info[esct_p->shipp->ship_info_index].flags & (SIF_BIG_SHIP|SIF_HUGE_SHIP)) {
2119  for (ss=GET_FIRST(&esct_p->shipp->subsys_list); ss!=END_OF_LIST(&esct_p->shipp->subsys_list); ss=GET_NEXT(ss)) {
2120 
2121  if (ss->flags & SSF_UNTARGETABLE)
2122  continue;
2123 
2124  if ( (ss->system_info->type == SUBSYSTEM_TURRET) && (ss->current_hits > 0) ) {
2125 
2126  if (esct_p->check_all_turrets || (ss->turret_enemy_objnum == esct_p->attacked_objnum)) {
2127  turret_is_attacking = 1;
2128  esct_p->check_nearest_turret = TRUE;
2129 
2130  if ( !esct_p->turret_attacking_target || (esct_p->turret_attacking_target && (ss->turret_enemy_objnum == esct_p->attacked_objnum)) ) {
2131  vec3d gsubpos;
2132  // get world pos of subsystem
2133  vm_vec_unrotate(&gsubpos, &ss->system_info->pnt, &objp->orient);
2134  vm_vec_add2(&gsubpos, &objp->pos);
2135  new_distance = vm_vec_dist_quick(&gsubpos, &Player_obj->pos);
2136 
2137  /*
2138  // GET TURRET TYPE, FAVOR BEAM, FLAK, OTHER
2139  int turret_type = ss->system_info->turret_weapon_type;
2140  if (Weapon_info[turret_type].wi_flags & WIF_BEAM) {
2141  new_distance *= 0.3f;
2142  } else if (Weapon_info[turret_type].wi_flags & WIF_FLAK) {
2143  new_distance *= 0.6f;
2144  } */
2145 
2146  // get the closest distance
2147  if (new_distance <= esct_p->min_distance) {
2148  esct_p->min_distance = new_distance;
2149  }
2150  }
2151  }
2152  }
2153  }
2154  }
2155 
2156  // If no turret is attacking, check if objp is actually targeting attacked_objnum
2157  // don't bail if targeting is for player
2158  if ( !targeting_player && !turret_is_attacking ) {
2159  ai_info *aip = &Ai_info[esct_p->shipp->ai_index];
2160 
2161  if (aip->target_objnum != esct_p->attacked_objnum) {
2162  return false;
2163  }
2164 
2165  if ( (Game_mode & GM_NORMAL) && ( aip->mode != AIM_CHASE ) && (aip->mode != AIM_STRAFE) && (aip->mode != AIM_EVADE) && (aip->mode != AIM_EVADE_WEAPON) && (aip->mode != AIM_AVOID)) {
2166  return false;
2167  }
2168  }
2169 
2170  // consider the ship alone if there are no attacking turrets
2171  if ( !turret_is_attacking ) {
2172  //new_distance = hud_find_target_distance(objp, Player_obj);
2173  new_distance = vm_vec_dist_quick(&objp->pos, &Player_obj->pos);
2174 
2175  if (new_distance <= esct_p->min_distance) {
2176  esct_p->min_distance = new_distance;
2177  esct_p->check_nearest_turret = FALSE;
2178  }
2179  }
2180 
2181  return true;
2182 }
2183 
2212 int hud_target_closest(int team_mask, int attacked_objnum, int play_fail_snd, int filter, int get_closest_turret_attacking_player)
2213 {
2214  object *A;
2215  object *nearest_obj = &obj_used_list;
2216  ship *shipp;
2217  ship_obj *so;
2218  int check_nearest_turret = FALSE;
2219 
2220  // evaluate ship closest target struct
2221  esct eval_ship_as_closest_target_args;
2222 
2223  float min_distance = FLT_MAX;
2224  int target_found = FALSE;
2225 
2226  int player_obj_index = OBJ_INDEX(Player_obj);
2227  ship_subsys *ss;
2228 
2229  int initial_attacked_objnum = attacked_objnum;
2230 
2231  if ( (attacked_objnum >= 0) && (attacked_objnum != player_obj_index) ) {
2232  // bail if player does not have target
2233  if ( Player_ai->target_objnum == -1 ) {
2234  goto Target_closest_done;
2235  }
2236 
2237  if ( Objects[attacked_objnum].type != OBJ_SHIP ) {
2238  goto Target_closest_done;
2239  }
2240 
2241  // bail if ship is to be ignored
2242  if (Ships[Objects[attacked_objnum].instance].flags & TARGET_SHIP_IGNORE_FLAGS) {
2243  goto Target_closest_done;
2244  }
2245  }
2246 
2247  if (attacked_objnum == -1) {
2248  attacked_objnum = player_obj_index;
2249  }
2250 
2251  // check all turrets if for player.
2252  eval_ship_as_closest_target_args.check_all_turrets = (attacked_objnum == player_obj_index);
2253  eval_ship_as_closest_target_args.filter = filter;
2254  eval_ship_as_closest_target_args.team_mask = team_mask;
2255  eval_ship_as_closest_target_args.attacked_objnum = attacked_objnum;
2256  eval_ship_as_closest_target_args.turret_attacking_target = get_closest_turret_attacking_player;
2257 
2258  for ( so=GET_FIRST(&Ship_obj_list); so!=END_OF_LIST(&Ship_obj_list); so=GET_NEXT(so) ) {
2259 
2260  A = &Objects[so->objnum];
2261  shipp = &Ships[A->instance]; // get a pointer to the ship information
2262 
2263  // fill in rest of eval_ship_as_closest_target_args
2264  eval_ship_as_closest_target_args.shipp = shipp;
2265 
2266  // Filter out any target that is not targeting the player --Mastadon
2267  if ( (initial_attacked_objnum == player_obj_index) && (Ai_info[shipp->ai_index].target_objnum != player_obj_index) ) {
2268  continue;
2269  }
2270  // check each shipp on list and update nearest obj and subsys
2271  evaluate_ship_as_closest_target(&eval_ship_as_closest_target_args);
2272  if (eval_ship_as_closest_target_args.min_distance < min_distance) {
2273  target_found = TRUE;
2274  min_distance = eval_ship_as_closest_target_args.min_distance;
2275  nearest_obj = A;
2276  check_nearest_turret = eval_ship_as_closest_target_args.check_nearest_turret;
2277  }
2278  }
2279 
2280  Target_closest_done:
2281 
2282  // maybe ignore target if too far away
2283  // DKA 9/8/99 Remove distance check
2284  /*
2285  if (target_found) {
2286  // get distance to nearest attacker
2287  float dist = vm_vec_dist_quick(&Objects[attacked_objnum].pos, &nearest_obj->pos);
2288 
2289  // no distance limit for player obj
2290  if ((attacked_objnum != player_obj_index) && (dist > MIN_DISTANCE_TO_CONSIDER_THREAT)) {
2291  target_found = FALSE;
2292  }
2293  } */
2294 
2295  if (target_found) {
2296  set_target_objnum(Player_ai, OBJ_INDEX(nearest_obj));
2297  hud_shield_hit_reset(nearest_obj);
2298  if ( check_nearest_turret ) {
2299 
2300  // if former subobject was not a turret do, not change subsystem
2301  ss = Ships[nearest_obj->instance].last_targeted_subobject[Player_num];
2302  if (ss == NULL || get_closest_turret_attacking_player) {
2303  // update nearest turret with later func
2304  hud_target_live_turret(1, 1, get_closest_turret_attacking_player);
2306  }
2307  } else {
2309  }
2310  } else {
2311  // no target found, maybe play fail sound
2312  if (play_fail_snd == TRUE) {
2314  }
2315  }
2316 
2317  return target_found;
2318 }
2319 
2320 // auto update closest turret to attack on big or huge ships
2322 {
2323  hud_target_live_turret(1, 1);
2324 
2325 /*
2326  float nearest_distance, new_distance;
2327  ship_subsys *ss, *closest_subsys;
2328  ship *shipp;
2329  object *objp;
2330 
2331  nearest_distance = FLT_MAX;
2332  objp = &Objects[Player_ai->target_objnum];
2333  shipp = &Ships[objp->instance];
2334  closest_subsys = NULL;
2335 
2336 
2337  Assert(Ship_info[shipp->ship_info_index].flags & (SIF_BIG_SHIP|SIF_HUGE_SHIP));
2338 
2339  for (ss=GET_FIRST(&shipp->subsys_list); ss!=END_OF_LIST(&shipp->subsys_list); ss=GET_NEXT(ss)) {
2340  if ( (ss->system_info->type == SUBSYSTEM_TURRET) && (ss->current_hits > 0) ) {
2341  // make sure turret is not "unused"
2342  if (ss->system_info->turret_weapon_type >= 0) {
2343  vec3d gsubpos;
2344  // get world pos of subsystem
2345  vm_vec_unrotate(&gsubpos, &ss->system_info->pnt, &objp->orient);
2346  vm_vec_add2(&gsubpos, &objp->pos);
2347  new_distance = vm_vec_dist_quick(&gsubpos, &Player_obj->pos);
2348 
2349  // GET TURRET TYPE, FAVOR BEAM, FLAK, OTHER
2350  int turret_type = ss->system_info->turret_weapon_type;
2351  if (Weapon_info[turret_type].wi_flags & WIF_BEAM) {
2352  new_distance *= 0.3f;
2353  } else if (Weapon_info[turret_type].wi_flags & WIF_FLAK) {
2354  new_distance *= 0.6f;
2355  }
2356 
2357  // check if facing and in view
2358  int facing = ship_subsystem_in_sight(objp, ss, &View_position, &gsubpos, 0);
2359 
2360  if (facing) {
2361  new_distance *= 0.5f;
2362  }
2363 
2364  // get the closest distance
2365  if (new_distance <= nearest_distance) {
2366  nearest_distance = new_distance;
2367  closest_subsys = ss;
2368  }
2369  }
2370  }
2371  }
2372 
2373  // check if new subsys to target
2374  if (Player_ai->targeted_subsys != NULL) {
2375  set_targeted_subsys(Player_ai, closest_subsys, Player_ai->target_objnum);
2376  shipp->last_targeted_subobject[Player_num] = Player_ai->targeted_subsys;
2377  }
2378  */
2379 }
2380 
2381 
2382 // --------------------------------------------------------------------
2383 // hud_target_targets_target()
2384 //
2385 // Target your target's target. Your target is specified by objnum passed
2386 // as a parameter.
2387 //
2389 {
2390  object *objp = NULL;
2391  object *tt_objp = NULL;
2392  int tt_objnum;
2393 
2395  goto ttt_fail;
2396  }
2397 
2398  objp = &Objects[Player_ai->target_objnum];
2399  if ( objp->type != OBJ_SHIP ) {
2400  goto ttt_fail;
2401  }
2402 
2403  tt_objnum = Ai_info[Ships[objp->instance].ai_index].target_objnum;
2404  if ( tt_objnum < 0 || tt_objnum >= MAX_OBJECTS ) {
2405  goto ttt_fail;
2406  }
2407 
2408  if ( tt_objnum == OBJ_INDEX(Player_obj) ) {
2409  goto ttt_fail;
2410  }
2411 
2412  tt_objp = &Objects[tt_objnum];
2413 
2414  if (hud_target_invalid_awacs(tt_objp)) {
2415  goto ttt_fail;
2416  }
2417 
2418  if ( tt_objp->type != OBJ_SHIP ) {
2419  goto ttt_fail;
2420  }
2421 
2422  if ( Ships[tt_objp->instance].flags & TARGET_SHIP_IGNORE_FLAGS ) {
2423  goto ttt_fail;
2424  }
2425 
2426  // if we've reached here, found player target's target
2427  set_target_objnum( Player_ai, tt_objnum );
2428  hud_shield_hit_reset(&Objects[tt_objnum]);
2429  if (Objects[tt_objnum].type == OBJ_SHIP) {
2430  hud_maybe_set_sorted_turret_subsys(&Ships[Objects[tt_objnum].instance]);
2431  }
2432  hud_restore_subsystem_target(&Ships[Objects[tt_objnum].instance]);
2433  return;
2434 
2435  ttt_fail:
2436  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
2437 }
2438 
2439 // Return !0 if target_objp is a valid object type for targeting in reticle, otherwise return 0
2440 int object_targetable_in_reticle(object *target_objp)
2441 {
2442  int obj_type;
2444 
2445  if (target_objp == Player_obj ) {
2446  return 0;
2447  }
2448 
2449  obj_type = target_objp->type;
2450 
2451  if ( (obj_type == OBJ_SHIP) || (obj_type == OBJ_DEBRIS) || (obj_type == OBJ_WEAPON) || (obj_type == OBJ_ASTEROID) )
2452  {
2453  return 1;
2454  } else if ( obj_type == OBJ_JUMP_NODE )
2455  {
2456  for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
2457  if(jnp->GetSCPObject() == target_objp)
2458  break;
2459  }
2460 
2461  if (!jnp->IsHidden())
2462  return 1;
2463  }
2464 
2465  return 0;
2466 }
2467 
2468 // hud_target_in_reticle_new() will target the object that is closest to the player, and who is
2469 // intersected by a ray passed from the center of the reticle out along the forward vector of the
2470 // player.
2471 //
2472 // targeting of objects of type OBJ_SHIP and OBJ_DEBRIS are supported
2473 //
2474 // Method: A ray is cast from the center of the reticle, and we keep track of any eligible object
2475 // the ray intersects. We take the ship closest to us that intersects an object.
2476 //
2477 // Since this method may work poorly with objects that are far away, hud_target_in_reticle_old()
2478 // is called if no intersections are found.
2479 //
2480 //
2481 #define TARGET_IN_RETICLE_DISTANCE 10000.0f
2482 
2484 {
2485  vec3d terminus;
2486  object *A;
2487  mc_info mc;
2488  float dist;
2490 
2491  hud_reticle_clear_list(&Reticle_cur_list);
2493 
2494  // Get 3d vector through center of reticle
2496 
2497  mc_info_init(&mc);
2498  mc.model_instance_num = -1;
2499  mc.model_num = 0;
2500  for ( A = GET_FIRST(&obj_used_list); A !=END_OF_LIST(&obj_used_list); A = GET_NEXT(A) ) {
2501  if ( !object_targetable_in_reticle(A) ) {
2502  continue;
2503  }
2504 
2505  if ( A->type == OBJ_WEAPON ) {
2508  continue;
2509  }
2510  }
2511  if (Weapons[A->instance].lssm_stage==3){
2512  continue;
2513  }
2514  }
2515 
2516 
2517  if ( A->type == OBJ_SHIP ) {
2519  continue;
2520  }
2521  }
2522 
2523  if(hud_target_invalid_awacs(A)){
2524  continue;
2525  }
2526 
2527  switch (A->type) {
2528  case OBJ_SHIP:
2529  mc.model_num = Ship_info[Ships[A->instance].ship_info_index].model_num;
2530  break;
2531  case OBJ_DEBRIS:
2533  break;
2534  case OBJ_WEAPON:
2536  break;
2537  case OBJ_ASTEROID:
2538  {
2539  int pof = 0;
2541  mc.model_num = Asteroid_info[Asteroids[A->instance].asteroid_type].model_num[pof];
2542  }
2543  break;
2544  case OBJ_JUMP_NODE:
2545  for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
2546  if(jnp->GetSCPObject() == A)
2547  break;
2548  }
2549 
2550  mc.model_num = jnp->GetModelNumber();
2551  break;
2552  default:
2553  Int3(); // Illegal object type.
2554  }
2555 
2556  if (mc.model_num == -1) {
2557  // so just check distance of a point
2558  vec3d temp_v;
2559  float angle;
2560  vm_vec_sub(&temp_v, &A->pos, &Eye_position);
2561  vm_vec_normalize(&temp_v);
2562  angle = vm_vec_dot(&Player_obj->orient.vec.fvec, &temp_v);
2563  if (angle > 0.99f) {
2564  dist = vm_vec_mag_squared(&temp_v);
2565  hud_reticle_list_update(A, dist, 0);
2566  }
2567 
2568  } else {
2569 
2571  mc.orient = &A->orient; // The object's orient
2572  mc.pos = &A->pos; // The object's position
2573  mc.p0 = &Eye_position; // Point 1 of ray to check
2574  mc.p1 = &terminus; // Point 2 of ray to check
2575  mc.flags = MC_CHECK_MODEL; // | MC_ONLY_BOUND_BOX; // check the model, but only its bounding box
2576 
2577  model_collide(&mc);
2578  if ( mc.num_hits ) {
2580  hud_reticle_list_update(A, dist, 0);
2581  }
2582  }
2583  } // end for (go to next object)
2584 
2585  hud_target_in_reticle_old(); // try the old method (works well with ships far away)
2586 }
2587 
2588 // hud_target_in_reticle_old() will target the object that is closest to the reticle center and inside
2589 // the reticle
2590 //
2591 // targeting of objects of type OBJ_SHIP and OBJ_DEBRIS are supported
2592 //
2593 //
2594 // Method: take the dot product of the foward vector and the vector to target. Take
2595 // the one that is closest to 1 and at least MIN_DOT_FOR_TARGET
2596 //
2597 // IMPORTANT: The MIN_DOT_FOR_TARGET value was arrived at by trial and error and
2598 // is only valid for the HUD reticle in use at that time.
2599 
2600 #define MIN_DOT_FOR_TARGET 0.9726// fov for targeting in reticle
2601 
2603 {
2604  object *A, *target_obj;
2605  float dot;
2606  vec3d vec_to_target;
2607 
2608  for ( A = GET_FIRST(&obj_used_list); A !=END_OF_LIST(&obj_used_list); A = GET_NEXT(A) ) {
2609  if ( !object_targetable_in_reticle(A) ) {
2610  continue;
2611  }
2612 
2613  if ( A->type == OBJ_WEAPON ) {
2616  continue;
2617  }
2618  }
2619 
2620  if (Weapons[A->instance].lssm_stage==3){
2621  continue;
2622  }
2623  }
2624 
2625  if ( A->type == OBJ_SHIP ) {
2627  continue;
2628  }
2629  }
2630 
2631  if(hud_target_invalid_awacs(A)){
2632  continue;
2633  }
2634 
2635  if ( vm_vec_same( &A->pos, &Eye_position ) ) {
2636  continue;
2637  }
2638 
2639  vm_vec_normalized_dir(&vec_to_target, &A->pos, &Eye_position);
2640  dot = vm_vec_dot(&Player_obj->orient.vec.fvec, &vec_to_target);
2641 
2642  if ( dot > MIN_DOT_FOR_TARGET ) {
2643  hud_reticle_list_update(A, dot, 1);
2644  }
2645  }
2646 
2647  target_obj = hud_reticle_pick_target();
2648  if ( target_obj != NULL ) {
2649  set_target_objnum( Player_ai, OBJ_INDEX(target_obj) );
2650  hud_shield_hit_reset(target_obj);
2651  if ( target_obj->type == OBJ_SHIP ) {
2652  // if BIG|HUGE, maybe set subsys to turret
2655  }
2656  }
2657  else {
2658  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
2659  }
2660 }
2661 
2662 // hud_target_subsystem_in_reticle() will target the subsystem that is within the reticle and
2663 // is closest to the reticle center. The current target is the only object that is searched for
2664 // subsystems
2665 //
2666 // Method: take the dot product of the foward vector and the vector to target. Take
2667 // the one that is closest to 1 and at least MIN_DOT_FOR_TARGET
2668 //
2669 // IMPORTANT: The MIN_DOT_FOR_TARGET value was arrived at by trial and error and
2670 // is only valid for the HUD reticle in use at that time.
2671 //
2672 
2674 {
2675  object* targetp;
2676  ship_subsys *subsys;
2677  ship_subsys *nearest_subsys = NULL;
2678  vec3d subobj_pos;
2679 
2680  float dot, best_dot;
2681  vec3d vec_to_target;
2682  best_dot = -1.0f;
2683 
2684  if ( Player_ai->target_objnum == -1){
2686  }
2687 
2688  if ( Player_ai->target_objnum == -1) { //-V581
2690  return;
2691  }
2692 
2693  targetp = &Objects[Player_ai->target_objnum];
2694 
2695  if ( targetp->type != OBJ_SHIP ){ // only targeting subsystems on ship
2696  return;
2697  }
2698 
2699  int shipnum = targetp->instance;
2700 
2701  if ( targetp->type == OBJ_SHIP ) {
2702  if ( Ships[shipnum].flags & TARGET_SHIP_IGNORE_FLAGS ) {
2703  return;
2704  }
2705  }
2706 
2707  for (subsys = GET_FIRST(&Ships[shipnum].subsys_list); subsys != END_OF_LIST(&Ships[shipnum].subsys_list) ; subsys = GET_NEXT( subsys ) ) {
2708 
2709  //if the subsystem isn't targetable, skip it
2710  if (subsys->flags & SSF_UNTARGETABLE)
2711  continue;
2712 
2713  get_subsystem_world_pos(targetp, subsys, &subobj_pos);
2714 
2715  vm_vec_normalized_dir(&vec_to_target, &subobj_pos, &Eye_position);
2716  dot = vm_vec_dot(&Player_obj->orient.vec.fvec, &vec_to_target);
2717 
2718  if ( dot > best_dot ) {
2719  best_dot = dot;
2720  if ( best_dot > MIN_DOT_FOR_TARGET )
2721  nearest_subsys = subsys;
2722  }
2723  } // end for
2724 
2725  if ( nearest_subsys != NULL ) {
2727  char r_name[NAME_LENGTH];
2728  int i;
2730  for (i = 0; r_name[i] > 0; i++) {
2731  if (r_name[i] == '|')
2732  r_name[i] = ' ';
2733  }
2734  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Targeting subsystem %s.", 323), r_name);
2736  }
2737  else {
2739  }
2740 }
2741 
2742 #define T_LENGTH 8
2743 #define T_OFFSET_FROM_CIRCLE -13
2744 #define T_BASE_LENGTH 4
2745 
2746 // On entry:
2747 // color set
2748 void HudGaugeOrientationTee::renderOrientation(object *from_objp, object *to_objp, matrix *from_orientp)
2749 {
2750  float dot_product;
2751  vec3d target_to_obj;
2752  float x1,y1,x2,y2,x3,y3,x4,y4;
2753 
2754  vm_vec_sub(&target_to_obj, &from_objp->pos, &to_objp->pos);
2755 
2756  vm_vec_normalize(&target_to_obj);
2757 
2758  // calculate the dot product between the target_to_player vector and the targets forward vector
2759  //
2760  // 0 - vectors are perpendicular
2761  // 1 - vectors are collinear and in the same direction (target is facing player)
2762  // -1 - vectors are collinear and in the opposite direction (target is facing away from player)
2763  dot_product = vm_vec_dot(&from_orientp->vec.fvec, &target_to_obj);
2764 
2765  if (vm_vec_dot(&from_orientp->vec.rvec, &target_to_obj) >= 0) {
2766  if (dot_product >= 0){
2767  dot_product = -PI_2*dot_product + PI;
2768  } else {
2769  dot_product = -PI_2*dot_product - PI;
2770  }
2771  } else {
2772  dot_product *= PI_2; //(range is now -PI/2 => PI/2)
2773  }
2774 
2775  y1 = sinf(dot_product) * (Radius - T_OFFSET_FROM_CIRCLE);
2776  x1 = cosf(dot_product) * (Radius - T_OFFSET_FROM_CIRCLE);
2777 
2778  y1 += position[1];
2779  x1 += position[0];
2780 
2781  x1 += HUD_offset_x;
2782  y1 += HUD_offset_y;
2783 
2784  y2 = sinf(dot_product) * (Radius - T_OFFSET_FROM_CIRCLE - T_LENGTH);
2785  x2 = cosf(dot_product) * (Radius - T_OFFSET_FROM_CIRCLE - T_LENGTH);
2786 
2787  y2 += position[1];
2788  x2 += position[0];
2789 
2790  x2 += HUD_offset_x;
2791  y2 += HUD_offset_y;
2792 
2793  x3 = x1 - T_BASE_LENGTH * sinf(dot_product);
2794  y3 = y1 + T_BASE_LENGTH * cosf(dot_product);
2795  x4 = x1 + T_BASE_LENGTH * sinf(dot_product);
2796  y4 = y1 - T_BASE_LENGTH * cosf(dot_product);
2797 
2798  // HACK! Should be antialiased!
2799  renderLine(fl2i(x3),fl2i(y3),fl2i(x4),fl2i(y4)); // bottom of T
2800  renderLine(fl2i(x1),fl2i(y1),fl2i(x2),fl2i(y2)); // part of T pointing towards center
2801 }
2802 
2803 void hud_tri(float x1,float y1,float x2,float y2,float x3,float y3)
2804 {
2805  int i;
2806 
2807  // Make the triangle always be the correct handiness so
2808  // the tmapper won't think its back-facing and throw it out.
2809  float det = (y2-y1)*(x3-x1) - (x2-x1)*(y3-y1);
2810  if ( det >= 0.0f ) {
2811  float tmp;
2812 
2813  // swap y1 & y3
2814  tmp = y1;
2815  y1 = y3;
2816  y3 = tmp;
2817 
2818  // swap x1 & x3
2819  tmp = x1;
2820  x1 = x3;
2821  x3 = tmp;
2822  }
2823 
2824  vertex * vertlist[3];
2825  vertex verts[3];
2826 
2827  // zero verts[] out, this is a faster way (nods to Kazan) to make sure that
2828  // the specular colors are set to 0 to avoid rendering problems - taylor
2829  memset(verts, 0, sizeof(verts));
2830 
2831  for (i=0; i<3; i++ )
2832  vertlist[i] = &verts[i];
2833 
2834  verts[0].screen.xyw.x = x1;
2835  verts[0].screen.xyw.y = y1;
2836  verts[0].screen.xyw.w = 0.0f;
2837  verts[0].texture_position.u = 0.0f;
2838  verts[0].texture_position.v = 0.0f;
2839  verts[0].flags = PF_PROJECTED;
2840  verts[0].codes = 0;
2841  verts[0].r = (ubyte)gr_screen.current_color.red;
2842  verts[0].g = (ubyte)gr_screen.current_color.green;
2843  verts[0].b = (ubyte)gr_screen.current_color.blue;
2844  verts[0].a = (ubyte)gr_screen.current_color.alpha;
2845 
2846  verts[1].screen.xyw.x = x2;
2847  verts[1].screen.xyw.y = y2;
2848  verts[1].screen.xyw.w = 0.0f;
2849  verts[1].texture_position.u = 0.0f;
2850  verts[1].texture_position.v = 0.0f;
2851  verts[1].flags = PF_PROJECTED;
2852  verts[1].codes = 0;
2853  verts[1].r = (ubyte)gr_screen.current_color.red;
2854  verts[1].g = (ubyte)gr_screen.current_color.green;
2855  verts[1].b = (ubyte)gr_screen.current_color.blue;
2856  verts[1].a = (ubyte)gr_screen.current_color.alpha;
2857 
2858  verts[2].screen.xyw.x = x3;
2859  verts[2].screen.xyw.y = y3;
2860  verts[2].screen.xyw.w = 0.0f;
2861  verts[2].texture_position.u = 0.0f;
2862  verts[2].texture_position.v = 0.0f;
2863  verts[2].flags = PF_PROJECTED;
2864  verts[2].codes = 0;
2865  verts[2].r = (ubyte)gr_screen.current_color.red;
2866  verts[2].g = (ubyte)gr_screen.current_color.green;
2867  verts[2].b = (ubyte)gr_screen.current_color.blue;
2868  verts[2].a = (ubyte)gr_screen.current_color.alpha;
2869 
2870  for (i=0; i<3; i++)
2871  gr_resize_screen_posf(&verts[i].screen.xyw.x, &verts[i].screen.xyw.y);
2872 
2873  uint saved_mode = gr_zbuffer_get();
2874  int cull = gr_set_cull(0);
2875 
2877 
2878  //gr_tmapper( 3, vertlist, TMAP_FLAG_TRILIST );
2880 
2881  gr_zbuffer_set( saved_mode );
2882  gr_set_cull(cull);
2883 }
2884 
2885 
2886 void hud_tri_empty(float x1,float y1,float x2,float y2,float x3,float y3)
2887 {
2888  gr_line(fl2i(x1),fl2i(y1),fl2i(x2),fl2i(y2));
2889  gr_line(fl2i(x2),fl2i(y2),fl2i(x3),fl2i(y3));
2890  gr_line(fl2i(x3),fl2i(y3),fl2i(x1),fl2i(y1));
2891 }
2892 
2895 {
2896 
2897 }
2898 
2899 HudGaugeReticleTriangle::HudGaugeReticleTriangle(int _gauge_object, int _gauge_config):
2900 HudGauge(_gauge_object, _gauge_config, true, false, VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY | VM_OTHER_SHIP, 255, 255, 255)
2901 {
2902 
2903 }
2904 
2906 {
2907  Radius = length;
2908 }
2909 
2911 {
2913 }
2914 
2916 {
2918 }
2919 
2920 void HudGaugeReticleTriangle::render(float frametime)
2921 {
2922 }
2923 
2924 // Render a missile warning triangle that has a tail on it to indicate distance
2925 void HudGaugeReticleTriangle::renderTriangleMissileTail(float ang, float xpos, float ypos, float cur_dist, int draw_solid, int draw_inside)
2926 {
2927  float x1=0.0f;
2928  float x2=0.0f;
2929  float y1=0.0f;
2930  float y2=0.0f;
2931  float xtail=0.0f;
2932  float ytail=0.0f;
2933 
2934  float sin_ang, cos_ang, tail_len;
2935 
2936  float max_tail_len=20.0f;
2937 
2938  sin_ang=sinf(ang);
2939  cos_ang=cosf(ang);
2940 
2941  if ( cur_dist < Min_warning_missile_dist ) {
2942  tail_len = 0.0f;
2943  } else if ( cur_dist > Max_warning_missile_dist ) {
2944  tail_len = max_tail_len;
2945  } else {
2946  tail_len = cur_dist/Max_warning_missile_dist * max_tail_len;
2947  }
2948 
2949  if ( draw_inside ) {
2950  x1 = xpos - Target_triangle_base * -sin_ang;
2951  y1 = ypos + Target_triangle_base * cos_ang;
2952  x2 = xpos + Target_triangle_base * -sin_ang;
2953  y2 = ypos - Target_triangle_base * cos_ang;
2954 
2955  xpos -= Target_triangle_height * cos_ang;
2956  ypos += Target_triangle_height * sin_ang;
2957 
2958  if ( tail_len > 0 ) {
2959  xtail = xpos - tail_len * cos_ang;
2960  ytail = ypos + tail_len * sin_ang;
2961  }
2962 
2963  } else {
2964  x1 = xpos - Target_triangle_base * -sin_ang;
2965  y1 = ypos + Target_triangle_base * cos_ang;
2966  x2 = xpos + Target_triangle_base * -sin_ang;
2967  y2 = ypos - Target_triangle_base * cos_ang;
2968 
2969  xpos += Target_triangle_height * cos_ang;
2970  ypos -= Target_triangle_height * sin_ang;
2971 
2972  if ( tail_len > 0 ) {
2973  xtail = xpos + tail_len * cos_ang;
2974  ytail = ypos - tail_len * sin_ang;
2975  }
2976  }
2977 
2979  if (draw_solid) {
2980  hud_tri(xpos,ypos,x1,y1,x2,y2);
2981  } else {
2982  hud_tri_empty(xpos,ypos,x1,y1,x2,y2);
2983  }
2984 
2985  // draw the tail indicating length
2986  if ( tail_len > 0 ) {
2987  gr_line(fl2i(xpos), fl2i(ypos), fl2i(xtail), fl2i(ytail));
2988  }
2990 }
2991 
2992 // Render a triangle on the outside of the targeting circle.
2993 // Must be inside a g3_start_frame().
2994 // If aspect_flag !0, then render filled, indicating aspect lock.
2995 // If show_interior !0, then point inwards to positions inside reticle
2996 void HudGaugeReticleTriangle::renderTriangle(vec3d *hostile_pos, int aspect_flag, int show_interior, int split_tri)
2997 {
2998  vertex hostile_vertex;
2999  float ang;
3000  float xpos,ypos,cur_dist,sin_ang,cos_ang;
3001  int draw_inside=0;
3002 
3003  // determine if the given object is within the targeting reticle
3004  // (which means the triangle is not drawn)
3005 
3006  cur_dist = vm_vec_dist_quick(&Player_obj->pos, hostile_pos);
3007 
3008  g3_rotate_vertex(&hostile_vertex, hostile_pos);
3009  g3_project_vertex(&hostile_vertex);
3010 
3011  if (hostile_vertex.codes == 0) { // on screen
3012  int projected_x, projected_y;
3013 
3014  if (!(hostile_vertex.flags & PF_OVERFLOW)) { // make sure point projected
3015  int mag_squared;
3016 
3017  projected_x = fl2i(hostile_vertex.screen.xyw.x);
3018  projected_y = fl2i(hostile_vertex.screen.xyw.y);
3019 
3020  unsize(&projected_x, &projected_y);
3021 
3022  mag_squared = (projected_x - position[0]) * (projected_x - position[0]) +
3023  (projected_y - position[1]) * (projected_y - position[1]);
3024 
3025  if ( mag_squared < Radius*Radius ) {
3026  if ( show_interior ) {
3027  draw_inside=1;
3028  } else {
3029  return;
3030  }
3031  }
3032  }
3033  }
3034 
3035  int HUD_nose_scaled_x = HUD_nose_x;
3036  int HUD_nose_scaled_y = HUD_nose_y;
3037 
3038  gr_resize_screen_pos(&HUD_nose_scaled_x, &HUD_nose_scaled_y);
3039 
3040  unsize( &hostile_vertex.world.xyz.x, &hostile_vertex.world.xyz.y );
3041 
3042  ang = atan2_safe(hostile_vertex.world.xyz.y,hostile_vertex.world.xyz.x);
3043  sin_ang=sinf(ang);
3044  cos_ang=cosf(ang);
3045 
3046  if ( draw_inside ) {
3047  xpos = position[0] + cos_ang*(Radius-7);
3048  ypos = position[1] - sin_ang*(Radius-7);
3049  } else {
3050  xpos = position[0] + cos_ang*(Radius+4);
3051  ypos = position[1] - sin_ang*(Radius+4);
3052  }
3053 
3054  xpos += HUD_offset_x + HUD_nose_x;
3055  ypos += HUD_offset_y + HUD_nose_y;
3056 
3057  if ( split_tri ) {
3058  // renderTriangleMissileSplit(ang, xpos, ypos, cur_dist, aspect_flag, draw_inside);
3059  renderTriangleMissileTail(ang, xpos, ypos, cur_dist, aspect_flag, draw_inside);
3060  } else {
3061  float x1=0.0f;
3062  float x2=0.0f;
3063  float y1=0.0f;
3064  float y2=0.0f;
3065 
3066  if ( draw_inside ) {
3067  x1 = xpos - Target_triangle_base * -sin_ang;
3068  y1 = ypos + Target_triangle_base * cos_ang;
3069  x2 = xpos + Target_triangle_base * -sin_ang;
3070  y2 = ypos - Target_triangle_base * cos_ang;
3071 
3072  xpos -= Target_triangle_height * cos_ang;
3073  ypos += Target_triangle_height * sin_ang;
3074 
3075  } else {
3076  x1 = xpos - Target_triangle_base * -sin_ang;
3077  y1 = ypos + Target_triangle_base * cos_ang;
3078  x2 = xpos + Target_triangle_base * -sin_ang;
3079  y2 = ypos - Target_triangle_base * cos_ang;
3080 
3081  xpos += Target_triangle_height * cos_ang;
3082  ypos -= Target_triangle_height * sin_ang;
3083  }
3084 
3085  //renderPrintf(position[0], position[1], "%d", fl2i((360*ang)/(2*PI)));
3087  if (aspect_flag) {
3088  hud_tri(xpos,ypos,x1,y1,x2,y2);
3089  } else {
3090  hud_tri_empty(xpos,ypos,x1,y1,x2,y2);
3091  }
3093  }
3094 }
3095 
3096 // Show all homing missiles locked onto the player.
3097 // Also, play the beep!
3099 {
3100  object *A;
3101  missile_obj *mo;
3102  weapon *wp;
3103  float dist, nearest_dist;
3104  int closest_is_aspect=0;
3105 
3106  nearest_dist = Homing_beep.max_cycle_dist;
3107 
3108  for ( mo = GET_NEXT(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) {
3109  A = &Objects[mo->objnum];
3110  Assert((A->instance >= 0) && (A->instance < MAX_WEAPONS));
3111 
3112  wp = &Weapons[A->instance];
3113 
3114  if (wp->homing_object == Player_obj) {
3115  dist = vm_vec_dist_quick(&A->pos, &Player_obj->pos);
3116 
3117  if (dist < nearest_dist) {
3118  nearest_dist = dist;
3120  closest_is_aspect=1;
3121  } else {
3122  closest_is_aspect=0;
3123  }
3124  }
3125  }
3126  }
3127 
3128  // See if need to play warning beep.
3129  if (nearest_dist < Homing_beep.max_cycle_dist ) {
3130  float delta_time;
3131  float cycle_time;
3132 
3133  delta_time = f2fl(Missiontime - Homing_beep.last_time_played);
3134 
3135  // figure out the cycle time by doing a linear interpretation
3136  cycle_time = Homing_beep.min_cycle_time + (nearest_dist-Homing_beep.min_cycle_dist) * Homing_beep.precalced_interp;
3137 
3138  // play a new 'beep' if cycle time has elapsed
3139  if ( (delta_time*1000) > cycle_time ) {
3140  Homing_beep.last_time_played = Missiontime;
3141  if ( snd_is_playing(Homing_beep.snd_handle) ) {
3142  snd_stop(Homing_beep.snd_handle);
3143  }
3144 
3145  if ( closest_is_aspect ) {
3147  } else {
3149  }
3150  }
3151  }
3152 }
3153 
3156 {
3157 }
3158 
3160 {
3161  object *A;
3162  missile_obj *mo;
3163  weapon *wp;
3164 
3165  bool in_frame = g3_in_frame() > 0;
3166  if(!in_frame)
3167  g3_start_frame(0);
3169 
3170  gr_set_color_fast(&HUD_color_homing_indicator);
3171 
3172  for ( mo = GET_NEXT(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) {
3173  A = &Objects[mo->objnum];
3174  Assert((A->instance >= 0) && (A->instance < MAX_WEAPONS));
3175 
3176  wp = &Weapons[A->instance];
3177 
3178  if (wp->homing_object == Player_obj) {
3180  }
3181  }
3182 
3184  if(!in_frame)
3185  g3_end_frame();
3186 }
3187 
3190 {
3191 }
3192 
3194 {
3195  Radius = length;
3196 }
3197 
3199 {
3200 }
3201 
3202 // hud_show_orientation_tee() will draw the orientation gauge that orbits the inside of the
3203 // outer reticle ring. If the T is at 12 o'clock, the target is facing the player, if the T
3204 // is at 6 o'clock the target is facing away from the player. If the T is at 3 or 9 o'clock
3205 // the target is facing 90 away from the player.
3206 void HudGaugeOrientationTee::render(float frametime)
3207 {
3208  object* targetp;
3209 
3211  return;
3212 
3213  targetp = &Objects[Player_ai->target_objnum];
3214 
3215  if ( maybeFlashSexp() == 1 ) {
3216  hud_set_iff_color( targetp );
3217  } else {
3218  hud_set_iff_color( targetp, 1);
3219  }
3220  renderOrientation(targetp, Player_obj, &targetp->orient);
3221 }
3222 
3223 // routine to draw a bounding box around a remote detonate missile and distance to
3225 {
3226  missile_obj *mo;
3227  object *mobjp;
3228  vertex target_point;
3229 
3230  memset(&target_point, 0, sizeof(target_point));
3231 
3232  // check for currently locked missiles (highest precedence)
3233  for ( mo = GET_FIRST(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) {
3234  Assert(mo->objnum >= 0 && mo->objnum < MAX_OBJECTS);
3235  mobjp = &Objects[mo->objnum];
3236 
3237  if ((Player_obj != NULL) && (mobjp->parent_sig == Player_obj->parent_sig)) {
3239  // get box center point
3240  g3_rotate_vertex(&target_point,&mobjp->pos);
3241 
3242  // project vertex
3243  g3_project_vertex(&target_point);
3244 
3245  if (!(target_point.flags & PF_OVERFLOW)) { // make sure point projected
3246  switch ( mobjp->type ) {
3247  case OBJ_WEAPON:
3248  hud_target_add_display_list(mobjp, &target_point, &mobjp->pos, 0, iff_get_color(IFF_COLOR_MESSAGE, 1), NULL, TARGET_DISPLAY_DIST);
3249  break;
3250 
3251  default:
3252  Int3(); // should never happen
3253  return;
3254  }
3255 
3256  // do only for the first remote detonate missile
3257  break;
3258  }
3259  }
3260  }
3261  }
3262 }
3263 
3264 // routine to possibly draw a bounding box around a ship sending a message to the player
3266 {
3267  object *targetp;
3268  vertex target_point; // temp vertex used to find screen position for 3-D object;
3269 
3270  // don't draw brackets if no ship sending a message
3271  if ( Message_shipnum == -1 )
3272  return;
3273 
3274  targetp = &Objects[Ships[Message_shipnum].objnum];
3275  Assert ( targetp != NULL );
3276 
3277  Assert ( targetp->type == OBJ_SHIP );
3278 
3279  // Don't do this for the ship you're flying!
3280  if ( targetp == Player_obj ) {
3281  return;
3282  }
3283 
3284  // Goober5000 - don't draw if primitive sensors
3285  if ( Ships[Player_obj->instance].flags2 & SF2_PRIMITIVE_SENSORS ) {
3286  return;
3287  }
3288 
3289  // Karajorma - If we've gone to all the trouble to make our friendly ships stealthed they shouldn't then give away
3290  // their position cause they're feeling chatty
3291  // MageKing17 - Make the check see if they're actually stealthed at the time, and may as well include a check for
3292  // being hidden from sensors, too; logic copied from a similar check in hudescort.cpp
3294  || ((Ships[Message_shipnum].flags2 & SF2_STEALTH) && ((Ships[Message_shipnum].team != Player_ship->team) || (Ships[Message_shipnum].flags2 & SF2_FRIENDLY_STEALTH_INVIS)))
3295  ) {
3296  return;
3297  }
3298 
3299  Assert ( targetp->instance >=0 && targetp->instance < MAX_SHIPS );
3300 
3301  // check the object flags to see if this ship is gone. If so, then don't do this stuff anymore
3302  if ( targetp->flags & OF_SHOULD_BE_DEAD ) {
3303  Message_shipnum = -1;
3304  return;
3305  }
3306 
3307  memset(&target_point, 0, sizeof(target_point));
3308 
3309  // find the current target vertex
3310  g3_rotate_vertex(&target_point, &targetp->pos);
3311  g3_project_vertex(&target_point);
3312 
3313  if (!(target_point.flags & PF_OVERFLOW)) { // make sure point projected
3314  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 10, iff_get_color(IFF_COLOR_MESSAGE, 1), NULL, 0);
3315  } else if (target_point.codes != 0) { // target center is not on screen
3316  // draw the offscreen indicator at the edge of the screen where the target is closest to
3317  // AL 11-19-97: only show offscreen indicator if player sensors are functioning
3319  if ( hud_sensors_ok(Player_ship, 0) ) {
3320  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 0, iff_get_color(IFF_COLOR_MESSAGE, 1), NULL, TARGET_DISPLAY_DIST);
3321  }
3322  }
3323  }
3324 }
3325 
3326 // hud_prune_hotkeys()
3327 //
3328 // Check for ships that are dying, departed or dead. These should be removed from the player's
3329 // hotkey lists.
3331 {
3332  int i;
3333  htarget_list *hitem, *plist;
3334  object *objp;
3335  ship *sp;
3336 
3337  for ( i = 0; i < MAX_KEYED_TARGETS; i++ ) {
3338  plist = &(Players[Player_num].keyed_targets[i]);
3339  if ( EMPTY( plist ) ) // no items in list, then do nothing
3340  continue;
3341 
3342  hitem = GET_FIRST(plist);
3343  while ( hitem != END_OF_LIST(plist) ) {
3344  int remove_item;
3345 
3346  remove_item = 0;
3347 
3348  objp = hitem->objp;
3349  Assert ( objp != NULL );
3350  if ( objp->type == OBJ_SHIP ) {
3351  Assert ( objp->instance >=0 && objp->instance < MAX_SHIPS );
3352  sp = &Ships[objp->instance];
3353  } else {
3354  // if the object isn't a ship, it shouldn't be on the list, so remove it without question
3355  remove_item = 1;
3356  sp = NULL;
3357  }
3358 
3359  // check to see if the object is dying -- if so, remove it from the list
3360  // check to see if the ship is departing -- if so, remove it from the list
3361  if ( remove_item || (objp->flags & OF_SHOULD_BE_DEAD) || (sp->flags & (SF_DEPARTING|SF_DYING)) ) {
3362  if ( sp != NULL ) {
3363  nprintf(("Network", "Hotkey: Pruning %s\n", sp->ship_name));
3364  }
3365 
3366  htarget_list *temp;
3367  temp = GET_NEXT(hitem);
3368  list_remove( plist, hitem );
3369  list_append( &htarget_free_list, hitem );
3370  hitem->objp = NULL;
3371  hitem = temp;
3372  continue;
3373  }
3374  hitem = GET_NEXT( hitem );
3375  } // end while
3376  } // end for
3377 
3378  // save the hotkey sets with mission time reaches a certain point. Code was put here because this
3379  // function always called for both single/multiplayer. Maybe not the best location, but whatever.
3381 }
3382 
3384 
3385 // hud_show_selection_set draws some indicator around all the ships in the current selection set. No
3386 // indicators will be drawn if there is only 1 ship in the set.
3388 {
3389  htarget_list *hitem, *plist;
3390  object *targetp;
3391  int set, count;
3392  vertex target_point; // temp vertex used to find screen position for 3-D object;
3393 
3394  HUD_drew_selection_bracket_on_target = 0;
3395 
3397  if ( set == -1 )
3398  return;
3399 
3400  Assert ( (set >= 0) && (set < MAX_KEYED_TARGETS) );
3401  plist = &(Players[Player_num].keyed_targets[set]);
3402 
3403  count = 0;
3404  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) )
3405  count++;
3406 
3407  if ( count == 0 ) { // only one ship, do nothing
3409  return;
3410  }
3411 
3412  memset(&target_point, 0, sizeof(target_point));
3413 
3414  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
3415  targetp = hitem->objp;
3416  Assert ( targetp != NULL );
3417 
3418  ship *target_shipp = NULL;
3419 
3420  Assert ( targetp->type == OBJ_SHIP );
3421  Assert ( targetp->instance >=0 && targetp->instance < MAX_SHIPS );
3422  target_shipp = &Ships[targetp->instance];
3423 
3424  if ( (Game_mode & GM_MULTIPLAYER) && (target_shipp == Player_ship) ) {
3425  continue;
3426  }
3427 
3428  // Goober5000 - don't draw indicators for non-visible ships, per Mantis #1972
3429  // (the only way we could get here is if the hotkey set contained a mix of visible
3430  // and invisible ships)
3431  if (awacs_get_level(targetp, Player_ship, 1) < 1) {
3432  continue;
3433  }
3434 
3435  // find the current target vertex
3436  //
3437  g3_rotate_vertex(&target_point,&targetp->pos);
3438  g3_project_vertex(&target_point);
3439 
3440  if (!(target_point.flags & PF_OVERFLOW)) { // make sure point projected
3441 
3442  switch ( targetp->type ) {
3443  case OBJ_SHIP:
3444  break;
3445 
3446  default:
3447  Int3(); // should never happen
3448  return;
3449  }
3450  if ( OBJ_INDEX(targetp) == Player_ai->target_objnum ) {
3451  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 5, iff_get_color(IFF_COLOR_SELECTION, 1), NULL, 0);
3452  HUD_drew_selection_bracket_on_target = 1;
3453  } else if ( Cmdline_targetinfo ) { //Backslash -- show the distance and a lead indicator
3455  } else {
3456  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 5, iff_get_color(IFF_COLOR_SELECTION, 1), NULL, 0);
3457  }
3458  }
3459 
3460  if (target_point.codes != 0) { // target center is not on screen
3461  // draw the offscreen indicator at the edge of the screen where the target is closest to
3462  // AL 11-19-97: only show offscreen indicator if player sensors are functioning
3463 
3464  if ( OBJ_INDEX(targetp) != Player_ai->target_objnum ) {
3465  if ( hud_sensors_ok(Player_ship, 0) ) {
3466  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 5, iff_get_color(IFF_COLOR_SELECTION, 1), NULL, 0);
3467  }
3468  }
3469  }
3470  }
3471 }
3472 
3473 // hud_show_targeting_gauges() will display the targeting information on the HUD. Called once per frame.
3474 //
3475 // Must be inside a g3_start_frame()
3476 // input: frametime => time in seconds since last update
3477 // in_cockpit => flag (default value 1) indicating whether viewpoint is from cockpit or external
3478 void hud_show_targeting_gauges(float frametime)
3479 {
3480  vertex target_point; // temp vertex used to find screen position for 3-D object;
3481  vec3d target_pos;
3482 
3484 
3485  if (Player_ai->target_objnum == -1)
3486  return;
3487 
3488  object * targetp = &Objects[Player_ai->target_objnum];
3490 
3491  // check to see if there is even a current target
3492  if ( targetp == &obj_used_list ) {
3493  return;
3494  }
3495 
3496  // AL 1/20/97: Point to targted subsystem if one exists
3497  if ( Player_ai->targeted_subsys != NULL ) {
3498  get_subsystem_world_pos(targetp, Player_ai->targeted_subsys, &target_pos);
3499  } else {
3500  target_pos = targetp->pos;
3501  }
3502 
3503  // find the current target vertex
3504  //
3505  // The 2D screen pos depends on the current viewer position and orientation.
3506  g3_rotate_vertex(&target_point,&target_pos);
3507 
3508  hud_set_iff_color( targetp, 1 );
3509  g3_project_vertex(&target_point);
3510 
3511  if (!(target_point.flags & PF_OVERFLOW)) { // make sure point projected
3512  if (target_point.codes == 0) { // target center is not on screen
3513  int target_display_flags;
3514 
3515  if(Cmdline_targetinfo) {
3517  } else {
3519  }
3520 
3521  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 0, NULL, NULL, target_display_flags);
3522  }
3523  } else {
3524  Hud_target_w = 0;
3525  Hud_target_h = 0;
3526  }
3527 
3528  // update cargo scanning
3529  hud_cargo_scan_update(targetp, frametime);
3530 
3531  // display the lock indicator
3532  if (!Player->target_is_dying) {
3533  hud_do_lock_indicator(frametime);
3534 
3535  // update and render artillery
3538  }
3539 
3540  if (target_point.codes != 0) {
3541  // draw the offscreen indicator at the edge of the screen where the target is closest to
3543 
3544  // AL 11-11-97: don't draw the indicator if the ship is messaging, the indicator is drawn
3545  // in the message sending color in hud_show_message_sender()
3547  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 0, NULL, NULL, 0);
3548  }
3549  }
3550 }
3551 
3552 // hud_show_hostile_triangle() will draw an empty triangle that oribits around the outer
3553 // circle of the reticle. It will point to the closest enemy that is firing on the player.
3554 // Currently, it points to the closest enemy that has the player as its target_objnum and has
3555 // SM_ATTACK or SM_SUPER_ATTACK as its ai submode.
3557 {
3558  object* A;
3559  float min_distance=1e20f;
3560  float new_distance=0.0f;
3561  object* nearest_obj = &obj_used_list;
3562  ai_info *aip;
3563  ship_obj *so;
3564  ship *sp;
3565  ship_subsys *ss;
3566 
3567  int player_obj_index = OBJ_INDEX(Player_obj);
3568  int turret_is_attacking = 0;
3569 
3570  hostile_obj = NULL;
3571 
3572  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
3573 
3574  A = &Objects[so->objnum];
3575  sp = &Ships[A->instance];
3576 
3577  // only look at ships who attack us
3578  if ( (A == Player_obj) || !(iff_x_attacks_y(Ships[A->instance].team, Player_ship->team)) ) {
3579  continue;
3580  }
3581 
3582  aip = &Ai_info[Ships[A->instance].ai_index];
3583 
3584  // don't look at ignore ships
3585  if ( sp->flags & TARGET_SHIP_IGNORE_FLAGS ) {
3586  continue;
3587  }
3588 
3589  // always ignore cargo containers and navbuoys
3590  if ( Ship_info[sp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[sp->ship_info_index].class_type].hud_bools & STI_HUD_SHOW_ATTACK_DIRECTION) ) {
3591  continue;
3592  }
3593 
3594  // check if ship is stealthy
3595  if (awacs_get_level(&Objects[sp->objnum], Player_ship, 1) < 1) {
3596  continue;
3597  }
3598 
3599  turret_is_attacking = 0;
3600 
3601  // check if any turrets on ship are firing at the player (only on non fighter-bombers)
3602  if ( !(Ship_info[sp->ship_info_index].flags & (SIF_FIGHTER|SIF_BOMBER)) ) {
3603  for (ss = GET_FIRST(&sp->subsys_list); ss != END_OF_LIST(&sp->subsys_list); ss = GET_NEXT(ss) ) {
3604  if (ss->flags & SSF_UNTARGETABLE)
3605  continue;
3606 
3607  if ( (ss->system_info->type == SUBSYSTEM_TURRET) && (ss->current_hits > 0) ) {
3608 
3609  if ( ss->turret_enemy_objnum == player_obj_index ) {
3610  turret_is_attacking = 1;
3611 
3612  vec3d gsubpos;
3613  // get world pos of subsystem
3614  vm_vec_unrotate(&gsubpos, &ss->system_info->pnt, &A->orient);
3615  vm_vec_add2(&gsubpos, &A->pos);
3616  new_distance = vm_vec_dist_quick(&gsubpos, &Player_obj->pos);
3617 
3618  if (new_distance <= min_distance) {
3619  min_distance=new_distance;
3620  nearest_obj = A;
3621  }
3622  }
3623  }
3624  }
3625  }
3626 
3627  if ( !turret_is_attacking ) {
3628  // check for ships attacking the player
3629  if ( aip->target_objnum != Player_ship->objnum ) {
3630  continue;
3631  }
3632 
3633  // ignore enemy if not in chase mode
3634  if ( (Game_mode & GM_NORMAL) && (aip->mode != AIM_CHASE) ) {
3635  continue;
3636  }
3637 
3638  new_distance = vm_vec_dist_quick(&A->pos, &Player_obj->pos);
3639 
3640  if (new_distance <= min_distance) {
3641  min_distance=new_distance;
3642  nearest_obj = A;
3643  }
3644  }
3645  }
3646 
3647  if ( nearest_obj == &obj_used_list ) {
3648  return;
3649  }
3650 
3651  if ( min_distance > MIN_DISTANCE_TO_CONSIDER_THREAT ) {
3652  return;
3653  }
3654 
3655  hostile_obj = nearest_obj;
3656 
3657  // hook to maybe warn player about this attacking ship
3658  ship_maybe_warn_player(&Ships[nearest_obj->instance], min_distance);
3659 }
3660 
3663 {
3664 }
3665 
3666 void HudGaugeHostileTriangle::render(float frametime)
3667 {
3668  if (hostile_obj && maybeFlashSexp() != 1) {
3669  bool in_frame = g3_in_frame() > 0;
3670  if(!in_frame)
3671  g3_start_frame(0);
3672 
3673  // hud_set_iff_color( TEAM_HOSTILE, 1 ); // Note: This should really be TEAM_HOSTILE, not opposite of Player_ship->team.
3674  hud_set_iff_color( hostile_obj, 1 );
3675  renderTriangle(&hostile_obj->pos, 0, 1, 0);
3676 
3677  if(!in_frame)
3678  g3_end_frame();
3679  }
3680 }
3681 
3682 void hud_calculate_lead_pos(vec3d *lead_target_pos, vec3d *target_pos, object *targetp, weapon_info *wip, float dist_to_target, vec3d *rel_pos)
3683 {
3684  vec3d target_moving_direction;
3685  vec3d last_delta_vector;
3686  float time_to_target, target_moved_dist;
3687 
3688  if(wip->max_speed != 0) {
3689  time_to_target = dist_to_target / wip->max_speed;
3690  } else {
3691  time_to_target = 0;
3692  }
3693 
3694  target_moved_dist = targetp->phys_info.speed * time_to_target;
3695 
3696  target_moving_direction = targetp->phys_info.vel;
3697 
3699  vm_vec_scale_sub2(&target_moving_direction, &Player_obj->phys_info.vel, wip->vel_inherit_amount);
3700 
3701  // test if the target is moving at all
3702  if ( vm_vec_mag_quick(&target_moving_direction) < 0.1f ) { // Find distance!
3703  *lead_target_pos = *target_pos;
3704  } else {
3705  vm_vec_normalize(&target_moving_direction);
3706  vm_vec_scale(&target_moving_direction, target_moved_dist);
3707  vm_vec_add(lead_target_pos, target_pos, &target_moving_direction );
3708  polish_predicted_target_pos(wip, targetp, target_pos, lead_target_pos, dist_to_target, &last_delta_vector, 1); // Not used:, float time_to_enemy)
3709 
3710  if(rel_pos) { // needed for quick lead indicators, not needed for normal lead indicators.
3711  vm_vec_add2(lead_target_pos, rel_pos);
3712  }
3713  }
3714 }
3715 
3716 // Return the bank number for the primary weapon that can fire the farthest, from
3717 // the number of active primary weapons
3718 // input: range => output parameter... it is the range of the selected bank
3720 {
3721  int i, best_bank, bank_to_fire, num_to_test;
3722  float weapon_range, farthest_weapon_range;
3723  ship_weapon *swp;
3724  weapon_info *wip;
3725 
3726  swp = &Player_ship->weapons;
3727 
3728  farthest_weapon_range = 0.0f;
3729  best_bank = -1;
3730 
3731  if ( Player_ship->flags & SF_PRIMARY_LINKED ) {
3732  num_to_test = swp->num_primary_banks;
3733  } else {
3734  num_to_test = MIN(1, swp->num_primary_banks);
3735  }
3736 
3737  for ( i = 0; i < num_to_test; i++ )
3738  {
3739  bank_to_fire = (swp->current_primary_bank + i) % swp->num_primary_banks;
3740 
3741  // calculate the range of the weapon, and only display the lead target indicator
3742  // if the weapon can actually hit the target
3743  Assert(bank_to_fire >= 0 && bank_to_fire < swp->num_primary_banks);
3744  Assert(swp->primary_bank_weapons[bank_to_fire] < MAX_WEAPON_TYPES);
3745 
3746  if (swp->primary_bank_weapons[bank_to_fire] < 0)
3747  continue;
3748 
3749  wip = &Weapon_info[swp->primary_bank_weapons[bank_to_fire]];
3750  weapon_range = MIN((wip->max_speed * wip->lifetime), wip->weapon_range);
3751 
3752  // don't consider this primary if it's a ballistic that's out of ammo - Goober5000
3753  if ( wip->wi_flags2 & WIF2_BALLISTIC )
3754  {
3755  if ( swp->primary_bank_ammo[bank_to_fire] <= 0)
3756  {
3757  continue;
3758  }
3759  }
3760 
3761  if ( weapon_range > farthest_weapon_range )
3762  {
3763  best_bank = bank_to_fire;
3764  farthest_weapon_range = weapon_range;
3765  }
3766  }
3767 
3768  *range = farthest_weapon_range;
3769  return best_bank;
3770 }
3771 
3772 // -----------------------------------------------------------------------------
3773 // polish_predicted_target_pos()
3774 //
3775 // Called by the draw lead indicator code to predict where the enemy is going to be
3776 //
3777 void polish_predicted_target_pos(weapon_info *wip, object *targetp, vec3d *enemy_pos, vec3d *predicted_enemy_pos, float dist_to_enemy, vec3d *last_delta_vec, int num_polish_steps)
3778 {
3779  int iteration;
3780  vec3d player_pos = Player_obj->pos;
3781  float time_to_enemy;
3782  vec3d last_predicted_enemy_pos = *predicted_enemy_pos;
3783 
3784  float weapon_speed = wip->max_speed;
3785 
3786  vm_vec_zero(last_delta_vec);
3787 
3788  // additive velocity stuff
3789  // not just the player's main target
3790  vec3d enemy_vel = targetp->phys_info.vel;
3793  }
3794 
3795  for (iteration=0; iteration < num_polish_steps; iteration++) {
3796  dist_to_enemy = vm_vec_dist_quick(predicted_enemy_pos, &player_pos);
3797  time_to_enemy = dist_to_enemy/weapon_speed;
3798  vm_vec_scale_add(predicted_enemy_pos, enemy_pos, &enemy_vel, time_to_enemy);
3799  vm_vec_sub(last_delta_vec, predicted_enemy_pos, &last_predicted_enemy_pos);
3800  last_predicted_enemy_pos= *predicted_enemy_pos;
3801  }
3802 }
3803 
3806 {
3807 
3808 }
3809 
3811 {
3812  Lead_indicator_half[0] = w;
3813  Lead_indicator_half[1] = h;
3814 }
3815 
3817 {
3818  Lead_indicator_gauge.first_frame = bm_load_animation(fname, &Lead_indicator_gauge.num_frames);
3819  if ( Lead_indicator_gauge.first_frame < 0 ) {
3820  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
3821  }
3822 }
3823 
3825 {
3826  bm_page_in_aabitmap(Lead_indicator_gauge.first_frame, Lead_indicator_gauge.num_frames);
3827 }
3828 
3829 // determine the correct frame to draw for the lead indicator
3830 // 0 -> center only (in secondary range only)
3831 // 1 -> full (in secondary and primary range)
3832 // 2 -> oustide only (in primary range only)
3833 //
3834 // input: prange => range of current primary weapon
3835 // srange => range of current secondary weapon
3836 // dist_to_target => current dist to target
3837 //
3838 // exit: 0-2 => frame offset
3839 // -1 => don't draw anything
3840 int HudGaugeLeadIndicator::pickFrame(float prange, float srange, float dist_to_target)
3841 {
3842  int frame_offset=-1;
3843  int in_prange=0, in_srange=0;
3844 
3845  if ( dist_to_target < prange ) {
3846  in_prange=1;
3847  }
3848 
3849  if ( dist_to_target < srange ) {
3850  in_srange=1;
3851  }
3852 
3853  if ( in_prange && in_srange ) {
3854  frame_offset=1;
3855  } else if ( in_prange && !in_srange ) {
3856  frame_offset=2;
3857  } else if ( !in_prange && in_srange ) {
3858  frame_offset=0;
3859  } else {
3860  frame_offset=-1;
3861  }
3862 
3863  return frame_offset;
3864 }
3865 
3866 void HudGaugeLeadIndicator::render(float frametime)
3867 {
3868  if(Player->target_is_dying) {
3869  return;
3870  }
3871 
3872  bool in_frame = g3_in_frame() > 0;
3873  if(!in_frame)
3874  g3_start_frame(0);
3875 
3876  // first render the current target the player has selected.
3878 
3879  // if extra targeting info is enabled, render lead indicators for objects in the target display list.
3880  for(size_t i = 0; i < target_display_list.size(); i++) {
3881  if ( (target_display_list[i].flags & TARGET_DISPLAY_LEAD) && target_display_list[i].objp ) {
3882 
3883  // set the color
3884  if( target_display_list[i].bracket_clr.red && target_display_list[i].bracket_clr.green &&
3885  target_display_list[i].bracket_clr.blue ) {
3886  gr_set_color_fast(&target_display_list[i].bracket_clr);
3887  } else {
3888  // use IFF colors if none defined.
3889  hud_set_iff_color(target_display_list[i].objp, 1);
3890  }
3891 
3892  renderLeadQuick(&target_display_list[i].target_pos, target_display_list[i].objp);
3893  }
3894  }
3895 
3896  if(!in_frame)
3897  g3_end_frame();
3898 }
3899 
3900 void HudGaugeLeadIndicator::renderIndicator(int frame_offset, object *targetp, vec3d *lead_target_pos)
3901 {
3902  vertex lead_target_vertex;
3903  int sx, sy;
3904 
3905  g3_rotate_vertex(&lead_target_vertex, lead_target_pos);
3906 
3907  if (lead_target_vertex.codes == 0) { // on screen
3908  g3_project_vertex(&lead_target_vertex);
3909 
3910  if (!(lead_target_vertex.flags & PF_OVERFLOW)) {
3911  if ( maybeFlashSexp() == 1 ) {
3912  hud_set_iff_color(targetp, 0);
3913  } else {
3914  hud_set_iff_color(targetp, 1);
3915  }
3916 
3917  if ( Lead_indicator_gauge.first_frame + frame_offset >= 0 ) {
3918  sx = fl2i(lead_target_vertex.screen.xyw.x);
3919  sy = fl2i(lead_target_vertex.screen.xyw.y);
3920 
3921  unsize(&sx, &sy);
3922  renderBitmap(Lead_indicator_gauge.first_frame + frame_offset, fl2i(sx - Lead_indicator_half[0]), fl2i(sy - Lead_indicator_half[1]));
3923  }
3924  }
3925  }
3926 }
3927 
3928 // HudGaugeLeadIndicator::renderTargetLead() determine where to draw the lead target box and display it
3930 {
3931  vec3d target_pos;
3932  vec3d source_pos;
3933  vec3d *rel_pos;
3934  vec3d lead_target_pos;
3935  object *targetp;
3936  polymodel *pm;
3937  ship_weapon *swp;
3938  weapon_info *wip;
3939  weapon_info *tmp=NULL;
3940  float dist_to_target, prange, srange;
3941  int bank_to_fire, frame_offset;
3942 
3943  if (Player_ai->target_objnum == -1)
3944  return;
3945 
3946  targetp = &Objects[Player_ai->target_objnum];
3947  if ( (targetp->type != OBJ_SHIP) && (targetp->type != OBJ_WEAPON) && (targetp->type != OBJ_ASTEROID) ) {
3948  return;
3949  }
3950 
3951  // only allow bombs to have lead indicator displayed
3952  if ( targetp->type == OBJ_WEAPON ) {
3955  return;
3956  }
3957  }
3958  }
3959 
3960  // If the target is out of range, then draw the correct frame for the lead indicator
3961  if ( Lead_indicator_gauge.first_frame == -1 ) {
3962  Int3();
3963  return;
3964  }
3965 
3966  // AL 1/20/97: Point to targted subsystem if one exists
3967  if ( Player_ai->targeted_subsys != NULL ) {
3968  get_subsystem_world_pos(targetp, Player_ai->targeted_subsys, &target_pos);
3969  } else {
3970  target_pos = targetp->pos;
3971  }
3972 
3973  pm = model_get(Ship_info[Player_ship->ship_info_index].model_num);
3974  swp = &Player_ship->weapons;
3975 
3976  // Added to take care of situation where there are no primary banks on the player ship
3977  // (this may not be possible, depending on what we decide for the weapons loadout rules)
3978  if ( swp->num_primary_banks == 0 )
3979  return;
3980 
3981  bank_to_fire = hud_get_best_primary_bank(&prange);
3982 
3983  if ( bank_to_fire < 0 )
3984  return;
3985 
3986  wip = &Weapon_info[swp->primary_bank_weapons[bank_to_fire]];
3987 
3988  if (pm->n_guns && bank_to_fire != -1 ) {
3989  rel_pos = &pm->gun_banks[bank_to_fire].pnt[0];
3990  } else {
3991  rel_pos = NULL;
3992  }
3993 
3994  // source_pos will contain the world coordinate of where to base the lead indicator prediction
3995  // from. Normally, this will be the world pos of the gun turret of the currently selected primary
3996  // weapon.
3997  source_pos = Player_obj->pos;
3998  if (rel_pos != NULL) {
3999  vec3d gun_point;
4000  vm_vec_unrotate(&gun_point, rel_pos, &Player_obj->orient);
4001  vm_vec_add2(&source_pos, &gun_point);
4002  }
4003 
4004  // Determine "accurate" distance to target.
4005  // This is the distance from the player ship to:
4006  // (if targeting a subsystem) the distance to the subsystem centre
4007  // (playing it safe, will usually be in range at slightly further away due to subsys radius)
4008  // (otherwise) the closest point on the bounding box of the target
4009  if ( Player_ai->targeted_subsys != NULL ) {
4010  dist_to_target = vm_vec_dist(&target_pos, &Player_obj->pos);
4011  } else {
4012  dist_to_target = hud_find_target_distance(targetp, Player_obj);
4013  }
4014 
4016 
4017  if ( (swp->current_secondary_bank >= 0) && (swp->secondary_bank_weapons[swp->current_secondary_bank] >= 0) )
4018  {
4019  int bank = swp->current_secondary_bank;
4020  tmp = &Weapon_info[swp->secondary_bank_weapons[bank]];
4021  if ( !(tmp->wi_flags & WIF_HOMING) && !(tmp->wi_flags & WIF_LOCKED_HOMING && Player->target_in_lock_cone) ) {
4022  //The secondary lead indicator is handled farther below if it is a non-locking type
4023  srange = -1.0f;
4024  }
4025  }
4026 
4027  frame_offset = pickFrame(prange, srange, dist_to_target);
4028  if ( frame_offset < 0 ) {
4029  return;
4030  }
4031 
4032  hud_calculate_lead_pos(&lead_target_pos, &target_pos, targetp, wip, dist_to_target);
4033  renderIndicator(frame_offset, targetp, &lead_target_pos);
4034 
4035  //do dumbfire lead indicator - color is orange (255,128,0) - bright, (192,96,0) - dim
4036  //phreak changed 9/01/02
4037  if((swp->current_secondary_bank>=0) && (swp->secondary_bank_weapons[swp->current_secondary_bank] >= 0)) {
4038  int bank=swp->current_secondary_bank;
4039  wip=&Weapon_info[swp->secondary_bank_weapons[bank]];
4040 
4041  //get out of here if the secondary weapon is a homer or if its out of range
4042  if ( wip->wi_flags & WIF_HOMING )
4043  return;
4044 
4045  double max_dist = MIN((wip->lifetime * wip->max_speed), wip->weapon_range);
4046 
4047  if (dist_to_target > max_dist)
4048  return;
4049  }
4050 
4051  hud_calculate_lead_pos(&lead_target_pos, &target_pos, targetp, wip, dist_to_target);
4052  renderIndicator(0, targetp, &lead_target_pos);
4053 }
4054 
4055 //Backslash
4056 // A stripped-down version of the lead indicator, only shows primary weapons
4057 // and works for a specified target (not just the current selected target).
4058 // Ideally I'd like to later turn this into something (or make a new function) that would actually WORK with gun convergence/normals
4059 // instead of the existing code (copied from above) that does some calculations and then is ignored ;-)
4060 // (Go look, what's it actually DO with source_pos?)
4061 // And also, something that could be called for multiple weapons, ITTS style.
4062 void HudGaugeLeadIndicator::renderLeadQuick(vec3d *target_world_pos, object *targetp)
4063 {
4064  vec3d source_pos;
4065  vec3d *rel_pos;
4066  vec3d lead_target_pos;
4067  polymodel *pm;
4068  ship_weapon *swp;
4069  weapon_info *wip;
4070  float dist_to_target, prange;
4071  int bank_to_fire, frame_offset;
4072 
4073  if ( (targetp->type != OBJ_SHIP) && (targetp->type != OBJ_WEAPON) && (targetp->type != OBJ_ASTEROID) ) {
4074  return;
4075  }
4076 
4077  // only allow bombs to have lead indicator displayed
4078  if ( targetp->type == OBJ_WEAPON ) {
4081  return;
4082  }
4083  }
4084  }
4085 
4086  // If the target is out of range, then draw the correct frame for the lead indicator
4087  if ( Lead_indicator_gauge.first_frame == -1 ) {
4088  Int3();
4089  return;
4090  }
4091 
4092  pm = model_get(Ship_info[Player_ship->ship_info_index].model_num);
4093  swp = &Player_ship->weapons;
4094 
4095  // Added to take care of situation where there are no primary banks on the player ship
4096  // (this may not be possible, depending on what we decide for the weapons loadout rules)
4097  if ( swp->num_primary_banks == 0 )
4098  return;
4099 
4100  bank_to_fire = hud_get_best_primary_bank(&prange); //Backslash note: this!
4101  if ( bank_to_fire < 0 )
4102  return;
4103  wip = &Weapon_info[swp->primary_bank_weapons[bank_to_fire]];
4104 
4105  if (pm->n_guns && bank_to_fire != -1 ) {
4106  rel_pos = &pm->gun_banks[bank_to_fire].pnt[0];
4107  } else {
4108  rel_pos = NULL;
4109  }
4110 // vec3d firing_vec;
4111 // vm_vec_unrotate(&firing_vec, &po->gun_banks[bank_to_fire].norm[pt], &obj->orient);
4112 // vm_vector_2_matrix(&firing_orient, &firing_vec, NULL, NULL);
4113 
4114  // source_pos will contain the world coordinate of where to base the lead indicator prediction
4115  // from. Normally, this will be the world pos of the gun turret of the currently selected primary
4116  // weapon.
4117  source_pos = Player_obj->pos;
4118  if (rel_pos != NULL) {
4119  vec3d gun_point;
4120  vm_vec_unrotate(&gun_point, rel_pos, &Player_obj->orient);
4121  vm_vec_add2(&source_pos, &gun_point);
4122  }
4123 
4124  // Determine "accurate" distance to target. This is the distance from the player ship
4125  // to the closest point on the bounding box of the target
4126  dist_to_target = hud_find_target_distance(targetp, Player_obj);
4127 
4128  frame_offset = pickFrame(prange, -1.0f, dist_to_target);
4129  if ( frame_offset < 0 ) {
4130  return;
4131  }
4132 
4133  hud_calculate_lead_pos(&lead_target_pos, target_world_pos, targetp, wip, dist_to_target, rel_pos);
4134  renderIndicator(frame_offset, targetp, &lead_target_pos);
4135 }
4136 
4139 {
4140 }
4141 
4143 {
4145 
4146  if ( Lead_sight.first_frame < 0 ) {
4147  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
4148  } else {
4149  int w, h;
4150 
4152  Lead_sight_half[0] = fl2i(w * 0.5f);
4153  Lead_sight_half[1] = fl2i(h * 0.5f);
4154  }
4155 }
4156 
4157 void HudGaugeLeadSight::renderSight(int frame_offset, vec3d *target_pos, vec3d *lead_target_pos)
4158 {
4159  vertex target_vertex;
4160  float target_sx;
4161  float target_sy;
4162 
4163  vertex lead_target_vertex;
4164  float target_lead_sx;
4165  float target_lead_sy;
4166 
4167  // first see if the lead is on screen
4168  g3_rotate_vertex(&lead_target_vertex, lead_target_pos);
4169 
4170  if (lead_target_vertex.codes != 0)
4171  return;
4172 
4173  g3_project_vertex(&lead_target_vertex);
4174 
4175  if (lead_target_vertex.flags & PF_OVERFLOW)
4176  return;
4177 
4178  target_lead_sx = lead_target_vertex.screen.xyw.x;
4179  target_lead_sy = lead_target_vertex.screen.xyw.y;
4180 
4181  // now see if the target is on screen
4182  g3_rotate_vertex(&target_vertex, target_pos);
4183 
4184  if (target_vertex.codes != 0)
4185  return;
4186 
4187  g3_project_vertex(&target_vertex);
4188 
4189  if (target_vertex.flags & PF_OVERFLOW)
4190  return;
4191 
4192  target_sx = target_vertex.screen.xyw.x;
4193  target_sy = target_vertex.screen.xyw.y;
4194 
4195  // render the lead sight
4196  if ( Lead_sight.first_frame >= 0 ) {
4197 
4198  unsize(&target_lead_sx, &target_lead_sy);
4199  unsize(&target_sx, &target_sy);
4200 
4201  float reticle_target_sx = target_sx - Lead_sight_half[0] - target_lead_sx;
4202  float reticle_target_sy = target_sy - Lead_sight_half[1] - target_lead_sy;
4203 
4204  reticle_target_sx += position[0] + 0.5f;
4205  reticle_target_sy += position[1] + 0.5f;
4206 
4207  setGaugeColor();
4208  renderBitmap(Lead_sight.first_frame + frame_offset, fl2i(reticle_target_sx) + fl2i(HUD_offset_x), fl2i(reticle_target_sy) + fl2i(HUD_offset_y));
4209  }
4210 }
4211 
4213 {
4215 }
4216 
4217 void HudGaugeLeadSight::render(float frametime)
4218 {
4219  vec3d target_pos;
4220  vec3d source_pos;
4221  vec3d *rel_pos;
4222  vec3d lead_target_pos;
4223  object *targetp;
4224  polymodel *pm;
4225  ship_weapon *swp;
4226  weapon_info *wip;
4227  float dist_to_target, prange;
4228  int bank_to_fire;
4229 
4230  if (Player_ai->target_objnum == -1)
4231  return;
4232 
4233  targetp = &Objects[Player_ai->target_objnum];
4234  if ( (targetp->type != OBJ_SHIP) && (targetp->type != OBJ_WEAPON) && (targetp->type != OBJ_ASTEROID) ) {
4235  return;
4236  }
4237 
4238  // only allow bombs to have lead indicator displayed
4239  if ( targetp->type == OBJ_WEAPON ) {
4241  return;
4242  }
4243  }
4244 
4245  // If the target is out of range, then draw the correct frame for the lead indicator
4246  if ( Lead_sight.first_frame == -1 ) {
4247  Int3();
4248  return;
4249  }
4250 
4251  // AL 1/20/97: Point to targeted subsystem if one exists
4252  if ( Player_ai->targeted_subsys != NULL ) {
4253  get_subsystem_world_pos(targetp, Player_ai->targeted_subsys, &target_pos);
4254  } else {
4255  target_pos = targetp->pos;
4256  }
4257 
4258  pm = model_get(Ship_info[Player_ship->ship_info_index].model_num);
4259  swp = &Player_ship->weapons;
4260 
4261  // Added to take care of situation where there are no primary banks on the player ship
4262  // (this may not be possible, depending on what we decide for the weapons loadout rules)
4263  if ( swp->num_primary_banks == 0 )
4264  return;
4265 
4266  bank_to_fire = hud_get_best_primary_bank(&prange);
4267  if ( bank_to_fire < 0 )
4268  return;
4269  wip = &Weapon_info[swp->primary_bank_weapons[bank_to_fire]];
4270 
4271  if (pm->n_guns && bank_to_fire != -1 ) {
4272  rel_pos = &pm->gun_banks[bank_to_fire].pnt[0];
4273  } else {
4274  rel_pos = NULL;
4275  }
4276 
4277  // source_pos will contain the world coordinate of where to base the lead indicator prediction
4278  // from. Normally, this will be the world pos of the gun turret of the currently selected primary
4279  // weapon.
4280  source_pos = Player_obj->pos;
4281  if (rel_pos != NULL) {
4282  vec3d gun_point;
4283  vm_vec_unrotate(&gun_point, rel_pos, &Player_obj->orient);
4284  vm_vec_add2(&source_pos, &gun_point);
4285  }
4286 
4287  // Determine "accurate" distance to target. This is the distance from the player ship
4288  // to the closest point on the bounding box of the target
4289  dist_to_target = hud_find_target_distance(targetp, Player_obj);
4290 
4291  bool in_frame;
4292  if ( dist_to_target < prange ) {
4293  // fire it up
4294  in_frame = g3_in_frame() > 0;
4295  if(!in_frame) {
4296  g3_start_frame(0);
4297  }
4298 
4299  hud_calculate_lead_pos(&lead_target_pos, &target_pos, targetp, wip, dist_to_target);
4300  renderSight(1, &target_pos, &lead_target_pos); // render the primary weapon lead sight
4301 
4302  if(!in_frame) {
4303  g3_end_frame();
4304  }
4305  }
4306 
4307  //do dumbfire lead indicator - color is orange (255,128,0) - bright, (192,96,0) - dim
4308  //phreak changed 9/01/02
4309  if((swp->current_secondary_bank>=0) && (swp->secondary_bank_weapons[swp->current_secondary_bank] >= 0))
4310  {
4311  int bank=swp->current_secondary_bank;
4312  wip=&Weapon_info[swp->secondary_bank_weapons[bank]];
4313 
4314  //get out of here if the secondary weapon is a homer or if its out of range
4315  if ( wip->wi_flags & WIF_HOMING ) {
4316  return;
4317  }
4318 
4319  double max_dist = MIN((wip->lifetime * wip->max_speed), wip->weapon_range);
4320 
4321  if (dist_to_target > max_dist) {
4322  return;
4323  }
4324  } else {
4325  return;
4326  }
4327 
4328  // fire it up
4329  in_frame = g3_in_frame() > 0;
4330  if(!in_frame) {
4331  g3_start_frame(0);
4332  }
4333 
4334  //give it the "in secondary range frame
4335 
4336  hud_calculate_lead_pos(&lead_target_pos, &target_pos, targetp, wip, dist_to_target);
4337  renderSight(0, &target_pos, &lead_target_pos); // now render the secondary weapon lead sight
4338 
4339  if(!in_frame) {
4340  g3_end_frame();
4341  }
4342 }
4343 
4344 // hud_cease_subsystem_targeting() will cease targeting the current targets subsystems
4345 //
4346 void hud_cease_subsystem_targeting(int print_message)
4347 {
4348  int ship_index;
4349 
4350  ship_index = Objects[Player_ai->target_objnum].instance;
4351  if ( ship_index < 0 )
4352  return;
4353 
4354  Ships[ship_index].last_targeted_subobject[Player_num] = NULL;
4355  Player_ai->targeted_subsys = NULL;
4357  if ( print_message ) {
4358  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Deactivating sub-system targeting", 324));
4359  }
4360 
4362  hud_lock_reset();
4363 }
4364 
4365 // hud_cease_targeting() will cease all targeting (main target and subsystem)
4366 //
4368 {
4372  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Deactivating targeting system", 325));
4373  hud_lock_reset();
4374 }
4375 
4376 // hud_restore_subsystem_target() will remember the last targeted subsystem
4377 // on a target.
4378 //
4380 {
4381  // check if there was a previously targeted sub-system for this target
4382  if ( shipp->last_targeted_subobject[Player_num] != NULL ) {
4385  }
4386  else {
4387  Player_ai->targeted_subsys = NULL;
4389  }
4390 }
4391 
4392 // --------------------------------------------------------------------------------
4393 // get_subsystem_world_pos() returns the world position for a given subsystem on a ship
4394 //
4395 vec3d* get_subsystem_world_pos(object* parent_obj, ship_subsys* subsys, vec3d* world_pos)
4396 {
4397  get_subsystem_pos(world_pos, parent_obj, subsys);
4398 
4399  return world_pos;
4400 }
4401 
4402 // ----------------------------------------------------------------------------
4403 // hud_target_change_check()
4404 //
4405 // called once per frame to account for when the target changes
4406 //
4408 {
4409  float current_speed=0.0f;
4410 
4411  // Check if player subsystem target has changed, and reset necessary player flag
4413  Player->subsys_in_view=-1;
4414  }
4415 
4416  // check if the main target has changed
4418 
4419  if ( Player_ai->target_objnum != -1){
4421  }
4422 
4423  // if we have a hotkey set active, see if new target is in set. If not in
4424  // set, deselect the current hotkey set.
4425  if ( Player->current_hotkey_set != -1 ) {
4426  htarget_list *hitem, *plist;
4427 
4429  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
4430  if ( OBJ_INDEX(hitem->objp) == Player_ai->target_objnum ){
4431  break;
4432  }
4433  }
4434  if ( hitem == END_OF_LIST(plist) ){
4435  Player->current_hotkey_set = -1;
4436  }
4437  }
4438 
4440  if ( (Player_ai->target_objnum >= 0) && (Player_ai->target_objnum < MAX_OBJECTS) ) {
4442  }
4447  Player->locking_subsys=NULL;
4450 
4453 
4457  }
4458  else {
4460  Players[Player_num].flags &= ~PLAYER_FLAGS_MATCH_TARGET; // no more target matching.
4461  }
4462 
4463  hud_lock_reset();
4464 
4465  if ( (Player_ai->target_objnum >= 0) && (Player_ai->target_objnum < MAX_OBJECTS) ) {
4468  }
4469  }
4470  }
4471  else {
4476  } else {
4478  }
4479 
4480  if ( (Player_ai->target_objnum >= 0) && (Player_ai->target_objnum < MAX_OBJECTS) ) {
4481  current_speed = Objects[Player_ai->target_objnum].phys_info.speed;
4482  }
4483 
4484  if (current_speed < Player_ai->last_speed-0.01){
4486  } else if (current_speed > Player_ai->last_speed+0.01) {
4488  } else {
4490  }
4491 
4495  }
4496  }
4497  }
4498 
4500  Player_ai->last_speed = current_speed;
4501 
4504 }
4505 
4508 {
4509 }
4510 
4511 void HudGaugeTargetTriangle::render(float frametime)
4512 {
4513  if ( Player_ai->target_objnum == -1)
4514  return;
4515 
4516  bool in_frame = g3_in_frame() > 0;
4517  if(!in_frame)
4518  g3_start_frame(0);
4519 
4520  object *targetp = &Objects[Player_ai->target_objnum];
4521 
4522  // draw the targeting triangle that orbits the outside of the outer circle of the reticle
4523  if (!Player->target_is_dying && maybeFlashSexp() != 1) {
4524 
4525  hud_set_iff_color(targetp, 1);
4526  renderTriangle(&targetp->pos, 1, 0, 0);
4527  }
4528 
4529  if(!in_frame)
4530  g3_end_frame();
4531 }
4532 
4533 // start the weapon line (on the HUD) flashing
4535 {
4536  if ( index >= MAX_WEAPON_FLASH_LINES ) {
4537  Int3(); // Get Alan
4538  return;
4539  }
4540 
4541  if ( timestamp_elapsed(Weapon_flash_info.flash_duration[index]) ) {
4542  Weapon_flash_info.flash_next[index] = timestamp(TBOX_FLASH_INTERVAL);
4543  Weapon_flash_info.is_bright &= ~(1<<index);
4544  }
4545 
4546  Weapon_flash_info.flash_duration[index] = timestamp(TBOX_FLASH_DURATION);
4547 }
4548 
4549 // maybe change the text color for the weapon line indicated by index
4551 {
4552  if ( index >= MAX_WEAPON_FLASH_LINES ) {
4553  Int3(); // Get Alan
4554  return;
4555  }
4556 
4557  // hud_set_default_color();
4559  if ( !timestamp_elapsed(Weapon_flash_info.flash_duration[index]) ) {
4560  if ( timestamp_elapsed(Weapon_flash_info.flash_next[index]) ) {
4561  Weapon_flash_info.flash_next[index] = timestamp(TBOX_FLASH_INTERVAL);
4562  Weapon_flash_info.is_bright ^= (1<<index);
4563  }
4564 
4565  if ( Weapon_flash_info.is_bright & (1<<index) ) {
4567  // hud_set_bright_color();
4568  } else {
4570  // hud_set_dim_color();
4571  }
4572  }
4573 }
4574 
4578 int hud_sensors_ok(ship *sp, int show_msg)
4579 {
4580  float sensors_str;
4581 
4582  // If playing on lowest skill level, sensors don't affect targeting
4583  // If dead, still allow player to target, despite any subsystem damage
4584  // If i'm a multiplayer observer, allow me to target
4586  return 1;
4587  }
4588 
4589  // if the ship is currently being affected by EMP
4590  if(emp_active_local()){
4591  return 0;
4592  }
4593 
4594  // ensure targeting functions are not disabled through damage
4595  sensors_str = ship_get_subsystem_strength( sp, SUBSYSTEM_SENSORS );
4596  if ( (sensors_str < MIN_SENSOR_STR_TO_TARGET) || (ship_subsys_disrupted(sp, SUBSYSTEM_SENSORS)) ) {
4597  if ( show_msg ) {
4598  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Targeting is disabled due to sensors damage", 330));
4600  }
4601  return 0;
4602  } else {
4603  return 1;
4604  }
4605 }
4606 
4608 {
4609  float str;
4610 
4611  // If playing on the lowest skill level, communications always ok
4612  // If dead, still allow player to communicate, despite any subsystem damage
4613  if ( Game_skill_level == 0 || (Game_mode & GM_DEAD) ) {
4614  return COMM_OK;
4615  }
4616 
4617  // Goober5000 - if the ship is the player, and he's dying, return OK (so laments can be played)
4618  if ((sp == Player_ship) && (sp->flags & SF_DYING))
4619  return COMM_OK;
4620 
4621  // Goober5000 - check for scrambled communications
4623  return COMM_SCRAMBLED;
4624 
4626 
4627  if ( (str <= 0.01) || ship_subsys_disrupted(sp, SUBSYSTEM_COMMUNICATION) ) {
4628  return COMM_DESTROYED;
4629  } else if ( str < MIN_COMM_STR_TO_MESSAGE ) {
4630  return COMM_DAMAGED;
4631  }
4632 
4633  return COMM_OK;
4634 }
4635 
4636 // target the next or previous hostile/friendly ship
4637 void hud_target_next_list(int hostile, int next_flag, int team_mask, int attacked_objnum, int play_fail_snd, int filter, int get_closest_turret_attacking_player)
4638 {
4639  int timestamp_val, valid_team_mask;
4640 
4641  if ( hostile ) {
4642  timestamp_val = Tl_hostile_reset_timestamp;
4643  Tl_hostile_reset_timestamp = timestamp(TL_RESET);
4644  if ( team_mask == -1 ) {
4645  valid_team_mask = iff_get_attackee_mask(Player_ship->team);
4646  } else {
4647  valid_team_mask = team_mask;
4648  }
4649  } else {
4650  // everyone hates a traitor including other traitors so the friendly target option shouldn't work for them
4651  if (Player_ship->team == Iff_traitor) {
4652  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
4653  return;
4654  }
4655 
4656  timestamp_val = Tl_friendly_reset_timestamp;
4657  Tl_friendly_reset_timestamp = timestamp(TL_RESET);
4658  valid_team_mask = iff_get_mask(Player_ship->team);
4659  }
4660 
4661  // If no target is selected, then simply target the closest ship
4662  if ( Player_ai->target_objnum == -1 || timestamp_elapsed(timestamp_val) ) {
4663  hud_target_closest(valid_team_mask, attacked_objnum, play_fail_snd, filter, get_closest_turret_attacking_player);
4664  return;
4665  }
4666 
4667  object *nearest_object = select_next_target_by_distance((next_flag != 0), valid_team_mask, attacked_objnum);
4668 
4669  if (nearest_object != NULL) {
4670  // set new target
4671  set_target_objnum( Player_ai, OBJ_INDEX(nearest_object) );
4672  hud_shield_hit_reset(nearest_object);
4673 
4674  // maybe set new turret subsystem
4676  hud_restore_subsystem_target(&Ships[nearest_object->instance]);
4677  }
4678  else {
4679  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
4680  }
4681 }
4682 
4685 {
4686 }
4687 
4689 {
4690  Auto_text_offsets[0] = x;
4691  Auto_text_offsets[1] = y;
4692 }
4693 
4695 {
4696  Target_text_offsets[0] = x;
4697  Target_text_offsets[1] = y;
4698 }
4699 
4701 {
4703  if ( Toggle_frame.first_frame < 0 ) {
4704  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
4705  }
4706 }
4707 
4708 void HudGaugeAutoTarget::initOnColor(int r, int g, int b, int a)
4709 {
4710  if ( r == -1 || g == -1 || b == -1 || a == -1 ) {
4711  Use_on_color = false;
4712  gr_init_alphacolor(&On_color, 0, 0, 0, 0);
4713  return;
4714  }
4715 
4716  Use_on_color = true;
4717  gr_init_alphacolor(&On_color, r, g, b, a);
4718 }
4719 
4720 void HudGaugeAutoTarget::initOffColor(int r, int g, int b, int a)
4721 {
4722  if ( r == -1 || g == -1 || b == -1 || a == -1 ) {
4723  Use_off_color = false;
4724  gr_init_alphacolor(&Off_color, 0, 0, 0, 0);
4725  return;
4726  }
4727 
4728  Use_off_color = true;
4729  gr_init_alphacolor(&Off_color, r, g, b, a);
4730 }
4731 
4732 void HudGaugeAutoTarget::render(float frametime)
4733 {
4735  return;
4736 
4737  int frame_offset;
4738 
4740  frame_offset = 1;
4741  } else {
4742  frame_offset = 0;
4743  }
4744 
4745  // draw the box background
4746  setGaugeColor();
4747  renderBitmap(Toggle_frame.first_frame+frame_offset, position[0], position[1]);
4748 
4749  // draw the text on top
4750  if (frame_offset == 1) {
4751  //static color text_color;
4752  //gr_init_alphacolor(&text_color, 0, 0, 0, Toggle_text_alpha);
4753  if ( Use_on_color ) {
4755  }
4756  } else if ( Use_off_color ) {
4758  }
4759 
4760  renderString(position[0] + Auto_text_offsets[0], position[1] + Auto_text_offsets[1], XSTR("auto", 1463));
4761  renderString(position[0] + Target_text_offsets[0], position[1] + Target_text_offsets[1], XSTR("target", 1465));
4762 }
4763 
4765 {
4767 }
4768 
4771 {
4772 }
4773 
4775 {
4776  Auto_text_offsets[0] = x;
4777  Auto_text_offsets[1] = y;
4778 }
4779 
4781 {
4782  Speed_text_offsets[0] = x;
4783  Speed_text_offsets[1] = y;
4784 }
4785 
4787 {
4789  if ( Toggle_frame.first_frame < 0 ) {
4790  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
4791  }
4792 }
4793 
4794 void HudGaugeAutoSpeed::initOnColor(int r, int g, int b, int a)
4795 {
4796  if ( r == -1 || g == -1 || b == -1 || a == -1 ) {
4797  Use_on_color = false;
4798  gr_init_alphacolor(&On_color, 0, 0, 0, 0);
4799  return;
4800  }
4801 
4802  Use_on_color = true;
4803  gr_init_alphacolor(&On_color, r, g, b, a);
4804 }
4805 
4806 void HudGaugeAutoSpeed::initOffColor(int r, int g, int b, int a)
4807 {
4808  if ( r == -1 || g == -1 || b == -1 || a == -1 ) {
4809  Use_off_color = false;
4810  gr_init_alphacolor(&Off_color, 0, 0, 0, 0);
4811  return;
4812  }
4813 
4814  Use_off_color = true;
4815  gr_init_alphacolor(&Off_color, r, g, b, a);
4816 }
4817 
4818 void HudGaugeAutoSpeed::render(float frametime)
4819 {
4821  return;
4822 
4823  int frame_offset;
4824 
4826  frame_offset = 3;
4827  } else {
4828  frame_offset = 2;
4829  }
4830 
4831  setGaugeColor();
4832 
4833  renderBitmap(Toggle_frame.first_frame+frame_offset, position[0], position[1]);
4834 
4835  // draw the text on top
4836  if (frame_offset == 3) {
4837  //static color text_color;
4838  //gr_init_alphacolor(&text_color, 0, 0, 0, Toggle_text_alpha);
4839  if ( Use_on_color ) {
4841  }
4842  } else if ( Use_off_color ) {
4844  }
4845  renderString(position[0] + Auto_text_offsets[0], position[1] + Auto_text_offsets[1], XSTR("auto", 1463));
4846  renderString(position[0] + Speed_text_offsets[0], position[1] + Speed_text_offsets[1], XSTR("speed", 1464));
4847 }
4848 
4850 {
4852 }
4853 
4854 // Set the player target to the closest friendly repair ship
4855 // input: goal_objnum => Try to find repair ship where aip->goal_objnum matches this
4856 // output: 1 => A repair ship was targeted
4857 // 0 => No targeting change
4859 {
4860  object *A;
4861  object *nearest_obj=&obj_used_list;
4862  ship *shipp;
4863  ship_obj *so;
4864  float min_distance=1e20f;
4865  float new_distance=0.0f;
4866  int rval=0;
4867 
4868  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
4869  A = &Objects[so->objnum];
4870  shipp = &Ships[A->instance]; // get a pointer to the ship information
4871 
4872  // ignore all ships that aren't repair ships
4873  if ( !(Ship_info[shipp->ship_info_index].flags & SIF_SUPPORT) ) {
4874  continue;
4875  }
4876 
4877  if ( (A == Player_obj) || (shipp->flags & TARGET_SHIP_IGNORE_FLAGS) )
4878  continue;
4879 
4880  // only consider friendly ships
4881  if ( !(Player_ship->team == shipp->team)) {
4882  continue;
4883  }
4884 
4885  if(hud_target_invalid_awacs(A)){
4886  continue;
4887  }
4888 
4889  if ( goal_objnum >= 0 ) {
4890  if ( Ai_info[shipp->ai_index].goal_objnum != goal_objnum ) {
4891  continue;
4892  }
4893  }
4894 
4895  new_distance = hud_find_target_distance(A,Player_obj);
4896 
4897  if (new_distance <= min_distance) {
4898  min_distance=new_distance;
4899  nearest_obj = A;
4900  }
4901  }
4902 
4903  if (nearest_obj != &obj_used_list) {
4904  set_target_objnum( Player_ai, OBJ_INDEX(nearest_obj) );
4905  hud_shield_hit_reset(nearest_obj);
4907  rval=1;
4908  }
4909  else {
4910  // inform player how to get a support ship
4911  if ( goal_objnum == -1 ) {
4912  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "No support ships in area. Use messaging to call one in.", 332));
4913  }
4914  rval=0;
4915  }
4916 
4917  return rval;
4918 }
4919 
4921 {
4923  TARGET_SHIP_IGNORE_FLAGS &= ~SF_HIDDEN_FROM_SENSORS;
4924  HUD_sourced_printf(HUD_SOURCE_HIDDEN, NOX("Target hiding from sensors disabled"));
4925  } else {
4927  HUD_sourced_printf(HUD_SOURCE_HIDDEN, NOX("Target hiding from sensors enabled"));
4928  }
4929 }
4930 
4931 // target the closest uninspected object
4933 {
4934  object *A, *nearest_obj = NULL;
4935  ship *shipp;
4936  ship_obj *so;
4937  float min_distance = 1e20f;
4938  float new_distance = 0.0f;
4939 
4940  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
4941 
4942  A = &Objects[so->objnum];
4943  shipp = &Ships[A->instance]; // get a pointer to the ship information
4944 
4945  if ( (A == Player_obj) || (shipp->flags & TARGET_SHIP_IGNORE_FLAGS) ){
4946  continue;
4947  }
4948 
4949  if(hud_target_invalid_awacs(A)){
4950  continue;
4951  }
4952 
4953  // ignore all non-cargo carrying craft
4954  if ( !hud_target_ship_can_be_scanned(shipp) ) {
4955  continue;
4956  }
4957 
4958  new_distance = hud_find_target_distance(A,Player_obj);
4959 
4960  if (new_distance <= min_distance) {
4961  min_distance=new_distance;
4962  nearest_obj = A;
4963  }
4964  }
4965 
4966  if (nearest_obj != NULL) {
4967  set_target_objnum( Player_ai, OBJ_INDEX(nearest_obj) );
4968  hud_shield_hit_reset(nearest_obj);
4970  }
4971  else {
4973  }
4974 }
4975 
4976 // target the next or previous uninspected/unscanned object
4978 {
4979  object *A, *min_obj, *max_obj, *nearest_obj;
4980  ship *shipp;
4981  ship_obj *so;
4982  float cur_dist, min_dist, max_dist, new_dist, nearest_dist, diff;
4983 
4984  // If no target is selected, then simply target the closest uninspected cargo
4985  if ( Player_ai->target_objnum == -1 || timestamp_elapsed(Target_next_uninspected_object_timestamp) ) {
4986  Target_next_uninspected_object_timestamp = timestamp(TL_RESET);
4988  return;
4989  }
4990 
4991  Target_next_uninspected_object_timestamp = timestamp(TL_RESET);
4992 
4994 
4995  min_obj = max_obj = nearest_obj = NULL;
4996  min_dist = 1e20f;
4997  max_dist = 0.0f;
4998  if ( next_flag ) {
4999  nearest_dist = 1e20f;
5000  } else {
5001  nearest_dist = 0.0f;
5002  }
5003 
5004  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
5005  A = &Objects[so->objnum];
5006  shipp = &Ships[A->instance]; // get a pointer to the ship information
5007 
5008  if ( (A == Player_obj) || (shipp->flags & TARGET_SHIP_IGNORE_FLAGS) )
5009  continue;
5010 
5011  // ignore all non-cargo carrying craft
5012  if ( !hud_target_ship_can_be_scanned(shipp) ) {
5013  continue;
5014  }
5015 
5016  // don't use object if it is already a target
5017  if ( OBJ_INDEX(A) == Player_ai->target_objnum ) {
5018  continue;
5019  }
5020 
5021  if(hud_target_invalid_awacs(A)){
5022  continue;
5023  }
5024 
5025  new_dist = hud_find_target_distance(A, Player_obj);
5026 
5027  if (new_dist <= min_dist) {
5028  min_dist = new_dist;
5029  min_obj = A;
5030  }
5031 
5032  if (new_dist >= max_dist) {
5033  max_dist = new_dist;
5034  max_obj = A;
5035  }
5036 
5037  if ( next_flag ) {
5038  diff = new_dist - cur_dist;
5039  if ( diff > 0 ) {
5040  if ( diff < ( nearest_dist - cur_dist ) ) {
5041  nearest_dist = new_dist;
5042  nearest_obj = A;
5043  }
5044  }
5045  } else {
5046  diff = cur_dist - new_dist;
5047  if ( diff > 0 ) {
5048  if ( diff < ( cur_dist - nearest_dist ) ) {
5049  nearest_dist = new_dist;
5050  nearest_obj = A;
5051  }
5052  }
5053  }
5054  }
5055 
5056  if ( nearest_obj == NULL ) {
5057 
5058  if ( next_flag ) {
5059  if ( min_obj != NULL ) {
5060  nearest_obj = min_obj;
5061  }
5062  } else {
5063  if ( max_obj != NULL ) {
5064  nearest_obj = max_obj;
5065  }
5066  }
5067  }
5068 
5069  if (nearest_obj != NULL) {
5070  set_target_objnum( Player_ai, OBJ_INDEX(nearest_obj) );
5071  hud_shield_hit_reset(nearest_obj);
5073  }
5074  else {
5076  }
5077 }
5078 
5079 // ----------------------------------------------------------------
5080 //
5081 // Target Last Transmission Sender code START
5082 //
5083 // ----------------------------------------------------------------
5084 
5085 typedef struct transmit_target
5086 {
5087  int objnum;
5088  int objsig;
5089 } transmit_target;
5090 
5091 static int Transmit_target_next_slot = 0;
5092 static int Transmit_target_current_slot = -1;
5093 static int Transmit_target_reset_timer = timestamp(0);
5094 
5095 #define MAX_TRANSMIT_TARGETS 10
5096 static transmit_target Transmit_target_list[MAX_TRANSMIT_TARGETS];
5097 
5098 // called once per level to initialize the target last transmission sender list
5100 {
5101  int i;
5102 
5103  for ( i = 0; i < MAX_TRANSMIT_TARGETS; i++ ) {
5104  Transmit_target_list[i].objnum = -1;
5105  Transmit_target_list[i].objsig = -1;
5106  }
5107 
5108  Transmit_target_next_slot = 0;
5109  Transmit_target_current_slot = 0;
5110  Transmit_target_reset_timer = timestamp(0);
5111 }
5112 
5113 // internal function only.. used to find index for last recorded ship transmission
5115 {
5116  int latest_slot;
5117 
5118  latest_slot = Transmit_target_next_slot - 1;
5119  if ( latest_slot < 0 ) {
5120  latest_slot = MAX_TRANSMIT_TARGETS - 1;
5121  }
5122 
5123  return latest_slot;
5124 }
5125 
5126 // called externally to set the player target to the last ship which sent a transmission to the player
5128 {
5129  int i;
5130 
5131  if ( Transmit_target_current_slot < 0 ) {
5132  Transmit_target_current_slot = hud_target_last_transmit_newest();
5133  }
5134 
5135  // If timed out, then simply target the last ship to transmit
5136  if ( timestamp_elapsed(Transmit_target_reset_timer) ) {
5137  Transmit_target_current_slot = hud_target_last_transmit_newest();
5138  }
5139 
5140  Transmit_target_reset_timer = timestamp(TL_RESET);
5141 
5142  int play_fail_sound = 1;
5143  int transmit_index = Transmit_target_current_slot;
5144  Assert(transmit_index >= 0);
5145  for ( i = 0; i < MAX_TRANSMIT_TARGETS; i++ ) {
5146  if ( Transmit_target_list[transmit_index].objnum >= 0 ) {
5147  int transmit_objnum = Transmit_target_list[transmit_index].objnum;
5148 
5149  if ( Player_ai->target_objnum == transmit_objnum ) {
5150  play_fail_sound = 0;
5151  } else {
5152  if ( Transmit_target_list[transmit_index].objsig == Objects[Transmit_target_list[transmit_index].objnum].signature ) {
5153  if ( !(Ships[Objects[transmit_objnum].instance].flags & TARGET_SHIP_IGNORE_FLAGS) ) {
5154  Transmit_target_current_slot = transmit_index-1;
5155  if ( Transmit_target_current_slot < 0 ) {
5156  Transmit_target_current_slot = MAX_TRANSMIT_TARGETS - 1;
5157  }
5158  break;
5159  }
5160  }
5161  }
5162  }
5163 
5164  transmit_index--;
5165  if ( transmit_index < 0 ) {
5166  transmit_index = MAX_TRANSMIT_TARGETS - 1;
5167  }
5168  }
5169 
5170  if ( i == MAX_TRANSMIT_TARGETS ) {
5171  if ( play_fail_sound ) {
5173  }
5174  Transmit_target_current_slot = -1;
5175  return;
5176  }
5177 
5178  if(hud_target_invalid_awacs(&Objects[Transmit_target_list[transmit_index].objnum])){
5179  return;
5180  }
5181 
5182  // target new ship!
5183  // Fix bug in targeting due to Alt-Y (target last ship sending transmission).
5184  // Was just bogus code in the call to hud_restore_subsystem_target(). -- MK, 9/15/99, 1:59 pm.
5185  int targeted_objnum;
5186  targeted_objnum = Transmit_target_list[transmit_index].objnum;
5187  Assert((targeted_objnum >= 0) && (targeted_objnum < MAX_OBJECTS));
5188 
5189  if ((targeted_objnum >= 0) && (targeted_objnum < MAX_OBJECTS)) {
5190  set_target_objnum( Player_ai, Transmit_target_list[transmit_index].objnum );
5191  hud_shield_hit_reset(&Objects[Transmit_target_list[transmit_index].objnum]);
5192  hud_restore_subsystem_target(&Ships[Objects[Transmit_target_list[transmit_index].objnum].instance]);
5193  }
5194 }
5195 
5196 // called externally to add a message sender to the list
5198 {
5199  object *ship_objp;
5200  int ship_objnum;
5201 
5202  ship_objnum = Ships[ship_num].objnum;
5203  Assert(ship_objnum >= 0 && ship_objnum < MAX_OBJECTS);
5204  ship_objp = &Objects[ship_objnum];
5205  Assert(ship_objp->type == OBJ_SHIP);
5206 
5207  // don't add ourselves to the list
5208  if (Player_obj == ship_objp) {
5209  return;
5210  }
5211 
5212  Transmit_target_list[Transmit_target_next_slot].objnum = ship_objnum;
5213  Transmit_target_list[Transmit_target_next_slot].objsig = ship_objp->signature;
5214  Transmit_target_next_slot++;
5215  if ( Transmit_target_next_slot >= MAX_TRANSMIT_TARGETS ) {
5216  Transmit_target_next_slot = 0;
5217  }
5218 }
5219 
5220 // target a random ship (useful for EMP stuff)
5222 {
5223  int shipnum;
5224  int objnum;
5225 
5226  shipnum = ship_get_random_targetable_ship();
5227  if((shipnum < 0) || (Ships[shipnum].objnum < 0)){
5228  return;
5229  }
5230  objnum = Ships[shipnum].objnum;
5231 
5232  if((objnum >= 0) && (Player_ai != NULL) && !hud_target_invalid_awacs(&Objects[objnum])){
5233  // never target yourself
5234  if(objnum == OBJ_INDEX(Player_obj)){
5236  } else {
5237  set_target_objnum(Player_ai, objnum);
5238  hud_shield_hit_reset(&Objects[objnum]);
5239  }
5240  }
5241 }
5242 
5243 // ----------------------------------------------------------------
5244 //
5245 // Target Last Transmission Sender code END
5246 //
5247 // ----------------------------------------------------------------
5248 
5250 {
5251  int i;
5252 
5253  for ( i = 0; i < NUM_WEAPON_GAUGES; i++ ) {
5254  bm_page_in_aabitmap( Weapon_gauges[ballistic_hud_index][i].first_frame, Weapon_gauges[ballistic_hud_index][i].num_frames);
5255  }
5256  bm_page_in_aabitmap( New_weapon.first_frame, New_weapon.num_frames );
5257 
5258  weapon_info* wip;
5259  for(i = 0; i < Num_weapon_types; i++)
5260  {
5261  wip = &Weapon_info[i];
5262  if(strlen(wip->hud_filename))
5263  {
5264  wip->hud_image_index = bm_load(wip->hud_filename);
5265  }
5266  }
5267 }
5268 
5269 void hud_stuff_ship_name(char *ship_name_text, ship *shipp)
5270 {
5271  // print ship name
5272  if ( ((Iff_info[shipp->team].flags & IFFF_WING_NAME_HIDDEN) && (shipp->wingnum != -1)) || (shipp->flags2 & SF2_HIDE_SHIP_NAME) ) {
5273  *ship_name_text = 0;
5274  } else {
5275  strcpy(ship_name_text, shipp->ship_name);
5276 
5277  // handle hash symbol
5278  end_string_at_first_hash_symbol(ship_name_text);
5279 
5280  // handle translation
5281  if (Lcl_gr) {
5282  lcl_translate_targetbox_name_gr(ship_name_text);
5283  } else if (Lcl_pl) {
5284  lcl_translate_targetbox_name_pl(ship_name_text);
5285  }
5286  }
5287 }
5288 
5289 extern char Fred_callsigns[MAX_SHIPS][NAME_LENGTH+1];
5290 void hud_stuff_ship_callsign(char *ship_callsign_text, ship *shipp)
5291 {
5292  // handle multiplayer callsign
5293  if (Game_mode & GM_MULTIPLAYER) {
5294  // get a player num from the object, then get a callsign from the player structure.
5295  int pn = multi_find_player_by_object( &Objects[shipp->objnum] );
5296 
5297  if (pn >= 0) {
5298  strcpy(ship_callsign_text, Net_players[pn].m_player->short_callsign);
5299  return;
5300  }
5301  }
5302 
5303  // try to get callsign
5304  if (Fred_running) {
5305  strcpy(ship_callsign_text, Fred_callsigns[shipp-Ships]);
5306  } else {
5307  *ship_callsign_text = 0;
5308  if (shipp->callsign_index >= 0) {
5309  mission_parse_lookup_callsign_index(shipp->callsign_index, ship_callsign_text);
5310  }
5311  }
5312 
5313  // handle hash symbol
5314  end_string_at_first_hash_symbol(ship_callsign_text);
5315 
5316  // handle translation
5317  if (Lcl_gr) {
5318  lcl_translate_targetbox_name_gr(ship_callsign_text);
5319  } else if (Lcl_pl) {
5320  lcl_translate_targetbox_name_pl(ship_callsign_text);
5321  }
5322 }
5323 
5324 extern char Fred_alt_names[MAX_SHIPS][NAME_LENGTH+1];
5325 void hud_stuff_ship_class(char *ship_class_text, ship *shipp)
5326 {
5327  // try to get alt name
5328  if (Fred_running) {
5329  strcpy(ship_class_text, Fred_alt_names[shipp-Ships]);
5330  } else {
5331  *ship_class_text = 0;
5332  if (shipp->alt_type_index >= 0) {
5333  mission_parse_lookup_alt_index(shipp->alt_type_index, ship_class_text);
5334  }
5335  }
5336 
5337  // maybe get ship class
5338  if (!*ship_class_text) {
5339  strcpy(ship_class_text, (Ship_info[shipp->ship_info_index].alt_name[0]) ? Ship_info[shipp->ship_info_index].alt_name : Ship_info[shipp->ship_info_index].name);
5340  }
5341 
5342  // handle hash symbol
5343  end_string_at_first_hash_symbol(ship_class_text);
5344 
5345  // handle translation
5346  if (Lcl_gr) {
5347  lcl_translate_targetbox_name_gr(ship_class_text);
5348  } else if (Lcl_pl) {
5349  lcl_translate_targetbox_name_pl(ship_class_text);
5350  }
5351 }
5352 
5355 {
5356 }
5357 
5359 {
5360  Cm_text_offsets[0] = x;
5361  Cm_text_offsets[1] = y;
5362 }
5363 
5365 {
5366  Cm_text_val_offsets[0] = x;
5367  Cm_text_val_offsets[1] = y;
5368 }
5369 
5371 {
5372  Cmeasure_gauge.first_frame = bm_load_animation(fname, &Cmeasure_gauge.num_frames);
5373  if ( Cmeasure_gauge.first_frame < 0 ) {
5374  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5375  }
5376 }
5377 
5379 {
5380  bm_page_in_aabitmap(Cmeasure_gauge.first_frame, Cmeasure_gauge.num_frames);
5381 }
5382 
5383 void HudGaugeCmeasures::render(float frametime)
5384 {
5385  if ( Cmeasure_gauge.first_frame == -1) {
5386  Int3(); // failed to load coutermeasure gauge background
5387  return;
5388  }
5389 
5391  if(sip->cmeasure_max < 0 || sip->cmeasure_type < 0){
5392  return;
5393  }
5394 
5395  // hud_set_default_color();
5396  setGaugeColor();
5397 
5398  // blit the background
5399  renderBitmap(Cmeasure_gauge.first_frame, position[0], position[1]);
5400 
5401  // blit text
5402  renderString(position[0] + Cm_text_offsets[0], position[1] + Cm_text_offsets[1], XSTR( "cm.", 327));
5403  if ( !Player_ship ) {
5404  Int3(); // player ship doesn't exist?
5405  return;
5406  }
5408 }
5409 
5412 {
5413 }
5414 
5416 {
5417  Energy_h = h;
5418 }
5419 
5421 {
5423 
5424  if ( Energy_bar.first_frame < 0 ) {
5425  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5426  }
5427 }
5428 
5429 // Render the HUD afterburner energy gauge
5430 void HudGaugeAfterburner::render(float frametime)
5431 {
5432  float percent_left;
5433  int clip_h,w,h;
5434 
5435  if ( Energy_bar.first_frame == -1 ){
5436  return;
5437  }
5438 
5441  // Goober5000 - instead of drawing an empty burner gauge, don't draw the gauge at all
5442  return;
5443  } else {
5444  percent_left = Player_ship->afterburner_fuel/Ship_info[Player_ship->ship_info_index].afterburner_fuel_capacity;
5445  }
5446 
5447  if ( percent_left > 1 ) {
5448  percent_left = 1.0f;
5449  }
5450 
5451  clip_h = fl2i( (1.0f - percent_left) * Energy_h + 0.5f );
5452 
5454 
5455  setGaugeColor();
5456 
5457  if ( clip_h > 0) {
5458  renderBitmapEx(Energy_bar.first_frame, position[0], position[1],w,clip_h,0,0);
5459  }
5460 
5461  if ( clip_h <= Energy_h ) {
5462  renderBitmapEx(Energy_bar.first_frame+1, position[0], position[1] + clip_h,w,h-clip_h,0,clip_h);
5463  }
5464 }
5465 
5467 {
5469 }
5470 
5473 {
5474 }
5475 
5477 {
5478  Wenergy_text_offsets[0] = x;
5479  Wenergy_text_offsets[1] = y;
5480 }
5481 
5483 {
5484  Wenergy_h = h;
5485 }
5486 
5487 void HudGaugeWeaponEnergy::initAlignments(int text_align, int armed_align)
5488 {
5489  Text_alignment = text_align;
5490  Armed_alignment = armed_align;
5491 }
5492 
5493 void HudGaugeWeaponEnergy::initArmedOffsets(int x, int y, int h, bool show)
5494 {
5495  Armed_name_offsets[0] = x;
5496  Armed_name_offsets[1] = y;
5497  Show_armed = show;
5498  Armed_name_h = h;
5499 }
5500 
5502 {
5503  Always_show_text = show_text;
5504 }
5505 
5507 {
5508  Moving_text = move_text;
5509 }
5510 
5512 {
5513  Show_ballistic = show_ballistics;
5514 }
5515 
5517 {
5519  if ( Energy_bar.first_frame < 0 ) {
5520  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5521  }
5522 }
5523 
5525 {
5527 }
5528 
5529 void HudGaugeWeaponEnergy::render(float frametime)
5530 {
5531  int x;
5532  bool use_new_gauge = false;
5533 
5534  // Goober5000 - only check for the new gauge in case of command line + a ballistic-capable ship
5536  {
5537  for(x = 0; x < Player_ship->weapons.num_primary_banks; x++)
5538  {
5540  {
5541  use_new_gauge = true;
5542  break;
5543  }
5544  }
5545  }
5546 
5547  if(use_new_gauge)
5548  {
5549  int currentx, currenty, line_height;
5550  int y;
5551  int max_w = 100;
5552  float remaining;
5553  currentx = position[0] + 10;
5554  currenty = position[1];
5555  line_height = gr_get_font_height() + 1;
5556  if(gr_screen.max_w_unscaled == 640) {
5557  max_w = 60;
5558  }
5559 
5560  //*****ENERGY GAUGE
5563 
5564  //Draw name
5565  renderString(currentx, currenty, "Energy");
5566  currenty += line_height;
5567 
5568  //Draw background
5570  renderRect(currentx, currenty, max_w, 10);
5571 
5572  //Draw gauge bar
5574  remaining = max_w * ((float)Player_ship->weapon_energy/(float)Ship_info[Player_ship->ship_info_index].max_weapon_reserve);
5575  if(remaining > 0)
5576  {
5578  for(y = 0; y < 10; y++) {
5579  renderGradientLine(currentx, currenty + y, currentx + fl2i(remaining), currenty + y);
5580  }
5581  }
5582  currenty += 12;
5583 
5584  char shortened_name[NAME_LENGTH];
5585  //*****BALLISTIC GAUGES
5586  for(x = 0; x < Player_ship->weapons.num_primary_banks; x++)
5587  {
5588  //Skip all pure-energy weapons
5590  continue;
5591 
5592  //Draw the weapon bright or normal depending if it's active or not.
5595  } else {
5597  }
5598  if(gr_screen.max_w_unscaled == 640) {
5599  gr_force_fit_string(shortened_name, NAME_LENGTH, 55);
5600  renderString(currentx, currenty, shortened_name);
5601  } else {
5603  }
5604 
5605  //Next 'line'
5606  currenty += line_height;
5607 
5608  //Draw the background for the gauge
5610  renderRect(currentx, currenty, max_w, 10);
5611 
5612  //Reset to normal brightness
5614 
5615  //Draw the bar graph
5616  remaining = (max_w - 4) * ((float) Player_ship->weapons.primary_bank_ammo[x] / (float) Player_ship->weapons.primary_bank_start_ammo[x]);
5617  if(remaining > 0) {
5618  renderRect(currentx + 2, currenty + 2, fl2i(remaining), 6);
5619  }
5620  //Increment for next 'line'
5621  currenty += 12;
5622  }
5623  }
5624  else
5625  {
5626  float percent_left;
5627  int ballistic_ammo = 0;
5628  int max_ballistic_ammo = 0;
5629  int clip_h, w, h, i;
5630  weapon_info *wip;
5631  ship_weapon *sw;
5632  char buf[40] = "";
5633 
5634  if ( Energy_bar.first_frame == -1 ) {
5635  return;
5636  }
5637 
5638  if ( Player_ship->weapons.num_primary_banks <= 0 ) {
5639  return;
5640  }
5641 
5642  sw = &Player_ship->weapons;
5643 
5644  // show ballistic ammunition in energy gauge if need be
5645  if ( Show_ballistic && Ship_info[Player_ship->ship_info_index].flags & SIF_BALLISTIC_PRIMARIES ) {
5646  if ( Player_ship->flags & SF_PRIMARY_LINKED ) {
5647 
5648  // go through all ballistic primaries and add up their ammunition totals and max capacities
5649  for ( i = 0; i < sw->num_primary_banks; i++ ) {
5650 
5651  // skip all pure-energy weapons
5653  continue;
5654  }
5655 
5656  ballistic_ammo += sw->primary_bank_ammo[i];
5657  max_ballistic_ammo += sw->primary_bank_start_ammo[i];
5658  }
5659  } else {
5660  ballistic_ammo = sw->primary_bank_ammo[sw->current_primary_bank];
5661  max_ballistic_ammo = sw->primary_bank_start_ammo[sw->current_primary_bank];
5662  }
5663 
5664  percent_left = i2fl(ballistic_ammo) / i2fl(max_ballistic_ammo);
5665  } else {
5666  // also leave if no energy can be stored for weapons - Goober5000
5668  return;
5669 
5670  percent_left = Player_ship->weapon_energy/Ship_info[Player_ship->ship_info_index].max_weapon_reserve;
5671  if ( percent_left > 1 )
5672  {
5673  percent_left = 1.0f;
5674  }
5675  }
5676 
5677  clip_h = fl2i( (1.0f - percent_left) * Wenergy_h + 0.5f );
5678 
5679  if ( percent_left <= 0.3 || Show_ballistic || Always_show_text ) {
5680  int delta_y = 0, delta_x = 0;
5681 
5682  if ( percent_left < 0.1 ) {
5684  } else {
5685  setGaugeColor();
5686  }
5687 
5688  if ( Show_ballistic ) {
5689  sprintf(buf, "%d", ballistic_ammo);
5690  } else {
5691  sprintf(buf,XSTR( "%d%%", 326), fl2i(percent_left*100+0.5f));
5692  }
5693 
5694  if ( Moving_text ) {
5695  delta_y = clip_h;
5696  }
5697 
5699 
5700  if ( Text_alignment ) {
5701  gr_get_string_size(&w, &h, buf);
5702  delta_x = -w;
5703  }
5704 
5705  renderString(position[0] + Wenergy_text_offsets[0] + delta_x, position[1] + Wenergy_text_offsets[1] + delta_y, buf);
5706  }
5707 
5708  setGaugeColor();
5709 
5710  // list currently armed primary banks if we have to
5711  if ( Show_armed ) {
5712  if ( Player_ship->flags & SF_PRIMARY_LINKED ) {
5713  // show all primary banks
5714  for ( i = 0; i < Player_ship->weapons.num_primary_banks; i++ ) {
5715  wip = &Weapon_info[sw->primary_bank_weapons[i]];
5716  strcpy_s(buf, (wip->alt_name[0]) ? wip->alt_name : wip->name);
5717 
5718  if ( Armed_alignment ) {
5719  gr_get_string_size(&w, &h, buf);
5720  } else {
5721  w = 0;
5722  }
5723 
5725  }
5726  } else {
5727  // just show the current armed bank
5729  wip = &Weapon_info[sw->primary_bank_weapons[i]];
5730  strcpy_s(buf, (wip->alt_name[0]) ? wip->alt_name : wip->name);
5731 
5732  if ( Armed_alignment ) {
5733  gr_get_string_size(&w, &h, buf);
5734  } else {
5735  w = 0;
5736  }
5737 
5739  }
5740  }
5741 
5742  for ( i = 0; i < sw->num_primary_banks; i++ )
5743  {
5744  if ( !timestamp_elapsed(Weapon_flash_info.flash_duration[i]) )
5745  {
5746  if ( Weapon_flash_info.is_bright & (1<<i) )
5747  {
5748  // hud_set_bright_color();
5750  break;
5751  }
5752  }
5753  }
5754 
5756 
5757  if ( clip_h > 0 ) {
5758  renderBitmapEx(Energy_bar.first_frame+2, position[0], position[1], w,clip_h,0,0);
5759  }
5760 
5761  if ( clip_h <= Wenergy_h ) {
5762  renderBitmapEx(Energy_bar.first_frame+3, position[0], position[1] + clip_h, w,h-clip_h,0,clip_h);
5763  }
5764 
5765  // hud_set_default_color();
5766  }
5767 }
5768 
5771 {
5772 }
5773 
5775 {
5777  // default to a '>' if the font has no special chars
5778  // seems about the closest normal char to the triangle
5779  if (sc == 0) {
5780  Weapon_link_icon = ubyte ('>');
5781  } else {
5782  Weapon_link_icon = sc + 2;
5783  }
5784 }
5785 
5787 {
5788  top_offset_x[0] = x;
5789  top_offset_x[1] = x_b;
5790 }
5791 
5792 void HudGaugeWeapons::initHeaderOffsets(int x, int y, int x_b, int y_b)
5793 {
5794  Weapon_header_offsets[0][0] = x;
5795  Weapon_header_offsets[0][1] = y;
5796  Weapon_header_offsets[1][0] = x_b;
5797  Weapon_header_offsets[1][1] = y_b;
5798 }
5799 
5801 {
5802  frame_offset_x[0] = x;
5803  frame_offset_x[1] = x_b;
5804 }
5805 
5806 void HudGaugeWeapons::initPrimaryWeaponOffsets(int link_x, int name_x, int ammo_x)
5807 {
5808  Weapon_plink_offset_x = link_x;
5809  Weapon_pname_offset_x = name_x;
5810  Weapon_pammo_offset_x = ammo_x;
5811 }
5812 
5813 void HudGaugeWeapons::initSecondaryWeaponOffsets(int ammo_x, int name_x, int reload_x, int linked_x, int unlinked_x)
5814 {
5815  Weapon_sammo_offset_x = ammo_x;
5816  Weapon_sname_offset_x = name_x;
5817  Weapon_sreload_offset_x = reload_x;
5818  Weapon_slinked_offset_x = linked_x;
5819  Weapon_sunlinked_offset_x = unlinked_x;
5820 }
5821 
5823 {
5824  pname_start_offset_y = p_y;
5825  sname_start_offset_y = s_y;
5826 }
5827 
5828 void HudGaugeWeapons::initPrimaryHeights(int top_h, int text_h)
5829 {
5830  top_primary_h = top_h;
5831  primary_text_h = text_h;
5832 }
5833 
5834 void HudGaugeWeapons::initSecondaryHeights(int top_h, int text_h)
5835 {
5836  top_secondary_h = top_h;
5837  secondary_text_h = text_h;
5838 }
5839 
5840 void HudGaugeWeapons::initBitmapsPrimaryTop(char *fname, char *fname_ballistic)
5841 {
5842  // load the graphics for the top portion of the weapons gauge
5843  primary_top[0].first_frame = bm_load_animation(fname, &primary_top[0].num_frames);
5844  if(primary_top[0].first_frame < 0) {
5845  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5846  }
5847 
5848  primary_top[1].first_frame = bm_load_animation(fname_ballistic, &primary_top[1].num_frames);
5849  if(primary_top[1].first_frame < 0) {
5852  }
5853 }
5854 
5855 void HudGaugeWeapons::initBitmapsPrimaryMiddle(char *fname, char *fname_ballistic)
5856 {
5857  // load the graphics for the middle portion of the primary weapons listing
5858  primary_middle[0].first_frame = bm_load_animation(fname, &primary_middle[0].num_frames);
5859  if(primary_middle[0].first_frame < 0) {
5860  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5861  }
5862 
5863  primary_middle[1].first_frame = bm_load_animation(fname_ballistic, &primary_middle[1].num_frames);
5864  if(primary_middle[1].first_frame < 0) {
5867  }
5868 }
5869 
5870 void HudGaugeWeapons::initBitmapsPrimaryLast(char *fname, char *fname_ballistic)
5871 {
5872  // load the graphics for the bottom portion of the primary weapons listing if there is one.
5873  // Don't bother the user if there isn't one since retail doesn't use this.
5874  primary_last[0].first_frame = bm_load_animation(fname, &primary_last[0].num_frames);
5875 
5876  primary_last[1].first_frame = bm_load_animation(fname_ballistic, &primary_last[1].num_frames);
5877  if(primary_last[1].first_frame < 0) {
5880  }
5881 }
5882 
5883 void HudGaugeWeapons::initBitmapsSecondaryTop(char *fname, char *fname_ballistic)
5884 {
5885  // top portion of the secondary weapons gauge
5886  secondary_top[0].first_frame = bm_load_animation(fname, &secondary_top[0].num_frames);
5887  if(secondary_top[0].first_frame < 0) {
5888  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5889  }
5890 
5891  secondary_top[1].first_frame = bm_load_animation(fname_ballistic, &secondary_top[1].num_frames);
5892  if(secondary_top[1].first_frame < 0) {
5895  }
5896 }
5897 
5898 void HudGaugeWeapons::initBitmapsSecondaryMiddle(char *fname, char *fname_ballistic)
5899 {
5900  // middle portion of the secondary weapons gauge
5901  secondary_middle[0].first_frame = bm_load_animation(fname, &secondary_middle[0].num_frames);
5902  if(secondary_middle[0].first_frame < 0) {
5903  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5904  }
5905 
5906  secondary_middle[1].first_frame = bm_load_animation(fname_ballistic, &secondary_middle[1].num_frames);
5907  if(secondary_middle[1].first_frame < 0) {
5910  }
5911 }
5912 
5913 void HudGaugeWeapons::initBitmapsSecondaryBottom(char *fname, char *fname_ballistic)
5914 {
5915  // bottom portion of the entire weapons gauge
5916  secondary_bottom[0].first_frame = bm_load_animation(fname, &secondary_bottom[0].num_frames);
5917  if(secondary_bottom[0].first_frame < 0) {
5918  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
5919  }
5920 
5921  secondary_bottom[1].first_frame = bm_load_animation(fname_ballistic, &secondary_bottom[1].num_frames);
5922  if(secondary_bottom[1].first_frame < 0) {
5925  }
5926 }
5927 
5929 {
5930  if(primary_top[0].first_frame > -1) {
5931  bm_page_in_aabitmap(primary_top[0].first_frame,primary_top[0].num_frames);
5932  }
5933 
5934  if(primary_top[1].first_frame > -1) {
5935  bm_page_in_aabitmap(primary_top[1].first_frame,primary_top[1].num_frames);
5936  }
5937 
5938  if(primary_middle[0].first_frame > -1) {
5939  bm_page_in_aabitmap(primary_middle[0].first_frame,primary_middle[0].num_frames);
5940  }
5941 
5942  if(primary_middle[1].first_frame > -1) {
5943  bm_page_in_aabitmap(primary_middle[1].first_frame, primary_middle[1].num_frames);
5944  }
5945 
5946  if(primary_last[1].first_frame > -1) {
5947  bm_page_in_aabitmap(primary_last[1].first_frame, primary_last[1].num_frames);
5948  }
5949 
5950  if(secondary_top[0].first_frame > -1) {
5951  bm_page_in_aabitmap(secondary_top[0].first_frame, secondary_top[0].num_frames);
5952  }
5953 
5954  if(secondary_top[1].first_frame > -1) {
5955  bm_page_in_aabitmap(secondary_top[1].first_frame, secondary_top[1].num_frames);
5956  }
5957 
5958  if(secondary_middle[0].first_frame > -1) {
5959  bm_page_in_aabitmap(secondary_middle[0].first_frame, secondary_middle[0].num_frames);
5960  }
5961 
5962  if(secondary_middle[1].first_frame >-1) {
5963  bm_page_in_aabitmap(secondary_middle[0].first_frame, secondary_middle[0].num_frames);
5964  }
5965 
5966  if(secondary_bottom[0].first_frame > -1) {
5967  bm_page_in_aabitmap(secondary_bottom[0].first_frame, secondary_bottom[0].num_frames);
5968  }
5969 
5970  if(secondary_bottom[1].first_frame > -1) {
5971  bm_page_in_aabitmap(secondary_bottom[0].first_frame, secondary_bottom[0].num_frames);
5972  }
5973 }
5974 
5975 void HudGaugeWeapons::render(float frametime)
5976 {
5977  ship_weapon *sw;
5978  int np, ns; // np == num primary, ns == num secondary
5979  char name[NAME_LENGTH];
5980 
5981  if(Player_obj->type == OBJ_OBSERVER)
5982  return;
5983 
5986 
5987  sw = &Ships[Player_obj->instance].weapons;
5988  np = sw->num_primary_banks;
5989  ns = sw->num_secondary_banks;
5990 
5991  setGaugeColor();
5992 
5993  // draw top of primary display
5994  renderBitmap(primary_top[ballistic_hud_index].first_frame, position[0] + top_offset_x[ballistic_hud_index], position[1]);
5995 
5996  // render the header of this gauge
5997  renderString(position[0] + Weapon_header_offsets[ballistic_hud_index][0], position[1] + Weapon_header_offsets[ballistic_hud_index][1], EG_WEAPON_TITLE, XSTR( "weapons", 328));
5998 
5999  char ammo_str[32];
6000  int i, w, h;
6001  int y = position[1] + top_primary_h;
6002  int name_y = position[1] + pname_start_offset_y;
6003 
6004  // render primaries
6005  for(i = 0; i < np; i++) {
6006  setGaugeColor();
6007 
6008  // choose which background to draw for additional primaries.
6009  // Note, we don't draw a background for the first primary.
6010  // It is assumed that the top primary wep frame already has this rendered.
6011  if(i == 1) {
6012  // used to draw the second primary weapon background
6013  renderBitmap(primary_middle[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
6014  } else if(i != 0) {
6015  // used to draw the the third, fourth, fifth, etc...
6016  if(primary_last[ballistic_hud_index].first_frame != -1)
6017  renderBitmap(primary_last[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
6018  }
6019 
6021  if (Lcl_gr) {
6023  }
6024 
6025  // maybe modify name here to fit
6026 
6027  // do we need to flash the text?
6028  if (HudGauge::maybeFlashSexp() == i ) {
6030  } else {
6031  maybeFlashWeapon(i);
6032  }
6033 
6034  // indicate if this is linked or currently armed
6037  }
6038 
6039  // either render this primary's image or its name
6042  } else {
6043  renderPrintf(position[0] + Weapon_pname_offset_x, name_y, EG_WEAPON_P2, "%s", name);
6044  }
6045 
6046  // if this is a ballistic primary with ammo, render the ammo count
6048  // print out the ammo right justified
6049  sprintf(ammo_str, "%d", sw->primary_bank_ammo[i]);
6050 
6051  // get rid of #
6053 
6054  hud_num_make_mono(ammo_str, font_num);
6055  gr_get_string_size(&w, &h, ammo_str);
6056 
6057  renderString(position[0] + Weapon_pammo_offset_x - w, name_y, EG_NULL, ammo_str);
6058  }
6059 
6060  if(i != 0) {
6061  y += primary_text_h;
6062  }
6063  name_y += primary_text_h;
6064  }
6065 
6066  weapon_info *wip;
6067  char weapon_name[NAME_LENGTH + 10];
6068 
6069  if ( HudGauge::maybeFlashSexp() == i ) {
6071  }
6072 
6073  renderBitmap(secondary_top[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
6074  name_y = y + sname_start_offset_y;
6075  y += top_secondary_h;
6076 
6077  for(i = 0; i < ns; i++)
6078  {
6079  setGaugeColor();
6080  wip = &Weapon_info[sw->secondary_bank_weapons[i]];
6081 
6082  if(i!=0) {
6083  renderBitmap(secondary_middle[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
6084  }
6085 
6086  maybeFlashWeapon(np+i);
6087 
6088  // HACK - make Cluster Bomb fit on the HUD.
6089  if(!stricmp(wip->name,"cluster bomb")){
6090  strcpy_s(weapon_name, NOX("Cluster"));
6091  } else {
6092  strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
6093  }
6094 
6095  // get rid of #
6096  end_string_at_first_hash_symbol(weapon_name);
6097 
6098  if ( sw->current_secondary_bank == i ) {
6099  // show that this is the current secondary armed
6101 
6102  // indicate if this is linked
6105  }
6106 
6107  // show secondary weapon's image or print its name
6108  if(wip->hud_image_index != -1) {
6110  } else {
6111  renderString(position[0] + Weapon_sname_offset_x, name_y, i ? EG_WEAPON_S1 : EG_WEAPON_S2, weapon_name);
6112  }
6113 
6114  // show the cooldown time
6115  if ( (sw->secondary_bank_ammo[i] > 0) && (sw->current_secondary_bank >= 0) ) {
6117  if ( (ms_till_fire >= 500) && ((wip->fire_wait >= 1 ) || (ms_till_fire > wip->fire_wait*1000)) ) {
6118  renderPrintf(position[0] + Weapon_sreload_offset_x, name_y, EG_NULL, "%d", fl2i(ms_till_fire/1000.0f +0.5f));
6119  }
6120  }
6121  } else {
6122  // just print the weapon's name since this isn't armed
6123  renderString(position[0] + Weapon_sname_offset_x, name_y, i ? EG_WEAPON_S1 : EG_WEAPON_S2, weapon_name);
6124  }
6125 
6126  int ammo=sw->secondary_bank_ammo[i];
6127 
6128  // print out the ammo right justified
6129  sprintf(ammo_str, "%d", ammo);
6130  hud_num_make_mono(ammo_str, font_num);
6131  gr_get_string_size(&w, &h, ammo_str);
6132 
6133  renderString(position[0] + Weapon_sammo_offset_x - w, name_y, EG_NULL, ammo_str);
6134 
6135  if(i != 0) {
6136  y += secondary_text_h;
6137  }
6138  name_y += secondary_text_h;
6139  }
6140 
6141  // a bit lonely here with no secondaries so just print "<none>"
6142  if(ns==0)
6143  {
6144  renderString(position[0] + Weapon_pname_offset_x, name_y, EG_WEAPON_S1, XSTR( "<none>", 329));
6145  }
6146 
6147  y -= 0;
6148  // finish drawing the background
6149  renderBitmap(secondary_bottom[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
6150 }
6151 
6153 {
6154  ship_weapon *sw;
6155  int num_weapons;
6156 
6157  sw = &Ships[Player_obj->instance].weapons;
6158  num_weapons = sw->num_primary_banks + sw->num_secondary_banks;
6159 
6160  if ( num_weapons > MAX_WEAPON_FLASH_LINES ) {
6161  Int3(); // Get Alan
6162  return;
6163  }
6164 
6165  for(int i = 0; i < num_weapons; i++) {
6166  if ( !timestamp_elapsed(Weapon_flash_info.flash_duration[i]) ) {
6167  if ( timestamp_elapsed(Weapon_flash_info.flash_next[i]) ) {
6168  Weapon_flash_info.flash_next[i] = timestamp(TBOX_FLASH_INTERVAL);
6169  Weapon_flash_info.is_bright ^= (1<<i);
6170  }
6171  }
6172  }
6173 }
6174 
6176 {
6177  if ( index >= MAX_WEAPON_FLASH_LINES ) {
6178  Int3(); // Get Alan
6179  return;
6180  }
6181 
6182  // hud_set_default_color();
6183  setGaugeColor();
6184  if ( !timestamp_elapsed(Weapon_flash_info.flash_duration[index]) ) {
6185  if ( Weapon_flash_info.is_bright & (1<<index) ) {
6187  // hud_set_bright_color();
6188  } else {
6190  // hud_set_dim_color();
6191  }
6192  }
6193 }
6194 
6195 void hud_target_add_display_list(object *objp, vertex *target_point, vec3d *target_pos, int correction, color *bracket_clr, char* name, int flags)
6196 {
6197  target_display_info element;
6198 
6199  element.objp = objp;
6200  element.target_point = *target_point;
6201  element.target_pos = *target_pos;
6202  element.correction = correction;
6203  element.flags = flags;
6204 
6205  if(bracket_clr) {
6206  element.bracket_clr = *bracket_clr;
6207  } else {
6208  // no color given, so this will tell the target display gauges to use IFF colors.
6209  gr_init_color(&element.bracket_clr, 0, 0, 0);
6210  }
6211 
6212  if(name) {
6213  strcpy_s(element.name, name);
6214  } else {
6215  strcpy_s(element.name, "");
6216  }
6217 
6218  target_display_list.push_back(element);
6219 }
6220 
6222 {
6223  target_display_list.clear();
6224 }
6225 
6228 {
6229 }
6230 
6232 {
6234 }
6235 
6237 {
6239 }
6240 
6242 {
6244 }
6245 
6247 {
6249 }
6250 
6252 {
6253 }
6254 
6255 void HudGaugeOffscreen::render(float frametime)
6256 {
6257  // don't show offscreen indicator if we're warping out.
6258  if ( Player->control_mode != PCM_NORMAL ) {
6259  return;
6260  }
6261 
6262  for(size_t i = 0; i < target_display_list.size(); i++) {
6263  if(target_display_list[i].target_point.codes != 0) {
6264  float dist = 0.0f;
6265  vec2d coords;
6266  float half_triangle_sep;
6267  int dir;
6268 
6269  if(target_display_list[i].objp) {
6270  dist = hud_find_target_distance( target_display_list[i].objp, Player_obj );
6271  } else {
6272  // if we don't have a corresponding object, use given position to figure out distance
6273  dist = vm_vec_dist_quick(&Player_obj->pos, &target_display_list[i].target_pos);
6274  }
6275 
6276  if( target_display_list[i].bracket_clr.red && target_display_list[i].bracket_clr.green &&
6277  target_display_list[i].bracket_clr.blue ) {
6278  gr_set_color_fast(&target_display_list[i].bracket_clr);
6279  } else {
6280  // use IFF colors if none defined.
6281  if(target_display_list[i].objp) {
6282  hud_set_iff_color(target_display_list[i].objp, 1);
6283  } else {
6284  // no object so this must mean it's a nav point. but for some odd reason someone forgot to include a color.
6285  gr_set_color_fast(&target_display_list[i].bracket_clr);
6286  }
6287  }
6288 
6289  calculatePosition(&target_display_list[i].target_point, &target_display_list[i].target_pos, &coords, &dir, &half_triangle_sep);
6290  renderOffscreenIndicator(&coords, dir, dist, half_triangle_sep, true);
6291  }
6292  }
6293 }
6294 
6295 void HudGaugeOffscreen::calculatePosition(vertex* target_point, vec3d *tpos, vec2d *outcoords, int *dir, float *half_triangle_sep)
6296 {
6297  float xpos,ypos;
6298  vec3d targ_to_player;
6299  float dist_behind;
6300  float triangle_sep;
6301  float half_gauge_length;
6302 
6303  bool in_frame = g3_in_frame() > 0;
6304  if(!in_frame)
6305  g3_start_frame(0);
6307 
6308  // calculate the dot product between the players forward vector and the vector connecting
6309  // the player to the target. Normalize targ_to_player since we want the dot product
6310  // to range between 0 -> 1.
6311  vm_vec_sub(&targ_to_player, &Player_obj->pos, tpos);
6312  vm_vec_normalize(&targ_to_player);
6313  dist_behind = vm_vec_dot(&Player_obj->orient.vec.fvec, &targ_to_player);
6314 
6315  if (dist_behind < 0) { // still in front of player, but not in view
6316  dist_behind = dist_behind + 1.0f;
6317  if (dist_behind > 0.2 ){
6318  triangle_sep = ( dist_behind ) * Max_front_seperation;
6319  } else {
6320  triangle_sep = 0.0f;
6321  }
6322  } else {
6323  triangle_sep = dist_behind * Max_offscreen_tri_seperation + Max_offscreen_tri_seperation;
6324  }
6325 
6326  if ( triangle_sep > Max_offscreen_tri_seperation + Max_front_seperation){
6328  }
6329 
6330  // calculate these values only once, since it will be used in several places
6331  *half_triangle_sep = 0.5f * triangle_sep;
6332  half_gauge_length = *half_triangle_sep + Offscreen_tri_base;
6333 
6334  // We need to find the screen (x,y) for where to draw the offscreen indicator
6335  //
6336  // The best way I've found is to draw a line from the eye_pos to the target, and
6337  // then use clip_line() to find the screen (x,y) for where the line hits the edge
6338  // of the screen.
6339  //
6340  // The weird thing about clip_line() is that is flips around the two verticies,
6341  // so I use eye_vertex->sx and eye_vertex->sy for the off-screen indicator (x,y)
6342  //
6343  vertex *eye_vertex = NULL;
6344  vertex real_eye_vertex;
6345  eye_vertex = &real_eye_vertex; // this is needed since clip line takes a **vertex
6346  vec3d eye_pos;
6347  vm_vec_add( &eye_pos, &Eye_position, &View_matrix.vec.fvec);
6348  g3_rotate_vertex(eye_vertex, &eye_pos);
6349 
6350  ubyte codes_or;
6351  codes_or = (ubyte)(target_point->codes | eye_vertex->codes);
6352  clip_line(&target_point,&eye_vertex,codes_or,0);
6353 
6354  if (!(target_point->flags&PF_PROJECTED))
6355  g3_project_vertex(target_point);
6356 
6357  if (!(eye_vertex->flags&PF_PROJECTED))
6358  g3_project_vertex(eye_vertex);
6359 
6360  if (eye_vertex->flags&PF_OVERFLOW) {
6361  Int3(); // This is unlikely to happen, but can if a clip goes through the player's eye.
6362  Player_ai->target_objnum = -1;
6363  return;
6364  }
6365 
6366  if (target_point->flags & PF_TEMP_POINT)
6367  free_temp_point(target_point);
6368 
6369  if (eye_vertex->flags & PF_TEMP_POINT)
6370  free_temp_point(eye_vertex);
6371 
6372  xpos = eye_vertex->screen.xyw.x;
6373  ypos = eye_vertex->screen.xyw.y;
6374 
6375  // we need it unsized here and it will be fixed when things are acutally drawn
6376  gr_unsize_screen_posf(&xpos, &ypos);
6377 
6378  xpos = (xpos<1) ? 0 : xpos;
6379  ypos = (ypos<1) ? 0 : ypos;
6380 
6381  if ( xpos >= gr_screen.clip_right_unscaled) {
6383  *dir = 0;
6384 
6385  if ( ypos < (half_gauge_length - gr_screen.clip_top_unscaled) )
6386  ypos = half_gauge_length;
6387 
6388  if ( ypos > (gr_screen.clip_bottom_unscaled - half_gauge_length) )
6389  ypos = gr_screen.clip_bottom_unscaled - half_gauge_length;
6390 
6391  } else if ( xpos <= gr_screen.clip_left_unscaled ) {
6393  *dir = 1;
6394 
6395  if ( ypos < (half_gauge_length - gr_screen.clip_top_unscaled) )
6396  ypos = half_gauge_length;
6397 
6398  if ( ypos > (gr_screen.clip_bottom_unscaled - half_gauge_length) )
6399  ypos = gr_screen.clip_bottom_unscaled - half_gauge_length;
6400 
6401  } else if ( ypos <= gr_screen.clip_top_unscaled ) {
6403  *dir = 2;
6404 
6405  if ( xpos < ( half_gauge_length - gr_screen.clip_left_unscaled) )
6406  xpos = half_gauge_length;
6407 
6408  if ( xpos > (gr_screen.clip_right_unscaled - half_gauge_length) )
6409  xpos = gr_screen.clip_right_unscaled - half_gauge_length;
6410 
6411  } else if ( ypos >= gr_screen.clip_bottom_unscaled ) {
6413  *dir = 3;
6414 
6415  if ( xpos < ( half_gauge_length - gr_screen.clip_left_unscaled) )
6416  xpos = half_gauge_length;
6417 
6418  if ( xpos > (gr_screen.clip_right_unscaled - half_gauge_length) )
6419  xpos = gr_screen.clip_right_unscaled - half_gauge_length;
6420 
6421  } else {
6422  Int3();
6423  return;
6424  }
6425 
6426  // The offscreen target triangles are drawn according the the diagram below
6427  //
6428  //
6429  //
6430  // x3 x3
6431  // / | | \.
6432  // / | | \.
6433  // x1____x2 x2____x1
6434  // | |
6435  // .......|................|............(xpos,ypos)
6436  // | |
6437  // x4____x5 x5____x4
6438  // \ | | /
6439  // \ | | /
6440  // x6 x6
6441  //
6442  //
6443 
6444  xpos = (float)floor(xpos);
6445  ypos = (float)floor(ypos);
6446 
6447  if (outcoords != NULL) {
6448  outcoords->x = xpos;
6449  outcoords->y = ypos;
6450  }
6451 
6453 
6454  if(!in_frame)
6455  g3_end_frame();
6456 }
6457 
6458 void HudGaugeOffscreen::renderOffscreenIndicator(vec2d *coords, int dir, float distance, float half_triangle_sep, bool draw_solid)
6459 {
6460  float xpos, ypos;
6461  float displayed_distance;
6462  char buf[32];
6463  int w = 0, h = 0;
6464 
6465  // points to draw triangles
6466  float x1=0.0f;
6467  float y1=0.0f;
6468  float x2=0.0f;
6469  float y2=0.0f;
6470  float x3=0.0f;
6471  float y3=0.0f;
6472  float x4=0.0f;
6473  float y4=0.0f;
6474  float x5=0.0f;
6475  float y5=0.0f;
6476  float x6=0.0f;
6477  float y6=0.0f;
6478 
6479  // scale by distance modifier from hud_guages.tbl for display purposes
6480  displayed_distance = distance * Hud_unit_multiplier;
6481 
6482  bool in_frame = g3_in_frame() > 0;
6483  if(!in_frame)
6484  g3_start_frame(0);
6485 
6487 
6488  if (displayed_distance > 0.0f) {
6489  sprintf(buf, "%d", fl2i(displayed_distance + 0.5f));
6491  gr_get_string_size(&w, &h, buf);
6492  } else {
6493  buf[0] = 0;
6494  }
6495 
6496  xpos = coords->x;
6497  ypos = coords->y;
6498 
6499  if (dir == 0) {
6500  x1 = x4 = (xpos+2);
6501 
6502  x2 = x3 = x5 = x6 = x1 - Offscreen_tri_height;
6503  y1 = y2 = ypos - half_triangle_sep;
6504  y3 = y2 - Offscreen_tri_base;
6505 
6506  y4 = y5 = ypos + half_triangle_sep;
6507  y6 = y5 + Offscreen_tri_base;
6508 
6509  if ( buf[0] ) {
6510  gr_string( fl2i(xpos - w - 10), fl2i(ypos - h/2.0f+0.5f), buf);
6511  }
6512  } else if (dir == 1) {
6513  x1 = x4 = (xpos-1);
6514 
6515  x2 = x3 = x5 = x6 = x1 + Offscreen_tri_height;
6516  y1 = y2 = ypos - half_triangle_sep;
6517  y3 = y2 - Offscreen_tri_base;
6518 
6519  y4 = y5 = ypos + half_triangle_sep;
6520  y6 = y5 + Offscreen_tri_base;
6521 
6522  if ( buf[0] ) {
6523  gr_string(fl2i(xpos + 10), fl2i(ypos - h/2.0f+0.5f), buf);
6524  }
6525  } else if (dir == 2) {
6526  y1 = y4 = (ypos-1);
6527 
6528  y2 = y3 = y5 = y6 = y1 + Offscreen_tri_height;
6529  x1 = x2 = xpos - half_triangle_sep;
6530  x3 = x2 - Offscreen_tri_base;
6531 
6532  x4 = x5 = xpos + half_triangle_sep;
6533  x6 = x5 + Offscreen_tri_base;
6534 
6535  if ( buf[0] ) {
6536  gr_string(fl2i(xpos - w/2.0f+0.5f), fl2i(ypos+10), buf);
6537  }
6538  } else if (dir == 3) {
6539  y1 = y4 = (ypos+2);
6540 
6541  y2 = y3 = y5 = y6 = y1 - Offscreen_tri_height;
6542  x1 = x2 = xpos - half_triangle_sep;
6543  x3 = x2 - Offscreen_tri_base;
6544 
6545  x4 = x5 = xpos + half_triangle_sep;
6546  x6 = x5 + Offscreen_tri_base;
6547 
6548  if ( buf[0] ) {
6549  gr_string(fl2i(xpos - w/2.0f+0.5f), fl2i(ypos-h-10), buf);
6550  }
6551  }
6552 
6553  if (draw_solid) {
6554  hud_tri(x3,y3,x2,y2,x1,y1);
6555  hud_tri(x4,y4,x5,y5,x6,y6);
6556  } else {
6557  hud_tri_empty(x3,y3,x2,y2,x1,y1);
6558  hud_tri_empty(x4,y4,x5,y5,x6,y6);
6559  }
6560 
6561  if (dir == 0 || dir == 3){
6562  gr_line(fl2i(x2),fl2i(y2),fl2i(x5),fl2i(y5));
6563  } else if (dir == 1) {
6564  gr_line(fl2i(x2-1),fl2i(y2),fl2i(x5-1),fl2i(y5));
6565  } else {
6566  gr_line(fl2i(x2),fl2i(y2-1),fl2i(x5),fl2i(y5-1));
6567  }
6568 
6570 
6571  if(!in_frame)
6572  g3_end_frame();
6573 }
6574 
6577 {
6578 }
6579 
6581 {
6582  Warhead.first_frame = bm_load_animation(fname, &Warhead.num_frames);
6583 
6584  if ( Warhead.first_frame < 0 ) {
6585  Warning(LOCATION,"Cannot load hud ani: %s\n", fname);
6586  }
6587 }
6588 
6590 {
6591  Warhead_name_offsets[0] = x;
6592  Warhead_name_offsets[1] = y;
6593 }
6594 
6596 {
6597  Warhead_count_offsets[0] = x;
6598  Warhead_count_offsets[1] = y;
6599 }
6600 
6602 {
6603  Warhead_count_size[0] = w;
6604  Warhead_count_size[1] = h;
6605 }
6606 
6608 {
6609  Max_symbols = count;
6610 }
6611 
6613 {
6614  Max_columns = count;
6615 }
6616 
6618 {
6619  Text_align = align;
6620 }
6621 
6623 {
6624  bm_page_in_aabitmap(Warhead.first_frame, Warhead.num_frames);
6625 }
6626 
6627 void HudGaugeWarheadCount::render(float frametime)
6628 {
6629  if(Player_obj->type == OBJ_OBSERVER) {
6630  return;
6631  }
6632 
6635 
6637 
6638  // don't bother displaying anything if we have no secondaries
6639  if ( sw->num_secondary_banks <= 0 ) {
6640  return;
6641  }
6642 
6643  int wep_num = sw->current_secondary_bank;
6644  weapon_info *wip = &Weapon_info[sw->secondary_bank_weapons[wep_num]];
6645  int ammo = sw->secondary_bank_ammo[wep_num];
6646 
6647  // don't bother displaying anything if we have no ammo.
6648  if ( ammo <= 0 ) {
6649  return;
6650  }
6651 
6652  char weapon_name[NAME_LENGTH + 10];
6653  strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
6654  end_string_at_first_hash_symbol(weapon_name);
6655 
6656  setGaugeColor();
6657 
6658  // display the weapon name
6659  if ( Text_align ) {
6660  int w, h;
6661 
6662  gr_get_string_size(&w, &h, weapon_name);
6663  renderString(position[0] + Warhead_name_offsets[0] - w, position[1] + Warhead_name_offsets[1], weapon_name);
6664  } else {
6665  renderString(position[0] + Warhead_name_offsets[0], position[1] + Warhead_name_offsets[1], weapon_name);
6666  }
6667 
6669 
6670  // if ammo is greater than the icon display limit, just show a numeric
6671  if ( ammo > Max_symbols ) {
6672  char ammo_str[32];
6673 
6674  sprintf(ammo_str, "%d", ammo);
6675  hud_num_make_mono(ammo_str, font_num);
6676 
6677  if ( Text_align ) {
6678  int w, h;
6679 
6680  gr_get_string_size(&w, &h, ammo_str);
6681  renderString(position[0] + Warhead_count_offsets[0] - w, position[1] + Warhead_count_offsets[1], ammo_str);
6682  } else {
6683  renderString(position[0] + Warhead_count_offsets[0], position[1] + Warhead_count_offsets[1], ammo_str);
6684  }
6685 
6686  return;
6687  }
6688 
6689  int delta_x = 0, delta_y = 0;
6690  if ( Text_align ) {
6691  delta_x = -Warhead_count_size[0];
6692  } else {
6693  delta_x = Warhead_count_size[0];
6694  }
6695 
6696  int i, column;
6697  for ( i = 0; i < ammo; i++ ) {
6698  if ( Max_columns > 0 ) {
6699  delta_y = Warhead_count_size[1] * (i / Max_columns);
6700  column = i % Max_columns;
6701  } else {
6702  column = i;
6703  }
6704 
6705  renderBitmap(Warhead.first_frame, position[0] + Warhead_count_offsets[0] + column * delta_x, position[1] + Warhead_count_offsets[1] + delta_y);
6706  }
6707 }
6708 
6711 {
6712 
6713 }
6714 
6717  // default to a '>' if the font has no special chars
6718  // seems about the closest normal char to the triangle
6719  if (sc == 0) {
6720  Weapon_link_icon = ubyte ('>');
6721  } else {
6722  Weapon_link_icon = sc + 2;
6723  }
6724 }
6725 
6726 void HudGaugeWeaponList::initBitmaps(char *fname_first, char *fname_entry, char *fname_last)
6727 {
6729  if(_background_first.first_frame < 0) {
6730  Warning(LOCATION,"Cannot load hud ani: %s\n", fname_first);
6731  }
6732 
6734  if(_background_entry.first_frame < 0) {
6735  Warning(LOCATION,"Cannot load hud ani: %s\n", fname_entry);
6736  }
6737 
6739  if(_background_last.first_frame < 0) {
6740  Warning(LOCATION,"Cannot load hud ani: %s\n", fname_last);
6741  }
6742 }
6743 
6745 {
6747 }
6748 
6750 {
6752 }
6753 
6755 {
6756  _bg_last_offset_x = x;
6757 }
6758 
6760 {
6761  _bg_last_offset_y = y;
6762 }
6763 
6765 {
6767 }
6768 
6770 {
6772 }
6773 
6775 {
6776  strcpy_s(header_text, text);
6777 }
6778 
6780 {
6781  _header_offsets[0] = x;
6782  _header_offsets[1] = y;
6783 }
6784 
6786 {
6787  _entry_start_y = y;
6788 }
6789 
6791 {
6792  _entry_h = h;
6793 }
6794 
6796 {
6797  if ( _background_first.first_frame >= 0 ) {
6799  }
6800 
6801  if ( _background_entry.first_frame >= 0 ) {
6803  }
6804 
6805  if ( _background_last.first_frame >= 0 ) {
6807  }
6808 }
6809 
6811 {
6812  if ( index >= MAX_WEAPON_FLASH_LINES ) {
6813  Int3(); // Get Alan
6814  return;
6815  }
6816 
6817  // hud_set_default_color();
6818  setGaugeColor();
6819  if ( !timestamp_elapsed(Weapon_flash_info.flash_duration[index]) ) {
6820  if ( Weapon_flash_info.is_bright & (1<<index) ) {
6822  // hud_set_bright_color();
6823  } else {
6825  // hud_set_dim_color();
6826  }
6827  }
6828 }
6829 
6830 void HudGaugeWeaponList::render(float frametime)
6831 {
6832 
6833 }
6834 
6837 {
6838 
6839 }
6840 
6842 {
6843  _plink_offset_x = x;
6844 }
6845 
6847 {
6848  _pname_offset_x = x;
6849 }
6850 
6852 {
6853  _pammo_offset_x = x;
6854 }
6855 
6856 void HudGaugePrimaryWeapons::render(float frametime)
6857 {
6858  ship_weapon *sw;
6859 
6860  int num_primaries; // np == num primary
6861  char name[NAME_LENGTH];
6862 
6863  if(Player_obj->type == OBJ_OBSERVER)
6864  return;
6865 
6868 
6869  sw = &Ships[Player_obj->instance].weapons;
6870 
6871  num_primaries = sw->num_primary_banks;
6872 
6873  setGaugeColor();
6874 
6876 
6877  // render the header of this gauge
6879 
6880  char ammo_str[32];
6881  int i, w, h;
6882  int bg_y_offset = _background_first_h;
6883  int text_y_offset = _entry_start_y;
6884 
6885  for ( i = 0; i < num_primaries; ++i ) {
6886  setGaugeColor();
6887 
6889 
6891 
6892  if (Lcl_gr) {
6894  }
6895 
6896  if (HudGauge::maybeFlashSexp() == i ) {
6898  } else {
6899  maybeFlashWeapon(i);
6900  }
6901 
6902  // indicate if this is linked or currently armed
6903  if ( (sw->current_primary_bank == i) || (Player_ship->flags & SF_PRIMARY_LINKED) ) {
6904  renderPrintf(position[0] + _plink_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
6905  }
6906 
6907  // either render this primary's image or its name
6910  } else {
6911  renderPrintf(position[0] + _pname_offset_x, position[1] + text_y_offset, EG_WEAPON_P2, "%s", name);
6912  }
6913 
6914  // if this is a ballistic primary with ammo, render the ammo count
6916  // print out the ammo right justified
6917  sprintf(ammo_str, "%d", sw->primary_bank_ammo[i]);
6918 
6919  // get rid of #
6921 
6922  hud_num_make_mono(ammo_str, font_num);
6923  gr_get_string_size(&w, &h, ammo_str);
6924 
6925  renderString(position[0] + _pammo_offset_x - w, position[1] + text_y_offset, EG_NULL, ammo_str);
6926  }
6927 
6928  text_y_offset += _entry_h;
6929  bg_y_offset += _background_entry_h;
6930  }
6931 
6932  if ( num_primaries == 0 ) {
6934  renderString(position[0] + _pname_offset_x, position[1] + text_y_offset, EG_WEAPON_P1, XSTR( "<none>", 329));
6935 
6936  bg_y_offset += _background_entry_h;
6937  }
6938 
6940 }
6941 
6944 {
6945 
6946 }
6947 
6949 {
6950  _sammo_offset_x = x;
6951 }
6952 
6954 {
6955  _sname_offset_x = x;
6956 }
6957 
6959 {
6960  _sreload_offset_x = x;
6961 }
6962 
6964 {
6965  _slinked_offset_x = x;
6966 }
6967 
6969 {
6971 }
6972 
6974 {
6975  ship_weapon *sw;
6976 
6977  int num_primaries, num_secondaries;
6978 
6981 
6982  sw = &Ships[Player_obj->instance].weapons;
6983 
6984  num_primaries = sw->num_primary_banks;
6985  num_secondaries = sw->num_secondary_banks;
6986 
6987  setGaugeColor();
6988 
6990 
6991  // render the header of this gauge
6993 
6994  weapon_info *wip;
6995  char weapon_name[NAME_LENGTH + 10];
6996  char ammo_str[32];
6997  int i, w, h;
6998  int bg_y_offset = _background_first_h;
6999  int text_y_offset = _entry_start_y;
7000 
7001  for ( i = 0; i < num_secondaries; ++i ) {
7002  setGaugeColor();
7003  wip = &Weapon_info[sw->secondary_bank_weapons[i]];
7004 
7006 
7007  maybeFlashWeapon(num_primaries+i);
7008 
7009  strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
7010  end_string_at_first_hash_symbol(weapon_name);
7011 
7012  if ( sw->current_secondary_bank == i ) {
7013  // show that this is the current secondary armed
7014  renderPrintf(position[0] + _sunlinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
7015 
7016  // indicate if this is linked
7018  renderPrintf(position[0] + _slinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
7019  }
7020 
7021  // show secondary weapon's image or print its name
7022  if(wip->hud_image_index != -1) {
7023  renderBitmap(wip->hud_image_index, position[0] + _sname_offset_x, position[1] + text_y_offset);
7024  } else {
7025  renderString(position[0] + _sname_offset_x, position[1] + text_y_offset, i ? EG_WEAPON_S1 : EG_WEAPON_S2, weapon_name);
7026  }
7027 
7028  // show the cooldown time
7029  if ( (sw->secondary_bank_ammo[i] > 0) && (sw->current_secondary_bank >= 0) ) {
7031  if ( (ms_till_fire >= 500) && ((wip->fire_wait >= 1 ) || (ms_till_fire > wip->fire_wait*1000)) ) {
7032  renderPrintf(position[0] + _sreload_offset_x, position[1] + text_y_offset, EG_NULL, "%d", fl2i(ms_till_fire/1000.0f +0.5f));
7033  }
7034  }
7035  } else {
7036  renderString(position[0] + _sname_offset_x, position[1] + text_y_offset, i ? EG_WEAPON_S1 : EG_WEAPON_S2, weapon_name);
7037  }
7038 
7039  int ammo = sw->secondary_bank_ammo[i];
7040 
7041  // print out the ammo right justified
7042  sprintf(ammo_str, "%d", ammo);
7043  hud_num_make_mono(ammo_str, font_num);
7044  gr_get_string_size(&w, &h, ammo_str);
7045 
7046  renderString(position[0] + _sammo_offset_x - w, position[1] + text_y_offset, EG_NULL, ammo_str);
7047 
7048  bg_y_offset += _background_entry_h;
7049  text_y_offset += _entry_h;
7050  }
7051 
7052  if ( num_secondaries == 0 ) {
7054  renderString(position[0] + _sname_offset_x, position[1] + text_y_offset, EG_WEAPON_S1, XSTR( "<none>", 329));
7055 
7056  bg_y_offset += _background_entry_h;
7057  }
7058 
7059  // finish drawing the background
7061 }
7062 
7065 {
7066 
7067 }
7068 
7070 {
7071  _size[0] = w;
7072  _size[1] = h;
7073 }
7074 
7076 {
7077  _line_width = w;
7078 }
7079 
7081 {
7082  _view_direction = dir;
7083 }
7084 
7085 void HudGaugeHardpoints::initDrawOptions(bool primary_models, bool secondary_models)
7086 {
7087  draw_primary_models = primary_models;
7088  draw_secondary_models = secondary_models;
7089 }
7090 
7091 void HudGaugeHardpoints::render(float frametime)
7092 {
7093  int sx, sy;
7094  ship *sp;
7095  ship_info *sip;
7096  object *objp = Player_obj;
7097 
7098  sp = &Ships[objp->instance];
7099  sip = &Ship_info[sp->ship_info_index];
7100 
7101  sx = position[0];
7102  sy = position[1];
7103 
7104  bool g3_yourself = !g3_in_frame();
7105  angles top_view = {-PI_2,0.0f,0.0f};
7106  angles front_view = {PI_2*2.0f,PI_2*2.0f,0.0f};
7107  matrix object_orient;
7108 
7109  switch ( _view_direction ) {
7110  case TOP:
7111  vm_angles_2_matrix(&object_orient, &top_view);
7112  break;
7113  case FRONT:
7114  vm_angles_2_matrix(&object_orient, &front_view);
7115  break;
7116  }
7117 
7118  gr_screen.clip_width = _size[0];
7119  gr_screen.clip_height = _size[1];
7120 
7121  //Fire it up
7122  if(g3_yourself)
7123  g3_start_frame(1);
7125  setClip(sx, sy, _size[0], _size[1]);
7126 
7128 
7129  if (!Cmdline_nohtl) {
7132  }
7133 
7134  setGaugeColor();
7135 
7136  //We're ready to show stuff
7137  model_render_params render_info;
7138 
7139  int detail_level_lock = 1;
7140  int cull = gr_set_cull(0);
7141  gr_stencil_clear();
7143  int zbuffer = gr_zbuffer_set(GR_ZBUFF_NONE);
7145 
7146  render_info.set_color(gauge_color);
7147  render_info.set_detail_level_lock(detail_level_lock);
7149  render_info.set_object_number(OBJ_INDEX(objp));
7150 
7151  model_render_immediate( &render_info, sip->model_num, &object_orient, &vmd_zero_vector);
7152 
7155  gr_set_cull(cull);
7156  gr_set_line_width(_line_width*2.0f);
7157 
7158  //model_set_alpha( gr_screen.current_color.alpha / 255.0f );
7159  //model_set_forced_texture(0);
7161 
7163  &render_info,
7164  sip->model_num,
7165  &object_orient,
7167  );
7168 
7170  gr_zbuffer_set(zbuffer);
7171  gr_set_line_width(1.0f);
7172 
7173  // draw weapon models
7174  int i, k;
7175  ship_weapon *swp = &sp->weapons;
7176  vertex draw_point;
7177  vec3d subobj_pos;
7178  g3_start_instance_matrix(&vmd_zero_vector, &object_orient, true);
7179 
7181 
7182  setGaugeColor();
7183  float alpha = gr_screen.current_color.alpha / 255.0f;
7184 
7185  //secondary weapons
7186  int num_secondaries_rendered = 0;
7187  vec3d secondary_weapon_pos;
7188  w_bank* bank;
7189 
7190  if ( draw_secondary_models ) {
7191  for (i = 0; i < swp->num_secondary_banks; i++) {
7193  continue;
7194 
7195  bank = &(model_get(sip->model_num))->missile_banks[i];
7196 
7198  for(k = 0; k < bank->num_slots; k++) {
7199  model_render_params weapon_render_info;
7200 
7201  weapon_render_info.set_detail_level_lock(detail_level_lock);
7202  weapon_render_info.set_flags(render_flags);
7203 
7205  }
7206  } else {
7207  num_secondaries_rendered = 0;
7208 
7209  for(k = 0; k < bank->num_slots; k++)
7210  {
7211  secondary_weapon_pos = bank->pnt[k];
7212 
7213  if (num_secondaries_rendered >= sp->weapons.secondary_bank_ammo[i])
7214  break;
7215 
7216  if(sp->secondary_point_reload_pct[i][k] <= 0.0)
7217  continue;
7218 
7219  model_render_params weapon_render_info;
7220 
7221  if ( swp->current_secondary_bank == i && ( swp->secondary_next_slot[i] == k || ( swp->secondary_next_slot[i]+1 == k && sp->flags & SF_SECONDARY_DUAL_FIRE ) ) ) {
7222  weapon_render_info.set_color(Color_bright_blue);
7223  } else {
7224  weapon_render_info.set_color(Color_bright_white);
7225  }
7226 
7227  num_secondaries_rendered++;
7228 
7230 
7231  weapon_render_info.set_detail_level_lock(detail_level_lock);
7232  weapon_render_info.set_flags(render_flags);
7233 
7234  model_render_immediate(&weapon_render_info, Weapon_info[swp->secondary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &secondary_weapon_pos);
7235  }
7236  }
7237  }
7238  }
7239  g3_done_instance(true);
7240  resetClip();
7241 
7243 
7244  //primary weapons
7245  if ( draw_primary_models ) {
7246  for ( i = 0; i < swp->num_primary_banks; i++ ) {
7247  bank = &model_get(sip->model_num)->gun_banks[i];
7248 
7249  for ( k = 0; k < bank->num_slots; k++ ) {
7250  if ( ( Weapon_info[swp->primary_bank_weapons[i]].external_model_num == -1 || !sip->draw_primary_models[i] ) ) {
7251  vm_vec_unrotate(&subobj_pos, &bank->pnt[k], &object_orient);
7252  //vm_vec_sub(&subobj_pos, &Eye_position, &subobj_pos);
7253  //g3_rotate_vertex(&draw_point, &bank->pnt[k]);
7254 
7255  g3_rotate_vertex(&draw_point, &subobj_pos);
7256  g3_project_vertex(&draw_point);
7257 
7258  //resize(&width, &height);
7259 
7260  //unsize(&xc, &yc);
7261  //unsize(&draw_point.screen.xyw.x, &draw_point.screen.xyw.y);
7262 
7263  renderCircle((int)draw_point.screen.xyw.x + position[0], (int)draw_point.screen.xyw.y + position[1], 10);
7264  //renderCircle(xc, yc, 25);
7265  } else {
7267 
7268 
7269  model_render_params weapon_render_info;
7270  weapon_render_info.set_detail_level_lock(detail_level_lock);
7271  weapon_render_info.set_flags(render_flags);
7272  weapon_render_info.set_alpha(alpha);
7273 
7276  pm->gun_submodel_rotation = 0.0f;
7277  }
7278  }
7279  }
7280  }
7281 
7282  //We're done
7283  if(!Cmdline_nohtl)
7284  {
7287  }
7288  if(g3_yourself)
7289  g3_end_frame();
7290 
7292 }
void mc_info_init(mc_info *mc)
Definition: model.h:1138
void initPrimaryNameOffsetX(int x)
Definition: hudtarget.cpp:6846
void initMaxTriSeperation(float length)
Definition: hudtarget.cpp:6231
object * objp
Definition: hudtarget.cpp:131
ship_subsys * advance_subsys(ship_subsys *cur, int next_flag)
Definition: hudtarget.cpp:480
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
int model_collide(mc_info *mc_info_obj)
char Lead_fname[NUM_HUD_RETICLE_STYLES][GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN]
Definition: hudtarget.cpp:182
#define MIN_COMM_STR_TO_MESSAGE
Definition: subsysdamage.h:47
#define gr_zbuffer_set
Definition: 2d.h:817
#define MIN_DISTANCE_TO_CONSIDER_THREAT
Definition: hudtarget.cpp:121
void ship_maybe_warn_player(ship *enemy_sp, float dist)
Definition: ship.cpp:15457
bool gr_resize_screen_posf(float *x, float *y, float *w, float *h, int resize_mode)
Definition: 2d.cpp:430
int timestamp(int delta_ms)
Definition: timer.cpp:226
int Weapon_secondary_name_x[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:374
#define PLAYER_FLAGS_MATCH_TARGET
Definition: player.h:36
#define INCREASING
Definition: hudtarget.h:22
struct screen3d::@234::@236 xyw
int flags
Definition: iff_defs.h:45
reticle_list Reticle_list[MAX_RETICLE_TARGETS]
Definition: hudtarget.cpp:141
void initSecondaryHeights(int top_h, int text_h)
Definition: hudtarget.cpp:5834
int Framecount
Definition: systemvars.cpp:22
int i
Definition: multi_pxo.cpp:466
fix Missiontime
Definition: systemvars.cpp:19
#define STI_HUD_SHOW_ATTACK_DIRECTION
Definition: ship.h:993
int check_all_turrets
Definition: hudtarget.h:82
#define HUD_OFFSCREEN_INDICATOR
Definition: hudgauges.h:42
void renderBitmapEx(int frame, int x, int y, int w, int h, int sx, int sy)
Definition: hud.cpp:818
model_subsystem * system_info
Definition: ship.h:314
float last_speed
Definition: ai.h:495
int HUD_color_alpha
Definition: hud.cpp:76
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
#define MR_SHOW_OUTLINE_HTL
Definition: model.h:885
int Auto_text_offsets[2]
Definition: hudtarget.h:187
void hud_gauge_popup_start(int gauge_index, int time)
Start a gauge to pop-up.
Definition: hud.cpp:3036
#define SF_DEPART_WARP
Definition: ship.h:449
void initCountTextOffsets(int x, int y)
Definition: hudtarget.cpp:5358
void initBgFirstOffsetX(int x)
Definition: hudtarget.cpp:6744
#define MIN(a, b)
Definition: pstypes.h:296
float Proj_fov
Definition: 3dsetup.cpp:31
int HUD_nose_x
Definition: hud.cpp:94
vec3d * pos
Definition: model.h:1113
#define HUD_HOSTILE_TRIANGLE
Definition: hudgauges.h:20
ai_info * Player_ai
Definition: ai.cpp:24
int Weapon_secondary_reload_x[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:386
#define MR_NO_CULL
Definition: model.h:879
int team
Definition: ship.h:606
int Weapon_sunlinked_offset_x
Definition: hudtarget.h:315
void hud_target_prev(int team_mask)
Definition: hudtarget.cpp:1252
char * ship_subsys_get_name(ship_subsys *ss)
Definition: ship.cpp:15001
int Weapon_slinked_x[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:344
hud_frames _background_last
Definition: hudtarget.h:355
hud_frames Lead_sight
Definition: hudtarget.h:561
#define HUD_C_BRIGHT
Definition: hud.h:162
float vm_vec_mag_quick(const vec3d *v)
Definition: vecmat.cpp:371
int flags
Definition: player.h:104
#define TARGET_DISPLAY_DIST
Definition: hudtarget.h:160
char name[NAME_LENGTH]
Definition: weapon.h:322
bool draw_primary_models[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:1302
reticle_list Reticle_save_list
Definition: hudtarget.cpp:139
vec3d vmd_z_vector
Definition: vecmat.cpp:27
vec3d View_position
Definition: 3dsetup.cpp:20
int num_primary_banks
Definition: ship.h:99
object * homing_object
Definition: weapon.h:177
int objnum
Definition: ship.h:537
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
#define HUD_TARGET_TRIANGLE
Definition: hudgauges.h:21
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
int Lead_indicator_gauge_loaded
Definition: hudtarget.cpp:181
void initAlwaysShowText(bool show_text)
Definition: hudtarget.cpp:5501
#define MISSION_FLAG_FULLNEB
Definition: missionparse.h:70
#define COMM_SCRAMBLED
Definition: subsysdamage.h:51
int team_mask
Definition: hudtarget.h:76
int alt_type_index
Definition: ship.h:556
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
int external_model_num
Definition: weapon.h:331
int obj_team(object *objp)
Definition: object.cpp:1843
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
int Cm_text_val_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudtarget.cpp:208
void initBitmaps(char *fname)
Definition: hudtarget.cpp:4142
int HUD_nose_y
Definition: hud.cpp:95
void hud_target_subsystem_in_reticle()
Definition: hudtarget.cpp:2673
ship_weapon weapons
Definition: ship.h:658
void hud_reticle_clear_list(reticle_list *rlist)
Definition: hudtarget.cpp:511
void hud_artillery_render()
net_player * Net_player
Definition: multi.cpp:94
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
float fire_wait
Definition: weapon.h:359
float v
Definition: pstypes.h:135
int Weapon_secondary_ammo_x[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:378
#define gr_end_view_matrix
Definition: 2d.h:896
hud_frames Energy_bar
Definition: hudtarget.h:261
hud_frames Energy_bar
Definition: hudtarget.h:247
#define EG_WEAPON_P1
Definition: emp.h:31
void initOnColor(int r, int g, int b, int a)
Definition: hudtarget.cpp:4794
#define WIF_LOCKED_HOMING
Definition: weapon.h:130
ship_obj * get_ship_obj_ptr_from_index(int index)
Definition: ship.cpp:513
object * objp
Definition: hudtarget.h:52
int Weapon_pname_coords[GR_NUM_RESOLUTIONS][2][2]
Definition: hudtarget.cpp:334
ubyte g
Definition: pstypes.h:175
void initPrimaryWeaponOffsets(int link_x, int name_x, int ammo_x)
Definition: hudtarget.cpp:5806
void mission_parse_lookup_callsign_index(int index, char *out)
void hud_num_make_mono(char *num_str, int font_num)
Convert a number string to use mono-spaced 1 character.
Definition: hud.cpp:2275
#define HUD_OBJECT_LEAD_SIGHT
Definition: hudparse.h:172
Definition: weapon.h:163
GLuint index
Definition: Glext.h:5608
int hud_get_best_primary_bank(float *range)
Definition: hudtarget.cpp:3719
asteroid Asteroids[MAX_ASTEROIDS]
Definition: asteroid.cpp:63
void render(float frametime)
Definition: hudtarget.cpp:5975
#define VM_WARP_CHASE
Definition: systemvars.h:37
physics_info phys_info
Definition: object.h:157
int Fred_running
Definition: fred.cpp:44
matrix * vm_angles_2_matrix(matrix *m, const angles *a)
Definition: vecmat.cpp:752
hud_frames Weapon_gauges[NUM_HUD_SETTINGS][NUM_WEAPON_GAUGES]
Definition: hudtarget.cpp:231
#define MAX_SHIPS
Definition: globals.h:37
void initPrimaryAmmoOffsetX(int x)
Definition: hudtarget.cpp:6851
void hud_stop_looped_locking_sounds()
Definition: hudlock.cpp:978
#define GR_STENCIL_WRITE
Definition: 2d.h:679
void initStartNameOffsetsY(int p_y, int s_y)
Definition: hudtarget.cpp:5822
int Weapon_title_coords[NUM_HUD_SETTINGS][GR_NUM_RESOLUTIONS][2]
Definition: hudtarget.cpp:305
void setGaugeColor(int bright_index=-4)
Definition: hud.cpp:445
void initSecondaryWeaponOffsets(int ammo_x, int name_x, int reload_x, int linked_x, int unlinked_x)
Definition: hudtarget.cpp:5813
int model_num
Definition: ship.h:1189
void initRadius(int length)
Definition: hudtarget.cpp:2905
int check_nearest_turret
Definition: hudtarget.h:80
proximity warning (aspect)
Definition: gamesnd.h:124
#define TOGGLE_TEXT_NORMAL_ALPHA
Definition: hudtarget.h:57
#define TYPE_NONE
Definition: hudtarget.cpp:1681
int missile_list_index
Definition: weapon.h:181
int cargo_inspect_time
Definition: player.h:171
float Max_front_seperation[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:67
int class_type
Definition: ship.h:1167
#define PCM_NORMAL
Definition: player.h:58
#define COMM_DAMAGED
Definition: subsysdamage.h:50
struct _reticle_list reticle_list
#define T_OFFSET_FROM_CIRCLE
Definition: hudtarget.cpp:2743
int next_secondary_fire_stamp[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:115
void mission_parse_lookup_alt_index(int index, char *out)
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void render(float frametime)
Definition: hudtarget.cpp:5529
Assert(pm!=NULL)
int target_objnum
Definition: ai.h:339
int current_hotkey_set
Definition: player.h:108
int Speed_text_offsets[2]
Definition: hudtarget.h:211
#define MR_NO_POLYS
Definition: model.h:866
void hud_stuff_ship_name(char *ship_name_text, ship *shipp)
Definition: hudtarget.cpp:5269
#define HUD_OBJECT_AUTO_SPEED
Definition: hudparse.h:85
Definition: pstypes.h:88
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
int HUD_drew_selection_bracket_on_target
Definition: hudtarget.cpp:3383
#define EG_WEAPON_S2
Definition: emp.h:35
void initEntryStartY(int y)
Definition: hudtarget.cpp:6785
int ai_index
Definition: ship.h:538
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
ship_weapon weapons
Definition: ship.h:362
void gr_init_alphacolor(color *clr, int r, int g, int b, int alpha, int type)
Definition: 2d.cpp:1173
w_bank * gun_banks
Definition: model.h:772
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
void initBitmap(char *fname)
Definition: hudtarget.cpp:6580
#define HUD_OBJECT_HARDPOINTS
Definition: hudparse.h:226
void initSecondaryAmmoOffsetX(int x)
Definition: hudtarget.cpp:6948
int Toggle_text_alpha
Definition: hudtarget.cpp:226
#define OBJ_ASTEROID
Definition: object.h:44
void player_stop_cargo_scan_sound()
void maybeFlashWeapon(int index)
Definition: hudtarget.cpp:6175
#define VM_EXTERNAL
Definition: systemvars.h:31
Definition: 2d.h:95
int subsys_in_view
Definition: player.h:168
matrix Eye_matrix
Definition: 3dsetup.cpp:26
#define SSF_UNTARGETABLE
Definition: ship.h:280
void initSecondaryReloadOffsetX(int x)
Definition: hudtarget.cpp:6958
#define SIF_CARGO
Definition: ship.h:884
int bm_get_info(int handle, int *w, int *h, ubyte *flags, int *nframes, int *fps)
Gets info on the bitmap indexed by handle.
Definition: bmpman.cpp:769
void set_flags(uint flags)
int Cm_text_offsets[2]
Definition: hudtarget.h:233
#define MR_NO_LIGHTING
Definition: model.h:867
int Lcl_pl
Definition: localize.cpp:49
struct vec3d::@225::@227 xyz
float afterburner_fuel
Definition: ship.h:648
CButton * team
int base_h
Definition: hud.h:205
void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d *pos, int render, bool sort)
hud_frames Cmeasure_gauge
Definition: hudtarget.cpp:190
#define MAX_KEYED_TARGETS
Definition: player.h:26
GLclampf f
Definition: Glext.h:7097
float y
Definition: pstypes.h:107
#define MAX_OBJECTS
Definition: globals.h:83
#define GR_ZBUFF_NONE
Definition: 2d.h:672
void polish_predicted_target_pos(weapon_info *wip, object *targetp, vec3d *enemy_pos, vec3d *predicted_enemy_pos, float dist_to_enemy, vec3d *last_delta_vec, int num_polish_steps)
Definition: hudtarget.cpp:3777
int ship_subsystem_in_sight(object *objp, ship_subsys *subsys, vec3d *eye_pos, vec3d *subsys_pos, int do_facing_check, float *dot_out, vec3d *vec_out)
Definition: ship.cpp:14881
int model_num
Definition: debris.h:34
#define TRUE
Definition: pstypes.h:399
int Reticle_save_timestamp
Definition: hudtarget.cpp:137
#define WIF2_EXTERNAL_WEAPON_LNCH
Definition: weapon.h:109
void hud_cease_targeting()
Definition: hudtarget.cpp:4367
int snd_is_playing(int sig)
Definition: sound.cpp:1047
void calculatePosition(vertex *target_point, vec3d *tpos, vec2d *outcoords, int *dir, float *half_triangle_sep)
Definition: hudtarget.cpp:6295
#define SF2_FRIENDLY_STEALTH_INVIS
Definition: ship.h:484
int Weapon_header_offsets[NUM_HUD_SETTINGS][2]
Definition: hudtarget.h:295
void free_temp_point(vertex *p)
Definition: 3dclipper.cpp:42
void hud_target_closest_locked_missile(object *locked_obj)
Definition: hudtarget.cpp:1908
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
float Target_triangle_base[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:87
int Weapon_sreload_offset_x
Definition: hudtarget.h:313
Definition: 2d.h:82
object obj_used_list
Definition: object.cpp:53
#define gr_set_line_width
Definition: 2d.h:938
float Max_offscreen_tri_seperation[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:63
#define f2fl(fx)
Definition: floating.h:37
int Message_shipnum
int current_primary_bank
Definition: ship.h:106
void set_detail_level_lock(int detail_level_lock)
ship_subsys * targeted_subsys
Definition: ai.h:472
#define MAX_HOTKEY_TARGET_ITEMS
Definition: hudtarget.h:35
float ship_get_secondary_weapon_range(ship *shipp)
Definition: ship.cpp:16238
#define HUD_LEAD_INDICATOR
Definition: hudgauges.h:18
color HUD_color_homing_indicator
Definition: hudtarget.cpp:957
int hud_sensors_ok(ship *sp, int show_msg)
Check if targeting is possible based on sensors strength.
Definition: hudtarget.cpp:4578
target acquried
Definition: gamesnd.h:76
Definition: model.h:432
void gr_set_screen_scale(int w, int h, int zoom_w, int zoom_h, int max_w, int max_h, int center_w, int center_h, bool force_stretch)
Definition: 2d.cpp:104
void renderLine(int x1, int y1, int x2, int y2)
Definition: hud.cpp:850
float max_speed
Definition: weapon.h:354
void vm_vec_scale_add2(vec3d *dest, const vec3d *src, float k)
Definition: vecmat.cpp:284
#define MAX_TRANSMIT_TARGETS
Definition: hudtarget.cpp:5095
hud_frames secondary_top[NUM_HUD_SETTINGS]
Definition: hudtarget.h:303
#define PLAYER_FLAGS_AUTO_TARGETING
Definition: player.h:38
float min_distance
Definition: hudtarget.h:79
void hud_check_reticle_list()
Definition: hudtarget.cpp:539
void initCountSizes(int w, int h)
Definition: hudtarget.cpp:6601
Definition: ai.h:329
SCP_vector< target_display_info > target_display_list
Definition: hudtarget.cpp:72
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
float weapon_energy
Definition: ship.h:640
#define HUD_OBJECT_TARGET_TRI
Definition: hudparse.h:205
uint flags
Definition: ship.h:644
float Offscreen_tri_base[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:55
ubyte blue
Definition: 2d.h:102
#define STI_HUD_TARGET_AS_THREAT
Definition: ship.h:992
matrix * B
Definition: lua.cpp:445
int sname_start_offset_y
Definition: hudtarget.h:322
void initOffColor(int r, int g, int b, int a)
Definition: hudtarget.cpp:4720
float weapon_range
Definition: weapon.h:390
int flags
Definition: multi.h:463
#define AIPF_USE_ADDITIVE_WEAPON_VELOCITY
Definition: ai_profiles.h:34
#define RL_USED
Definition: hudtarget.cpp:126
void initTextOffsets(int x, int y)
Definition: hudtarget.cpp:5476
object * objp
Definition: lua.cpp:3105
shader Training_msg_glass
Definition: hudtarget.cpp:84
#define EG_WEAPON_TITLE
Definition: emp.h:30
#define OBJ_OBSERVER
Definition: object.h:43
int current_secondary_bank
Definition: ship.h:107
int max_w_unscaled
Definition: 2d.h:361
int subtype
Definition: weapon.h:326
#define Int3()
Definition: pstypes.h:292
void initTriBase(float length)
Definition: hudtarget.cpp:6241
void hud_target_hotkey_select(int k)
Definition: hudtarget.cpp:855
void initDrawOptions(bool primary_models, bool secondary_models)
Definition: hudtarget.cpp:7085
void HUD_sourced_printf(int source, const char *format,...)
Definition: hudmessage.cpp:571
int Cm_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudtarget.cpp:192
float current_target_distance
Definition: ai.h:489
ship * shipp
Definition: lua.cpp:9162
void renderGradientLine(int x1, int y1, int x2, int y2)
Definition: hud.cpp:873
hud_frames secondary_middle[NUM_HUD_SETTINGS]
Definition: hudtarget.h:304
vec3d pos
Definition: object.h:152
void hud_target_clear_display_list()
Definition: hudtarget.cpp:6221
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
float Offscreen_tri_height
Definition: hudtarget.h:528
void initAutoTextOffsets(int x, int y)
Definition: hudtarget.cpp:4774
vec3d * p0
Definition: model.h:1114
void hud_target_add_display_list(object *objp, vertex *target_point, vec3d *target_pos, int correction, color *bracket_clr, char *name, int flags)
Definition: hudtarget.cpp:6195
void hud_weapons_init()
Definition: hudtarget.cpp:999
int TARGET_SHIP_IGNORE_FLAGS
Definition: hudtarget.cpp:49
float gun_submodel_rotation
Definition: model.h:813
float vm_vec_mag_squared(const vec3d *v)
Definition: vecmat.cpp:339
void asteroid_target_closest_danger()
Definition: asteroid.cpp:2192
#define TOGGLE_TEXT_NEBULA_ALPHA
Definition: hudtarget.h:56
#define SIF_AFTERBURNER
Definition: ship.h:879
int asteroid_subtype
Definition: asteroid.h:103
#define gr_end_proj_matrix
Definition: 2d.h:894
void setClip(int x, int y, int w, int h)
Definition: hud.cpp:942
vec3d pnt[MAX_SLOTS]
Definition: model.h:434
int signature
Definition: object.h:145
void render(float frametime)
Definition: hudtarget.cpp:5430
#define TYPE_FACING_MISSILE
Definition: hudtarget.cpp:1684
#define PLAYER_FLAGS_AUTO_MATCH_SPEED
Definition: player.h:39
int clip_height
Definition: 2d.h:378
SCP_list< CJumpNode > Jump_nodes
Definition: jumpnode.cpp:16
void hud_target_hotkey_clear(int k)
Definition: hudtarget.cpp:835
void initBitmapsPrimaryTop(char *fname, char *fname_ballistic)
Definition: hudtarget.cpp:5840
int model_num
Definition: model.h:1110
int object_targetable_in_reticle(object *target_objp)
Definition: hudtarget.cpp:2440
GLenum type
Definition: Gl.h:1492
int Wenergy_text_offsets[2]
Definition: hudtarget.h:263
#define TURRET_RESET
Definition: hudtarget.cpp:147
int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
Loads a bitmap sequance so we can draw with it.
Definition: bmpman.cpp:1420
void mission_hotkey_maybe_save_sets()
void initTriHeight(float length)
Definition: hudtarget.cpp:6246
void hud_target_subobject_common(int next_flag)
Definition: hudtarget.cpp:1076
Definition: hud.h:201
iff_info Iff_info[MAX_IFFS]
Definition: iff_defs.cpp:20
int iff_get_attackee_mask(int attacker_team)
Definition: iff_defs.cpp:561
ubyte green
Definition: 2d.h:101
void hud_calculate_lead_pos(vec3d *lead_target_pos, vec3d *target_pos, object *targetp, weapon_info *wip, float dist_to_target, vec3d *rel_pos)
Definition: hudtarget.cpp:3682
int weapon_info_index
Definition: weapon.h:164
void hud_target_hotkey_add_remove(int k, object *ctarget, int how_to_add)
Definition: hudtarget.cpp:771
#define SF2_SCRAMBLE_MESSAGES
Definition: ship.h:509
#define SUBSYSTEM_COMMUNICATION
Definition: model.h:57
float lifetime
Definition: weapon.h:382
void g3_done_instance(bool set_api=false)
Definition: 3dsetup.cpp:341
int asteroid_type
Definition: asteroid.h:102
int Weapon_pammo_offset_x
Definition: hudtarget.h:309
GLfloat angle
Definition: Glext.h:10324
float atan2_safe(float y, float x)
Definition: vecmat.cpp:68
int objnum
Definition: ship.h:1483
#define OF_TARGETABLE_AS_BOMB
Definition: object.h:118
ship_subsys subsys_list
Definition: ship.h:630
uv_pair texture_position
Definition: pstypes.h:174
player Players[MAX_PLAYERS]
int objnum
Definition: weapon.h:561
hud_frames primary_middle[NUM_HUD_SETTINGS]
Definition: hudtarget.h:297
#define gr_set_view_matrix
Definition: 2d.h:895
void set_alpha(float alpha)
int Weapon_gauge_secondary_coords[NUM_HUD_SETTINGS][GR_NUM_RESOLUTIONS][5][2]
Definition: hudtarget.cpp:266
#define SIF_BOMBER
Definition: ship.h:886
ubyte a
Definition: pstypes.h:175
int current_target_speed_trend
Definition: ai.h:492
void initEnergyHeight(int h)
Definition: hudtarget.cpp:5415
void initBgLastOffsetX(int x)
Definition: hudtarget.cpp:6754
int instance
Definition: object.h:150
#define TBOX_FLASH_DURATION
Definition: hudtargetbox.h:21
void render(float frametime)
Definition: hudtarget.cpp:4818
#define WIF_FLAK
Definition: weapon.h:75
void initEnergyHeight(int h)
Definition: hudtarget.cpp:5482
GLenum GLint * range
Definition: Glext.h:7096
#define PF_OVERFLOW
Definition: 3d.h:22
float ship_get_subsystem_strength(ship *shipp, int type)
Definition: ship.cpp:13446
ship * shipp
Definition: hudtarget.h:78
object * hostile_obj
Definition: hudtarget.cpp:76
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
int Cmdline_nohtl
Definition: cmdline.cpp:438
#define VM_DEAD_VIEW
Definition: systemvars.h:33
#define gr_set_proj_matrix
Definition: 2d.h:893
_reticle_list * next
Definition: hudtarget.cpp:130
float Offscreen_tri_height[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:59
int clip_left_unscaled
Definition: 2d.h:390
int cmeasure_max
Definition: ship.h:1291
int target_is_dying
Definition: player.h:172
GLdouble GLdouble GLdouble r
Definition: Glext.h:5337
int flags
Definition: ship.h:322
#define SIF_BIG_SHIP
Definition: ship.h:944
int flags
Definition: model.h:1116
struct matrix::@228::@230 vec
#define SIF_NAVBUOY
Definition: ship.h:891
int target_in_lock_cone
Definition: player.h:175
unsigned int uint
Definition: pstypes.h:64
#define HUD_TARGET_MINI_ICON
Definition: hudgauges.h:41
An abbreviation for "Evaluate Ship as Closest Target", defines a data structure used to hold the requ...
Definition: hudtarget.h:74
void initOnColor(int r, int g, int b, int a)
Definition: hudtarget.cpp:4708
#define WIF_REMOTE
Definition: weapon.h:48
#define HUD_OBJECT_MISSILE_TRI
Definition: hudparse.h:208
void initBitmaps(char *fname)
Definition: hudtarget.cpp:5420
screen3d screen
Definition: pstypes.h:173
int subtype
Definition: lua.cpp:9763
GLboolean GLboolean g
Definition: Glext.h:5781
#define HOTKEY_USER_ADDED
Definition: hudtarget.h:43
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
#define MR_NO_ZBUFFER
Definition: model.h:878
int timestamp_until(int stamp)
Definition: timer.cpp:242
#define nprintf(args)
Definition: pstypes.h:239
GLuint coords
Definition: Glext.h:6925
#define TMAP_FLAG_GOURAUD
Definition: tmapper.h:40
int font_num
Definition: hud.h:210
#define GM_MULTIPLAYER
Definition: systemvars.h:18
#define HUD_AFTERBURNER_ENERGY
Definition: hudgauges.h:38
char hud_filename[MAX_FILENAME_LEN]
Definition: weapon.h:343
int clip_top_unscaled
Definition: 2d.h:390
missile_obj * missile_obj_return_address(int index)
Definition: weapons.cpp:458
int clip_right_unscaled
Definition: 2d.h:390
int primary_bank_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:121
float clip_aspect
Definition: 2d.h:372
#define MR_NO_TEXTURING
Definition: model.h:868
int turret_compare_func(const void *e1, const void *e2)
Definition: hudtarget.cpp:1698
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
int Weapon_primary_ammo_x[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:382
vec3d * p1
Definition: model.h:1115
int ship_subsys_disrupted(ship_subsys *ss)
Definition: ship.cpp:9033
void g3_set_view_matrix(const vec3d *view_pos, const matrix *view_matrix, float zoom)
Definition: 3dsetup.cpp:152
ai_profile_t * ai_profile
Definition: missionparse.h:168
void render(float frametime)
Definition: hudtarget.cpp:4511
hud_frames Lead_indicator_gauge
Definition: hudtarget.cpp:180
void model_clear_instance(int model_num)
Definition: modelread.cpp:4624
int Weapon_slinked_offset_x
Definition: hudtarget.h:314
int Weapon_plink_offset_x
Definition: hudtarget.h:307
int num_frames
Definition: hud.h:34
int Target_text_offsets[2]
Definition: hudtarget.h:188
int wingnum
Definition: ship.h:623
int ship_get_sound(object *objp, GameSoundsIndex id)
Returns a ship-specific sound index.
Definition: ship.cpp:18614
float speed
Definition: physics.h:79
#define TYPE_NONFACING_INC
Definition: hudtarget.cpp:1690
#define TL_RESET
Definition: hudtarget.cpp:146
int num_secondary_banks
Definition: ship.h:100
#define OBJ_WEAPON
Definition: object.h:33
void hud_show_selection_set()
Definition: hudtarget.cpp:3387
int mode
Definition: ai.h:336
weapon_flash Weapon_flash_info
Definition: hudtarget.cpp:437
void initBitmapsPrimaryLast(char *fname, char *fname_ballistic)
Definition: hudtarget.cpp:5870
void initBitmaps(char *fname)
Definition: hudtarget.cpp:4786
#define SF2_HIDE_SHIP_NAME
Definition: ship.h:498
void initAutoTextOffsets(int x, int y)
Definition: hudtarget.cpp:4688
#define WP_LASER
Definition: weapon.h:27
#define MAX_WEAPON_TYPES
Definition: globals.h:73
ship_subsys * last_subsys_target
Definition: ai.h:473
void hud_target_targets_target()
Definition: hudtarget.cpp:2388
int base_w
Definition: hud.h:205
float Max_draw_distance
Definition: 2d.cpp:85
#define PF_TEMP_POINT
Definition: 3d.h:23
#define T_BASE_LENGTH
Definition: hudtarget.cpp:2744
hud_frames New_weapon
Definition: hudtarget.cpp:232
#define OBJ_DEBRIS
Definition: object.h:37
int last_target
Definition: ai.h:497
#define w(p)
Definition: modelsinc.h:68
void hud_lock_reset(float lock_time_scale)
Definition: hudlock.cpp:271
#define MAX_MODEL_SUBSYSTEMS
Definition: model.h:103
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define IFF_COLOR_MESSAGE
Definition: iff_defs.h:20
void hud_target_auto_target_next()
Definition: hudtarget.cpp:1971
int hud_target_closest(int team_mask, int attacked_objnum, int play_fail_snd, int filter, int get_closest_turret_attacking_player)
Sets the Players[Player_num].current_target to the closest ship to the player that matches the team p...
Definition: hudtarget.cpp:2212
#define SF_HIDDEN_FROM_SENSORS
Definition: ship.h:464
ubyte red
Definition: 2d.h:100
float precalced_interp
Definition: hudtarget.cpp:448
#define SUBSYSTEM_TURRET
Definition: model.h:54
void lcl_translate_targetbox_name_gr(char *name)
Definition: localize.cpp:1401
int pname_start_offset_y
Definition: hudtarget.h:319
#define TYPE_FACING_BEAM
Definition: hudtarget.cpp:1682
#define HUD_MISSILE_WARNING_ARROW
Definition: hudgauges.h:46
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:97
void initHalfSize(float w, float h)
Definition: hudtarget.cpp:3810
#define TARGET_DISPLAY_SUBSYS
Definition: hudtarget.h:163
ship_subsys * ss
Definition: hudtarget.cpp:1693
#define HUD_SOURCE_HIDDEN
Definition: hudmessage.h:23
hull_check p1
Definition: lua.cpp:5052
void initBitmaps(char *fname)
Definition: hudtarget.cpp:5516
float primary_rotate_ang[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:786
#define HUD_OBJECT_ORIENTATION_TEE
Definition: hudparse.h:199
char Cm_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN]
Definition: hudtarget.cpp:216
void hud_target_last_transmit()
Definition: hudtarget.cpp:5127
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
#define HUD_WEAPONS_ENERGY
Definition: hudgauges.h:39
void hud_reticle_list_update(object *objp, float measure, int dot_flag)
Definition: hudtarget.cpp:612
#define SF_PRIMARY_LINKED
Definition: ship.h:458
void initMoveText(bool move_text)
Definition: hudtarget.cpp:5506
int secondary_text_h
Definition: hudtarget.h:326
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:104
void hud_start_flash_weapon(int index)
Definition: hudtarget.cpp:4534
Definition: hud.h:32
void initBitmaps(char *fname)
Definition: hudtarget.cpp:5370
void hud_set_gauge_color(int gauge_index, int bright_index)
Set the HUD color for the gauge, based on whether it is flashing or not.
Definition: hud.cpp:3095
float u
Definition: pstypes.h:135
#define AIM_CHASE
Definition: ai.h:166
float vm_vec_normalized_dir(vec3d *dest, const vec3d *end, const vec3d *start)
Definition: vecmat.cpp:591
bool turret_weapon_has_subtype(ship_weapon *swp, int subtype)
Definition: aiturret.cpp:411
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
#define WIF2_CAN_BE_TARGETED
Definition: weapon.h:104
void initTopOffsetX(int x, int x_b)
Definition: hudtarget.cpp:5786
void initSecondaryNameOffsetX(int x)
Definition: hudtarget.cpp:6953
virtual void render(float frametime)
Definition: hudtarget.cpp:6830
void hud_tri_empty(float x1, float y1, float x2, float y2, float x3, float y3)
Definition: hudtarget.cpp:2886
int Weapon_plink_coords[GR_NUM_RESOLUTIONS][2][2]
Definition: hudtarget.cpp:324
int lssm_stage
Definition: weapon.h:216
void maybeFlashWeapon(int index)
Definition: hudtarget.cpp:6810
vec3d closeup_pos
Definition: ship.h:1327
int hud_reticle_list_find_free()
Definition: hudtarget.cpp:564
int ship_has_energy_weapons(ship *shipp)
Definition: ship.cpp:17611
int callsign_index
Definition: ship.h:557
#define HUD_OBJECT_CMEASURES
Definition: hudparse.h:91
float current_hits
Definition: ship.h:319
void insertion_sort(void *array_base, size_t array_size, size_t element_size, int(*fncompare)(const void *, const void *))
Definition: systemvars.cpp:599
proximity warning (heat seeker)
Definition: gamesnd.h:123
int Cmeasure_gauge_loaded
Definition: hudtarget.cpp:191
Definition: ship.h:534
int wi_flags3
Definition: weapon.h:386
#define COMM_DESTROYED
Definition: subsysdamage.h:49
#define SIF_BALLISTIC_PRIMARIES
Definition: ship.h:880
vec3d eye_pos
Definition: fredrender.cpp:103
void initPrimaryLinkOffsetX(int x)
Definition: hudtarget.cpp:6841
#define TARGET_DISPLAY_DOTS
Definition: hudtarget.h:161
#define STI_SHIP_SCANNABLE
Definition: ship.h:996
#define HUD_OBJECT_LEAD
Definition: hudparse.h:169
int num_slots
Definition: model.h:433
#define TARGET_DISPLAY_CLASS
Definition: hudtarget.h:165
char Fred_alt_names[MAX_SHIPS][NAME_LENGTH+1]
Definition: management.cpp:93
void hud_target_uninspected_object(int next_flag)
Definition: hudtarget.cpp:4977
void render(float frametime)
Definition: hudtarget.cpp:6627
void set_color(color &clr)
#define HUD_OBJECT_AFTERBURNER
Definition: hudparse.h:151
void hud_target_live_turret(int next_flag, int auto_advance, int only_player_target)
Definition: hudtarget.cpp:1724
_reticle_list * prev
Definition: hudtarget.cpp:130
int g3_project_vertex(vertex *point)
Definition: 3dmath.cpp:202
void resetClip()
Definition: hud.cpp:978
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:134
void hud_show_targeting_gauges(float frametime)
Definition: hudtarget.cpp:3478
debris Debris[MAX_DEBRIS_PIECES]
Definition: debris.cpp:41
int Weapon_gauges_loaded
Definition: hudtarget.cpp:233
int targeted_subsys_parent
Definition: ai.h:474
void initBgEntryOffsetX(int x)
Definition: hudtarget.cpp:6749
int how_added
Definition: hudtarget.h:51
void render(float frametime)
Definition: hudtarget.cpp:7091
void renderLeadQuick(vec3d *target_pos, object *targetp)
Definition: hudtarget.cpp:4062
void hud_target_next_list(int hostile, int next_flag, int team_mask, int attacked_objnum, int play_fail_snd, int filter, int get_closest_turret_attacking_player)
Definition: hudtarget.cpp:4637
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:959
void renderString(int x, int y, const char *str)
Definition: hud.cpp:665
float vm_vec_dist_squared(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:344
void initMaxSymbols(int count)
Definition: hudtarget.cpp:6607
void hud_prune_hotkeys()
Definition: hudtarget.cpp:3330
reticle_list Reticle_cur_list
Definition: hudtarget.cpp:138
void hud_update_closest_turret()
Definition: hudtarget.cpp:2321
int iff_x_attacks_y(int team_x, int team_y)
Definition: iff_defs.cpp:605
int get_subsystem_pos(vec3d *pos, object *objp, ship_subsys *subsysp)
Definition: ship.cpp:12975
int Cm_text_val_offsets[2]
Definition: hudtarget.h:234
#define MIN_DOT_FOR_TARGET
Definition: hudtarget.cpp:2600
int filter
Definition: hudtarget.h:77
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
ubyte alpha
Definition: 2d.h:103
long fix
Definition: pstypes.h:54
int top_offset_x[NUM_HUD_SETTINGS]
Definition: hudtarget.h:293
void hud_show_hostile_triangle()
Definition: hudtarget.cpp:3556
unsigned char ubyte
Definition: pstypes.h:62
#define RESET_TARGET_IN_RETICLE
Definition: hudtarget.cpp:136
int wi_flags
Definition: weapon.h:384
#define vm_vec_zero(v)
Definition: vecmat.h:37
void initPrimaryHeights(int top_h, int text_h)
Definition: hudtarget.cpp:5828
int Lead_sight_half[2]
Definition: hudtarget.h:562
#define SF_ARRIVING_STAGE_1
Definition: ship.h:451
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
#define GM_DEAD
Definition: systemvars.h:25
void initHeaderText(char *text)
Definition: hudtarget.cpp:6774
HudGaugeWeaponList(int gauge_object)
Definition: hudtarget.cpp:6709
void hud_target_in_reticle_old()
Definition: hudtarget.cpp:2602
#define OBJ_INDEX(objp)
Definition: object.h:235
int cmeasure_type
Definition: ship.h:1290
hud_frames primary_top[NUM_HUD_SETTINGS]
Definition: hudtarget.h:292
target fail sound (i.e. press targeting key, but nothing happens)
Definition: gamesnd.h:96
#define GR_STENCIL_NONE
Definition: 2d.h:677
vec3d hit_point_world
Definition: model.h:1124
ship * Player_ship
Definition: ship.cpp:124
void hud_target_newest_ship()
Definition: hudtarget.cpp:1619
color Color_bright_red
Definition: alphacolors.cpp:34
void renderTriangle(vec3d *hostile_pos, int aspect_flag, int show_interior, int split_tri)
Definition: hudtarget.cpp:2996
#define gr_set_cull
Definition: 2d.h:838
char * Weapon_gauge_fnames[NUM_HUD_SETTINGS][GR_NUM_RESOLUTIONS][NUM_WEAPON_GAUGES]
Definition: hudtarget.cpp:390
#define MAX_RETICLE_TARGETS
Definition: hudtarget.cpp:140
matrix orient
Definition: object.h:153
#define gr_stencil_set
Definition: 2d.h:820
float Max_warning_missile_dist
Definition: hudtarget.cpp:455
int wi_flags2
Definition: weapon.h:385
void render(float frametime)
Definition: hudtarget.cpp:4732
#define NOX(s)
Definition: pstypes.h:473
float last_dist
Definition: ai.h:494
#define TMAP_FLAG_RGB
Definition: tmapper.h:39
#define EG_NULL
Definition: emp.h:29
bool end_string_at_first_hash_symbol(char *src)
Definition: parselo.cpp:3833
GLuint start
Definition: Gl.h:1502
int iff_get_mask(int team)
Definition: iff_defs.cpp:615
ubyte b
Definition: pstypes.h:175
#define EG_WEAPON_S1
Definition: emp.h:34
#define WIF_BOMB
Definition: weapon.h:63
#define OBJ_SHIP
Definition: object.h:32
#define MULTIPLAYER_STANDALONE
Definition: multi.h:133
int hud_communications_state(ship *sp)
Definition: hudtarget.cpp:4607
void renderTriangleMissileTail(float ang, float xpos, float ypos, float cur_dist, int draw_solid, int draw_inside)
Definition: hudtarget.cpp:2925
void initBitmapsSecondaryBottom(char *fname, char *fname_ballistic)
Definition: hudtarget.cpp:5913
float Offscreen_tri_base
Definition: hudtarget.h:527
ubyte lcl_get_font_index(int font_num)
Definition: localize.cpp:495
void hud_target_in_reticle_new()
Definition: hudtarget.cpp:2483
void initShowBallistics(bool show_ballistics)
Definition: hudtarget.cpp:5511
homing_beep_info Homing_beep
Definition: hudtarget.cpp:451
ubyte flags
Definition: pstypes.h:178
GLbitfield flags
Definition: Glext.h:6722
int Hud_target_w
Definition: hudtarget.cpp:52
void hud_stuff_reticle_list(reticle_list *rl, object *objp, float measure, int dot_flag)
Definition: hudtarget.cpp:589
#define HUD_OBJECT_AUTO_TARGET
Definition: hudparse.h:88
int Num_weapon_types
Definition: weapons.cpp:105
#define HUD_AUTO_TARGET
Definition: hudgauges.h:32
#define SIF_HUGE_SHIP
Definition: ship.h:945
#define HOTKEY_MISSION_FILE_ADDED
Definition: hudtarget.h:44
char Fred_callsigns[MAX_SHIPS][NAME_LENGTH+1]
Definition: management.cpp:94
void renderRect(int x, int y, int w, int h)
Definition: hud.cpp:896
#define gr_set_color_buffer
Definition: 2d.h:839
int control_mode
Definition: player.h:134
int maybeFlashSexp()
Definition: hud.cpp:617
GLuint const GLchar * name
Definition: Glext.h:5608
void hud_target_last_transmit_add(int ship_num)
Definition: hudtarget.cpp:5197
void renderSight(int indicator_frame, vec3d *target_pos, vec3d *lead_target_pos)
Definition: hudtarget.cpp:4157
int hud_target_closest_repair_ship(int goal_objnum)
Definition: hudtarget.cpp:4858
__inline void gr_line(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:791
#define HUD_OBJECT_HOSTILE_TRI
Definition: hudparse.h:202
float Min_warning_missile_dist
Definition: hudtarget.cpp:454
int first_frame
Definition: hud.h:33
void hud_init_homing_beep()
Definition: hudtarget.cpp:1012
float awacs_get_level(object *target, ship *viewer, int use_awacs)
Definition: awacs.cpp:168
float x
Definition: pstypes.h:107
int Weapon_pname_offset_x
Definition: hudtarget.h:308
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
bool turret_weapon_has_flags(ship_weapon *swp, int flags)
Definition: aiturret.cpp:306
#define HUD_ORIENTATION_TEE
Definition: hudgauges.h:19
vec3d vel
Definition: physics.h:77
#define AIM_EVADE
Definition: ai.h:167
#define SF_SCANNABLE
Definition: ship.h:465
int _header_offsets[2]
Definition: hudtarget.h:366
#define SIF_SUPPORT
Definition: ship.h:878
vec3d Eye_position
Definition: 3dsetup.cpp:27
color * iff_get_color(int color_index, int is_bright)
Definition: iff_defs.cpp:636
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
int num_hits
Definition: model.h:1121
#define HUD_OBJECT_OFFSCREEN
Definition: hudparse.h:193
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
#define TYPE_FACING_FLAK
Definition: hudtarget.cpp:1683
bool gr_resize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
Definition: 2d.cpp:212
#define SF_DEPARTING
Definition: ship.h:475
#define HUD_C_NORMAL
Definition: hud.h:164
void player_match_target_speed(char *no_target_text=NULL, char *match_off_text=NULL, char *match_on_text=NULL)
if(aifft_max_checks<=0)
Definition: aiturret.cpp:1581
#define SF_EXPLODED
Definition: ship.h:467
void hud_do_lock_indicator(float frametime)
Definition: hudlock.cpp:492
void hud_target_prev_subobject()
Definition: hudtarget.cpp:1142
#define HUD_OBJECT_WEAPONS
Definition: hudparse.h:100
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
void hud_reticle_list_init()
Definition: hudtarget.cpp:522
color Color_bright_white
Definition: alphacolors.cpp:32
color gauge_color
Definition: hud.h:206
struct weapon_flash weapon_flash
#define T_LENGTH
Definition: hudtarget.cpp:2742
void initRadius(int length)
Definition: hudtarget.cpp:3193
int flash_duration[MAX_WEAPON_FLASH_LINES]
Definition: hudtarget.cpp:433
vec3d pnt
Definition: model.h:178
int vm_vec_same(const vec3d *v1, const vec3d *v2)
Definition: vecmat.cpp:1526
void initSpeedTextOffsets(int x, int y)
Definition: hudtarget.cpp:4780
int secondary_next_slot[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:137
hud_frames secondary_bottom[NUM_HUD_SETTINGS]
Definition: hudtarget.h:305
void initBgFirstHeight(int h)
Definition: hudtarget.cpp:6764
void hud_target_change_check()
Definition: hudtarget.cpp:4407
float vm_vec_dist_quick(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:417
ship_obj * advance_ship(ship_obj *so, int next_flag)
Definition: hudtarget.cpp:1269
#define NAME_LENGTH
Definition: globals.h:15
hud_frames _background_entry
Definition: hudtarget.h:354
#define SF_SECONDARY_DUAL_FIRE
Definition: ship.h:459
int hud_target_last_transmit_newest()
Definition: hudtarget.cpp:5114
float Target_triangle_height[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:91
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
void initTextAlign(int align)
Definition: hudtarget.cpp:6617
#define WP_MISSILE
Definition: weapon.h:28
void unsize(int *x, int *y)
Definition: hud.cpp:1012
float rad
Definition: model.h:757
int position[2]
Definition: hud.h:204
char header_text[NAME_LENGTH]
Definition: hudtarget.h:370
int set_target_objnum(ai_info *aip, int objnum)
Definition: aicode.cpp:1250
object * hud_reticle_pick_target()
Definition: hudtarget.cpp:679
Definition: pstypes.h:106
void renderOrientation(object *from_objp, object *to_objp, matrix *from_orientp)
Definition: hudtarget.cpp:2748
int clip_bottom_unscaled
Definition: 2d.h:390
void bm_page_in_aabitmap(int bitmapnum, int nframes)
Marks a texture as being used for this level, and is anti-aliased.
Definition: bmpman.cpp:2354
int Weapon_primary_y[GR_NUM_RESOLUTIONS][2]
Definition: hudtarget.cpp:364
int g3_in_frame()
Definition: 3dsetup.cpp:66
void initBitmapsSecondaryMiddle(char *fname, char *fname_ballistic)
Definition: hudtarget.cpp:5898
hud_frames Toggle_frame
Definition: hudtarget.h:185
void initAlignments(int text_align, int armed_align)
Definition: hudtarget.cpp:5487
#define SUBSYSTEM_SENSORS
Definition: model.h:59
void initBitmaps(char *fname)
Definition: hudtarget.cpp:4700
#define fl2i(fl)
Definition: floating.h:33
hud_frames Toggle_frame
Definition: hudtarget.h:208
void initCountValueOffsets(int x, int y)
Definition: hudtarget.cpp:5364
void initArmedOffsets(int x, int y, int h, bool show)
Definition: hudtarget.cpp:5493
int hud_target_ship_can_be_scanned(ship *shipp)
Definition: hudtarget.cpp:1545
htarget_list htarget_items[MAX_HOTKEY_TARGET_ITEMS]
Definition: hudtarget.cpp:97
player * Player
#define NUM_WEAPON_GAUGES
Definition: hudtarget.cpp:230
int gr_force_fit_string(char *str, int max_str, int max_width)
Definition: font.cpp:48
void hud_target_random_ship()
Definition: hudtarget.cpp:5221
void hud_target_next(int team_mask)
Definition: hudtarget.cpp:1247
#define MC_CHECK_MODEL
Definition: model.h:1169
void hud_targetbox_start_flash(int index, int duration)
GLenum target
Definition: Glext.h:6872
#define g3_end_frame()
Definition: 3d.h:49
ubyte Weapon_link_icon
Definition: hudtarget.h:316
void initBgEntryHeight(int h)
Definition: hudtarget.cpp:6769
#define RETICLE_DEFAULT_DOT
Definition: hudtarget.cpp:588
int Weapon_gauge_primary_coords[NUM_HUD_SETTINGS][GR_NUM_RESOLUTIONS][3][2]
Definition: hudtarget.cpp:235
#define TARGET_DISPLAY_NAME
Definition: hudtarget.h:164
void initSizes(int w, int h)
Definition: hudtarget.cpp:7069
void initSecondaryLinkedOffsetX(int x)
Definition: hudtarget.cpp:6963
#define HUD_WEAPONS_GAUGE
Definition: hudgauges.h:34
int clip_width
Definition: 2d.h:378
screen gr_screen
Definition: 2d.cpp:46
void hud_target_uninspected_cargo(int next_flag)
Definition: hudtarget.cpp:1567
float Min_draw_distance
Definition: 2d.cpp:84
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
#define WIF_BEAM
Definition: weapon.h:76
void initFrameOffsetX(int x, int x_b)
Definition: hudtarget.cpp:5800
void render(float frametime)
Definition: hudtarget.cpp:6255
void hudtarget_page_in()
Definition: hudtarget.cpp:5249
int Cm_text_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudtarget.cpp:200
struct eval_next_turret eval_next_turret
void initBgLastOffsetY(int x)
Definition: hudtarget.cpp:6759
#define NUM_HUD_SETTINGS
Definition: hudtarget.h:47
#define COMM_OK
Definition: subsysdamage.h:52
int ship_get_random_targetable_ship()
Definition: ship.cpp:16876
ship_subsys * locking_subsys
Definition: player.h:176
#define GM_DEAD_BLEW_UP
Definition: systemvars.h:21
void initViewDir(int dir)
Definition: hudtarget.cpp:7080
#define NO_CHANGE
Definition: hudtarget.h:24
ship_obj Ship_obj_list
Definition: ship.cpp:162
int gr_get_font_height()
Definition: font.cpp:187
void hud_keyed_targets_clear()
Definition: hudtarget.cpp:982
int Cmdline_targetinfo
Definition: cmdline.cpp:367
#define AIM_EVADE_WEAPON
Definition: ai.h:180
int ship_info_index
Definition: ship.h:539
#define DECREASING
Definition: hudtarget.h:23
void initBitmapsSecondaryTop(char *fname, char *fname_ballistic)
Definition: hudtarget.cpp:5883
void hud_make_shader(shader *sh, ubyte r, ubyte g, ubyte b, float dimmer=1000.0f)
Definition: hudtarget.cpp:959
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
#define TMAP_FLAG_ALPHA
Definition: tmapper.h:53
void render(float frametime)
Definition: hudtarget.cpp:4217
#define VM_PADLOCK_ANY
Definition: systemvars.h:46
void gr_reset_screen_scale()
Definition: 2d.cpp:176
ship_subsys * last_targeted_subobject[MAX_PLAYERS]
Definition: ship.h:631
#define SIF_FIGHTER
Definition: ship.h:885
void g3_start_instance_matrix(const vec3d *pos, const matrix *orient, bool set_api=true)
Definition: 3dsetup.cpp:249
void initTriBase(float length)
Definition: hudtarget.cpp:2910
#define WIF_HOMING
Definition: weapon.h:129
void renderIndicator(int frame_offset, object *targetp, vec3d *lead_target_pos)
Definition: hudtarget.cpp:3900
#define timestamp_elapsed(stamp)
Definition: timer.h:102
float Hud_unit_multiplier
Definition: hudparse.cpp:40
virtual void render(float frametime)
Definition: hudtarget.cpp:2920
#define OF_SHOULD_BE_DEAD
Definition: object.h:106
void hud_target_toggle_hidden_from_sensors()
Definition: hudtarget.cpp:4920
void initTargetTextOffsets(int x, int y)
Definition: hudtarget.cpp:4694
vec3d * get_subsystem_world_pos(object *parent_obj, ship_subsys *subsys, vec3d *world_pos)
Definition: hudtarget.cpp:4395
#define RETICLE_DEFAULT_DIST
Definition: hudtarget.cpp:587
int Auto_text_offsets[2]
Definition: hudtarget.h:210
color current_color
Definition: 2d.h:396
void render(float frametime)
Definition: hudtarget.cpp:5383
void render(float frametime)
Definition: hudtarget.cpp:3866
#define PI
Definition: pstypes.h:303
GLenum GLenum GLvoid GLvoid * column
Definition: Glext.h:5241
#define MAX_WEAPONS
Definition: globals.h:71
int Game_skill_level
Definition: fredstubs.cpp:170
int ship_is_visible_by_team(object *target, ship *viewer)
Definition: awacs.cpp:442
void hud_maybe_set_sorted_turret_subsys(ship *shipp)
Definition: hudtarget.cpp:490
float HUD_offset_x
Definition: hud.cpp:90
void initEntryHeight(int h)
Definition: hudtarget.cpp:6790
#define RL_USE_DOT
Definition: hudtarget.cpp:127
#define TBOX_FLASH_INTERVAL
Definition: hudtargetbox.h:22
int model_instance_num
Definition: model.h:1109
int Iff_traitor
Definition: iff_defs.cpp:22
int n_guns
Definition: model.h:768
void renderPrintf(int x, int y, const char *format,...)
Definition: hud.cpp:724
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
GLenum GLuint GLenum GLsizei length
Definition: Glext.h:5156
void hud_stuff_ship_class(char *ship_class_text, ship *shipp)
Definition: hudtarget.cpp:5325
int model_num
Definition: weapon.h:329
#define i2fl(i)
Definition: floating.h:32
void hud_target_next_subobject()
Definition: hudtarget.cpp:1147
void render(float frametime)
Definition: hudtarget.cpp:6973
#define PF_PROJECTED
Definition: 3d.h:21
void hud_init_artillery()
void vm_vec_scale_sub2(vec3d *dest, const vec3d *src, float k)
Definition: vecmat.cpp:293
#define GR_STENCIL_READ
Definition: 2d.h:678
bool draw_secondary_models[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:1303
int turret_attacking_target
Definition: hudtarget.h:83
GLint GLsizei count
Definition: Gl.h:1491
void hud_update_weapon_flash()
Definition: hudtarget.cpp:6152
int attacked_objnum
Definition: hudtarget.h:81
float energy_consumed
Definition: weapon.h:383
void hud_shield_hit_reset(object *objp, int player)
Definition: hudshield.cpp:497
#define MAX_WEAPON_FLASH_LINES
Definition: hudtarget.cpp:430
matrix * A
Definition: lua.cpp:444
const float PI_2
Definition: pstypes.h:307
#define TYPE_FACING_LASER
Definition: hudtarget.cpp:1685
object * Player_obj
Definition: object.cpp:56
int frame_offset_x[NUM_HUD_SETTINGS]
Definition: hudtarget.h:301
#define EG_WEAPON_P2
Definition: emp.h:32
struct homing_beep_info homing_beep_info
matrix View_matrix
Definition: 3dsetup.cpp:19
void hud_init_missile_lock()
Definition: hudlock.cpp:97
#define AIM_AVOID
Definition: ai.h:172
#define SF_CARGO_REVEALED
Definition: ship.h:456
void hud_restore_subsystem_target(ship *shipp)
Definition: hudtarget.cpp:4379
void hud_target_missile(object *source_obj, int next_flag)
Definition: hudtarget.cpp:1425
uint flags2
Definition: ship.h:645
int locking_on_center
Definition: player.h:178
int Hud_target_h
Definition: hudtarget.cpp:52
#define SF_DYING
Definition: ship.h:447
vec3d world
Definition: pstypes.h:172
void hud_target_last_transmit_level_init()
Definition: hudtarget.cpp:5099
int temp
Definition: lua.cpp:4996
void initBitmapsPrimaryMiddle(char *fname, char *fname_ballistic)
Definition: hudtarget.cpp:5855
#define IFFF_WING_NAME_HIDDEN
Definition: iff_defs.h:29
int Weapon_sammo_offset_x
Definition: hudtarget.h:311
int goal_objnum
Definition: ai.h:355
void hud_target_closest_uninspected_object()
Definition: hudtarget.cpp:4932
int emp_active_local()
Definition: emp.cpp:428
#define WIF2_BALLISTIC
Definition: weapon.h:84
polymodel * pm
Definition: lua.cpp:1598
void gr_create_shader(shader *shade, ubyte r, ubyte g, ubyte b, ubyte c)
Definition: 2d.cpp:1211
#define TBOX_FLASH_NAME
Definition: hudtargetbox.h:26
int flash_next[MAX_WEAPON_FLASH_LINES]
Definition: hudtarget.cpp:434
bool gr_unsize_screen_posf(float *x, float *y, float *w, float *h, int resize_mode)
Definition: 2d.cpp:538
float closeup_zoom
Definition: ship.h:1328
float HUD_offset_y
Definition: hud.cpp:91
htarget_list keyed_targets[MAX_KEYED_TARGETS]
Definition: player.h:107
#define VM_OTHER_SHIP
Definition: systemvars.h:35
int current_target_dist_trend
Definition: ai.h:491
ubyte Weapon_link_icon
Definition: hudtarget.h:356
int iff_matches_mask(int team, int mask)
Definition: iff_defs.cpp:628
#define SF2_PRIMITIVE_SENSORS
Definition: ship.h:483
float hud_find_target_distance(object *targetee, object *targeter)
Definition: hudtarget.cpp:2009
void initBitmaps(char *fname_first, char *fname_entry, char *fname_last)
Definition: hudtarget.cpp:6726
int primary_bank_start_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:122
#define HUD_OBJECT_WEAPON_ENERGY
Definition: hudparse.h:154
uint create_time
Definition: ship.h:701
missile_obj * advance_missile_obj(missile_obj *mo, int next_flag)
Definition: hudtarget.cpp:1260
#define WIF3_NOLINK
Definition: weapon.h:117
void render(float frametime)
Definition: hudtarget.cpp:3159
ubyte codes
Definition: pstypes.h:177
float vel_inherit_amount
Definition: weapon.h:356
#define HUD_OBJECT_WARHEAD_COUNT
Definition: hudparse.h:223
#define GM_NORMAL
Definition: systemvars.h:19
#define TARGET_DISPLAY_LEAD
Definition: hudtarget.h:162
#define gr_zbuffer_get
Definition: 2d.h:816
false
Definition: lua.cpp:6789
#define SF2_STEALTH
Definition: ship.h:485
void hud_tri(float x1, float y1, float x2, float y2, float x3, float y3)
Definition: hudtarget.cpp:2803
uint flags
Definition: object.h:151
color Color_bright_blue
Definition: alphacolors.cpp:31
int Weapon_sname_offset_x
Definition: hudtarget.h:312
float radius
Definition: object.h:154
char alt_name[NAME_LENGTH]
Definition: weapon.h:323
void snd_stop(int sig)
Definition: sound.cpp:875
void hud_stuff_ship_callsign(char *ship_callsign_text, ship *shipp)
Definition: hudtarget.cpp:5290
int hud_target_invalid_awacs(object *objp)
Definition: hudtarget.cpp:460
mission The_mission
missile_obj Missile_obj_list
Definition: weapons.cpp:84
void initMaxFrontSeperation(float length)
Definition: hudtarget.cpp:6236
void hud_targetbox_init_flash()
void hud_init_targeting()
Definition: hudtarget.cpp:1038
void initCountOffsets(int x, int y)
Definition: hudtarget.cpp:6595
void initBitmaps(char *fname)
Definition: hudtarget.cpp:3816
void hud_cease_subsystem_targeting(int print_message)
Definition: hudtarget.cpp:4346
int turret_enemy_objnum
Definition: ship.h:337
int model_num
Definition: lua.cpp:4996
GLclampf GLclampf GLclampf alpha
Definition: Glext.h:5177
void set_object_number(int num)
#define HUD_CMEASURE_GAUGE
Definition: hudgauges.h:47
char type
Definition: object.h:146
void hud_init_targeting_colors()
Definition: hudtarget.cpp:973
float Max_front_seperation
Definition: hudtarget.h:526
void hud_init_brackets()
Definition: hudbrackets.cpp:44
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
void initTriHeight(float h)
Definition: hudtarget.cpp:2915
struct transmit_target transmit_target
void initHeaderOffsets(int x, int y, int x_b, int y_b)
Definition: hudtarget.cpp:5792
#define HUD_AUTO_SPEED
Definition: hudgauges.h:33
void renderOffscreenIndicator(vec2d *coords, int dir, float distance, float half_triangle_sep, bool draw_solid=true)
Definition: hudtarget.cpp:6458
int pickFrame(float prange, float srange, float dist_to_target)
Definition: hudtarget.cpp:3840
#define FALSE
Definition: pstypes.h:400
void clip_line(vertex **p0, vertex **p1, ubyte codes_or, uint flags)
Clips a line to the viewing pyramid.
Definition: 3dclipper.cpp:197
void render(float frametime)
Definition: hudtarget.cpp:3206
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
#define wp(p)
Definition: modelsinc.h:69
#define MIN_SENSOR_STR_TO_TARGET
Definition: subsysdamage.h:34
char * Cargo_names[]
hud_frames primary_last[NUM_HUD_SETTINGS]
Definition: hudtarget.h:298
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
SCP_vector< asteroid_info > Asteroid_info
Definition: asteroid.cpp:62
void hud_cargo_scan_update(object *targetp, float frametime)
void lcl_translate_wep_name_gr(char *name)
Definition: localize.cpp:1134
#define HUD_C_DIM
Definition: hud.h:163
htarget_list htarget_free_list
Definition: hudtarget.cpp:98
void render(float frametime)
Definition: hudtarget.cpp:3666
#define MR_NO_FOGGING
Definition: model.h:884
void hud_set_iff_color(object *objp, int is_bright)
Will set the color to the IFF color based on the team.
Definition: hud.cpp:2950
matrix * orient
Definition: model.h:1112
int Weapon_secondary_y[GR_NUM_RESOLUTIONS][3]
Definition: hudtarget.cpp:352
#define stricmp(s1, s2)
Definition: config.h:271
#define OBJ_JUMP_NODE
Definition: object.h:45
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:159
void initSecondaryUnlinkedOffsetX(int x)
Definition: hudtarget.cpp:6968
void gr_init_color(color *c, int r, int g, int b)
Definition: 2d.cpp:1155
matrix vmd_identity_matrix
Definition: vecmat.cpp:28
int locking_subsys_parent
Definition: player.h:177
int Cmdline_ballistic_gauge
Definition: cmdline.cpp:363
void initLineWidth(float w)
Definition: hudtarget.cpp:7075
int cmeasure_count
Definition: ship.h:651
int Weapon_sunlinked_x[GR_NUM_RESOLUTIONS]
Definition: hudtarget.cpp:348
int parent_sig
Definition: object.h:148
void render(float frametime)
Definition: hudtarget.cpp:6856
char ship_name[NAME_LENGTH]
Definition: ship.h:604
void hud_init_ballistic_index()
Definition: hudtarget.cpp:1019
ship_subsys * set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int parent_objnum)
Definition: aicode.cpp:1289
void lcl_translate_targetbox_name_pl(char *name)
Definition: localize.cpp:1453
float model_find_closest_point(vec3d *outpnt, int model_num, int submodel_num, matrix *orient, vec3d *pos, vec3d *eye_pos)
int g3_draw_poly_constant_sw(int nv, vertex **pointlist, uint tmap_flags, float constant_sw)
Definition: 3ddraw.cpp:381
#define HUD_OBJECT_SECONDARY_WEAPONS
Definition: hudparse.h:232
#define IFF_COLOR_SELECTION
Definition: iff_defs.h:19
void initNameOffsets(int x, int y)
Definition: hudtarget.cpp:6589
void hud_artillery_update()
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: Glext.h:6566
void hud_process_remote_detonate_missile()
Definition: hudtarget.cpp:3224
float Lead_indicator_half[NUM_HUD_RETICLE_STYLES][GR_NUM_RESOLUTIONS][2]
Definition: hudtarget.cpp:157
SCP_vector< ship_type_info > Ship_types
Definition: ship.cpp:168
int Lcl_gr
Definition: localize.cpp:48
hud_frames _background_first
Definition: hudtarget.h:353
#define TARGET_IN_RETICLE_DISTANCE
Definition: hudtarget.cpp:2481
void hud_save_restore_camera_data(int save)
Called to save and restore the 3D camera settings.
Definition: hud.cpp:3656
void hud_process_homing_missiles()
Definition: hudtarget.cpp:3098
#define AIM_STRAFE
Definition: ai.h:181
GLuint GLuint end
Definition: Gl.h:1502
void hud_target_common(int team_mask, int next_flag)
Definition: hudtarget.cpp:1158
#define HUD_OBJECT_PRIMARY_WEAPONS
Definition: hudparse.h:229
ubyte r
Definition: pstypes.h:175
GLint y
Definition: Gl.h:1505
float secondary_point_reload_pct[MAX_SHIP_SECONDARY_BANKS][MAX_SLOTS]
Definition: ship.h:784
void initMaxColumns(int count)
Definition: hudtarget.cpp:6612
void initHeaderOffsets(int x, int y)
Definition: hudtarget.cpp:6779
void hud_show_message_sender()
Definition: hudtarget.cpp:3265
#define gr_stencil_clear
Definition: 2d.h:821
int Armed_name_offsets[2]
Definition: hudtarget.h:267
void renderCircle(int x, int y, int diameter)
Definition: hud.cpp:919
Definition: 2d.h:358
#define g3_start_frame(zbuffer_flag)
Definition: 3d.h:39
bool evaluate_ship_as_closest_target(esct *esct_p)
evaluate a ship (and maybe turrets) as a potential target
Definition: hudtarget.cpp:2069
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
float Lead_indicator_half[2]
Definition: hudtarget.h:545
int Player_num
#define strcpy_s(...)
Definition: safe_strings.h:67
object * advance_fb(object *objp, int next_flag)
Definition: hudtarget.cpp:1131
int hud_image_index
Definition: weapon.h:344
void renderBitmap(int x, int y)
Definition: hud.cpp:782
int lead_indicator_active
Definition: player.h:112
float Max_offscreen_tri_seperation
Definition: hudtarget.h:525
void hud_maybe_flash_weapon(int index)
Definition: hudtarget.cpp:4550
#define NUM_HUD_RETICLE_STYLES
Definition: hudparse.h:17
#define MR_AUTOCENTER
Definition: model.h:875
void initOffColor(int r, int g, int b, int a)
Definition: hudtarget.cpp:4806