FS2_Open
Open source remastering of the Freespace 2 engine
missiondebrief.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 "cfile/cfile.h"
14 #include "gamehelp/contexthelp.h"
16 #include "gamesnd/eventmusic.h"
17 #include "gamesnd/gamesnd.h"
18 #include "globalincs/alphacolors.h"
19 #include "globalincs/globals.h"
20 #include "graphics/font.h"
21 #include "iff_defs/iff_defs.h"
22 #include "io/key.h"
23 #include "io/timer.h"
24 #include "localization/localize.h"
27 #include "mission/missiongoals.h"
28 #include "missionui/chatbox.h"
30 #include "missionui/missionpause.h"
32 #include "network/multi.h"
33 #include "network/multi_campaign.h"
34 #include "network/multi_endgame.h"
35 #include "network/multi_kick.h"
36 #include "network/multi_pinfo.h"
37 #include "network/multimsgs.h"
38 #include "network/multiui.h"
39 #include "network/multiutil.h"
40 #include "osapi/osapi.h"
41 #include "parse/parselo.h"
42 #include "pilotfile/pilotfile.h"
43 #include "playerman/player.h"
44 #include "popup/popup.h"
45 #include "ship/ship.h"
46 #include "sound/audiostr.h"
47 #include "sound/fsspeech.h"
48 #include "stats/medals.h"
49 #include "stats/stats.h"
50 #include "ui/uidefs.h"
51 
52 
53 #define MAX_TOTAL_DEBRIEF_LINES 200
54 
55 #define TEXT_TYPE_NORMAL 1
56 #define TEXT_TYPE_RECOMMENDATION 2
57 
58 #define DEBRIEF_NUM_STATS_PAGES 4
59 #define DEBRIEF_MISSION_STATS 0
60 #define DEBRIEF_MISSION_KILLS 1
61 #define DEBRIEF_ALLTIME_STATS 2
62 #define DEBRIEF_ALLTIME_KILLS 3
63 
64 #define DEBRIEFING_FONT FONT1
65 
66 extern float Brief_text_wipe_time_elapsed;
67 
68 // 3rd coord is max width in pixels
70  { // GR_640
71  18, 118, 174
72  },
73  { // GR_1024
74  28, 193, 280
75  }
76 };
77 
79  { // GR_640
80  43, 140, 339, 303
81  },
82  { // GR_1024
83  69, 224, 535, 485
84  }
85 };
86 
88  276, // GR_640
89  450 // GR_1024
90 };
91 
93  { // GR_640
94  379, 137
95  },
96  { // GR_1024
97  578, 224
98  }
99 };
100 
102  { // GR_640
103  323, 453
104  },
105  { // GR_1024
106  323, 453
107  }
108 };
109 
110 #define MULTI_LIST_TEAM_OFFSET 16
111 
113  9, // GR_640
114  12 // GR_1024
115 };
116 
118  { // GR_640
119  416, 280, 195, 101
120  },
121  { // GR_1024
122  666, 448, 312, 162
123  }
124 };
125 
127  { // GR_640
128  411, 126
129  },
130  { // GR_1024
131  658, 203
132  }
133 };
134 
135 
137  { // GR_640
138  416, 140
139  },
140  { // GR_1024
141  666, 224
142  }
143 };
144 
145 // 0=x, 1=y, 2=width of the field
147  { // GR_640
148  423, 247, 189
149  },
150  { // GR_1024
151  666, 333, 67
152  }
153 };
154 
155 // 0=x, 1=y, 2=height of the field
157  { // GR_640
158  416, 210, 42
159  },
160  { // GR_1024
161  666, 333, 67
162  }
163 };
164 
165 // 0 = with medal
166 // 1 = without medal (text will use medal space)
167 #define DB_WITH_MEDAL 0
168 #define DB_WITHOUT_MEDAL 1
170  { // GR_640
171  123, 203
172  },
173  { // GR_1024
174  196, 312
175  }
176 };
177 
179  "DebriefSingle", // GR_640
180  "2_DebriefSingle" // GR_1024
181 };
183  "DebriefMulti", // GR_640
184  "2_DebriefMulti" // GR_1024
185 };
187  "Debrief-m", // GR_640
188  "2_Debrief-m" // GR_1024
189 };
190 
191 #define NUM_BUTTONS 18
192 #define NUM_TABS 2
193 
194 #define DEBRIEF_TAB 0
195 #define STATS_TAB 1
196 #define TEXT_SCROLL_UP 2
197 #define TEXT_SCROLL_DOWN 3
198 #define REPLAY_MISSION 4
199 #define RECOMMENDATIONS 5
200 #define FIRST_STAGE 6
201 #define PREV_STAGE 7
202 #define NEXT_STAGE 8
203 #define LAST_STAGE 9
204 #define MULTI_PINFO_POPUP 10
205 #define MULTI_KICK 11
206 #define MEDALS_BUTTON 12
207 #define PLAYER_SCROLL_UP 13
208 #define PLAYER_SCROLL_DOWN 14
209 #define HELP_BUTTON 15
210 #define OPTIONS_BUTTON 16
211 #define ACCEPT_BUTTON 17
212 
213 #define REPEAT 1
214 
215 //XSTR:OFF
217  "PleaseWait", // GR_640
218  "2_PleaseWait" // GR_1024
219 };
220 
221 //XSTR:ON
222 
223 typedef struct {
224  char text[NAME_LENGTH+1]; // name of ship type with a colon
225  int num; // how many ships of this type player has killed
227 
228 typedef struct {
229  int net_player_index; // index into Net_players[] array
230  int rank_bitmap; // bitmap id for rank
231  char callsign[CALLSIGN_LEN];
233 
234 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
235  { // GR_640
236  ui_button_info("DB_00", 6, 1, 37, 7, 0), // debriefing
237  ui_button_info("DB_01", 6, 21, 37, 23, 1), // statistics
238  ui_button_info("DB_02", 1, 195, -1, -1, 2), // scroll stats up
239  ui_button_info("DB_03", 1, 236, -1, -1, 3), // scroll stats down
240  ui_button_info("DB_04", 1, 428, 49, 447, 4), // replay mission
241  ui_button_info("DB_05", 17, 459, 49, 464, 5), // recommendations
242  ui_button_info("DB_06", 323, 454, -1, -1, 6), // first page
243  ui_button_info("DB_07", 348, 454, -1, -1, 7), // prev page
244  ui_button_info("DB_08", 372, 454, -1, -1, 8), // next page
245  ui_button_info("DB_09", 396, 454, -1, -1, 9), // last page
246  ui_button_info("DB_10", 441, 384, 433, 413, 10), // pilot info
247  ui_button_info("DB_11", 511, 384, 510, 413, 11), // kick
248  ui_button_info("DB_12", 613, 226, -1, -1, 12), // medals
249  ui_button_info("DB_13", 615, 329, -1, -1, 13), // scroll pilots up
250  ui_button_info("DB_14", 615, 371, -1, -1, 14), // scroll pilots down
251  ui_button_info("DB_15", 538, 431, 500, 440, 15), // help
252  ui_button_info("DB_16", 538, 455, 479, 464, 16), // options
253  ui_button_info("DB_17", 573, 432, 572, 413, 17), // accept
254  },
255  { // GR_1024
256  ui_button_info("2_DB_00", 10, 1, 59, 12, 0), // debriefing
257  ui_button_info("2_DB_01", 10, 33, 59, 37, 1), // statistics
258  ui_button_info("2_DB_02", 1, 312, -1, -1, 2), // scroll stats up
259  ui_button_info("2_DB_03", 1, 378, -1, -1, 3), // scroll stats down
260  ui_button_info("2_DB_04", 1, 685, 79, 715, 4), // replay mission
261  ui_button_info("2_DB_05", 28, 735, 79, 743, 5), // recommendations
262  ui_button_info("2_DB_06", 517, 726, -1, -1, 6), // first page
263  ui_button_info("2_DB_07", 556, 726, -1, -1, 7), // prev page
264  ui_button_info("2_DB_08", 595, 726, -1, -1, 8), // next page
265  ui_button_info("2_DB_09", 633, 726, -1, -1, 9), // last page
266  ui_button_info("2_DB_10", 706, 615, 700, 661, 10), // pilot info
267  ui_button_info("2_DB_11", 817, 615, 816, 661, 11), // kick
268  ui_button_info("2_DB_12", 981, 362, -1, -1, 12), // medals
269  ui_button_info("2_DB_13", 984, 526, -1, -1, 13), // scroll pilots up
270  ui_button_info("2_DB_14", 984, 594, -1, -1, 14), // scroll pilots down
271  ui_button_info("2_DB_15", 861, 689, 801, 705, 15), // help
272  ui_button_info("2_DB_16", 861, 728, 777, 744, 16), // options
273  ui_button_info("2_DB_17", 917, 692, 917, 692, 17), // accept
274  }
275 };
276 
277 // text
278 #define NUM_DEBRIEF_TEXT 10
279 #define MP_TEXT_INDEX_1 4
280 #define MP_TEXT_INDEX_2 5
281 #define MP_TEXT_INDEX_3 6
283  { // GR_640
284  { "Debriefing", 804, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][DEBRIEF_TAB].button },
285  { "Statistics", 1333, 37, 26, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][STATS_TAB].button },
286  { "Replay Mission", 444, 49, 447, UI_XSTR_COLOR_PINK, -1, &Buttons[0][REPLAY_MISSION].button },
287  { "Recommendations", 1334, 49, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][RECOMMENDATIONS].button },
288  { "Pilot", 1310, 433, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
289  { "Info", 1311, 433, 423, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
290  { "Kick", 1266, 510, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_KICK].button },
291  { "Help", 928, 500, 440, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HELP_BUTTON].button },
292  { "Options", 1036, 479, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][OPTIONS_BUTTON].button },
293  { "Accept", 1035, 572, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][ACCEPT_BUTTON].button },
294  },
295  { // GR_1024
296  { "Debriefing", 804, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][DEBRIEF_TAB].button },
297  { "Statistics", 1333, 59, 47, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][STATS_TAB].button },
298  { "Replay Mission", 444, 79, 715, UI_XSTR_COLOR_PINK, -1, &Buttons[1][REPLAY_MISSION].button },
299  { "Recommendations", 1334, 79, 743, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][RECOMMENDATIONS].button },
300  { "Pilot", 1310, 700, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
301  { "Info", 1311, 700, 679, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
302  { "Kick", 1266, 816, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_KICK].button },
303  { "Help", 928, 801, 705, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HELP_BUTTON].button },
304  { "Options", 1036, 780, 744, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][OPTIONS_BUTTON].button },
305  { "Accept", 1035, 917, 672, UI_XSTR_COLOR_PINK, -1, &Buttons[1][ACCEPT_BUTTON].button },
306  }
307 };
308 
309 
312 
313 static UI_WINDOW Debrief_ui_window;
314 static UI_BUTTON List_region;
315 static int Background_bitmap; // bitmap for the background of the debriefing
316 static int Award_bg_bitmap;
317 static int Debrief_multi_loading_bitmap;
318 static int Rank_bitmap;
319 static int Medal_bitmap;
320 static int Badge_bitmap;
321 
322 static int Promoted;
323 static int Debrief_accepted;
324 static int Turned_traitor;
325 static int Must_replay_mission;
326 
327 static int Current_mode;
328 static int New_mode;
329 static int Recommend_active;
330 static int Award_active;
331 static int Text_offset;
332 static int Num_text_lines = 0;
333 
334 static int Debrief_inited = 0;
335 static int New_stage;
336 static int Current_stage;
337 static int Num_stages;
338 static int Num_debrief_stages;
339 static int Stage_voice = -1;
340 static int Debrief_music_timeout = 0;
341 
342 static int Multi_list_size;
343 static int Multi_list_offset;
344 
346 
349 
350 // static int Debrief_voice_ask_for_cd;
351 
352 // voice id's for debriefing text
353 static int Debrief_voices[MAX_DEBRIEF_STAGES];
354 
355 #define DEBRIEF_VOICE_DELAY 400 // time to delay voice playback when a new stage starts
356 static int Debrief_cue_voice; // timestamp to cue the playback of the voice
357 static int Debrief_first_voice_flag = 1; // used to delay the first voice playback extra long
358 
359 static int Debriefing_paused = 0;
360 
362 
363 // pointer used for getting to debriefing information
364 debriefing Traitor_debriefing; // used when player is a traitor
365 
366 // pointers to the active stages for this debriefing
367 static debrief_stage *Debrief_stages[MAX_DEBRIEF_STAGES];
368 static debrief_stage Promotion_stage, Badge_stage;
369 static debrief_stats_kill_info *Debrief_stats_kills = NULL;
370 static debrief_multi_list_info Multi_list[MAX_PLAYERS];
372 
373 // flag indicating if we should display info for the given player (in multiplayer)
375 
376 // already shown skip mission popup?
377 static int Debrief_skip_popup_already_shown = 0;
378 
379 void debrief_text_init();
380 void debrief_accept(int ok_to_post_start_game_event = 1);
382 
383 
384 // promotion voice selection stuff
385 #define NUM_VOLITION_CAMPAIGNS 1
386 typedef struct {
387  char campaign_name[32];
389 } v_campaign;
390 
392  {
393  BUILTIN_CAMPAIGN, // the only campaign for now, but this leaves room for a mission pack
394  35 // make sure this is equal to the number of missions you gave in the corresponding Debrief_promotion_voice_mapping
395  }
396 };
397 
398 
399 // data for which voice goes w/ which mission
400 typedef struct voice_map {
401  char mission_file[32];
403 } voice_map;
404 
406  { // FreeSpace2 campaign
407  { "SM1-01.fs2", 1 },
408  { "SM1-02.fs2", 1 },
409  { "SM1-03.fs2", 1 },
410  { "SM1-04.fs2", 2 },
411  { "SM1-05.fs2", 2 },
412  { "SM1-06.fs2", 2 },
413  { "SM1-07.fs2", 2 },
414  { "SM1-08.fs2", 3 },
415  { "SM1-09.fs2", 3 },
416  { "SM1-10.fs2", 3 },
417 
418  { "SM2-01.fs2", 6 },
419  { "SM2-02.fs2", 6 },
420  { "SM2-03.fs2", 6 },
421  { "SM2-04.fs2", 7 },
422  { "SM2-05.fs2", 7 },
423  { "SM2-06.fs2", 7 },
424  { "SM2-07.fs2", 8 },
425  { "SM2-08.fs2", 8 },
426  { "SM2-09.fs2", 8 },
427  { "SM2-10.fs2", 8 },
428 
429  { "SM3-01.fs2", 8 },
430  { "SM3-02.fs2", 8 },
431  { "SM3-03.fs2", 8 },
432  { "SM3-04.fs2", 8 },
433  { "SM3-05.fs2", 8 },
434  { "SM3-06.fs2", 9 },
435  { "SM3-07.fs2", 9 },
436  { "SM3-08.fs2", 9 },
437  { "SM3-09.fs2", 9 },
438  { "SM3-10.fs2", 9 }, // no debriefing for 3-10
439 
440  { "loop1-1.fs2", 4 },
441  { "loop1-2.fs2", 4 },
442  { "loop1-3.fs2", 5 },
443  { "loop2-1.fs2", 4 },
444  { "loop2-2.fs2", 4 }
445  }
446 };
447 
448 static char* Debrief_award_background[GR_NUM_RESOLUTIONS] = {
449  "DebriefAward",
450  "2_DebriefAward"
451 };
452 
453 #define AWARD_TEXT_MAX_LINES 5
454 #define AWARD_TEXT_MAX_LINE_LENGTH 128
457 
458 
459 
460 // prototypes, you know you love 'em
461 void debrief_add_award_text(char *str);
463 
464 
465 
466 // functions
467 const char *debrief_tooltip_handler(const char *str)
468 {
469  if (!stricmp(str, NOX("@.Medal"))) {
470  if (Award_active){
471  return XSTR( "Medal", 435);
472  }
473 
474  } else if (!stricmp(str, NOX("@.Rank"))) {
475  if (Award_active){
476  return XSTR( "Rank", 436);
477  }
478 
479  } else if (!stricmp(str, NOX("@.Badge"))) {
480  if (Award_active){
481  return XSTR( "Badge", 437);
482  }
483 
484  } else if (!stricmp(str, NOX("@Medal"))) {
485  if (Medal_bitmap >= 0){
486  return Medals[Player->stats.m_medal_earned].name;
487  }
488 
489  } else if (!stricmp(str, NOX("@Rank"))) {
490  if (Rank_bitmap >= 0){
491  return Ranks[Promoted].name;
492  }
493 
494  } else if (!stricmp(str, NOX("@Badge"))) {
495  if (Badge_bitmap >= 0){
496  return Medals[Player->stats.m_badge_earned.back()].name;
497  }
498  }
499 
500  return NULL;
501 }
502 
503 // initialize the array of handles to the different voice streams
505 {
506  int i;
507 
508  for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
509  Debrief_voices[i] = -1;
510  }
511 }
512 
513 void debrief_load_voice_file(int voice_num, char *name)
514 {
515  int load_attempts = 0;
516  while(1) {
517 
518  if ( load_attempts++ > 5 ) {
519  break;
520  }
521 
522  Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
523  if ( Debrief_voices[voice_num] >= 0 ) {
524  break;
525  }
526 
527  // Don't bother to ask for the CD in multiplayer
528  if ( Game_mode & GM_MULTIPLAYER ) {
529  break;
530  }
531 
532  // couldn't load voice, ask user to insert CD (if necessary)
533 
534  // if ( Debrief_voice_ask_for_cd ) {
535  // if ( game_do_cd_check() == 0 ) {
536  // Debrief_voice_ask_for_cd = 0;
537  // break;
538  // }
539  // }
540  }
541 }
542 
543 // open and pre-load the stream buffers for the different voice streams
545 {
546  int i;
547 
548  // Debrief_voice_ask_for_cd = 1;
549 
550  for ( i=0; i<Num_debrief_stages; i++ ) {
551  if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
552  continue;
553  }
554  if ( strnicmp(Debrief_stages[i]->voice, NOX("none"), 4) ) {
555  debrief_load_voice_file(i, Debrief_stages[i]->voice);
556 // Debrief_voices[i] = audiostream_open(Debrief_stages[i]->voice, ASF_VOICE);
557  }
558  }
559 }
560 
561 // close all the briefing voice streams
563 {
564  int i;
565 
566  for ( i=0; i<MAX_DEBRIEF_STAGES; i++ ) {
567  if ( Debrief_voices[i] != -1 ) {
568  audiostream_close_file(Debrief_voices[i], 0);
569  Debrief_voices[i] = -1;
570  }
571  }
572 }
573 
574 // start playback of the voice for a particular briefing stage
576 {
577  if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
578  return;
579  }
580 
581  // no more stages? We are done then.
582  if (Stage_voice >= Num_debrief_stages){
583  return;
584  }
585 
586  // if in delayed start, see if delay has elapsed and start voice if so
587  if (Debrief_cue_voice) {
588  if (!timestamp_elapsed(Debrief_cue_voice)){
589  return;
590  }
591 
592  Stage_voice++; // move up to next voice
593  if ((Stage_voice < Num_debrief_stages) && (Debrief_voices[Stage_voice] >= 0)) {
594  audiostream_play(Debrief_voices[Stage_voice], Master_voice_volume, 0);
595  Debrief_cue_voice = 0; // indicate no longer in delayed start checking
596  }
597 
598  return;
599  }
600 
601  // see if voice is still playing. If so, do nothing yet.
602  if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
603  return;
604  }
605 
606  // set voice to play in a little while from now.
607  Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
608 }
609 
610 // stop playback of the voice for a particular briefing stage
612 {
613  if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
614  return;
615 
616  audiostream_stop(Debrief_voices[Stage_voice], 1, 0); // stream is automatically rewound
617  Stage_voice = -1;
618 
619  fsspeech_stop();
620 }
621 
622 extern int Briefing_music_handle;
623 
625 {
626  if (Debriefing_paused)
627  return;
628 
629  Debriefing_paused = 1;
630 
631  if (Briefing_music_handle >= 0) {
633  }
634 
635  if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
636  return;
637 
638  audiostream_pause(Debrief_voices[Stage_voice]);
639 
640  fsspeech_pause(true);
641 }
642 
644 {
645  if (!Debriefing_paused)
646  return;
647 
648  Debriefing_paused = 1;
649 
650  if (Briefing_music_handle >= 0) {
652  }
653 
654  if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
655  return;
656 
657  audiostream_unpause(Debrief_voices[Stage_voice]);
658 
659  fsspeech_pause(false);
660 }
661 
662 // function to deal with inserting possible promition and badge stages into the debriefing
663 // on the clients
665 {
666  int i;
667 
668  // possibly insert the badge stage first, them the promotion stage since they are
669  // inserted at the front of the debrief stages.
670  if ( Badge_bitmap >= 0 ) {
671  // move all stages forward one. Don't
672  for ( i = Num_debrief_stages; i > 0; i-- ) {
673  Debrief_stages[i] = Debrief_stages[i-1];
674  }
675  Debrief_stages[0] = &Badge_stage;
676  Num_debrief_stages++;
677  }
678 
679  if ( Promoted >= 0) {
680  // move all stages forward one
681  for ( i = Num_debrief_stages; i > 0; i-- ) {
682  Debrief_stages[i] = Debrief_stages[i-1];
683  }
684  Debrief_stages[0] = &Promotion_stage;
685  Num_debrief_stages++;
686  }
687 }
688 
689 
690 // function called from multiplayer clients to set up the debriefing information for them
691 // (sent from the server).
692 void debrief_set_multi_clients( int stage_count, int active_stages[] )
693 {
694  int i;
695 
696  // set up the right briefing for this guy
697  if(MULTI_TEAM){
699  } else {
700  Debriefing = &Debriefings[0];
701  }
702 
703  // see if this client was promoted -- if so, then add the first stage.
704  Num_debrief_stages = 0;
705 
706  // set the pointers to the debriefings for this client
707  for (i = 0; i < stage_count; i++) {
708  Debrief_stages[Num_debrief_stages++] = &Debriefing->stages[active_stages[i]];
709  }
710 
712 }
713 
714 // evaluate all stages for all teams. Server of a multiplayer game will have to send that
715 // information to all clients after leaving this screen.
717 {
718  debriefing *debriefp;
719 
721  int i, j, num_stages, stage_count[MAX_TVT_TEAMS];
722 
723  memset( stage_active, 0, sizeof(stage_active) );
724 
725  for (i=0; i<Num_teams; i++) {
726  debriefp = &Debriefings[i];
727  num_stages = 0;
728  stages[i] = stage_active[i];
729  for (j=0; j<debriefp->num_stages; j++) {
730  if ( eval_sexp(debriefp->stages[j].formula) ) {
731  stage_active[i][num_stages] = j;
732  num_stages++;
733  }
734  }
735 
736  stage_count[i] = num_stages;
737  }
738 
739  // if we're in campaign mode, evaluate campaign stuff
742  }
743 
744  // send the information to all clients.
745  send_debrief_info( stage_count, stages );
746 }
747 
748 
749 // --------------------------------------------------------------------------------------
750 // debrief_set_stages_and_multi_stuff()
751 //
752 // Set up the active stages for this debriefing
753 //
754 // returns: number of active debriefing stages
755 //
757 {
758  int i;
759  debriefing *debriefp;
760 
761  if ( MULTIPLAYER_CLIENT ) {
762  return 0;
763  }
764 
765  Num_debrief_stages = 0;
766 
767  if ( Game_mode & GM_MULTIPLAYER ) {
769  }
770 
771  // check to see if player is a traitor (looking at his team). If so, use the special
772  // traitor debriefing. Only done in single player
773  debriefp = Debriefing;
774  if ( !(Game_mode & GM_MULTIPLAYER) ) {
775  // although the no traitor flag check seems redundant it allows the mission designer to turn the traitor
776  // debriefing off before the mission ends and supply one themselves
778  debriefp = &Traitor_debriefing;
779  }
780 
781  Num_debrief_stages = 0;
782  if (Promoted >= 0) {
783  Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
784  }
785 
786  if (Badge_bitmap >= 0) {
787  Debrief_stages[Num_debrief_stages++] = &Badge_stage;
788  }
789 
790  for (i=0; i<debriefp->num_stages; i++) {
791  if (eval_sexp(debriefp->stages[i].formula) == 1) {
792  Debrief_stages[Num_debrief_stages++] = &debriefp->stages[i];
793  }
794  }
795 
796  return Num_debrief_stages;
797 }
798 
799 // init the buttons that are specific to the debriefing screen
801 {
802  ui_button_info *b;
803  int i;
804 
805  for ( i=0; i<NUM_BUTTONS; i++ ) {
806  b = &Buttons[gr_screen.res][i];
807  b->button.create( &Debrief_ui_window, "", b->x, b->y, 60, 30, 0 /*b->flags & REPEAT*/, 1 );
808  // set up callback for when a mouse first goes over a button
810  b->button.set_bmaps(b->filename);
811  b->button.link_hotspot(b->hotspot);
812  }
813 
814  // add all xstrs
815  for(i=0; i<NUM_DEBRIEF_TEXT; i++){
816  // multiplayer specific text
817  if((i == MP_TEXT_INDEX_1) || (i == MP_TEXT_INDEX_2) || (i == MP_TEXT_INDEX_3)){
818  // only add if in multiplayer mode
820  Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
821  }
822  }
823  // all other text
824  else {
825  Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
826  }
827  }
828 
829  // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
837 
838  // if in multiplayer, disable the button for all players except the host
839  // also disable for squad war matches
843  }
844  }
845 }
846 
847 // --------------------------------------------------------------------------------------
848 // debrief_ui_init()
849 //
851 {
852  // init ship selection masks and buttons
853  common_set_interface_palette("DebriefPalette"); // set the interface palette
854  Debrief_ui_window.create( 0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0 );
855  Debrief_ui_window.set_mask_bmap(Debrief_mask_name[gr_screen.res]);
856  Debrief_ui_window.tooltip_handler = debrief_tooltip_handler;
858 
859  // load in help overlay bitmap
862 
863  if ( Game_mode & GM_MULTIPLAYER ) {
864  // close down any old instances of the chatbox
865  chatbox_close();
866 
867  // create the new one
868  chatbox_create();
870  List_region.hide();
871 
872  }
873 
875 
876  if ( Background_bitmap < 0 ) {
877  Warning(LOCATION, "Could not load the background bitmap for debrief screen");
878  }
879 
880  Award_bg_bitmap = bm_load(Debrief_award_background[gr_screen.res]);
881  Debrief_multi_loading_bitmap = bm_load(Debrief_loading_bitmap_fname[gr_screen.res]);
882 }
883 
884 // Goober5000
886 {
887  int i, j;
888 
890  {
891  // Goober5000 - first see if the campaign supplied a persona index
892  // (0 means use the Volition default)
895 
896  // search through all official campaigns for our current campaign
897  for (i = 0; i < NUM_VOLITION_CAMPAIGNS; i++)
898  {
899  if (!stricmp(Campaign.filename, Volition_campaigns[i].campaign_name))
900  {
901  // now search through the mission filenames
902  for (j = 0; j < Volition_campaigns[i].num_missions; j++)
903  {
904  // found it!
905  if (!stricmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file))
906  {
907  return Debrief_promotion_voice_mapping[i][j].persona_index;
908  }
909  }
910  }
911  }
912  }
913 
914  // not found
915  return -1;
916 }
917 
918 // Goober5000
919 // V sez: "defaults to number 9 (Petrarch) for non-volition missions
920 // this is an ugly, nasty, hateful way of doing this, but it saves us changing the missions at this point"
921 void debrief_choose_voice(char *voice_dest, char *voice_base, int persona_index, int default_to_base = 0)
922 {
923  if (persona_index >= 0)
924  {
925  // get voice file
926  sprintf(voice_dest, NOX("%d_%s"), persona_index, voice_base);
927 
928  // if it exists, we're done
929  if (cf_exists_full(voice_dest, CF_TYPE_VOICE_DEBRIEFINGS))
930  return;
931  }
932 
933  // that didn't work, so use the default
934 
935  // use the base file; don't prepend anything to it
936  if (default_to_base)
937  {
938  strcpy(voice_dest, voice_base);
939  }
940  // default to Petrarch
941  else
942  {
943  strcpy(voice_dest, "9_");
944  strcpy(voice_dest + 2, voice_base);
945  }
946 }
947 
948 void debrief_choose_medal_variant(char *buf, int medal_earned, int zero_based_version_index)
949 {
950  Assert(buf != NULL && medal_earned >= 0 && zero_based_version_index >= 0);
951 
952  // start with the regular file name, adapted for resolution
953  sprintf(buf, NOX("%s%s"), Resolution_prefixes[gr_screen.res], Medals[medal_earned].debrief_bitmap);
954 
955  // if the medal has multiple versions, we may want to choose a specific bitmap
956  char *p = strstr(buf, "##");
957  if (p != NULL)
958  {
959  int version;
960  char number[8];
961 
962  // possible to earn more than we have variants for
963  if (zero_based_version_index >= Medals[medal_earned].num_versions)
964  version = Medals[medal_earned].num_versions - 1;
965  else
966  version = zero_based_version_index;
967 
968  // also, this is dumb
969  if (Medals[medal_earned].version_starts_at_1)
970  version++;
971 
972  sprintf(number, NOX("%.2d"), version);
973  Assert(strlen(number) == 2);
974  strncpy(p, number, 2);
975  }
976 }
977 
979 {
980  char buf[80];
981 
982  Rank_bitmap = -1;
983  Medal_bitmap = -1;
984  Badge_bitmap = -1;
985  Promoted = -1;
986 
987  // be sure there are no old award texts floating around
989 
990  // handle medal earned
991  if ( Player->stats.m_medal_earned != -1 ) {
993  Medal_bitmap = bm_load(buf);
994 
996  }
997 
998  // handle promotions
999  if ( Player->stats.m_promotion_earned != -1 ) {
1000  Promoted = Player->stats.m_promotion_earned;
1002  Rank_bitmap = bm_load(buf);
1003 
1004  // see if we have a persona
1005  int persona_index = debrief_find_persona_index();
1006 
1007  // use persona-specific promotion text if it exists; otherwise, use default
1008  if (Ranks[Promoted].promotion_text.find(persona_index) != Ranks[Promoted].promotion_text.end()) {
1009  Promotion_stage.text = Ranks[Promoted].promotion_text[persona_index];
1010  } else {
1011  Promotion_stage.text = Ranks[Promoted].promotion_text[-1];
1012  }
1013  Promotion_stage.recommendation_text = "";
1014 
1015  // choose appropriate promotion voice for this mission
1016  debrief_choose_voice(Promotion_stage.voice, Ranks[Promoted].promotion_voice_base, persona_index);
1017 
1018  debrief_add_award_text(Ranks[Promoted].name);
1019  }
1020 
1021  // handle badge earned
1022  // only grant badge if earned and allowed. (no_promotion really means no promotion and no badges)
1023  if ( Player->stats.m_badge_earned.size() ) {
1025  Badge_bitmap = bm_load(buf);
1026 
1027  // see if we have a persona
1028  int persona_index = debrief_find_persona_index();
1029 
1030  // use persona-specific badge text if it exists; otherwise, use default
1031  if (Medals[Player->stats.m_badge_earned.back()].promotion_text.find(persona_index) != Medals[Player->stats.m_badge_earned.back()].promotion_text.end()) {
1032  Badge_stage.text = Medals[Player->stats.m_badge_earned.back()].promotion_text[persona_index];
1033  } else {
1034  Badge_stage.text = Medals[Player->stats.m_badge_earned.back()].promotion_text[-1];
1035  }
1036  Badge_stage.recommendation_text = "";
1037 
1038  // choose appropriate badge voice for this mission
1039  debrief_choose_voice(Badge_stage.voice, Medals[Player->stats.m_badge_earned.back()].voice_base, persona_index);
1040 
1042  }
1043 
1044  if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0)) {
1045  Award_active = 1;
1046  } else {
1047  Award_active = 0;
1048  }
1049 }
1050 
1051 // debrief_traitor_init() initializes local data which could be used if the player leaves the
1052 // mission a traitor. The same debriefing always gets played
1054 {
1055  static int inited = 0;
1056 
1057  if ( !inited ) {
1058  debriefing *debrief;
1059  debrief_stage *stagep;
1060  int stage_num;
1061 
1062  try
1063  {
1064  read_file_text("traitor.tbl", CF_TYPE_TABLES);
1065  reset_parse();
1066 
1067  // simplied form of the debriefing stuff.
1068  debrief = &Traitor_debriefing;
1069  required_string("#Debriefing_info");
1070 
1071  required_string("$Num stages:");
1072  stuff_int(&debrief->num_stages);
1073  Assert(debrief->num_stages == 1);
1074 
1075  stage_num = 0;
1076  stagep = &debrief->stages[stage_num++];
1077  required_string("$Formula:");
1078  stagep->formula = get_sexp_main();
1079  required_string("$multi text");
1080  stuff_string(stagep->text, F_MULTITEXT, NULL);
1081  required_string("$Voice:");
1082  char traitor_voice_file[MAX_FILENAME_LEN];
1083  stuff_string(traitor_voice_file, F_FILESPEC, MAX_FILENAME_LEN);
1084 
1085  // DKA 9/13/99 Only 1 traitor msg for FS2
1086  // if ( Player->main_hall ) {
1087  // strcpy_s(stagep->voice, NOX("3_"));
1088  // } else {
1089  // strcpy_s(stagep->voice, NOX("1_"));
1090  // }
1091 
1092  // Goober5000
1093  debrief_choose_voice(stagep->voice, traitor_voice_file, debrief_find_persona_index(), 1);
1094 
1095  required_string("$Recommendation text:");
1097 
1098  inited = 1;
1099  }
1100  catch (const parse::ParseException& e)
1101  {
1102  mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "traitor.tbl", e.what()));
1103  return;
1104  }
1105  }
1106 
1107  // disable the accept button if in single player and I am a traitor
1108  Debrief_accepted = 0;
1109  Turned_traitor = Must_replay_mission = 0;
1111  if (Player_ship->team == Iff_traitor){
1112  Turned_traitor = 1;
1113  }
1114 
1116  Must_replay_mission = 1;
1117  }
1118  }
1119 
1120  if (Turned_traitor || Must_replay_mission) {
1121  Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1122 
1123  // kill off any stats
1126  }
1127 }
1128 
1129 // initialization for listing of players in game
1131 {
1132  Multi_list_size = 0; // number of net players to choose from
1133  Multi_list_offset = 0;
1134 
1135  Multi_list_select = -1;
1136 
1137  if ( !(Game_mode & GM_MULTIPLAYER) )
1138  return;
1139 
1141 
1142  // switch stats display to this newly selected player
1143  set_player_stats(Multi_list[0].net_player_index);
1144  strcpy_s(Debrief_current_callsign, Multi_list[0].callsign);
1145  Debrief_player = Player;
1146 }
1147 
1149 {
1150  // if we're at the beginning of the list, don't do anything
1151  if(Multi_list_offset == 0){
1153  return;
1154  }
1155 
1156  // otherwise scroll up
1157  Multi_list_offset--;
1159 }
1160 
1162 {
1163  // if we can scroll down no further
1164  if(Multi_list_size < Debrief_multi_list_team_max_display[gr_screen.res]){
1166  return;
1167  }
1168  if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1170  return;
1171  }
1172 
1173  // otherwise scroll down
1174  Multi_list_offset++;
1176 }
1177 
1178 // draw the connected net players
1180 {
1181  int y, z, font_height,idx;
1182  char str[CALLSIGN_LEN+5];
1183  net_player *np;
1184 
1185  font_height = gr_get_font_height();
1186 
1187  // if we currently have no item picked, pick a reasonable one
1188  if((Multi_list_size >= 0) && (Multi_list_select == -1)){
1189  // select the entry which corresponds to the local player
1190  Multi_list_select = 0;
1191  for(idx=0;idx<Multi_list_size;idx++){
1192  if(Multi_list[idx].net_player_index == MY_NET_PLAYER_NUM){
1194 
1195  // switch stats display to this newly selected player
1196  set_player_stats(Multi_list[idx].net_player_index);
1197  strcpy_s(Debrief_current_callsign, Multi_list[idx].callsign);
1198  Debrief_player = Net_players[Multi_list[idx].net_player_index].m_player;
1199  break;
1200  }
1201  }
1202  }
1203 
1204  // draw the list itself
1205  y = 0;
1206  z = Multi_list_offset;
1207  while (y + font_height <= Debrief_list_coords[gr_screen.res][3]){
1208  np = &Net_players[Multi_list[z].net_player_index];
1209 
1210  if (z >= Multi_list_size){
1211  break;
1212  }
1213  // set the proper text color for the highlight
1214  if(np->flags & NETINFO_FLAG_GAME_HOST){
1215  if(Multi_list_select == z){
1217  } else {
1219  }
1220  } else {
1221  if(Multi_list_select == z){
1223  } else {
1225  }
1226  }
1227 
1228  // blit the proper indicator - skipping observers
1229  if(!((np->flags & NETINFO_FLAG_OBSERVER) && !(np->flags & NETINFO_FLAG_OBS_PLAYER))){
1231  // team 0
1232  if(np->p_info.team == 0){
1233  // draw his "selected" icon
1237  }
1238  // draw his "normal" icon
1239  else if(Multi_common_icons[MICON_TEAM0] != -1){
1242  }
1243  } else if(np->p_info.team == 1){
1244  // draw his "selected" icon
1248  }
1249  // draw his "normal" icon
1250  else if(Multi_common_icons[MICON_TEAM1] != -1){
1253  }
1254  }
1255  } else {
1256  // draw the team 0 selected icon
1260  }
1261  }
1262  }
1263 
1264  strcpy_s(str,Multi_list[z].callsign);
1265  if(Net_players[Multi_list[z].net_player_index].flags & NETINFO_FLAG_OBSERVER && !(Net_players[Multi_list[z].net_player_index].flags & NETINFO_FLAG_OBS_PLAYER)){
1266  strcat_s(str,XSTR( "(O)", 438));
1267  }
1268 
1269  // bli
1271 
1272  y += font_height;
1273  z++;
1274  }
1275 }
1276 
1278 {
1279  if(Multi_list_select >= 0){
1281  multi_kick_player(Multi_list[Multi_list_select].net_player_index);
1282  }
1283 }
1284 
1285 
1286 // get optional mission popup text
1287 void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
1288 {
1289  Assert(buffer != NULL);
1290  // base message
1291 
1292  if (mission_loop_desc == NULL) {
1293  strcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490));
1294  mprintf(("No mission loop description available\n"));
1295  } else {
1296  strcpy(buffer, mission_loop_desc);
1297  }
1298 
1299  strcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491));
1300 }
1301 
1302 // what to do when the accept button is hit
1303 void debrief_accept(int ok_to_post_start_game_event)
1304 {
1305  extern int Weapon_energy_cheat;
1306  int go_loop = 0;
1307  Weapon_energy_cheat=0;
1308 
1309  if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1310  const char *str;
1311  int z;
1312 
1313  if (Game_mode & GM_MULTIPLAYER) {
1314  return;
1315  }
1316 
1317  if (Player_ship->team == Iff_traitor){
1318  str = XSTR( "Your career is over, Traitor! You can't accept new missions!", 439);
1319  }/* else if (Cheats_enabled) {
1320  str = XSTR( "You are a cheater. You cannot accept this mission!", 440);
1321  }*/ else {
1322  str = XSTR( "You have failed this mission and cannot accept. What do you you wish to do instead?", 441);
1323  }
1324 
1325  z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
1326  if (z == 2){
1327  gameseq_post_event(GS_EVENT_START_GAME); // restart mission
1328  } else if ( z == 1 ) {
1329  gameseq_post_event(GS_EVENT_END_GAME); // return to main hall, tossing stats
1330  }
1331 
1332  return;
1333  }
1334 
1335  Debrief_accepted = 1;
1336  // save mission stats
1337  if (Game_mode & GM_MULTIPLAYER) {
1338  // note that multi_debrief_accept_hit() will handle all mission_campaign_* calls on its own
1339  // as well as doing stats transfers, etc.
1341  } else {
1342  int play_commit_sound = 1;
1343  // only write the player's stats if he's accepted
1344 
1345  // if we are just playing a single mission, then don't do many of the things
1346  // that need to be done. Nothing much should happen when just playing a single
1347  // mission that isn't in a campaign.
1348  if ( Game_mode & GM_CAMPAIGN_MODE ) {
1349 
1351 
1352  // check for possible mission loop
1353  // check for (1) mission loop available, (2) don't have to repeat last mission
1354  if(!(Game_mode & GM_MULTIPLAYER)){
1355  int cur = Campaign.current_mission;
1356  bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
1359  }
1360 
1361  if ( (Campaign.missions[cur].flags & CMISSION_FLAG_HAS_LOOP) && (Campaign.loop_mission != -1) && !require_repeat_mission ) {
1362  /*
1363  char buffer[512];
1364  debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1365 
1366  int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1367  if (choice == 1) {
1368  Campaign.loop_enabled = 1;
1369  Campaign.next_mission = Campaign.loop_mission;
1370  }
1371  */
1372  go_loop = 1;
1373  }
1374  }
1375 
1376  // loopy loopy time
1377  if (go_loop && ok_to_post_start_game_event) {
1379  }
1380  // continue as normal
1381  else {
1382  // end the mission
1383  // if we can loop, but don't want to right now, then setup so that we can later
1384  mission_campaign_mission_over( (go_loop) ? false : true );
1385 
1386  // check to see if we are out of the loop now
1388  Campaign.loop_enabled = 0;
1389  }
1390 
1391  // check if campaign is over, or if FREDer wants the mainhall
1394  } else {
1395  if ( ok_to_post_start_game_event ) {
1397  } else {
1398  play_commit_sound = 0;
1399  }
1400  }
1401  }
1402  } else {
1404  }
1405 
1406  // Goober5000
1407  if ( play_commit_sound && !(The_mission.flags & MISSION_FLAG_TOGGLE_DEBRIEFING)) {
1409  }
1410 
1411  game_flush();
1412  }
1413 }
1414 
1416 {
1417  New_mode = Current_mode + 1;
1418  if (New_mode >= NUM_TABS)
1419  New_mode = 0;
1420 }
1421 
1423 {
1424  New_mode = Current_mode - 1;
1425  if (New_mode < 0)
1426  New_mode = NUM_TABS - 1;
1427 }
1428 
1429 // --------------------------------------------------------------------------------------
1430 // debrief_next_stage()
1431 //
1433 {
1434  if (Current_stage < Num_stages - 1) {
1435  New_stage = Current_stage + 1;
1437 
1438  } else
1440 }
1441 
1442 // --------------------------------------------------------------------------------------
1443 // debrief_prev_stage()
1444 //
1446 {
1447  if (Current_stage) {
1448  New_stage = Current_stage - 1;
1450 
1451  } else
1453 }
1454 
1455 // --------------------------------------------------------------------------------------
1456 // debrief_first_stage()
1458 {
1459  if (Current_stage) {
1460  New_stage = 0;
1462 
1463  } else
1465 }
1466 
1467 // --------------------------------------------------------------------------------------
1468 // debrief_last_stage()
1470 {
1471  if (Current_stage != Num_stages - 1) {
1472  New_stage = Num_stages - 1;
1474 
1475  } else
1477 }
1478 
1479 // draw what stage number the debriefing is on
1481 {
1482  int w;
1483  char buf[64];
1484 
1485  if (Num_stages < 2)
1486  return;
1487 
1488  sprintf(buf, XSTR( "%d of %d", 445), Current_stage + 1, Num_stages);
1489  gr_get_string_size(&w, NULL, buf);
1493 }
1494 
1495 // render the mission difficulty at the specified y location
1497 {
1498  gr_string(0, y_loc, XSTR( "Skill Level", 1509), GR_RESIZE_MENU);
1500 }
1501 
1502 // render the mission time at the specified y location
1504 {
1505  char time_str[30];
1506 
1507  game_format_time(Missiontime, time_str);
1508  gr_string(0, y_loc, XSTR( "Mission Time", 446), GR_RESIZE_MENU);
1509  gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str, GR_RESIZE_MENU);
1510 }
1511 
1512 // render out the stats info to the scroll window
1513 //
1515 {
1516  int i, y, font_height;
1517 
1521  font_height = gr_get_font_height();
1522  y = 30;
1523 
1525 
1527  y += 2*font_height;
1528 
1529  switch ( Current_stage ) {
1530  case DEBRIEF_MISSION_STATS:
1531  i = Current_stage - 1;
1532  if ( i < 0 )
1533  i = 0;
1534 
1535  // display mission completion time
1537 
1538  y += 2*font_height;
1539  show_stats_label(i, 0, y, font_height);
1540  show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
1541  break;
1542  case DEBRIEF_ALLTIME_STATS:
1543  i = Current_stage - 1;
1544  if ( i < 0 )
1545  i = 0;
1546 
1547  show_stats_label(i, 0, y, font_height);
1548  show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
1549  break;
1550 
1551  case DEBRIEF_ALLTIME_KILLS:
1552  case DEBRIEF_MISSION_KILLS:
1553  i = Text_offset;
1554  while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1555  if (i >= Num_text_lines)
1556  break;
1557 
1558  if (!i) {
1559  if ( Current_stage == DEBRIEF_MISSION_KILLS )
1560  gr_printf_menu(0, y, XSTR( "Mission Kills by Ship Type", 447));
1561  else
1562  gr_printf_menu(0, y, XSTR( "All-time Kills by Ship Type", 448));
1563 
1564  } else if (i > 1) {
1565  //Assert: Was debrief_setup_ship_kill_stats called?
1566  Assert(Debrief_stats_kills != NULL);
1567 
1568  gr_printf_menu(0, y, "%s", Debrief_stats_kills[i - 2].text);
1569  gr_printf_menu(Debrief_text_x2[gr_screen.res], y, "%d", Debrief_stats_kills[i - 2].num);
1570  }
1571 
1572  y += font_height;
1573  i++;
1574  }
1575 
1576  if (Num_text_lines == 2) {
1577  if ( Current_stage == DEBRIEF_MISSION_KILLS )
1578  gr_printf_menu(0, y, XSTR( "(No ship kills this mission)", 449));
1579  else
1580  gr_printf_menu(0, y, XSTR( "(No ship kills)", 450));
1581  }
1582 
1583  break;
1584 
1585  default:
1586  Int3();
1587  break;
1588  }
1589 
1590  gr_reset_clip();
1591 }
1592 
1593 // do action for when the replay button is pressed
1595 {
1596  if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
1597  int choice;
1598  choice = popup(0, 2, POPUP_CANCEL, XSTR( "&Replay", 451), XSTR( "If you choose to replay this mission, you will be required to complete it again before proceeding to future missions.\n\nIn addition, any statistics gathered during this mission will be discarded if you choose to replay.", 452));
1599 
1600  if (choice != 1){
1601  return;
1602  }
1603  }
1604 
1605  gameseq_post_event(GS_EVENT_START_GAME); // restart mission
1607 }
1608 
1609 // -------------------------------------------------------------------
1610 // debrief_redraw_pressed_buttons()
1611 //
1612 // Redraw any debriefing buttons that are pressed down. This function is needed
1613 // since we sometimes need to draw pressed buttons last to ensure the entire
1614 // button gets drawn (and not overlapped by other buttons)
1615 //
1617 {
1618  int i;
1619  UI_BUTTON *b;
1620 
1621  for ( i=0; i<NUM_BUTTONS; i++ ) {
1622  b = &Buttons[gr_screen.res][i].button;
1623  // don't draw the recommendations button if we're in stats mode
1624  if ( b->button_down() ) {
1625  b->draw_forced(2);
1626  }
1627  }
1628 }
1629 
1630 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
1631 //
1633 {
1634  switch (num) {
1635  case DEBRIEF_TAB:
1636  Buttons[gr_screen.res][RECOMMENDATIONS].button.enable();
1637  // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
1638  if (num != Current_mode){
1640  }
1641  New_mode = num;
1642  break;
1643  case STATS_TAB:
1644  // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 1; // allows failure sound to be played
1646  if (num != Current_mode){
1648  }
1649  New_mode = num;
1650  break;
1651 
1652  case TEXT_SCROLL_UP:
1653  if (Text_offset) {
1654  Text_offset--;
1656  } else {
1658  }
1659  break;
1660 
1661  case TEXT_SCROLL_DOWN:
1662  if (Max_debrief_Lines < (Num_text_lines - Text_offset)) {
1663  Text_offset++;
1665  } else {
1667  }
1668  break;
1669 
1670  case REPLAY_MISSION:
1671  if(Game_mode & GM_MULTIPLAYER){
1673  } else {
1675  }
1676  break;
1677 
1678  case RECOMMENDATIONS:
1680  Recommend_active = !Recommend_active;
1682  break;
1683 
1684  case FIRST_STAGE:
1686  break;
1687 
1688  case PREV_STAGE:
1690  break;
1691 
1692  case NEXT_STAGE:
1694  break;
1695 
1696  case LAST_STAGE:
1698  break;
1699 
1700  case HELP_BUTTON:
1703  break;
1704 
1705  case OPTIONS_BUTTON:
1708  break;
1709 
1710  case ACCEPT_BUTTON:
1711  debrief_accept();
1712  break;
1713 
1714  case MEDALS_BUTTON:
1717  break;
1718 
1719  case PLAYER_SCROLL_UP:
1721  break;
1722 
1723  case PLAYER_SCROLL_DOWN:
1725  break;
1726 
1727  case MULTI_PINFO_POPUP:
1729  break;
1730 
1731  case MULTI_KICK:
1733  break;
1734  } // end swtich
1735 }
1736 
1738 {
1739  int i;
1740  //ushort *kill_arr;
1741  int *kill_arr; //DTP max ships
1742  debrief_stats_kill_info *kill_info;
1743 
1744  Assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
1745  if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
1746  return;
1747 
1748  if(Debrief_stats_kills == NULL)
1749  {
1750  Debrief_stats_kills = new debrief_stats_kill_info[Ship_info.size()];
1751  }
1752 
1753  Assert(Debrief_player != NULL);
1754 
1755  // kill_ar points to an array of MAX_SHIP_TYPE ints
1756  if ( Current_stage == DEBRIEF_MISSION_KILLS ) {
1757  kill_arr = Debrief_player->stats.m_okKills;
1758  } else {
1759  kill_arr = Debrief_player->stats.kills;
1760  }
1761 
1762  Num_text_lines = 0;
1763  i = 0;
1764  for ( auto it = Ship_info.begin(); it != Ship_info.end(); i++, ++it ) {
1765 
1766  // code used to add in mission kills, but the new system assumes that the player will accept, so
1767  // all time stats already have mission stats added in.
1768  if ( kill_arr[i] <= 0 ){
1769  continue;
1770  }
1771 
1772 
1773  kill_info = &Debrief_stats_kills[Num_text_lines++];
1774 
1775  kill_info->num = kill_arr[i];
1776 
1777  strcpy_s(kill_info->text, it->name);
1778  strcat_s(kill_info->text, NOX(":"));
1779  }
1780 
1781  Num_text_lines += 2;
1782 }
1783 
1784 // Iterate through the debriefing buttons, checking if they are pressed
1786 {
1787  int i;
1788 
1789  for ( i=0; i<NUM_BUTTONS; i++ ) {
1790  if ( Buttons[gr_screen.res][i].button.pressed() ) {
1792  }
1793  }
1794 
1795  int y, z;
1796 
1797  if ( !(Game_mode & GM_MULTIPLAYER) )
1798  return;
1799 
1800  if (List_region.pressed()) {
1801  List_region.get_mouse_pos(NULL, &y);
1802  z = Multi_list_offset + y / gr_get_font_height();
1803  if ((z >= 0) && (z < Multi_list_size)) {
1804  // switch stats display to this newly selected player
1805  set_player_stats(Multi_list[z].net_player_index);
1806  strcpy_s(Debrief_current_callsign, Multi_list[z].callsign);
1807  Debrief_player = Net_players[Multi_list[z].net_player_index].m_player;
1808  Multi_list_select = z;
1809  debrief_setup_ship_kill_stats(Current_stage);
1811  }
1812  }
1813 
1814  // if the player was double clicked on - we should popup a player info popup
1815  /*
1816  if (List_region.double_clicked()) {
1817  Debrief_should_show_popup = 1;
1818  }
1819  */
1820 }
1821 
1822 // setup the debriefing text lines for rendering
1824 {
1825  int r_count = 0;
1826  const char *src;
1827  int i;
1828 
1829  // If no wav files are being used use speech simulation
1830  bool use_sim_speech = true;
1831  for (i = 0; i < MAX_DEBRIEF_STAGES; i++) {
1832  if(Debrief_voices[i] != -1) {
1833  use_sim_speech = false;
1834  break;
1835  }
1836  }
1837 
1838  Num_text_lines = Text_offset = brief_color_text_init("", Debrief_text_wnd_coords[gr_screen.res][2], default_debriefing_color, 0, 0); // Initialize color stuff -MageKing17
1839 
1841 
1842  if (Current_mode == DEBRIEF_TAB) {
1843  for (i=0; i<Num_debrief_stages; i++) {
1844  if (i)
1845  // add a blank line between stages
1847 
1848  src = Debrief_stages[i]->text.c_str();
1849 
1850  if (*src) {
1852 
1853  if (use_sim_speech && !Recommend_active) {
1854  fsspeech_stuff_buffer(src);
1855  fsspeech_stuff_buffer("\n");
1856  }
1857  }
1858 
1859  if (Recommend_active) {
1860  src = Debrief_stages[i]->recommendation_text.c_str();
1861 
1862  if ((i == Num_debrief_stages - 1) && !r_count && !*src)
1863  src = XSTR( "We have no recommendations for you.", 1054);
1864 
1865  if (*src) {
1867 
1869  r_count++;
1870 
1871  if (use_sim_speech) {
1872  fsspeech_stuff_buffer(src);
1873  fsspeech_stuff_buffer("\n");
1874  }
1875  }
1876  }
1877  }
1878  Brief_text_wipe_time_elapsed = BRIEF_TEXT_WIPE_TIME; // Skip the wipe effect
1879 
1880  if(use_sim_speech) {
1882  }
1883  return;
1884  }
1885 
1886  // not in debriefing mode, must be in stats mode
1887  Num_text_lines = 0;
1888  debrief_setup_ship_kill_stats(Current_stage);
1889 }
1890 
1891 
1892 // --------------------------------------------------------------------------------------
1893 //
1894 
1895 // start up the appropriate music
1896 static void debrief_init_music()
1897 {
1898  int score = SCORE_DEBRIEF_AVERAGE;
1899 
1900  Debrief_music_timeout = 0;
1901 
1903  // you failed the mission, so you get the fail music
1904  score = SCORE_DEBRIEF_FAIL;
1905  } else if ( mission_goals_met() ) {
1906  // you completed all primaries and secondaries, so you get the win music
1907  score = SCORE_DEBRIEF_SUCCESS;
1908  } else {
1909  // you somehow passed the mission, so you get a little something for your efforts.
1910  score = SCORE_DEBRIEF_AVERAGE;
1911  }
1912 
1913  // if multi client then give a slight delay before playing average music
1914  // since we'd like to eval the goals once more for slow clients
1915  if ( MULTIPLAYER_CLIENT && (score == SCORE_DEBRIEF_AVERAGE) ) {
1916  Debrief_music_timeout = timestamp(2000);
1917  return;
1918  }
1919 
1920  common_music_init(score);
1921 }
1922 
1924 {
1925  int i;
1926 
1927  Assert(!Debrief_inited);
1928 // Campaign.loop_enabled = 0;
1930 
1931  // MageKing17 - Set the font so that wordwrapping in brief_color_text_init() calculates based on the same font as the debriefing itself.
1933 
1934  // set up the right briefing for this guy
1935  if(MULTI_TEAM){
1937  } else {
1938  Debriefing = &Debriefings[0];
1939  }
1940 
1941  // Goober5000 - replace any variables with their values
1942  for (i = 0; i < Debriefing->num_stages; i++) {
1945  }
1946 
1947  // no longer is mission
1948  Game_mode &= ~(GM_IN_MISSION);
1949 
1950  game_flush();
1951  Current_mode = -1;
1952  New_mode = DEBRIEF_TAB;
1953  Recommend_active = Award_active = 0;
1954 
1955  Current_stage = -1;
1956  New_stage = 0;
1957  Debrief_cue_voice = 0;
1958  Num_text_lines = 0;
1959  Debrief_first_voice_flag = 1;
1960 
1962 
1963  if ( (Game_mode & GM_CAMPAIGN_MODE) && ( !MULTIPLAYER_CLIENT ) ) {
1964  // MUST store goals and events first - may be used to evaluate next mission
1965  // store goals and events
1967 
1968  // evaluate next mission
1970  }
1971 
1972  // call traitor init before calling scoring_level_close. traitor init will essentially nullify
1973  // any stats
1974  if ( !(Game_mode & GM_MULTIPLAYER) ) { // only do for single player
1975  debrief_traitor_init(); // initialize data needed if player becomes traitor.
1976  }
1977 
1978  // call scoring level close for my stats. Needed for award_init. The stats will
1979  // be backed out if used chooses to replace them.
1981 
1982  debrief_ui_init(); // init UI items
1984  show_stats_init();
1986 
1988 
1989 // rank_bitmaps_clear();
1990 // rank_bitmaps_load();
1991 
1993  Debrief_player = Player;
1994 // Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
1995 
1996  // set up the Debrief_stages[] and Recommendations[] arrays. Only do the following stuff
1997  // for non-clients (i.e. single and game server). Multiplayer clients will get their debriefing
1998  // info directly from the server.
1999  if ( !MULTIPLAYER_CLIENT ) {
2001 
2002  if ( Num_debrief_stages <= 0 ) {
2003  Num_debrief_stages = 0;
2004  } else {
2006  }
2007  } else {
2008  // multiplayer client may have already received their debriefing info. If they have not,
2009  // then set the num debrief stages to 0
2010  if ( !Debrief_multi_stages_loaded ) {
2011  Num_debrief_stages = 0;
2012  }
2013  }
2014 
2015  /*
2016  if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2017  common_music_init(SCORE_DEBRIEF_SUCCESS);
2018  } else {
2019  common_music_init(SCORE_DEBRIEF_FAIL);
2020  }
2021  */
2022 
2023  // Just calculate this once instead of every frame. -MageKing17
2024  Max_debrief_Lines = Debrief_text_wnd_coords[gr_screen.res][3]/gr_get_font_height(); //Make the max number of lines dependent on the font height.
2025 
2026  // start up the appropriate music
2027  debrief_init_music();
2028 
2029  if (Game_mode & GM_MULTIPLAYER) {
2031 
2032  // if i'm not the host of the game, disable the multi kick button
2034  Buttons[gr_screen.res][MULTI_KICK].button.disable();
2035  }
2036  } else {
2040  Buttons[gr_screen.res][MULTI_KICK].button.disable();
2043  Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.hide();
2044  Buttons[gr_screen.res][MULTI_KICK].button.hide();
2045  }
2046 
2047  if (!Award_active) {
2049  Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2050  }
2051 
2052  Debrief_skip_popup_already_shown = 0;
2053 
2054  Debrief_inited = 1;
2055 }
2056 
2057 // --------------------------------------------------------------------------------------
2058 // debrief_close()
2060 {
2061  int i;
2062  scoring_struct *sc;
2063 
2064  Assert(Debrief_inited);
2065 
2066  // if the mission wasn't accepted, clear out my stats
2067  // we need to evaluate a little differently for multiplayer since the conditions for "accepting"
2068  // are a little bit different
2069  if (Game_mode & GM_MULTIPLAYER) {
2070  // if stats weren't accepted, backout my own stats
2071  if (multi_debrief_stats_accept_code() != 1) {
2072  if(MULTIPLAYER_MASTER){
2073  for(i=0; i<MAX_PLAYERS; i++){
2074  if(MULTI_CONNECTED(Net_players[i]) && !MULTI_STANDALONE(Net_players[i]) && !MULTI_PERM_OBSERVER(Net_players[i]) && (Net_players[i].m_player != NULL)){
2075  sc = &Net_players[i].m_player->stats;
2077 
2078  if (Net_player == &Net_players[i]) {
2080  }
2081  }
2082  }
2083  } else {
2086  }
2087  }
2088  } else {
2089  // single player
2090  if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2091  // Make sure we don't skip any missions in a campaign.
2092  if ( Game_mode & GM_CAMPAIGN_MODE ) {
2094  }
2097  }
2098  }
2099 
2100  // if dude passed the misson and accepted, reset his show skip popup flag
2101  if (Debrief_accepted) {
2102  Player->show_skip_popup = 1;
2103  }
2104 
2105  // clear out debrief info parsed from mission file - taylor
2107 
2108  // clear out award text
2110 
2113  chatbox_close();
2114 
2115  // unload bitmaps
2116  if (Background_bitmap >= 0){
2117  bm_release(Background_bitmap);
2118  }
2119 
2120  if (Award_bg_bitmap >= 0){
2121  bm_release(Award_bg_bitmap);
2122  }
2123 
2124  if (Rank_bitmap >= 0){
2125  bm_release(Rank_bitmap);
2126  }
2127 
2128  if (Medal_bitmap >= 0){
2129  bm_release(Medal_bitmap);
2130  }
2131 
2132  if (Badge_bitmap >= 0){
2133  bm_release(Badge_bitmap);
2134  }
2135 
2136  Debrief_ui_window.destroy();
2137  common_free_interface_palette(); // restore game palette
2138  show_stats_close();
2139 
2140  if (Game_mode & GM_MULTIPLAYER){
2142  }
2143 
2144  if(Debrief_stats_kills != NULL)
2145  {
2146  delete[] Debrief_stats_kills;
2147  Debrief_stats_kills = NULL;
2148  }
2149  game_flush();
2150 
2151  Stage_voice = -1;
2152 
2153  Debriefing_paused = 0;
2154 
2155  Debrief_inited = 0;
2156 }
2157 
2158 // handle keypresses in debriefing
2159 void debrief_do_keys(int new_k)
2160 {
2161  switch (new_k) {
2162  case KEY_TAB:
2163  debrief_next_tab();
2164  break;
2165 
2166  case KEY_SHIFTED | KEY_TAB:
2167  debrief_prev_tab();
2168  break;
2169 
2170  case KEY_ESC: {
2171  int pf_flags;
2172  int choice;
2173 
2174  // multiplayer accept popup is a little bit different
2175  if (Game_mode & GM_MULTIPLAYER) {
2177  } else {
2178  // display the normal debrief popup
2179  if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2180  pf_flags = PF_BODY_BIG; // | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
2181  choice = popup(pf_flags, 3, POPUP_CANCEL, XSTR( "&Yes", 454), XSTR( "&No, retry later", 455), XSTR( "Accept this mission outcome?", 456));
2182  if (choice == 1) { // accept and continue on
2183  debrief_accept(0);
2185  }
2186 
2187  if (choice < 1)
2188  break;
2189 
2190  } else if ( ( Turned_traitor || Must_replay_mission ) && (Game_mode & GM_CAMPAIGN_MODE)) {
2191  // need to popup saying that mission was a failure and must be replayed
2192  choice = popup(0, 2, POPUP_NO, POPUP_YES, XSTR( "Because this mission was a failure, you must replay this mission when you continue your campaign.\n\nReturn to the Flight Deck?", 457));
2193  if (choice <= 0) {
2194  break;
2195  }
2196  }
2197 
2198  // Return to Main Hall
2200  }
2201  }
2202 
2203  default:
2204  break;
2205  } // end switch
2206 }
2207 
2208 // uuuuuugly
2210 {
2211  int start_y, curr_y, i, x, sw;
2212  int fh = gr_get_font_height();
2214 
2215  // vertically centered within field
2217  curr_y = start_y;
2218 
2219  // draw the strings
2220  for (i=0; i<Debrief_award_text_num_lines; i++) {
2221  gr_get_string_size(&sw, NULL, Debrief_award_text[i]);
2222  x = (Medal_bitmap < 0) ? (Debrief_award_text_coords[gr_screen.res][0] + (field_width - sw) / 2) : Debrief_award_text_coords[gr_screen.res][0];
2223  if (i==AWARD_TEXT_MAX_LINES-1) x += 7; // hack because of the shape of the box
2226 
2227  // adjust y pos, including a little extra between the "pairs"
2228  curr_y += fh;
2229  if ((i == 1) || (i == 3)) {
2230  curr_y += ((gr_screen.res == GR_640) ? 2 : 6);
2231  }
2232  }
2233 }
2234 
2235 // clears out text array so we don't have old award text showing up on new awards.
2237  int i;
2238 
2240  for (i=0; i<AWARD_TEXT_MAX_LINES; i++) {
2241  //Debrief_award_text[i][0] = 0;
2242  memset(Debrief_award_text[i], 0, sizeof(char)*AWARD_TEXT_MAX_LINE_LENGTH);
2243  }
2244 }
2245 
2246 // this is the nastiest code I have ever written. if you are modifying this, i feel bad for you.
2247 void debrief_add_award_text(char *str)
2248 {
2251  return;
2252  }
2253 
2254  char *line2;
2256 
2257  // copy in the line
2259 
2260  // maybe translate for displaying
2261  if (Lcl_gr) {
2262  lcl_translate_medal_name_gr(Debrief_award_text[Debrief_award_text_num_lines]);
2263  } else if (Lcl_pl) {
2264  lcl_translate_medal_name_pl(Debrief_award_text[Debrief_award_text_num_lines]);
2265  }
2266 
2267  Debrief_award_text_num_lines++;
2268 
2269  // if its too long, split once ONLY
2270  // assumes text isnt > 2 lines, but this is a safe assumption due to the char limits of the ranks/badges/etc
2271  if (Debrief_award_text_num_lines < AWARD_TEXT_MAX_LINES) {
2272  line2 = split_str_once(Debrief_award_text[Debrief_award_text_num_lines-1], field_width);
2273  if (line2 != NULL) {
2274  sprintf(Debrief_award_text[Debrief_award_text_num_lines], " %s", line2); // indent a space
2275  }
2276  Debrief_award_text_num_lines++; // leave blank line even if it all fits into 1
2277  }
2278 }
2279 
2280 // called once per frame to drive all the input reading and rendering
2281 void debrief_do_frame(float frametime)
2282 {
2283  int k=0, new_k=0;
2284  const char *please_wait_str = XSTR("Please Wait", 1242);
2285  char buf[256];
2286 
2287  Assert(Debrief_inited);
2288 
2289  // Goober5000 - accept immediately if skipping debriefing
2291  {
2292  // make sure that we can actually advance - we don't want an endless loop!!!
2293  if ( !((/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE)) )
2294  {
2295  debrief_accept();
2296  return;
2297  }
2298  }
2299 
2300  int str_w, str_h;
2301 
2302  // first thing is to load the files
2304  // draw the background, etc
2305  GR_MAYBE_CLEAR_RES(Background_bitmap);
2306  if (Background_bitmap >= 0) {
2307  gr_set_bitmap(Background_bitmap);
2308  gr_bitmap(0, 0, GR_RESIZE_MENU);
2309  }
2310 
2311  Debrief_ui_window.draw();
2312  chatbox_render();
2313  if ( Debrief_multi_loading_bitmap > -1 ){
2314  gr_set_bitmap(Debrief_multi_loading_bitmap);
2316  }
2317 
2318  // draw "Please Wait"
2320  gr_set_font(FONT2);
2321  gr_get_string_size(&str_w, &str_h, please_wait_str);
2322  gr_string((gr_screen.max_w_unscaled - str_w) / 2, (gr_screen.max_h_unscaled - str_h) / 2, please_wait_str, GR_RESIZE_MENU);
2323  gr_set_font(FONT1);
2324 
2325  gr_flip();
2326 
2327  // make sure we run the debrief do frame
2328  if (Game_mode & GM_MULTIPLAYER) {
2330  }
2331 
2332  // esc pressed?
2333  os_poll();
2334  int keypress = game_check_key();
2335  if(keypress == KEY_ESC){
2336  // popup to leave
2338  }
2339 
2340  return;
2341  }
2342 
2343  // if multiplayer client, and not loaded voice, then load it
2348  }
2349 
2352  Debrief_ui_window.set_ignore_gadgets(1);
2353  }
2354 
2355 
2356  k = chatbox_process();
2357 
2358  if ( Game_mode & GM_NORMAL ) {
2359  new_k = Debrief_ui_window.process(k);
2360  } else {
2361  new_k = Debrief_ui_window.process(k, 0);
2362  }
2363 
2364  if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
2367  Debrief_ui_window.set_ignore_gadgets(0);
2368  k = 0;
2369  new_k = 0;
2370  }
2371  }
2372 
2374  Debrief_ui_window.set_ignore_gadgets(0);
2375  }
2376 
2377  // don't show pilot info popup by default
2379 
2380  // see if the mode has changed and handle it if so.
2381  if ( Current_mode != New_mode ) {
2383  Current_mode = New_mode;
2384  Current_stage = -1;
2385  New_stage = 0;
2386  if (New_mode == DEBRIEF_TAB) {
2387  Num_stages = 1;
2388  Debrief_cue_voice = 0;
2389  Stage_voice = -1;
2390  if (Debrief_first_voice_flag) {
2391  Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY * 3);
2392  Debrief_first_voice_flag = 0;
2393  }
2394  } else {
2395  Num_stages = DEBRIEF_NUM_STATS_PAGES;
2396  }
2397  }
2398 
2399  if ((Num_stages > 0) && (New_stage != Current_stage)) {
2400  Current_stage = New_stage;
2402  }
2403 
2405 
2406  // multi clients get a slight delay before music start to check goals again
2407  if ( timestamp_valid(Debrief_music_timeout) ) {
2408  if ( timestamp_elapsed(Debrief_music_timeout) ) {
2409  Debrief_music_timeout = 0;
2410 
2411  if ( mission_goals_met() ) {
2413  } else {
2415  }
2416 
2417  common_music_do();
2418  }
2419  } else {
2420  common_music_do();
2421  }
2422 
2423  if (Game_mode & GM_MULTIPLAYER) {
2425  }
2426 
2427  // Now do all the rendering for the frame
2428  GR_MAYBE_CLEAR_RES(Background_bitmap);
2429  if (Background_bitmap >= 0) {
2430  gr_set_bitmap(Background_bitmap);
2431  gr_bitmap(0, 0, GR_RESIZE_MENU);
2432  }
2433 
2434  // draw the awarded stuff, G
2435  if ( Award_active && (Award_bg_bitmap >= 0) ) {
2436  gr_set_bitmap(Award_bg_bitmap);
2438  if (Rank_bitmap >= 0) {
2439  gr_set_bitmap(Rank_bitmap);
2441  }
2442 
2443  if (Medal_bitmap >= 0) {
2444  gr_set_bitmap(Medal_bitmap);
2446  }
2447 
2448  if (Badge_bitmap >= 0) {
2449  gr_set_bitmap(Badge_bitmap);
2451  }
2452 
2453  // draw medal/badge/rank labels
2455  }
2456 
2457  Debrief_ui_window.draw();
2459  Buttons[gr_screen.res][Current_mode].button.draw_forced(2);
2460  if (Recommend_active && (Current_mode != STATS_TAB)) {
2462  }
2463 
2464  // draw the title of the mission
2466  strcpy_s(buf, The_mission.name);
2469 
2470 #if !defined(NDEBUG)
2473 #endif
2474 
2475  // Set the font for the debriefing instead of relying on the implicit font-setting of Debrief_ui_window.draw() -MageKing17
2477 
2478  // draw the screen-specific text
2479  switch (Current_mode) {
2480  case DEBRIEF_TAB:
2481  if ( Num_debrief_stages <= 0 ) {
2485 
2486  } else {
2488  }
2489 
2490  break;
2491 
2492  case STATS_TAB:
2494  break;
2495  } // end switch
2496 
2497  if ( (Max_debrief_Lines + Text_offset) < Num_text_lines ) {
2498  int w;
2499 
2501  gr_get_string_size(&w, NULL, XSTR( "More", 459));
2503  }
2504 
2507 
2508  // render some extra stuff in multiplayer
2509  if (Game_mode & GM_MULTIPLAYER) {
2510  // render the chatbox last
2511  chatbox_render();
2512 
2513  // draw tooltips
2514  Debrief_ui_window.draw_tooltip();
2515 
2516  // render the status indicator for the voice system
2518  }
2519 
2520  // AL 3-6-98: Needed to move key reading here, since popups are launched from this code, and we don't
2521  // want to include the mouse pointer which is drawn in the flip
2522 
2525  debrief_do_keys(new_k);
2526  }
2527 
2528  // blit help overlay if active
2530 
2531  gr_flip();
2532 
2533  // maybe show skip mission popup
2534  if ( Must_replay_mission && (!Debrief_skip_popup_already_shown) && (Player->show_skip_popup) && (Game_mode & GM_NORMAL) && (Game_mode & GM_CAMPAIGN_MODE) && (Player->failures_this_session >= PLAYER_MISSION_FAILURE_LIMIT) && !(Game_mode & GM_MULTIPLAYER)) {
2535  int popup_choice = popup(0, 3, XSTR("Do Not Skip This Mission", 1473),
2536  XSTR("Advance To The Next Mission", 1474),
2537  XSTR("Don't Show Me This Again", 1475),
2538  XSTR("You have failed this mission five times. If you like, you may advance to the next mission.", 1472) );
2539  switch (popup_choice) {
2540  case 0:
2541  // stay on this mission, so proceed to normal debrief
2542  // in other words, do nothing.
2543  break;
2544  case 1:
2545  // skip this mission
2548  break;
2549  case 2:
2550  // don't show this again
2551  Player->show_skip_popup = 0;
2552  break;
2553  }
2554 
2555  Debrief_skip_popup_already_shown = 1;
2556  }
2557 
2558  // check to see if we should be showing a pilot info popup in multiplayer (if a guy was double clicked)
2559  if ((Game_mode & GM_MULTIPLAYER) && Debrief_should_show_popup) {
2560  Assert((Multi_list_select >= 0) && (Multi_list_select < Multi_list_size));
2561  multi_pinfo_popup(&Net_players[Multi_list[Multi_list_select].net_player_index]);
2562 
2564  }
2565 }
2566 
2568 {
2569  int i;
2570  net_player *np;
2572 
2573  Multi_list_size = 0; // number of net players to choose from
2574 
2575  for ( i=0; i<MAX_PLAYERS; i++ ) {
2576  np = &Net_players[i];
2577  // remember not to include the standalone.
2578  if ( MULTI_CONNECTED((*np)) && !MULTI_STANDALONE((*np))){
2579  list = &Multi_list[Multi_list_size++];
2580  list->net_player_index = i;
2581  strcpy_s(list->callsign, np->m_player->callsign);
2582 
2583  // make sure to leave some room to blit the team indicator
2585  }
2586  } // end for
2587 }
2588 
2590 {
2592 }
2593 
2595 {
2596 }
void game_flush()
Definition: fredstubs.cpp:83
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
pilotfile Pilot
Definition: pilotfile.cpp:7
#define DEBRIEF_MISSION_KILLS
int timestamp(int delta_ms)
Definition: timer.cpp:226
void fsspeech_pause(bool playing)
Definition: fsspeech.h:46
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
void debrief_multi_list_draw()
int i
Definition: multi_pxo.cpp:466
fix Missiontime
Definition: systemvars.cpp:19
SCP_vector< medal_stuff > Medals
Definition: medals.cpp:33
float Brief_text_wipe_time_elapsed
int Briefing_voice_enabled
int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4]
int chatbox_create(int mode_flags)
Definition: chatbox.cpp:495
void add_XSTR(char *string, int _xstr_id, int _x, int _y, UI_GADGET *_assoc, int _color_type, int _font_id=-1)
Definition: window.cpp:476
int Debrief_award_coords[GR_NUM_RESOLUTIONS][2]
void reset_status()
Definition: button.cpp:78
char * Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS]
void fsspeech_stop()
Definition: fsspeech.h:45
void multi_campaign_eval_debrief()
int team
Definition: ship.h:606
int Debrief_award_text_num_lines
GLbitfield stages
Definition: Glext.h:7177
void debrief_check_buttons()
#define KEY_DOWN
Definition: key.h:180
int flags
Definition: player.h:104
int kills[MAX_SHIP_CLASSES]
Definition: scoring.h:87
#define CF_TYPE_VOICE_DEBRIEFINGS
Definition: cfile.h:57
int Game_mode
Definition: systemvars.cpp:24
#define KEY_LEFT
Definition: key.h:181
void show_stats_close()
Definition: stats.cpp:302
void gr_flip()
Definition: 2d.cpp:2113
commit pressed
Definition: gamesnd.h:294
#define MP_TEXT_INDEX_2
void scoring_level_init(scoring_struct *scp)
Definition: scoring.cpp:223
int x
Definition: ui.h:658
void debrief_last_stage()
int mission_goals_met()
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
void debrief_pause()
SCP_string recommendation_text
#define GR_RESIZE_MENU
Definition: 2d.h:684
net_player * Net_player
Definition: multi.cpp:94
color Color_more_indicator
Definition: alphacolors.cpp:28
void debrief_text_init()
#define DEBRIEF_ALLTIME_STATS
#define DEBRIEF_VOICE_DELAY
int y
Definition: ui.h:658
char name[NAME_LENGTH]
Definition: missionparse.h:131
#define PLAYER_SCROLL_DOWN
int Weapon_energy_cheat
Definition: hudets.cpp:27
int Debrief_title_coords[GR_NUM_RESOLUTIONS][3]
void lcl_translate_medal_name_gr(char *name)
Definition: localize.cpp:1502
#define ASF_VOICE
Definition: audiostr.h:21
player * m_player
Definition: multi.h:459
void show_stats_label(int stage, int sx, int sy, int dy)
Definition: stats.cpp:42
const float BRIEF_TEXT_WIPE_TIME
#define KEY_RIGHT
Definition: key.h:182
int brief_color_text_init(const char *src, int w, const char default_color, int instance, int max_lines, const bool append)
#define MISSION_FLAG_TOGGLE_DEBRIEFING
Definition: missionparse.h:79
int Rank_medal_index
Definition: medals.cpp:177
#define MULTI_STANDALONE(np)
Definition: multi.h:139
#define MICON_TEAM1
Definition: multiui.h:58
void debrief_traitor_init()
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)
int Max_debrief_Lines
void debrief_setup_ship_kill_stats(int stage_num)
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
#define mprintf(args)
Definition: pstypes.h:238
int debrief_find_persona_index()
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
#define PLAYER_SCROLL_UP
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
general failure sound for any event
Definition: gamesnd.h:297
ubyte debrief_persona_index
help pressed
Definition: gamesnd.h:293
int res
Definition: 2d.h:370
int max_h_unscaled
Definition: 2d.h:361
void debrief_kick_selected_player()
int Lcl_pl
Definition: localize.cpp:49
void debrief_multi_fixup_stages()
int Debrief_should_show_popup
#define DEBRIEFING_OVERLAY
Definition: contexthelp.h:27
#define MP_TEXT_INDEX_3
void debrief_close()
#define GR_MAYBE_CLEAR_RES(bmap)
Definition: 2d.h:639
void common_music_close()
void debrief_redraw_pressed_buttons()
#define NETINFO_FLAG_OBS_PLAYER
Definition: multi.h:606
void help_overlay_set_state(int overlay_id, int resolution_index, int state)
void set_ignore_gadgets(int state)
Definition: window.cpp:471
virtual void hide(int n)
Definition: gadget.cpp:207
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
void debrief_prev_stage()
void mission_campaign_mission_over(bool do_next_mission)
void debrief_multi_server_stuff()
color Color_text_active_hi
Definition: alphacolors.cpp:27
Definition: ui.h:195
#define STATS_TAB
int flags
Definition: multi.h:463
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
void debrief_voice_stop()
int max_w_unscaled
Definition: 2d.h:361
#define Int3()
Definition: pstypes.h:292
#define MEDALS_BUTTON
void multi_debrief_replay_hit()
Definition: multiui.cpp:8869
int get_sexp_main()
Definition: sexp.cpp:25494
#define PLAYER_FLAGS_PROMOTED
Definition: player.h:41
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
const char *(* tooltip_handler)(const char *text)
Definition: ui.h:649
#define PLAYER_MISSION_FAILURE_LIMIT
Definition: player.h:77
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
void debrief_voice_load_all()
char callsign[CALLSIGN_LEN+1]
Definition: player.h:91
char * name
#define LAST_STAGE
void debrief_multi_list_init()
SCP_vector< int > m_badge_earned
Definition: scoring.h:108
char mission_file[32]
#define B1_JUST_RELEASED
Definition: uidefs.h:50
#define NUM_DEBRIEF_TEXT
#define DEBRIEFING_FONT
color Color_blue
Definition: alphacolors.cpp:31
void debrief_next_stage()
void multi_debrief_do_frame()
Definition: multiui.cpp:8664
void debrief_replay_pressed()
void debrief_unpause()
#define DEBRIEF_TAB
void mission_campaign_skip_to_next(int start_game)
int audiostream_is_playing(int i)
Definition: audiostr.cpp:1827
void common_set_interface_palette(char *filename)
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
void draw_forced(int frame_num)
Definition: button.cpp:104
void show_stats_numbers(int stage, int sx, int sy, int dy, int add_mission)
Definition: stats.cpp:131
#define SCORE_DEBRIEF_FAIL
Definition: eventmusic.h:54
char * Debrief_mask_name[GR_NUM_RESOLUTIONS]
void destroy()
Definition: window.cpp:189
#define gr_reset_clip
Definition: 2d.h:745
void set_mask_bmap(char *fname)
Definition: window.cpp:75
#define SCORE_DEBRIEF_AVERAGE
Definition: eventmusic.h:53
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
void game_format_time(long, char *)
Definition: fredstubs.cpp:204
Definition: player.h:85
void chatbox_render()
Definition: chatbox.cpp:683
void multi_kick_player(int player_index, int ban, int reason)
Definition: multi_kick.cpp:82
net_player_info p_info
Definition: multi.h:473
int Debrief_award_text_width[GR_NUM_RESOLUTIONS][2]
int m_okKills[MAX_SHIP_CLASSES]
Definition: scoring.h:113
void common_free_interface_palette()
cfp version
Definition: cfile.cpp:1063
int type_flags
Definition: multi.h:493
void debrief_multi_list_scroll_down()
void scoring_backout_accept(scoring_struct *score)
Definition: scoring.cpp:378
color Color_bright
Definition: alphacolors.cpp:28
char campaign_name[32]
#define NUM_VOLITION_CAMPAIGNS
int state
Definition: multi.h:464
int m_promotion_earned
Definition: scoring.h:109
#define GM_MULTIPLAYER
Definition: systemvars.h:18
void mission_campaign_store_goals_and_events()
int Debrief_text_x2[GR_NUM_RESOLUTIONS]
void set_player_stats(int pid)
Definition: stats.cpp:318
void audiostream_stop(int i, int rewind, int paused)
Definition: audiostr.cpp:1840
void scoring_level_close(int accepted)
Definition: scoring.cpp:432
int cf_exists_full(const char *filename, int dir_type)
Definition: cfile.cpp:527
void fsspeech_start_buffer()
Definition: fsspeech.h:48
#define strnicmp(s1, s2, n)
Definition: config.h:272
void multi_pinfo_popup(net_player *np)
netgame_info Netgame
Definition: multi.cpp:97
int hotspot
Definition: ui.h:659
int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3]
int pressed()
Definition: button.cpp:325
Switching to a new screen, but not commit.
Definition: gamesnd.h:292
#define KEY_SHIFTED
Definition: key.h:62
#define ACCEPT_BUTTON
#define OPTIONS_BUTTON
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2]
void debrief_award_init()
#define MISSION_FLAG_END_TO_MAINHALL
Definition: missionparse.h:92
#define MP_CAMPAIGN
Definition: multi.h:98
#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)
void debrief_first_stage()
#define NG_TYPE_TEAM
Definition: multi.h:650
void debrief_voice_play()
#define TEXT_SCROLL_UP
GLdouble GLdouble z
Definition: Glext.h:5451
#define KEY_ENTER
Definition: key.h:125
#define GR_640
Definition: 2d.h:652
#define MULTI_KICK
int required_string(const char *pstr)
Definition: parselo.cpp:468
GLuint buffer
Definition: Glext.h:5492
int Num_teams
#define MAX_PLAYERS
Definition: pstypes.h:32
int failures_this_session
Definition: player.h:202
#define BUILTIN_CAMPAIGN
SCP_vector< int > medal_counts
Definition: scoring.h:85
#define NETINFO_FLAG_GAME_HOST
Definition: multi.h:603
int Briefing_music_handle
UI_BUTTON button
Definition: ui.h:660
int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2]
void debrief_do_frame(float frametime)
void debrief_render_mission_difficulty(int y_loc)
ubyte show_skip_popup
Definition: player.h:203
void debrief_load_voice_file(int voice_num, char *name)
void debrief_render_mission_time(int y_loc)
#define NETPLAYER_STATE_DEBRIEF_REPLAY
Definition: multi.h:704
char Mission_filename[80]
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
void debrief_handle_player_drop()
#define REPLAY_MISSION
int Debrief_multi_voice_loaded
void debrief_stats_render()
int idx
Definition: multiui.cpp:761
void multi_debrief_init()
Definition: multiui.cpp:8622
void audiostream_unpause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1960
#define MULTI_LIST_TEAM_OFFSET
void debrief_init()
char text[NAME_LENGTH+1]
char voice[MAX_FILENAME_LEN]
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
int debrief_set_stages_and_multi_stuff()
void os_poll()
Definition: osapi.cpp:748
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
#define MULTI_TEAM
Definition: multi.h:655
user_click (mouse selects a control)
Definition: gamesnd.h:305
void debrief_voice_unload_all()
ship * Player_ship
Definition: ship.cpp:124
#define GM_IN_MISSION
Definition: systemvars.h:23
void fsspeech_play_buffer(int type)
Definition: fsspeech.h:50
char modified[DATE_TIME_LENGTH]
Definition: missionparse.h:135
char callsign[CALLSIGN_LEN]
#define DB_WITHOUT_MEDAL
int inited
Definition: fredrender.cpp:76
#define NOX(s)
Definition: pstypes.h:473
void debrief_multi_list_scroll_up()
void common_music_do()
GLbitfield flags
Definition: Glext.h:6722
void set_hotkey(int keycode)
Definition: gadget.cpp:280
char default_debriefing_color
Definition: alphacolors.cpp:44
void reset_parse(char *text)
Definition: parselo.cpp:3305
color Color_text_active
Definition: alphacolors.cpp:27
void debrief_next_tab()
char * Debrief_multi_name[GR_NUM_RESOLUTIONS]
GLuint const GLchar * name
Definition: Glext.h:5608
void multi_debrief_esc_hit()
Definition: multiui.cpp:8793
char background[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN]
#define AWARD_TEXT_MAX_LINES
int current_mission
char default_recommendation_color
Definition: alphacolors.cpp:45
void debrief_add_award_text(char *str)
bool sexp_replace_variable_names_with_values(char *text, int max_len)
Definition: sexp.cpp:29395
brief stage change fail
Definition: gamesnd.h:302
void mission_campaign_store_variables()
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
void debrief_button_pressed(int num)
void stuff_int(int *i)
Definition: parselo.cpp:2372
void audiostream_close_file(int i, int fade)
Definition: audiostr.cpp:1772
debrief_stage stages[MAX_DEBRIEF_STAGES]
#define MULTI_PERM_OBSERVER(np)
Definition: multi.h:142
#define DEBRIEF_MISSION_STATS
if(aifft_max_checks<=0)
Definition: aiturret.cpp:1581
void chatbox_close()
Definition: chatbox.cpp:634
GLuint GLuint num
Definition: Glext.h:9089
color Color_bright_white
Definition: alphacolors.cpp:32
const char * debrief_tooltip_handler(const char *str)
#define DEBRIEF_ALLTIME_KILLS
#define DB_WITH_MEDAL
#define NUM_TABS
void fsspeech_stuff_buffer(const char *text)
Definition: fsspeech.h:49
void mission_campaign_eval_next_mission()
#define FONT1
Definition: font.h:65
void debrief_award_text_clear()
scroll pressed (and scroll)
Definition: gamesnd.h:296
color Color_white
Definition: alphacolors.cpp:32
#define CALLSIGN_LEN
Definition: globals.h:31
void update_stats_backout(scoring_struct *stats, bool training=false)
Definition: pilotfile.cpp:185
void debrief_buttons_init()
int campaign_mode
Definition: multi.h:509
void link_hotspot(int num)
Definition: gadget.cpp:50
campaign Campaign
void debrief_rebuild_player_list()
int m_medal_earned
Definition: scoring.h:107
void multi_debrief_accept_hit()
Definition: multiui.cpp:8711
#define strcat_s(...)
Definition: safe_strings.h:68
#define FIRST_STAGE
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
#define KEY_ESC
Definition: key.h:124
#define NAME_LENGTH
Definition: globals.h:15
#define DEBRIEF_NUM_STATS_PAGES
press briefing, ship selection or weapons bar (top-left)
Definition: gamesnd.h:291
const char * Resolution_prefixes[GR_NUM_RESOLUTIONS]
Definition: 2d.cpp:44
#define UI_XSTR_COLOR_PINK
Definition: ui.h:161
#define FONT2
Definition: font.h:66
brief stage change
Definition: gamesnd.h:301
int button_down()
Definition: button.cpp:363
voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS]
#define MULTI_CONNECTED(np)
Definition: multi.h:136
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
int eval_sexp(int cur_node, int referenced_node)
Definition: sexp.cpp:22894
player * Player
#define NETPLAYER_STATE_DEBRIEF_ACCEPT
Definition: multi.h:703
int gr_force_fit_string(char *str, int max_str, int max_width)
Definition: font.cpp:48
void debrief_accept(int ok_to_post_start_game_event=1)
int Please_wait_coords[GR_NUM_RESOLUTIONS][4]
#define NEXT_STAGE
Definition: ui.h:584
int game_check_key()
Definition: fredstubs.cpp:65
screen gr_screen
Definition: 2d.cpp:46
#define PREV_STAGE
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
void debrief_do_keys(int new_k)
void multi_debrief_close()
Definition: multiui.cpp:8680
char * split_str_once(char *src, int max_pixel_w)
Definition: parselo.cpp:3330
Definition: ui.h:162
struct voice_map voice_map
void enable(int n=1)
Definition: gadget.cpp:440
char Debrief_award_text[AWARD_TEXT_MAX_LINES][AWARD_TEXT_MAX_LINE_LENGTH]
#define HELP_BUTTON
int gr_get_font_height()
Definition: font.cpp:187
void show_stats_init()
Definition: stats.cpp:32
void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
GLfloat GLfloat p
Definition: Glext.h:8373
#define MULTIPLAYER_MASTER
Definition: multi.h:130
SCP_map< int, char * > promotion_text
Definition: scoring.h:67
GLenum src
Definition: Glext.h:5917
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
#define MICON_TEAM0_SELECT
Definition: multiui.h:57
int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS]
const char * Skill_level_names(int skill_level, int translate=1)
Definition: aicode.cpp:208
#define timestamp_elapsed(stamp)
Definition: timer.h:102
void multi_common_voice_display_status()
Definition: multiui.cpp:369
void get_mouse_pos(int *xx, int *yy)
Definition: gadget.cpp:341
#define PROMPT_CLIENT
Definition: multi_endgame.h:28
#define MAX_DEBRIEF_LINES
void draw_tooltip()
Definition: window.cpp:304
v_campaign Volition_campaigns[NUM_VOLITION_CAMPAIGNS]
int chatbox_process(int key_in)
Definition: chatbox.cpp:575
void audiostream_play(int i, float volume, int looping)
Definition: audiostr.cpp:1803
int Game_skill_level
Definition: fredstubs.cpp:170
#define KEY_CTRLED
Definition: key.h:64
int Iff_traitor
Definition: iff_defs.cpp:22
color Color_normal
Definition: alphacolors.cpp:28
#define AWARD_TEXT_MAX_LINE_LENGTH
#define KEY_TAB
Definition: key.h:127
#define MAX_TVT_TEAMS
Definition: globals.h:57
UI_XSTR Debrief_strings[GR_NUM_RESOLUTIONS][NUM_DEBRIEF_TEXT]
char * filename
Definition: ui.h:657
debriefing Debriefings[MAX_TVT_TEAMS]
char Debrief_current_callsign[CALLSIGN_LEN+10]
void debrief_disable_accept()
#define MICON_TEAM1_SELECT
Definition: multiui.h:59
int brief_render_text(int line_offset, int x, int y, int h, float frametime, int instance, int line_spacing)
void debrief_draw_award_text()
rank_stuff Ranks[NUM_RANKS]
Definition: scoring.cpp:45
#define MAX_CAMPAIGN_MISSIONS
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
#define CAMPAIGN_LOOP_MISSION_UNINITIALIZED
#define KEY_UP
Definition: key.h:179
void debrief_choose_voice(char *voice_dest, char *voice_base, int persona_index, int default_to_base=0)
#define UI_XSTR_COLOR_GREEN
Definition: ui.h:160
#define SCORE_DEBRIEF_SUCCESS
Definition: eventmusic.h:52
int Multi_list_select
color Color_text_normal
Definition: alphacolors.cpp:26
void send_debrief_info(int stage_count[], int *stages[])
Definition: multimsgs.cpp:7260
#define F_FILESPEC
Definition: parselo.h:37
#define TEXT_SCROLL_DOWN
char filename[MAX_FILENAME_LEN]
int Debrief_overlay_id
int mission_ui_background_load(const char *custom_background, const char *single_background, const char *multi_background)
player * Debrief_player
int audiostream_open(const char *filename, int type)
Definition: audiostr.cpp:1713
void debrief_render_stagenum()
int multi_debrief_stats_accept_code()
Definition: multiui.cpp:8942
void audiostream_pause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1943
#define GM_NORMAL
Definition: systemvars.h:19
color Color_bright_blue
Definition: alphacolors.cpp:31
#define NG_TYPE_SW
Definition: multi.h:649
void launch_context_help()
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
mission The_mission
void debrief_choose_medal_variant(char *buf, int medal_earned, int zero_based_version_index)
void disable()
Definition: gadget.cpp:432
void draw()
Definition: window.cpp:220
struct ui_button_info ui_button_info
void gr_set_font(int fontnum)
Definition: font.cpp:566
void debrief_ui_init()
#define MULTI_PINFO_POPUP
#define MP_TEXT_INDEX_1
#define MISSION_FLAG_NO_TRAITOR
Definition: missionparse.h:72
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
int help_overlay_get_index(const char *overlay_name)
int Multi_common_icons[MULTI_NUM_COMMON_ICONS]
Definition: multiui.cpp:304
char promotion_voice_base[MAX_FILENAME_LEN]
Definition: scoring.h:70
#define MICON_TEAM0
Definition: multiui.h:56
int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3]
void debrief_prev_tab()
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
void _cdecl gr_printf_menu(int x, int y, const char *format,...)
Definition: font.cpp:314
void gameseq_post_event(int event)
#define CMISSION_FLAG_HAS_LOOP
void lcl_translate_medal_name_pl(char *name)
Definition: localize.cpp:1563
#define F_MULTITEXT
Definition: parselo.h:43
#define GM_CAMPAIGN_MODE
Definition: systemvars.h:29
#define stricmp(s1, s2)
Definition: config.h:271
debriefing Traitor_debriefing
#define timestamp_valid(stamp)
Definition: timer.h:104
void debrief_voice_init()
void help_overlay_maybe_blit(int overlay_id, int resolution_index)
int help_overlay_active(int overlay_id)
#define RECOMMENDATIONS
void debrief_set_multi_clients(int stage_count, int active_stages[])
char * Debrief_single_name[GR_NUM_RESOLUTIONS]
debriefing * Debriefing
int Debrief_list_coords[GR_NUM_RESOLUTIONS][4]
float Master_voice_volume
Definition: sound.cpp:54
int Lcl_gr
Definition: localize.cpp:48
cmission missions[MAX_CAMPAIGN_MISSIONS]
void common_music_init(int score_index)
#define NUM_BUTTONS
GLint y
Definition: Gl.h:1505
int Debrief_multi_stages_loaded
#define MAX_DEBRIEF_STAGES
scoring_struct stats
Definition: player.h:127
#define strcpy_s(...)
Definition: safe_strings.h:67
int Debrief_more_coords[GR_NUM_RESOLUTIONS][2]
char name[NAME_LENGTH]
Definition: scoring.h:66