FS2_Open
Open source remastering of the Freespace 2 engine
missionbriefcommon.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 "anim/animplay.h"
14 #include "gamesnd/gamesnd.h"
15 #include "globalincs/alphacolors.h"
16 #include "globalincs/linklist.h"
17 #include "iff_defs/iff_defs.h"
18 #include "io/mouse.h"
19 #include "io/timer.h"
20 #include "localization/localize.h"
21 #include "math/fvi.h"
23 #include "mission/missiongrid.h"
24 #include "mission/missionparse.h"
25 #include "missionui/missionbrief.h"
28 #include "mod_table/mod_table.h"
29 #include "parse/parselo.h"
30 #include "playerman/player.h"
31 #include "render/3d.h"
32 #include "ship/ship.h"
33 #include "sound/audiostr.h"
34 #include "sound/fsspeech.h"
36 
37 
38 // --------------------------------------------------------------------------------------
39 // briefing screen
40 // --------------------------------------------------------------------------------------
41 
43 
44 // briefing screen sections
45 #define BRIEF_CUP_X1 400
46 #define BRIEF_CUP_Y1 70
47 #define BRIEF_CUP_X2 639
48 #define BRIEF_CUP_Y2 245
49 #define BRIEF_CUPINFO_X1 445
50 #define BRIEF_CUPINFO_Y1 247
51 #define BRIEF_CUPINFO_X2 639
52 #define BRIEF_CUPINFO_Y2 438
53 
55  "BriefMap",
56  "2_BriefMap"
57 };
58 
60  { // GR_640
61  10, 130
62  },
63  { // GR_1024
64  15, 208
65  }
66 };
67 
69  { // GR_640
70  0, 115
71  },
72  { // GR_1024
73  0, 184
74  }
75 };
76 
78  { // GR_640
79  19, 147, 555, 232
80  },
81  { // GR_1024
82  30, 235, 888, 371
83  }
84 };
85 
87  { // GR_640
88  28, 399, 395, 74
89  },
90  { // GR_1024
91  46, 637, 630, 120
92  }
93 };
94 
96  { // GR_640
97  138, 117
98  },
99  { // GR_1024
100  227, 194
101  }
102 };
103 
105  { // GR_640
106  479, 385
107  },
108  { // GR_1024
109  821, 616
110  }
111 };
112 
114  8, 13
115 };
116 
117 #define LOOKAT_DIST 500.0f
118 #define STAGE_ADVANCE_DELAY 1000 // time in ms to wait after voice stops before advancing stage
119 
120 extern const float BRIEF_TEXT_WIPE_TIME = 1.5f; // time in seconds for wipe to occur
121 
122 // --------------------------------------------------------------------------------------
123 // Game-wide global data
124 // --------------------------------------------------------------------------------------
125 briefing Briefings[MAX_TVT_TEAMS]; // there is exactly one briefing per mission
126 debriefing Debriefings[MAX_TVT_TEAMS]; // there can be multiple debriefings per mission
127 briefing *Briefing; // pointer used in code -- points to correct briefing
128 debriefing *Debriefing; // pointer to correct debriefing
129 
130 int Briefing_voice_enabled=1; // flag which turn on/off voice playback of briefings/debriefings
131 
132 // --------------------------------------------------------------------------------------
133 // Module global data
134 // --------------------------------------------------------------------------------------
135 
136 static int Last_new_stage;
138 
139 const char BRIEF_META_CHAR = '$';
140 
142 
143 // camera related
144 static vec3d Current_cam_pos; // current camera position
145 static vec3d Target_cam_pos; // desired camera position
146 static matrix Current_cam_orient; // current camera orientation
147 static matrix Target_cam_orient; // desired camera orientation
148 static matrix Start_cam_orient; // start camera orientation
149 static vec3d Start_cam_pos; // position of camera at the start of a translation
150 static vec3d Cam_vel; // camera velocity
151 static vec3d Current_lookat_pos; // lookat point
152 static vec3d Target_lookat_pos; // lookat point
153 static vec3d Start_lookat_pos;
154 static vec3d Lookat_vel; // lookat point velocity
155 
156 static float Start_cam_move; // time at which camera started moving (seconds)
157 static float Total_move_time; // time in which camera should move from current pos to target pos (seconds)
158 static float Elapsed_time;
159 
160 static float Start_dist;
161 static float End_dist;
162 static float Dist_change_rate;
163 
164 static vec3d Acc_limit;
165 static vec3d Vel_limit;
166 
167 static float Total_dist;
168 static float Peak_speed;
169 static float Cam_accel;
170 static float Last_dist;
171 static vec3d W_init;
172 
173 // flag to indicate that the sound for a spinning highlight animation has played
174 static int Brief_stage_highlight_sound_handle = -1;
175 
176 // used for scrolling briefing text ( if necessary )
179 
180 // Used to support drawing colored text for the briefing. Gets complicates since we
181 // need to be able to draw one character at a time as well when the briefing text
182 // first appears.
183 typedef struct colored_char
184 {
185  char letter;
186  char color; // tag to look up in Tagged_Colors
187 } colored_char;
188 
191 static briefing_stream Colored_stream[MAX_TEXT_STREAMS];
192 
193 #define BRIGHTEN_LEAD 2
194 
196 static int Max_briefing_line_len;
197 
198 static int Voice_started_time;
199 static int Voice_ended_time;
200 
201 static int Brief_text_wipe_snd; // sound handle of sound effect for text wipe
202 static int Play_brief_voice;
203 
204 // animation stuff
205 static int Play_highlight_flag;
206 static int Cam_target_reached;
207 static int Cam_movement_done;
208 
209 // moving icons
210 typedef struct icon_move_info
211 {
213  int used;
214  int id;
218 
219  // used to move icons smoothly
221  float total_dist;
222  float accel;
224  float peak_speed;
226  float last_dist;
228 
229 #define MAX_MOVING_ICONS MAX_STAGE_ICONS
230 
232 icon_move_info Icon_move_list; // head of linked list
233 
234 // fading out icons
235 typedef struct icon_fade_info
236 {
239  int team;
240 } fade_icon;
241 
242 #define MAX_FADING_ICONS MAX_STAGE_ICONS
243 
246 
247 // voice id's for briefing text
249 
252 
254 
255 // --------------------------------------------------------------------------------------
256 // forward declarations
257 // --------------------------------------------------------------------------------------
258 void brief_render_elements(vec3d *pos, grid *gridp);
259 void brief_render_icons(int stage_num, float frametime);
260 void brief_grid_read_camera_controls( control_info * ci, float frametime );
261 void brief_maybe_create_new_grid(grid *gridp, vec3d *pos, matrix *orient, int force = 0);
262 grid *brief_create_grid(grid *gridp, vec3d *forward, vec3d *right, vec3d *center, int nrows, int ncols, float square_size);
264 void brief_render_grid(grid *gridp);
265 void brief_modify_grid(grid *gridp);
266 void brief_rpd_line(vec3d *v0, vec3d *v1);
267 void brief_set_text_color(char color_tag);
268 extern void get_camera_limits(const matrix *start_camera, const matrix *end_camera, float time, vec3d *acc_max, vec3d *w_max);
270 
271 // --------------------------------------------------------------------------------------
272 // brief_parse_icon_tbl()
273 //
274 //
276 {
277  int icon;
278  size_t species;
279  char name[MAX_FILENAME_LEN];
280 
281  Assert(!Species_info.empty());
282  const size_t max_icons = Species_info.size() * MIN_BRIEF_ICONS;
283 
284  try
285  {
286  read_file_text("icons.tbl", CF_TYPE_TABLES);
287  reset_parse();
288 
289  required_string("#Start");
290 
291  Briefing_icon_info.clear();
292  while (required_string_either("#End", "$Name:"))
293  {
294  if (Briefing_icon_info.size() >= max_icons) {
295  Warning(LOCATION, "Too many icons in icons.tbl; only the first " SIZE_T_ARG " will be used", max_icons);
296  skip_to_start_of_string("#End");
297  break;
298  }
299 
300  briefing_icon_info bii;
301 
302  // parse regular frames
303  required_string("$Name:");
305  generic_anim_init(&bii.regular, name);
306 
307  // parse fade frames
308  required_string("$Name:");
310  hud_anim_init(&bii.fade, 0, 0, name);
311 
312  // parse highlighting frames
313  required_string("$Name:");
315  hud_anim_init(&bii.highlight, 0, 0, name);
316 
317  // add it to the collection
318  Briefing_icon_info.push_back(bii);
319  }
320  required_string("#End");
321 
322 
323  // now assign the icons to their species
324  const size_t num_species_covered = Briefing_icon_info.size() / MIN_BRIEF_ICONS;
325  size_t bii_index = 0;
326  for (icon = 0; icon < MIN_BRIEF_ICONS; icon++)
327  {
328  for (species = 0; species < num_species_covered; species++)
329  Species_info[species].bii_index[icon] = bii_index++;
330  }
331 
332  // error check
333  if (num_species_covered < Species_info.size())
334  {
335  SCP_string errormsg = "The following species are missing icon info in icons.tbl:\n";
336 
337  for (species = num_species_covered; species < Species_info.size(); species++)
338  {
339  errormsg += Species_info[species].species_name;
340  errormsg += "\n";
341  }
342 
343  Error(LOCATION, "%s", errormsg.c_str());
344  }
345  }
346  catch (const parse::ParseException& e)
347  {
348  mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "icons.tbl", e.what()));
349  }
350 }
351 
353 {
355 }
356 
357 // --------------------------------------------------------------------------------------
358 // brief_move_icon_reset()
359 //
360 //
362 {
363  int i;
364 
365  list_init(&Icon_move_list);
366  for ( i = 0; i < MAX_MOVING_ICONS; i++ )
367  Icon_movers[i].used = 0;
368 }
369 
370 
376 {
377  int i,j;
378 
379  // setup brief text colors
380  gr_init_alphacolor( &Brief_color_green, 50, 100, 50, 255 );
381  gr_init_alphacolor( &Brief_color_red, 140, 20, 20, 255 );
383 
384  // extra catch to reset everything that's already loaded - taylor
387 
388  if ( Fred_running ) {
389  // If Fred is running malloc out max space
390  for (i = 0; i < MAX_TVT_TEAMS; i++) {
391  for (j = 0; j < MAX_BRIEF_STAGES; j++) {
392  Briefings[i].stages[j].text = "";
393 
394  if (Briefings[i].stages[j].icons == NULL) {
395  Briefings[i].stages[j].icons = (brief_icon *)vm_malloc(sizeof(brief_icon) * MAX_STAGE_ICONS);
396  Assert( Briefings[i].stages[j].icons != NULL );
397  memset( Briefings[i].stages[j].icons, 0, sizeof(brief_icon) * MAX_STAGE_ICONS );
398  }
399 
400  if (Briefings[i].stages[j].lines == NULL) {
401  Briefings[i].stages[j].lines = (brief_line *)vm_malloc(sizeof(brief_line) * MAX_BRIEF_STAGE_LINES);
402  Assert( Briefings[i].stages[j].lines != NULL );
403  memset( Briefings[i].stages[j].lines, 0, sizeof(brief_line) * MAX_BRIEF_STAGE_LINES );
404  }
405 
406  Briefings[i].stages[j].num_icons = 0;
407  Briefings[i].stages[j].num_lines = 0;
408  }
409  }
410 
411  for (i = 0; i < MAX_TVT_TEAMS; i++) {
412  for (j = 0; j < MAX_DEBRIEF_STAGES; j++) {
413  Debriefings[i].stages[j].text = "";
414  Debriefings[i].stages[j].recommendation_text = "";
415  }
416  }
417 
418  } else {
419  // If game is running don't malloc anything
420  for (i=0; i<MAX_TVT_TEAMS; i++ ) {
421  for (j=0; j<MAX_BRIEF_STAGES; j++ ) {
422  Briefings[i].stages[j].text = "";
423  Briefings[i].stages[j].num_icons = 0;
424  Briefings[i].stages[j].icons = NULL;
425  Briefings[i].stages[j].num_lines = 0;
426  Briefings[i].stages[j].lines = NULL;
427  }
428  }
429 
430  for (i=0; i<MAX_TVT_TEAMS; i++ ) {
431  for (j=0; j<MAX_DEBRIEF_STAGES; j++ ) {
432  Debriefings[i].stages[j].text = "";
433  Debriefings[i].stages[j].recommendation_text = "";
434  }
435  }
436 
437  }
438 }
439 
444 {
445  int i, j;
446 
447  for (i = 0; i < MAX_TVT_TEAMS; i++) {
448  Briefings[i].num_stages = 0;
449 
450  for (j = 0; j < MAX_BRIEF_STAGES; j++) {
451  Briefings[i].stages[j].num_icons = 0;
452  Briefings[i].stages[j].num_lines = 0;
453  Briefings[i].stages[j].text = "";
454 
455  if (Fred_running) {
456  if ( Briefings[i].stages[j].icons ) {
457  memset( Briefings[i].stages[j].icons, 0, sizeof(brief_icon) * MAX_STAGE_ICONS );
458  Briefings[i].stages[j].icons->ship_class = -1;
459  Briefings[i].stages[j].icons->modelnum = -1;
460  Briefings[i].stages[j].icons->bitmap_id = -1;
461  }
462 
463  if ( Briefings[i].stages[j].lines )
464  memset( Briefings[i].stages[j].lines, 0, sizeof(brief_line) * MAX_BRIEF_STAGE_LINES );
465  } else {
466  if ( Briefings[i].stages[j].icons ) {
467  vm_free(Briefings[i].stages[j].icons);
468  Briefings[i].stages[j].icons = NULL;
469  }
470 
471  if ( Briefings[i].stages[j].lines ) {
472  vm_free(Briefings[i].stages[j].lines);
473  Briefings[i].stages[j].lines = NULL;
474  }
475  }
476  }
477  }
478 }
479 
485 {
486  int i, j;
487 
488  for (i = 0; i < MAX_TVT_TEAMS; i++) {
489  Debriefings[i].num_stages = 0;
490 
491  for (j = 0; j < MAX_DEBRIEF_STAGES; j++) {
492  Debriefings[i].stages[j].text = "";
493  Debriefings[i].stages[j].recommendation_text = "";
494  }
495  }
496 }
497 
498 
499 
500 
501 // --------------------------------------------------------------------------------------
502 // brief_reset()
503 //
504 //
506 {
508 
509  Briefing = NULL;
510  Cur_brief_id = 1;
511 }
512 
513 // --------------------------------------------------------------------------------------
514 // debrief_reset()
515 //
516 //
518 {
520 
521  Debriefing = NULL;
522 
523  // MWA 4/27/98 -- must initialize this variable here since we cannot do it as debrief
524  // init time because race conditions between all players in the game make that type of
525  // initialization unsafe.
527 }
528 
532 void brief_init_screen(int multiplayer_flag)
533 {
534  bscreen.map_x1 = Brief_grid_coords[gr_screen.res][0];
536  bscreen.map_y1 = Brief_grid_coords[gr_screen.res][1];
537  bscreen.map_y2 = Brief_grid_coords[gr_screen.res][1] + Brief_grid_coords[gr_screen.res][3];
538 }
539 
540 // --------------------------------------------------------------------------------------
541 // brief_init_colors()
542 //
543 //
545 {
546 }
547 
549 {
550  if (bi->ship_class < 0)
551  return NULL;
552  ship_info *sip = &Ship_info[bi->ship_class];
553 
554  // ship info might override the usual briefing icon
555  if (sip->bii_index_ship >= 0)
556  {
557  if (bi->flags & BI_USE_WING_ICON)
558  {
559  if (bi->flags & BI_USE_CARGO_ICON)
560  {
561  if (sip->bii_index_wing_with_cargo >= 0)
562  return &Briefing_icon_info[sip->bii_index_wing_with_cargo];
563  else
564  mprintf(("Ship '%s' is missing the wing-with-cargo briefing icon!", sip->name));
565  }
566  else
567  {
568  if (sip->bii_index_wing >= 0)
569  return &Briefing_icon_info[sip->bii_index_wing];
570  else
571  mprintf(("Ship '%s' is missing the wing briefing icon!", sip->name));
572  }
573  }
574  else
575  {
576  if (bi->flags & BI_USE_CARGO_ICON)
577  {
578  if (sip->bii_index_ship_with_cargo >= 0)
579  return &Briefing_icon_info[sip->bii_index_ship_with_cargo];
580  else
581  mprintf(("Ship '%s' is missing the ship-with-cargo briefing icon!", sip->name));
582  }
583  }
584 
585  // this will be reached if we just want the plain ship icon, or if we specified icon modifiers which didn't exist
586  return &Briefing_icon_info[sip->bii_index_ship];
587  }
588 
589  if (sip->species < 0)
590  return NULL;
591 
592  int bii_index = Species_info[sip->species].bii_index[bi->type];
593  if (bii_index < 0)
594  return NULL;
595 
596  return &Briefing_icon_info[bii_index];
597 }
598 
600 {
602  if (bii == NULL)
603  return;
604 
605  generic_anim *ga = &bii->regular;
606  if ( !stricmp(NOX("none"), ga->filename) )
607  return;
608 
609  // force read of data from disk, so we don't glitch on initial playback
610  if ( ga->first_frame == -1 ) {
612  Assert(ga->first_frame >= 0);
613  }
614 }
615 
617 {
619  if (bii == NULL)
620  return;
621 
622  hud_anim *ha = &bii->fade;
623  if ( !stricmp(NOX("none"), ha->filename) )
624  return;
625 
626  // force read of data from disk, so we don't glitch on initial playback
627  if ( ha->first_frame == -1 ) {
628  hud_anim_load(ha);
629  Assert(ha->first_frame >= 0);
630  }
631 
633  gr_aabitmap(0, 0);
634 }
635 
637 {
639  if (bii == NULL)
640  return;
641 
642  hud_anim *ha = &bii->highlight;
643  if ( !stricmp(NOX("none"), ha->filename) )
644  return;
645 
646  // force read of data from disk, so we don't glitch on initial playback
647  if ( ha->first_frame == -1 ) {
648  hud_anim_load(ha);
649  Assert(ha->first_frame >= 0);
650  }
651 
652  bi->highlight_anim = *ha;
653 
655  gr_aabitmap(0, 0);
656 }
657 
662 {
663  int num_icons, num_stages, i, j;
664  brief_icon *bi;
665 
666  num_stages = Briefing->num_stages;
667 
668  for ( i = 0; i < num_stages; i++ ) {
669  num_icons = Briefing->stages[i].num_icons;
670  for ( j = 0; j < num_icons; j++ ) {
671  bi = &Briefing->stages[i].icons[j];
672 
675  if ( bi->flags & BI_HIGHLIGHT ) {
677  }
678  }
679  }
680 }
681 
682 // --------------------------------------------------------------------------------------
683 // brief_init_map()
684 //
685 //
687 {
688  vec3d *pos;
689  matrix *orient;
690 
691  Assert( Briefing != NULL );
692 
693  pos = &Briefing->stages[0].camera_pos;
694  orient = &Briefing->stages[0].camera_orient;
695  vm_vec_zero(&Current_lookat_pos);
696  vm_vec_zero(&Target_lookat_pos);
697  Elapsed_time = 0.0f;
698  Total_move_time = 0.0f;
699 
701  brief_maybe_create_new_grid(The_grid, pos, orient, 1);
702 
705 
707 
708  Brief_text_wipe_snd = -1;
709  Last_new_stage = -1;
710  Num_fade_icons=0;
711 }
712 
713 #ifdef _MSC_VER
714 #pragma optimize("", off)
715 #endif
716 
717 void brief_render_fade_outs(float frametime)
718 {
719  int i,bx,by,w,h;
720  float bxf,byf;
721  vertex tv; // temp vertex used to find screen position for text
722  fade_icon *fi;
723 
724 
725  for (i=0; i<Num_fade_icons; i++) {
726  fi = &Fading_icons[i];
727 
728  g3_rotate_vertex(&tv, &fi->pos);
729 
730  if (!(tv.flags & PF_PROJECTED))
731  g3_project_vertex(&tv);
732 
733  if (!(tv.flags & PF_OVERFLOW) ) { // make sure point projected before drawing text
734 
736 
737  if ( fi->fade_anim.first_frame < 0 ) {
738  continue;
739  }
740 
741  bm_get_info( fi->fade_anim.first_frame, &w, &h, NULL);
742  float screenX = tv.screen.xyw.x;
743  float screenY = tv.screen.xyw.y;
744  gr_unsize_screen_posf( &screenX, &screenY, NULL, NULL, GR_RESIZE_MENU_NO_OFFSET );
745 
746  bxf = screenX - w / 2.0f + 0.5f;
747  byf = screenY - h / 2.0f + 0.5f;
748  bx = fl2i(bxf);
749  by = fl2i(byf);
750 
751  if ( fi->fade_anim.first_frame >= 0 ) {
752  fi->fade_anim.sx = bx;
753  fi->fade_anim.sy = by;
754  hud_anim_render(&fi->fade_anim, frametime, 1, 0, 0, 0, GR_RESIZE_MENU);
755  }
756  }
757  }
758 }
759 
763 float brief_icon_get_dist_moved(icon_move_info *mi, float elapsed_time)
764 {
765  float time, dist_moved=0.0f;
766 
767  // first half of movement
768  if ( elapsed_time < mi->total_move_time/2.0f ) {
769  dist_moved=0.5f*mi->accel*elapsed_time*elapsed_time; // d = 1/2at^2
770  return dist_moved;
771  }
772 
773  // second half of movement
774  time=elapsed_time - mi->total_move_time/2.0f;
775  dist_moved=(mi->total_dist/2.0f)+(mi->peak_speed*time) - 0.5f*mi->accel*time*time;
776  return dist_moved;
777 }
778 
782 void brief_render_icon_line(int stage_num, int line_num)
783 {
784  brief_line *bl;
785  brief_stage *bs;
786  brief_icon *icon[2];
787  int i;
788  vertex icon_vertex[2];
789  int icon_status[2] = {0,0};
790  int icon_w, icon_h;
791  float icon_x[2], icon_y[2];
792 
793  bl = &Briefing->stages[stage_num].lines[line_num];
794  bs = &Briefing->stages[stage_num];
795 
796  if(bl->start_icon < 0 || bl->start_icon >= bs->num_icons)
797  {
798  Warning(LOCATION, "Start icon (%d/%d) missing for line %d in briefing stage %d", bl->start_icon, bs->num_icons, line_num, stage_num);
799  //Remove line
800  bs->num_lines--;
801  for(i = line_num; i < bs->num_lines; i++)
802  bs->lines[i] = bs->lines[i+1];
803  return;
804  }
805  if(bl->end_icon < 0 || bl->end_icon >= Briefing->stages[stage_num].num_icons)
806  {
807  Warning(LOCATION, "End icon (%d/%d) missing for line %d in briefing stage %d", bl->end_icon, bs->num_icons, line_num, stage_num);
808  //Remove line
809  bs->num_lines--;
810  for(i = line_num; i < bs->num_lines; i++)
811  bs->lines[i] = bs->lines[i+1];
812  return;
813  }
814 
815  icon[0] = &Briefing->stages[stage_num].icons[bl->start_icon];
816  icon[1] = &Briefing->stages[stage_num].icons[bl->end_icon];
817 
818  // project icons
819  for (i=0; i<2; i++) {
820  g3_rotate_vertex(&icon_vertex[i],&icon[i]->pos);
821  if (!(icon_vertex[i].flags&PF_PROJECTED))
822  g3_project_vertex(&icon_vertex[i]);
823 
824  if (!(icon_vertex[i].flags & PF_OVERFLOW) ) { // make sure point projected before drawing text
825  icon_status[i]=1;
826  }
827  }
828 
829  if ( !icon_status[0] || !icon_status[1] ) {
830  return;
831  }
832 
833  // get screen (x,y) for icons
834  for (i=0; i<2; i++) {
835  brief_common_get_icon_dimensions(&icon_w, &icon_h, icon[i]);
836  icon_x[i] = icon_vertex[i].screen.xyw.x;
837  icon_y[i] = icon_vertex[i].screen.xyw.y;
838  }
839 
840  brief_set_icon_color(icon[0]->team);
841 
842  gr_line(fl2i(icon_x[0]), fl2i(icon_y[0]), fl2i(icon_x[1]), fl2i(icon_y[1]), GR_RESIZE_NONE);
843 }
844 
855 void brief_render_icon(int stage_num, int icon_num, float frametime, int selected, float w_scale_factor, float h_scale_factor)
856 {
857  brief_icon *bi, *closeup_icon;
858  generic_anim *ga;
859  vertex tv; // temp vertex used to find screen position for text
860  vec3d *pos = NULL;
861  int bx,by,bc,w,h,icon_w,icon_h,icon_bitmap=-1;
862  float bxf, byf, dist=0.0f;
863  bool mirror_icon;
864 
865  Assert( Briefing != NULL );
866 
867  bi = &Briefing->stages[stage_num].icons[icon_num];
868  mirror_icon = (bi->flags & BI_MIRROR_ICON)? true:false;
869 
870  icon_move_info *mi, *next;
871  int interp_pos_found = 0;
872 
873  mi = GET_FIRST(&Icon_move_list);
874  if (mi)
875  while ( mi != &Icon_move_list ) {
876  next = mi->next;
877  if ( ( mi->id != 0 ) && ( mi->id == bi->id ) ) {
878 
879  if ( !mi->reached_dest ) {
880  dist = brief_icon_get_dist_moved(mi, Elapsed_time);
881  if ( dist < mi->last_dist ) {
882  mi->reached_dest=1;
883  mi->last_dist=0.0f;
884  }
885  mi->last_dist=dist;
886  }
887 
888  if ( !mi->reached_dest ) {
889  vec3d dist_moved;
890  vm_vec_copy_scale(&dist_moved, &mi->direction, dist);
891  vm_vec_add(&mi->current, &mi->start, &dist_moved);
892  } else {
893  mi->current = mi->finish;
894  }
895 
896  pos = &mi->current;
897  interp_pos_found = 1;
898  break;
899  }
900  mi = next;
901  }
902 
903  if ( !interp_pos_found )
904  pos = &bi->pos;
905 
907  g3_rotate_vertex(&tv,pos);
908 
909  if (!(tv.flags&PF_PROJECTED))
910  g3_project_vertex(&tv);
911 
912  if (!(tv.flags & PF_OVERFLOW) ) { // make sure point projected before drawing text
913 
915 
917  if (bii == NULL) {
918  return;
919  }
920 
921  ga = &bii->regular;
922  if (ga->first_frame < 0) {
923  Int3();
924  return;
925  }
926 
927  brief_common_get_icon_dimensions(&icon_w, &icon_h, bi);
928 
929  closeup_icon = brief_get_closeup_icon();
930  if ( bi == closeup_icon || selected ) {
931  icon_bitmap = ga->first_frame+1;
932  }
933  else {
934  icon_bitmap = ga->first_frame;
935  }
936 
937  float scaled_w, scaled_h;
938 
939  float sx = tv.screen.xyw.x;
940  float sy = tv.screen.xyw.y;
941  gr_unsize_screen_posf( &sx, &sy, NULL, NULL, GR_RESIZE_MENU_NO_OFFSET );
942 
943  scaled_w = icon_w * w_scale_factor;
944  scaled_h = icon_h * h_scale_factor;
945  bxf = sx - scaled_w / 2.0f + 0.5f;
946  byf = sy - scaled_h / 2.0f + 0.5f;
947  bx = fl2i(bxf);
948  by = fl2i(byf);
949  bc = fl2i(sx);
950 
951  if ( ( (bx < 0) || (bx > gr_screen.max_w_unscaled) || (by < 0) || (by > gr_screen.max_h_unscaled) ) && !Fred_running ) {
952  bi->x = bx;
953  bi->y = by;
954  return;
955  }
956 
957  // render highlight anim frame
958  if ( (bi->flags&BI_SHOWHIGHLIGHT) && (bi->flags&BI_HIGHLIGHT) ) {
959  hud_anim *ha = &bi->highlight_anim;
960  if ( ha->first_frame >= 0 ) {
961  ha->sx = bi->hold_x;
962  if (bi->label[0] != '\0') {
963  ha->sy = bi->hold_y - fl2i(gr_get_font_height()/2.0f +0.5) - 2;
964  } else {
965  ha->sy = bi->hold_y;
966  }
967 
968  //hud_set_iff_color(bi->team);
970 
971  hud_anim_render(ha, frametime, 1, 0, 1, 0, GR_RESIZE_MENU, mirror_icon);
972 
973  if ( Brief_stage_highlight_sound_handle < 0 ) {
974  if ( !Fred_running) {
975  Brief_stage_highlight_sound_handle = snd_play(&Snds_iface[SND_ICON_HIGHLIGHT]);
976  }
977  }
978  }
979  }
980 
981  // render fade-in anim frame
982  if ( bi->flags & BI_FADEIN ) {
983  hud_anim *ha = &bi->fadein_anim;
984  if ( ha->first_frame >= 0 ) {
985  ha->sx = bx;
986  ha->sy = by;
988 
989  if ( hud_anim_render(ha, frametime, 1, 0, 0, 1, GR_RESIZE_MENU, mirror_icon) == 0 ) {
990  bi->flags &= ~BI_FADEIN;
991  }
992  } else {
993  bi->flags &= ~BI_FADEIN;
994  }
995  }
996 
997  if ( !(bi->flags & BI_FADEIN) ) {
998  gr_set_bitmap(icon_bitmap);
999  gr_aabitmap(bx, by, GR_RESIZE_MENU,mirror_icon);
1000 
1001  // draw text centered over the icon (make text darker)
1002  if ( bi->type == ICON_FIGHTER_PLAYER || bi->type == ICON_BOMBER_PLAYER ) {
1003  gr_get_string_size(&w,&h,Players[Player_num].callsign);
1004  gr_string(bc - fl2i(w/2.0f), by - h, Players[Player_num].callsign, GR_RESIZE_MENU);
1005  }
1006  else {
1007  if (Lcl_gr) {
1008  char buf[128];
1009  strcpy_s(buf, bi->label);
1011  gr_get_string_size(&w, &h, buf);
1012  gr_string(bc - fl2i(w/2.0f), by - h, buf, GR_RESIZE_MENU);
1013  } else if (Lcl_pl) {
1014  char buf[128];
1015  strcpy_s(buf, bi->label);
1017  gr_get_string_size(&w, &h, buf);
1018  gr_string(bc - fl2i(w/2.0f), by - h, buf, GR_RESIZE_MENU);
1019  } else {
1020  gr_get_string_size(&w,&h,bi->label);
1021  gr_string(bc - fl2i(w/2.0f), by - h, bi->label, GR_RESIZE_MENU);
1022  }
1023  }
1024 
1025  // show icon as selected (FRED only)
1026  if ( selected ) {
1027  gr_get_string_size(&w,&h,NOX("(S)"));
1028  gr_printf(bc - fl2i(w/2.0f), by - h*2, NOX("(S)"));
1029  }
1030  }
1031 
1032  // store screen x,y,w,h
1033  bi->x = bx;
1034  bi->y = by;
1035  bi->w = fl2i(scaled_w);
1036  bi->h = fl2i(scaled_h);
1037 
1038  } // end if vertex is projected
1039 }
1040 
1041 #ifdef _MSC_VER
1042 #pragma optimize("", on)
1043 #endif
1044 
1045 // -------------------------------------------------------------------------------------
1046 // brief_render_icons()
1047 //
1048 void brief_render_icons(int stage_num, float frametime)
1049 {
1050  int i, num_icons, num_lines;
1051 
1052  Assert( Briefing != NULL );
1053 
1054  num_icons = Briefing->stages[stage_num].num_icons;
1055  num_lines = Briefing->stages[stage_num].num_lines;
1056 
1057  if ( Cam_target_reached ) {
1058  for ( i = 0; i < num_lines; i++ ) {
1059  brief_render_icon_line(stage_num, i);
1060  }
1061  }
1062 
1063  for ( i = 0; i < num_icons; i++ ) {
1064  brief_render_icon(stage_num, i, frametime, 0);
1065  }
1066 }
1067 
1071 void brief_start_highlight_anims(int stage_num)
1072 {
1073  brief_stage *bs;
1074  brief_icon *bi;
1075  int x,y,i,anim_w,anim_h;
1076 
1077  Assert( Briefing != NULL );
1078  bs = &Briefing->stages[stage_num];
1079 
1080  for ( i = 0; i < bs->num_icons; i++ ) {
1081  bi = &bs->icons[i];
1082  if ( bi->flags & BI_HIGHLIGHT ) {
1083  bi->flags &= ~BI_SHOWHIGHLIGHT;
1084  if ( bi->highlight_anim.first_frame < 0 ) {
1085  continue;
1086  }
1087 
1088  bi->highlight_anim.time_elapsed=0.0f;
1089 
1090  bm_get_info( bi->highlight_anim.first_frame, &anim_w, &anim_h, NULL);
1091  x = fl2i( i2fl(bi->x) + bi->w/2.0f - anim_w/2.0f );
1092  y = fl2i( i2fl(bi->y) + bi->h/2.0f - anim_h/2.0f );
1093  bi->hold_x = x;
1094  bi->hold_y = y;
1095  bi->flags |= BI_SHOWHIGHLIGHT;
1096  bi->highlight_anim.time_elapsed=0.0f;
1097  }
1098  }
1099 }
1100 
1101 // -------------------------------------------------------------------------------------
1102 // brief_render_map()
1103 //
1104 //
1105 void brief_render_map(int stage_num, float frametime)
1106 {
1107  gr_set_clip(bscreen.map_x1 + 1, bscreen.map_y1 + 1, bscreen.map_x2 - bscreen.map_x1 - 1, bscreen.map_y2 - bscreen.map_y1 - 2, GR_RESIZE_MENU);
1108 
1109  if (stage_num >= Briefing->num_stages) {
1110  gr_reset_clip();
1111  return;
1112  }
1113 
1114  Assert(Briefing);
1115 
1116  g3_start_frame(0);
1117  g3_set_view_matrix(&Current_cam_pos, &Current_cam_orient, Briefing_window_FOV);
1118 
1119  brief_maybe_create_new_grid(The_grid, &Current_cam_pos, &Current_cam_orient);
1121 
1122  brief_render_fade_outs(frametime);
1123 
1124  // go ahead and render everything that is in the active objects list
1125  brief_render_icons(stage_num, frametime);
1126 
1127  if ( Cam_target_reached && brief_text_wipe_finished() ) {
1128  if ( Play_highlight_flag ) {
1129  brief_start_highlight_anims(stage_num);
1130  Play_highlight_flag = 0;
1131  }
1132  }
1133 
1134  anim_render_all(ON_BRIEFING_SELECT, frametime);
1135 
1136  gr_reset_clip();
1137  g3_end_frame();
1138 }
1139 
1143 void brief_blit_stage_num(int stage_num, int stage_max)
1144 {
1145  char buf[64];
1146 
1147  Assert( Briefing != NULL );
1149  sprintf(buf, XSTR( "Stage %d of %d", 394), stage_num + 1, stage_max);
1150  if (Game_mode & GM_MULTIPLAYER) {
1152  } else {
1154  }
1155 }
1156 
1167 void brief_render_line(int line_num, int x, int y, int instance)
1168 {
1169  Assert( 0<=instance && instance < (int)(sizeof(Colored_stream)/sizeof(*Colored_stream)) );
1170 
1171  SCP_vector<colored_char> *src = &Colored_stream[instance].at(line_num);
1172 
1173  // empty strings do not have to be drawn
1174  int src_len = src->size();
1175  if (src_len == 0){
1176  return;
1177  }
1178  // truncate_len is the number of characters currently displayed including the bright white characters
1179  int truncate_len = fl2i(Brief_text_wipe_time_elapsed / BRIEF_TEXT_WIPE_TIME * Max_briefing_line_len);
1180  if (truncate_len > src_len){
1181  truncate_len = src_len;
1182  }
1183  // truncate_len is going to be the number of characters displayed with normal intensity
1184  // bright_len is the additional characters displayed with high intensity
1185  // bright_len+truncate_len<len chars are displayed
1186  int bright_len = 0;
1187  if (truncate_len < src_len) {
1188  if (truncate_len <= BRIGHTEN_LEAD) {
1189  bright_len = truncate_len;
1190  truncate_len = 0;
1191  } else {
1192  bright_len = BRIGHTEN_LEAD;
1193  truncate_len -= BRIGHTEN_LEAD;
1194  }
1195  }
1196  int char_seq_pos=0; //Cursor position into the following character sequence
1197  char char_seq[MAX_BRIEF_LINE_LEN];
1198  int offset = 0; //offset is the horizontal position of the screen where strings are drawn
1200 
1201  // PART1: Draw the the briefing line part with normal intensity and word colors.
1202  // The following algorithm builds a character sequence of color 'last_color' into 'line' buffer.
1203  // When the color changes, the buffer is drawn and reset.
1204  {
1205  char last_color = src->at(0).color;
1206  for (int current_pos=0; current_pos<truncate_len; current_pos++) {
1207  colored_char &current_char=src->at(current_pos);
1208  //when the current color changes, the accumulated character sequence is drawn.
1209  if (current_char.color != last_color){
1210  //add a 0 terminal character to make line a valid C string
1211  Assert(char_seq_pos < (int)sizeof(char_seq));
1212  char_seq[char_seq_pos] = 0;
1213  { // Draw coloured text, and increment cariage position
1214  int w=0,h=0;
1215  brief_set_text_color(last_color);
1216  gr_string(x + offset, y, char_seq, GR_RESIZE_MENU);
1217  gr_get_string_size(&w, &h, char_seq);
1218  offset += w;
1219  }
1220  //clear char buffer
1221  char_seq_pos = 0;
1222  last_color = current_char.color;
1223  }
1224  Assert(char_seq_pos < (int)sizeof(char_seq));
1225  char_seq[char_seq_pos++] = current_char.letter;
1226  }
1227  // Draw the final chunk of acumulated characters
1228  // Add a 0 terminal character to make line a valid C string
1229  Assert(char_seq_pos < (int)sizeof(char_seq));
1230  char_seq[char_seq_pos] = 0;
1231  { // Draw coloured text, and increment cariage position
1232  int w=0,h=0;
1233  brief_set_text_color(last_color);
1234  gr_string(x + offset, y, char_seq, GR_RESIZE_MENU);
1235  gr_get_string_size(&w, &h, char_seq);
1236  offset += w;
1237  }
1238  }
1239 
1240  { // PART2: Draw leading bright white characters
1241  char_seq_pos = 0;
1242  for( int current_pos = truncate_len; current_pos<truncate_len + bright_len; current_pos++){
1243  Assert(char_seq_pos < (int)sizeof(char_seq));
1244  char_seq[char_seq_pos++] = src->at(current_pos).letter;
1245  }
1246  Assert(char_seq_pos < (int)sizeof(char_seq));
1247  char_seq[char_seq_pos] = 0;
1249  gr_string(x + offset, y, char_seq, GR_RESIZE_MENU);
1250  }
1251 }
1252 
1254 {
1256  return 1;
1257  }
1258 
1259  return 0;
1260 }
1261 
1274 int brief_render_text(int line_offset, int x, int y, int h, float frametime, int instance, int line_spacing)
1275 {
1276  int fh, line, yy;
1277 
1278  fh = gr_get_font_height();
1279  if (Brief_text_wipe_time_elapsed == 0) {
1280  if (snd_is_playing(Brief_text_wipe_snd)) {
1281  snd_stop(Brief_text_wipe_snd);
1282  }
1284  Play_brief_voice = 1;
1285  }
1286 
1287  Brief_text_wipe_time_elapsed += frametime;
1288 
1289  line = line_offset;
1290  yy = 0;
1291  while (yy + fh <= h) {
1292  if (line >= Num_brief_text_lines[instance])
1293  break;
1294 
1295  brief_render_line(line, x, y + yy, instance);
1296 
1297  line++;
1298  yy += fh + line_spacing;
1299  }
1300 
1301  if ( brief_text_wipe_finished() && (Play_brief_voice) ) {
1302  Play_brief_voice = 0;
1303  return 1;
1304  }
1305 
1306  return 0;
1307 }
1308 
1314 {
1315  vec3d gpos; // Location of point on grid.
1316  plane tplane;
1317  vec3d *gv;
1318 
1319  if ( pos->xyz.y < 1 && pos->xyz.y > -1 )
1320  return;
1321 
1322  tplane.A = gridp->gmatrix.vec.uvec.xyz.x;
1323  tplane.B = gridp->gmatrix.vec.uvec.xyz.y;
1324  tplane.C = gridp->gmatrix.vec.uvec.xyz.z;
1325  tplane.D = gridp->planeD;
1326 
1327  compute_point_on_plane(&gpos, &tplane, pos);
1328 
1329  gv = &gridp->gmatrix.vec.uvec;
1330  if (gv->xyz.x * pos->xyz.x + gv->xyz.y * pos->xyz.y + gv->xyz.z * pos->xyz.z < -gridp->planeD)
1331  gr_set_color(127, 127, 127);
1332  else
1333  gr_set_color(255, 255, 255); // white
1334 }
1335 
1336 
1337 // ------------------------------------------------------------------------------------
1338 // brief_reset_icons()
1339 //
1340 void brief_reset_icons(int stage_num)
1341 {
1342  brief_stage *bs;
1343  brief_icon *bi;
1344  int i;
1345 
1346  Assert( Briefing != NULL );
1347  bs = &Briefing->stages[stage_num];
1348 
1349  for ( i = 0; i < bs->num_icons; i++ ) {
1350  bi = &bs->icons[i];
1351  bi->flags &= ~BI_SHOWHIGHLIGHT;
1352  }
1353 }
1354 
1355 
1364 {
1365  float time_in_seconds;
1366 
1367  time_in_seconds = time / 1000.0f;
1368 
1369  if ( time == 0 ) {
1370  Current_cam_pos = *pos;
1371  Current_cam_orient = *orient;
1372  }
1373 
1374  Target_cam_pos = *pos;
1375  Target_cam_orient = *orient;
1376  Start_cam_orient = Current_cam_orient;
1377  Start_cam_pos = Current_cam_pos; // we need this when checking if camera movement complete
1378  Start_cam_move = timer_get_milliseconds()*1000.0f; // start time, convert to seconds
1379  Total_move_time = time_in_seconds;
1380  Elapsed_time = 0.0f;
1381 
1382  vm_vec_scale_add(&Start_lookat_pos, &Start_cam_pos, &Start_cam_orient.vec.fvec, LOOKAT_DIST);
1383  vm_vec_scale_add(&Target_lookat_pos, &Target_cam_pos, &Target_cam_orient.vec.fvec, LOOKAT_DIST);
1384 
1385  Play_highlight_flag = 1; // once target reached, play highlight anims
1386  Cam_target_reached = 0;
1387  Cam_movement_done=0;
1388  anim_release_all_instances(ON_BRIEFING_SELECT); // stop any briefing-specific anims
1389 
1390  // calculate camera velocity
1391  vm_vec_sub(&Cam_vel, pos, &Current_cam_pos);
1392 
1393  if ( !IS_VEC_NULL_SQ_SAFE(&Cam_vel) ) {
1394  vm_vec_normalize(&Cam_vel);
1395  }
1396 
1397  // calculate lookat point velocity
1398  vm_vec_sub(&Lookat_vel, &Target_lookat_pos, &Current_lookat_pos);
1399  vm_vec_scale(&Lookat_vel, 1.0f/time_in_seconds);
1400 
1401  Start_dist = vm_vec_dist(&Start_cam_pos, &Start_lookat_pos);
1402  End_dist = vm_vec_dist(&Target_cam_pos, &Target_lookat_pos);
1403  Dist_change_rate = (End_dist - Start_dist) / time_in_seconds;
1404 
1405  Total_dist=vm_vec_dist(&Start_cam_pos, &Target_cam_pos);
1406 
1407  Peak_speed=Total_dist/Total_move_time*2.0f;
1408  Cam_accel = 4*Total_dist/(Total_move_time*Total_move_time);
1409  Last_dist=0.0f;
1410 
1411  vm_vec_zero(&W_init);
1412 
1413  get_camera_limits(&Start_cam_orient, &Target_cam_orient, Total_move_time, &Acc_limit, &Vel_limit);
1414 }
1415 
1416 
1417 bool brief_verify_color_tag(char color_tag)
1418 {
1419  if ( Tagged_Colors.find(color_tag) == Tagged_Colors.end() ) {
1420  Warning(LOCATION, "Invalid text color tag '$%c' used in mission: '%s'.\n", color_tag, Mission_filename);
1421  return false;
1422  }
1423  return true;
1424 }
1425 
1426 void brief_set_text_color(char color_tag)
1427 {
1428  gr_set_color_fast(Tagged_Colors[color_tag]);
1429 }
1430 
1436 bool is_a_word_separator(char character)
1437 {
1438  return ((character >= 0) && (character <= 32)); // all control characters including space, newline, and tab
1439 }
1440 
1455 int brief_text_colorize(char *src, int instance, char default_color_stack[], int &color_stack_index)
1456 {
1457  Assert(src);
1458  Assert((0 <= instance) && (instance < (int)(sizeof(Colored_stream) / sizeof(*Colored_stream))));
1459 
1460  briefing_line dest_line; //the resulting vector of colored character
1461  char active_color_index; //the current drawing color
1462 
1463  active_color_index = default_color_stack[color_stack_index];
1464 
1465  int src_len = strlen(src);
1466  for (int i = 0; i < src_len; i++)
1467  {
1468  // Is the character a color markup?
1469  // text markup consists of a '$' plus a character plus an optional space
1470  if ( (i < src_len - 1) && (src[i] == BRIEF_META_CHAR) )
1471  {
1472  i++; // Consume the $ character
1473 
1474  // it's possible that there's a closing brace here
1475  if (src[i] == '}')
1476  {
1477  if (color_stack_index > 0)
1478  {
1479  color_stack_index--;
1480  active_color_index = default_color_stack[color_stack_index];
1481  }
1482  i++; // consume the }
1483  }
1484  // breaking character
1485  else if (src[i] == '|')
1486  {
1487  active_color_index = default_color_stack[color_stack_index];
1488  i++; // consume the |
1489  }
1490  // normal $c or $c{
1491  else
1492  {
1493  if (brief_verify_color_tag(src[i])) active_color_index = src[i];
1494  i++; // Consume the color identifier and focus on the white character (if any)
1495 
1496  // special case: color spans (different default color within braces)
1497  // (there's a slim chance that src[i] could be the null-terminator, but that's okay here)
1498  if (src[i] == '{')
1499  {
1500  if (color_stack_index < HIGHEST_COLOR_STACK_INDEX)
1501  {
1502  color_stack_index++;
1503  default_color_stack[color_stack_index] = active_color_index;
1504  }
1505  i++; // consume the {
1506  }
1507  }
1508 
1509  // Skip every whitespace until the next word is reached
1510  while ( (i < src_len) && is_white_space(src[i]) )
1511  i++;
1512  //The next character is not a whitespace, let's process it as usual
1513  //(subtract 1 because the for loop will add it again)
1514  i--;
1515  continue;
1516  }
1517 
1518  // When the word is terminated, reset color to default
1519  if ( (is_white_space(src[i]) ) || ( is_a_word_separator(src[i]) ))
1520  active_color_index = default_color_stack[color_stack_index];
1521 
1522  // Append the character to the result structure
1523  colored_char dest;
1524  dest.letter = src[i];
1525  dest.color = active_color_index;
1526  dest_line.push_back(dest);
1527  }
1528 
1529  Colored_stream[instance].push_back(dest_line);
1530  return dest_line.size();
1531 }
1532 
1543 int brief_color_text_init(const char* src, int w, const char default_color, int instance, int max_lines, const bool append)
1544 {
1545  int i, n_lines, len;
1546  SCP_vector<int> n_chars;
1548  char tmp_brief_line[MAX_BRIEF_LINE_LEN];
1549 
1550  // manage different default colors (don't use a SCP_ stack because eh)
1551  char default_color_stack[HIGHEST_COLOR_STACK_INDEX + 1];
1552  int color_stack_index = 0;
1553 
1554  // start off with white, or whatever our default is
1555  if (default_color == '\0' || !brief_verify_color_tag(default_color)) { // call brief_verify_color_tag() to make sure our default is actually a defined color tag
1556  default_color_stack[0] = Color_Tags[0];
1557  } else {
1558  default_color_stack[0] = default_color;
1559  }
1560 
1561  Assert(src != NULL);
1562  n_lines = split_str(src, w, n_chars, p_str, BRIEF_META_CHAR);
1563  Assert(n_lines >= 0);
1564 
1565  //for compatability reasons truncate text from everything except the fiction viewer
1566  if ((max_lines > 0) && (n_lines > max_lines)) {
1567  n_lines = max_lines;
1568  }
1569 
1570  if (!append) {
1571  Max_briefing_line_len = 1;
1572  Colored_stream[instance].clear();
1573  } else if (n_lines == 0 && !strcmp(src, "\n")) { // Silly hack to allow inserting blank lines for debriefings -MageKing17
1574  n_lines = 1;
1575  p_str.push_back(0);
1576  n_chars.push_back(0);
1577  }
1578  for (i=0; i<n_lines; i++) {
1579  Assert(n_chars[i] < MAX_BRIEF_LINE_LEN);
1580  strncpy(tmp_brief_line, p_str[i], n_chars[i]);
1581  tmp_brief_line[n_chars[i]] = 0;
1582  drop_leading_white_space(tmp_brief_line);
1583  len = brief_text_colorize(&tmp_brief_line[0], instance, default_color_stack, color_stack_index);
1584  if (len > Max_briefing_line_len)
1585  Max_briefing_line_len = len;
1586  }
1587 
1589  Play_brief_voice = 0;
1590 
1591  if (append) {
1592  Num_brief_text_lines[instance] += n_lines;
1593  } else {
1594  Num_brief_text_lines[instance] = n_lines;
1595  }
1596  return n_lines;
1597 }
1598 
1605 {
1606  int i;
1607 
1608  for ( i = 0; i < MAX_MOVING_ICONS; i++ ) {
1609  if ( Icon_movers[i].used == 0 )
1610  break;
1611  }
1612 
1613  if ( i == MAX_MOVING_ICONS )
1614  return -1;
1615 
1616  Icon_movers[i].used = 1;
1617  return i;
1618 }
1619 
1627 int brief_set_move_list(int new_stage, int current_stage, float time)
1628 {
1629  brief_stage *newb, *cb;
1630  icon_move_info *imi;
1631  int i,j,k,num_movers,is_gone=0;
1632  vec3d zero_v = ZERO_VECTOR;
1633 
1634  Assert(new_stage != current_stage);
1635 
1636  Assert( Briefing != NULL );
1637  newb = &Briefing->stages[new_stage];
1638  cb = &Briefing->stages[current_stage];
1639  num_movers = 0;
1640 
1641  for ( i = 0; i < cb->num_icons; i++ ) {
1642  is_gone=1;
1643  for ( j = 0; j < newb->num_icons; j++ ) {
1644  if ( ( cb->icons[i].id != 0 ) && ( cb->icons[i].id == newb->icons[j].id ) ) {
1645  is_gone=0;
1646  if ( vm_vec_cmp(&cb->icons[i].pos, &newb->icons[j].pos) ) {
1647 
1648  k = brief_get_free_move_icon();
1649  if ( k == -1 ) {
1650  Warning(LOCATION, "Too many briefing icons are moving simultaneously!");
1651  return 0;
1652  }
1653  imi = &Icon_movers[k];
1654  imi->id = cb->icons[i].id;
1655  imi->start = cb->icons[i].pos;
1656  imi->finish = newb->icons[j].pos;
1657  imi->current = imi->start;
1658  list_append(&Icon_move_list, imi);
1659 
1660  imi->total_dist = vm_vec_dist(&imi->start, &imi->finish);
1661  imi->total_move_time = time;
1662  imi->peak_speed = imi->total_dist/imi->total_move_time*2.0f;
1663  imi->accel = 4*imi->total_dist/(time*time);
1664  imi->last_dist=0.0f;
1665  imi->reached_dest=0;
1666  imi->direction = zero_v;
1667 
1668  vm_vec_sub(&imi->direction, &imi->finish, &imi->start);
1669  if ( !IS_VEC_NULL_SQ_SAFE(&imi->direction) ) {
1670  vm_vec_normalize(&imi->direction);
1671  }
1672 
1673  num_movers++;
1674  }
1675  }
1676  }
1677 
1678  // Set up fading icon (to fade out)
1679  if (is_gone == 1) {
1680  if ( Num_fade_icons >= MAX_FADING_ICONS ) {
1681  Int3();
1682  Num_fade_icons = 0;
1683  }
1684 
1686  if (bii == NULL) {
1687  return 0;
1688  }
1689 
1690  Fading_icons[Num_fade_icons].fade_anim = bii->fade;
1691  Fading_icons[Num_fade_icons].pos = cb->icons[i].pos;
1692  Fading_icons[Num_fade_icons].team = cb->icons[i].team;
1693  Num_fade_icons++;
1694  }
1695  }
1696 
1697  // flag new icons for fading in
1698  for ( i=0; i<newb->num_icons; i++ ) {
1699  int is_new = 1;
1700  newb->icons[i].flags &= ~BI_FADEIN;
1701  for ( j=0; j<cb->num_icons; j++ ) {
1702  if ( ( cb->icons[j].id != 0 ) && ( cb->icons[j].id == newb->icons[i].id ) ) {
1703  is_new=0;
1704  }
1705  }
1706  if ( is_new ) {
1707  briefing_icon_info *bii = brief_get_icon_info(&newb->icons[i]);
1708  if (bii == NULL) {
1709  return 0;
1710  }
1711 
1712  newb->icons[i].flags |= BI_FADEIN;
1713  newb->icons[i].fadein_anim = bii->fade;
1714  newb->icons[i].fadein_anim.time_elapsed = 0.0f;
1715  }
1716  }
1717 
1718  return num_movers;
1719 }
1720 
1722 {
1723  Num_fade_icons = 0;
1724 }
1725 
1726 
1735 void brief_set_new_stage(vec3d *pos, matrix *orient, int time, int stage_num)
1736 {
1737  const char *msg;
1738  int num_movers, new_time, not_objv = 1;
1739 
1740  Assert( Briefing != NULL );
1741  new_time = time;
1742 
1743  if (stage_num >= Briefing->num_stages) {
1744  not_objv = 0; // turns out this is an objectives stage
1745  new_time = 0;
1746  }
1747 
1748  if ( stage_num == Last_new_stage ) {
1749  return;
1750  }
1751 
1752  num_movers = 0;
1755  if ( (Last_new_stage != -1) && not_objv ) {
1756  num_movers = brief_set_move_list(stage_num, Last_new_stage, new_time / 1000.0f);
1757  }
1758 
1759  if ( (Last_new_stage != -1) && (num_movers == 0) && not_objv ) {
1760  if ( !vm_vec_cmp( &Briefing->stages[stage_num].camera_pos, &Briefing->stages[Last_new_stage].camera_pos) ) {
1761  if ( !vm_vec_cmp( &Briefing->stages[stage_num].camera_orient.vec.fvec, &Briefing->stages[Last_new_stage].camera_orient.vec.fvec) ){
1762  new_time = 0;
1763  }
1764  }
1765  }
1766 
1767  if (not_objv) {
1768  msg = Briefing->stages[stage_num].text.c_str();
1769  } else {
1770  msg = XSTR( "Please review your objectives for this mission.", 395);
1771  }
1772 
1773  if (gr_screen.res == GR_640) {
1774  // GR_640
1776  } else {
1777  // GR_1024
1779  }
1780 
1781  Top_brief_text_line = 0;
1782 
1783  if (not_objv){
1784  brief_set_camera_target(pos, orient, new_time);
1785  }
1786 
1787  if ( snd_is_playing(Brief_stage_highlight_sound_handle) ) {
1788  snd_stop(Brief_stage_highlight_sound_handle);
1789  }
1790 
1791  Voice_started_time = 0;
1792  Voice_ended_time = 0;
1793 
1794  Brief_stage_highlight_sound_handle = -1;
1795  Last_new_stage = stage_num;
1796 }
1797 
1798 // ------------------------------------------------------------------------------------
1799 // camera_pos_past_target()
1800 //
1801 //
1803 {
1804  vec3d num, den;
1805  float ratio;
1806 
1807  vm_vec_sub(&num, current, start);
1808  vm_vec_sub(&den, start, dest);
1809 
1810  ratio = vm_vec_mag_quick(&num) / vm_vec_mag_quick(&den);
1811  if (ratio >= 1.0f)
1812  return TRUE;
1813 
1814  return FALSE;
1815 }
1816 
1821 void interpolate_matrix(matrix *result, matrix *goal, matrix *start, float elapsed_time, float total_time)
1822 {
1823  vec3d fvec, rvec;
1824  float time0, time1;
1825 
1826  if ( !vm_matrix_cmp( goal, start ) ) {
1827  return;
1828  }
1829 
1830  time0 = elapsed_time / total_time;
1831  time1 = (total_time - elapsed_time) / total_time;
1832 
1833  vm_vec_copy_scale(&fvec, &start->vec.fvec, time1);
1834  vm_vec_scale_add2(&fvec, &goal->vec.fvec, time0);
1835 
1836  vm_vec_copy_scale(&rvec, &start->vec.rvec, time1);
1837  vm_vec_scale_add2(&rvec, &goal->vec.rvec, time0);
1838 
1839  vm_vector_2_matrix(result, &fvec, NULL, &rvec);
1840  }
1841 
1845 float brief_camera_get_dist_moved(float elapsed_time)
1846 {
1847  float time, dist_moved=0.0f;
1848 
1849  // first half of movement
1850  if ( elapsed_time < Total_move_time/2.0f ) {
1851  dist_moved=0.5f*Cam_accel*elapsed_time*elapsed_time; // d = 1/2at^2
1852  return dist_moved;
1853  }
1854 
1855  // second half of movement
1856  time=elapsed_time - Total_move_time/2.0f;
1857  dist_moved=(Total_dist/2.0f)+(Peak_speed*time) - 0.5f*Cam_accel*time*time;
1858  return dist_moved;
1859 
1860 }
1861 
1865 void brief_camera_move(float frametime, int stage_num)
1866 {
1867  vec3d dist_moved;
1868  float dist;
1869  vec3d w_out;
1870  matrix result;
1871 
1872  Elapsed_time += frametime;
1873 
1874  if ( Cam_target_reached )
1875  return;
1876 
1877  // Update orientation
1878  if ( (Elapsed_time < Total_move_time) ) {
1879  vm_matrix_interpolate(&Target_cam_orient, &Current_cam_orient, &W_init, frametime, &result, &w_out, &Vel_limit, &Acc_limit);
1880  Current_cam_orient = result;
1881  W_init = w_out;
1882  }
1883 
1884  // use absolute pos to update position
1885  if ( vm_vec_cmp( &Current_cam_pos, &Target_cam_pos ) ) {
1886  dist = brief_camera_get_dist_moved(Elapsed_time);
1887  if ( dist < Last_dist ) {
1888  Cam_movement_done=1;
1889  Last_dist=0.0f;
1890  }
1891  Last_dist=dist;
1892 
1893  if ( Cam_movement_done == 0 ) {
1894  vm_vec_copy_scale(&dist_moved, &Cam_vel, dist);
1895  vm_vec_add(&Current_cam_pos, &Start_cam_pos, &dist_moved);
1896  } else {
1897  Current_cam_pos=Target_cam_pos;
1898  }
1899  }
1900  else {
1901  Cam_movement_done=1;
1902  Current_cam_pos=Target_cam_pos;
1903  }
1904 
1905  if ( Cam_movement_done && (Elapsed_time >= Total_move_time) ) {
1906  Cam_target_reached=1;
1907  }
1908 }
1909 
1915 {
1916  int roundoff;
1917  plane tplane;
1918  vec3d gpos, tmp, c;
1919  float dist_to_plane;
1920  float square_size, ux, uy, uz;
1921 
1922  ux = tplane.A = gridp->gmatrix.vec.uvec.xyz.x;
1923  uy = tplane.B = gridp->gmatrix.vec.uvec.xyz.y;
1924  uz = tplane.C = gridp->gmatrix.vec.uvec.xyz.z;
1925  tplane.D = gridp->planeD;
1926 
1927  compute_point_on_plane(&c, &tplane, pos);
1928  dist_to_plane = fl_abs(vm_dist_to_plane(pos, &gridp->gmatrix.vec.uvec, &c));
1929  square_size = 1.0f;
1930 
1931  while (dist_to_plane >= 25.0f)
1932  {
1933  square_size *= 10.0f;
1934  dist_to_plane /= 10.0f;
1935  }
1936 
1937  if (fvi_ray_plane(&gpos, &gridp->center, &gridp->gmatrix.vec.uvec, pos, &orient->vec.fvec, 0.0f)<0.0f) {
1938  vec3d p;
1939  vm_vec_scale_add(&p,pos,&orient->vec.fvec, 100.0f );
1940  compute_point_on_plane(&gpos, &tplane, &p );
1941  }
1942 
1943  if (vm_vec_dist(&gpos, &c) > 50.0f * square_size)
1944  {
1945  vm_vec_sub(&tmp, &gpos, &c);
1946  vm_vec_normalize(&tmp);
1947  vm_vec_scale_add(&gpos, &c, &tmp, 50.0f * square_size);
1948  }
1949 
1950  roundoff = (int) square_size * 10;
1951  if (!ux)
1952  gpos.xyz.x = fl_roundoff(gpos.xyz.x, roundoff);
1953  if (!uy)
1954  gpos.xyz.y = fl_roundoff(gpos.xyz.y, roundoff);
1955  if (!uz)
1956  gpos.xyz.z = fl_roundoff(gpos.xyz.z, roundoff);
1957 
1958  if ((square_size != gridp->square_size) ||
1959  (gpos.xyz.x != gridp->center.xyz.x) ||
1960  (gpos.xyz.y != gridp->center.xyz.y) ||
1961  (gpos.xyz.z != gridp->center.xyz.z) || force)
1962  {
1963  gridp->square_size = square_size;
1964  gridp->center = gpos;
1965  brief_modify_grid(gridp);
1966  }
1967 }
1968 
1969 // Create a grid
1970 // *forward is vector pointing forward
1971 // *right is vector pointing right
1972 // *center is center point of grid
1973 // length is length of grid
1974 // width is width of grid
1975 // square_size is size of a grid square
1976 // For example:
1977 // *forward = (0.0, 0.0, 1.0)
1978 // *right = (1.0, 0.0, 0.0)
1979 // *center = (0.0, 0.0, 0.0)
1980 // nrows = 10
1981 // ncols = 50.0
1982 // square_size = 10.0
1983 // will generate a grid of squares 10 long by 5 wide.
1984 // Each grid square will be 10.0 x 10.0 units.
1985 // The center of the grid will be at the global origin.
1986 // The grid will be parallel to the xz plane (because the normal is 0,1,0).
1987 // (In fact, it will be the xz plane because it is centered on the origin.)
1988 //
1989 // Stuffs grid in *gridp. If gridp == NULL, mallocs and returns a grid.
1990 grid *brief_create_grid(grid *gridp, vec3d *forward, vec3d *right, vec3d *center, int nrows, int ncols, float square_size)
1991 {
1992  int i, ncols2, nrows2, d = 1;
1993  vec3d dfvec, drvec, cur, cur2, tvec, uvec, save, save2;
1994 
1995  Assert(square_size > 0.0);
1997  d = 2;
1998 
1999  if (gridp == NULL)
2000  gridp = (grid *) vm_malloc(sizeof(grid));
2001 
2002  Assert(gridp);
2003 
2004  gridp->center = *center;
2005  gridp->square_size = square_size;
2006 
2007  // Create the plane equation.
2008  Assert(!IS_VEC_NULL(forward));
2009  Assert(!IS_VEC_NULL(right));
2010 
2011  vm_vec_copy_normalize(&dfvec, forward);
2012  vm_vec_copy_normalize(&drvec, right);
2013 
2014  vm_vec_cross(&uvec, &dfvec, &drvec);
2015 
2016  Assert(!IS_VEC_NULL(&uvec));
2017 
2018  gridp->gmatrix.vec.uvec = uvec;
2019 
2020  gridp->planeD = -(center->xyz.x * uvec.xyz.x + center->xyz.y * uvec.xyz.y + center->xyz.z * uvec.xyz.z);
2021  Assert(!_isnan(gridp->planeD));
2022 
2023  gridp->gmatrix.vec.fvec = dfvec;
2024  gridp->gmatrix.vec.rvec = drvec;
2025 
2026  vm_vec_scale(&dfvec, square_size);
2027  vm_vec_scale(&drvec, square_size);
2028 
2029  vm_vec_scale_add(&cur, center, &dfvec, (float) -nrows * d / 2);
2030  vm_vec_scale_add2(&cur, &drvec, (float) -ncols * d / 2);
2031  vm_vec_scale_add(&cur2, center, &dfvec, (float) -nrows * 5 / 2);
2032  vm_vec_scale_add2(&cur2, &drvec, (float) -ncols * 5 / 2);
2033  save = cur;
2034  save2 = cur2;
2035 
2036  gridp->ncols = ncols;
2037  gridp->nrows = nrows;
2038  ncols2 = ncols / 2;
2039  nrows2 = nrows / 2;
2040  Assert(ncols < MAX_GRIDLINE_POINTS && nrows < MAX_GRIDLINE_POINTS);
2041 
2042  // Create the points along the edges of the grid, so we can just draw lines
2043  // between them to form the grid.
2044  for (i=0; i<=ncols*d; i++) {
2045  gridp->gpoints1[i] = cur; // small, dark gridline points
2046  vm_vec_scale_add(&tvec, &cur, &dfvec, (float) nrows * d);
2047  gridp->gpoints2[i] = tvec;
2048  vm_vec_add2(&cur, &drvec);
2049  }
2050 
2051  for (i=0; i<=ncols2; i++) {
2052  gridp->gpoints5[i] = cur2; // large, brighter gridline points
2053  vm_vec_scale_add(&tvec, &cur2, &dfvec, (float) nrows2 * 10);
2054  gridp->gpoints6[i] = tvec;
2055  vm_vec_scale_add2(&cur2, &drvec, 10.0f);
2056  }
2057 
2058  cur = save;
2059  cur2 = save2;
2060  for (i=0; i<=nrows*d; i++) {
2061  gridp->gpoints3[i] = cur; // small, dark gridline points
2062  vm_vec_scale_add(&tvec, &cur, &drvec, (float) ncols * d);
2063  gridp->gpoints4[i] = tvec;
2064  vm_vec_add2(&cur, &dfvec);
2065  }
2066 
2067  for (i=0; i<=nrows2; i++) {
2068  gridp->gpoints7[i] = cur2; // large, brighter gridline points
2069  vm_vec_scale_add(&tvec, &cur2, &drvec, (float) ncols2 * 10);
2070  gridp->gpoints8[i] = tvec;
2071  vm_vec_scale_add2(&cur2, &dfvec, 10.0f);
2072  }
2073 
2074  return gridp;
2075 }
2076 
2082 {
2083  grid *rgrid;
2084  vec3d fvec, rvec, cvec;
2085 
2086  vm_vec_make(&fvec, 0.0f, 0.0f, 1.0f);
2087  vm_vec_make(&rvec, 1.0f, 0.0f, 0.0f);
2088  vm_vec_make(&cvec, 0.0f, -10.0f, 0.0f);
2089 
2090  rgrid = brief_create_grid(&Global_grid, &fvec, &rvec, &cvec, 100, 100, 5.0f);
2091 
2092  physics_init(&rgrid->physics);
2094  return rgrid;
2095 }
2096 
2101 {
2102  vertex tv0, tv1;
2103  g3_rotate_vertex(&tv0, v0);
2104  g3_rotate_vertex(&tv1, v1);
2105 
2107  g3_draw_line(&tv0, &tv1);
2108 }
2109 
2116 {
2117  int i, ncols, nrows;
2118 
2119  ncols = gridp->ncols;
2120  nrows = gridp->nrows;
2122  {
2123  ncols *= 2;
2124  nrows *= 2;
2125  }
2126 
2127  gr_set_color(30,30,30);
2128 
2129  // Draw the column lines.
2130  for (i=0; i<=ncols; i++)
2131  brief_rpd_line(&gridp->gpoints1[i], &gridp->gpoints2[i]);
2132 
2133  // Draw the row lines.
2134  for (i=0; i<=nrows; i++)
2135  brief_rpd_line(&gridp->gpoints3[i], &gridp->gpoints4[i]);
2136 }
2137 
2139 {
2140  brief_create_grid(gridp, &gridp->gmatrix.vec.fvec, &gridp->gmatrix.vec.rvec, &gridp->center,
2141  gridp->nrows, gridp->ncols, gridp->square_size);
2142 }
2143 
2145 {
2146  for (SCP_vector<briefing_icon_info>::iterator ii = Briefing_icon_info.begin(); ii != Briefing_icon_info.end(); ++ii)
2147  {
2148  if (ii->regular.first_frame >= 0)
2149  {
2150  bm_unload(ii->regular.first_frame);
2151  ii->regular.first_frame = -1;
2152  }
2153 
2154  if (ii->fade.first_frame >= 0)
2155  {
2156  bm_unload(ii->fade.first_frame);
2157  ii->fade.first_frame = -1;
2158  }
2159 
2160  if (ii->highlight.first_frame >= 0)
2161  {
2162  bm_unload(ii->highlight.first_frame);
2163  ii->highlight.first_frame = -1;
2164  }
2165  }
2166 }
2167 
2169 {
2171 }
2172 
2174 {
2175  Voice_started_time = 0;
2176  Voice_ended_time = 0;
2178 }
2179 
2184 {
2185  int i;
2186  for ( i = 0; i < MAX_BRIEF_STAGES; i++ ) {
2187  Brief_voices[i] = -1;
2188  }
2189 }
2190 
2191 void brief_load_voice_file(int voice_num, char *name)
2192 {
2193  int load_attempts = 0;
2194  while(1) {
2195 
2196  if ( load_attempts++ > 5 ) {
2197  break;
2198  }
2199 
2200  Brief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
2201  if ( Brief_voices[voice_num] >= 0 ) {
2202  break;
2203  }
2204 
2205  // Don't bother to ask for the CD in multiplayer
2206  if ( Game_mode & GM_MULTIPLAYER ) {
2207  break;
2208  }
2209  }
2210 }
2211 
2216 {
2217  int i;
2218  brief_stage *bs;
2219 
2220  Assert( Briefing != NULL );
2221  for ( i = 0; i < Briefing->num_stages; i++ ) {
2222  bs = &Briefing->stages[i];
2223  if ( strnicmp(bs->voice, NOX("none"), 4) ) {
2224  brief_load_voice_file(i, bs->voice);
2225  }
2226  }
2227 }
2228 
2233 {
2234  int i;
2235 
2236  for ( i = 0; i < MAX_BRIEF_STAGES; i++ ) {
2237  if ( Brief_voices[i] != -1 ) {
2239  Brief_voices[i] = -1;
2240  }
2241  }
2242 }
2243 
2247 void brief_voice_play(int stage_num)
2248 {
2249  if (!Voice_started_time) {
2250  Voice_started_time = timer_get_milliseconds();
2251  Voice_ended_time = 0;
2252  }
2253 
2254  if ( !Briefing_voice_enabled ) {
2255  return;
2256  }
2257 
2258  if ( Brief_voices[stage_num] < 0 ) {
2259  // play simulated speech?
2261  if (fsspeech_playing()) {
2262  return;
2263  }
2264 
2265  fsspeech_play(FSSPEECH_FROM_BRIEFING, Briefing->stages[stage_num].text.c_str());
2266  }
2267  } else {
2268  if ( audiostream_is_playing( Brief_voices[stage_num]) ) {
2269  return;
2270  }
2271 
2273  }
2274 }
2275 
2279 void brief_voice_stop(int stage_num)
2280 {
2281  if (Brief_voices[stage_num] < 0) {
2282  fsspeech_stop();
2283  } else {
2284  audiostream_stop(Brief_voices[stage_num], 1, 0); // stream is automatically rewound
2285  }
2286 }
2287 
2292 void brief_voice_pause(int stage_num)
2293 {
2294  if (Brief_voices[stage_num] < 0) {
2295  fsspeech_stop();
2296  } else {
2297  audiostream_pause(Brief_voices[stage_num]);
2298  }
2299 }
2300 
2301 void brief_voice_unpause(int stage_num)
2302 {
2303  if (Brief_voices[stage_num] < 0) {
2304  fsspeech_stop();
2305  } else {
2306  audiostream_unpause(Brief_voices[stage_num]);
2307  }
2308 }
2309 
2311 {
2312  Last_new_stage = -1;
2313 }
2314 
2319 {
2320  Assert(bi != NULL);
2321 
2322  // in case anything goes wrong
2323  *w=0;
2324  *h=0;
2325 
2327  if (bii == NULL) {
2328  return;
2329  }
2330 
2331  if (bii->regular.first_frame >= 0) {
2332  bm_get_info(bii->regular.first_frame, w, h, NULL);
2333  }
2334 }
2335 
2337 {
2338  int i, j;
2339  static int inited = 0;
2340 
2341  if (inited) {
2342  for (i=0; i<MAX_TVT_TEAMS; i++) {
2343  for (j=0; j<Cmd_briefs[i].num_stages; j++) {
2344  Cmd_briefs[i].stage[j].text = "";
2345  }
2346  }
2347  }
2348 
2349  inited = 1;
2350  for (i=0; i<MAX_TVT_TEAMS; i++)
2351  Cmd_briefs[i].num_stages = 0;
2352 }
2353 
2357 int brief_time_to_advance(int stage_num)
2358 {
2359  if (brief_get_closeup_icon() != NULL)
2360  return 0;
2361 
2362  if (Briefing_paused)
2363  return 0;
2364 
2365  if ( !Player->auto_advance )
2366  return 0;
2367 
2368  if (!brief_text_wipe_finished())
2369  return 0;
2370 
2371  if (Voice_ended_time && (timer_get_milliseconds() - Voice_ended_time >= STAGE_ADVANCE_DELAY))
2372  return 1;
2373 
2374  // check normal speech
2375  if (Briefing_voice_enabled && (Brief_voices[stage_num] >= 0)) {
2376  if (audiostream_is_playing(Brief_voices[stage_num])) {
2377  return 0;
2378  }
2379 
2380  if (!Voice_ended_time) {
2381  Voice_ended_time = timer_get_milliseconds();
2382  }
2383 
2384  return 0;
2385  }
2386 
2387  // check simulated speech
2389  if (fsspeech_playing()) {
2390  return 0;
2391  }
2392 
2393  if (!Voice_ended_time) {
2394  Voice_ended_time = timer_get_milliseconds();
2395  }
2396 
2397  return 0;
2398  }
2399 
2400  // if we get here, there is no voice, so we simulate the time it would take instead
2401  if (!Voice_ended_time)
2402  Voice_ended_time = Voice_started_time + MAX(5000, Num_brief_text_lines[0] * 3500);
2403 
2404  return 0;
2405 }
void brief_render_icon_line(int stage_num, int line_num)
SCP_vector< briefing_line > briefing_stream
#define MAX_TEXT_STREAMS
GLuint64EXT * result
Definition: Glext.h:10775
int brief_text_colorize(char *src, int instance, char default_color_stack[], int &color_stack_index)
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
void brief_voice_init()
struct screen3d::@234::@236 xyw
void lcl_translate_brief_icon_name_gr(char *name)
Definition: localize.cpp:1153
int i
Definition: multi_pxo.cpp:466
int Briefing_voice_enabled
#define vm_free(ptr)
Definition: pstypes.h:548
#define GR_RESIZE_MENU_NO_OFFSET
Definition: 2d.h:686
void brief_unload_anims()
#define BI_HIGHLIGHT
#define _isnan(f)
Definition: config.h:280
float square_size
Definition: missiongrid.h:26
void fsspeech_stop()
Definition: fsspeech.h:45
void brief_init_map()
GLbitfield stages
Definition: Glext.h:7177
#define MAX_BRIEF_LINE_LEN
float Briefing_window_FOV
Definition: mod_table.cpp:33
int Num_brief_text_lines[MAX_TEXT_STREAMS]
float vm_vec_mag_quick(const vec3d *v)
Definition: vecmat.cpp:371
#define ICON_FIGHTER_PLAYER
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
color * iff_get_color_by_team(int team, int seen_from_team, int is_bright)
Definition: iff_defs.cpp:644
int bii_index_ship_with_cargo
Definition: ship.h:1345
color Brief_color_red
Definition: alphacolors.cpp:38
char * Brief_static_name[GR_NUM_RESOLUTIONS]
SCP_string recommendation_text
#define GR_RESIZE_MENU
Definition: 2d.h:684
void brief_reset()
void brief_start_highlight_anims(int stage_num)
int brief_text_wipe_finished()
#define ASF_VOICE
Definition: audiostr.h:21
bool brief_verify_color_tag(char color_tag)
int Fred_running
Definition: fred.cpp:44
const float BRIEF_TEXT_WIPE_TIME
spinning highlight in briefing
Definition: gamesnd.h:328
int iff_get_alpha_value(bool is_bright)
Definition: iff_defs.cpp:45
int brief_color_text_init(const char *src, int w, const char default_color, int instance, int max_lines, const bool append)
void brief_voice_unpause(int stage_num)
int hud_anim_render(hud_anim *ha, float frametime, int draw_alpha, int loop, int hold_last, int reverse, int resize_mode, bool mirror)
Render out a frame of the targetbox static animation, based on how much time has elapsed.
Definition: hud.cpp:2228
brief_stage stages[MAX_BRIEF_STAGES]
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
void brief_maybe_create_new_grid(grid *gridp, vec3d *pos, matrix *orient, int force=0)
Definition: pstypes.h:88
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
#define mprintf(args)
Definition: pstypes.h:238
void brief_set_text_color(char color_tag)
void gr_init_alphacolor(color *clr, int r, int g, int b, int alpha, int type)
Definition: 2d.cpp:1173
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
int Brief_voices[MAX_BRIEF_STAGES]
void brief_common_close()
int res
Definition: 2d.h:370
color Brief_color_legacy_neutral
Definition: alphacolors.cpp:38
void brief_rpd_line(vec3d *v0, vec3d *v1)
int max_h_unscaled
Definition: 2d.h:361
#define STAGE_ADVANCE_DELAY
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
int Lcl_pl
Definition: localize.cpp:49
struct vec3d::@225::@227 xyz
#define ICON_BOMBER_PLAYER
char default_briefing_color
Definition: alphacolors.cpp:42
CButton * team
icon_move_info Icon_movers[MAX_MOVING_ICONS]
GLclampf f
Definition: Glext.h:7097
briefing_icon_info * brief_get_icon_info(brief_icon *bi)
#define SIZE_T_ARG
Definition: clang.h:61
#define TRUE
Definition: pstypes.h:399
int snd_is_playing(int sig)
Definition: sound.cpp:1047
hud_anim highlight_anim
#define BI_FADEIN
void vm_vec_scale_add2(vec3d *dest, const vec3d *src, float k)
Definition: vecmat.cpp:284
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
float A
Definition: vecmat.h:73
#define MAX_STAGE_ICONS
int g3_draw_line(vertex *p0, vertex *p1)
Definition: 3ddraw.cpp:112
hull_check orient
Definition: lua.cpp:5049
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
cmd_brief Cmd_briefs[MAX_TVT_TEAMS]
int Brief_text_coords[GR_NUM_RESOLUTIONS][4]
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
int max_w_unscaled
Definition: 2d.h:361
#define Int3()
Definition: pstypes.h:292
briefing Briefings[MAX_TVT_TEAMS]
void anim_release_all_instances(int screen_id)
Free all anim instances that are on the anim_render_list.
Definition: animplay.cpp:567
int required_string_either(char *str1, char *str2)
Checks for one of two required strings.
Definition: parselo.cpp:673
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define GR_RESIZE_NONE
Definition: 2d.h:681
#define IS_VEC_NULL(v)
Definition: vecmat.h:28
float time_elapsed
Definition: hud.h:29
int nrows
Definition: missiongrid.h:22
float B
Definition: vecmat.h:73
int double_fine_gridlines
Definition: missiongrid.cpp:21
void brief_set_icon_color(int team)
int camera_pos_past_target(vec3d *start, vec3d *current, vec3d *dest)
#define BI_USE_WING_ICON
#define BI_MIRROR_ICON
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
#define IS_VEC_NULL_SQ_SAFE(v)
Definition: vecmat.h:24
int ncols
Definition: missiongrid.h:22
#define ON_BRIEFING_SELECT
Definition: missionbrief.h:18
void gr_set_color(int r, int g, int b)
Definition: 2d.cpp:1188
int audiostream_is_playing(int i)
Definition: audiostr.cpp:1827
int species
Definition: ship.h:1166
#define MAX_GRIDLINE_POINTS
Definition: missiongrid.h:18
void mission_debrief_common_reset()
__inline void gr_set_clip(int x, int y, int w, int h, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:741
int vm_matrix_cmp(const matrix *a, const matrix *b)
Definition: vecmat.cpp:1426
player Players[MAX_PLAYERS]
#define MAX_BRIEF_LINE_W_640
#define BRIGHTEN_LEAD
void brief_restart_text_wipe()
icon_move_info * next
brief_icon * icons
void brief_clear_fade_out_icons()
int num_frames
Definition: generic.h:20
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
struct icon_fade_info fade_icon
#define gr_reset_clip
Definition: 2d.h:745
int Brief_text_max_lines[GR_NUM_RESOLUTIONS]
float D
Definition: vecmat.h:73
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:850
GLintptr offset
Definition: Glext.h:5497
#define PF_OVERFLOW
Definition: 3d.h:22
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
int auto_advance
Definition: player.h:190
void brief_render_icon(int stage_num, int icon_num, float frametime, int selected, float w_scale_factor, float h_scale_factor)
char voice[MAX_FILENAME_LEN]
briefing text wipe
Definition: gamesnd.h:307
struct matrix::@228::@230 vec
int bii_index_wing_with_cargo
Definition: ship.h:1347
int first_frame
Definition: hud.h:24
screen3d screen
Definition: pstypes.h:173
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
struct icon_move_info icon_move_info
int brief_time_to_advance(int stage_num)
#define GM_MULTIPLAYER
Definition: systemvars.h:18
void brief_modify_grid(grid *gridp)
matrix gmatrix
Definition: missiongrid.h:24
int first_frame
Definition: generic.h:19
void audiostream_stop(int i, int rewind, int paused)
Definition: audiostr.cpp:1840
int Brief_static_coords[GR_NUM_RESOLUTIONS][2]
void brief_load_voice_file(int voice_num, char *name)
void brief_init_screen(int multiplayer_flag)
SCP_vector< briefing_icon_info > Briefing_icon_info
#define MAX_MOVING_ICONS
int sx
Definition: hud.h:27
int Brief_grid_coords[GR_NUM_RESOLUTIONS][4]
color Brief_color_green
Definition: alphacolors.cpp:38
void g3_set_view_matrix(const vec3d *view_pos, const matrix *view_matrix, float zoom)
Definition: 3dsetup.cpp:152
int Brief_bmap_coords[GR_NUM_RESOLUTIONS][2]
void brief_voice_play(int stage_num)
#define strnicmp(s1, s2, n)
Definition: config.h:272
void brief_init_colors()
icon_move_info Icon_move_list
void brief_reset_icons(int stage_num)
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
#define PF_ACCELERATES
Definition: physics.h:18
void _cdecl gr_printf(int x, int y, const char *format,...)
Definition: font.cpp:300
vec3d center
Definition: missiongrid.h:23
GLfloat v0
Definition: Glext.h:5638
vec3d gpoints4[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:31
#define w(p)
Definition: modelsinc.h:68
#define CF_TYPE_TABLES
Definition: cfile.h:50
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
vec3d gpoints7[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:34
int Brief_stage_text_coords[GR_NUM_RESOLUTIONS][2]
void brief_camera_move(float frametime, int stage_num)
#define GR_640
Definition: 2d.h:652
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:97
void physics_init(physics_info *pi)
Definition: physics.cpp:49
int Top_brief_text_line
int required_string(const char *pstr)
Definition: parselo.cpp:468
float brief_camera_get_dist_moved(float elapsed_time)
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
#define fl_abs(fl)
Definition: floating.h:31
vec3d gpoints5[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:32
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
void brief_render_grid(grid *gridp)
float Brief_text_wipe_time_elapsed
float vm_dist_to_plane(const vec3d *checkp, const vec3d *norm, const vec3d *planep)
Definition: vecmat.cpp:1128
char Mission_filename[80]
icon_fade_info Fading_icons[MAX_FADING_ICONS]
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
float C
Definition: vecmat.h:73
void fsspeech_play(int type, const char *text)
Definition: fsspeech.h:44
void brief_render_elements(vec3d *pos, grid *gridp)
void anim_render_all(int screen_id, float frametime)
Display the frames for the currently playing anims.
Definition: animplay.cpp:67
#define LOOKAT_DIST
int bii_index_wing
Definition: ship.h:1346
cmd_brief_stage stage[CMD_BRIEF_STAGES_MAX]
int g3_project_vertex(vertex *point)
Definition: 3dmath.cpp:202
#define BI_SHOWHIGHLIGHT
void brief_set_new_stage(vec3d *pos, matrix *orient, int time, int stage_num)
void audiostream_unpause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1960
float fl_roundoff(float x, int multiple)
Rounds off a floating point number to a multiple of some number.
Definition: floating.cpp:21
void brief_voice_pause(int stage_num)
char name[NAME_LENGTH]
Definition: ship.h:1163
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
vec3d gpoints6[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:33
SCP_vector< game_snd > Snds_iface
Definition: gamesnd.cpp:20
const char BRIEF_META_CHAR
#define vm_vec_zero(v)
Definition: vecmat.h:37
uint flags
Definition: physics.h:37
void debrief_reset()
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
Definition: hud.h:22
#define ZERO_VECTOR
Definition: vecmat.h:60
#define vm_vec_make(v, _x, _y, _z)
Definition: vecmat.h:48
vec3d gpoints2[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:29
void brief_blit_stage_num(int stage_num, int stage_max)
int inited
Definition: fredrender.cpp:76
void mission_brief_common_init()
void brief_preload_icon_anim(brief_icon *bi)
#define NOX(s)
Definition: pstypes.h:473
GLuint start
Definition: Gl.h:1502
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
Definition: vecmat.cpp:257
GLfloat GLfloat v1
Definition: Glext.h:5639
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void brief_reset_last_new_stage()
grid * brief_create_grid(grid *gridp, vec3d *forward, vec3d *right, vec3d *center, int nrows, int ncols, float square_size)
void brief_common_get_icon_dimensions(int *w, int *h, brief_icon *bi)
ubyte flags
Definition: pstypes.h:178
GLbitfield flags
Definition: Glext.h:6722
#define vm_malloc(size)
Definition: pstypes.h:547
void brief_preload_fade_anim(brief_icon *bi)
vec3d gpoints1[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:28
void reset_parse(char *text)
Definition: parselo.cpp:3305
void hud_anim_init(hud_anim *ha, int sx, int sy, const char *filename)
Initialise the members of the hud_anim struct to default values.
Definition: hud.cpp:2169
GLuint const GLchar * name
Definition: Glext.h:5608
__inline void gr_line(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:791
GLdouble GLdouble right
Definition: Glext.h:10330
int bii_index_ship
Definition: ship.h:1344
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
void brief_set_camera_target(vec3d *pos, matrix *orient, int time)
GLbyte by
Definition: Glext.h:8237
void audiostream_close_file(int i, int fade)
Definition: audiostr.cpp:1772
debrief_stage stages[MAX_DEBRIEF_STAGES]
briefing * Briefing
bool fsspeech_play_from(int type)
Definition: fsspeech.h:52
void interpolate_matrix(matrix *result, matrix *goal, matrix *start, float elapsed_time, float total_time)
GLuint GLuint num
Definition: Glext.h:9089
color Color_bright_white
Definition: alphacolors.cpp:32
SCP_vector< colored_char > briefing_line
#define MAX_BRIEF_STAGE_LINES
brief_icon * brief_get_closeup_icon()
color Color_white
Definition: alphacolors.cpp:32
SCP_vector< char > Color_Tags
Definition: alphacolors.cpp:20
void brief_render_line(int line_num, int x, int y, int instance)
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
void vm_matrix_interpolate(const matrix *goal_orient, const matrix *curr_orient, const vec3d *w_in, float delta_t, matrix *next_orient, vec3d *w_out, const vec3d *vel_limit, const vec3d *acc_limit, int no_overshoot)
Definition: vecmat.cpp:1859
grid Global_grid
Definition: missiongrid.cpp:19
#define fl2i(fl)
Definition: floating.h:33
color Color_briefing_grid
Definition: alphacolors.cpp:29
player * Player
void brief_preload_anims()
#define g3_end_frame()
Definition: 3d.h:49
brief_screen bscreen
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
void generic_anim_init(generic_anim *ga)
Definition: generic.cpp:80
int sy
Definition: hud.h:27
void brief_move_icon_reset()
grid * brief_create_default_grid(void)
#define BI_USE_CARGO_ICON
#define MAX_BRIEF_LINE_W_1024
float planeD
Definition: missiongrid.h:27
int Briefing_paused
float vm_vec_copy_normalize(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:427
int gr_get_font_height()
Definition: font.cpp:187
#define MAX_BRIEF_STAGES
bool is_a_word_separator(char character)
void brief_grid_read_camera_controls(control_info *ci, float frametime)
GLfloat GLfloat p
Definition: Glext.h:8373
cfbp line_num
Definition: cfile.cpp:1072
#define F_NAME
Definition: parselo.h:34
GLenum src
Definition: Glext.h:5917
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
__inline void gr_aabitmap(int x, int y, int resize_mode=GR_RESIZE_FULL, bool mirror=false)
Definition: 2d.h:750
void cmd_brief_reset()
int hud_anim_load(hud_anim *ha)
Load a hud_anim.
Definition: hud.cpp:2193
SCP_vector< species_info > Species_info
int vm_vec_cmp(const vec3d *a, const vec3d *b)
Definition: vecmat.cpp:1415
struct colored_char colored_char
#define PF_SLIDE_ENABLED
Definition: physics.h:21
hull_check pos
Definition: lua.cpp:5050
void audiostream_play(int i, float volume, int looping)
Definition: audiostr.cpp:1803
void lcl_translate_brief_icon_name_pl(char *name)
Definition: localize.cpp:1300
int Num_fade_icons
void drop_leading_white_space(char *str)
Definition: parselo.cpp:115
#define MAX_TVT_TEAMS
Definition: globals.h:57
debriefing Debriefings[MAX_TVT_TEAMS]
#define i2fl(i)
Definition: floating.h:32
#define PF_PROJECTED
Definition: 3d.h:21
int brief_render_text(int line_offset, int x, int y, int h, float frametime, int instance, int line_spacing)
int Brief_stage_text_coords_multi[GR_NUM_RESOLUTIONS][2]
cmd_brief * Cur_cmd_brief
GLenum GLsizei len
Definition: Glext.h:6283
int brief_get_free_move_icon()
void brief_preload_highlight_anim(brief_icon *bi)
char filename[MAX_FILENAME_LEN]
Definition: hud.h:23
void brief_voice_load_all()
int audiostream_open(const char *filename, int type)
Definition: audiostr.cpp:1713
void brief_render_map(int stage_num, float frametime)
grid * The_grid
Definition: missiongrid.cpp:20
int brief_set_move_list(int new_stage, int current_stage, float time)
bool gr_unsize_screen_posf(float *x, float *y, float *w, float *h, int resize_mode)
Definition: 2d.cpp:538
#define MAX(a, b)
Definition: pstypes.h:299
vec3d gpoints3[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:30
color Color_text_heading
Definition: alphacolors.cpp:28
float fvi_ray_plane(vec3d *new_pnt, const vec3d *plane_pnt, const vec3d *plane_norm, const vec3d *ray_origin, const vec3d *ray_direction, float rad)
Definition: fvi.cpp:118
int is_white_space(char ch)
Definition: parselo.cpp:59
int bm_unload(int handle, int clear_render_targets, bool nodebug)
Unloads a bitmap's data, but not the bitmap info.
Definition: bmpman.cpp:2890
char filename[MAX_FILENAME_LEN]
Definition: generic.h:18
void compute_point_on_plane(vec3d *q, const plane *planep, const vec3d *p)
Definition: vecmat.cpp:1363
void audiostream_pause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1943
vec3d * vm_vec_cross(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:645
vec3d gpoints8[MAX_GRIDLINE_POINTS]
Definition: missiongrid.h:35
void brief_parse_icon_tbl()
Definition: vecmat.h:72
void snd_stop(int sig)
Definition: sound.cpp:875
const int HIGHEST_COLOR_STACK_INDEX
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
bool fsspeech_playing()
Definition: fsspeech.h:53
void brief_voice_unload_all()
physics_info physics
Definition: missiongrid.h:25
#define MAX_FADING_ICONS
icon_move_info * prev
#define FALSE
Definition: pstypes.h:400
void mission_brief_common_reset()
char label[MAX_LABEL_LEN]
SCP_map< char, color * > Tagged_Colors
Definition: alphacolors.cpp:18
int timer_get_milliseconds()
Definition: timer.cpp:150
void _cdecl gr_printf_menu(int x, int y, const char *format,...)
Definition: font.cpp:314
#define stricmp(s1, s2)
Definition: config.h:271
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:159
debriefing * Debriefing
const GLubyte * c
Definition: Glext.h:8376
float Master_voice_volume
Definition: sound.cpp:54
int skip_to_start_of_string(char *pstr, char *end)
Definition: parselo.cpp:404
hud_anim fadein_anim
int Lcl_gr
Definition: localize.cpp:48
#define MIN_BRIEF_ICONS
float brief_icon_get_dist_moved(icon_move_info *mi, float elapsed_time)
GLint y
Definition: Gl.h:1505
int Debrief_multi_stages_loaded
void brief_voice_stop(int stage_num)
#define MAX_DEBRIEF_STAGES
brief_line * lines
#define g3_start_frame(zbuffer_flag)
Definition: 3d.h:39
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
void get_camera_limits(const matrix *start_camera, const matrix *end_camera, float time, vec3d *acc_max, vec3d *w_max)
Definition: vecmat.cpp:2005
int Player_num
#define strcpy_s(...)
Definition: safe_strings.h:67
void brief_render_icons(int stage_num, float frametime)
void brief_render_fade_outs(float frametime)
int Cur_brief_id